diff options
581 files changed, 12625 insertions, 10118 deletions
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 5aceb88b3f8b..05e2ae236865 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt | |||
@@ -4,20 +4,18 @@ | |||
4 | James E.J. Bottomley <James.Bottomley@HansenPartnership.com> | 4 | James E.J. Bottomley <James.Bottomley@HansenPartnership.com> |
5 | 5 | ||
6 | This document describes the DMA API. For a more gentle introduction | 6 | This document describes the DMA API. For a more gentle introduction |
7 | phrased in terms of the pci_ equivalents (and actual examples) see | 7 | of the API (and actual examples) see |
8 | Documentation/PCI/PCI-DMA-mapping.txt. | 8 | Documentation/DMA-API-HOWTO.txt. |
9 | 9 | ||
10 | This API is split into two pieces. Part I describes the API and the | 10 | This API is split into two pieces. Part I describes the API. Part II |
11 | corresponding pci_ API. Part II describes the extensions to the API | 11 | describes the extensions to the API for supporting non-consistent |
12 | for supporting non-consistent memory machines. Unless you know that | 12 | memory machines. Unless you know that your driver absolutely has to |
13 | your driver absolutely has to support non-consistent platforms (this | 13 | support non-consistent platforms (this is usually only legacy |
14 | is usually only legacy platforms) you should only use the API | 14 | platforms) you should only use the API described in part I. |
15 | described in part I. | ||
16 | 15 | ||
17 | Part I - pci_ and dma_ Equivalent API | 16 | Part I - dma_ API |
18 | ------------------------------------- | 17 | ------------------------------------- |
19 | 18 | ||
20 | To get the pci_ API, you must #include <linux/pci.h> | ||
21 | To get the dma_ API, you must #include <linux/dma-mapping.h> | 19 | To get the dma_ API, you must #include <linux/dma-mapping.h> |
22 | 20 | ||
23 | 21 | ||
@@ -27,9 +25,6 @@ Part Ia - Using large dma-coherent buffers | |||
27 | void * | 25 | void * |
28 | dma_alloc_coherent(struct device *dev, size_t size, | 26 | dma_alloc_coherent(struct device *dev, size_t size, |
29 | dma_addr_t *dma_handle, gfp_t flag) | 27 | dma_addr_t *dma_handle, gfp_t flag) |
30 | void * | ||
31 | pci_alloc_consistent(struct pci_dev *dev, size_t size, | ||
32 | dma_addr_t *dma_handle) | ||
33 | 28 | ||
34 | Consistent memory is memory for which a write by either the device or | 29 | Consistent memory is memory for which a write by either the device or |
35 | the processor can immediately be read by the processor or device | 30 | the processor can immediately be read by the processor or device |
@@ -53,15 +48,11 @@ The simplest way to do that is to use the dma_pool calls (see below). | |||
53 | The flag parameter (dma_alloc_coherent only) allows the caller to | 48 | The flag parameter (dma_alloc_coherent only) allows the caller to |
54 | specify the GFP_ flags (see kmalloc) for the allocation (the | 49 | specify the GFP_ flags (see kmalloc) for the allocation (the |
55 | implementation may choose to ignore flags that affect the location of | 50 | implementation may choose to ignore flags that affect the location of |
56 | the returned memory, like GFP_DMA). For pci_alloc_consistent, you | 51 | the returned memory, like GFP_DMA). |
57 | must assume GFP_ATOMIC behaviour. | ||
58 | 52 | ||
59 | void | 53 | void |
60 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | 54 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, |
61 | dma_addr_t dma_handle) | 55 | dma_addr_t dma_handle) |
62 | void | ||
63 | pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, | ||
64 | dma_addr_t dma_handle) | ||
65 | 56 | ||
66 | Free the region of consistent memory you previously allocated. dev, | 57 | Free the region of consistent memory you previously allocated. dev, |
67 | size and dma_handle must all be the same as those passed into the | 58 | size and dma_handle must all be the same as those passed into the |
@@ -89,10 +80,6 @@ for alignment, like queue heads needing to be aligned on N-byte boundaries. | |||
89 | dma_pool_create(const char *name, struct device *dev, | 80 | dma_pool_create(const char *name, struct device *dev, |
90 | size_t size, size_t align, size_t alloc); | 81 | size_t size, size_t align, size_t alloc); |
91 | 82 | ||
92 | struct pci_pool * | ||
93 | pci_pool_create(const char *name, struct pci_device *dev, | ||
94 | size_t size, size_t align, size_t alloc); | ||
95 | |||
96 | The pool create() routines initialize a pool of dma-coherent buffers | 83 | The pool create() routines initialize a pool of dma-coherent buffers |
97 | for use with a given device. It must be called in a context which | 84 | for use with a given device. It must be called in a context which |
98 | can sleep. | 85 | can sleep. |
@@ -108,9 +95,6 @@ from this pool must not cross 4KByte boundaries. | |||
108 | void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags, | 95 | void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags, |
109 | dma_addr_t *dma_handle); | 96 | dma_addr_t *dma_handle); |
110 | 97 | ||
111 | void *pci_pool_alloc(struct pci_pool *pool, gfp_t gfp_flags, | ||
112 | dma_addr_t *dma_handle); | ||
113 | |||
114 | This allocates memory from the pool; the returned memory will meet the size | 98 | This allocates memory from the pool; the returned memory will meet the size |
115 | and alignment requirements specified at creation time. Pass GFP_ATOMIC to | 99 | and alignment requirements specified at creation time. Pass GFP_ATOMIC to |
116 | prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks), | 100 | prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks), |
@@ -122,9 +106,6 @@ pool's device. | |||
122 | void dma_pool_free(struct dma_pool *pool, void *vaddr, | 106 | void dma_pool_free(struct dma_pool *pool, void *vaddr, |
123 | dma_addr_t addr); | 107 | dma_addr_t addr); |
124 | 108 | ||
125 | void pci_pool_free(struct pci_pool *pool, void *vaddr, | ||
126 | dma_addr_t addr); | ||
127 | |||
128 | This puts memory back into the pool. The pool is what was passed to | 109 | This puts memory back into the pool. The pool is what was passed to |
129 | the pool allocation routine; the cpu (vaddr) and dma addresses are what | 110 | the pool allocation routine; the cpu (vaddr) and dma addresses are what |
130 | were returned when that routine allocated the memory being freed. | 111 | were returned when that routine allocated the memory being freed. |
@@ -132,8 +113,6 @@ were returned when that routine allocated the memory being freed. | |||
132 | 113 | ||
133 | void dma_pool_destroy(struct dma_pool *pool); | 114 | void dma_pool_destroy(struct dma_pool *pool); |
134 | 115 | ||
135 | void pci_pool_destroy(struct pci_pool *pool); | ||
136 | |||
137 | The pool destroy() routines free the resources of the pool. They must be | 116 | The pool destroy() routines free the resources of the pool. They must be |
138 | called in a context which can sleep. Make sure you've freed all allocated | 117 | called in a context which can sleep. Make sure you've freed all allocated |
139 | memory back to the pool before you destroy it. | 118 | memory back to the pool before you destroy it. |
@@ -144,8 +123,6 @@ Part Ic - DMA addressing limitations | |||
144 | 123 | ||
145 | int | 124 | int |
146 | dma_supported(struct device *dev, u64 mask) | 125 | dma_supported(struct device *dev, u64 mask) |
147 | int | ||
148 | pci_dma_supported(struct pci_dev *hwdev, u64 mask) | ||
149 | 126 | ||
150 | Checks to see if the device can support DMA to the memory described by | 127 | Checks to see if the device can support DMA to the memory described by |
151 | mask. | 128 | mask. |
@@ -159,8 +136,14 @@ driver writers. | |||
159 | 136 | ||
160 | int | 137 | int |
161 | dma_set_mask(struct device *dev, u64 mask) | 138 | dma_set_mask(struct device *dev, u64 mask) |
139 | |||
140 | Checks to see if the mask is possible and updates the device | ||
141 | parameters if it is. | ||
142 | |||
143 | Returns: 0 if successful and a negative error if not. | ||
144 | |||
162 | int | 145 | int |
163 | pci_set_dma_mask(struct pci_device *dev, u64 mask) | 146 | dma_set_coherent_mask(struct device *dev, u64 mask) |
164 | 147 | ||
165 | Checks to see if the mask is possible and updates the device | 148 | Checks to see if the mask is possible and updates the device |
166 | parameters if it is. | 149 | parameters if it is. |
@@ -187,9 +170,6 @@ Part Id - Streaming DMA mappings | |||
187 | dma_addr_t | 170 | dma_addr_t |
188 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | 171 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, |
189 | enum dma_data_direction direction) | 172 | enum dma_data_direction direction) |
190 | dma_addr_t | ||
191 | pci_map_single(struct pci_dev *hwdev, void *cpu_addr, size_t size, | ||
192 | int direction) | ||
193 | 173 | ||
194 | Maps a piece of processor virtual memory so it can be accessed by the | 174 | Maps a piece of processor virtual memory so it can be accessed by the |
195 | device and returns the physical handle of the memory. | 175 | device and returns the physical handle of the memory. |
@@ -198,14 +178,10 @@ The direction for both api's may be converted freely by casting. | |||
198 | However the dma_ API uses a strongly typed enumerator for its | 178 | However the dma_ API uses a strongly typed enumerator for its |
199 | direction: | 179 | direction: |
200 | 180 | ||
201 | DMA_NONE = PCI_DMA_NONE no direction (used for | 181 | DMA_NONE no direction (used for debugging) |
202 | debugging) | 182 | DMA_TO_DEVICE data is going from the memory to the device |
203 | DMA_TO_DEVICE = PCI_DMA_TODEVICE data is going from the | 183 | DMA_FROM_DEVICE data is coming from the device to the memory |
204 | memory to the device | 184 | DMA_BIDIRECTIONAL direction isn't known |
205 | DMA_FROM_DEVICE = PCI_DMA_FROMDEVICE data is coming from | ||
206 | the device to the | ||
207 | memory | ||
208 | DMA_BIDIRECTIONAL = PCI_DMA_BIDIRECTIONAL direction isn't known | ||
209 | 185 | ||
210 | Notes: Not all memory regions in a machine can be mapped by this | 186 | Notes: Not all memory regions in a machine can be mapped by this |
211 | API. Further, regions that appear to be physically contiguous in | 187 | API. Further, regions that appear to be physically contiguous in |
@@ -268,9 +244,6 @@ cache lines are updated with data that the device may have changed). | |||
268 | void | 244 | void |
269 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 245 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, |
270 | enum dma_data_direction direction) | 246 | enum dma_data_direction direction) |
271 | void | ||
272 | pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, | ||
273 | size_t size, int direction) | ||
274 | 247 | ||
275 | Unmaps the region previously mapped. All the parameters passed in | 248 | Unmaps the region previously mapped. All the parameters passed in |
276 | must be identical to those passed in (and returned) by the mapping | 249 | must be identical to those passed in (and returned) by the mapping |
@@ -280,15 +253,9 @@ dma_addr_t | |||
280 | dma_map_page(struct device *dev, struct page *page, | 253 | dma_map_page(struct device *dev, struct page *page, |
281 | unsigned long offset, size_t size, | 254 | unsigned long offset, size_t size, |
282 | enum dma_data_direction direction) | 255 | enum dma_data_direction direction) |
283 | dma_addr_t | ||
284 | pci_map_page(struct pci_dev *hwdev, struct page *page, | ||
285 | unsigned long offset, size_t size, int direction) | ||
286 | void | 256 | void |
287 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | 257 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, |
288 | enum dma_data_direction direction) | 258 | enum dma_data_direction direction) |
289 | void | ||
290 | pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, | ||
291 | size_t size, int direction) | ||
292 | 259 | ||
293 | API for mapping and unmapping for pages. All the notes and warnings | 260 | API for mapping and unmapping for pages. All the notes and warnings |
294 | for the other mapping APIs apply here. Also, although the <offset> | 261 | for the other mapping APIs apply here. Also, although the <offset> |
@@ -299,9 +266,6 @@ cache width is. | |||
299 | int | 266 | int |
300 | dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | 267 | dma_mapping_error(struct device *dev, dma_addr_t dma_addr) |
301 | 268 | ||
302 | int | ||
303 | pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr) | ||
304 | |||
305 | In some circumstances dma_map_single and dma_map_page will fail to create | 269 | In some circumstances dma_map_single and dma_map_page will fail to create |
306 | a mapping. A driver can check for these errors by testing the returned | 270 | a mapping. A driver can check for these errors by testing the returned |
307 | dma address with dma_mapping_error(). A non-zero return value means the mapping | 271 | dma address with dma_mapping_error(). A non-zero return value means the mapping |
@@ -311,9 +275,6 @@ reduce current DMA mapping usage or delay and try again later). | |||
311 | int | 275 | int |
312 | dma_map_sg(struct device *dev, struct scatterlist *sg, | 276 | dma_map_sg(struct device *dev, struct scatterlist *sg, |
313 | int nents, enum dma_data_direction direction) | 277 | int nents, enum dma_data_direction direction) |
314 | int | ||
315 | pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, | ||
316 | int nents, int direction) | ||
317 | 278 | ||
318 | Returns: the number of physical segments mapped (this may be shorter | 279 | Returns: the number of physical segments mapped (this may be shorter |
319 | than <nents> passed in if some elements of the scatter/gather list are | 280 | than <nents> passed in if some elements of the scatter/gather list are |
@@ -353,9 +314,6 @@ accessed sg->address and sg->length as shown above. | |||
353 | void | 314 | void |
354 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, | 315 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, |
355 | int nhwentries, enum dma_data_direction direction) | 316 | int nhwentries, enum dma_data_direction direction) |
356 | void | ||
357 | pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, | ||
358 | int nents, int direction) | ||
359 | 317 | ||
360 | Unmap the previously mapped scatter/gather list. All the parameters | 318 | Unmap the previously mapped scatter/gather list. All the parameters |
361 | must be the same as those and passed in to the scatter/gather mapping | 319 | must be the same as those and passed in to the scatter/gather mapping |
@@ -365,21 +323,23 @@ Note: <nents> must be the number you passed in, *not* the number of | |||
365 | physical entries returned. | 323 | physical entries returned. |
366 | 324 | ||
367 | void | 325 | void |
368 | dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, | 326 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, |
369 | enum dma_data_direction direction) | 327 | enum dma_data_direction direction) |
370 | void | 328 | void |
371 | pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, | 329 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, |
372 | size_t size, int direction) | 330 | enum dma_data_direction direction) |
373 | void | 331 | void |
374 | dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, | 332 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, |
375 | enum dma_data_direction direction) | 333 | enum dma_data_direction direction) |
376 | void | 334 | void |
377 | pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, | 335 | dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, |
378 | int nelems, int direction) | 336 | enum dma_data_direction direction) |
379 | 337 | ||
380 | Synchronise a single contiguous or scatter/gather mapping. All the | 338 | Synchronise a single contiguous or scatter/gather mapping for the cpu |
381 | parameters must be the same as those passed into the single mapping | 339 | and device. With the sync_sg API, all the parameters must be the same |
382 | API. | 340 | as those passed into the single mapping API. With the sync_single API, |
341 | you can use dma_handle and size parameters that aren't identical to | ||
342 | those passed into the single mapping API to do a partial sync. | ||
383 | 343 | ||
384 | Notes: You must do this: | 344 | Notes: You must do this: |
385 | 345 | ||
@@ -461,9 +421,9 @@ void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr, | |||
461 | Part II - Advanced dma_ usage | 421 | Part II - Advanced dma_ usage |
462 | ----------------------------- | 422 | ----------------------------- |
463 | 423 | ||
464 | Warning: These pieces of the DMA API have no PCI equivalent. They | 424 | Warning: These pieces of the DMA API should not be used in the |
465 | should also not be used in the majority of cases, since they cater for | 425 | majority of cases, since they cater for unlikely corner cases that |
466 | unlikely corner cases that don't belong in usual drivers. | 426 | don't belong in usual drivers. |
467 | 427 | ||
468 | If you don't understand how cache line coherency works between a | 428 | If you don't understand how cache line coherency works between a |
469 | processor and an I/O device, you should not be using this part of the | 429 | processor and an I/O device, you should not be using this part of the |
@@ -514,16 +474,6 @@ into the width returned by this call. It will also always be a power | |||
514 | of two for easy alignment. | 474 | of two for easy alignment. |
515 | 475 | ||
516 | void | 476 | void |
517 | dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, | ||
518 | unsigned long offset, size_t size, | ||
519 | enum dma_data_direction direction) | ||
520 | |||
521 | Does a partial sync, starting at offset and continuing for size. You | ||
522 | must be careful to observe the cache alignment and width when doing | ||
523 | anything like this. You must also be extra careful about accessing | ||
524 | memory you intend to sync partially. | ||
525 | |||
526 | void | ||
527 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, | 477 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
528 | enum dma_data_direction direction) | 478 | enum dma_data_direction direction) |
529 | 479 | ||
diff --git a/Documentation/HOWTO b/Documentation/HOWTO index 8495fc970391..f5395af88a41 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO | |||
@@ -221,8 +221,8 @@ branches. These different branches are: | |||
221 | - main 2.6.x kernel tree | 221 | - main 2.6.x kernel tree |
222 | - 2.6.x.y -stable kernel tree | 222 | - 2.6.x.y -stable kernel tree |
223 | - 2.6.x -git kernel patches | 223 | - 2.6.x -git kernel patches |
224 | - 2.6.x -mm kernel patches | ||
225 | - subsystem specific kernel trees and patches | 224 | - subsystem specific kernel trees and patches |
225 | - the 2.6.x -next kernel tree for integration tests | ||
226 | 226 | ||
227 | 2.6.x kernel tree | 227 | 2.6.x kernel tree |
228 | ----------------- | 228 | ----------------- |
@@ -232,7 +232,7 @@ process is as follows: | |||
232 | - As soon as a new kernel is released a two weeks window is open, | 232 | - As soon as a new kernel is released a two weeks window is open, |
233 | during this period of time maintainers can submit big diffs to | 233 | during this period of time maintainers can submit big diffs to |
234 | Linus, usually the patches that have already been included in the | 234 | Linus, usually the patches that have already been included in the |
235 | -mm kernel for a few weeks. The preferred way to submit big changes | 235 | -next kernel for a few weeks. The preferred way to submit big changes |
236 | is using git (the kernel's source management tool, more information | 236 | is using git (the kernel's source management tool, more information |
237 | can be found at http://git.or.cz/) but plain patches are also just | 237 | can be found at http://git.or.cz/) but plain patches are also just |
238 | fine. | 238 | fine. |
@@ -293,84 +293,43 @@ daily and represent the current state of Linus' tree. They are more | |||
293 | experimental than -rc kernels since they are generated automatically | 293 | experimental than -rc kernels since they are generated automatically |
294 | without even a cursory glance to see if they are sane. | 294 | without even a cursory glance to see if they are sane. |
295 | 295 | ||
296 | 2.6.x -mm kernel patches | ||
297 | ------------------------ | ||
298 | These are experimental kernel patches released by Andrew Morton. Andrew | ||
299 | takes all of the different subsystem kernel trees and patches and mushes | ||
300 | them together, along with a lot of patches that have been plucked from | ||
301 | the linux-kernel mailing list. This tree serves as a proving ground for | ||
302 | new features and patches. Once a patch has proved its worth in -mm for | ||
303 | a while Andrew or the subsystem maintainer pushes it on to Linus for | ||
304 | inclusion in mainline. | ||
305 | |||
306 | It is heavily encouraged that all new patches get tested in the -mm tree | ||
307 | before they are sent to Linus for inclusion in the main kernel tree. Code | ||
308 | which does not make an appearance in -mm before the opening of the merge | ||
309 | window will prove hard to merge into the mainline. | ||
310 | |||
311 | These kernels are not appropriate for use on systems that are supposed | ||
312 | to be stable and they are more risky to run than any of the other | ||
313 | branches. | ||
314 | |||
315 | If you wish to help out with the kernel development process, please test | ||
316 | and use these kernel releases and provide feedback to the linux-kernel | ||
317 | mailing list if you have any problems, and if everything works properly. | ||
318 | |||
319 | In addition to all the other experimental patches, these kernels usually | ||
320 | also contain any changes in the mainline -git kernels available at the | ||
321 | time of release. | ||
322 | |||
323 | The -mm kernels are not released on a fixed schedule, but usually a few | ||
324 | -mm kernels are released in between each -rc kernel (1 to 3 is common). | ||
325 | |||
326 | Subsystem Specific kernel trees and patches | 296 | Subsystem Specific kernel trees and patches |
327 | ------------------------------------------- | 297 | ------------------------------------------- |
328 | A number of the different kernel subsystem developers expose their | 298 | The maintainers of the various kernel subsystems --- and also many |
329 | development trees so that others can see what is happening in the | 299 | kernel subsystem developers --- expose their current state of |
330 | different areas of the kernel. These trees are pulled into the -mm | 300 | development in source repositories. That way, others can see what is |
331 | kernel releases as described above. | 301 | happening in the different areas of the kernel. In areas where |
332 | 302 | development is rapid, a developer may be asked to base his submissions | |
333 | Here is a list of some of the different kernel trees available: | 303 | onto such a subsystem kernel tree so that conflicts between the |
334 | git trees: | 304 | submission and other already ongoing work are avoided. |
335 | - Kbuild development tree, Sam Ravnborg <sam@ravnborg.org> | 305 | |
336 | git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git | 306 | Most of these repositories are git trees, but there are also other SCMs |
337 | 307 | in use, or patch queues being published as quilt series. Addresses of | |
338 | - ACPI development tree, Len Brown <len.brown@intel.com> | 308 | these subsystem repositories are listed in the MAINTAINERS file. Many |
339 | git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git | 309 | of them can be browsed at http://git.kernel.org/. |
340 | 310 | ||
341 | - Block development tree, Jens Axboe <jens.axboe@oracle.com> | 311 | Before a proposed patch is committed to such a subsystem tree, it is |
342 | git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git | 312 | subject to review which primarily happens on mailing lists (see the |
343 | 313 | respective section below). For several kernel subsystems, this review | |
344 | - DRM development tree, Dave Airlie <airlied@linux.ie> | 314 | process is tracked with the tool patchwork. Patchwork offers a web |
345 | git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git | 315 | interface which shows patch postings, any comments on a patch or |
346 | 316 | revisions to it, and maintainers can mark patches as under review, | |
347 | - ia64 development tree, Tony Luck <tony.luck@intel.com> | 317 | accepted, or rejected. Most of these patchwork sites are listed at |
348 | git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git | 318 | http://patchwork.kernel.org/ or http://patchwork.ozlabs.org/. |
349 | 319 | ||
350 | - infiniband, Roland Dreier <rolandd@cisco.com> | 320 | 2.6.x -next kernel tree for integration tests |
351 | git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git | 321 | --------------------------------------------- |
352 | 322 | Before updates from subsystem trees are merged into the mainline 2.6.x | |
353 | - libata, Jeff Garzik <jgarzik@pobox.com> | 323 | tree, they need to be integration-tested. For this purpose, a special |
354 | git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git | 324 | testing repository exists into which virtually all subsystem trees are |
355 | 325 | pulled on an almost daily basis: | |
356 | - network drivers, Jeff Garzik <jgarzik@pobox.com> | 326 | http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git |
357 | git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git | 327 | http://linux.f-seidel.de/linux-next/pmwiki/ |
358 | 328 | ||
359 | - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net> | 329 | This way, the -next kernel gives a summary outlook onto what will be |
360 | git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git | 330 | expected to go into the mainline kernel at the next merge period. |
361 | 331 | Adventurous testers are very welcome to runtime-test the -next kernel. | |
362 | - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com> | ||
363 | git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git | ||
364 | |||
365 | - x86, Ingo Molnar <mingo@elte.hu> | ||
366 | git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git | ||
367 | |||
368 | quilt trees: | ||
369 | - USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de> | ||
370 | kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ | ||
371 | 332 | ||
372 | Other kernel trees can be found listed at http://git.kernel.org/ and in | ||
373 | the MAINTAINERS file. | ||
374 | 333 | ||
375 | Bug Reporting | 334 | Bug Reporting |
376 | ------------- | 335 | ------------- |
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt index bc38283379f0..69dd29ed824e 100644 --- a/Documentation/IPMI.txt +++ b/Documentation/IPMI.txt | |||
@@ -365,6 +365,7 @@ You can change this at module load time (for a module) with: | |||
365 | regshifts=<shift1>,<shift2>,... | 365 | regshifts=<shift1>,<shift2>,... |
366 | slave_addrs=<addr1>,<addr2>,... | 366 | slave_addrs=<addr1>,<addr2>,... |
367 | force_kipmid=<enable1>,<enable2>,... | 367 | force_kipmid=<enable1>,<enable2>,... |
368 | kipmid_max_busy_us=<ustime1>,<ustime2>,... | ||
368 | unload_when_empty=[0|1] | 369 | unload_when_empty=[0|1] |
369 | 370 | ||
370 | Each of these except si_trydefaults is a list, the first item for the | 371 | Each of these except si_trydefaults is a list, the first item for the |
@@ -433,6 +434,7 @@ kernel command line as: | |||
433 | ipmi_si.regshifts=<shift1>,<shift2>,... | 434 | ipmi_si.regshifts=<shift1>,<shift2>,... |
434 | ipmi_si.slave_addrs=<addr1>,<addr2>,... | 435 | ipmi_si.slave_addrs=<addr1>,<addr2>,... |
435 | ipmi_si.force_kipmid=<enable1>,<enable2>,... | 436 | ipmi_si.force_kipmid=<enable1>,<enable2>,... |
437 | ipmi_si.kipmid_max_busy_us=<ustime1>,<ustime2>,... | ||
436 | 438 | ||
437 | It works the same as the module parameters of the same names. | 439 | It works the same as the module parameters of the same names. |
438 | 440 | ||
@@ -450,6 +452,16 @@ force this thread on or off. If you force it off and don't have | |||
450 | interrupts, the driver will run VERY slowly. Don't blame me, | 452 | interrupts, the driver will run VERY slowly. Don't blame me, |
451 | these interfaces suck. | 453 | these interfaces suck. |
452 | 454 | ||
455 | Unfortunately, this thread can use a lot of CPU depending on the | ||
456 | interface's performance. This can waste a lot of CPU and cause | ||
457 | various issues with detecting idle CPU and using extra power. To | ||
458 | avoid this, the kipmid_max_busy_us sets the maximum amount of time, in | ||
459 | microseconds, that kipmid will spin before sleeping for a tick. This | ||
460 | value sets a balance between performance and CPU waste and needs to be | ||
461 | tuned to your needs. Maybe, someday, auto-tuning will be added, but | ||
462 | that's not a simple thing and even the auto-tuning would need to be | ||
463 | tuned to the user's desired performance. | ||
464 | |||
453 | The driver supports a hot add and remove of interfaces. This way, | 465 | The driver supports a hot add and remove of interfaces. This way, |
454 | interfaces can be added or removed after the kernel is up and running. | 466 | interfaces can be added or removed after the kernel is up and running. |
455 | This is done using /sys/modules/ipmi_si/parameters/hotmod, which is a | 467 | This is done using /sys/modules/ipmi_si/parameters/hotmod, which is a |
diff --git a/Documentation/Makefile b/Documentation/Makefile index 94b945733534..6fc7ea1d1f9d 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | obj-m := DocBook/ accounting/ auxdisplay/ connector/ \ | 1 | obj-m := DocBook/ accounting/ auxdisplay/ connector/ \ |
2 | filesystems/configfs/ ia64/ networking/ \ | 2 | filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \ |
3 | pcmcia/ spi/ video4linux/ vm/ watchdog/src/ | 3 | pcmcia/ spi/ timers/ video4linux/ vm/ watchdog/src/ |
diff --git a/Documentation/PCI/PCI-DMA-mapping.txt b/Documentation/PCI/PCI-DMA-mapping.txt index ecad88d9fe59..52618ab069ad 100644 --- a/Documentation/PCI/PCI-DMA-mapping.txt +++ b/Documentation/PCI/PCI-DMA-mapping.txt | |||
@@ -1,12 +1,12 @@ | |||
1 | Dynamic DMA mapping | 1 | Dynamic DMA mapping Guide |
2 | =================== | 2 | ========================= |
3 | 3 | ||
4 | David S. Miller <davem@redhat.com> | 4 | David S. Miller <davem@redhat.com> |
5 | Richard Henderson <rth@cygnus.com> | 5 | Richard Henderson <rth@cygnus.com> |
6 | Jakub Jelinek <jakub@redhat.com> | 6 | Jakub Jelinek <jakub@redhat.com> |
7 | 7 | ||
8 | This document describes the DMA mapping system in terms of the pci_ | 8 | This is a guide to device driver writers on how to use the DMA API |
9 | API. For a similar API that works for generic devices, see | 9 | with example pseudo-code. For a concise description of the API, see |
10 | DMA-API.txt. | 10 | DMA-API.txt. |
11 | 11 | ||
12 | Most of the 64bit platforms have special hardware that translates bus | 12 | Most of the 64bit platforms have special hardware that translates bus |
@@ -26,12 +26,15 @@ mapped only for the time they are actually used and unmapped after the DMA | |||
26 | transfer. | 26 | transfer. |
27 | 27 | ||
28 | The following API will work of course even on platforms where no such | 28 | The following API will work of course even on platforms where no such |
29 | hardware exists, see e.g. arch/x86/include/asm/pci.h for how it is implemented on | 29 | hardware exists. |
30 | top of the virt_to_bus interface. | 30 | |
31 | Note that the DMA API works with any bus independent of the underlying | ||
32 | microprocessor architecture. You should use the DMA API rather than | ||
33 | the bus specific DMA API (e.g. pci_dma_*). | ||
31 | 34 | ||
32 | First of all, you should make sure | 35 | First of all, you should make sure |
33 | 36 | ||
34 | #include <linux/pci.h> | 37 | #include <linux/dma-mapping.h> |
35 | 38 | ||
36 | is in your driver. This file will obtain for you the definition of the | 39 | is in your driver. This file will obtain for you the definition of the |
37 | dma_addr_t (which can hold any valid DMA address for the platform) | 40 | dma_addr_t (which can hold any valid DMA address for the platform) |
@@ -78,44 +81,43 @@ for you to DMA from/to. | |||
78 | DMA addressing limitations | 81 | DMA addressing limitations |
79 | 82 | ||
80 | Does your device have any DMA addressing limitations? For example, is | 83 | Does your device have any DMA addressing limitations? For example, is |
81 | your device only capable of driving the low order 24-bits of address | 84 | your device only capable of driving the low order 24-bits of address? |
82 | on the PCI bus for SAC DMA transfers? If so, you need to inform the | 85 | If so, you need to inform the kernel of this fact. |
83 | PCI layer of this fact. | ||
84 | 86 | ||
85 | By default, the kernel assumes that your device can address the full | 87 | By default, the kernel assumes that your device can address the full |
86 | 32-bits in a SAC cycle. For a 64-bit DAC capable device, this needs | 88 | 32-bits. For a 64-bit capable device, this needs to be increased. |
87 | to be increased. And for a device with limitations, as discussed in | 89 | And for a device with limitations, as discussed in the previous |
88 | the previous paragraph, it needs to be decreased. | 90 | paragraph, it needs to be decreased. |
89 | 91 | ||
90 | pci_alloc_consistent() by default will return 32-bit DMA addresses. | 92 | Special note about PCI: PCI-X specification requires PCI-X devices to |
91 | PCI-X specification requires PCI-X devices to support 64-bit | 93 | support 64-bit addressing (DAC) for all transactions. And at least |
92 | addressing (DAC) for all transactions. And at least one platform (SGI | 94 | one platform (SGI SN2) requires 64-bit consistent allocations to |
93 | SN2) requires 64-bit consistent allocations to operate correctly when | 95 | operate correctly when the IO bus is in PCI-X mode. |
94 | the IO bus is in PCI-X mode. Therefore, like with pci_set_dma_mask(), | 96 | |
95 | it's good practice to call pci_set_consistent_dma_mask() to set the | 97 | For correct operation, you must interrogate the kernel in your device |
96 | appropriate mask even if your device only supports 32-bit DMA | 98 | probe routine to see if the DMA controller on the machine can properly |
97 | (default) and especially if it's a PCI-X device. | 99 | support the DMA addressing limitation your device has. It is good |
98 | 100 | style to do this even if your device holds the default setting, | |
99 | For correct operation, you must interrogate the PCI layer in your | ||
100 | device probe routine to see if the PCI controller on the machine can | ||
101 | properly support the DMA addressing limitation your device has. It is | ||
102 | good style to do this even if your device holds the default setting, | ||
103 | because this shows that you did think about these issues wrt. your | 101 | because this shows that you did think about these issues wrt. your |
104 | device. | 102 | device. |
105 | 103 | ||
106 | The query is performed via a call to pci_set_dma_mask(): | 104 | The query is performed via a call to dma_set_mask(): |
107 | 105 | ||
108 | int pci_set_dma_mask(struct pci_dev *pdev, u64 device_mask); | 106 | int dma_set_mask(struct device *dev, u64 mask); |
109 | 107 | ||
110 | The query for consistent allocations is performed via a call to | 108 | The query for consistent allocations is performed via a call to |
111 | pci_set_consistent_dma_mask(): | 109 | dma_set_coherent_mask(): |
112 | 110 | ||
113 | int pci_set_consistent_dma_mask(struct pci_dev *pdev, u64 device_mask); | 111 | int dma_set_coherent_mask(struct device *dev, u64 mask); |
114 | 112 | ||
115 | Here, pdev is a pointer to the PCI device struct of your device, and | 113 | Here, dev is a pointer to the device struct of your device, and mask |
116 | device_mask is a bit mask describing which bits of a PCI address your | 114 | is a bit mask describing which bits of an address your device |
117 | device supports. It returns zero if your card can perform DMA | 115 | supports. It returns zero if your card can perform DMA properly on |
118 | properly on the machine given the address mask you provided. | 116 | the machine given the address mask you provided. In general, the |
117 | device struct of your device is embedded in the bus specific device | ||
118 | struct of your device. For example, a pointer to the device struct of | ||
119 | your PCI device is pdev->dev (pdev is a pointer to the PCI device | ||
120 | struct of your device). | ||
119 | 121 | ||
120 | If it returns non-zero, your device cannot perform DMA properly on | 122 | If it returns non-zero, your device cannot perform DMA properly on |
121 | this platform, and attempting to do so will result in undefined | 123 | this platform, and attempting to do so will result in undefined |
@@ -133,31 +135,30 @@ of your driver reports that performance is bad or that the device is not | |||
133 | even detected, you can ask them for the kernel messages to find out | 135 | even detected, you can ask them for the kernel messages to find out |
134 | exactly why. | 136 | exactly why. |
135 | 137 | ||
136 | The standard 32-bit addressing PCI device would do something like | 138 | The standard 32-bit addressing device would do something like this: |
137 | this: | ||
138 | 139 | ||
139 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { | 140 | if (dma_set_mask(dev, DMA_BIT_MASK(32))) { |
140 | printk(KERN_WARNING | 141 | printk(KERN_WARNING |
141 | "mydev: No suitable DMA available.\n"); | 142 | "mydev: No suitable DMA available.\n"); |
142 | goto ignore_this_device; | 143 | goto ignore_this_device; |
143 | } | 144 | } |
144 | 145 | ||
145 | Another common scenario is a 64-bit capable device. The approach | 146 | Another common scenario is a 64-bit capable device. The approach here |
146 | here is to try for 64-bit DAC addressing, but back down to a | 147 | is to try for 64-bit addressing, but back down to a 32-bit mask that |
147 | 32-bit mask should that fail. The PCI platform code may fail the | 148 | should not fail. The kernel may fail the 64-bit mask not because the |
148 | 64-bit mask not because the platform is not capable of 64-bit | 149 | platform is not capable of 64-bit addressing. Rather, it may fail in |
149 | addressing. Rather, it may fail in this case simply because | 150 | this case simply because 32-bit addressing is done more efficiently |
150 | 32-bit SAC addressing is done more efficiently than DAC addressing. | 151 | than 64-bit addressing. For example, Sparc64 PCI SAC addressing is |
151 | Sparc64 is one platform which behaves in this way. | 152 | more efficient than DAC addressing. |
152 | 153 | ||
153 | Here is how you would handle a 64-bit capable device which can drive | 154 | Here is how you would handle a 64-bit capable device which can drive |
154 | all 64-bits when accessing streaming DMA: | 155 | all 64-bits when accessing streaming DMA: |
155 | 156 | ||
156 | int using_dac; | 157 | int using_dac; |
157 | 158 | ||
158 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { | 159 | if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { |
159 | using_dac = 1; | 160 | using_dac = 1; |
160 | } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { | 161 | } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) { |
161 | using_dac = 0; | 162 | using_dac = 0; |
162 | } else { | 163 | } else { |
163 | printk(KERN_WARNING | 164 | printk(KERN_WARNING |
@@ -170,36 +171,36 @@ the case would look like this: | |||
170 | 171 | ||
171 | int using_dac, consistent_using_dac; | 172 | int using_dac, consistent_using_dac; |
172 | 173 | ||
173 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { | 174 | if (!dma_set_mask(dev, DMA_BIT_MASK(64))) { |
174 | using_dac = 1; | 175 | using_dac = 1; |
175 | consistent_using_dac = 1; | 176 | consistent_using_dac = 1; |
176 | pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | 177 | dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); |
177 | } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { | 178 | } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) { |
178 | using_dac = 0; | 179 | using_dac = 0; |
179 | consistent_using_dac = 0; | 180 | consistent_using_dac = 0; |
180 | pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | 181 | dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); |
181 | } else { | 182 | } else { |
182 | printk(KERN_WARNING | 183 | printk(KERN_WARNING |
183 | "mydev: No suitable DMA available.\n"); | 184 | "mydev: No suitable DMA available.\n"); |
184 | goto ignore_this_device; | 185 | goto ignore_this_device; |
185 | } | 186 | } |
186 | 187 | ||
187 | pci_set_consistent_dma_mask() will always be able to set the same or a | 188 | dma_set_coherent_mask() will always be able to set the same or a |
188 | smaller mask as pci_set_dma_mask(). However for the rare case that a | 189 | smaller mask as dma_set_mask(). However for the rare case that a |
189 | device driver only uses consistent allocations, one would have to | 190 | device driver only uses consistent allocations, one would have to |
190 | check the return value from pci_set_consistent_dma_mask(). | 191 | check the return value from dma_set_coherent_mask(). |
191 | 192 | ||
192 | Finally, if your device can only drive the low 24-bits of | 193 | Finally, if your device can only drive the low 24-bits of |
193 | address during PCI bus mastering you might do something like: | 194 | address you might do something like: |
194 | 195 | ||
195 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(24))) { | 196 | if (dma_set_mask(dev, DMA_BIT_MASK(24))) { |
196 | printk(KERN_WARNING | 197 | printk(KERN_WARNING |
197 | "mydev: 24-bit DMA addressing not available.\n"); | 198 | "mydev: 24-bit DMA addressing not available.\n"); |
198 | goto ignore_this_device; | 199 | goto ignore_this_device; |
199 | } | 200 | } |
200 | 201 | ||
201 | When pci_set_dma_mask() is successful, and returns zero, the PCI layer | 202 | When dma_set_mask() is successful, and returns zero, the kernel saves |
202 | saves away this mask you have provided. The PCI layer will use this | 203 | away this mask you have provided. The kernel will use this |
203 | information later when you make DMA mappings. | 204 | information later when you make DMA mappings. |
204 | 205 | ||
205 | There is a case which we are aware of at this time, which is worth | 206 | There is a case which we are aware of at this time, which is worth |
@@ -208,7 +209,7 @@ functions (for example a sound card provides playback and record | |||
208 | functions) and the various different functions have _different_ | 209 | functions) and the various different functions have _different_ |
209 | DMA addressing limitations, you may wish to probe each mask and | 210 | DMA addressing limitations, you may wish to probe each mask and |
210 | only provide the functionality which the machine can handle. It | 211 | only provide the functionality which the machine can handle. It |
211 | is important that the last call to pci_set_dma_mask() be for the | 212 | is important that the last call to dma_set_mask() be for the |
212 | most specific mask. | 213 | most specific mask. |
213 | 214 | ||
214 | Here is pseudo-code showing how this might be done: | 215 | Here is pseudo-code showing how this might be done: |
@@ -217,17 +218,17 @@ Here is pseudo-code showing how this might be done: | |||
217 | #define RECORD_ADDRESS_BITS DMA_BIT_MASK(24) | 218 | #define RECORD_ADDRESS_BITS DMA_BIT_MASK(24) |
218 | 219 | ||
219 | struct my_sound_card *card; | 220 | struct my_sound_card *card; |
220 | struct pci_dev *pdev; | 221 | struct device *dev; |
221 | 222 | ||
222 | ... | 223 | ... |
223 | if (!pci_set_dma_mask(pdev, PLAYBACK_ADDRESS_BITS)) { | 224 | if (!dma_set_mask(dev, PLAYBACK_ADDRESS_BITS)) { |
224 | card->playback_enabled = 1; | 225 | card->playback_enabled = 1; |
225 | } else { | 226 | } else { |
226 | card->playback_enabled = 0; | 227 | card->playback_enabled = 0; |
227 | printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n", | 228 | printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n", |
228 | card->name); | 229 | card->name); |
229 | } | 230 | } |
230 | if (!pci_set_dma_mask(pdev, RECORD_ADDRESS_BITS)) { | 231 | if (!dma_set_mask(dev, RECORD_ADDRESS_BITS)) { |
231 | card->record_enabled = 1; | 232 | card->record_enabled = 1; |
232 | } else { | 233 | } else { |
233 | card->record_enabled = 0; | 234 | card->record_enabled = 0; |
@@ -252,8 +253,8 @@ There are two types of DMA mappings: | |||
252 | Think of "consistent" as "synchronous" or "coherent". | 253 | Think of "consistent" as "synchronous" or "coherent". |
253 | 254 | ||
254 | The current default is to return consistent memory in the low 32 | 255 | The current default is to return consistent memory in the low 32 |
255 | bits of the PCI bus space. However, for future compatibility you | 256 | bits of the bus space. However, for future compatibility you should |
256 | should set the consistent mask even if this default is fine for your | 257 | set the consistent mask even if this default is fine for your |
257 | driver. | 258 | driver. |
258 | 259 | ||
259 | Good examples of what to use consistent mappings for are: | 260 | Good examples of what to use consistent mappings for are: |
@@ -285,9 +286,9 @@ There are two types of DMA mappings: | |||
285 | found in PCI bridges (such as by reading a register's value | 286 | found in PCI bridges (such as by reading a register's value |
286 | after writing it). | 287 | after writing it). |
287 | 288 | ||
288 | - Streaming DMA mappings which are usually mapped for one DMA transfer, | 289 | - Streaming DMA mappings which are usually mapped for one DMA |
289 | unmapped right after it (unless you use pci_dma_sync_* below) and for which | 290 | transfer, unmapped right after it (unless you use dma_sync_* below) |
290 | hardware can optimize for sequential accesses. | 291 | and for which hardware can optimize for sequential accesses. |
291 | 292 | ||
292 | This of "streaming" as "asynchronous" or "outside the coherency | 293 | This of "streaming" as "asynchronous" or "outside the coherency |
293 | domain". | 294 | domain". |
@@ -302,8 +303,8 @@ There are two types of DMA mappings: | |||
302 | optimizations the hardware allows. To this end, when using | 303 | optimizations the hardware allows. To this end, when using |
303 | such mappings you must be explicit about what you want to happen. | 304 | such mappings you must be explicit about what you want to happen. |
304 | 305 | ||
305 | Neither type of DMA mapping has alignment restrictions that come | 306 | Neither type of DMA mapping has alignment restrictions that come from |
306 | from PCI, although some devices may have such restrictions. | 307 | the underlying bus, although some devices may have such restrictions. |
307 | Also, systems with caches that aren't DMA-coherent will work better | 308 | Also, systems with caches that aren't DMA-coherent will work better |
308 | when the underlying buffers don't share cache lines with other data. | 309 | when the underlying buffers don't share cache lines with other data. |
309 | 310 | ||
@@ -315,33 +316,27 @@ you should do: | |||
315 | 316 | ||
316 | dma_addr_t dma_handle; | 317 | dma_addr_t dma_handle; |
317 | 318 | ||
318 | cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle); | 319 | cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp); |
319 | |||
320 | where pdev is a struct pci_dev *. This may be called in interrupt context. | ||
321 | You should use dma_alloc_coherent (see DMA-API.txt) for buses | ||
322 | where devices don't have struct pci_dev (like ISA, EISA). | ||
323 | 320 | ||
324 | This argument is needed because the DMA translations may be bus | 321 | where device is a struct device *. This may be called in interrupt |
325 | specific (and often is private to the bus which the device is attached | 322 | context with the GFP_ATOMIC flag. |
326 | to). | ||
327 | 323 | ||
328 | Size is the length of the region you want to allocate, in bytes. | 324 | Size is the length of the region you want to allocate, in bytes. |
329 | 325 | ||
330 | This routine will allocate RAM for that region, so it acts similarly to | 326 | This routine will allocate RAM for that region, so it acts similarly to |
331 | __get_free_pages (but takes size instead of a page order). If your | 327 | __get_free_pages (but takes size instead of a page order). If your |
332 | driver needs regions sized smaller than a page, you may prefer using | 328 | driver needs regions sized smaller than a page, you may prefer using |
333 | the pci_pool interface, described below. | 329 | the dma_pool interface, described below. |
334 | 330 | ||
335 | The consistent DMA mapping interfaces, for non-NULL pdev, will by | 331 | The consistent DMA mapping interfaces, for non-NULL dev, will by |
336 | default return a DMA address which is SAC (Single Address Cycle) | 332 | default return a DMA address which is 32-bit addressable. Even if the |
337 | addressable. Even if the device indicates (via PCI dma mask) that it | 333 | device indicates (via DMA mask) that it may address the upper 32-bits, |
338 | may address the upper 32-bits and thus perform DAC cycles, consistent | 334 | consistent allocation will only return > 32-bit addresses for DMA if |
339 | allocation will only return > 32-bit PCI addresses for DMA if the | 335 | the consistent DMA mask has been explicitly changed via |
340 | consistent dma mask has been explicitly changed via | 336 | dma_set_coherent_mask(). This is true of the dma_pool interface as |
341 | pci_set_consistent_dma_mask(). This is true of the pci_pool interface | 337 | well. |
342 | as well. | 338 | |
343 | 339 | dma_alloc_coherent returns two values: the virtual address which you | |
344 | pci_alloc_consistent returns two values: the virtual address which you | ||
345 | can use to access it from the CPU and dma_handle which you pass to the | 340 | can use to access it from the CPU and dma_handle which you pass to the |
346 | card. | 341 | card. |
347 | 342 | ||
@@ -354,54 +349,54 @@ buffer you receive will not cross a 64K boundary. | |||
354 | 349 | ||
355 | To unmap and free such a DMA region, you call: | 350 | To unmap and free such a DMA region, you call: |
356 | 351 | ||
357 | pci_free_consistent(pdev, size, cpu_addr, dma_handle); | 352 | dma_free_coherent(dev, size, cpu_addr, dma_handle); |
358 | 353 | ||
359 | where pdev, size are the same as in the above call and cpu_addr and | 354 | where dev, size are the same as in the above call and cpu_addr and |
360 | dma_handle are the values pci_alloc_consistent returned to you. | 355 | dma_handle are the values dma_alloc_coherent returned to you. |
361 | This function may not be called in interrupt context. | 356 | This function may not be called in interrupt context. |
362 | 357 | ||
363 | If your driver needs lots of smaller memory regions, you can write | 358 | If your driver needs lots of smaller memory regions, you can write |
364 | custom code to subdivide pages returned by pci_alloc_consistent, | 359 | custom code to subdivide pages returned by dma_alloc_coherent, |
365 | or you can use the pci_pool API to do that. A pci_pool is like | 360 | or you can use the dma_pool API to do that. A dma_pool is like |
366 | a kmem_cache, but it uses pci_alloc_consistent not __get_free_pages. | 361 | a kmem_cache, but it uses dma_alloc_coherent not __get_free_pages. |
367 | Also, it understands common hardware constraints for alignment, | 362 | Also, it understands common hardware constraints for alignment, |
368 | like queue heads needing to be aligned on N byte boundaries. | 363 | like queue heads needing to be aligned on N byte boundaries. |
369 | 364 | ||
370 | Create a pci_pool like this: | 365 | Create a dma_pool like this: |
371 | 366 | ||
372 | struct pci_pool *pool; | 367 | struct dma_pool *pool; |
373 | 368 | ||
374 | pool = pci_pool_create(name, pdev, size, align, alloc); | 369 | pool = dma_pool_create(name, dev, size, align, alloc); |
375 | 370 | ||
376 | The "name" is for diagnostics (like a kmem_cache name); pdev and size | 371 | The "name" is for diagnostics (like a kmem_cache name); dev and size |
377 | are as above. The device's hardware alignment requirement for this | 372 | are as above. The device's hardware alignment requirement for this |
378 | type of data is "align" (which is expressed in bytes, and must be a | 373 | type of data is "align" (which is expressed in bytes, and must be a |
379 | power of two). If your device has no boundary crossing restrictions, | 374 | power of two). If your device has no boundary crossing restrictions, |
380 | pass 0 for alloc; passing 4096 says memory allocated from this pool | 375 | pass 0 for alloc; passing 4096 says memory allocated from this pool |
381 | must not cross 4KByte boundaries (but at that time it may be better to | 376 | must not cross 4KByte boundaries (but at that time it may be better to |
382 | go for pci_alloc_consistent directly instead). | 377 | go for dma_alloc_coherent directly instead). |
383 | 378 | ||
384 | Allocate memory from a pci pool like this: | 379 | Allocate memory from a dma pool like this: |
385 | 380 | ||
386 | cpu_addr = pci_pool_alloc(pool, flags, &dma_handle); | 381 | cpu_addr = dma_pool_alloc(pool, flags, &dma_handle); |
387 | 382 | ||
388 | flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor | 383 | flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor |
389 | holding SMP locks), SLAB_ATOMIC otherwise. Like pci_alloc_consistent, | 384 | holding SMP locks), SLAB_ATOMIC otherwise. Like dma_alloc_coherent, |
390 | this returns two values, cpu_addr and dma_handle. | 385 | this returns two values, cpu_addr and dma_handle. |
391 | 386 | ||
392 | Free memory that was allocated from a pci_pool like this: | 387 | Free memory that was allocated from a dma_pool like this: |
393 | 388 | ||
394 | pci_pool_free(pool, cpu_addr, dma_handle); | 389 | dma_pool_free(pool, cpu_addr, dma_handle); |
395 | 390 | ||
396 | where pool is what you passed to pci_pool_alloc, and cpu_addr and | 391 | where pool is what you passed to dma_pool_alloc, and cpu_addr and |
397 | dma_handle are the values pci_pool_alloc returned. This function | 392 | dma_handle are the values dma_pool_alloc returned. This function |
398 | may be called in interrupt context. | 393 | may be called in interrupt context. |
399 | 394 | ||
400 | Destroy a pci_pool by calling: | 395 | Destroy a dma_pool by calling: |
401 | 396 | ||
402 | pci_pool_destroy(pool); | 397 | dma_pool_destroy(pool); |
403 | 398 | ||
404 | Make sure you've called pci_pool_free for all memory allocated | 399 | Make sure you've called dma_pool_free for all memory allocated |
405 | from a pool before you destroy the pool. This function may not | 400 | from a pool before you destroy the pool. This function may not |
406 | be called in interrupt context. | 401 | be called in interrupt context. |
407 | 402 | ||
@@ -411,15 +406,15 @@ The interfaces described in subsequent portions of this document | |||
411 | take a DMA direction argument, which is an integer and takes on | 406 | take a DMA direction argument, which is an integer and takes on |
412 | one of the following values: | 407 | one of the following values: |
413 | 408 | ||
414 | PCI_DMA_BIDIRECTIONAL | 409 | DMA_BIDIRECTIONAL |
415 | PCI_DMA_TODEVICE | 410 | DMA_TO_DEVICE |
416 | PCI_DMA_FROMDEVICE | 411 | DMA_FROM_DEVICE |
417 | PCI_DMA_NONE | 412 | DMA_NONE |
418 | 413 | ||
419 | One should provide the exact DMA direction if you know it. | 414 | One should provide the exact DMA direction if you know it. |
420 | 415 | ||
421 | PCI_DMA_TODEVICE means "from main memory to the PCI device" | 416 | DMA_TO_DEVICE means "from main memory to the device" |
422 | PCI_DMA_FROMDEVICE means "from the PCI device to main memory" | 417 | DMA_FROM_DEVICE means "from the device to main memory" |
423 | It is the direction in which the data moves during the DMA | 418 | It is the direction in which the data moves during the DMA |
424 | transfer. | 419 | transfer. |
425 | 420 | ||
@@ -427,12 +422,12 @@ You are _strongly_ encouraged to specify this as precisely | |||
427 | as you possibly can. | 422 | as you possibly can. |
428 | 423 | ||
429 | If you absolutely cannot know the direction of the DMA transfer, | 424 | If you absolutely cannot know the direction of the DMA transfer, |
430 | specify PCI_DMA_BIDIRECTIONAL. It means that the DMA can go in | 425 | specify DMA_BIDIRECTIONAL. It means that the DMA can go in |
431 | either direction. The platform guarantees that you may legally | 426 | either direction. The platform guarantees that you may legally |
432 | specify this, and that it will work, but this may be at the | 427 | specify this, and that it will work, but this may be at the |
433 | cost of performance for example. | 428 | cost of performance for example. |
434 | 429 | ||
435 | The value PCI_DMA_NONE is to be used for debugging. One can | 430 | The value DMA_NONE is to be used for debugging. One can |
436 | hold this in a data structure before you come to know the | 431 | hold this in a data structure before you come to know the |
437 | precise direction, and this will help catch cases where your | 432 | precise direction, and this will help catch cases where your |
438 | direction tracking logic has failed to set things up properly. | 433 | direction tracking logic has failed to set things up properly. |
@@ -442,21 +437,21 @@ potential platform-specific optimizations of such) is for debugging. | |||
442 | Some platforms actually have a write permission boolean which DMA | 437 | Some platforms actually have a write permission boolean which DMA |
443 | mappings can be marked with, much like page protections in the user | 438 | mappings can be marked with, much like page protections in the user |
444 | program address space. Such platforms can and do report errors in the | 439 | program address space. Such platforms can and do report errors in the |
445 | kernel logs when the PCI controller hardware detects violation of the | 440 | kernel logs when the DMA controller hardware detects violation of the |
446 | permission setting. | 441 | permission setting. |
447 | 442 | ||
448 | Only streaming mappings specify a direction, consistent mappings | 443 | Only streaming mappings specify a direction, consistent mappings |
449 | implicitly have a direction attribute setting of | 444 | implicitly have a direction attribute setting of |
450 | PCI_DMA_BIDIRECTIONAL. | 445 | DMA_BIDIRECTIONAL. |
451 | 446 | ||
452 | The SCSI subsystem tells you the direction to use in the | 447 | The SCSI subsystem tells you the direction to use in the |
453 | 'sc_data_direction' member of the SCSI command your driver is | 448 | 'sc_data_direction' member of the SCSI command your driver is |
454 | working on. | 449 | working on. |
455 | 450 | ||
456 | For Networking drivers, it's a rather simple affair. For transmit | 451 | For Networking drivers, it's a rather simple affair. For transmit |
457 | packets, map/unmap them with the PCI_DMA_TODEVICE direction | 452 | packets, map/unmap them with the DMA_TO_DEVICE direction |
458 | specifier. For receive packets, just the opposite, map/unmap them | 453 | specifier. For receive packets, just the opposite, map/unmap them |
459 | with the PCI_DMA_FROMDEVICE direction specifier. | 454 | with the DMA_FROM_DEVICE direction specifier. |
460 | 455 | ||
461 | Using Streaming DMA mappings | 456 | Using Streaming DMA mappings |
462 | 457 | ||
@@ -467,43 +462,43 @@ scatterlist. | |||
467 | 462 | ||
468 | To map a single region, you do: | 463 | To map a single region, you do: |
469 | 464 | ||
470 | struct pci_dev *pdev = mydev->pdev; | 465 | struct device *dev = &my_dev->dev; |
471 | dma_addr_t dma_handle; | 466 | dma_addr_t dma_handle; |
472 | void *addr = buffer->ptr; | 467 | void *addr = buffer->ptr; |
473 | size_t size = buffer->len; | 468 | size_t size = buffer->len; |
474 | 469 | ||
475 | dma_handle = pci_map_single(pdev, addr, size, direction); | 470 | dma_handle = dma_map_single(dev, addr, size, direction); |
476 | 471 | ||
477 | and to unmap it: | 472 | and to unmap it: |
478 | 473 | ||
479 | pci_unmap_single(pdev, dma_handle, size, direction); | 474 | dma_unmap_single(dev, dma_handle, size, direction); |
480 | 475 | ||
481 | You should call pci_unmap_single when the DMA activity is finished, e.g. | 476 | You should call dma_unmap_single when the DMA activity is finished, e.g. |
482 | from the interrupt which told you that the DMA transfer is done. | 477 | from the interrupt which told you that the DMA transfer is done. |
483 | 478 | ||
484 | Using cpu pointers like this for single mappings has a disadvantage, | 479 | Using cpu pointers like this for single mappings has a disadvantage, |
485 | you cannot reference HIGHMEM memory in this way. Thus, there is a | 480 | you cannot reference HIGHMEM memory in this way. Thus, there is a |
486 | map/unmap interface pair akin to pci_{map,unmap}_single. These | 481 | map/unmap interface pair akin to dma_{map,unmap}_single. These |
487 | interfaces deal with page/offset pairs instead of cpu pointers. | 482 | interfaces deal with page/offset pairs instead of cpu pointers. |
488 | Specifically: | 483 | Specifically: |
489 | 484 | ||
490 | struct pci_dev *pdev = mydev->pdev; | 485 | struct device *dev = &my_dev->dev; |
491 | dma_addr_t dma_handle; | 486 | dma_addr_t dma_handle; |
492 | struct page *page = buffer->page; | 487 | struct page *page = buffer->page; |
493 | unsigned long offset = buffer->offset; | 488 | unsigned long offset = buffer->offset; |
494 | size_t size = buffer->len; | 489 | size_t size = buffer->len; |
495 | 490 | ||
496 | dma_handle = pci_map_page(pdev, page, offset, size, direction); | 491 | dma_handle = dma_map_page(dev, page, offset, size, direction); |
497 | 492 | ||
498 | ... | 493 | ... |
499 | 494 | ||
500 | pci_unmap_page(pdev, dma_handle, size, direction); | 495 | dma_unmap_page(dev, dma_handle, size, direction); |
501 | 496 | ||
502 | Here, "offset" means byte offset within the given page. | 497 | Here, "offset" means byte offset within the given page. |
503 | 498 | ||
504 | With scatterlists, you map a region gathered from several regions by: | 499 | With scatterlists, you map a region gathered from several regions by: |
505 | 500 | ||
506 | int i, count = pci_map_sg(pdev, sglist, nents, direction); | 501 | int i, count = dma_map_sg(dev, sglist, nents, direction); |
507 | struct scatterlist *sg; | 502 | struct scatterlist *sg; |
508 | 503 | ||
509 | for_each_sg(sglist, sg, count, i) { | 504 | for_each_sg(sglist, sg, count, i) { |
@@ -527,16 +522,16 @@ accessed sg->address and sg->length as shown above. | |||
527 | 522 | ||
528 | To unmap a scatterlist, just call: | 523 | To unmap a scatterlist, just call: |
529 | 524 | ||
530 | pci_unmap_sg(pdev, sglist, nents, direction); | 525 | dma_unmap_sg(dev, sglist, nents, direction); |
531 | 526 | ||
532 | Again, make sure DMA activity has already finished. | 527 | Again, make sure DMA activity has already finished. |
533 | 528 | ||
534 | PLEASE NOTE: The 'nents' argument to the pci_unmap_sg call must be | 529 | PLEASE NOTE: The 'nents' argument to the dma_unmap_sg call must be |
535 | the _same_ one you passed into the pci_map_sg call, | 530 | the _same_ one you passed into the dma_map_sg call, |
536 | it should _NOT_ be the 'count' value _returned_ from the | 531 | it should _NOT_ be the 'count' value _returned_ from the |
537 | pci_map_sg call. | 532 | dma_map_sg call. |
538 | 533 | ||
539 | Every pci_map_{single,sg} call should have its pci_unmap_{single,sg} | 534 | Every dma_map_{single,sg} call should have its dma_unmap_{single,sg} |
540 | counterpart, because the bus address space is a shared resource (although | 535 | counterpart, because the bus address space is a shared resource (although |
541 | in some ports the mapping is per each BUS so less devices contend for the | 536 | in some ports the mapping is per each BUS so less devices contend for the |
542 | same bus address space) and you could render the machine unusable by eating | 537 | same bus address space) and you could render the machine unusable by eating |
@@ -547,14 +542,14 @@ the data in between the DMA transfers, the buffer needs to be synced | |||
547 | properly in order for the cpu and device to see the most uptodate and | 542 | properly in order for the cpu and device to see the most uptodate and |
548 | correct copy of the DMA buffer. | 543 | correct copy of the DMA buffer. |
549 | 544 | ||
550 | So, firstly, just map it with pci_map_{single,sg}, and after each DMA | 545 | So, firstly, just map it with dma_map_{single,sg}, and after each DMA |
551 | transfer call either: | 546 | transfer call either: |
552 | 547 | ||
553 | pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction); | 548 | dma_sync_single_for_cpu(dev, dma_handle, size, direction); |
554 | 549 | ||
555 | or: | 550 | or: |
556 | 551 | ||
557 | pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction); | 552 | dma_sync_sg_for_cpu(dev, sglist, nents, direction); |
558 | 553 | ||
559 | as appropriate. | 554 | as appropriate. |
560 | 555 | ||
@@ -562,27 +557,27 @@ Then, if you wish to let the device get at the DMA area again, | |||
562 | finish accessing the data with the cpu, and then before actually | 557 | finish accessing the data with the cpu, and then before actually |
563 | giving the buffer to the hardware call either: | 558 | giving the buffer to the hardware call either: |
564 | 559 | ||
565 | pci_dma_sync_single_for_device(pdev, dma_handle, size, direction); | 560 | dma_sync_single_for_device(dev, dma_handle, size, direction); |
566 | 561 | ||
567 | or: | 562 | or: |
568 | 563 | ||
569 | pci_dma_sync_sg_for_device(dev, sglist, nents, direction); | 564 | dma_sync_sg_for_device(dev, sglist, nents, direction); |
570 | 565 | ||
571 | as appropriate. | 566 | as appropriate. |
572 | 567 | ||
573 | After the last DMA transfer call one of the DMA unmap routines | 568 | After the last DMA transfer call one of the DMA unmap routines |
574 | pci_unmap_{single,sg}. If you don't touch the data from the first pci_map_* | 569 | dma_unmap_{single,sg}. If you don't touch the data from the first dma_map_* |
575 | call till pci_unmap_*, then you don't have to call the pci_dma_sync_* | 570 | call till dma_unmap_*, then you don't have to call the dma_sync_* |
576 | routines at all. | 571 | routines at all. |
577 | 572 | ||
578 | Here is pseudo code which shows a situation in which you would need | 573 | Here is pseudo code which shows a situation in which you would need |
579 | to use the pci_dma_sync_*() interfaces. | 574 | to use the dma_sync_*() interfaces. |
580 | 575 | ||
581 | my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len) | 576 | my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len) |
582 | { | 577 | { |
583 | dma_addr_t mapping; | 578 | dma_addr_t mapping; |
584 | 579 | ||
585 | mapping = pci_map_single(cp->pdev, buffer, len, PCI_DMA_FROMDEVICE); | 580 | mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE); |
586 | 581 | ||
587 | cp->rx_buf = buffer; | 582 | cp->rx_buf = buffer; |
588 | cp->rx_len = len; | 583 | cp->rx_len = len; |
@@ -606,25 +601,25 @@ to use the pci_dma_sync_*() interfaces. | |||
606 | * the DMA transfer with the CPU first | 601 | * the DMA transfer with the CPU first |
607 | * so that we see updated contents. | 602 | * so that we see updated contents. |
608 | */ | 603 | */ |
609 | pci_dma_sync_single_for_cpu(cp->pdev, cp->rx_dma, | 604 | dma_sync_single_for_cpu(&cp->dev, cp->rx_dma, |
610 | cp->rx_len, | 605 | cp->rx_len, |
611 | PCI_DMA_FROMDEVICE); | 606 | DMA_FROM_DEVICE); |
612 | 607 | ||
613 | /* Now it is safe to examine the buffer. */ | 608 | /* Now it is safe to examine the buffer. */ |
614 | hp = (struct my_card_header *) cp->rx_buf; | 609 | hp = (struct my_card_header *) cp->rx_buf; |
615 | if (header_is_ok(hp)) { | 610 | if (header_is_ok(hp)) { |
616 | pci_unmap_single(cp->pdev, cp->rx_dma, cp->rx_len, | 611 | dma_unmap_single(&cp->dev, cp->rx_dma, cp->rx_len, |
617 | PCI_DMA_FROMDEVICE); | 612 | DMA_FROM_DEVICE); |
618 | pass_to_upper_layers(cp->rx_buf); | 613 | pass_to_upper_layers(cp->rx_buf); |
619 | make_and_setup_new_rx_buf(cp); | 614 | make_and_setup_new_rx_buf(cp); |
620 | } else { | 615 | } else { |
621 | /* Just sync the buffer and give it back | 616 | /* Just sync the buffer and give it back |
622 | * to the card. | 617 | * to the card. |
623 | */ | 618 | */ |
624 | pci_dma_sync_single_for_device(cp->pdev, | 619 | dma_sync_single_for_device(&cp->dev, |
625 | cp->rx_dma, | 620 | cp->rx_dma, |
626 | cp->rx_len, | 621 | cp->rx_len, |
627 | PCI_DMA_FROMDEVICE); | 622 | DMA_FROM_DEVICE); |
628 | give_rx_buf_to_card(cp); | 623 | give_rx_buf_to_card(cp); |
629 | } | 624 | } |
630 | } | 625 | } |
@@ -634,19 +629,19 @@ Drivers converted fully to this interface should not use virt_to_bus any | |||
634 | longer, nor should they use bus_to_virt. Some drivers have to be changed a | 629 | longer, nor should they use bus_to_virt. Some drivers have to be changed a |
635 | little bit, because there is no longer an equivalent to bus_to_virt in the | 630 | little bit, because there is no longer an equivalent to bus_to_virt in the |
636 | dynamic DMA mapping scheme - you have to always store the DMA addresses | 631 | dynamic DMA mapping scheme - you have to always store the DMA addresses |
637 | returned by the pci_alloc_consistent, pci_pool_alloc, and pci_map_single | 632 | returned by the dma_alloc_coherent, dma_pool_alloc, and dma_map_single |
638 | calls (pci_map_sg stores them in the scatterlist itself if the platform | 633 | calls (dma_map_sg stores them in the scatterlist itself if the platform |
639 | supports dynamic DMA mapping in hardware) in your driver structures and/or | 634 | supports dynamic DMA mapping in hardware) in your driver structures and/or |
640 | in the card registers. | 635 | in the card registers. |
641 | 636 | ||
642 | All PCI drivers should be using these interfaces with no exceptions. | 637 | All drivers should be using these interfaces with no exceptions. It |
643 | It is planned to completely remove virt_to_bus() and bus_to_virt() as | 638 | is planned to completely remove virt_to_bus() and bus_to_virt() as |
644 | they are entirely deprecated. Some ports already do not provide these | 639 | they are entirely deprecated. Some ports already do not provide these |
645 | as it is impossible to correctly support them. | 640 | as it is impossible to correctly support them. |
646 | 641 | ||
647 | Optimizing Unmap State Space Consumption | 642 | Optimizing Unmap State Space Consumption |
648 | 643 | ||
649 | On many platforms, pci_unmap_{single,page}() is simply a nop. | 644 | On many platforms, dma_unmap_{single,page}() is simply a nop. |
650 | Therefore, keeping track of the mapping address and length is a waste | 645 | Therefore, keeping track of the mapping address and length is a waste |
651 | of space. Instead of filling your drivers up with ifdefs and the like | 646 | of space. Instead of filling your drivers up with ifdefs and the like |
652 | to "work around" this (which would defeat the whole purpose of a | 647 | to "work around" this (which would defeat the whole purpose of a |
@@ -655,7 +650,7 @@ portable API) the following facilities are provided. | |||
655 | Actually, instead of describing the macros one by one, we'll | 650 | Actually, instead of describing the macros one by one, we'll |
656 | transform some example code. | 651 | transform some example code. |
657 | 652 | ||
658 | 1) Use DECLARE_PCI_UNMAP_{ADDR,LEN} in state saving structures. | 653 | 1) Use DEFINE_DMA_UNMAP_{ADDR,LEN} in state saving structures. |
659 | Example, before: | 654 | Example, before: |
660 | 655 | ||
661 | struct ring_state { | 656 | struct ring_state { |
@@ -668,14 +663,11 @@ transform some example code. | |||
668 | 663 | ||
669 | struct ring_state { | 664 | struct ring_state { |
670 | struct sk_buff *skb; | 665 | struct sk_buff *skb; |
671 | DECLARE_PCI_UNMAP_ADDR(mapping) | 666 | DEFINE_DMA_UNMAP_ADDR(mapping); |
672 | DECLARE_PCI_UNMAP_LEN(len) | 667 | DEFINE_DMA_UNMAP_LEN(len); |
673 | }; | 668 | }; |
674 | 669 | ||
675 | NOTE: DO NOT put a semicolon at the end of the DECLARE_*() | 670 | 2) Use dma_unmap_{addr,len}_set to set these values. |
676 | macro. | ||
677 | |||
678 | 2) Use pci_unmap_{addr,len}_set to set these values. | ||
679 | Example, before: | 671 | Example, before: |
680 | 672 | ||
681 | ringp->mapping = FOO; | 673 | ringp->mapping = FOO; |
@@ -683,21 +675,21 @@ transform some example code. | |||
683 | 675 | ||
684 | after: | 676 | after: |
685 | 677 | ||
686 | pci_unmap_addr_set(ringp, mapping, FOO); | 678 | dma_unmap_addr_set(ringp, mapping, FOO); |
687 | pci_unmap_len_set(ringp, len, BAR); | 679 | dma_unmap_len_set(ringp, len, BAR); |
688 | 680 | ||
689 | 3) Use pci_unmap_{addr,len} to access these values. | 681 | 3) Use dma_unmap_{addr,len} to access these values. |
690 | Example, before: | 682 | Example, before: |
691 | 683 | ||
692 | pci_unmap_single(pdev, ringp->mapping, ringp->len, | 684 | dma_unmap_single(dev, ringp->mapping, ringp->len, |
693 | PCI_DMA_FROMDEVICE); | 685 | DMA_FROM_DEVICE); |
694 | 686 | ||
695 | after: | 687 | after: |
696 | 688 | ||
697 | pci_unmap_single(pdev, | 689 | dma_unmap_single(dev, |
698 | pci_unmap_addr(ringp, mapping), | 690 | dma_unmap_addr(ringp, mapping), |
699 | pci_unmap_len(ringp, len), | 691 | dma_unmap_len(ringp, len), |
700 | PCI_DMA_FROMDEVICE); | 692 | DMA_FROM_DEVICE); |
701 | 693 | ||
702 | It really should be self-explanatory. We treat the ADDR and LEN | 694 | It really should be self-explanatory. We treat the ADDR and LEN |
703 | separately, because it is possible for an implementation to only | 695 | separately, because it is possible for an implementation to only |
@@ -732,15 +724,15 @@ to "Closing". | |||
732 | DMA address space is limited on some architectures and an allocation | 724 | DMA address space is limited on some architectures and an allocation |
733 | failure can be determined by: | 725 | failure can be determined by: |
734 | 726 | ||
735 | - checking if pci_alloc_consistent returns NULL or pci_map_sg returns 0 | 727 | - checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0 |
736 | 728 | ||
737 | - checking the returned dma_addr_t of pci_map_single and pci_map_page | 729 | - checking the returned dma_addr_t of dma_map_single and dma_map_page |
738 | by using pci_dma_mapping_error(): | 730 | by using dma_mapping_error(): |
739 | 731 | ||
740 | dma_addr_t dma_handle; | 732 | dma_addr_t dma_handle; |
741 | 733 | ||
742 | dma_handle = pci_map_single(pdev, addr, size, direction); | 734 | dma_handle = dma_map_single(dev, addr, size, direction); |
743 | if (pci_dma_mapping_error(pdev, dma_handle)) { | 735 | if (dma_mapping_error(dev, dma_handle)) { |
744 | /* | 736 | /* |
745 | * reduce current DMA mapping usage, | 737 | * reduce current DMA mapping usage, |
746 | * delay and try again later or | 738 | * delay and try again later or |
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist index 1053a56be3b1..8916ca48bc95 100644 --- a/Documentation/SubmitChecklist +++ b/Documentation/SubmitChecklist | |||
@@ -9,10 +9,14 @@ Documentation/SubmittingPatches and elsewhere regarding submitting Linux | |||
9 | kernel patches. | 9 | kernel patches. |
10 | 10 | ||
11 | 11 | ||
12 | 1: Builds cleanly with applicable or modified CONFIG options =y, =m, and | 12 | 1: If you use a facility then #include the file that defines/declares |
13 | that facility. Don't depend on other header files pulling in ones | ||
14 | that you use. | ||
15 | |||
16 | 2: Builds cleanly with applicable or modified CONFIG options =y, =m, and | ||
13 | =n. No gcc warnings/errors, no linker warnings/errors. | 17 | =n. No gcc warnings/errors, no linker warnings/errors. |
14 | 18 | ||
15 | 2: Passes allnoconfig, allmodconfig | 19 | 2b: Passes allnoconfig, allmodconfig |
16 | 20 | ||
17 | 3: Builds on multiple CPU architectures by using local cross-compile tools | 21 | 3: Builds on multiple CPU architectures by using local cross-compile tools |
18 | or some other build farm. | 22 | or some other build farm. |
diff --git a/Documentation/cgroups/cgroup_event_listener.c b/Documentation/cgroups/cgroup_event_listener.c new file mode 100644 index 000000000000..8c2bfc4a6358 --- /dev/null +++ b/Documentation/cgroups/cgroup_event_listener.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * cgroup_event_listener.c - Simple listener of cgroup events | ||
3 | * | ||
4 | * Copyright (C) Kirill A. Shutemov <kirill@shutemov.name> | ||
5 | */ | ||
6 | |||
7 | #include <assert.h> | ||
8 | #include <errno.h> | ||
9 | #include <fcntl.h> | ||
10 | #include <libgen.h> | ||
11 | #include <limits.h> | ||
12 | #include <stdio.h> | ||
13 | #include <string.h> | ||
14 | #include <unistd.h> | ||
15 | |||
16 | #include <sys/eventfd.h> | ||
17 | |||
18 | #define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>\n" | ||
19 | |||
20 | int main(int argc, char **argv) | ||
21 | { | ||
22 | int efd = -1; | ||
23 | int cfd = -1; | ||
24 | int event_control = -1; | ||
25 | char event_control_path[PATH_MAX]; | ||
26 | char line[LINE_MAX]; | ||
27 | int ret; | ||
28 | |||
29 | if (argc != 3) { | ||
30 | fputs(USAGE_STR, stderr); | ||
31 | return 1; | ||
32 | } | ||
33 | |||
34 | cfd = open(argv[1], O_RDONLY); | ||
35 | if (cfd == -1) { | ||
36 | fprintf(stderr, "Cannot open %s: %s\n", argv[1], | ||
37 | strerror(errno)); | ||
38 | goto out; | ||
39 | } | ||
40 | |||
41 | ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control", | ||
42 | dirname(argv[1])); | ||
43 | if (ret >= PATH_MAX) { | ||
44 | fputs("Path to cgroup.event_control is too long\n", stderr); | ||
45 | goto out; | ||
46 | } | ||
47 | |||
48 | event_control = open(event_control_path, O_WRONLY); | ||
49 | if (event_control == -1) { | ||
50 | fprintf(stderr, "Cannot open %s: %s\n", event_control_path, | ||
51 | strerror(errno)); | ||
52 | goto out; | ||
53 | } | ||
54 | |||
55 | efd = eventfd(0, 0); | ||
56 | if (efd == -1) { | ||
57 | perror("eventfd() failed"); | ||
58 | goto out; | ||
59 | } | ||
60 | |||
61 | ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]); | ||
62 | if (ret >= LINE_MAX) { | ||
63 | fputs("Arguments string is too long\n", stderr); | ||
64 | goto out; | ||
65 | } | ||
66 | |||
67 | ret = write(event_control, line, strlen(line) + 1); | ||
68 | if (ret == -1) { | ||
69 | perror("Cannot write to cgroup.event_control"); | ||
70 | goto out; | ||
71 | } | ||
72 | |||
73 | while (1) { | ||
74 | uint64_t result; | ||
75 | |||
76 | ret = read(efd, &result, sizeof(result)); | ||
77 | if (ret == -1) { | ||
78 | if (errno == EINTR) | ||
79 | continue; | ||
80 | perror("Cannot read from eventfd"); | ||
81 | break; | ||
82 | } | ||
83 | assert(ret == sizeof(result)); | ||
84 | |||
85 | ret = access(event_control_path, W_OK); | ||
86 | if ((ret == -1) && (errno == ENOENT)) { | ||
87 | puts("The cgroup seems to have removed."); | ||
88 | ret = 0; | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | if (ret == -1) { | ||
93 | perror("cgroup.event_control " | ||
94 | "is not accessable any more"); | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | printf("%s %s: crossed\n", argv[1], argv[2]); | ||
99 | } | ||
100 | |||
101 | out: | ||
102 | if (efd >= 0) | ||
103 | close(efd); | ||
104 | if (event_control >= 0) | ||
105 | close(event_control); | ||
106 | if (cfd >= 0) | ||
107 | close(cfd); | ||
108 | |||
109 | return (ret != 0); | ||
110 | } | ||
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt index 0b33bfe7dde9..fd588ff0e296 100644 --- a/Documentation/cgroups/cgroups.txt +++ b/Documentation/cgroups/cgroups.txt | |||
@@ -22,6 +22,8 @@ CONTENTS: | |||
22 | 2. Usage Examples and Syntax | 22 | 2. Usage Examples and Syntax |
23 | 2.1 Basic Usage | 23 | 2.1 Basic Usage |
24 | 2.2 Attaching processes | 24 | 2.2 Attaching processes |
25 | 2.3 Mounting hierarchies by name | ||
26 | 2.4 Notification API | ||
25 | 3. Kernel API | 27 | 3. Kernel API |
26 | 3.1 Overview | 28 | 3.1 Overview |
27 | 3.2 Synchronization | 29 | 3.2 Synchronization |
@@ -434,6 +436,25 @@ you give a subsystem a name. | |||
434 | The name of the subsystem appears as part of the hierarchy description | 436 | The name of the subsystem appears as part of the hierarchy description |
435 | in /proc/mounts and /proc/<pid>/cgroups. | 437 | in /proc/mounts and /proc/<pid>/cgroups. |
436 | 438 | ||
439 | 2.4 Notification API | ||
440 | -------------------- | ||
441 | |||
442 | There is mechanism which allows to get notifications about changing | ||
443 | status of a cgroup. | ||
444 | |||
445 | To register new notification handler you need: | ||
446 | - create a file descriptor for event notification using eventfd(2); | ||
447 | - open a control file to be monitored (e.g. memory.usage_in_bytes); | ||
448 | - write "<event_fd> <control_fd> <args>" to cgroup.event_control. | ||
449 | Interpretation of args is defined by control file implementation; | ||
450 | |||
451 | eventfd will be woken up by control file implementation or when the | ||
452 | cgroup is removed. | ||
453 | |||
454 | To unregister notification handler just close eventfd. | ||
455 | |||
456 | NOTE: Support of notifications should be implemented for the control | ||
457 | file. See documentation for the subsystem. | ||
437 | 458 | ||
438 | 3. Kernel API | 459 | 3. Kernel API |
439 | ============= | 460 | ============= |
@@ -488,6 +509,11 @@ Each subsystem should: | |||
488 | - add an entry in linux/cgroup_subsys.h | 509 | - add an entry in linux/cgroup_subsys.h |
489 | - define a cgroup_subsys object called <name>_subsys | 510 | - define a cgroup_subsys object called <name>_subsys |
490 | 511 | ||
512 | If a subsystem can be compiled as a module, it should also have in its | ||
513 | module initcall a call to cgroup_load_subsys(), and in its exitcall a | ||
514 | call to cgroup_unload_subsys(). It should also set its_subsys.module = | ||
515 | THIS_MODULE in its .c file. | ||
516 | |||
491 | Each subsystem may export the following methods. The only mandatory | 517 | Each subsystem may export the following methods. The only mandatory |
492 | methods are create/destroy. Any others that are null are presumed to | 518 | methods are create/destroy. Any others that are null are presumed to |
493 | be successful no-ops. | 519 | be successful no-ops. |
@@ -536,10 +562,21 @@ returns an error, this will abort the attach operation. If a NULL | |||
536 | task is passed, then a successful result indicates that *any* | 562 | task is passed, then a successful result indicates that *any* |
537 | unspecified task can be moved into the cgroup. Note that this isn't | 563 | unspecified task can be moved into the cgroup. Note that this isn't |
538 | called on a fork. If this method returns 0 (success) then this should | 564 | called on a fork. If this method returns 0 (success) then this should |
539 | remain valid while the caller holds cgroup_mutex. If threadgroup is | 565 | remain valid while the caller holds cgroup_mutex and it is ensured that either |
566 | attach() or cancel_attach() will be called in future. If threadgroup is | ||
540 | true, then a successful result indicates that all threads in the given | 567 | true, then a successful result indicates that all threads in the given |
541 | thread's threadgroup can be moved together. | 568 | thread's threadgroup can be moved together. |
542 | 569 | ||
570 | void cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, | ||
571 | struct task_struct *task, bool threadgroup) | ||
572 | (cgroup_mutex held by caller) | ||
573 | |||
574 | Called when a task attach operation has failed after can_attach() has succeeded. | ||
575 | A subsystem whose can_attach() has some side-effects should provide this | ||
576 | function, so that the subsytem can implement a rollback. If not, not necessary. | ||
577 | This will be called only about subsystems whose can_attach() operation have | ||
578 | succeeded. | ||
579 | |||
543 | void attach(struct cgroup_subsys *ss, struct cgroup *cgrp, | 580 | void attach(struct cgroup_subsys *ss, struct cgroup *cgrp, |
544 | struct cgroup *old_cgrp, struct task_struct *task, | 581 | struct cgroup *old_cgrp, struct task_struct *task, |
545 | bool threadgroup) | 582 | bool threadgroup) |
diff --git a/Documentation/cgroups/memcg_test.txt b/Documentation/cgroups/memcg_test.txt index 72db89ed0609..f7f68b2ac199 100644 --- a/Documentation/cgroups/memcg_test.txt +++ b/Documentation/cgroups/memcg_test.txt | |||
@@ -1,6 +1,6 @@ | |||
1 | Memory Resource Controller(Memcg) Implementation Memo. | 1 | Memory Resource Controller(Memcg) Implementation Memo. |
2 | Last Updated: 2009/1/20 | 2 | Last Updated: 2010/2 |
3 | Base Kernel Version: based on 2.6.29-rc2. | 3 | Base Kernel Version: based on 2.6.33-rc7-mm(candidate for 34). |
4 | 4 | ||
5 | Because VM is getting complex (one of reasons is memcg...), memcg's behavior | 5 | Because VM is getting complex (one of reasons is memcg...), memcg's behavior |
6 | is complex. This is a document for memcg's internal behavior. | 6 | is complex. This is a document for memcg's internal behavior. |
@@ -337,7 +337,7 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y. | |||
337 | race and lock dependency with other cgroup subsystems. | 337 | race and lock dependency with other cgroup subsystems. |
338 | 338 | ||
339 | example) | 339 | example) |
340 | # mount -t cgroup none /cgroup -t cpuset,memory,cpu,devices | 340 | # mount -t cgroup none /cgroup -o cpuset,memory,cpu,devices |
341 | 341 | ||
342 | and do task move, mkdir, rmdir etc...under this. | 342 | and do task move, mkdir, rmdir etc...under this. |
343 | 343 | ||
@@ -348,7 +348,7 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y. | |||
348 | 348 | ||
349 | For example, test like following is good. | 349 | For example, test like following is good. |
350 | (Shell-A) | 350 | (Shell-A) |
351 | # mount -t cgroup none /cgroup -t memory | 351 | # mount -t cgroup none /cgroup -o memory |
352 | # mkdir /cgroup/test | 352 | # mkdir /cgroup/test |
353 | # echo 40M > /cgroup/test/memory.limit_in_bytes | 353 | # echo 40M > /cgroup/test/memory.limit_in_bytes |
354 | # echo 0 > /cgroup/test/tasks | 354 | # echo 0 > /cgroup/test/tasks |
@@ -378,3 +378,42 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y. | |||
378 | #echo 50M > memory.limit_in_bytes | 378 | #echo 50M > memory.limit_in_bytes |
379 | #echo 50M > memory.memsw.limit_in_bytes | 379 | #echo 50M > memory.memsw.limit_in_bytes |
380 | run 51M of malloc | 380 | run 51M of malloc |
381 | |||
382 | 9.9 Move charges at task migration | ||
383 | Charges associated with a task can be moved along with task migration. | ||
384 | |||
385 | (Shell-A) | ||
386 | #mkdir /cgroup/A | ||
387 | #echo $$ >/cgroup/A/tasks | ||
388 | run some programs which uses some amount of memory in /cgroup/A. | ||
389 | |||
390 | (Shell-B) | ||
391 | #mkdir /cgroup/B | ||
392 | #echo 1 >/cgroup/B/memory.move_charge_at_immigrate | ||
393 | #echo "pid of the program running in group A" >/cgroup/B/tasks | ||
394 | |||
395 | You can see charges have been moved by reading *.usage_in_bytes or | ||
396 | memory.stat of both A and B. | ||
397 | See 8.2 of Documentation/cgroups/memory.txt to see what value should be | ||
398 | written to move_charge_at_immigrate. | ||
399 | |||
400 | 9.10 Memory thresholds | ||
401 | Memory controler implements memory thresholds using cgroups notification | ||
402 | API. You can use Documentation/cgroups/cgroup_event_listener.c to test | ||
403 | it. | ||
404 | |||
405 | (Shell-A) Create cgroup and run event listener | ||
406 | # mkdir /cgroup/A | ||
407 | # ./cgroup_event_listener /cgroup/A/memory.usage_in_bytes 5M | ||
408 | |||
409 | (Shell-B) Add task to cgroup and try to allocate and free memory | ||
410 | # echo $$ >/cgroup/A/tasks | ||
411 | # a="$(dd if=/dev/zero bs=1M count=10)" | ||
412 | # a= | ||
413 | |||
414 | You will see message from cgroup_event_listener every time you cross | ||
415 | the thresholds. | ||
416 | |||
417 | Use /cgroup/A/memory.memsw.usage_in_bytes to test memsw thresholds. | ||
418 | |||
419 | It's good idea to test root cgroup as well. | ||
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index b871f2552b45..f8bc802d70b9 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt | |||
@@ -182,6 +182,8 @@ list. | |||
182 | NOTE: Reclaim does not work for the root cgroup, since we cannot set any | 182 | NOTE: Reclaim does not work for the root cgroup, since we cannot set any |
183 | limits on the root cgroup. | 183 | limits on the root cgroup. |
184 | 184 | ||
185 | Note2: When panic_on_oom is set to "2", the whole system will panic. | ||
186 | |||
185 | 2. Locking | 187 | 2. Locking |
186 | 188 | ||
187 | The memory controller uses the following hierarchy | 189 | The memory controller uses the following hierarchy |
@@ -262,10 +264,12 @@ some of the pages cached in the cgroup (page cache pages). | |||
262 | 4.2 Task migration | 264 | 4.2 Task migration |
263 | 265 | ||
264 | When a task migrates from one cgroup to another, it's charge is not | 266 | When a task migrates from one cgroup to another, it's charge is not |
265 | carried forward. The pages allocated from the original cgroup still | 267 | carried forward by default. The pages allocated from the original cgroup still |
266 | remain charged to it, the charge is dropped when the page is freed or | 268 | remain charged to it, the charge is dropped when the page is freed or |
267 | reclaimed. | 269 | reclaimed. |
268 | 270 | ||
271 | Note: You can move charges of a task along with task migration. See 8. | ||
272 | |||
269 | 4.3 Removing a cgroup | 273 | 4.3 Removing a cgroup |
270 | 274 | ||
271 | A cgroup can be removed by rmdir, but as discussed in sections 4.1 and 4.2, a | 275 | A cgroup can be removed by rmdir, but as discussed in sections 4.1 and 4.2, a |
@@ -377,7 +381,8 @@ The feature can be disabled by | |||
377 | NOTE1: Enabling/disabling will fail if the cgroup already has other | 381 | NOTE1: Enabling/disabling will fail if the cgroup already has other |
378 | cgroups created below it. | 382 | cgroups created below it. |
379 | 383 | ||
380 | NOTE2: This feature can be enabled/disabled per subtree. | 384 | NOTE2: When panic_on_oom is set to "2", the whole system will panic in |
385 | case of an oom event in any cgroup. | ||
381 | 386 | ||
382 | 7. Soft limits | 387 | 7. Soft limits |
383 | 388 | ||
@@ -414,7 +419,76 @@ NOTE1: Soft limits take effect over a long period of time, since they involve | |||
414 | NOTE2: It is recommended to set the soft limit always below the hard limit, | 419 | NOTE2: It is recommended to set the soft limit always below the hard limit, |
415 | otherwise the hard limit will take precedence. | 420 | otherwise the hard limit will take precedence. |
416 | 421 | ||
417 | 8. TODO | 422 | 8. Move charges at task migration |
423 | |||
424 | Users can move charges associated with a task along with task migration, that | ||
425 | is, uncharge task's pages from the old cgroup and charge them to the new cgroup. | ||
426 | This feature is not supported in !CONFIG_MMU environments because of lack of | ||
427 | page tables. | ||
428 | |||
429 | 8.1 Interface | ||
430 | |||
431 | This feature is disabled by default. It can be enabled(and disabled again) by | ||
432 | writing to memory.move_charge_at_immigrate of the destination cgroup. | ||
433 | |||
434 | If you want to enable it: | ||
435 | |||
436 | # echo (some positive value) > memory.move_charge_at_immigrate | ||
437 | |||
438 | Note: Each bits of move_charge_at_immigrate has its own meaning about what type | ||
439 | of charges should be moved. See 8.2 for details. | ||
440 | Note: Charges are moved only when you move mm->owner, IOW, a leader of a thread | ||
441 | group. | ||
442 | Note: If we cannot find enough space for the task in the destination cgroup, we | ||
443 | try to make space by reclaiming memory. Task migration may fail if we | ||
444 | cannot make enough space. | ||
445 | Note: It can take several seconds if you move charges in giga bytes order. | ||
446 | |||
447 | And if you want disable it again: | ||
448 | |||
449 | # echo 0 > memory.move_charge_at_immigrate | ||
450 | |||
451 | 8.2 Type of charges which can be move | ||
452 | |||
453 | Each bits of move_charge_at_immigrate has its own meaning about what type of | ||
454 | charges should be moved. | ||
455 | |||
456 | bit | what type of charges would be moved ? | ||
457 | -----+------------------------------------------------------------------------ | ||
458 | 0 | A charge of an anonymous page(or swap of it) used by the target task. | ||
459 | | Those pages and swaps must be used only by the target task. You must | ||
460 | | enable Swap Extension(see 2.4) to enable move of swap charges. | ||
461 | |||
462 | Note: Those pages and swaps must be charged to the old cgroup. | ||
463 | Note: More type of pages(e.g. file cache, shmem,) will be supported by other | ||
464 | bits in future. | ||
465 | |||
466 | 8.3 TODO | ||
467 | |||
468 | - Add support for other types of pages(e.g. file cache, shmem, etc.). | ||
469 | - Implement madvise(2) to let users decide the vma to be moved or not to be | ||
470 | moved. | ||
471 | - All of moving charge operations are done under cgroup_mutex. It's not good | ||
472 | behavior to hold the mutex too long, so we may need some trick. | ||
473 | |||
474 | 9. Memory thresholds | ||
475 | |||
476 | Memory controler implements memory thresholds using cgroups notification | ||
477 | API (see cgroups.txt). It allows to register multiple memory and memsw | ||
478 | thresholds and gets notifications when it crosses. | ||
479 | |||
480 | To register a threshold application need: | ||
481 | - create an eventfd using eventfd(2); | ||
482 | - open memory.usage_in_bytes or memory.memsw.usage_in_bytes; | ||
483 | - write string like "<event_fd> <memory.usage_in_bytes> <threshold>" to | ||
484 | cgroup.event_control. | ||
485 | |||
486 | Application will be notified through eventfd when memory usage crosses | ||
487 | threshold in any direction. | ||
488 | |||
489 | It's applicable for root and non-root cgroup. | ||
490 | |||
491 | 10. TODO | ||
418 | 492 | ||
419 | 1. Add support for accounting huge pages (as a separate controller) | 493 | 1. Add support for accounting huge pages (as a separate controller) |
420 | 2. Make per-cgroup scanner reclaim not-shared pages first | 494 | 2. Make per-cgroup scanner reclaim not-shared pages first |
diff --git a/Documentation/email-clients.txt b/Documentation/email-clients.txt index a618efab7b15..945ff3fda433 100644 --- a/Documentation/email-clients.txt +++ b/Documentation/email-clients.txt | |||
@@ -216,26 +216,14 @@ Works. Use "Insert file..." or external editor. | |||
216 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 216 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
217 | Gmail (Web GUI) | 217 | Gmail (Web GUI) |
218 | 218 | ||
219 | If you just have to use Gmail to send patches, it CAN be made to work. It | 219 | Does not work for sending patches. |
220 | requires a bit of external help, though. | 220 | |
221 | 221 | Gmail web client converts tabs to spaces automatically. | |
222 | The first problem is that Gmail converts tabs to spaces. This will | 222 | |
223 | totally break your patches. To prevent this, you have to use a different | 223 | At the same time it wraps lines every 78 chars with CRLF style line breaks |
224 | editor. There is a firefox extension called "ViewSourceWith" | 224 | although tab2space problem can be solved with external editor. |
225 | (https://addons.mozilla.org/en-US/firefox/addon/394) which allows you to | 225 | |
226 | edit any text box in the editor of your choice. Configure it to launch | 226 | Another problem is that Gmail will base64-encode any message that has a |
227 | your favorite editor. When you want to send a patch, use this technique. | 227 | non-ASCII character. That includes things like European names. |
228 | Once you have crafted your messsage + patch, save and exit the editor, | ||
229 | which should reload the Gmail edit box. GMAIL WILL PRESERVE THE TABS. | ||
230 | Hoorah. Apparently you can cut-n-paste literal tabs, but Gmail will | ||
231 | convert those to spaces upon sending! | ||
232 | |||
233 | The second problem is that Gmail converts tabs to spaces on replies. If | ||
234 | you reply to a patch, don't expect to be able to apply it as a patch. | ||
235 | |||
236 | The last problem is that Gmail will base64-encode any message that has a | ||
237 | non-ASCII character. That includes things like European names. Be aware. | ||
238 | |||
239 | Gmail is not convenient for lkml patches, but CAN be made to work. | ||
240 | 228 | ||
241 | ### | 229 | ### |
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index 5139b8c9d5af..3bae418c6ad3 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX | |||
@@ -32,6 +32,8 @@ dlmfs.txt | |||
32 | - info on the userspace interface to the OCFS2 DLM. | 32 | - info on the userspace interface to the OCFS2 DLM. |
33 | dnotify.txt | 33 | dnotify.txt |
34 | - info about directory notification in Linux. | 34 | - info about directory notification in Linux. |
35 | dnotify_test.c | ||
36 | - example program for dnotify | ||
35 | ecryptfs.txt | 37 | ecryptfs.txt |
36 | - docs on eCryptfs: stacked cryptographic filesystem for Linux. | 38 | - docs on eCryptfs: stacked cryptographic filesystem for Linux. |
37 | exofs.txt | 39 | exofs.txt |
diff --git a/Documentation/filesystems/Makefile b/Documentation/filesystems/Makefile new file mode 100644 index 000000000000..a5dd114da14f --- /dev/null +++ b/Documentation/filesystems/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # kbuild trick to avoid linker error. Can be omitted if a module is built. | ||
2 | obj- := dummy.o | ||
3 | |||
4 | # List of programs to build | ||
5 | hostprogs-y := dnotify_test | ||
6 | |||
7 | # Tell kbuild to always build the programs | ||
8 | always := $(hostprogs-y) | ||
diff --git a/Documentation/filesystems/dnotify.txt b/Documentation/filesystems/dnotify.txt index 9f5d338ddbb8..6baf88f46859 100644 --- a/Documentation/filesystems/dnotify.txt +++ b/Documentation/filesystems/dnotify.txt | |||
@@ -62,38 +62,9 @@ disabled, fcntl(fd, F_NOTIFY, ...) will return -EINVAL. | |||
62 | 62 | ||
63 | Example | 63 | Example |
64 | ------- | 64 | ------- |
65 | See Documentation/filesystems/dnotify_test.c for an example. | ||
65 | 66 | ||
66 | #define _GNU_SOURCE /* needed to get the defines */ | 67 | NOTE |
67 | #include <fcntl.h> /* in glibc 2.2 this has the needed | 68 | ---- |
68 | values defined */ | 69 | Beginning with Linux 2.6.13, dnotify has been replaced by inotify. |
69 | #include <signal.h> | 70 | See Documentation/filesystems/inotify.txt for more information on it. |
70 | #include <stdio.h> | ||
71 | #include <unistd.h> | ||
72 | |||
73 | static volatile int event_fd; | ||
74 | |||
75 | static void handler(int sig, siginfo_t *si, void *data) | ||
76 | { | ||
77 | event_fd = si->si_fd; | ||
78 | } | ||
79 | |||
80 | int main(void) | ||
81 | { | ||
82 | struct sigaction act; | ||
83 | int fd; | ||
84 | |||
85 | act.sa_sigaction = handler; | ||
86 | sigemptyset(&act.sa_mask); | ||
87 | act.sa_flags = SA_SIGINFO; | ||
88 | sigaction(SIGRTMIN + 1, &act, NULL); | ||
89 | |||
90 | fd = open(".", O_RDONLY); | ||
91 | fcntl(fd, F_SETSIG, SIGRTMIN + 1); | ||
92 | fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT); | ||
93 | /* we will now be notified if any of the files | ||
94 | in "." is modified or new files are created */ | ||
95 | while (1) { | ||
96 | pause(); | ||
97 | printf("Got event on fd=%d\n", event_fd); | ||
98 | } | ||
99 | } | ||
diff --git a/Documentation/filesystems/dnotify_test.c b/Documentation/filesystems/dnotify_test.c new file mode 100644 index 000000000000..8b37b4a1e18d --- /dev/null +++ b/Documentation/filesystems/dnotify_test.c | |||
@@ -0,0 +1,34 @@ | |||
1 | #define _GNU_SOURCE /* needed to get the defines */ | ||
2 | #include <fcntl.h> /* in glibc 2.2 this has the needed | ||
3 | values defined */ | ||
4 | #include <signal.h> | ||
5 | #include <stdio.h> | ||
6 | #include <unistd.h> | ||
7 | |||
8 | static volatile int event_fd; | ||
9 | |||
10 | static void handler(int sig, siginfo_t *si, void *data) | ||
11 | { | ||
12 | event_fd = si->si_fd; | ||
13 | } | ||
14 | |||
15 | int main(void) | ||
16 | { | ||
17 | struct sigaction act; | ||
18 | int fd; | ||
19 | |||
20 | act.sa_sigaction = handler; | ||
21 | sigemptyset(&act.sa_mask); | ||
22 | act.sa_flags = SA_SIGINFO; | ||
23 | sigaction(SIGRTMIN + 1, &act, NULL); | ||
24 | |||
25 | fd = open(".", O_RDONLY); | ||
26 | fcntl(fd, F_SETSIG, SIGRTMIN + 1); | ||
27 | fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT); | ||
28 | /* we will now be notified if any of the files | ||
29 | in "." is modified or new files are created */ | ||
30 | while (1) { | ||
31 | pause(); | ||
32 | printf("Got event on fd=%d\n", event_fd); | ||
33 | } | ||
34 | } | ||
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt index c79ab996dada..bdb13817e1e9 100644 --- a/Documentation/kobject.txt +++ b/Documentation/kobject.txt | |||
@@ -266,7 +266,7 @@ kobj_type: | |||
266 | 266 | ||
267 | struct kobj_type { | 267 | struct kobj_type { |
268 | void (*release)(struct kobject *); | 268 | void (*release)(struct kobject *); |
269 | struct sysfs_ops *sysfs_ops; | 269 | const struct sysfs_ops *sysfs_ops; |
270 | struct attribute **default_attrs; | 270 | struct attribute **default_attrs; |
271 | }; | 271 | }; |
272 | 272 | ||
diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX index ee5692b26dd4..f1fc13d05f3e 100644 --- a/Documentation/laptops/00-INDEX +++ b/Documentation/laptops/00-INDEX | |||
@@ -2,6 +2,8 @@ | |||
2 | - This file | 2 | - This file |
3 | acer-wmi.txt | 3 | acer-wmi.txt |
4 | - information on the Acer Laptop WMI Extras driver. | 4 | - information on the Acer Laptop WMI Extras driver. |
5 | dslm.c | ||
6 | - Simple Disk Sleep Monitor program | ||
5 | laptop-mode.txt | 7 | laptop-mode.txt |
6 | - how to conserve battery power using laptop-mode. | 8 | - how to conserve battery power using laptop-mode. |
7 | sony-laptop.txt | 9 | sony-laptop.txt |
diff --git a/Documentation/laptops/Makefile b/Documentation/laptops/Makefile new file mode 100644 index 000000000000..5cb144af3c09 --- /dev/null +++ b/Documentation/laptops/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # kbuild trick to avoid linker error. Can be omitted if a module is built. | ||
2 | obj- := dummy.o | ||
3 | |||
4 | # List of programs to build | ||
5 | hostprogs-y := dslm | ||
6 | |||
7 | # Tell kbuild to always build the programs | ||
8 | always := $(hostprogs-y) | ||
diff --git a/Documentation/laptops/dslm.c b/Documentation/laptops/dslm.c new file mode 100644 index 000000000000..72ff290c5fc6 --- /dev/null +++ b/Documentation/laptops/dslm.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * dslm.c | ||
3 | * Simple Disk Sleep Monitor | ||
4 | * by Bartek Kania | ||
5 | * Licenced under the GPL | ||
6 | */ | ||
7 | #include <unistd.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <stdio.h> | ||
10 | #include <fcntl.h> | ||
11 | #include <errno.h> | ||
12 | #include <time.h> | ||
13 | #include <string.h> | ||
14 | #include <signal.h> | ||
15 | #include <sys/ioctl.h> | ||
16 | #include <linux/hdreg.h> | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | #define D(x) x | ||
20 | #else | ||
21 | #define D(x) | ||
22 | #endif | ||
23 | |||
24 | int endit = 0; | ||
25 | |||
26 | /* Check if the disk is in powersave-mode | ||
27 | * Most of the code is stolen from hdparm. | ||
28 | * 1 = active, 0 = standby/sleep, -1 = unknown */ | ||
29 | static int check_powermode(int fd) | ||
30 | { | ||
31 | unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0}; | ||
32 | int state; | ||
33 | |||
34 | if (ioctl(fd, HDIO_DRIVE_CMD, &args) | ||
35 | && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */ | ||
36 | && ioctl(fd, HDIO_DRIVE_CMD, &args)) { | ||
37 | if (errno != EIO || args[0] != 0 || args[1] != 0) { | ||
38 | state = -1; /* "unknown"; */ | ||
39 | } else | ||
40 | state = 0; /* "sleeping"; */ | ||
41 | } else { | ||
42 | state = (args[2] == 255) ? 1 : 0; | ||
43 | } | ||
44 | D(printf(" drive state is: %d\n", state)); | ||
45 | |||
46 | return state; | ||
47 | } | ||
48 | |||
49 | static char *state_name(int i) | ||
50 | { | ||
51 | if (i == -1) return "unknown"; | ||
52 | if (i == 0) return "sleeping"; | ||
53 | if (i == 1) return "active"; | ||
54 | |||
55 | return "internal error"; | ||
56 | } | ||
57 | |||
58 | static char *myctime(time_t time) | ||
59 | { | ||
60 | char *ts = ctime(&time); | ||
61 | ts[strlen(ts) - 1] = 0; | ||
62 | |||
63 | return ts; | ||
64 | } | ||
65 | |||
66 | static void measure(int fd) | ||
67 | { | ||
68 | time_t start_time; | ||
69 | int last_state; | ||
70 | time_t last_time; | ||
71 | int curr_state; | ||
72 | time_t curr_time = 0; | ||
73 | time_t time_diff; | ||
74 | time_t active_time = 0; | ||
75 | time_t sleep_time = 0; | ||
76 | time_t unknown_time = 0; | ||
77 | time_t total_time = 0; | ||
78 | int changes = 0; | ||
79 | float tmp; | ||
80 | |||
81 | printf("Starting measurements\n"); | ||
82 | |||
83 | last_state = check_powermode(fd); | ||
84 | start_time = last_time = time(0); | ||
85 | printf(" System is in state %s\n\n", state_name(last_state)); | ||
86 | |||
87 | while(!endit) { | ||
88 | sleep(1); | ||
89 | curr_state = check_powermode(fd); | ||
90 | |||
91 | if (curr_state != last_state || endit) { | ||
92 | changes++; | ||
93 | curr_time = time(0); | ||
94 | time_diff = curr_time - last_time; | ||
95 | |||
96 | if (last_state == 1) active_time += time_diff; | ||
97 | else if (last_state == 0) sleep_time += time_diff; | ||
98 | else unknown_time += time_diff; | ||
99 | |||
100 | last_state = curr_state; | ||
101 | last_time = curr_time; | ||
102 | |||
103 | printf("%s: State-change to %s\n", myctime(curr_time), | ||
104 | state_name(curr_state)); | ||
105 | } | ||
106 | } | ||
107 | changes--; /* Compensate for SIGINT */ | ||
108 | |||
109 | total_time = time(0) - start_time; | ||
110 | printf("\nTotal running time: %lus\n", curr_time - start_time); | ||
111 | printf(" State changed %d times\n", changes); | ||
112 | |||
113 | tmp = (float)sleep_time / (float)total_time * 100; | ||
114 | printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp); | ||
115 | tmp = (float)active_time / (float)total_time * 100; | ||
116 | printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp); | ||
117 | tmp = (float)unknown_time / (float)total_time * 100; | ||
118 | printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp); | ||
119 | } | ||
120 | |||
121 | static void ender(int s) | ||
122 | { | ||
123 | endit = 1; | ||
124 | } | ||
125 | |||
126 | static void usage(void) | ||
127 | { | ||
128 | puts("usage: dslm [-w <time>] <disk>"); | ||
129 | exit(0); | ||
130 | } | ||
131 | |||
132 | int main(int argc, char **argv) | ||
133 | { | ||
134 | int fd; | ||
135 | char *disk = 0; | ||
136 | int settle_time = 60; | ||
137 | |||
138 | /* Parse the simple command-line */ | ||
139 | if (argc == 2) | ||
140 | disk = argv[1]; | ||
141 | else if (argc == 4) { | ||
142 | settle_time = atoi(argv[2]); | ||
143 | disk = argv[3]; | ||
144 | } else | ||
145 | usage(); | ||
146 | |||
147 | if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) { | ||
148 | printf("Can't open %s, because: %s\n", disk, strerror(errno)); | ||
149 | exit(-1); | ||
150 | } | ||
151 | |||
152 | if (settle_time) { | ||
153 | printf("Waiting %d seconds for the system to settle down to " | ||
154 | "'normal'\n", settle_time); | ||
155 | sleep(settle_time); | ||
156 | } else | ||
157 | puts("Not waiting for system to settle down"); | ||
158 | |||
159 | signal(SIGINT, ender); | ||
160 | |||
161 | measure(fd); | ||
162 | |||
163 | close(fd); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
diff --git a/Documentation/laptops/laptop-mode.txt b/Documentation/laptops/laptop-mode.txt index eeedee11c8c2..2c3c35093023 100644 --- a/Documentation/laptops/laptop-mode.txt +++ b/Documentation/laptops/laptop-mode.txt | |||
@@ -779,172 +779,4 @@ Monitoring tool | |||
779 | --------------- | 779 | --------------- |
780 | 780 | ||
781 | Bartek Kania submitted this, it can be used to measure how much time your disk | 781 | Bartek Kania submitted this, it can be used to measure how much time your disk |
782 | spends spun up/down. | 782 | spends spun up/down. See Documentation/laptops/dslm.c |
783 | |||
784 | ---------------------------dslm.c BEGIN----------------------------------------- | ||
785 | /* | ||
786 | * Simple Disk Sleep Monitor | ||
787 | * by Bartek Kania | ||
788 | * Licenced under the GPL | ||
789 | */ | ||
790 | #include <unistd.h> | ||
791 | #include <stdlib.h> | ||
792 | #include <stdio.h> | ||
793 | #include <fcntl.h> | ||
794 | #include <errno.h> | ||
795 | #include <time.h> | ||
796 | #include <string.h> | ||
797 | #include <signal.h> | ||
798 | #include <sys/ioctl.h> | ||
799 | #include <linux/hdreg.h> | ||
800 | |||
801 | #ifdef DEBUG | ||
802 | #define D(x) x | ||
803 | #else | ||
804 | #define D(x) | ||
805 | #endif | ||
806 | |||
807 | int endit = 0; | ||
808 | |||
809 | /* Check if the disk is in powersave-mode | ||
810 | * Most of the code is stolen from hdparm. | ||
811 | * 1 = active, 0 = standby/sleep, -1 = unknown */ | ||
812 | int check_powermode(int fd) | ||
813 | { | ||
814 | unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0}; | ||
815 | int state; | ||
816 | |||
817 | if (ioctl(fd, HDIO_DRIVE_CMD, &args) | ||
818 | && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */ | ||
819 | && ioctl(fd, HDIO_DRIVE_CMD, &args)) { | ||
820 | if (errno != EIO || args[0] != 0 || args[1] != 0) { | ||
821 | state = -1; /* "unknown"; */ | ||
822 | } else | ||
823 | state = 0; /* "sleeping"; */ | ||
824 | } else { | ||
825 | state = (args[2] == 255) ? 1 : 0; | ||
826 | } | ||
827 | D(printf(" drive state is: %d\n", state)); | ||
828 | |||
829 | return state; | ||
830 | } | ||
831 | |||
832 | char *state_name(int i) | ||
833 | { | ||
834 | if (i == -1) return "unknown"; | ||
835 | if (i == 0) return "sleeping"; | ||
836 | if (i == 1) return "active"; | ||
837 | |||
838 | return "internal error"; | ||
839 | } | ||
840 | |||
841 | char *myctime(time_t time) | ||
842 | { | ||
843 | char *ts = ctime(&time); | ||
844 | ts[strlen(ts) - 1] = 0; | ||
845 | |||
846 | return ts; | ||
847 | } | ||
848 | |||
849 | void measure(int fd) | ||
850 | { | ||
851 | time_t start_time; | ||
852 | int last_state; | ||
853 | time_t last_time; | ||
854 | int curr_state; | ||
855 | time_t curr_time = 0; | ||
856 | time_t time_diff; | ||
857 | time_t active_time = 0; | ||
858 | time_t sleep_time = 0; | ||
859 | time_t unknown_time = 0; | ||
860 | time_t total_time = 0; | ||
861 | int changes = 0; | ||
862 | float tmp; | ||
863 | |||
864 | printf("Starting measurements\n"); | ||
865 | |||
866 | last_state = check_powermode(fd); | ||
867 | start_time = last_time = time(0); | ||
868 | printf(" System is in state %s\n\n", state_name(last_state)); | ||
869 | |||
870 | while(!endit) { | ||
871 | sleep(1); | ||
872 | curr_state = check_powermode(fd); | ||
873 | |||
874 | if (curr_state != last_state || endit) { | ||
875 | changes++; | ||
876 | curr_time = time(0); | ||
877 | time_diff = curr_time - last_time; | ||
878 | |||
879 | if (last_state == 1) active_time += time_diff; | ||
880 | else if (last_state == 0) sleep_time += time_diff; | ||
881 | else unknown_time += time_diff; | ||
882 | |||
883 | last_state = curr_state; | ||
884 | last_time = curr_time; | ||
885 | |||
886 | printf("%s: State-change to %s\n", myctime(curr_time), | ||
887 | state_name(curr_state)); | ||
888 | } | ||
889 | } | ||
890 | changes--; /* Compensate for SIGINT */ | ||
891 | |||
892 | total_time = time(0) - start_time; | ||
893 | printf("\nTotal running time: %lus\n", curr_time - start_time); | ||
894 | printf(" State changed %d times\n", changes); | ||
895 | |||
896 | tmp = (float)sleep_time / (float)total_time * 100; | ||
897 | printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp); | ||
898 | tmp = (float)active_time / (float)total_time * 100; | ||
899 | printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp); | ||
900 | tmp = (float)unknown_time / (float)total_time * 100; | ||
901 | printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp); | ||
902 | } | ||
903 | |||
904 | void ender(int s) | ||
905 | { | ||
906 | endit = 1; | ||
907 | } | ||
908 | |||
909 | void usage() | ||
910 | { | ||
911 | puts("usage: dslm [-w <time>] <disk>"); | ||
912 | exit(0); | ||
913 | } | ||
914 | |||
915 | int main(int argc, char **argv) | ||
916 | { | ||
917 | int fd; | ||
918 | char *disk = 0; | ||
919 | int settle_time = 60; | ||
920 | |||
921 | /* Parse the simple command-line */ | ||
922 | if (argc == 2) | ||
923 | disk = argv[1]; | ||
924 | else if (argc == 4) { | ||
925 | settle_time = atoi(argv[2]); | ||
926 | disk = argv[3]; | ||
927 | } else | ||
928 | usage(); | ||
929 | |||
930 | if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) { | ||
931 | printf("Can't open %s, because: %s\n", disk, strerror(errno)); | ||
932 | exit(-1); | ||
933 | } | ||
934 | |||
935 | if (settle_time) { | ||
936 | printf("Waiting %d seconds for the system to settle down to " | ||
937 | "'normal'\n", settle_time); | ||
938 | sleep(settle_time); | ||
939 | } else | ||
940 | puts("Not waiting for system to settle down"); | ||
941 | |||
942 | signal(SIGINT, ender); | ||
943 | |||
944 | measure(fd); | ||
945 | |||
946 | close(fd); | ||
947 | |||
948 | return 0; | ||
949 | } | ||
950 | ---------------------------dslm.c END------------------------------------------- | ||
diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt index 5e5349a4fcd2..7c900507279f 100644 --- a/Documentation/serial/tty.txt +++ b/Documentation/serial/tty.txt | |||
@@ -105,6 +105,10 @@ write_wakeup() - May be called at any point between open and close. | |||
105 | is permitted to call the driver write method from | 105 | is permitted to call the driver write method from |
106 | this function. In such a situation defer it. | 106 | this function. In such a situation defer it. |
107 | 107 | ||
108 | dcd_change() - Report to the tty line the current DCD pin status | ||
109 | changes and the relative timestamp. The timestamp | ||
110 | can be NULL. | ||
111 | |||
108 | 112 | ||
109 | Driver Access | 113 | Driver Access |
110 | 114 | ||
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 33df82e3a398..bfcbbf88c44d 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
@@ -1812,7 +1812,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
1812 | Module snd-ua101 | 1812 | Module snd-ua101 |
1813 | ---------------- | 1813 | ---------------- |
1814 | 1814 | ||
1815 | Module for the Edirol UA-101 audio/MIDI interface. | 1815 | Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces. |
1816 | 1816 | ||
1817 | This module supports multiple devices, autoprobe and hotplugging. | 1817 | This module supports multiple devices, autoprobe and hotplugging. |
1818 | 1818 | ||
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index fc5790d36cd9..6c7d18c53f84 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt | |||
@@ -573,11 +573,14 @@ Because other nodes' memory may be free. This means system total status | |||
573 | may be not fatal yet. | 573 | may be not fatal yet. |
574 | 574 | ||
575 | If this is set to 2, the kernel panics compulsorily even on the | 575 | If this is set to 2, the kernel panics compulsorily even on the |
576 | above-mentioned. | 576 | above-mentioned. Even oom happens under memory cgroup, the whole |
577 | system panics. | ||
577 | 578 | ||
578 | The default value is 0. | 579 | The default value is 0. |
579 | 1 and 2 are for failover of clustering. Please select either | 580 | 1 and 2 are for failover of clustering. Please select either |
580 | according to your policy of failover. | 581 | according to your policy of failover. |
582 | panic_on_oom=2+kdump gives you very strong tool to investigate | ||
583 | why oom happens. You can get snapshot. | ||
581 | 584 | ||
582 | ============================================================= | 585 | ============================================================= |
583 | 586 | ||
diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX index 397dc35e1323..a9248da5cdbc 100644 --- a/Documentation/timers/00-INDEX +++ b/Documentation/timers/00-INDEX | |||
@@ -4,6 +4,8 @@ highres.txt | |||
4 | - High resolution timers and dynamic ticks design notes | 4 | - High resolution timers and dynamic ticks design notes |
5 | hpet.txt | 5 | hpet.txt |
6 | - High Precision Event Timer Driver for Linux | 6 | - High Precision Event Timer Driver for Linux |
7 | hpet_example.c | ||
8 | - sample hpet timer test program | ||
7 | hrtimers.txt | 9 | hrtimers.txt |
8 | - subsystem for high-resolution kernel timers | 10 | - subsystem for high-resolution kernel timers |
9 | timer_stats.txt | 11 | timer_stats.txt |
diff --git a/Documentation/timers/Makefile b/Documentation/timers/Makefile new file mode 100644 index 000000000000..c85625f4ab25 --- /dev/null +++ b/Documentation/timers/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # kbuild trick to avoid linker error. Can be omitted if a module is built. | ||
2 | obj- := dummy.o | ||
3 | |||
4 | # List of programs to build | ||
5 | hostprogs-y := hpet_example | ||
6 | |||
7 | # Tell kbuild to always build the programs | ||
8 | always := $(hostprogs-y) | ||
diff --git a/Documentation/timers/hpet.txt b/Documentation/timers/hpet.txt index 16d25e6b5a00..767392ffd31e 100644 --- a/Documentation/timers/hpet.txt +++ b/Documentation/timers/hpet.txt | |||
@@ -26,274 +26,5 @@ initialization. An example of this initialization can be found in | |||
26 | arch/x86/kernel/hpet.c. | 26 | arch/x86/kernel/hpet.c. |
27 | 27 | ||
28 | The driver provides a userspace API which resembles the API found in the | 28 | The driver provides a userspace API which resembles the API found in the |
29 | RTC driver framework. An example user space program is provided below. | 29 | RTC driver framework. An example user space program is provided in |
30 | 30 | file:Documentation/timers/hpet_example.c | |
31 | #include <stdio.h> | ||
32 | #include <stdlib.h> | ||
33 | #include <unistd.h> | ||
34 | #include <fcntl.h> | ||
35 | #include <string.h> | ||
36 | #include <memory.h> | ||
37 | #include <malloc.h> | ||
38 | #include <time.h> | ||
39 | #include <ctype.h> | ||
40 | #include <sys/types.h> | ||
41 | #include <sys/wait.h> | ||
42 | #include <signal.h> | ||
43 | #include <fcntl.h> | ||
44 | #include <errno.h> | ||
45 | #include <sys/time.h> | ||
46 | #include <linux/hpet.h> | ||
47 | |||
48 | |||
49 | extern void hpet_open_close(int, const char **); | ||
50 | extern void hpet_info(int, const char **); | ||
51 | extern void hpet_poll(int, const char **); | ||
52 | extern void hpet_fasync(int, const char **); | ||
53 | extern void hpet_read(int, const char **); | ||
54 | |||
55 | #include <sys/poll.h> | ||
56 | #include <sys/ioctl.h> | ||
57 | #include <signal.h> | ||
58 | |||
59 | struct hpet_command { | ||
60 | char *command; | ||
61 | void (*func)(int argc, const char ** argv); | ||
62 | } hpet_command[] = { | ||
63 | { | ||
64 | "open-close", | ||
65 | hpet_open_close | ||
66 | }, | ||
67 | { | ||
68 | "info", | ||
69 | hpet_info | ||
70 | }, | ||
71 | { | ||
72 | "poll", | ||
73 | hpet_poll | ||
74 | }, | ||
75 | { | ||
76 | "fasync", | ||
77 | hpet_fasync | ||
78 | }, | ||
79 | }; | ||
80 | |||
81 | int | ||
82 | main(int argc, const char ** argv) | ||
83 | { | ||
84 | int i; | ||
85 | |||
86 | argc--; | ||
87 | argv++; | ||
88 | |||
89 | if (!argc) { | ||
90 | fprintf(stderr, "-hpet: requires command\n"); | ||
91 | return -1; | ||
92 | } | ||
93 | |||
94 | |||
95 | for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++) | ||
96 | if (!strcmp(argv[0], hpet_command[i].command)) { | ||
97 | argc--; | ||
98 | argv++; | ||
99 | fprintf(stderr, "-hpet: executing %s\n", | ||
100 | hpet_command[i].command); | ||
101 | hpet_command[i].func(argc, argv); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]); | ||
106 | |||
107 | return -1; | ||
108 | } | ||
109 | |||
110 | void | ||
111 | hpet_open_close(int argc, const char **argv) | ||
112 | { | ||
113 | int fd; | ||
114 | |||
115 | if (argc != 1) { | ||
116 | fprintf(stderr, "hpet_open_close: device-name\n"); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | fd = open(argv[0], O_RDONLY); | ||
121 | if (fd < 0) | ||
122 | fprintf(stderr, "hpet_open_close: open failed\n"); | ||
123 | else | ||
124 | close(fd); | ||
125 | |||
126 | return; | ||
127 | } | ||
128 | |||
129 | void | ||
130 | hpet_info(int argc, const char **argv) | ||
131 | { | ||
132 | } | ||
133 | |||
134 | void | ||
135 | hpet_poll(int argc, const char **argv) | ||
136 | { | ||
137 | unsigned long freq; | ||
138 | int iterations, i, fd; | ||
139 | struct pollfd pfd; | ||
140 | struct hpet_info info; | ||
141 | struct timeval stv, etv; | ||
142 | struct timezone tz; | ||
143 | long usec; | ||
144 | |||
145 | if (argc != 3) { | ||
146 | fprintf(stderr, "hpet_poll: device-name freq iterations\n"); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | freq = atoi(argv[1]); | ||
151 | iterations = atoi(argv[2]); | ||
152 | |||
153 | fd = open(argv[0], O_RDONLY); | ||
154 | |||
155 | if (fd < 0) { | ||
156 | fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | if (ioctl(fd, HPET_IRQFREQ, freq) < 0) { | ||
161 | fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n"); | ||
162 | goto out; | ||
163 | } | ||
164 | |||
165 | if (ioctl(fd, HPET_INFO, &info) < 0) { | ||
166 | fprintf(stderr, "hpet_poll: failed to get info\n"); | ||
167 | goto out; | ||
168 | } | ||
169 | |||
170 | fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags); | ||
171 | |||
172 | if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) { | ||
173 | fprintf(stderr, "hpet_poll: HPET_EPI failed\n"); | ||
174 | goto out; | ||
175 | } | ||
176 | |||
177 | if (ioctl(fd, HPET_IE_ON, 0) < 0) { | ||
178 | fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n"); | ||
179 | goto out; | ||
180 | } | ||
181 | |||
182 | pfd.fd = fd; | ||
183 | pfd.events = POLLIN; | ||
184 | |||
185 | for (i = 0; i < iterations; i++) { | ||
186 | pfd.revents = 0; | ||
187 | gettimeofday(&stv, &tz); | ||
188 | if (poll(&pfd, 1, -1) < 0) | ||
189 | fprintf(stderr, "hpet_poll: poll failed\n"); | ||
190 | else { | ||
191 | long data; | ||
192 | |||
193 | gettimeofday(&etv, &tz); | ||
194 | usec = stv.tv_sec * 1000000 + stv.tv_usec; | ||
195 | usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec; | ||
196 | |||
197 | fprintf(stderr, | ||
198 | "hpet_poll: expired time = 0x%lx\n", usec); | ||
199 | |||
200 | fprintf(stderr, "hpet_poll: revents = 0x%x\n", | ||
201 | pfd.revents); | ||
202 | |||
203 | if (read(fd, &data, sizeof(data)) != sizeof(data)) { | ||
204 | fprintf(stderr, "hpet_poll: read failed\n"); | ||
205 | } | ||
206 | else | ||
207 | fprintf(stderr, "hpet_poll: data 0x%lx\n", | ||
208 | data); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | out: | ||
213 | close(fd); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | static int hpet_sigio_count; | ||
218 | |||
219 | static void | ||
220 | hpet_sigio(int val) | ||
221 | { | ||
222 | fprintf(stderr, "hpet_sigio: called\n"); | ||
223 | hpet_sigio_count++; | ||
224 | } | ||
225 | |||
226 | void | ||
227 | hpet_fasync(int argc, const char **argv) | ||
228 | { | ||
229 | unsigned long freq; | ||
230 | int iterations, i, fd, value; | ||
231 | sig_t oldsig; | ||
232 | struct hpet_info info; | ||
233 | |||
234 | hpet_sigio_count = 0; | ||
235 | fd = -1; | ||
236 | |||
237 | if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) { | ||
238 | fprintf(stderr, "hpet_fasync: failed to set signal handler\n"); | ||
239 | return; | ||
240 | } | ||
241 | |||
242 | if (argc != 3) { | ||
243 | fprintf(stderr, "hpet_fasync: device-name freq iterations\n"); | ||
244 | goto out; | ||
245 | } | ||
246 | |||
247 | fd = open(argv[0], O_RDONLY); | ||
248 | |||
249 | if (fd < 0) { | ||
250 | fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | |||
255 | if ((fcntl(fd, F_SETOWN, getpid()) == 1) || | ||
256 | ((value = fcntl(fd, F_GETFL)) == 1) || | ||
257 | (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) { | ||
258 | fprintf(stderr, "hpet_fasync: fcntl failed\n"); | ||
259 | goto out; | ||
260 | } | ||
261 | |||
262 | freq = atoi(argv[1]); | ||
263 | iterations = atoi(argv[2]); | ||
264 | |||
265 | if (ioctl(fd, HPET_IRQFREQ, freq) < 0) { | ||
266 | fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n"); | ||
267 | goto out; | ||
268 | } | ||
269 | |||
270 | if (ioctl(fd, HPET_INFO, &info) < 0) { | ||
271 | fprintf(stderr, "hpet_fasync: failed to get info\n"); | ||
272 | goto out; | ||
273 | } | ||
274 | |||
275 | fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags); | ||
276 | |||
277 | if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) { | ||
278 | fprintf(stderr, "hpet_fasync: HPET_EPI failed\n"); | ||
279 | goto out; | ||
280 | } | ||
281 | |||
282 | if (ioctl(fd, HPET_IE_ON, 0) < 0) { | ||
283 | fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n"); | ||
284 | goto out; | ||
285 | } | ||
286 | |||
287 | for (i = 0; i < iterations; i++) { | ||
288 | (void) pause(); | ||
289 | fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count); | ||
290 | } | ||
291 | |||
292 | out: | ||
293 | signal(SIGIO, oldsig); | ||
294 | |||
295 | if (fd >= 0) | ||
296 | close(fd); | ||
297 | |||
298 | return; | ||
299 | } | ||
diff --git a/Documentation/timers/hpet_example.c b/Documentation/timers/hpet_example.c new file mode 100644 index 000000000000..f9ce2d9fdfd5 --- /dev/null +++ b/Documentation/timers/hpet_example.c | |||
@@ -0,0 +1,269 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <unistd.h> | ||
4 | #include <fcntl.h> | ||
5 | #include <string.h> | ||
6 | #include <memory.h> | ||
7 | #include <malloc.h> | ||
8 | #include <time.h> | ||
9 | #include <ctype.h> | ||
10 | #include <sys/types.h> | ||
11 | #include <sys/wait.h> | ||
12 | #include <signal.h> | ||
13 | #include <fcntl.h> | ||
14 | #include <errno.h> | ||
15 | #include <sys/time.h> | ||
16 | #include <linux/hpet.h> | ||
17 | |||
18 | |||
19 | extern void hpet_open_close(int, const char **); | ||
20 | extern void hpet_info(int, const char **); | ||
21 | extern void hpet_poll(int, const char **); | ||
22 | extern void hpet_fasync(int, const char **); | ||
23 | extern void hpet_read(int, const char **); | ||
24 | |||
25 | #include <sys/poll.h> | ||
26 | #include <sys/ioctl.h> | ||
27 | #include <signal.h> | ||
28 | |||
29 | struct hpet_command { | ||
30 | char *command; | ||
31 | void (*func)(int argc, const char ** argv); | ||
32 | } hpet_command[] = { | ||
33 | { | ||
34 | "open-close", | ||
35 | hpet_open_close | ||
36 | }, | ||
37 | { | ||
38 | "info", | ||
39 | hpet_info | ||
40 | }, | ||
41 | { | ||
42 | "poll", | ||
43 | hpet_poll | ||
44 | }, | ||
45 | { | ||
46 | "fasync", | ||
47 | hpet_fasync | ||
48 | }, | ||
49 | }; | ||
50 | |||
51 | int | ||
52 | main(int argc, const char ** argv) | ||
53 | { | ||
54 | int i; | ||
55 | |||
56 | argc--; | ||
57 | argv++; | ||
58 | |||
59 | if (!argc) { | ||
60 | fprintf(stderr, "-hpet: requires command\n"); | ||
61 | return -1; | ||
62 | } | ||
63 | |||
64 | |||
65 | for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++) | ||
66 | if (!strcmp(argv[0], hpet_command[i].command)) { | ||
67 | argc--; | ||
68 | argv++; | ||
69 | fprintf(stderr, "-hpet: executing %s\n", | ||
70 | hpet_command[i].command); | ||
71 | hpet_command[i].func(argc, argv); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]); | ||
76 | |||
77 | return -1; | ||
78 | } | ||
79 | |||
80 | void | ||
81 | hpet_open_close(int argc, const char **argv) | ||
82 | { | ||
83 | int fd; | ||
84 | |||
85 | if (argc != 1) { | ||
86 | fprintf(stderr, "hpet_open_close: device-name\n"); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | fd = open(argv[0], O_RDONLY); | ||
91 | if (fd < 0) | ||
92 | fprintf(stderr, "hpet_open_close: open failed\n"); | ||
93 | else | ||
94 | close(fd); | ||
95 | |||
96 | return; | ||
97 | } | ||
98 | |||
99 | void | ||
100 | hpet_info(int argc, const char **argv) | ||
101 | { | ||
102 | } | ||
103 | |||
104 | void | ||
105 | hpet_poll(int argc, const char **argv) | ||
106 | { | ||
107 | unsigned long freq; | ||
108 | int iterations, i, fd; | ||
109 | struct pollfd pfd; | ||
110 | struct hpet_info info; | ||
111 | struct timeval stv, etv; | ||
112 | struct timezone tz; | ||
113 | long usec; | ||
114 | |||
115 | if (argc != 3) { | ||
116 | fprintf(stderr, "hpet_poll: device-name freq iterations\n"); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | freq = atoi(argv[1]); | ||
121 | iterations = atoi(argv[2]); | ||
122 | |||
123 | fd = open(argv[0], O_RDONLY); | ||
124 | |||
125 | if (fd < 0) { | ||
126 | fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]); | ||
127 | return; | ||
128 | } | ||
129 | |||
130 | if (ioctl(fd, HPET_IRQFREQ, freq) < 0) { | ||
131 | fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n"); | ||
132 | goto out; | ||
133 | } | ||
134 | |||
135 | if (ioctl(fd, HPET_INFO, &info) < 0) { | ||
136 | fprintf(stderr, "hpet_poll: failed to get info\n"); | ||
137 | goto out; | ||
138 | } | ||
139 | |||
140 | fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags); | ||
141 | |||
142 | if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) { | ||
143 | fprintf(stderr, "hpet_poll: HPET_EPI failed\n"); | ||
144 | goto out; | ||
145 | } | ||
146 | |||
147 | if (ioctl(fd, HPET_IE_ON, 0) < 0) { | ||
148 | fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n"); | ||
149 | goto out; | ||
150 | } | ||
151 | |||
152 | pfd.fd = fd; | ||
153 | pfd.events = POLLIN; | ||
154 | |||
155 | for (i = 0; i < iterations; i++) { | ||
156 | pfd.revents = 0; | ||
157 | gettimeofday(&stv, &tz); | ||
158 | if (poll(&pfd, 1, -1) < 0) | ||
159 | fprintf(stderr, "hpet_poll: poll failed\n"); | ||
160 | else { | ||
161 | long data; | ||
162 | |||
163 | gettimeofday(&etv, &tz); | ||
164 | usec = stv.tv_sec * 1000000 + stv.tv_usec; | ||
165 | usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec; | ||
166 | |||
167 | fprintf(stderr, | ||
168 | "hpet_poll: expired time = 0x%lx\n", usec); | ||
169 | |||
170 | fprintf(stderr, "hpet_poll: revents = 0x%x\n", | ||
171 | pfd.revents); | ||
172 | |||
173 | if (read(fd, &data, sizeof(data)) != sizeof(data)) { | ||
174 | fprintf(stderr, "hpet_poll: read failed\n"); | ||
175 | } | ||
176 | else | ||
177 | fprintf(stderr, "hpet_poll: data 0x%lx\n", | ||
178 | data); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | out: | ||
183 | close(fd); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | static int hpet_sigio_count; | ||
188 | |||
189 | static void | ||
190 | hpet_sigio(int val) | ||
191 | { | ||
192 | fprintf(stderr, "hpet_sigio: called\n"); | ||
193 | hpet_sigio_count++; | ||
194 | } | ||
195 | |||
196 | void | ||
197 | hpet_fasync(int argc, const char **argv) | ||
198 | { | ||
199 | unsigned long freq; | ||
200 | int iterations, i, fd, value; | ||
201 | sig_t oldsig; | ||
202 | struct hpet_info info; | ||
203 | |||
204 | hpet_sigio_count = 0; | ||
205 | fd = -1; | ||
206 | |||
207 | if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) { | ||
208 | fprintf(stderr, "hpet_fasync: failed to set signal handler\n"); | ||
209 | return; | ||
210 | } | ||
211 | |||
212 | if (argc != 3) { | ||
213 | fprintf(stderr, "hpet_fasync: device-name freq iterations\n"); | ||
214 | goto out; | ||
215 | } | ||
216 | |||
217 | fd = open(argv[0], O_RDONLY); | ||
218 | |||
219 | if (fd < 0) { | ||
220 | fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]); | ||
221 | return; | ||
222 | } | ||
223 | |||
224 | |||
225 | if ((fcntl(fd, F_SETOWN, getpid()) == 1) || | ||
226 | ((value = fcntl(fd, F_GETFL)) == 1) || | ||
227 | (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) { | ||
228 | fprintf(stderr, "hpet_fasync: fcntl failed\n"); | ||
229 | goto out; | ||
230 | } | ||
231 | |||
232 | freq = atoi(argv[1]); | ||
233 | iterations = atoi(argv[2]); | ||
234 | |||
235 | if (ioctl(fd, HPET_IRQFREQ, freq) < 0) { | ||
236 | fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n"); | ||
237 | goto out; | ||
238 | } | ||
239 | |||
240 | if (ioctl(fd, HPET_INFO, &info) < 0) { | ||
241 | fprintf(stderr, "hpet_fasync: failed to get info\n"); | ||
242 | goto out; | ||
243 | } | ||
244 | |||
245 | fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags); | ||
246 | |||
247 | if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) { | ||
248 | fprintf(stderr, "hpet_fasync: HPET_EPI failed\n"); | ||
249 | goto out; | ||
250 | } | ||
251 | |||
252 | if (ioctl(fd, HPET_IE_ON, 0) < 0) { | ||
253 | fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n"); | ||
254 | goto out; | ||
255 | } | ||
256 | |||
257 | for (i = 0; i < iterations; i++) { | ||
258 | (void) pause(); | ||
259 | fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count); | ||
260 | } | ||
261 | |||
262 | out: | ||
263 | signal(SIGIO, oldsig); | ||
264 | |||
265 | if (fd >= 0) | ||
266 | close(fd); | ||
267 | |||
268 | return; | ||
269 | } | ||
diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX index e57d6a9dd32b..dca82d7c83d8 100644 --- a/Documentation/vm/00-INDEX +++ b/Documentation/vm/00-INDEX | |||
@@ -4,23 +4,35 @@ active_mm.txt | |||
4 | - An explanation from Linus about tsk->active_mm vs tsk->mm. | 4 | - An explanation from Linus about tsk->active_mm vs tsk->mm. |
5 | balance | 5 | balance |
6 | - various information on memory balancing. | 6 | - various information on memory balancing. |
7 | hugepage-mmap.c | ||
8 | - Example app using huge page memory with the mmap system call. | ||
9 | hugepage-shm.c | ||
10 | - Example app using huge page memory with Sys V shared memory system calls. | ||
7 | hugetlbpage.txt | 11 | hugetlbpage.txt |
8 | - a brief summary of hugetlbpage support in the Linux kernel. | 12 | - a brief summary of hugetlbpage support in the Linux kernel. |
13 | hwpoison.txt | ||
14 | - explains what hwpoison is | ||
9 | ksm.txt | 15 | ksm.txt |
10 | - how to use the Kernel Samepage Merging feature. | 16 | - how to use the Kernel Samepage Merging feature. |
11 | locking | 17 | locking |
12 | - info on how locking and synchronization is done in the Linux vm code. | 18 | - info on how locking and synchronization is done in the Linux vm code. |
19 | map_hugetlb.c | ||
20 | - an example program that uses the MAP_HUGETLB mmap flag. | ||
13 | numa | 21 | numa |
14 | - information about NUMA specific code in the Linux vm. | 22 | - information about NUMA specific code in the Linux vm. |
15 | numa_memory_policy.txt | 23 | numa_memory_policy.txt |
16 | - documentation of concepts and APIs of the 2.6 memory policy support. | 24 | - documentation of concepts and APIs of the 2.6 memory policy support. |
17 | overcommit-accounting | 25 | overcommit-accounting |
18 | - description of the Linux kernels overcommit handling modes. | 26 | - description of the Linux kernels overcommit handling modes. |
27 | page-types.c | ||
28 | - Tool for querying page flags | ||
19 | page_migration | 29 | page_migration |
20 | - description of page migration in NUMA systems. | 30 | - description of page migration in NUMA systems. |
31 | pagemap.txt | ||
32 | - pagemap, from the userspace perspective | ||
21 | slabinfo.c | 33 | slabinfo.c |
22 | - source code for a tool to get reports about slabs. | 34 | - source code for a tool to get reports about slabs. |
23 | slub.txt | 35 | slub.txt |
24 | - a short users guide for SLUB. | 36 | - a short users guide for SLUB. |
25 | map_hugetlb.c | 37 | unevictable-lru.txt |
26 | - an example program that uses the MAP_HUGETLB mmap flag. | 38 | - Unevictable LRU infrastructure |
diff --git a/Documentation/vm/Makefile b/Documentation/vm/Makefile index 5bd269b3731a..9dcff328b964 100644 --- a/Documentation/vm/Makefile +++ b/Documentation/vm/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | obj- := dummy.o | 2 | obj- := dummy.o |
3 | 3 | ||
4 | # List of programs to build | 4 | # List of programs to build |
5 | hostprogs-y := slabinfo page-types | 5 | hostprogs-y := slabinfo page-types hugepage-mmap hugepage-shm map_hugetlb |
6 | 6 | ||
7 | # Tell kbuild to always build the programs | 7 | # Tell kbuild to always build the programs |
8 | always := $(hostprogs-y) | 8 | always := $(hostprogs-y) |
diff --git a/Documentation/vm/hugepage-mmap.c b/Documentation/vm/hugepage-mmap.c new file mode 100644 index 000000000000..db0dd9a33d54 --- /dev/null +++ b/Documentation/vm/hugepage-mmap.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * hugepage-mmap: | ||
3 | * | ||
4 | * Example of using huge page memory in a user application using the mmap | ||
5 | * system call. Before running this application, make sure that the | ||
6 | * administrator has mounted the hugetlbfs filesystem (on some directory | ||
7 | * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this | ||
8 | * example, the app is requesting memory of size 256MB that is backed by | ||
9 | * huge pages. | ||
10 | * | ||
11 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for | ||
12 | * huge pages. That means that if one requires a fixed address, a huge page | ||
13 | * aligned address starting with 0x800000... will be required. If a fixed | ||
14 | * address is not required, the kernel will select an address in the proper | ||
15 | * range. | ||
16 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
17 | */ | ||
18 | |||
19 | #include <stdlib.h> | ||
20 | #include <stdio.h> | ||
21 | #include <unistd.h> | ||
22 | #include <sys/mman.h> | ||
23 | #include <fcntl.h> | ||
24 | |||
25 | #define FILE_NAME "/mnt/hugepagefile" | ||
26 | #define LENGTH (256UL*1024*1024) | ||
27 | #define PROTECTION (PROT_READ | PROT_WRITE) | ||
28 | |||
29 | /* Only ia64 requires this */ | ||
30 | #ifdef __ia64__ | ||
31 | #define ADDR (void *)(0x8000000000000000UL) | ||
32 | #define FLAGS (MAP_SHARED | MAP_FIXED) | ||
33 | #else | ||
34 | #define ADDR (void *)(0x0UL) | ||
35 | #define FLAGS (MAP_SHARED) | ||
36 | #endif | ||
37 | |||
38 | static void check_bytes(char *addr) | ||
39 | { | ||
40 | printf("First hex is %x\n", *((unsigned int *)addr)); | ||
41 | } | ||
42 | |||
43 | static void write_bytes(char *addr) | ||
44 | { | ||
45 | unsigned long i; | ||
46 | |||
47 | for (i = 0; i < LENGTH; i++) | ||
48 | *(addr + i) = (char)i; | ||
49 | } | ||
50 | |||
51 | static void read_bytes(char *addr) | ||
52 | { | ||
53 | unsigned long i; | ||
54 | |||
55 | check_bytes(addr); | ||
56 | for (i = 0; i < LENGTH; i++) | ||
57 | if (*(addr + i) != (char)i) { | ||
58 | printf("Mismatch at %lu\n", i); | ||
59 | break; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | int main(void) | ||
64 | { | ||
65 | void *addr; | ||
66 | int fd; | ||
67 | |||
68 | fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755); | ||
69 | if (fd < 0) { | ||
70 | perror("Open failed"); | ||
71 | exit(1); | ||
72 | } | ||
73 | |||
74 | addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0); | ||
75 | if (addr == MAP_FAILED) { | ||
76 | perror("mmap"); | ||
77 | unlink(FILE_NAME); | ||
78 | exit(1); | ||
79 | } | ||
80 | |||
81 | printf("Returned address is %p\n", addr); | ||
82 | check_bytes(addr); | ||
83 | write_bytes(addr); | ||
84 | read_bytes(addr); | ||
85 | |||
86 | munmap(addr, LENGTH); | ||
87 | close(fd); | ||
88 | unlink(FILE_NAME); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
diff --git a/Documentation/vm/hugepage-shm.c b/Documentation/vm/hugepage-shm.c new file mode 100644 index 000000000000..07956d8592c9 --- /dev/null +++ b/Documentation/vm/hugepage-shm.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * hugepage-shm: | ||
3 | * | ||
4 | * Example of using huge page memory in a user application using Sys V shared | ||
5 | * memory system calls. In this example the app is requesting 256MB of | ||
6 | * memory that is backed by huge pages. The application uses the flag | ||
7 | * SHM_HUGETLB in the shmget system call to inform the kernel that it is | ||
8 | * requesting huge pages. | ||
9 | * | ||
10 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for | ||
11 | * huge pages. That means that if one requires a fixed address, a huge page | ||
12 | * aligned address starting with 0x800000... will be required. If a fixed | ||
13 | * address is not required, the kernel will select an address in the proper | ||
14 | * range. | ||
15 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
16 | * | ||
17 | * Note: The default shared memory limit is quite low on many kernels, | ||
18 | * you may need to increase it via: | ||
19 | * | ||
20 | * echo 268435456 > /proc/sys/kernel/shmmax | ||
21 | * | ||
22 | * This will increase the maximum size per shared memory segment to 256MB. | ||
23 | * The other limit that you will hit eventually is shmall which is the | ||
24 | * total amount of shared memory in pages. To set it to 16GB on a system | ||
25 | * with a 4kB pagesize do: | ||
26 | * | ||
27 | * echo 4194304 > /proc/sys/kernel/shmall | ||
28 | */ | ||
29 | |||
30 | #include <stdlib.h> | ||
31 | #include <stdio.h> | ||
32 | #include <sys/types.h> | ||
33 | #include <sys/ipc.h> | ||
34 | #include <sys/shm.h> | ||
35 | #include <sys/mman.h> | ||
36 | |||
37 | #ifndef SHM_HUGETLB | ||
38 | #define SHM_HUGETLB 04000 | ||
39 | #endif | ||
40 | |||
41 | #define LENGTH (256UL*1024*1024) | ||
42 | |||
43 | #define dprintf(x) printf(x) | ||
44 | |||
45 | /* Only ia64 requires this */ | ||
46 | #ifdef __ia64__ | ||
47 | #define ADDR (void *)(0x8000000000000000UL) | ||
48 | #define SHMAT_FLAGS (SHM_RND) | ||
49 | #else | ||
50 | #define ADDR (void *)(0x0UL) | ||
51 | #define SHMAT_FLAGS (0) | ||
52 | #endif | ||
53 | |||
54 | int main(void) | ||
55 | { | ||
56 | int shmid; | ||
57 | unsigned long i; | ||
58 | char *shmaddr; | ||
59 | |||
60 | if ((shmid = shmget(2, LENGTH, | ||
61 | SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) { | ||
62 | perror("shmget"); | ||
63 | exit(1); | ||
64 | } | ||
65 | printf("shmid: 0x%x\n", shmid); | ||
66 | |||
67 | shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS); | ||
68 | if (shmaddr == (char *)-1) { | ||
69 | perror("Shared memory attach failure"); | ||
70 | shmctl(shmid, IPC_RMID, NULL); | ||
71 | exit(2); | ||
72 | } | ||
73 | printf("shmaddr: %p\n", shmaddr); | ||
74 | |||
75 | dprintf("Starting the writes:\n"); | ||
76 | for (i = 0; i < LENGTH; i++) { | ||
77 | shmaddr[i] = (char)(i); | ||
78 | if (!(i % (1024 * 1024))) | ||
79 | dprintf("."); | ||
80 | } | ||
81 | dprintf("\n"); | ||
82 | |||
83 | dprintf("Starting the Check..."); | ||
84 | for (i = 0; i < LENGTH; i++) | ||
85 | if (shmaddr[i] != (char)i) | ||
86 | printf("\nIndex %lu mismatched\n", i); | ||
87 | dprintf("Done.\n"); | ||
88 | |||
89 | if (shmdt((const void *)shmaddr) != 0) { | ||
90 | perror("Detach failure"); | ||
91 | shmctl(shmid, IPC_RMID, NULL); | ||
92 | exit(3); | ||
93 | } | ||
94 | |||
95 | shmctl(shmid, IPC_RMID, NULL); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index bc31636973e3..457634c1e03e 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt | |||
@@ -299,176 +299,11 @@ map_hugetlb.c. | |||
299 | ******************************************************************* | 299 | ******************************************************************* |
300 | 300 | ||
301 | /* | 301 | /* |
302 | * Example of using huge page memory in a user application using Sys V shared | 302 | * hugepage-shm: see Documentation/vm/hugepage-shm.c |
303 | * memory system calls. In this example the app is requesting 256MB of | ||
304 | * memory that is backed by huge pages. The application uses the flag | ||
305 | * SHM_HUGETLB in the shmget system call to inform the kernel that it is | ||
306 | * requesting huge pages. | ||
307 | * | ||
308 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for | ||
309 | * huge pages. That means that if one requires a fixed address, a huge page | ||
310 | * aligned address starting with 0x800000... will be required. If a fixed | ||
311 | * address is not required, the kernel will select an address in the proper | ||
312 | * range. | ||
313 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
314 | * | ||
315 | * Note: The default shared memory limit is quite low on many kernels, | ||
316 | * you may need to increase it via: | ||
317 | * | ||
318 | * echo 268435456 > /proc/sys/kernel/shmmax | ||
319 | * | ||
320 | * This will increase the maximum size per shared memory segment to 256MB. | ||
321 | * The other limit that you will hit eventually is shmall which is the | ||
322 | * total amount of shared memory in pages. To set it to 16GB on a system | ||
323 | * with a 4kB pagesize do: | ||
324 | * | ||
325 | * echo 4194304 > /proc/sys/kernel/shmall | ||
326 | */ | 303 | */ |
327 | #include <stdlib.h> | ||
328 | #include <stdio.h> | ||
329 | #include <sys/types.h> | ||
330 | #include <sys/ipc.h> | ||
331 | #include <sys/shm.h> | ||
332 | #include <sys/mman.h> | ||
333 | |||
334 | #ifndef SHM_HUGETLB | ||
335 | #define SHM_HUGETLB 04000 | ||
336 | #endif | ||
337 | |||
338 | #define LENGTH (256UL*1024*1024) | ||
339 | |||
340 | #define dprintf(x) printf(x) | ||
341 | |||
342 | #define ADDR (void *)(0x0UL) /* let kernel choose address */ | ||
343 | #define SHMAT_FLAGS (0) | ||
344 | |||
345 | int main(void) | ||
346 | { | ||
347 | int shmid; | ||
348 | unsigned long i; | ||
349 | char *shmaddr; | ||
350 | |||
351 | if ((shmid = shmget(2, LENGTH, | ||
352 | SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) { | ||
353 | perror("shmget"); | ||
354 | exit(1); | ||
355 | } | ||
356 | printf("shmid: 0x%x\n", shmid); | ||
357 | |||
358 | shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS); | ||
359 | if (shmaddr == (char *)-1) { | ||
360 | perror("Shared memory attach failure"); | ||
361 | shmctl(shmid, IPC_RMID, NULL); | ||
362 | exit(2); | ||
363 | } | ||
364 | printf("shmaddr: %p\n", shmaddr); | ||
365 | |||
366 | dprintf("Starting the writes:\n"); | ||
367 | for (i = 0; i < LENGTH; i++) { | ||
368 | shmaddr[i] = (char)(i); | ||
369 | if (!(i % (1024 * 1024))) | ||
370 | dprintf("."); | ||
371 | } | ||
372 | dprintf("\n"); | ||
373 | |||
374 | dprintf("Starting the Check..."); | ||
375 | for (i = 0; i < LENGTH; i++) | ||
376 | if (shmaddr[i] != (char)i) | ||
377 | printf("\nIndex %lu mismatched\n", i); | ||
378 | dprintf("Done.\n"); | ||
379 | |||
380 | if (shmdt((const void *)shmaddr) != 0) { | ||
381 | perror("Detach failure"); | ||
382 | shmctl(shmid, IPC_RMID, NULL); | ||
383 | exit(3); | ||
384 | } | ||
385 | |||
386 | shmctl(shmid, IPC_RMID, NULL); | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | 304 | ||
391 | ******************************************************************* | 305 | ******************************************************************* |
392 | 306 | ||
393 | /* | 307 | /* |
394 | * Example of using huge page memory in a user application using the mmap | 308 | * hugepage-mmap: see Documentation/vm/hugepage-mmap.c |
395 | * system call. Before running this application, make sure that the | ||
396 | * administrator has mounted the hugetlbfs filesystem (on some directory | ||
397 | * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this | ||
398 | * example, the app is requesting memory of size 256MB that is backed by | ||
399 | * huge pages. | ||
400 | * | ||
401 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for | ||
402 | * huge pages. That means that if one requires a fixed address, a huge page | ||
403 | * aligned address starting with 0x800000... will be required. If a fixed | ||
404 | * address is not required, the kernel will select an address in the proper | ||
405 | * range. | ||
406 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
407 | */ | 309 | */ |
408 | #include <stdlib.h> | ||
409 | #include <stdio.h> | ||
410 | #include <unistd.h> | ||
411 | #include <sys/mman.h> | ||
412 | #include <fcntl.h> | ||
413 | |||
414 | #define FILE_NAME "/mnt/hugepagefile" | ||
415 | #define LENGTH (256UL*1024*1024) | ||
416 | #define PROTECTION (PROT_READ | PROT_WRITE) | ||
417 | |||
418 | #define ADDR (void *)(0x0UL) /* let kernel choose address */ | ||
419 | #define FLAGS (MAP_SHARED) | ||
420 | |||
421 | void check_bytes(char *addr) | ||
422 | { | ||
423 | printf("First hex is %x\n", *((unsigned int *)addr)); | ||
424 | } | ||
425 | |||
426 | void write_bytes(char *addr) | ||
427 | { | ||
428 | unsigned long i; | ||
429 | |||
430 | for (i = 0; i < LENGTH; i++) | ||
431 | *(addr + i) = (char)i; | ||
432 | } | ||
433 | |||
434 | void read_bytes(char *addr) | ||
435 | { | ||
436 | unsigned long i; | ||
437 | |||
438 | check_bytes(addr); | ||
439 | for (i = 0; i < LENGTH; i++) | ||
440 | if (*(addr + i) != (char)i) { | ||
441 | printf("Mismatch at %lu\n", i); | ||
442 | break; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | int main(void) | ||
447 | { | ||
448 | void *addr; | ||
449 | int fd; | ||
450 | |||
451 | fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755); | ||
452 | if (fd < 0) { | ||
453 | perror("Open failed"); | ||
454 | exit(1); | ||
455 | } | ||
456 | |||
457 | addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0); | ||
458 | if (addr == MAP_FAILED) { | ||
459 | perror("mmap"); | ||
460 | unlink(FILE_NAME); | ||
461 | exit(1); | ||
462 | } | ||
463 | |||
464 | printf("Returned address is %p\n", addr); | ||
465 | check_bytes(addr); | ||
466 | write_bytes(addr); | ||
467 | read_bytes(addr); | ||
468 | |||
469 | munmap(addr, LENGTH); | ||
470 | close(fd); | ||
471 | unlink(FILE_NAME); | ||
472 | |||
473 | return 0; | ||
474 | } | ||
diff --git a/Documentation/vm/map_hugetlb.c b/Documentation/vm/map_hugetlb.c index e2bdae37f499..9969c7d9f985 100644 --- a/Documentation/vm/map_hugetlb.c +++ b/Documentation/vm/map_hugetlb.c | |||
@@ -31,12 +31,12 @@ | |||
31 | #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB) | 31 | #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB) |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | void check_bytes(char *addr) | 34 | static void check_bytes(char *addr) |
35 | { | 35 | { |
36 | printf("First hex is %x\n", *((unsigned int *)addr)); | 36 | printf("First hex is %x\n", *((unsigned int *)addr)); |
37 | } | 37 | } |
38 | 38 | ||
39 | void write_bytes(char *addr) | 39 | static void write_bytes(char *addr) |
40 | { | 40 | { |
41 | unsigned long i; | 41 | unsigned long i; |
42 | 42 | ||
@@ -44,7 +44,7 @@ void write_bytes(char *addr) | |||
44 | *(addr + i) = (char)i; | 44 | *(addr + i) = (char)i; |
45 | } | 45 | } |
46 | 46 | ||
47 | void read_bytes(char *addr) | 47 | static void read_bytes(char *addr) |
48 | { | 48 | { |
49 | unsigned long i; | 49 | unsigned long i; |
50 | 50 | ||
diff --git a/Documentation/voyager.txt b/Documentation/voyager.txt deleted file mode 100644 index 2749af552cdf..000000000000 --- a/Documentation/voyager.txt +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | Running Linux on the Voyager Architecture | ||
2 | ========================================= | ||
3 | |||
4 | For full details and current project status, see | ||
5 | |||
6 | http://www.hansenpartnership.com/voyager | ||
7 | |||
8 | The voyager architecture was designed by NCR in the mid 80s to be a | ||
9 | fully SMP capable RAS computing architecture built around intel's 486 | ||
10 | chip set. The voyager came in three levels of architectural | ||
11 | sophistication: 3,4 and 5 --- 1 and 2 never made it out of prototype. | ||
12 | The linux patches support only the Level 5 voyager architecture (any | ||
13 | machine class 3435 and above). | ||
14 | |||
15 | The Voyager Architecture | ||
16 | ------------------------ | ||
17 | |||
18 | Voyager machines consist of a Baseboard with a 386 diagnostic | ||
19 | processor, a Power Supply Interface (PSI) a Primary and possibly | ||
20 | Secondary Microchannel bus and between 2 and 20 voyager slots. The | ||
21 | voyager slots can be populated with memory and cpu cards (up to 4GB | ||
22 | memory and from 1 486 to 32 Pentium Pro processors). Internally, the | ||
23 | voyager has a dual arbitrated system bus and a configuration and test | ||
24 | bus (CAT). The voyager bus speed is 40MHz. Therefore (since all | ||
25 | voyager cards are dual ported for each system bus) the maximum | ||
26 | transfer rate is 320Mb/s but only if you have your slot configuration | ||
27 | tuned (only memory cards can communicate with both busses at once, CPU | ||
28 | cards utilise them one at a time). | ||
29 | |||
30 | Voyager SMP | ||
31 | ----------- | ||
32 | |||
33 | Since voyager was the first intel based SMP system, it is slightly | ||
34 | more primitive than the Intel IO-APIC approach to SMP. Voyager allows | ||
35 | arbitrary interrupt routing (including processor affinity routing) of | ||
36 | all 16 PC type interrupts. However it does this by using a modified | ||
37 | 5259 master/slave chip set instead of an APIC bus. Additionally, | ||
38 | voyager supports Cross Processor Interrupts (CPI) equivalent to the | ||
39 | APIC IPIs. There are two routed voyager interrupt lines provided to | ||
40 | each slot. | ||
41 | |||
42 | Processor Cards | ||
43 | --------------- | ||
44 | |||
45 | These come in single, dyadic and quad configurations (the quads are | ||
46 | problematic--see later). The maximum configuration is 8 quad cards | ||
47 | for 32 way SMP. | ||
48 | |||
49 | Quad Processors | ||
50 | --------------- | ||
51 | |||
52 | Because voyager only supplies two interrupt lines to each Processor | ||
53 | card, the Quad processors have to be configured (and Bootstrapped) in | ||
54 | as a pair of Master/Slave processors. | ||
55 | |||
56 | In fact, most Quad cards only accept one VIC interrupt line, so they | ||
57 | have one interrupt handling processor (called the VIC extended | ||
58 | processor) and three non-interrupt handling processors. | ||
59 | |||
60 | Current Status | ||
61 | -------------- | ||
62 | |||
63 | The System will boot on Mono, Dyad and Quad cards. There was | ||
64 | originally a Quad boot problem which has been fixed by proper gdt | ||
65 | alignment in the initial boot loader. If you still cannot get your | ||
66 | voyager system to boot, email me at: | ||
67 | |||
68 | <J.E.J.Bottomley@HansenPartnership.com> | ||
69 | |||
70 | |||
71 | The Quad cards now support using the separate Quad CPI vectors instead | ||
72 | of going through the VIC mailbox system. | ||
73 | |||
74 | The Level 4 architecture (3430 and 3360 Machines) should also work | ||
75 | fine. | ||
76 | |||
77 | Dump Switch | ||
78 | ----------- | ||
79 | |||
80 | The voyager dump switch sends out a broadcast NMI which the voyager | ||
81 | code intercepts and does a task dump. | ||
82 | |||
83 | Power Switch | ||
84 | ------------ | ||
85 | |||
86 | The front panel power switch is intercepted by the kernel and should | ||
87 | cause a system shutdown and power off. | ||
88 | |||
89 | A Note About Mixed CPU Systems | ||
90 | ------------------------------ | ||
91 | |||
92 | Linux isn't designed to handle mixed CPU systems very well. In order | ||
93 | to get everything going you *must* make sure that your lowest | ||
94 | capability CPU is used for booting. Also, mixing CPU classes | ||
95 | (e.g. 486 and 586) is really not going to work very well at all. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index bd8ac1ebc65b..fe88b5f732cd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1251,6 +1251,13 @@ W: http://blackfin.uclinux.org | |||
1251 | S: Supported | 1251 | S: Supported |
1252 | F: drivers/rtc/rtc-bfin.c | 1252 | F: drivers/rtc/rtc-bfin.c |
1253 | 1253 | ||
1254 | BLACKFIN SDH DRIVER | ||
1255 | M: Cliff Cai <cliff.cai@analog.com> | ||
1256 | L: uclinux-dist-devel@blackfin.uclinux.org | ||
1257 | W: http://blackfin.uclinux.org | ||
1258 | S: Supported | ||
1259 | F: drivers/mmc/host/bfin_sdh.c | ||
1260 | |||
1254 | BLACKFIN SERIAL DRIVER | 1261 | BLACKFIN SERIAL DRIVER |
1255 | M: Sonic Zhang <sonic.zhang@analog.com> | 1262 | M: Sonic Zhang <sonic.zhang@analog.com> |
1256 | L: uclinux-dist-devel@blackfin.uclinux.org | 1263 | L: uclinux-dist-devel@blackfin.uclinux.org |
@@ -2820,7 +2827,7 @@ S: Maintained | |||
2820 | F: drivers/input/ | 2827 | F: drivers/input/ |
2821 | 2828 | ||
2822 | INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) | 2829 | INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) |
2823 | M: Sylvain Meyer <sylvain.meyer@worldonline.fr> | 2830 | M: Maik Broemme <mbroemme@plusserver.de> |
2824 | L: linux-fbdev@vger.kernel.org | 2831 | L: linux-fbdev@vger.kernel.org |
2825 | S: Maintained | 2832 | S: Maintained |
2826 | F: Documentation/fb/intelfb.txt | 2833 | F: Documentation/fb/intelfb.txt |
@@ -3637,7 +3644,7 @@ F: mm/ | |||
3637 | 3644 | ||
3638 | MEMORY RESOURCE CONTROLLER | 3645 | MEMORY RESOURCE CONTROLLER |
3639 | M: Balbir Singh <balbir@linux.vnet.ibm.com> | 3646 | M: Balbir Singh <balbir@linux.vnet.ibm.com> |
3640 | M: Pavel Emelyanov <xemul@openvz.org> | 3647 | M: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> |
3641 | M: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 3648 | M: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> |
3642 | L: linux-mm@kvack.org | 3649 | L: linux-mm@kvack.org |
3643 | S: Maintained | 3650 | S: Maintained |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 33 | 3 | SUBLEVEL = 34 |
4 | EXTRAVERSION = | 4 | EXTRAVERSION = -rc1 |
5 | NAME = Man-Eating Seals of Antiquity | 5 | NAME = Man-Eating Seals of Antiquity |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index bd7261ea8f94..75291fdd379f 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -10,6 +10,7 @@ config ALPHA | |||
10 | select HAVE_OPROFILE | 10 | select HAVE_OPROFILE |
11 | select HAVE_SYSCALL_WRAPPERS | 11 | select HAVE_SYSCALL_WRAPPERS |
12 | select HAVE_PERF_EVENTS | 12 | select HAVE_PERF_EVENTS |
13 | select HAVE_DMA_ATTRS | ||
13 | help | 14 | help |
14 | The Alpha is a 64-bit general-purpose processor designed and | 15 | The Alpha is a 64-bit general-purpose processor designed and |
15 | marketed by the Digital Equipment Corporation of blessed memory, | 16 | marketed by the Digital Equipment Corporation of blessed memory, |
@@ -58,6 +59,9 @@ config ZONE_DMA | |||
58 | bool | 59 | bool |
59 | default y | 60 | default y |
60 | 61 | ||
62 | config NEED_DMA_MAP_STATE | ||
63 | def_bool y | ||
64 | |||
61 | config GENERIC_ISA_DMA | 65 | config GENERIC_ISA_DMA |
62 | bool | 66 | bool |
63 | default y | 67 | default y |
diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h index 04eb5681448c..1bce8169733c 100644 --- a/arch/alpha/include/asm/dma-mapping.h +++ b/arch/alpha/include/asm/dma-mapping.h | |||
@@ -1,71 +1,49 @@ | |||
1 | #ifndef _ALPHA_DMA_MAPPING_H | 1 | #ifndef _ALPHA_DMA_MAPPING_H |
2 | #define _ALPHA_DMA_MAPPING_H | 2 | #define _ALPHA_DMA_MAPPING_H |
3 | 3 | ||
4 | #include <linux/dma-attrs.h> | ||
4 | 5 | ||
5 | #ifdef CONFIG_PCI | 6 | extern struct dma_map_ops *dma_ops; |
6 | 7 | ||
7 | #include <linux/pci.h> | 8 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) |
9 | { | ||
10 | return dma_ops; | ||
11 | } | ||
8 | 12 | ||
9 | #define dma_map_single(dev, va, size, dir) \ | 13 | #include <asm-generic/dma-mapping-common.h> |
10 | pci_map_single(alpha_gendev_to_pci(dev), va, size, dir) | ||
11 | #define dma_unmap_single(dev, addr, size, dir) \ | ||
12 | pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir) | ||
13 | #define dma_alloc_coherent(dev, size, addr, gfp) \ | ||
14 | __pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr, gfp) | ||
15 | #define dma_free_coherent(dev, size, va, addr) \ | ||
16 | pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr) | ||
17 | #define dma_map_page(dev, page, off, size, dir) \ | ||
18 | pci_map_page(alpha_gendev_to_pci(dev), page, off, size, dir) | ||
19 | #define dma_unmap_page(dev, addr, size, dir) \ | ||
20 | pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir) | ||
21 | #define dma_map_sg(dev, sg, nents, dir) \ | ||
22 | pci_map_sg(alpha_gendev_to_pci(dev), sg, nents, dir) | ||
23 | #define dma_unmap_sg(dev, sg, nents, dir) \ | ||
24 | pci_unmap_sg(alpha_gendev_to_pci(dev), sg, nents, dir) | ||
25 | #define dma_supported(dev, mask) \ | ||
26 | pci_dma_supported(alpha_gendev_to_pci(dev), mask) | ||
27 | #define dma_mapping_error(dev, addr) \ | ||
28 | pci_dma_mapping_error(alpha_gendev_to_pci(dev), addr) | ||
29 | 14 | ||
30 | #else /* no PCI - no IOMMU. */ | 15 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, |
16 | dma_addr_t *dma_handle, gfp_t gfp) | ||
17 | { | ||
18 | return get_dma_ops(dev)->alloc_coherent(dev, size, dma_handle, gfp); | ||
19 | } | ||
31 | 20 | ||
32 | #include <asm/io.h> /* for virt_to_phys() */ | 21 | static inline void dma_free_coherent(struct device *dev, size_t size, |
22 | void *vaddr, dma_addr_t dma_handle) | ||
23 | { | ||
24 | get_dma_ops(dev)->free_coherent(dev, size, vaddr, dma_handle); | ||
25 | } | ||
33 | 26 | ||
34 | struct scatterlist; | 27 | static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) |
35 | void *dma_alloc_coherent(struct device *dev, size_t size, | 28 | { |
36 | dma_addr_t *dma_handle, gfp_t gfp); | 29 | return get_dma_ops(dev)->mapping_error(dev, dma_addr); |
37 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 30 | } |
38 | enum dma_data_direction direction); | ||
39 | 31 | ||
40 | #define dma_free_coherent(dev, size, va, addr) \ | 32 | static inline int dma_supported(struct device *dev, u64 mask) |
41 | free_pages((unsigned long)va, get_order(size)) | 33 | { |
42 | #define dma_supported(dev, mask) (mask < 0x00ffffffUL ? 0 : 1) | 34 | return get_dma_ops(dev)->dma_supported(dev, mask); |
43 | #define dma_map_single(dev, va, size, dir) virt_to_phys(va) | 35 | } |
44 | #define dma_map_page(dev, page, off, size, dir) (page_to_pa(page) + off) | ||
45 | 36 | ||
46 | #define dma_unmap_single(dev, addr, size, dir) ((void)0) | 37 | static inline int dma_set_mask(struct device *dev, u64 mask) |
47 | #define dma_unmap_page(dev, addr, size, dir) ((void)0) | 38 | { |
48 | #define dma_unmap_sg(dev, sg, nents, dir) ((void)0) | 39 | return get_dma_ops(dev)->set_dma_mask(dev, mask); |
49 | 40 | } | |
50 | #define dma_mapping_error(dev, addr) (0) | ||
51 | |||
52 | #endif /* !CONFIG_PCI */ | ||
53 | 41 | ||
54 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | 42 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) |
55 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | 43 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) |
56 | #define dma_is_consistent(d, h) (1) | 44 | #define dma_is_consistent(d, h) (1) |
57 | 45 | ||
58 | int dma_set_mask(struct device *dev, u64 mask); | ||
59 | |||
60 | #define dma_sync_single_for_cpu(dev, addr, size, dir) ((void)0) | ||
61 | #define dma_sync_single_for_device(dev, addr, size, dir) ((void)0) | ||
62 | #define dma_sync_single_range(dev, addr, off, size, dir) ((void)0) | ||
63 | #define dma_sync_sg_for_cpu(dev, sg, nents, dir) ((void)0) | ||
64 | #define dma_sync_sg_for_device(dev, sg, nents, dir) ((void)0) | ||
65 | #define dma_cache_sync(dev, va, size, dir) ((void)0) | 46 | #define dma_cache_sync(dev, va, size, dir) ((void)0) |
66 | #define dma_sync_single_range_for_cpu(dev, addr, offset, size, dir) ((void)0) | ||
67 | #define dma_sync_single_range_for_device(dev, addr, offset, size, dir) ((void)0) | ||
68 | |||
69 | #define dma_get_cache_alignment() L1_CACHE_BYTES | 47 | #define dma_get_cache_alignment() L1_CACHE_BYTES |
70 | 48 | ||
71 | #endif /* _ALPHA_DMA_MAPPING_H */ | 49 | #endif /* _ALPHA_DMA_MAPPING_H */ |
diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h index dd8dcabf160f..28d0497fd3c7 100644 --- a/arch/alpha/include/asm/pci.h +++ b/arch/alpha/include/asm/pci.h | |||
@@ -70,142 +70,11 @@ extern inline void pcibios_penalize_isa_irq(int irq, int active) | |||
70 | decisions. */ | 70 | decisions. */ |
71 | #define PCI_DMA_BUS_IS_PHYS 0 | 71 | #define PCI_DMA_BUS_IS_PHYS 0 |
72 | 72 | ||
73 | /* Allocate and map kernel buffer using consistent mode DMA for PCI | 73 | #ifdef CONFIG_PCI |
74 | device. Returns non-NULL cpu-view pointer to the buffer if | ||
75 | successful and sets *DMA_ADDRP to the pci side dma address as well, | ||
76 | else DMA_ADDRP is undefined. */ | ||
77 | |||
78 | extern void *__pci_alloc_consistent(struct pci_dev *, size_t, | ||
79 | dma_addr_t *, gfp_t); | ||
80 | static inline void * | ||
81 | pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma) | ||
82 | { | ||
83 | return __pci_alloc_consistent(dev, size, dma, GFP_ATOMIC); | ||
84 | } | ||
85 | |||
86 | /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must | ||
87 | be values that were returned from pci_alloc_consistent. SIZE must | ||
88 | be the same as what as passed into pci_alloc_consistent. | ||
89 | References to the memory and mappings associated with CPU_ADDR or | ||
90 | DMA_ADDR past this call are illegal. */ | ||
91 | |||
92 | extern void pci_free_consistent(struct pci_dev *, size_t, void *, dma_addr_t); | ||
93 | |||
94 | /* Map a single buffer of the indicate size for PCI DMA in streaming mode. | ||
95 | The 32-bit PCI bus mastering address to use is returned. Once the device | ||
96 | is given the dma address, the device owns this memory until either | ||
97 | pci_unmap_single or pci_dma_sync_single_for_cpu is performed. */ | ||
98 | |||
99 | extern dma_addr_t pci_map_single(struct pci_dev *, void *, size_t, int); | ||
100 | |||
101 | /* Likewise, but for a page instead of an address. */ | ||
102 | extern dma_addr_t pci_map_page(struct pci_dev *, struct page *, | ||
103 | unsigned long, size_t, int); | ||
104 | |||
105 | /* Test for pci_map_single or pci_map_page having generated an error. */ | ||
106 | |||
107 | static inline int | ||
108 | pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr) | ||
109 | { | ||
110 | return dma_addr == 0; | ||
111 | } | ||
112 | |||
113 | /* Unmap a single streaming mode DMA translation. The DMA_ADDR and | ||
114 | SIZE must match what was provided for in a previous pci_map_single | ||
115 | call. All other usages are undefined. After this call, reads by | ||
116 | the cpu to the buffer are guaranteed to see whatever the device | ||
117 | wrote there. */ | ||
118 | |||
119 | extern void pci_unmap_single(struct pci_dev *, dma_addr_t, size_t, int); | ||
120 | extern void pci_unmap_page(struct pci_dev *, dma_addr_t, size_t, int); | ||
121 | |||
122 | /* pci_unmap_{single,page} is not a nop, thus... */ | ||
123 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | ||
124 | dma_addr_t ADDR_NAME; | ||
125 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | ||
126 | __u32 LEN_NAME; | ||
127 | #define pci_unmap_addr(PTR, ADDR_NAME) \ | ||
128 | ((PTR)->ADDR_NAME) | ||
129 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
130 | (((PTR)->ADDR_NAME) = (VAL)) | ||
131 | #define pci_unmap_len(PTR, LEN_NAME) \ | ||
132 | ((PTR)->LEN_NAME) | ||
133 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
134 | (((PTR)->LEN_NAME) = (VAL)) | ||
135 | |||
136 | /* Map a set of buffers described by scatterlist in streaming mode for | ||
137 | PCI DMA. This is the scatter-gather version of the above | ||
138 | pci_map_single interface. Here the scatter gather list elements | ||
139 | are each tagged with the appropriate PCI dma address and length. | ||
140 | They are obtained via sg_dma_{address,length}(SG). | ||
141 | |||
142 | NOTE: An implementation may be able to use a smaller number of DMA | ||
143 | address/length pairs than there are SG table elements. (for | ||
144 | example via virtual mapping capabilities) The routine returns the | ||
145 | number of addr/length pairs actually used, at most nents. | ||
146 | |||
147 | Device ownership issues as mentioned above for pci_map_single are | ||
148 | the same here. */ | ||
149 | |||
150 | extern int pci_map_sg(struct pci_dev *, struct scatterlist *, int, int); | ||
151 | |||
152 | /* Unmap a set of streaming mode DMA translations. Again, cpu read | ||
153 | rules concerning calls here are the same as for pci_unmap_single() | ||
154 | above. */ | ||
155 | |||
156 | extern void pci_unmap_sg(struct pci_dev *, struct scatterlist *, int, int); | ||
157 | |||
158 | /* Make physical memory consistent for a single streaming mode DMA | ||
159 | translation after a transfer and device currently has ownership | ||
160 | of the buffer. | ||
161 | |||
162 | If you perform a pci_map_single() but wish to interrogate the | ||
163 | buffer using the cpu, yet do not wish to teardown the PCI dma | ||
164 | mapping, you must call this function before doing so. At the next | ||
165 | point you give the PCI dma address back to the card, you must first | ||
166 | perform a pci_dma_sync_for_device, and then the device again owns | ||
167 | the buffer. */ | ||
168 | |||
169 | static inline void | ||
170 | pci_dma_sync_single_for_cpu(struct pci_dev *dev, dma_addr_t dma_addr, | ||
171 | long size, int direction) | ||
172 | { | ||
173 | /* Nothing to do. */ | ||
174 | } | ||
175 | |||
176 | static inline void | ||
177 | pci_dma_sync_single_for_device(struct pci_dev *dev, dma_addr_t dma_addr, | ||
178 | size_t size, int direction) | ||
179 | { | ||
180 | /* Nothing to do. */ | ||
181 | } | ||
182 | |||
183 | /* Make physical memory consistent for a set of streaming mode DMA | ||
184 | translations after a transfer. The same as pci_dma_sync_single_* | ||
185 | but for a scatter-gather list, same rules and usage. */ | ||
186 | |||
187 | static inline void | ||
188 | pci_dma_sync_sg_for_cpu(struct pci_dev *dev, struct scatterlist *sg, | ||
189 | int nents, int direction) | ||
190 | { | ||
191 | /* Nothing to do. */ | ||
192 | } | ||
193 | |||
194 | static inline void | ||
195 | pci_dma_sync_sg_for_device(struct pci_dev *dev, struct scatterlist *sg, | ||
196 | int nents, int direction) | ||
197 | { | ||
198 | /* Nothing to do. */ | ||
199 | } | ||
200 | |||
201 | /* Return whether the given PCI device DMA address mask can | ||
202 | be supported properly. For example, if your device can | ||
203 | only drive the low 24-bits during PCI bus mastering, then | ||
204 | you would pass 0x00ffffff as the mask to this function. */ | ||
205 | 74 | ||
206 | extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask); | 75 | /* implement the pci_ DMA API in terms of the generic device dma_ one */ |
76 | #include <asm-generic/pci-dma-compat.h> | ||
207 | 77 | ||
208 | #ifdef CONFIG_PCI | ||
209 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, | 78 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, |
210 | enum pci_dma_burst_strategy *strat, | 79 | enum pci_dma_burst_strategy *strat, |
211 | unsigned long *strategy_parameter) | 80 | unsigned long *strategy_parameter) |
@@ -244,8 +113,6 @@ static inline int pci_proc_domain(struct pci_bus *bus) | |||
244 | return hose->need_domain_info; | 113 | return hose->need_domain_info; |
245 | } | 114 | } |
246 | 115 | ||
247 | struct pci_dev *alpha_gendev_to_pci(struct device *dev); | ||
248 | |||
249 | #endif /* __KERNEL__ */ | 116 | #endif /* __KERNEL__ */ |
250 | 117 | ||
251 | /* Values for the `which' argument to sys_pciconfig_iobase. */ | 118 | /* Values for the `which' argument to sys_pciconfig_iobase. */ |
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h index 32c7a5cddd59..65cf3e28e2f4 100644 --- a/arch/alpha/include/asm/ptrace.h +++ b/arch/alpha/include/asm/ptrace.h | |||
@@ -68,6 +68,7 @@ struct switch_stack { | |||
68 | 68 | ||
69 | #ifdef __KERNEL__ | 69 | #ifdef __KERNEL__ |
70 | 70 | ||
71 | #define arch_has_single_step() (1) | ||
71 | #define user_mode(regs) (((regs)->ps & 8) != 0) | 72 | #define user_mode(regs) (((regs)->ps & 8) != 0) |
72 | #define instruction_pointer(regs) ((regs)->pc) | 73 | #define instruction_pointer(regs) ((regs)->pc) |
73 | #define profile_pc(regs) instruction_pointer(regs) | 74 | #define profile_pc(regs) instruction_pointer(regs) |
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c index c19a376520f4..823a540f9f5b 100644 --- a/arch/alpha/kernel/pci-noop.c +++ b/arch/alpha/kernel/pci-noop.c | |||
@@ -106,58 +106,8 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn, | |||
106 | return -ENODEV; | 106 | return -ENODEV; |
107 | } | 107 | } |
108 | 108 | ||
109 | /* Stubs for the routines in pci_iommu.c: */ | 109 | static void *alpha_noop_alloc_coherent(struct device *dev, size_t size, |
110 | 110 | dma_addr_t *dma_handle, gfp_t gfp) | |
111 | void * | ||
112 | __pci_alloc_consistent(struct pci_dev *pdev, size_t size, | ||
113 | dma_addr_t *dma_addrp, gfp_t gfp) | ||
114 | { | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | void | ||
119 | pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, | ||
120 | dma_addr_t dma_addr) | ||
121 | { | ||
122 | } | ||
123 | |||
124 | dma_addr_t | ||
125 | pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, | ||
126 | int direction) | ||
127 | { | ||
128 | return (dma_addr_t) 0; | ||
129 | } | ||
130 | |||
131 | void | ||
132 | pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | ||
133 | int direction) | ||
134 | { | ||
135 | } | ||
136 | |||
137 | int | ||
138 | pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | ||
139 | int direction) | ||
140 | { | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | void | ||
145 | pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | ||
146 | int direction) | ||
147 | { | ||
148 | } | ||
149 | |||
150 | int | ||
151 | pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) | ||
152 | { | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | /* Generic DMA mapping functions: */ | ||
157 | |||
158 | void * | ||
159 | dma_alloc_coherent(struct device *dev, size_t size, | ||
160 | dma_addr_t *dma_handle, gfp_t gfp) | ||
161 | { | 111 | { |
162 | void *ret; | 112 | void *ret; |
163 | 113 | ||
@@ -171,11 +121,22 @@ dma_alloc_coherent(struct device *dev, size_t size, | |||
171 | return ret; | 121 | return ret; |
172 | } | 122 | } |
173 | 123 | ||
174 | EXPORT_SYMBOL(dma_alloc_coherent); | 124 | static void alpha_noop_free_coherent(struct device *dev, size_t size, |
125 | void *cpu_addr, dma_addr_t dma_addr) | ||
126 | { | ||
127 | free_pages((unsigned long)cpu_addr, get_order(size)); | ||
128 | } | ||
129 | |||
130 | static dma_addr_t alpha_noop_map_page(struct device *dev, struct page *page, | ||
131 | unsigned long offset, size_t size, | ||
132 | enum dma_data_direction dir, | ||
133 | struct dma_attrs *attrs) | ||
134 | { | ||
135 | return page_to_pa(page) + offset; | ||
136 | } | ||
175 | 137 | ||
176 | int | 138 | static int alpha_noop_map_sg(struct device *dev, struct scatterlist *sgl, int nents, |
177 | dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents, | 139 | enum dma_data_direction dir, struct dma_attrs *attrs) |
178 | enum dma_data_direction direction) | ||
179 | { | 140 | { |
180 | int i; | 141 | int i; |
181 | struct scatterlist *sg; | 142 | struct scatterlist *sg; |
@@ -192,19 +153,37 @@ dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents, | |||
192 | return nents; | 153 | return nents; |
193 | } | 154 | } |
194 | 155 | ||
195 | EXPORT_SYMBOL(dma_map_sg); | 156 | static int alpha_noop_mapping_error(struct device *dev, dma_addr_t dma_addr) |
157 | { | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int alpha_noop_supported(struct device *dev, u64 mask) | ||
162 | { | ||
163 | return mask < 0x00ffffffUL ? 0 : 1; | ||
164 | } | ||
196 | 165 | ||
197 | int | 166 | static int alpha_noop_set_mask(struct device *dev, u64 mask) |
198 | dma_set_mask(struct device *dev, u64 mask) | ||
199 | { | 167 | { |
200 | if (!dev->dma_mask || !dma_supported(dev, mask)) | 168 | if (!dev->dma_mask || !dma_supported(dev, mask)) |
201 | return -EIO; | 169 | return -EIO; |
202 | 170 | ||
203 | *dev->dma_mask = mask; | 171 | *dev->dma_mask = mask; |
204 | |||
205 | return 0; | 172 | return 0; |
206 | } | 173 | } |
207 | EXPORT_SYMBOL(dma_set_mask); | 174 | |
175 | struct dma_map_ops alpha_noop_ops = { | ||
176 | .alloc_coherent = alpha_noop_alloc_coherent, | ||
177 | .free_coherent = alpha_noop_free_coherent, | ||
178 | .map_page = alpha_noop_map_page, | ||
179 | .map_sg = alpha_noop_map_sg, | ||
180 | .mapping_error = alpha_noop_mapping_error, | ||
181 | .dma_supported = alpha_noop_supported, | ||
182 | .set_dma_mask = alpha_noop_set_mask, | ||
183 | }; | ||
184 | |||
185 | struct dma_map_ops *dma_ops = &alpha_noop_ops; | ||
186 | EXPORT_SYMBOL(dma_ops); | ||
208 | 187 | ||
209 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | 188 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) |
210 | { | 189 | { |
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index 8449504f5e0b..ce9e54c887fa 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c | |||
@@ -216,10 +216,30 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n) | |||
216 | for (i = 0; i < n; ++i) | 216 | for (i = 0; i < n; ++i) |
217 | p[i] = 0; | 217 | p[i] = 0; |
218 | } | 218 | } |
219 | 219 | ||
220 | /* True if the machine supports DAC addressing, and DEV can | 220 | /* |
221 | make use of it given MASK. */ | 221 | * True if the machine supports DAC addressing, and DEV can |
222 | static int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask); | 222 | * make use of it given MASK. |
223 | */ | ||
224 | static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask) | ||
225 | { | ||
226 | dma64_addr_t dac_offset = alpha_mv.pci_dac_offset; | ||
227 | int ok = 1; | ||
228 | |||
229 | /* If this is not set, the machine doesn't support DAC at all. */ | ||
230 | if (dac_offset == 0) | ||
231 | ok = 0; | ||
232 | |||
233 | /* The device has to be able to address our DAC bit. */ | ||
234 | if ((dac_offset & dev->dma_mask) != dac_offset) | ||
235 | ok = 0; | ||
236 | |||
237 | /* If both conditions above are met, we are fine. */ | ||
238 | DBGA("pci_dac_dma_supported %s from %p\n", | ||
239 | ok ? "yes" : "no", __builtin_return_address(0)); | ||
240 | |||
241 | return ok; | ||
242 | } | ||
223 | 243 | ||
224 | /* Map a single buffer of the indicated size for PCI DMA in streaming | 244 | /* Map a single buffer of the indicated size for PCI DMA in streaming |
225 | mode. The 32-bit PCI bus mastering address to use is returned. | 245 | mode. The 32-bit PCI bus mastering address to use is returned. |
@@ -301,23 +321,36 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, | |||
301 | return ret; | 321 | return ret; |
302 | } | 322 | } |
303 | 323 | ||
304 | dma_addr_t | 324 | /* Helper for generic DMA-mapping functions. */ |
305 | pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, int dir) | 325 | static struct pci_dev *alpha_gendev_to_pci(struct device *dev) |
306 | { | 326 | { |
307 | int dac_allowed; | 327 | if (dev && dev->bus == &pci_bus_type) |
328 | return to_pci_dev(dev); | ||
308 | 329 | ||
309 | if (dir == PCI_DMA_NONE) | 330 | /* Assume that non-PCI devices asking for DMA are either ISA or EISA, |
310 | BUG(); | 331 | BUG() otherwise. */ |
332 | BUG_ON(!isa_bridge); | ||
311 | 333 | ||
312 | dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; | 334 | /* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA |
313 | return pci_map_single_1(pdev, cpu_addr, size, dac_allowed); | 335 | bridge is bus master then). */ |
336 | if (!dev || !dev->dma_mask || !*dev->dma_mask) | ||
337 | return isa_bridge; | ||
338 | |||
339 | /* For EISA bus masters, return isa_bridge (it might have smaller | ||
340 | dma_mask due to wiring limitations). */ | ||
341 | if (*dev->dma_mask >= isa_bridge->dma_mask) | ||
342 | return isa_bridge; | ||
343 | |||
344 | /* This assumes ISA bus master with dma_mask 0xffffff. */ | ||
345 | return NULL; | ||
314 | } | 346 | } |
315 | EXPORT_SYMBOL(pci_map_single); | ||
316 | 347 | ||
317 | dma_addr_t | 348 | static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page, |
318 | pci_map_page(struct pci_dev *pdev, struct page *page, unsigned long offset, | 349 | unsigned long offset, size_t size, |
319 | size_t size, int dir) | 350 | enum dma_data_direction dir, |
351 | struct dma_attrs *attrs) | ||
320 | { | 352 | { |
353 | struct pci_dev *pdev = alpha_gendev_to_pci(dev); | ||
321 | int dac_allowed; | 354 | int dac_allowed; |
322 | 355 | ||
323 | if (dir == PCI_DMA_NONE) | 356 | if (dir == PCI_DMA_NONE) |
@@ -327,7 +360,6 @@ pci_map_page(struct pci_dev *pdev, struct page *page, unsigned long offset, | |||
327 | return pci_map_single_1(pdev, (char *)page_address(page) + offset, | 360 | return pci_map_single_1(pdev, (char *)page_address(page) + offset, |
328 | size, dac_allowed); | 361 | size, dac_allowed); |
329 | } | 362 | } |
330 | EXPORT_SYMBOL(pci_map_page); | ||
331 | 363 | ||
332 | /* Unmap a single streaming mode DMA translation. The DMA_ADDR and | 364 | /* Unmap a single streaming mode DMA translation. The DMA_ADDR and |
333 | SIZE must match what was provided for in a previous pci_map_single | 365 | SIZE must match what was provided for in a previous pci_map_single |
@@ -335,16 +367,17 @@ EXPORT_SYMBOL(pci_map_page); | |||
335 | the cpu to the buffer are guaranteed to see whatever the device | 367 | the cpu to the buffer are guaranteed to see whatever the device |
336 | wrote there. */ | 368 | wrote there. */ |
337 | 369 | ||
338 | void | 370 | static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr, |
339 | pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | 371 | size_t size, enum dma_data_direction dir, |
340 | int direction) | 372 | struct dma_attrs *attrs) |
341 | { | 373 | { |
342 | unsigned long flags; | 374 | unsigned long flags; |
375 | struct pci_dev *pdev = alpha_gendev_to_pci(dev); | ||
343 | struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose; | 376 | struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose; |
344 | struct pci_iommu_arena *arena; | 377 | struct pci_iommu_arena *arena; |
345 | long dma_ofs, npages; | 378 | long dma_ofs, npages; |
346 | 379 | ||
347 | if (direction == PCI_DMA_NONE) | 380 | if (dir == PCI_DMA_NONE) |
348 | BUG(); | 381 | BUG(); |
349 | 382 | ||
350 | if (dma_addr >= __direct_map_base | 383 | if (dma_addr >= __direct_map_base |
@@ -393,25 +426,16 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | |||
393 | DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %p\n", | 426 | DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %p\n", |
394 | dma_addr, size, npages, __builtin_return_address(0)); | 427 | dma_addr, size, npages, __builtin_return_address(0)); |
395 | } | 428 | } |
396 | EXPORT_SYMBOL(pci_unmap_single); | ||
397 | |||
398 | void | ||
399 | pci_unmap_page(struct pci_dev *pdev, dma_addr_t dma_addr, | ||
400 | size_t size, int direction) | ||
401 | { | ||
402 | pci_unmap_single(pdev, dma_addr, size, direction); | ||
403 | } | ||
404 | EXPORT_SYMBOL(pci_unmap_page); | ||
405 | 429 | ||
406 | /* Allocate and map kernel buffer using consistent mode DMA for PCI | 430 | /* Allocate and map kernel buffer using consistent mode DMA for PCI |
407 | device. Returns non-NULL cpu-view pointer to the buffer if | 431 | device. Returns non-NULL cpu-view pointer to the buffer if |
408 | successful and sets *DMA_ADDRP to the pci side dma address as well, | 432 | successful and sets *DMA_ADDRP to the pci side dma address as well, |
409 | else DMA_ADDRP is undefined. */ | 433 | else DMA_ADDRP is undefined. */ |
410 | 434 | ||
411 | void * | 435 | static void *alpha_pci_alloc_coherent(struct device *dev, size_t size, |
412 | __pci_alloc_consistent(struct pci_dev *pdev, size_t size, | 436 | dma_addr_t *dma_addrp, gfp_t gfp) |
413 | dma_addr_t *dma_addrp, gfp_t gfp) | ||
414 | { | 437 | { |
438 | struct pci_dev *pdev = alpha_gendev_to_pci(dev); | ||
415 | void *cpu_addr; | 439 | void *cpu_addr; |
416 | long order = get_order(size); | 440 | long order = get_order(size); |
417 | 441 | ||
@@ -439,13 +463,12 @@ try_again: | |||
439 | gfp |= GFP_DMA; | 463 | gfp |= GFP_DMA; |
440 | goto try_again; | 464 | goto try_again; |
441 | } | 465 | } |
442 | 466 | ||
443 | DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %p\n", | 467 | DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %p\n", |
444 | size, cpu_addr, *dma_addrp, __builtin_return_address(0)); | 468 | size, cpu_addr, *dma_addrp, __builtin_return_address(0)); |
445 | 469 | ||
446 | return cpu_addr; | 470 | return cpu_addr; |
447 | } | 471 | } |
448 | EXPORT_SYMBOL(__pci_alloc_consistent); | ||
449 | 472 | ||
450 | /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must | 473 | /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must |
451 | be values that were returned from pci_alloc_consistent. SIZE must | 474 | be values that were returned from pci_alloc_consistent. SIZE must |
@@ -453,17 +476,16 @@ EXPORT_SYMBOL(__pci_alloc_consistent); | |||
453 | References to the memory and mappings associated with CPU_ADDR or | 476 | References to the memory and mappings associated with CPU_ADDR or |
454 | DMA_ADDR past this call are illegal. */ | 477 | DMA_ADDR past this call are illegal. */ |
455 | 478 | ||
456 | void | 479 | static void alpha_pci_free_coherent(struct device *dev, size_t size, |
457 | pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, | 480 | void *cpu_addr, dma_addr_t dma_addr) |
458 | dma_addr_t dma_addr) | ||
459 | { | 481 | { |
482 | struct pci_dev *pdev = alpha_gendev_to_pci(dev); | ||
460 | pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL); | 483 | pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL); |
461 | free_pages((unsigned long)cpu_addr, get_order(size)); | 484 | free_pages((unsigned long)cpu_addr, get_order(size)); |
462 | 485 | ||
463 | DBGA2("pci_free_consistent: [%llx,%zx] from %p\n", | 486 | DBGA2("pci_free_consistent: [%llx,%zx] from %p\n", |
464 | dma_addr, size, __builtin_return_address(0)); | 487 | dma_addr, size, __builtin_return_address(0)); |
465 | } | 488 | } |
466 | EXPORT_SYMBOL(pci_free_consistent); | ||
467 | 489 | ||
468 | /* Classify the elements of the scatterlist. Write dma_address | 490 | /* Classify the elements of the scatterlist. Write dma_address |
469 | of each element with: | 491 | of each element with: |
@@ -626,23 +648,21 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end, | |||
626 | return 1; | 648 | return 1; |
627 | } | 649 | } |
628 | 650 | ||
629 | int | 651 | static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg, |
630 | pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | 652 | int nents, enum dma_data_direction dir, |
631 | int direction) | 653 | struct dma_attrs *attrs) |
632 | { | 654 | { |
655 | struct pci_dev *pdev = alpha_gendev_to_pci(dev); | ||
633 | struct scatterlist *start, *end, *out; | 656 | struct scatterlist *start, *end, *out; |
634 | struct pci_controller *hose; | 657 | struct pci_controller *hose; |
635 | struct pci_iommu_arena *arena; | 658 | struct pci_iommu_arena *arena; |
636 | dma_addr_t max_dma; | 659 | dma_addr_t max_dma; |
637 | int dac_allowed; | 660 | int dac_allowed; |
638 | struct device *dev; | ||
639 | 661 | ||
640 | if (direction == PCI_DMA_NONE) | 662 | if (dir == PCI_DMA_NONE) |
641 | BUG(); | 663 | BUG(); |
642 | 664 | ||
643 | dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; | 665 | dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; |
644 | |||
645 | dev = pdev ? &pdev->dev : NULL; | ||
646 | 666 | ||
647 | /* Fast path single entry scatterlists. */ | 667 | /* Fast path single entry scatterlists. */ |
648 | if (nents == 1) { | 668 | if (nents == 1) { |
@@ -699,19 +719,19 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | |||
699 | /* Some allocation failed while mapping the scatterlist | 719 | /* Some allocation failed while mapping the scatterlist |
700 | entries. Unmap them now. */ | 720 | entries. Unmap them now. */ |
701 | if (out > start) | 721 | if (out > start) |
702 | pci_unmap_sg(pdev, start, out - start, direction); | 722 | pci_unmap_sg(pdev, start, out - start, dir); |
703 | return 0; | 723 | return 0; |
704 | } | 724 | } |
705 | EXPORT_SYMBOL(pci_map_sg); | ||
706 | 725 | ||
707 | /* Unmap a set of streaming mode DMA translations. Again, cpu read | 726 | /* Unmap a set of streaming mode DMA translations. Again, cpu read |
708 | rules concerning calls here are the same as for pci_unmap_single() | 727 | rules concerning calls here are the same as for pci_unmap_single() |
709 | above. */ | 728 | above. */ |
710 | 729 | ||
711 | void | 730 | static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg, |
712 | pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | 731 | int nents, enum dma_data_direction dir, |
713 | int direction) | 732 | struct dma_attrs *attrs) |
714 | { | 733 | { |
734 | struct pci_dev *pdev = alpha_gendev_to_pci(dev); | ||
715 | unsigned long flags; | 735 | unsigned long flags; |
716 | struct pci_controller *hose; | 736 | struct pci_controller *hose; |
717 | struct pci_iommu_arena *arena; | 737 | struct pci_iommu_arena *arena; |
@@ -719,7 +739,7 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | |||
719 | dma_addr_t max_dma; | 739 | dma_addr_t max_dma; |
720 | dma_addr_t fbeg, fend; | 740 | dma_addr_t fbeg, fend; |
721 | 741 | ||
722 | if (direction == PCI_DMA_NONE) | 742 | if (dir == PCI_DMA_NONE) |
723 | BUG(); | 743 | BUG(); |
724 | 744 | ||
725 | if (! alpha_mv.mv_pci_tbi) | 745 | if (! alpha_mv.mv_pci_tbi) |
@@ -783,15 +803,13 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | |||
783 | 803 | ||
784 | DBGA("pci_unmap_sg: %ld entries\n", nents - (end - sg)); | 804 | DBGA("pci_unmap_sg: %ld entries\n", nents - (end - sg)); |
785 | } | 805 | } |
786 | EXPORT_SYMBOL(pci_unmap_sg); | ||
787 | |||
788 | 806 | ||
789 | /* Return whether the given PCI device DMA address mask can be | 807 | /* Return whether the given PCI device DMA address mask can be |
790 | supported properly. */ | 808 | supported properly. */ |
791 | 809 | ||
792 | int | 810 | static int alpha_pci_supported(struct device *dev, u64 mask) |
793 | pci_dma_supported(struct pci_dev *pdev, u64 mask) | ||
794 | { | 811 | { |
812 | struct pci_dev *pdev = alpha_gendev_to_pci(dev); | ||
795 | struct pci_controller *hose; | 813 | struct pci_controller *hose; |
796 | struct pci_iommu_arena *arena; | 814 | struct pci_iommu_arena *arena; |
797 | 815 | ||
@@ -818,7 +836,6 @@ pci_dma_supported(struct pci_dev *pdev, u64 mask) | |||
818 | 836 | ||
819 | return 0; | 837 | return 0; |
820 | } | 838 | } |
821 | EXPORT_SYMBOL(pci_dma_supported); | ||
822 | 839 | ||
823 | 840 | ||
824 | /* | 841 | /* |
@@ -918,66 +935,32 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count) | |||
918 | return 0; | 935 | return 0; |
919 | } | 936 | } |
920 | 937 | ||
921 | /* True if the machine supports DAC addressing, and DEV can | 938 | static int alpha_pci_mapping_error(struct device *dev, dma_addr_t dma_addr) |
922 | make use of it given MASK. */ | ||
923 | |||
924 | static int | ||
925 | pci_dac_dma_supported(struct pci_dev *dev, u64 mask) | ||
926 | { | ||
927 | dma64_addr_t dac_offset = alpha_mv.pci_dac_offset; | ||
928 | int ok = 1; | ||
929 | |||
930 | /* If this is not set, the machine doesn't support DAC at all. */ | ||
931 | if (dac_offset == 0) | ||
932 | ok = 0; | ||
933 | |||
934 | /* The device has to be able to address our DAC bit. */ | ||
935 | if ((dac_offset & dev->dma_mask) != dac_offset) | ||
936 | ok = 0; | ||
937 | |||
938 | /* If both conditions above are met, we are fine. */ | ||
939 | DBGA("pci_dac_dma_supported %s from %p\n", | ||
940 | ok ? "yes" : "no", __builtin_return_address(0)); | ||
941 | |||
942 | return ok; | ||
943 | } | ||
944 | |||
945 | /* Helper for generic DMA-mapping functions. */ | ||
946 | |||
947 | struct pci_dev * | ||
948 | alpha_gendev_to_pci(struct device *dev) | ||
949 | { | 939 | { |
950 | if (dev && dev->bus == &pci_bus_type) | 940 | return dma_addr == 0; |
951 | return to_pci_dev(dev); | ||
952 | |||
953 | /* Assume that non-PCI devices asking for DMA are either ISA or EISA, | ||
954 | BUG() otherwise. */ | ||
955 | BUG_ON(!isa_bridge); | ||
956 | |||
957 | /* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA | ||
958 | bridge is bus master then). */ | ||
959 | if (!dev || !dev->dma_mask || !*dev->dma_mask) | ||
960 | return isa_bridge; | ||
961 | |||
962 | /* For EISA bus masters, return isa_bridge (it might have smaller | ||
963 | dma_mask due to wiring limitations). */ | ||
964 | if (*dev->dma_mask >= isa_bridge->dma_mask) | ||
965 | return isa_bridge; | ||
966 | |||
967 | /* This assumes ISA bus master with dma_mask 0xffffff. */ | ||
968 | return NULL; | ||
969 | } | 941 | } |
970 | EXPORT_SYMBOL(alpha_gendev_to_pci); | ||
971 | 942 | ||
972 | int | 943 | static int alpha_pci_set_mask(struct device *dev, u64 mask) |
973 | dma_set_mask(struct device *dev, u64 mask) | ||
974 | { | 944 | { |
975 | if (!dev->dma_mask || | 945 | if (!dev->dma_mask || |
976 | !pci_dma_supported(alpha_gendev_to_pci(dev), mask)) | 946 | !pci_dma_supported(alpha_gendev_to_pci(dev), mask)) |
977 | return -EIO; | 947 | return -EIO; |
978 | 948 | ||
979 | *dev->dma_mask = mask; | 949 | *dev->dma_mask = mask; |
980 | |||
981 | return 0; | 950 | return 0; |
982 | } | 951 | } |
983 | EXPORT_SYMBOL(dma_set_mask); | 952 | |
953 | struct dma_map_ops alpha_pci_ops = { | ||
954 | .alloc_coherent = alpha_pci_alloc_coherent, | ||
955 | .free_coherent = alpha_pci_free_coherent, | ||
956 | .map_page = alpha_pci_map_page, | ||
957 | .unmap_page = alpha_pci_unmap_page, | ||
958 | .map_sg = alpha_pci_map_sg, | ||
959 | .unmap_sg = alpha_pci_unmap_sg, | ||
960 | .mapping_error = alpha_pci_mapping_error, | ||
961 | .dma_supported = alpha_pci_supported, | ||
962 | .set_dma_mask = alpha_pci_set_mask, | ||
963 | }; | ||
964 | |||
965 | struct dma_map_ops *dma_ops = &alpha_pci_ops; | ||
966 | EXPORT_SYMBOL(dma_ops); | ||
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index e072041d19f8..9acadc6b16a0 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c | |||
@@ -249,6 +249,17 @@ ptrace_cancel_bpt(struct task_struct * child) | |||
249 | return (nsaved != 0); | 249 | return (nsaved != 0); |
250 | } | 250 | } |
251 | 251 | ||
252 | void user_enable_single_step(struct task_struct *child) | ||
253 | { | ||
254 | /* Mark single stepping. */ | ||
255 | task_thread_info(child)->bpt_nsaved = -1; | ||
256 | } | ||
257 | |||
258 | void user_disable_single_step(struct task_struct *child) | ||
259 | { | ||
260 | ptrace_cancel_bpt(child); | ||
261 | } | ||
262 | |||
252 | /* | 263 | /* |
253 | * Called by kernel/ptrace.c when detaching.. | 264 | * Called by kernel/ptrace.c when detaching.. |
254 | * | 265 | * |
@@ -256,7 +267,7 @@ ptrace_cancel_bpt(struct task_struct * child) | |||
256 | */ | 267 | */ |
257 | void ptrace_disable(struct task_struct *child) | 268 | void ptrace_disable(struct task_struct *child) |
258 | { | 269 | { |
259 | ptrace_cancel_bpt(child); | 270 | user_disable_single_step(child); |
260 | } | 271 | } |
261 | 272 | ||
262 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 273 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
@@ -295,52 +306,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
295 | DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data)); | 306 | DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data)); |
296 | ret = put_reg(child, addr, data); | 307 | ret = put_reg(child, addr, data); |
297 | break; | 308 | break; |
298 | |||
299 | case PTRACE_SYSCALL: | ||
300 | /* continue and stop at next (return from) syscall */ | ||
301 | case PTRACE_CONT: /* restart after signal. */ | ||
302 | ret = -EIO; | ||
303 | if (!valid_signal(data)) | ||
304 | break; | ||
305 | if (request == PTRACE_SYSCALL) | ||
306 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
307 | else | ||
308 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
309 | child->exit_code = data; | ||
310 | /* make sure single-step breakpoint is gone. */ | ||
311 | ptrace_cancel_bpt(child); | ||
312 | wake_up_process(child); | ||
313 | ret = 0; | ||
314 | break; | ||
315 | |||
316 | /* | ||
317 | * Make the child exit. Best I can do is send it a sigkill. | ||
318 | * perhaps it should be put in the status that it wants to | ||
319 | * exit. | ||
320 | */ | ||
321 | case PTRACE_KILL: | ||
322 | ret = 0; | ||
323 | if (child->exit_state == EXIT_ZOMBIE) | ||
324 | break; | ||
325 | child->exit_code = SIGKILL; | ||
326 | /* make sure single-step breakpoint is gone. */ | ||
327 | ptrace_cancel_bpt(child); | ||
328 | wake_up_process(child); | ||
329 | break; | ||
330 | |||
331 | case PTRACE_SINGLESTEP: /* execute single instruction. */ | ||
332 | ret = -EIO; | ||
333 | if (!valid_signal(data)) | ||
334 | break; | ||
335 | /* Mark single stepping. */ | ||
336 | task_thread_info(child)->bpt_nsaved = -1; | ||
337 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
338 | child->exit_code = data; | ||
339 | wake_up_process(child); | ||
340 | /* give it a chance to run. */ | ||
341 | ret = 0; | ||
342 | break; | ||
343 | |||
344 | default: | 309 | default: |
345 | ret = ptrace_request(child, request, addr, data); | 310 | ret = ptrace_request(child, request, addr, data); |
346 | break; | 311 | break; |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e12d700d985a..cadfe2ee66a5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -155,6 +155,9 @@ config ARCH_MAY_HAVE_PC_FDC | |||
155 | config ZONE_DMA | 155 | config ZONE_DMA |
156 | bool | 156 | bool |
157 | 157 | ||
158 | config NEED_DMA_MAP_STATE | ||
159 | def_bool y | ||
160 | |||
158 | config GENERIC_ISA_DMA | 161 | config GENERIC_ISA_DMA |
159 | bool | 162 | bool |
160 | 163 | ||
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 2793447621c3..ee1d3b85eb65 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c | |||
@@ -272,33 +272,6 @@ int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) | |||
272 | ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); | 272 | ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); |
273 | } | 273 | } |
274 | 274 | ||
275 | /* | ||
276 | * We override these so we properly do dmabounce otherwise drivers | ||
277 | * are able to set the dma_mask to 0xffffffff and we can no longer | ||
278 | * trap bounces. :( | ||
279 | * | ||
280 | * We just return true on everyhing except for < 64MB in which case | ||
281 | * we will fail miseralby and die since we can't handle that case. | ||
282 | */ | ||
283 | int pci_set_dma_mask(struct pci_dev *dev, u64 mask) | ||
284 | { | ||
285 | dev_dbg(&dev->dev, "%s: %llx\n", __func__, mask); | ||
286 | if (mask >= PHYS_OFFSET + SZ_64M - 1) | ||
287 | return 0; | ||
288 | |||
289 | return -EIO; | ||
290 | } | ||
291 | |||
292 | int | ||
293 | pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | ||
294 | { | ||
295 | dev_dbg(&dev->dev, "%s: %llx\n", __func__, mask); | ||
296 | if (mask >= PHYS_OFFSET + SZ_64M - 1) | ||
297 | return 0; | ||
298 | |||
299 | return -EIO; | ||
300 | } | ||
301 | |||
302 | int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) | 275 | int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) |
303 | { | 276 | { |
304 | it8152_io.start = IT8152_IO_BASE + 0x12000; | 277 | it8152_io.start = IT8152_IO_BASE + 0x12000; |
diff --git a/arch/arm/configs/nuc950_defconfig b/arch/arm/configs/nuc950_defconfig index 97300ec478dd..51cc2a260cbb 100644 --- a/arch/arm/configs/nuc950_defconfig +++ b/arch/arm/configs/nuc950_defconfig | |||
@@ -590,8 +590,40 @@ CONFIG_SSB_POSSIBLE=y | |||
590 | # | 590 | # |
591 | # CONFIG_VGASTATE is not set | 591 | # CONFIG_VGASTATE is not set |
592 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | 592 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set |
593 | # CONFIG_FB is not set | ||
594 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | 593 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set |
594 | CONFIG_FB=y | ||
595 | # CONFIG_FIRMWARE_EDID is not set | ||
596 | # CONFIG_FB_DDC is not set | ||
597 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
598 | CONFIG_FB_CFB_FILLRECT=y | ||
599 | CONFIG_FB_CFB_COPYAREA=y | ||
600 | CONFIG_FB_CFB_IMAGEBLIT=y | ||
601 | # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | ||
602 | # CONFIG_FB_SYS_FILLRECT is not set | ||
603 | # CONFIG_FB_SYS_COPYAREA is not set | ||
604 | # CONFIG_FB_SYS_IMAGEBLIT is not set | ||
605 | # CONFIG_FB_FOREIGN_ENDIAN is not set | ||
606 | # CONFIG_FB_SYS_FOPS is not set | ||
607 | # CONFIG_FB_SVGALIB is not set | ||
608 | # CONFIG_FB_MACMODES is not set | ||
609 | # CONFIG_FB_BACKLIGHT is not set | ||
610 | # CONFIG_FB_MODE_HELPERS is not set | ||
611 | # CONFIG_FB_TILEBLITTING is not set | ||
612 | |||
613 | # | ||
614 | # Frame buffer hardware drivers | ||
615 | # | ||
616 | # CONFIG_FB_S1D13XXX is not set | ||
617 | CONFIG_FB_NUC900=y | ||
618 | CONFIG_GPM1040A0_320X240=y | ||
619 | CONFIG_FB_NUC900_DEBUG=y | ||
620 | # CONFIG_FB_VIRTUAL is not set | ||
621 | # CONFIG_FB_METRONOME is not set | ||
622 | # CONFIG_FB_MB862XX is not set | ||
623 | # CONFIG_FB_BROADSHEET is not set | ||
624 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
625 | |||
626 | |||
595 | 627 | ||
596 | # | 628 | # |
597 | # Display device support | 629 | # Display device support |
@@ -603,6 +635,25 @@ CONFIG_SSB_POSSIBLE=y | |||
603 | # | 635 | # |
604 | # CONFIG_VGA_CONSOLE is not set | 636 | # CONFIG_VGA_CONSOLE is not set |
605 | CONFIG_DUMMY_CONSOLE=y | 637 | CONFIG_DUMMY_CONSOLE=y |
638 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
639 | CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y | ||
640 | # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | ||
641 | CONFIG_FONTS=y | ||
642 | # CONFIG_FONT_8x8 is not set | ||
643 | CONFIG_FONT_8x16=y | ||
644 | # CONFIG_FONT_6x11 is not set | ||
645 | # CONFIG_FONT_7x14 is not set | ||
646 | # CONFIG_FONT_PEARL_8x8 is not set | ||
647 | # CONFIG_FONT_ACORN_8x8 is not set | ||
648 | # CONFIG_FONT_MINI_4x6 is not set | ||
649 | # CONFIG_FONT_SUN8x16 is not set | ||
650 | # CONFIG_FONT_SUN12x22 is not set | ||
651 | # CONFIG_FONT_10x18 is not set | ||
652 | CONFIG_LOGO=y | ||
653 | # CONFIG_LOGO_LINUX_MONO is not set | ||
654 | # CONFIG_LOGO_LINUX_VGA16 is not set | ||
655 | CONFIG_LOGO_LINUX_CLUT224=y | ||
656 | |||
606 | # CONFIG_SOUND is not set | 657 | # CONFIG_SOUND is not set |
607 | # CONFIG_HID_SUPPORT is not set | 658 | # CONFIG_HID_SUPPORT is not set |
608 | CONFIG_USB_SUPPORT=y | 659 | CONFIG_USB_SUPPORT=y |
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 256ee1c9f51a..69ce0727edb5 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -128,6 +128,14 @@ static inline int dma_supported(struct device *dev, u64 mask) | |||
128 | 128 | ||
129 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | 129 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) |
130 | { | 130 | { |
131 | #ifdef CONFIG_DMABOUNCE | ||
132 | if (dev->archdata.dmabounce) { | ||
133 | if (dma_mask >= ISA_DMA_THRESHOLD) | ||
134 | return 0; | ||
135 | else | ||
136 | return -EIO; | ||
137 | } | ||
138 | #endif | ||
131 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | 139 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) |
132 | return -EIO; | 140 | return -EIO; |
133 | 141 | ||
diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index 226cddd2fb65..47980118d0a5 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h | |||
@@ -30,17 +30,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) | |||
30 | */ | 30 | */ |
31 | #define PCI_DMA_BUS_IS_PHYS (1) | 31 | #define PCI_DMA_BUS_IS_PHYS (1) |
32 | 32 | ||
33 | /* | ||
34 | * Whether pci_unmap_{single,page} is a nop depends upon the | ||
35 | * configuration. | ||
36 | */ | ||
37 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME; | ||
38 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME; | ||
39 | #define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) | ||
40 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) | ||
41 | #define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) | ||
42 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) | ||
43 | |||
44 | #ifdef CONFIG_PCI | 33 | #ifdef CONFIG_PCI |
45 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, | 34 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, |
46 | enum pci_dma_burst_strategy *strat, | 35 | enum pci_dma_burst_strategy *strat, |
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index eec6e897ceb2..9dcb11e59026 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h | |||
@@ -128,6 +128,8 @@ struct pt_regs { | |||
128 | 128 | ||
129 | #ifdef __KERNEL__ | 129 | #ifdef __KERNEL__ |
130 | 130 | ||
131 | #define arch_has_single_step() (1) | ||
132 | |||
131 | #define user_mode(regs) \ | 133 | #define user_mode(regs) \ |
132 | (((regs)->ARM_cpsr & 0xf) == 0) | 134 | (((regs)->ARM_cpsr & 0xf) == 0) |
133 | 135 | ||
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index cf9cdaa2d4d4..dd2bf53000fe 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h | |||
@@ -443,9 +443,12 @@ | |||
443 | #define __ARCH_WANT_SYS_SIGPROCMASK | 443 | #define __ARCH_WANT_SYS_SIGPROCMASK |
444 | #define __ARCH_WANT_SYS_RT_SIGACTION | 444 | #define __ARCH_WANT_SYS_RT_SIGACTION |
445 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 445 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
446 | #define __ARCH_WANT_SYS_OLD_MMAP | ||
447 | #define __ARCH_WANT_SYS_OLD_SELECT | ||
446 | 448 | ||
447 | #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) | 449 | #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) |
448 | #define __ARCH_WANT_SYS_TIME | 450 | #define __ARCH_WANT_SYS_TIME |
451 | #define __ARCH_WANT_SYS_IPC | ||
449 | #define __ARCH_WANT_SYS_OLDUMOUNT | 452 | #define __ARCH_WANT_SYS_OLDUMOUNT |
450 | #define __ARCH_WANT_SYS_ALARM | 453 | #define __ARCH_WANT_SYS_ALARM |
451 | #define __ARCH_WANT_SYS_UTIME | 454 | #define __ARCH_WANT_SYS_UTIME |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 9314a2d681f1..37ae301cc47c 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -91,7 +91,7 @@ | |||
91 | CALL(sys_settimeofday) | 91 | CALL(sys_settimeofday) |
92 | /* 80 */ CALL(sys_getgroups16) | 92 | /* 80 */ CALL(sys_getgroups16) |
93 | CALL(sys_setgroups16) | 93 | CALL(sys_setgroups16) |
94 | CALL(OBSOLETE(old_select)) /* used by libc4 */ | 94 | CALL(OBSOLETE(sys_old_select)) /* used by libc4 */ |
95 | CALL(sys_symlink) | 95 | CALL(sys_symlink) |
96 | CALL(sys_ni_syscall) /* was sys_lstat */ | 96 | CALL(sys_ni_syscall) /* was sys_lstat */ |
97 | /* 85 */ CALL(sys_readlink) | 97 | /* 85 */ CALL(sys_readlink) |
@@ -99,7 +99,7 @@ | |||
99 | CALL(sys_swapon) | 99 | CALL(sys_swapon) |
100 | CALL(sys_reboot) | 100 | CALL(sys_reboot) |
101 | CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ | 101 | CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ |
102 | /* 90 */ CALL(OBSOLETE(old_mmap)) /* used by libc4 */ | 102 | /* 90 */ CALL(OBSOLETE(sys_old_mmap)) /* used by libc4 */ |
103 | CALL(sys_munmap) | 103 | CALL(sys_munmap) |
104 | CALL(sys_truncate) | 104 | CALL(sys_truncate) |
105 | CALL(sys_ftruncate) | 105 | CALL(sys_ftruncate) |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 08f899fb76a6..3f562a7c0a99 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -452,12 +452,23 @@ void ptrace_cancel_bpt(struct task_struct *child) | |||
452 | clear_breakpoint(child, &child->thread.debug.bp[i]); | 452 | clear_breakpoint(child, &child->thread.debug.bp[i]); |
453 | } | 453 | } |
454 | 454 | ||
455 | void user_disable_single_step(struct task_struct *task) | ||
456 | { | ||
457 | task->ptrace &= ~PT_SINGLESTEP; | ||
458 | ptrace_cancel_bpt(task); | ||
459 | } | ||
460 | |||
461 | void user_enable_single_step(struct task_struct *task) | ||
462 | { | ||
463 | task->ptrace |= PT_SINGLESTEP; | ||
464 | } | ||
465 | |||
455 | /* | 466 | /* |
456 | * Called by kernel/ptrace.c when detaching.. | 467 | * Called by kernel/ptrace.c when detaching.. |
457 | */ | 468 | */ |
458 | void ptrace_disable(struct task_struct *child) | 469 | void ptrace_disable(struct task_struct *child) |
459 | { | 470 | { |
460 | single_step_disable(child); | 471 | user_disable_single_step(child); |
461 | } | 472 | } |
462 | 473 | ||
463 | /* | 474 | /* |
@@ -753,53 +764,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
753 | ret = ptrace_write_user(child, addr, data); | 764 | ret = ptrace_write_user(child, addr, data); |
754 | break; | 765 | break; |
755 | 766 | ||
756 | /* | ||
757 | * continue/restart and stop at next (return from) syscall | ||
758 | */ | ||
759 | case PTRACE_SYSCALL: | ||
760 | case PTRACE_CONT: | ||
761 | ret = -EIO; | ||
762 | if (!valid_signal(data)) | ||
763 | break; | ||
764 | if (request == PTRACE_SYSCALL) | ||
765 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
766 | else | ||
767 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
768 | child->exit_code = data; | ||
769 | single_step_disable(child); | ||
770 | wake_up_process(child); | ||
771 | ret = 0; | ||
772 | break; | ||
773 | |||
774 | /* | ||
775 | * make the child exit. Best I can do is send it a sigkill. | ||
776 | * perhaps it should be put in the status that it wants to | ||
777 | * exit. | ||
778 | */ | ||
779 | case PTRACE_KILL: | ||
780 | single_step_disable(child); | ||
781 | if (child->exit_state != EXIT_ZOMBIE) { | ||
782 | child->exit_code = SIGKILL; | ||
783 | wake_up_process(child); | ||
784 | } | ||
785 | ret = 0; | ||
786 | break; | ||
787 | |||
788 | /* | ||
789 | * execute single instruction. | ||
790 | */ | ||
791 | case PTRACE_SINGLESTEP: | ||
792 | ret = -EIO; | ||
793 | if (!valid_signal(data)) | ||
794 | break; | ||
795 | single_step_enable(child); | ||
796 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
797 | child->exit_code = data; | ||
798 | /* give it a chance to run. */ | ||
799 | wake_up_process(child); | ||
800 | ret = 0; | ||
801 | break; | ||
802 | |||
803 | case PTRACE_GETREGS: | 767 | case PTRACE_GETREGS: |
804 | ret = ptrace_getregs(child, (void __user *)data); | 768 | ret = ptrace_getregs(child, (void __user *)data); |
805 | break; | 769 | break; |
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h index def3b6184a79..3926605b82ea 100644 --- a/arch/arm/kernel/ptrace.h +++ b/arch/arm/kernel/ptrace.h | |||
@@ -14,20 +14,6 @@ extern void ptrace_set_bpt(struct task_struct *); | |||
14 | extern void ptrace_break(struct task_struct *, struct pt_regs *); | 14 | extern void ptrace_break(struct task_struct *, struct pt_regs *); |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * make sure single-step breakpoint is gone. | ||
18 | */ | ||
19 | static inline void single_step_disable(struct task_struct *task) | ||
20 | { | ||
21 | task->ptrace &= ~PT_SINGLESTEP; | ||
22 | ptrace_cancel_bpt(task); | ||
23 | } | ||
24 | |||
25 | static inline void single_step_enable(struct task_struct *task) | ||
26 | { | ||
27 | task->ptrace |= PT_SINGLESTEP; | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * Send SIGTRAP if we're single-stepping | 17 | * Send SIGTRAP if we're single-stepping |
32 | */ | 18 | */ |
33 | static inline void single_step_trap(struct task_struct *task) | 19 | static inline void single_step_trap(struct task_struct *task) |
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index ae4027bd01bd..4350f75e578c 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c | |||
@@ -28,135 +28,6 @@ | |||
28 | #include <linux/ipc.h> | 28 | #include <linux/ipc.h> |
29 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
30 | 30 | ||
31 | struct mmap_arg_struct { | ||
32 | unsigned long addr; | ||
33 | unsigned long len; | ||
34 | unsigned long prot; | ||
35 | unsigned long flags; | ||
36 | unsigned long fd; | ||
37 | unsigned long offset; | ||
38 | }; | ||
39 | |||
40 | asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) | ||
41 | { | ||
42 | int error = -EFAULT; | ||
43 | struct mmap_arg_struct a; | ||
44 | |||
45 | if (copy_from_user(&a, arg, sizeof(a))) | ||
46 | goto out; | ||
47 | |||
48 | error = -EINVAL; | ||
49 | if (a.offset & ~PAGE_MASK) | ||
50 | goto out; | ||
51 | |||
52 | error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); | ||
53 | out: | ||
54 | return error; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
59 | * calls. | ||
60 | */ | ||
61 | |||
62 | struct sel_arg_struct { | ||
63 | unsigned long n; | ||
64 | fd_set __user *inp, *outp, *exp; | ||
65 | struct timeval __user *tvp; | ||
66 | }; | ||
67 | |||
68 | asmlinkage int old_select(struct sel_arg_struct __user *arg) | ||
69 | { | ||
70 | struct sel_arg_struct a; | ||
71 | |||
72 | if (copy_from_user(&a, arg, sizeof(a))) | ||
73 | return -EFAULT; | ||
74 | /* sys_select() does the appropriate kernel locking */ | ||
75 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
76 | } | ||
77 | |||
78 | #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) | ||
79 | /* | ||
80 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
81 | * | ||
82 | * This is really horribly ugly. | ||
83 | */ | ||
84 | asmlinkage int sys_ipc(uint call, int first, int second, int third, | ||
85 | void __user *ptr, long fifth) | ||
86 | { | ||
87 | int version, ret; | ||
88 | |||
89 | version = call >> 16; /* hack for backward compatibility */ | ||
90 | call &= 0xffff; | ||
91 | |||
92 | switch (call) { | ||
93 | case SEMOP: | ||
94 | return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); | ||
95 | case SEMTIMEDOP: | ||
96 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, | ||
97 | (const struct timespec __user *)fifth); | ||
98 | |||
99 | case SEMGET: | ||
100 | return sys_semget (first, second, third); | ||
101 | case SEMCTL: { | ||
102 | union semun fourth; | ||
103 | if (!ptr) | ||
104 | return -EINVAL; | ||
105 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
106 | return -EFAULT; | ||
107 | return sys_semctl (first, second, third, fourth); | ||
108 | } | ||
109 | |||
110 | case MSGSND: | ||
111 | return sys_msgsnd(first, (struct msgbuf __user *) ptr, | ||
112 | second, third); | ||
113 | case MSGRCV: | ||
114 | switch (version) { | ||
115 | case 0: { | ||
116 | struct ipc_kludge tmp; | ||
117 | if (!ptr) | ||
118 | return -EINVAL; | ||
119 | if (copy_from_user(&tmp,(struct ipc_kludge __user *)ptr, | ||
120 | sizeof (tmp))) | ||
121 | return -EFAULT; | ||
122 | return sys_msgrcv (first, tmp.msgp, second, | ||
123 | tmp.msgtyp, third); | ||
124 | } | ||
125 | default: | ||
126 | return sys_msgrcv (first, | ||
127 | (struct msgbuf __user *) ptr, | ||
128 | second, fifth, third); | ||
129 | } | ||
130 | case MSGGET: | ||
131 | return sys_msgget ((key_t) first, second); | ||
132 | case MSGCTL: | ||
133 | return sys_msgctl(first, second, (struct msqid_ds __user *)ptr); | ||
134 | |||
135 | case SHMAT: | ||
136 | switch (version) { | ||
137 | default: { | ||
138 | ulong raddr; | ||
139 | ret = do_shmat(first, (char __user *)ptr, second, &raddr); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | return put_user(raddr, (ulong __user *)third); | ||
143 | } | ||
144 | case 1: /* Of course, we don't support iBCS2! */ | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | case SHMDT: | ||
148 | return sys_shmdt ((char __user *)ptr); | ||
149 | case SHMGET: | ||
150 | return sys_shmget (first, second, third); | ||
151 | case SHMCTL: | ||
152 | return sys_shmctl (first, second, | ||
153 | (struct shmid_ds __user *) ptr); | ||
154 | default: | ||
155 | return -ENOSYS; | ||
156 | } | ||
157 | } | ||
158 | #endif | ||
159 | |||
160 | /* Fork a new task - this creates a new program thread. | 31 | /* Fork a new task - this creates a new program thread. |
161 | * This is called indirectly via a small wrapper | 32 | * This is called indirectly via a small wrapper |
162 | */ | 33 | */ |
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index d59a0cd537f0..33ff678e32f2 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c | |||
@@ -346,9 +346,6 @@ asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, | |||
346 | return sys_oabi_semtimedop(semid, tsops, nsops, NULL); | 346 | return sys_oabi_semtimedop(semid, tsops, nsops, NULL); |
347 | } | 347 | } |
348 | 348 | ||
349 | extern asmlinkage int sys_ipc(uint call, int first, int second, int third, | ||
350 | void __user *ptr, long fifth); | ||
351 | |||
352 | asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, | 349 | asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, |
353 | void __user *ptr, long fifth) | 350 | void __user *ptr, long fifth) |
354 | { | 351 | { |
diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h index 3bd934e9a7f1..93107d88ff3a 100644 --- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h +++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h | |||
@@ -65,6 +65,8 @@ | |||
65 | #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 | 65 | #define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 |
66 | #define TS72XX_RTC_DATA_SIZE 0x00001000 | 66 | #define TS72XX_RTC_DATA_SIZE 0x00001000 |
67 | 67 | ||
68 | #define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000 | ||
69 | #define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000 | ||
68 | 70 | ||
69 | #ifndef __ASSEMBLY__ | 71 | #ifndef __ASSEMBLY__ |
70 | 72 | ||
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 259f7822ba52..fac1ec7a60fb 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c | |||
@@ -166,6 +166,26 @@ static struct platform_device ts72xx_rtc_device = { | |||
166 | .num_resources = 0, | 166 | .num_resources = 0, |
167 | }; | 167 | }; |
168 | 168 | ||
169 | static struct resource ts72xx_wdt_resources[] = { | ||
170 | { | ||
171 | .start = TS72XX_WDT_CONTROL_PHYS_BASE, | ||
172 | .end = TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1, | ||
173 | .flags = IORESOURCE_MEM, | ||
174 | }, | ||
175 | { | ||
176 | .start = TS72XX_WDT_FEED_PHYS_BASE, | ||
177 | .end = TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1, | ||
178 | .flags = IORESOURCE_MEM, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static struct platform_device ts72xx_wdt_device = { | ||
183 | .name = "ts72xx-wdt", | ||
184 | .id = -1, | ||
185 | .num_resources = ARRAY_SIZE(ts72xx_wdt_resources), | ||
186 | .resource = ts72xx_wdt_resources, | ||
187 | }; | ||
188 | |||
169 | static struct ep93xx_eth_data ts72xx_eth_data = { | 189 | static struct ep93xx_eth_data ts72xx_eth_data = { |
170 | .phy_id = 1, | 190 | .phy_id = 1, |
171 | }; | 191 | }; |
@@ -175,6 +195,7 @@ static void __init ts72xx_init_machine(void) | |||
175 | ep93xx_init_devices(); | 195 | ep93xx_init_devices(); |
176 | ts72xx_register_flash(); | 196 | ts72xx_register_flash(); |
177 | platform_device_register(&ts72xx_rtc_device); | 197 | platform_device_register(&ts72xx_rtc_device); |
198 | platform_device_register(&ts72xx_wdt_device); | ||
178 | 199 | ||
179 | ep93xx_register_eth(&ts72xx_eth_data, 1); | 200 | ep93xx_register_eth(&ts72xx_eth_data, 1); |
180 | } | 201 | } |
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index c4a01594c761..e3181534c7f9 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c | |||
@@ -502,32 +502,6 @@ struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys) | |||
502 | return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys); | 502 | return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys); |
503 | } | 503 | } |
504 | 504 | ||
505 | /* | ||
506 | * We override these so we properly do dmabounce otherwise drivers | ||
507 | * are able to set the dma_mask to 0xffffffff and we can no longer | ||
508 | * trap bounces. :( | ||
509 | * | ||
510 | * We just return true on everyhing except for < 64MB in which case | ||
511 | * we will fail miseralby and die since we can't handle that case. | ||
512 | */ | ||
513 | int | ||
514 | pci_set_dma_mask(struct pci_dev *dev, u64 mask) | ||
515 | { | ||
516 | if (mask >= SZ_64M - 1 ) | ||
517 | return 0; | ||
518 | |||
519 | return -EIO; | ||
520 | } | ||
521 | |||
522 | int | ||
523 | pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | ||
524 | { | ||
525 | if (mask >= SZ_64M - 1 ) | ||
526 | return 0; | ||
527 | |||
528 | return -EIO; | ||
529 | } | ||
530 | |||
531 | EXPORT_SYMBOL(ixp4xx_pci_read); | 505 | EXPORT_SYMBOL(ixp4xx_pci_read); |
532 | EXPORT_SYMBOL(ixp4xx_pci_write); | 506 | EXPORT_SYMBOL(ixp4xx_pci_write); |
533 | 507 | ||
diff --git a/arch/arm/mach-ixp4xx/include/mach/hardware.h b/arch/arm/mach-ixp4xx/include/mach/hardware.h index f9d1c43e4a54..f91ca6d4fbe8 100644 --- a/arch/arm/mach-ixp4xx/include/mach/hardware.h +++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h | |||
@@ -26,11 +26,6 @@ | |||
26 | #define PCIBIOS_MAX_MEM 0x4BFFFFFF | 26 | #define PCIBIOS_MAX_MEM 0x4BFFFFFF |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | /* | ||
30 | * We override the standard dma-mask routines for bouncing. | ||
31 | */ | ||
32 | #define HAVE_ARCH_PCI_SET_DMA_MASK | ||
33 | |||
34 | #define pcibios_assign_all_busses() 1 | 29 | #define pcibios_assign_all_busses() 1 |
35 | 30 | ||
36 | /* Register locations and bits */ | 31 | /* Register locations and bits */ |
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c index 4bd10a17332e..993d75e66390 100644 --- a/arch/arm/mach-pxa/am300epd.c +++ b/arch/arm/mach-pxa/am300epd.c | |||
@@ -288,7 +288,7 @@ int __init am300_init(void) | |||
288 | } | 288 | } |
289 | 289 | ||
290 | module_param(panel_type, uint, 0); | 290 | module_param(panel_type, uint, 0); |
291 | MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97"); | 291 | MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97"); |
292 | 292 | ||
293 | MODULE_DESCRIPTION("board driver for am300 epd kit"); | 293 | MODULE_DESCRIPTION("board driver for am300 epd kit"); |
294 | MODULE_AUTHOR("Jaya Kumar"); | 294 | MODULE_AUTHOR("Jaya Kumar"); |
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c index a5ee70735e04..1d9bc118ee32 100644 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ b/arch/arm/mach-pxa/corgi_ssp.c | |||
@@ -204,7 +204,7 @@ void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo) | |||
204 | ssp_machinfo = machinfo; | 204 | ssp_machinfo = machinfo; |
205 | } | 205 | } |
206 | 206 | ||
207 | static int __init corgi_ssp_probe(struct platform_device *dev) | 207 | static int __devinit corgi_ssp_probe(struct platform_device *dev) |
208 | { | 208 | { |
209 | int ret; | 209 | int ret; |
210 | 210 | ||
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h index e741bf1bfb2d..7515757d6911 100644 --- a/arch/arm/mach-pxa/include/mach/hardware.h +++ b/arch/arm/mach-pxa/include/mach/hardware.h | |||
@@ -314,7 +314,6 @@ extern unsigned long get_clock_tick_rate(void); | |||
314 | #define PCIBIOS_MIN_IO 0 | 314 | #define PCIBIOS_MIN_IO 0 |
315 | #define PCIBIOS_MIN_MEM 0 | 315 | #define PCIBIOS_MIN_MEM 0 |
316 | #define pcibios_assign_all_busses() 1 | 316 | #define pcibios_assign_all_busses() 1 |
317 | #define HAVE_ARCH_PCI_SET_DMA_MASK 1 | ||
318 | #endif | 317 | #endif |
319 | 318 | ||
320 | 319 | ||
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 67229a1ef55c..463d874bb867 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c | |||
@@ -900,7 +900,7 @@ static struct platform_suspend_ops sharpsl_pm_ops = { | |||
900 | }; | 900 | }; |
901 | #endif | 901 | #endif |
902 | 902 | ||
903 | static int __init sharpsl_pm_probe(struct platform_device *pdev) | 903 | static int __devinit sharpsl_pm_probe(struct platform_device *pdev) |
904 | { | 904 | { |
905 | int ret; | 905 | int ret; |
906 | 906 | ||
diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c index b7d1f8d27bc2..a3f3c7b1ca38 100644 --- a/arch/arm/mach-s3c2410/h1940-bluetooth.c +++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c | |||
@@ -56,7 +56,7 @@ static const struct rfkill_ops h1940bt_rfkill_ops = { | |||
56 | .set_block = h1940bt_set_block, | 56 | .set_block = h1940bt_set_block, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static int __init h1940bt_probe(struct platform_device *pdev) | 59 | static int __devinit h1940bt_probe(struct platform_device *pdev) |
60 | { | 60 | { |
61 | struct rfkill *rfk; | 61 | struct rfkill *rfk; |
62 | int ret = 0; | 62 | int ret = 0; |
diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c index 506a5e5a9ad5..9b6dee5d16db 100644 --- a/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/arch/arm/mach-sa1100/jornada720_ssp.c | |||
@@ -130,7 +130,7 @@ void jornada_ssp_end(void) | |||
130 | }; | 130 | }; |
131 | EXPORT_SYMBOL(jornada_ssp_end); | 131 | EXPORT_SYMBOL(jornada_ssp_end); |
132 | 132 | ||
133 | static int __init jornada_ssp_probe(struct platform_device *dev) | 133 | static int __devinit jornada_ssp_probe(struct platform_device *dev) |
134 | { | 134 | { |
135 | int ret; | 135 | int ret; |
136 | 136 | ||
diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h index 4d58ba164e25..f8730b60bd76 100644 --- a/arch/arm/mach-w90x900/cpu.h +++ b/arch/arm/mach-w90x900/cpu.h | |||
@@ -57,3 +57,4 @@ extern struct platform_device nuc900_device_fmi; | |||
57 | extern struct platform_device nuc900_device_kpi; | 57 | extern struct platform_device nuc900_device_kpi; |
58 | extern struct platform_device nuc900_device_rtc; | 58 | extern struct platform_device nuc900_device_rtc; |
59 | extern struct platform_device nuc900_device_ts; | 59 | extern struct platform_device nuc900_device_ts; |
60 | extern struct platform_device nuc900_device_lcd; | ||
diff --git a/arch/arm/mach-w90x900/dev.c b/arch/arm/mach-w90x900/dev.c index ec711f4b4019..48876122df91 100644 --- a/arch/arm/mach-w90x900/dev.c +++ b/arch/arm/mach-w90x900/dev.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <mach/regs-serial.h> | 34 | #include <mach/regs-serial.h> |
35 | #include <mach/nuc900_spi.h> | 35 | #include <mach/nuc900_spi.h> |
36 | #include <mach/map.h> | 36 | #include <mach/map.h> |
37 | #include <mach/fb.h> | ||
37 | 38 | ||
38 | #include "cpu.h" | 39 | #include "cpu.h" |
39 | 40 | ||
@@ -380,6 +381,47 @@ struct platform_device nuc900_device_kpi = { | |||
380 | .resource = nuc900_kpi_resource, | 381 | .resource = nuc900_kpi_resource, |
381 | }; | 382 | }; |
382 | 383 | ||
384 | #ifdef CONFIG_FB_NUC900 | ||
385 | |||
386 | static struct resource nuc900_lcd_resource[] = { | ||
387 | [0] = { | ||
388 | .start = W90X900_PA_LCD, | ||
389 | .end = W90X900_PA_LCD + W90X900_SZ_LCD - 1, | ||
390 | .flags = IORESOURCE_MEM, | ||
391 | }, | ||
392 | [1] = { | ||
393 | .start = IRQ_LCD, | ||
394 | .end = IRQ_LCD, | ||
395 | .flags = IORESOURCE_IRQ, | ||
396 | } | ||
397 | }; | ||
398 | |||
399 | static u64 nuc900_device_lcd_dmamask = -1; | ||
400 | struct platform_device nuc900_device_lcd = { | ||
401 | .name = "nuc900-lcd", | ||
402 | .id = -1, | ||
403 | .num_resources = ARRAY_SIZE(nuc900_lcd_resource), | ||
404 | .resource = nuc900_lcd_resource, | ||
405 | .dev = { | ||
406 | .dma_mask = &nuc900_device_lcd_dmamask, | ||
407 | .coherent_dma_mask = -1, | ||
408 | } | ||
409 | }; | ||
410 | |||
411 | void nuc900_fb_set_platdata(struct nuc900fb_mach_info *pd) | ||
412 | { | ||
413 | struct nuc900fb_mach_info *npd; | ||
414 | |||
415 | npd = kmalloc(sizeof(*npd), GFP_KERNEL); | ||
416 | if (npd) { | ||
417 | memcpy(npd, pd, sizeof(*npd)); | ||
418 | nuc900_device_lcd.dev.platform_data = npd; | ||
419 | } else { | ||
420 | printk(KERN_ERR "no memory for LCD platform data\n"); | ||
421 | } | ||
422 | } | ||
423 | #endif | ||
424 | |||
383 | /*Here should be your evb resourse,such as LCD*/ | 425 | /*Here should be your evb resourse,such as LCD*/ |
384 | 426 | ||
385 | static struct platform_device *nuc900_public_dev[] __initdata = { | 427 | static struct platform_device *nuc900_public_dev[] __initdata = { |
diff --git a/arch/arm/mach-w90x900/include/mach/fb.h b/arch/arm/mach-w90x900/include/mach/fb.h new file mode 100644 index 000000000000..cec5ece765ed --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/fb.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* linux/include/asm/arch-nuc900/fb.h | ||
2 | * | ||
3 | * Copyright (c) 2008 Nuvoton technology corporation | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * Changelog: | ||
12 | * | ||
13 | * 2008/08/26 vincen.zswan modify this file for LCD. | ||
14 | */ | ||
15 | |||
16 | #ifndef __ASM_ARM_FB_H | ||
17 | #define __ASM_ARM_FB_H | ||
18 | |||
19 | |||
20 | |||
21 | /* LCD Controller Hardware Desc */ | ||
22 | struct nuc900fb_hw { | ||
23 | unsigned int lcd_dccs; | ||
24 | unsigned int lcd_device_ctrl; | ||
25 | unsigned int lcd_mpulcd_cmd; | ||
26 | unsigned int lcd_int_cs; | ||
27 | unsigned int lcd_crtc_size; | ||
28 | unsigned int lcd_crtc_dend; | ||
29 | unsigned int lcd_crtc_hr; | ||
30 | unsigned int lcd_crtc_hsync; | ||
31 | unsigned int lcd_crtc_vr; | ||
32 | unsigned int lcd_va_baddr0; | ||
33 | unsigned int lcd_va_baddr1; | ||
34 | unsigned int lcd_va_fbctrl; | ||
35 | unsigned int lcd_va_scale; | ||
36 | unsigned int lcd_va_test; | ||
37 | unsigned int lcd_va_win; | ||
38 | unsigned int lcd_va_stuff; | ||
39 | }; | ||
40 | |||
41 | /* LCD Display Description */ | ||
42 | struct nuc900fb_display { | ||
43 | /* LCD Image type */ | ||
44 | unsigned type; | ||
45 | |||
46 | /* LCD Screen Size */ | ||
47 | unsigned short width; | ||
48 | unsigned short height; | ||
49 | |||
50 | /* LCD Screen Info */ | ||
51 | unsigned short xres; | ||
52 | unsigned short yres; | ||
53 | unsigned short bpp; | ||
54 | |||
55 | unsigned long pixclock; | ||
56 | unsigned short left_margin; | ||
57 | unsigned short right_margin; | ||
58 | unsigned short hsync_len; | ||
59 | unsigned short upper_margin; | ||
60 | unsigned short lower_margin; | ||
61 | unsigned short vsync_len; | ||
62 | |||
63 | /* hardware special register value */ | ||
64 | unsigned int dccs; | ||
65 | unsigned int devctl; | ||
66 | unsigned int fbctrl; | ||
67 | unsigned int scale; | ||
68 | }; | ||
69 | |||
70 | struct nuc900fb_mach_info { | ||
71 | struct nuc900fb_display *displays; | ||
72 | unsigned num_displays; | ||
73 | unsigned default_display; | ||
74 | /* GPIO Setting Info */ | ||
75 | unsigned gpio_dir; | ||
76 | unsigned gpio_dir_mask; | ||
77 | unsigned gpio_data; | ||
78 | unsigned gpio_data_mask; | ||
79 | }; | ||
80 | |||
81 | extern void __init nuc900_fb_set_platdata(struct nuc900fb_mach_info *); | ||
82 | |||
83 | #endif /* __ASM_ARM_FB_H */ | ||
diff --git a/arch/arm/mach-w90x900/include/mach/regs-ldm.h b/arch/arm/mach-w90x900/include/mach/regs-ldm.h new file mode 100644 index 000000000000..e9d480a5b232 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/regs-ldm.h | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-w90x900/include/mach/regs-serial.h | ||
3 | * | ||
4 | * Copyright (c) 2009 Nuvoton technology corporation | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * Description: | ||
13 | * Nuvoton Display, LCM Register list | ||
14 | * Author: Wang Qiang (rurality.linux@gmail.com) 2009/12/11 | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | |||
19 | #ifndef __ASM_ARM_W90X900_REGS_LDM_H | ||
20 | #define __ASM_ARM_W90X900_REGS_LDM_H | ||
21 | |||
22 | #include <mach/map.h> | ||
23 | |||
24 | /* Display Controller Control/Status Register */ | ||
25 | #define REG_LCM_DCCS (0x00) | ||
26 | |||
27 | #define LCM_DCCS_ENG_RST (1 << 0) | ||
28 | #define LCM_DCCS_VA_EN (1 << 1) | ||
29 | #define LCM_DCCS_OSD_EN (1 << 2) | ||
30 | #define LCM_DCCS_DISP_OUT_EN (1 << 3) | ||
31 | #define LCM_DCCS_DISP_INT_EN (1 << 4) | ||
32 | #define LCM_DCCS_CMD_ON (1 << 5) | ||
33 | #define LCM_DCCS_FIELD_INTR (1 << 6) | ||
34 | #define LCM_DCCS_SINGLE (1 << 7) | ||
35 | |||
36 | enum LCM_DCCS_VA_SRC { | ||
37 | LCM_DCCS_VA_SRC_YUV422 = (0 << 8), | ||
38 | LCM_DCCS_VA_SRC_YCBCR422 = (1 << 8), | ||
39 | LCM_DCCS_VA_SRC_RGB888 = (2 << 8), | ||
40 | LCM_DCCS_VA_SRC_RGB666 = (3 << 8), | ||
41 | LCM_DCCS_VA_SRC_RGB565 = (4 << 8), | ||
42 | LCM_DCCS_VA_SRC_RGB444LOW = (5 << 8), | ||
43 | LCM_DCCS_VA_SRC_RGB444HIGH = (7 << 8) | ||
44 | }; | ||
45 | |||
46 | |||
47 | /* Display Device Control Register */ | ||
48 | #define REG_LCM_DEV_CTRL (0x04) | ||
49 | |||
50 | enum LCM_DEV_CTRL_SWAP_YCbCr { | ||
51 | LCM_DEV_CTRL_SWAP_UYVY = (0 << 1), | ||
52 | LCM_DEV_CTRL_SWAP_YUYV = (1 << 1), | ||
53 | LCM_DEV_CTRL_SWAP_VYUY = (2 << 1), | ||
54 | LCM_DEV_CTRL_SWAP_YVYU = (3 << 1) | ||
55 | }; | ||
56 | |||
57 | enum LCM_DEV_CTRL_RGB_SHIFT { | ||
58 | LCM_DEV_CTRL_RGB_SHIFT_NOT = (0 << 3), | ||
59 | LCM_DEV_CTRL_RGB_SHIFT_ONECYCLE = (1 << 3), | ||
60 | LCM_DEV_CTRL_RGB_SHIFT_TWOCYCLE = (2 << 3), | ||
61 | LCM_DEV_CTRL_RGB_SHIFT_NOT_DEF = (3 << 3) | ||
62 | }; | ||
63 | |||
64 | enum LCM_DEV_CTRL_DEVICE { | ||
65 | LCM_DEV_CTRL_DEVICE_YUV422 = (0 << 5), | ||
66 | LCM_DEV_CTRL_DEVICE_YUV444 = (1 << 5), | ||
67 | LCM_DEV_CTRL_DEVICE_UNIPAC = (4 << 5), | ||
68 | LCM_DEV_CTRL_DEVICE_SEIKO_EPSON = (5 << 5), | ||
69 | LCM_DEV_CTRL_DEVICE_HIGH_COLOR = (6 << 5), | ||
70 | LCM_DEV_CTRL_DEVICE_MPU = (7 << 5) | ||
71 | }; | ||
72 | |||
73 | #define LCM_DEV_CTRL_LCD_DDA (8) | ||
74 | #define LCM_DEV_CTRL_YUV2CCIR (16) | ||
75 | |||
76 | enum LCM_DEV_CTRL_LCD_SEL { | ||
77 | LCM_DEV_CTRL_LCD_SEL_RGB_GBR = (0 << 17), | ||
78 | LCM_DEV_CTRL_LCD_SEL_BGR_RBG = (1 << 17), | ||
79 | LCM_DEV_CTRL_LCD_SEL_GBR_RGB = (2 << 17), | ||
80 | LCM_DEV_CTRL_LCD_SEL_RBG_BGR = (3 << 17) | ||
81 | }; | ||
82 | |||
83 | enum LCM_DEV_CTRL_FAL_D { | ||
84 | LCM_DEV_CTRL_FAL_D_FALLING = (0 << 19), | ||
85 | LCM_DEV_CTRL_FAL_D_RISING = (1 << 19), | ||
86 | }; | ||
87 | |||
88 | enum LCM_DEV_CTRL_H_POL { | ||
89 | LCM_DEV_CTRL_H_POL_LOW = (0 << 20), | ||
90 | LCM_DEV_CTRL_H_POL_HIGH = (1 << 20), | ||
91 | }; | ||
92 | |||
93 | enum LCM_DEV_CTRL_V_POL { | ||
94 | LCM_DEV_CTRL_V_POL_LOW = (0 << 21), | ||
95 | LCM_DEV_CTRL_V_POL_HIGH = (1 << 21), | ||
96 | }; | ||
97 | |||
98 | enum LCM_DEV_CTRL_VR_LACE { | ||
99 | LCM_DEV_CTRL_VR_LACE_NINTERLACE = (0 << 22), | ||
100 | LCM_DEV_CTRL_VR_LACE_INTERLACE = (1 << 22), | ||
101 | }; | ||
102 | |||
103 | enum LCM_DEV_CTRL_LACE { | ||
104 | LCM_DEV_CTRL_LACE_NINTERLACE = (0 << 23), | ||
105 | LCM_DEV_CTRL_LACE_INTERLACE = (1 << 23), | ||
106 | }; | ||
107 | |||
108 | enum LCM_DEV_CTRL_RGB_SCALE { | ||
109 | LCM_DEV_CTRL_RGB_SCALE_4096 = (0 << 24), | ||
110 | LCM_DEV_CTRL_RGB_SCALE_65536 = (1 << 24), | ||
111 | LCM_DEV_CTRL_RGB_SCALE_262144 = (2 << 24), | ||
112 | LCM_DEV_CTRL_RGB_SCALE_16777216 = (3 << 24), | ||
113 | }; | ||
114 | |||
115 | enum LCM_DEV_CTRL_DBWORD { | ||
116 | LCM_DEV_CTRL_DBWORD_HALFWORD = (0 << 26), | ||
117 | LCM_DEV_CTRL_DBWORD_FULLWORD = (1 << 26), | ||
118 | }; | ||
119 | |||
120 | enum LCM_DEV_CTRL_MPU68 { | ||
121 | LCM_DEV_CTRL_MPU68_80_SERIES = (0 << 27), | ||
122 | LCM_DEV_CTRL_MPU68_68_SERIES = (1 << 27), | ||
123 | }; | ||
124 | |||
125 | enum LCM_DEV_CTRL_DE_POL { | ||
126 | LCM_DEV_CTRL_DE_POL_HIGH = (0 << 28), | ||
127 | LCM_DEV_CTRL_DE_POL_LOW = (1 << 28), | ||
128 | }; | ||
129 | |||
130 | #define LCM_DEV_CTRL_CMD16 (29) | ||
131 | #define LCM_DEV_CTRL_CM16t18 (30) | ||
132 | #define LCM_DEV_CTRL_CMD_LOW (31) | ||
133 | |||
134 | /* MPU-Interface LCD Write Command */ | ||
135 | #define REG_LCM_MPU_CMD (0x08) | ||
136 | |||
137 | /* Interrupt Control/Status Register */ | ||
138 | #define REG_LCM_INT_CS (0x0c) | ||
139 | #define LCM_INT_CS_DISP_F_EN (1 << 0) | ||
140 | #define LCM_INT_CS_UNDERRUN_EN (1 << 1) | ||
141 | #define LCM_INT_CS_BUS_ERROR_INT (1 << 28) | ||
142 | #define LCM_INT_CS_UNDERRUN_INT (1 << 29) | ||
143 | #define LCM_INT_CS_DISP_F_STATUS (1 << 30) | ||
144 | #define LCM_INT_CS_DISP_F_INT (1 << 31) | ||
145 | |||
146 | /* CRTC Display Size Control Register */ | ||
147 | #define REG_LCM_CRTC_SIZE (0x10) | ||
148 | #define LCM_CRTC_SIZE_VTTVAL(x) ((x) << 16) | ||
149 | #define LCM_CRTC_SIZE_HTTVAL(x) ((x) << 0) | ||
150 | |||
151 | /* CRTC Display Enable End */ | ||
152 | #define REG_LCM_CRTC_DEND (0x14) | ||
153 | #define LCM_CRTC_DEND_VDENDVAL(x) ((x) << 16) | ||
154 | #define LCM_CRTC_DEND_HDENDVAL(x) ((x) << 0) | ||
155 | |||
156 | /* CRTC Internal Horizontal Retrace Control Register */ | ||
157 | #define REG_LCM_CRTC_HR (0x18) | ||
158 | #define LCM_CRTC_HR_EVAL(x) ((x) << 16) | ||
159 | #define LCM_CRTC_HR_SVAL(x) ((x) << 0) | ||
160 | |||
161 | /* CRTC Horizontal Sync Control Register */ | ||
162 | #define REG_LCM_CRTC_HSYNC (0x1C) | ||
163 | #define LCM_CRTC_HSYNC_SHIFTVAL(x) ((x) << 30) | ||
164 | #define LCM_CRTC_HSYNC_EVAL(x) ((x) << 16) | ||
165 | #define LCM_CRTC_HSYNC_SVAL(x) ((x) << 0) | ||
166 | |||
167 | /* CRTC Internal Vertical Retrace Control Register */ | ||
168 | #define REG_LCM_CRTC_VR (0x20) | ||
169 | #define LCM_CRTC_VR_EVAL(x) ((x) << 16) | ||
170 | #define LCM_CRTC_VR_SVAL(x) ((x) << 0) | ||
171 | |||
172 | /* Video Stream Frame Buffer-0 Starting Address */ | ||
173 | #define REG_LCM_VA_BADDR0 (0x24) | ||
174 | |||
175 | /* Video Stream Frame Buffer-1 Starting Address */ | ||
176 | #define REG_LCM_VA_BADDR1 (0x28) | ||
177 | |||
178 | /* Video Stream Frame Buffer Control Register */ | ||
179 | #define REG_LCM_VA_FBCTRL (0x2C) | ||
180 | #define LCM_VA_FBCTRL_IO_REGION_HALF (1 << 28) | ||
181 | #define LCM_VA_FBCTRL_FIELD_DUAL (1 << 29) | ||
182 | #define LCM_VA_FBCTRL_START_BUF (1 << 30) | ||
183 | #define LCM_VA_FBCTRL_DB_EN (1 << 31) | ||
184 | |||
185 | /* Video Stream Scaling Control Register */ | ||
186 | #define REG_LCM_VA_SCALE (0x30) | ||
187 | #define LCM_VA_SCALE_XCOPY_INTERPOLATION (0 << 15) | ||
188 | #define LCM_VA_SCALE_XCOPY_DUPLICATION (1 << 15) | ||
189 | |||
190 | /* Image Stream Active Window Coordinates */ | ||
191 | #define REG_LCM_VA_WIN (0x38) | ||
192 | |||
193 | /* Image Stream Stuff Pixel */ | ||
194 | #define REG_LCM_VA_STUFF (0x3C) | ||
195 | |||
196 | /* OSD Window Starting Coordinates */ | ||
197 | #define REG_LCM_OSD_WINS (0x40) | ||
198 | |||
199 | /* OSD Window Ending Coordinates */ | ||
200 | #define REG_LCM_OSD_WINE (0x44) | ||
201 | |||
202 | /* OSD Stream Frame Buffer Starting Address */ | ||
203 | #define REG_LCM_OSD_BADDR (0x48) | ||
204 | |||
205 | /* OSD Stream Frame Buffer Control Register */ | ||
206 | #define REG_LCM_OSD_FBCTRL (0x4c) | ||
207 | |||
208 | /* OSD Overlay Control Register */ | ||
209 | #define REG_LCM_OSD_OVERLAY (0x50) | ||
210 | |||
211 | /* OSD Overlay Color-Key Pattern Register */ | ||
212 | #define REG_LCM_OSD_CKEY (0x54) | ||
213 | |||
214 | /* OSD Overlay Color-Key Mask Register */ | ||
215 | #define REG_LCM_OSD_CMASK (0x58) | ||
216 | |||
217 | /* OSD Window Skip1 Register */ | ||
218 | #define REG_LCM_OSD_SKIP1 (0x5C) | ||
219 | |||
220 | /* OSD Window Skip2 Register */ | ||
221 | #define REG_LCM_OSD_SKIP2 (0x60) | ||
222 | |||
223 | /* OSD horizontal up scaling control register */ | ||
224 | #define REG_LCM_OSD_SCALE (0x64) | ||
225 | |||
226 | /* MPU Vsync control register */ | ||
227 | #define REG_LCM_MPU_VSYNC (0x68) | ||
228 | |||
229 | /* Hardware cursor control Register */ | ||
230 | #define REG_LCM_HC_CTRL (0x6C) | ||
231 | |||
232 | /* Hardware cursot tip point potison on va picture */ | ||
233 | #define REG_LCM_HC_POS (0x70) | ||
234 | |||
235 | /* Hardware Cursor Window Buffer Control Register */ | ||
236 | #define REG_LCM_HC_WBCTRL (0x74) | ||
237 | |||
238 | /* Hardware cursor memory base address register */ | ||
239 | #define REG_LCM_HC_BADDR (0x78) | ||
240 | |||
241 | /* Hardware cursor color ram register mapped to bpp = 0 */ | ||
242 | #define REG_LCM_HC_COLOR0 (0x7C) | ||
243 | |||
244 | /* Hardware cursor color ram register mapped to bpp = 1 */ | ||
245 | #define REG_LCM_HC_COLOR1 (0x80) | ||
246 | |||
247 | /* Hardware cursor color ram register mapped to bpp = 2 */ | ||
248 | #define REG_LCM_HC_COLOR2 (0x84) | ||
249 | |||
250 | /* Hardware cursor color ram register mapped to bpp = 3 */ | ||
251 | #define REG_LCM_HC_COLOR3 (0x88) | ||
252 | |||
253 | #endif /* __ASM_ARM_W90X900_REGS_LDM_H */ | ||
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c index cef903bcccd1..b3edc3cccf52 100644 --- a/arch/arm/mach-w90x900/mach-nuc950evb.c +++ b/arch/arm/mach-w90x900/mach-nuc950evb.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License as | 11 | * modify it under the terms of the GNU General Public License as |
12 | * published by the Free Software Foundation;version 2 of the License. | 12 | * published by the Free Software Foundation;version 2 of the License. |
13 | * history: | ||
14 | * Wang Qiang (rurality.linux@gmail.com) add LCD support | ||
13 | * | 15 | * |
14 | */ | 16 | */ |
15 | 17 | ||
@@ -18,9 +20,51 @@ | |||
18 | #include <asm/mach/map.h> | 20 | #include <asm/mach/map.h> |
19 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
20 | #include <mach/map.h> | 22 | #include <mach/map.h> |
23 | #include <mach/regs-ldm.h> | ||
24 | #include <mach/fb.h> | ||
21 | 25 | ||
22 | #include "nuc950.h" | 26 | #include "nuc950.h" |
23 | 27 | ||
28 | #ifdef CONFIG_FB_NUC900 | ||
29 | /* LCD Controller */ | ||
30 | static struct nuc900fb_display __initdata nuc950_lcd_info[] = { | ||
31 | /* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */ | ||
32 | [0] = { | ||
33 | .type = LCM_DCCS_VA_SRC_RGB565, | ||
34 | .width = 320, | ||
35 | .height = 240, | ||
36 | .xres = 320, | ||
37 | .yres = 240, | ||
38 | .bpp = 16, | ||
39 | .pixclock = 200000, | ||
40 | .left_margin = 34, | ||
41 | .right_margin = 54, | ||
42 | .hsync_len = 10, | ||
43 | .upper_margin = 18, | ||
44 | .lower_margin = 4, | ||
45 | .vsync_len = 1, | ||
46 | .dccs = 0x8e00041a, | ||
47 | .devctl = 0x060800c0, | ||
48 | .fbctrl = 0x00a000a0, | ||
49 | .scale = 0x04000400, | ||
50 | }, | ||
51 | }; | ||
52 | |||
53 | static struct nuc900fb_mach_info nuc950_fb_info __initdata = { | ||
54 | #if defined(CONFIG_GPM1040A0_320X240) | ||
55 | .displays = &nuc950_lcd_info[0], | ||
56 | #else | ||
57 | .displays = nuc950_lcd_info, | ||
58 | #endif | ||
59 | .num_displays = ARRAY_SIZE(nuc950_lcd_info), | ||
60 | .default_display = 0, | ||
61 | .gpio_dir = 0x00000004, | ||
62 | .gpio_dir_mask = 0xFFFFFFFD, | ||
63 | .gpio_data = 0x00000004, | ||
64 | .gpio_data_mask = 0xFFFFFFFD, | ||
65 | }; | ||
66 | #endif | ||
67 | |||
24 | static void __init nuc950evb_map_io(void) | 68 | static void __init nuc950evb_map_io(void) |
25 | { | 69 | { |
26 | nuc950_map_io(); | 70 | nuc950_map_io(); |
@@ -30,6 +74,9 @@ static void __init nuc950evb_map_io(void) | |||
30 | static void __init nuc950evb_init(void) | 74 | static void __init nuc950evb_init(void) |
31 | { | 75 | { |
32 | nuc950_board_init(); | 76 | nuc950_board_init(); |
77 | #ifdef CONFIG_FB_NUC900 | ||
78 | nuc900_fb_set_platdata(&nuc950_fb_info); | ||
79 | #endif | ||
33 | } | 80 | } |
34 | 81 | ||
35 | MACHINE_START(W90P950EVB, "W90P950EVB") | 82 | MACHINE_START(W90P950EVB, "W90P950EVB") |
diff --git a/arch/arm/mach-w90x900/nuc950.c b/arch/arm/mach-w90x900/nuc950.c index 149508116d18..4d1f1ab044c4 100644 --- a/arch/arm/mach-w90x900/nuc950.c +++ b/arch/arm/mach-w90x900/nuc950.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <asm/mach/map.h> | 19 | #include <asm/mach/map.h> |
20 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
21 | |||
21 | #include "cpu.h" | 22 | #include "cpu.h" |
22 | 23 | ||
23 | /* define specific CPU platform device */ | 24 | /* define specific CPU platform device */ |
@@ -25,6 +26,9 @@ | |||
25 | static struct platform_device *nuc950_dev[] __initdata = { | 26 | static struct platform_device *nuc950_dev[] __initdata = { |
26 | &nuc900_device_kpi, | 27 | &nuc900_device_kpi, |
27 | &nuc900_device_fmi, | 28 | &nuc900_device_fmi, |
29 | #ifdef CONFIG_FB_NUC900 | ||
30 | &nuc900_device_lcd, | ||
31 | #endif | ||
28 | }; | 32 | }; |
29 | 33 | ||
30 | /* define specific CPU platform io map */ | 34 | /* define specific CPU platform io map */ |
diff --git a/arch/avr32/include/asm/ptrace.h b/arch/avr32/include/asm/ptrace.h index 9e2d44f4e0fe..e53dd0d900f5 100644 --- a/arch/avr32/include/asm/ptrace.h +++ b/arch/avr32/include/asm/ptrace.h | |||
@@ -124,6 +124,8 @@ struct pt_regs { | |||
124 | 124 | ||
125 | #include <asm/ocd.h> | 125 | #include <asm/ocd.h> |
126 | 126 | ||
127 | #define arch_has_single_step() (1) | ||
128 | |||
127 | #define arch_ptrace_attach(child) ocd_enable(child) | 129 | #define arch_ptrace_attach(child) ocd_enable(child) |
128 | 130 | ||
129 | #define user_mode(regs) (((regs)->sr & MODE_MASK) == MODE_USER) | 131 | #define user_mode(regs) (((regs)->sr & MODE_MASK) == MODE_USER) |
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 1fed38fcf594..dd5b882aab40 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c | |||
@@ -28,9 +28,9 @@ static struct pt_regs *get_user_regs(struct task_struct *tsk) | |||
28 | THREAD_SIZE - sizeof(struct pt_regs)); | 28 | THREAD_SIZE - sizeof(struct pt_regs)); |
29 | } | 29 | } |
30 | 30 | ||
31 | static void ptrace_single_step(struct task_struct *tsk) | 31 | static void user_enable_single_step(struct task_struct *tsk) |
32 | { | 32 | { |
33 | pr_debug("ptrace_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n", | 33 | pr_debug("user_enable_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n", |
34 | tsk->pid, task_pt_regs(tsk)->pc, task_pt_regs(tsk)->sr); | 34 | tsk->pid, task_pt_regs(tsk)->pc, task_pt_regs(tsk)->sr); |
35 | 35 | ||
36 | /* | 36 | /* |
@@ -49,6 +49,11 @@ static void ptrace_single_step(struct task_struct *tsk) | |||
49 | set_tsk_thread_flag(tsk, TIF_SINGLE_STEP); | 49 | set_tsk_thread_flag(tsk, TIF_SINGLE_STEP); |
50 | } | 50 | } |
51 | 51 | ||
52 | void user_disable_single_step(struct task_struct *child) | ||
53 | { | ||
54 | /* XXX(hch): a no-op here seems wrong.. */ | ||
55 | } | ||
56 | |||
52 | /* | 57 | /* |
53 | * Called by kernel/ptrace.c when detaching | 58 | * Called by kernel/ptrace.c when detaching |
54 | * | 59 | * |
@@ -167,50 +172,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
167 | ret = ptrace_write_user(child, addr, data); | 172 | ret = ptrace_write_user(child, addr, data); |
168 | break; | 173 | break; |
169 | 174 | ||
170 | /* continue and stop at next (return from) syscall */ | ||
171 | case PTRACE_SYSCALL: | ||
172 | /* restart after signal */ | ||
173 | case PTRACE_CONT: | ||
174 | ret = -EIO; | ||
175 | if (!valid_signal(data)) | ||
176 | break; | ||
177 | if (request == PTRACE_SYSCALL) | ||
178 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
179 | else | ||
180 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
181 | child->exit_code = data; | ||
182 | /* XXX: Are we sure no breakpoints are active here? */ | ||
183 | wake_up_process(child); | ||
184 | ret = 0; | ||
185 | break; | ||
186 | |||
187 | /* | ||
188 | * Make the child exit. Best I can do is send it a | ||
189 | * SIGKILL. Perhaps it should be put in the status that it | ||
190 | * wants to exit. | ||
191 | */ | ||
192 | case PTRACE_KILL: | ||
193 | ret = 0; | ||
194 | if (child->exit_state == EXIT_ZOMBIE) | ||
195 | break; | ||
196 | child->exit_code = SIGKILL; | ||
197 | wake_up_process(child); | ||
198 | break; | ||
199 | |||
200 | /* | ||
201 | * execute single instruction. | ||
202 | */ | ||
203 | case PTRACE_SINGLESTEP: | ||
204 | ret = -EIO; | ||
205 | if (!valid_signal(data)) | ||
206 | break; | ||
207 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
208 | ptrace_single_step(child); | ||
209 | child->exit_code = data; | ||
210 | wake_up_process(child); | ||
211 | ret = 0; | ||
212 | break; | ||
213 | |||
214 | case PTRACE_GETREGS: | 175 | case PTRACE_GETREGS: |
215 | ret = ptrace_getregs(child, (void __user *)data); | 176 | ret = ptrace_getregs(child, (void __user *)data); |
216 | break; | 177 | break; |
diff --git a/arch/blackfin/include/asm/dma-mapping.h b/arch/blackfin/include/asm/dma-mapping.h index f9172ff30e5c..413a30314a6f 100644 --- a/arch/blackfin/include/asm/dma-mapping.h +++ b/arch/blackfin/include/asm/dma-mapping.h | |||
@@ -65,13 +65,6 @@ _dma_sync(dma_addr_t addr, size_t size, enum dma_data_direction dir) | |||
65 | } | 65 | } |
66 | } | 66 | } |
67 | 67 | ||
68 | /* | ||
69 | * Map a single buffer of the indicated size for DMA in streaming mode. | ||
70 | * The 32-bit bus address to use is returned. | ||
71 | * | ||
72 | * Once the device is given the dma address, the device owns this memory | ||
73 | * until either pci_unmap_single or pci_dma_sync_single is performed. | ||
74 | */ | ||
75 | static inline dma_addr_t | 68 | static inline dma_addr_t |
76 | dma_map_single(struct device *dev, void *ptr, size_t size, | 69 | dma_map_single(struct device *dev, void *ptr, size_t size, |
77 | enum dma_data_direction dir) | 70 | enum dma_data_direction dir) |
@@ -88,14 +81,6 @@ dma_map_page(struct device *dev, struct page *page, | |||
88 | return dma_map_single(dev, page_address(page) + offset, size, dir); | 81 | return dma_map_single(dev, page_address(page) + offset, size, dir); |
89 | } | 82 | } |
90 | 83 | ||
91 | /* | ||
92 | * Unmap a single streaming mode DMA translation. The dma_addr and size | ||
93 | * must match what was provided for in a previous pci_map_single call. All | ||
94 | * other usages are undefined. | ||
95 | * | ||
96 | * After this call, reads by the cpu to the buffer are guarenteed to see | ||
97 | * whatever the device wrote there. | ||
98 | */ | ||
99 | static inline void | 84 | static inline void |
100 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 85 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, |
101 | enum dma_data_direction dir) | 86 | enum dma_data_direction dir) |
@@ -110,30 +95,9 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
110 | dma_unmap_single(dev, dma_addr, size, dir); | 95 | dma_unmap_single(dev, dma_addr, size, dir); |
111 | } | 96 | } |
112 | 97 | ||
113 | /* | ||
114 | * Map a set of buffers described by scatterlist in streaming | ||
115 | * mode for DMA. This is the scather-gather version of the | ||
116 | * above pci_map_single interface. Here the scatter gather list | ||
117 | * elements are each tagged with the appropriate dma address | ||
118 | * and length. They are obtained via sg_dma_{address,length}(SG). | ||
119 | * | ||
120 | * NOTE: An implementation may be able to use a smaller number of | ||
121 | * DMA address/length pairs than there are SG table elements. | ||
122 | * (for example via virtual mapping capabilities) | ||
123 | * The routine returns the number of addr/length pairs actually | ||
124 | * used, at most nents. | ||
125 | * | ||
126 | * Device ownership issues as mentioned above for pci_map_single are | ||
127 | * the same here. | ||
128 | */ | ||
129 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 98 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, |
130 | enum dma_data_direction dir); | 99 | enum dma_data_direction dir); |
131 | 100 | ||
132 | /* | ||
133 | * Unmap a set of streaming mode DMA translations. | ||
134 | * Again, cpu read rules concerning calls here are the same as for | ||
135 | * pci_unmap_single() above. | ||
136 | */ | ||
137 | static inline void | 101 | static inline void |
138 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, | 102 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, |
139 | int nhwentries, enum dma_data_direction dir) | 103 | int nhwentries, enum dma_data_direction dir) |
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index c52bef39e250..0d6420d087fd 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S | |||
@@ -692,7 +692,7 @@ sys_call_table: | |||
692 | .long sys_swapon | 692 | .long sys_swapon |
693 | .long sys_reboot | 693 | .long sys_reboot |
694 | .long sys_old_readdir | 694 | .long sys_old_readdir |
695 | .long old_mmap /* 90 */ | 695 | .long sys_old_mmap /* 90 */ |
696 | .long sys_munmap | 696 | .long sys_munmap |
697 | .long sys_truncate | 697 | .long sys_truncate |
698 | .long sys_ftruncate | 698 | .long sys_ftruncate |
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index ee505b2eb4db..e70c804e9377 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c | |||
@@ -127,57 +127,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
127 | ret = 0; | 127 | ret = 0; |
128 | break; | 128 | break; |
129 | 129 | ||
130 | case PTRACE_SYSCALL: | ||
131 | case PTRACE_CONT: | ||
132 | ret = -EIO; | ||
133 | |||
134 | if (!valid_signal(data)) | ||
135 | break; | ||
136 | |||
137 | if (request == PTRACE_SYSCALL) { | ||
138 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
139 | } | ||
140 | else { | ||
141 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
142 | } | ||
143 | |||
144 | child->exit_code = data; | ||
145 | |||
146 | /* TODO: make sure any pending breakpoint is killed */ | ||
147 | wake_up_process(child); | ||
148 | ret = 0; | ||
149 | |||
150 | break; | ||
151 | |||
152 | /* Make the child exit by sending it a sigkill. */ | ||
153 | case PTRACE_KILL: | ||
154 | ret = 0; | ||
155 | |||
156 | if (child->exit_state == EXIT_ZOMBIE) | ||
157 | break; | ||
158 | |||
159 | child->exit_code = SIGKILL; | ||
160 | |||
161 | /* TODO: make sure any pending breakpoint is killed */ | ||
162 | wake_up_process(child); | ||
163 | break; | ||
164 | |||
165 | /* Set the trap flag. */ | ||
166 | case PTRACE_SINGLESTEP: | ||
167 | ret = -EIO; | ||
168 | |||
169 | if (!valid_signal(data)) | ||
170 | break; | ||
171 | |||
172 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
173 | |||
174 | /* TODO: set some clever breakpoint mechanism... */ | ||
175 | |||
176 | child->exit_code = data; | ||
177 | wake_up_process(child); | ||
178 | ret = 0; | ||
179 | break; | ||
180 | |||
181 | /* Get all GP registers from the child. */ | 130 | /* Get all GP registers from the child. */ |
182 | case PTRACE_GETREGS: { | 131 | case PTRACE_GETREGS: { |
183 | int i; | 132 | int i; |
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 435b9671bd4b..1f39861eac8c 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S | |||
@@ -615,7 +615,7 @@ sys_call_table: | |||
615 | .long sys_swapon | 615 | .long sys_swapon |
616 | .long sys_reboot | 616 | .long sys_reboot |
617 | .long sys_old_readdir | 617 | .long sys_old_readdir |
618 | .long old_mmap /* 90 */ | 618 | .long sys_old_mmap /* 90 */ |
619 | .long sys_munmap | 619 | .long sys_munmap |
620 | .long sys_truncate | 620 | .long sys_truncate |
621 | .long sys_ftruncate | 621 | .long sys_ftruncate |
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index dd401473f5b5..f4ebd1e7d0f5 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c | |||
@@ -78,6 +78,35 @@ int put_reg(struct task_struct *task, unsigned int regno, unsigned long data) | |||
78 | return 0; | 78 | return 0; |
79 | } | 79 | } |
80 | 80 | ||
81 | void user_enable_single_step(struct task_struct *child) | ||
82 | { | ||
83 | unsigned long tmp; | ||
84 | |||
85 | /* | ||
86 | * Set up SPC if not set already (in which case we have no other | ||
87 | * choice but to trust it). | ||
88 | */ | ||
89 | if (!get_reg(child, PT_SPC)) { | ||
90 | /* In case we're stopped in a delay slot. */ | ||
91 | tmp = get_reg(child, PT_ERP) & ~1; | ||
92 | put_reg(child, PT_SPC, tmp); | ||
93 | } | ||
94 | tmp = get_reg(child, PT_CCS) | SBIT_USER; | ||
95 | put_reg(child, PT_CCS, tmp); | ||
96 | } | ||
97 | |||
98 | void user_disable_single_step(struct task_struct *child) | ||
99 | { | ||
100 | put_reg(child, PT_SPC, 0); | ||
101 | |||
102 | if (!get_debugreg(child->pid, PT_BP_CTRL)) { | ||
103 | unsigned long tmp; | ||
104 | /* If no h/w bp configured, disable S bit. */ | ||
105 | tmp = get_reg(child, PT_CCS) & ~SBIT_USER; | ||
106 | put_reg(child, PT_CCS, tmp); | ||
107 | } | ||
108 | } | ||
109 | |||
81 | /* | 110 | /* |
82 | * Called by kernel/ptrace.c when detaching. | 111 | * Called by kernel/ptrace.c when detaching. |
83 | * | 112 | * |
@@ -89,8 +118,7 @@ ptrace_disable(struct task_struct *child) | |||
89 | unsigned long tmp; | 118 | unsigned long tmp; |
90 | 119 | ||
91 | /* Deconfigure SPC and S-bit. */ | 120 | /* Deconfigure SPC and S-bit. */ |
92 | tmp = get_reg(child, PT_CCS) & ~SBIT_USER; | 121 | user_disable_single_step(child); |
93 | put_reg(child, PT_CCS, tmp); | ||
94 | put_reg(child, PT_SPC, 0); | 122 | put_reg(child, PT_SPC, 0); |
95 | 123 | ||
96 | /* Deconfigure any watchpoints associated with the child. */ | 124 | /* Deconfigure any watchpoints associated with the child. */ |
@@ -169,83 +197,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
169 | ret = 0; | 197 | ret = 0; |
170 | break; | 198 | break; |
171 | 199 | ||
172 | case PTRACE_SYSCALL: | ||
173 | case PTRACE_CONT: | ||
174 | ret = -EIO; | ||
175 | |||
176 | if (!valid_signal(data)) | ||
177 | break; | ||
178 | |||
179 | /* Continue means no single-step. */ | ||
180 | put_reg(child, PT_SPC, 0); | ||
181 | |||
182 | if (!get_debugreg(child->pid, PT_BP_CTRL)) { | ||
183 | unsigned long tmp; | ||
184 | /* If no h/w bp configured, disable S bit. */ | ||
185 | tmp = get_reg(child, PT_CCS) & ~SBIT_USER; | ||
186 | put_reg(child, PT_CCS, tmp); | ||
187 | } | ||
188 | |||
189 | if (request == PTRACE_SYSCALL) { | ||
190 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
191 | } | ||
192 | else { | ||
193 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
194 | } | ||
195 | |||
196 | child->exit_code = data; | ||
197 | |||
198 | /* TODO: make sure any pending breakpoint is killed */ | ||
199 | wake_up_process(child); | ||
200 | ret = 0; | ||
201 | |||
202 | break; | ||
203 | |||
204 | /* Make the child exit by sending it a sigkill. */ | ||
205 | case PTRACE_KILL: | ||
206 | ret = 0; | ||
207 | |||
208 | if (child->exit_state == EXIT_ZOMBIE) | ||
209 | break; | ||
210 | |||
211 | child->exit_code = SIGKILL; | ||
212 | |||
213 | /* Deconfigure single-step and h/w bp. */ | ||
214 | ptrace_disable(child); | ||
215 | |||
216 | /* TODO: make sure any pending breakpoint is killed */ | ||
217 | wake_up_process(child); | ||
218 | break; | ||
219 | |||
220 | /* Set the trap flag. */ | ||
221 | case PTRACE_SINGLESTEP: { | ||
222 | unsigned long tmp; | ||
223 | ret = -EIO; | ||
224 | |||
225 | /* Set up SPC if not set already (in which case we have | ||
226 | no other choice but to trust it). */ | ||
227 | if (!get_reg(child, PT_SPC)) { | ||
228 | /* In case we're stopped in a delay slot. */ | ||
229 | tmp = get_reg(child, PT_ERP) & ~1; | ||
230 | put_reg(child, PT_SPC, tmp); | ||
231 | } | ||
232 | tmp = get_reg(child, PT_CCS) | SBIT_USER; | ||
233 | put_reg(child, PT_CCS, tmp); | ||
234 | |||
235 | if (!valid_signal(data)) | ||
236 | break; | ||
237 | |||
238 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
239 | |||
240 | /* TODO: set some clever breakpoint mechanism... */ | ||
241 | |||
242 | child->exit_code = data; | ||
243 | wake_up_process(child); | ||
244 | ret = 0; | ||
245 | break; | ||
246 | |||
247 | } | ||
248 | |||
249 | /* Get all GP registers from the child. */ | 200 | /* Get all GP registers from the child. */ |
250 | case PTRACE_GETREGS: { | 201 | case PTRACE_GETREGS: { |
251 | int i; | 202 | int i; |
diff --git a/arch/cris/include/arch-v32/arch/ptrace.h b/arch/cris/include/arch-v32/arch/ptrace.h index 41f4e8662bc2..ffca8d0f2e17 100644 --- a/arch/cris/include/arch-v32/arch/ptrace.h +++ b/arch/cris/include/arch-v32/arch/ptrace.h | |||
@@ -108,6 +108,7 @@ struct switch_stack { | |||
108 | 108 | ||
109 | #ifdef __KERNEL__ | 109 | #ifdef __KERNEL__ |
110 | 110 | ||
111 | #define arch_has_single_step() (1) | ||
111 | #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0) | 112 | #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0) |
112 | #define instruction_pointer(regs) ((regs)->erp) | 113 | #define instruction_pointer(regs) ((regs)->erp) |
113 | extern void show_regs(struct pt_regs *); | 114 | extern void show_regs(struct pt_regs *); |
diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h index 730ce40fdd0f..9f1cd56da28c 100644 --- a/arch/cris/include/asm/pci.h +++ b/arch/cris/include/asm/pci.h | |||
@@ -44,14 +44,6 @@ struct pci_dev; | |||
44 | */ | 44 | */ |
45 | #define PCI_DMA_BUS_IS_PHYS (1) | 45 | #define PCI_DMA_BUS_IS_PHYS (1) |
46 | 46 | ||
47 | /* pci_unmap_{page,single} is a nop so... */ | ||
48 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
49 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
50 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
51 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
52 | #define pci_unmap_len(PTR, LEN_NAME) (0) | ||
53 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
54 | |||
55 | #define HAVE_PCI_MMAP | 47 | #define HAVE_PCI_MMAP |
56 | extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | 48 | extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, |
57 | enum pci_mmap_state mmap_state, int write_combine); | 49 | enum pci_mmap_state mmap_state, int write_combine); |
diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h index c17079388bb9..f6fad83b3a8c 100644 --- a/arch/cris/include/asm/unistd.h +++ b/arch/cris/include/asm/unistd.h | |||
@@ -352,6 +352,7 @@ | |||
352 | #define __ARCH_WANT_STAT64 | 352 | #define __ARCH_WANT_STAT64 |
353 | #define __ARCH_WANT_SYS_ALARM | 353 | #define __ARCH_WANT_SYS_ALARM |
354 | #define __ARCH_WANT_SYS_GETHOSTNAME | 354 | #define __ARCH_WANT_SYS_GETHOSTNAME |
355 | #define __ARCH_WANT_SYS_IPC | ||
355 | #define __ARCH_WANT_SYS_PAUSE | 356 | #define __ARCH_WANT_SYS_PAUSE |
356 | #define __ARCH_WANT_SYS_SGETMASK | 357 | #define __ARCH_WANT_SYS_SGETMASK |
357 | #define __ARCH_WANT_SYS_SIGNAL | 358 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -364,6 +365,7 @@ | |||
364 | #define __ARCH_WANT_SYS_LLSEEK | 365 | #define __ARCH_WANT_SYS_LLSEEK |
365 | #define __ARCH_WANT_SYS_NICE | 366 | #define __ARCH_WANT_SYS_NICE |
366 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 367 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
368 | #define __ARCH_WANT_SYS_OLD_MMAP | ||
367 | #define __ARCH_WANT_SYS_OLDUMOUNT | 369 | #define __ARCH_WANT_SYS_OLDUMOUNT |
368 | #define __ARCH_WANT_SYS_SIGPENDING | 370 | #define __ARCH_WANT_SYS_SIGPENDING |
369 | #define __ARCH_WANT_SYS_SIGPROCMASK | 371 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c index c2bbb1ac98a9..7aa036ec78ff 100644 --- a/arch/cris/kernel/sys_cris.c +++ b/arch/cris/kernel/sys_cris.c | |||
@@ -26,24 +26,6 @@ | |||
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/segment.h> | 27 | #include <asm/segment.h> |
28 | 28 | ||
29 | asmlinkage unsigned long old_mmap(unsigned long __user *args) | ||
30 | { | ||
31 | unsigned long buffer[6]; | ||
32 | int err = -EFAULT; | ||
33 | |||
34 | if (copy_from_user(&buffer, args, sizeof(buffer))) | ||
35 | goto out; | ||
36 | |||
37 | err = -EINVAL; | ||
38 | if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */ | ||
39 | goto out; | ||
40 | |||
41 | err = sys_mmap_pgoff(buffer[0], buffer[1], buffer[2], buffer[3], | ||
42 | buffer[4], buffer[5] >> PAGE_SHIFT); | ||
43 | out: | ||
44 | return err; | ||
45 | } | ||
46 | |||
47 | asmlinkage long | 29 | asmlinkage long |
48 | sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | 30 | sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, |
49 | unsigned long flags, unsigned long fd, unsigned long pgoff) | 31 | unsigned long flags, unsigned long fd, unsigned long pgoff) |
@@ -51,81 +33,3 @@ sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | |||
51 | /* bug(?): 8Kb pages here */ | 33 | /* bug(?): 8Kb pages here */ |
52 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); | 34 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); |
53 | } | 35 | } |
54 | |||
55 | /* | ||
56 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
57 | * | ||
58 | * This is really horribly ugly. (same as arch/i386) | ||
59 | */ | ||
60 | |||
61 | asmlinkage int sys_ipc (uint call, int first, int second, | ||
62 | int third, void __user *ptr, long fifth) | ||
63 | { | ||
64 | int version, ret; | ||
65 | |||
66 | version = call >> 16; /* hack for backward compatibility */ | ||
67 | call &= 0xffff; | ||
68 | |||
69 | switch (call) { | ||
70 | case SEMOP: | ||
71 | return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); | ||
72 | case SEMTIMEDOP: | ||
73 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, | ||
74 | (const struct timespec __user *)fifth); | ||
75 | |||
76 | case SEMGET: | ||
77 | return sys_semget (first, second, third); | ||
78 | case SEMCTL: { | ||
79 | union semun fourth; | ||
80 | if (!ptr) | ||
81 | return -EINVAL; | ||
82 | if (get_user(fourth.__pad, (void * __user *) ptr)) | ||
83 | return -EFAULT; | ||
84 | return sys_semctl (first, second, third, fourth); | ||
85 | } | ||
86 | |||
87 | case MSGSND: | ||
88 | return sys_msgsnd (first, (struct msgbuf __user *) ptr, | ||
89 | second, third); | ||
90 | case MSGRCV: | ||
91 | switch (version) { | ||
92 | case 0: { | ||
93 | struct ipc_kludge tmp; | ||
94 | if (!ptr) | ||
95 | return -EINVAL; | ||
96 | |||
97 | if (copy_from_user(&tmp, | ||
98 | (struct ipc_kludge __user *) ptr, | ||
99 | sizeof (tmp))) | ||
100 | return -EFAULT; | ||
101 | return sys_msgrcv (first, tmp.msgp, second, | ||
102 | tmp.msgtyp, third); | ||
103 | } | ||
104 | default: | ||
105 | return sys_msgrcv (first, | ||
106 | (struct msgbuf __user *) ptr, | ||
107 | second, fifth, third); | ||
108 | } | ||
109 | case MSGGET: | ||
110 | return sys_msgget ((key_t) first, second); | ||
111 | case MSGCTL: | ||
112 | return sys_msgctl (first, second, (struct msqid_ds __user *) ptr); | ||
113 | |||
114 | case SHMAT: { | ||
115 | ulong raddr; | ||
116 | ret = do_shmat (first, (char __user *) ptr, second, &raddr); | ||
117 | if (ret) | ||
118 | return ret; | ||
119 | return put_user (raddr, (ulong __user *) third); | ||
120 | } | ||
121 | case SHMDT: | ||
122 | return sys_shmdt ((char __user *)ptr); | ||
123 | case SHMGET: | ||
124 | return sys_shmget (first, second, third); | ||
125 | case SHMCTL: | ||
126 | return sys_shmctl (first, second, | ||
127 | (struct shmid_ds __user *) ptr); | ||
128 | default: | ||
129 | return -ENOSYS; | ||
130 | } | ||
131 | } | ||
diff --git a/arch/frv/include/asm/dma-mapping.h b/arch/frv/include/asm/dma-mapping.h index b2898877c07b..6af5d83e2fb2 100644 --- a/arch/frv/include/asm/dma-mapping.h +++ b/arch/frv/include/asm/dma-mapping.h | |||
@@ -7,6 +7,11 @@ | |||
7 | #include <asm/scatterlist.h> | 7 | #include <asm/scatterlist.h> |
8 | #include <asm/io.h> | 8 | #include <asm/io.h> |
9 | 9 | ||
10 | /* | ||
11 | * See Documentation/DMA-API.txt for the description of how the | ||
12 | * following DMA API should work. | ||
13 | */ | ||
14 | |||
10 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | 15 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) |
11 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | 16 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) |
12 | 17 | ||
@@ -16,24 +21,9 @@ extern unsigned long __nongprelbss dma_coherent_mem_end; | |||
16 | void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp); | 21 | void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp); |
17 | void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); | 22 | void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); |
18 | 23 | ||
19 | /* | ||
20 | * Map a single buffer of the indicated size for DMA in streaming mode. | ||
21 | * The 32-bit bus address to use is returned. | ||
22 | * | ||
23 | * Once the device is given the dma address, the device owns this memory | ||
24 | * until either pci_unmap_single or pci_dma_sync_single is performed. | ||
25 | */ | ||
26 | extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 24 | extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, |
27 | enum dma_data_direction direction); | 25 | enum dma_data_direction direction); |
28 | 26 | ||
29 | /* | ||
30 | * Unmap a single streaming mode DMA translation. The dma_addr and size | ||
31 | * must match what was provided for in a previous pci_map_single call. All | ||
32 | * other usages are undefined. | ||
33 | * | ||
34 | * After this call, reads by the cpu to the buffer are guarenteed to see | ||
35 | * whatever the device wrote there. | ||
36 | */ | ||
37 | static inline | 27 | static inline |
38 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 28 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, |
39 | enum dma_data_direction direction) | 29 | enum dma_data_direction direction) |
@@ -41,30 +31,9 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
41 | BUG_ON(direction == DMA_NONE); | 31 | BUG_ON(direction == DMA_NONE); |
42 | } | 32 | } |
43 | 33 | ||
44 | /* | ||
45 | * Map a set of buffers described by scatterlist in streaming | ||
46 | * mode for DMA. This is the scather-gather version of the | ||
47 | * above pci_map_single interface. Here the scatter gather list | ||
48 | * elements are each tagged with the appropriate dma address | ||
49 | * and length. They are obtained via sg_dma_{address,length}(SG). | ||
50 | * | ||
51 | * NOTE: An implementation may be able to use a smaller number of | ||
52 | * DMA address/length pairs than there are SG table elements. | ||
53 | * (for example via virtual mapping capabilities) | ||
54 | * The routine returns the number of addr/length pairs actually | ||
55 | * used, at most nents. | ||
56 | * | ||
57 | * Device ownership issues as mentioned above for pci_map_single are | ||
58 | * the same here. | ||
59 | */ | ||
60 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 34 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, |
61 | enum dma_data_direction direction); | 35 | enum dma_data_direction direction); |
62 | 36 | ||
63 | /* | ||
64 | * Unmap a set of streaming mode DMA translations. | ||
65 | * Again, cpu read rules concerning calls here are the same as for | ||
66 | * pci_unmap_single() above. | ||
67 | */ | ||
68 | static inline | 37 | static inline |
69 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | 38 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, |
70 | enum dma_data_direction direction) | 39 | enum dma_data_direction direction) |
diff --git a/arch/frv/include/asm/pci.h b/arch/frv/include/asm/pci.h index 8c7260a3cd41..0d5997909850 100644 --- a/arch/frv/include/asm/pci.h +++ b/arch/frv/include/asm/pci.h | |||
@@ -43,14 +43,6 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, | |||
43 | /* Return the index of the PCI controller for device PDEV. */ | 43 | /* Return the index of the PCI controller for device PDEV. */ |
44 | #define pci_controller_num(PDEV) (0) | 44 | #define pci_controller_num(PDEV) (0) |
45 | 45 | ||
46 | /* pci_unmap_{page,single} is a nop so... */ | ||
47 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
48 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
49 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
50 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
51 | #define pci_unmap_len(PTR, LEN_NAME) (0) | ||
52 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
53 | |||
54 | #ifdef CONFIG_PCI | 46 | #ifdef CONFIG_PCI |
55 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, | 47 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, |
56 | enum pci_dma_burst_strategy *strat, | 48 | enum pci_dma_burst_strategy *strat, |
diff --git a/arch/frv/include/asm/ptrace.h b/arch/frv/include/asm/ptrace.h index a54b535c9e49..6bfad4cf1907 100644 --- a/arch/frv/include/asm/ptrace.h +++ b/arch/frv/include/asm/ptrace.h | |||
@@ -84,8 +84,6 @@ extern void show_regs(struct pt_regs *); | |||
84 | #define task_pt_regs(task) ((task)->thread.frame0) | 84 | #define task_pt_regs(task) ((task)->thread.frame0) |
85 | 85 | ||
86 | #define arch_has_single_step() (1) | 86 | #define arch_has_single_step() (1) |
87 | extern void user_enable_single_step(struct task_struct *); | ||
88 | extern void user_disable_single_step(struct task_struct *); | ||
89 | 87 | ||
90 | #endif /* !__ASSEMBLY__ */ | 88 | #endif /* !__ASSEMBLY__ */ |
91 | #endif /* __KERNEL__ */ | 89 | #endif /* __KERNEL__ */ |
diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h index be6ef0f5cd42..b28da499e22a 100644 --- a/arch/frv/include/asm/unistd.h +++ b/arch/frv/include/asm/unistd.h | |||
@@ -354,6 +354,7 @@ | |||
354 | #define __ARCH_WANT_STAT64 | 354 | #define __ARCH_WANT_STAT64 |
355 | #define __ARCH_WANT_SYS_ALARM | 355 | #define __ARCH_WANT_SYS_ALARM |
356 | /* #define __ARCH_WANT_SYS_GETHOSTNAME */ | 356 | /* #define __ARCH_WANT_SYS_GETHOSTNAME */ |
357 | #define __ARCH_WANT_SYS_IPC | ||
357 | #define __ARCH_WANT_SYS_PAUSE | 358 | #define __ARCH_WANT_SYS_PAUSE |
358 | /* #define __ARCH_WANT_SYS_SGETMASK */ | 359 | /* #define __ARCH_WANT_SYS_SGETMASK */ |
359 | /* #define __ARCH_WANT_SYS_SIGNAL */ | 360 | /* #define __ARCH_WANT_SYS_SIGNAL */ |
diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c index 1d3d4c9e2521..9c4980825bbb 100644 --- a/arch/frv/kernel/sys_frv.c +++ b/arch/frv/kernel/sys_frv.c | |||
@@ -42,92 +42,3 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | |||
42 | return sys_mmap_pgoff(addr, len, prot, flags, fd, | 42 | return sys_mmap_pgoff(addr, len, prot, flags, fd, |
43 | pgoff >> (PAGE_SHIFT - 12)); | 43 | pgoff >> (PAGE_SHIFT - 12)); |
44 | } | 44 | } |
45 | |||
46 | /* | ||
47 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
48 | * | ||
49 | * This is really horribly ugly. | ||
50 | */ | ||
51 | asmlinkage long sys_ipc(unsigned long call, | ||
52 | unsigned long first, | ||
53 | unsigned long second, | ||
54 | unsigned long third, | ||
55 | void __user *ptr, | ||
56 | unsigned long fifth) | ||
57 | { | ||
58 | int version, ret; | ||
59 | |||
60 | version = call >> 16; /* hack for backward compatibility */ | ||
61 | call &= 0xffff; | ||
62 | |||
63 | switch (call) { | ||
64 | case SEMOP: | ||
65 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL); | ||
66 | case SEMTIMEDOP: | ||
67 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, | ||
68 | (const struct timespec __user *)fifth); | ||
69 | |||
70 | case SEMGET: | ||
71 | return sys_semget (first, second, third); | ||
72 | case SEMCTL: { | ||
73 | union semun fourth; | ||
74 | if (!ptr) | ||
75 | return -EINVAL; | ||
76 | if (get_user(fourth.__pad, (void * __user *) ptr)) | ||
77 | return -EFAULT; | ||
78 | return sys_semctl (first, second, third, fourth); | ||
79 | } | ||
80 | |||
81 | case MSGSND: | ||
82 | return sys_msgsnd (first, (struct msgbuf __user *) ptr, | ||
83 | second, third); | ||
84 | case MSGRCV: | ||
85 | switch (version) { | ||
86 | case 0: { | ||
87 | struct ipc_kludge tmp; | ||
88 | if (!ptr) | ||
89 | return -EINVAL; | ||
90 | |||
91 | if (copy_from_user(&tmp, | ||
92 | (struct ipc_kludge __user *) ptr, | ||
93 | sizeof (tmp))) | ||
94 | return -EFAULT; | ||
95 | return sys_msgrcv (first, tmp.msgp, second, | ||
96 | tmp.msgtyp, third); | ||
97 | } | ||
98 | default: | ||
99 | return sys_msgrcv (first, | ||
100 | (struct msgbuf __user *) ptr, | ||
101 | second, fifth, third); | ||
102 | } | ||
103 | case MSGGET: | ||
104 | return sys_msgget ((key_t) first, second); | ||
105 | case MSGCTL: | ||
106 | return sys_msgctl (first, second, (struct msqid_ds __user *) ptr); | ||
107 | |||
108 | case SHMAT: | ||
109 | switch (version) { | ||
110 | default: { | ||
111 | ulong raddr; | ||
112 | ret = do_shmat (first, (char __user *) ptr, second, &raddr); | ||
113 | if (ret) | ||
114 | return ret; | ||
115 | return put_user (raddr, (ulong __user *) third); | ||
116 | } | ||
117 | case 1: /* iBCS2 emulator entry point */ | ||
118 | if (!segment_eq(get_fs(), get_ds())) | ||
119 | return -EINVAL; | ||
120 | /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */ | ||
121 | return do_shmat (first, (char __user *) ptr, second, (ulong *) third); | ||
122 | } | ||
123 | case SHMDT: | ||
124 | return sys_shmdt ((char __user *)ptr); | ||
125 | case SHMGET: | ||
126 | return sys_shmget (first, second, third); | ||
127 | case SHMCTL: | ||
128 | return sys_shmctl (first, second, | ||
129 | (struct shmid_ds __user *) ptr); | ||
130 | default: | ||
131 | return -ENOSYS; | ||
132 | } | ||
133 | } | ||
diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c index 4e1ba0b15443..e47857f889b6 100644 --- a/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c | |||
@@ -106,13 +106,6 @@ void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_ | |||
106 | 106 | ||
107 | EXPORT_SYMBOL(dma_free_coherent); | 107 | EXPORT_SYMBOL(dma_free_coherent); |
108 | 108 | ||
109 | /* | ||
110 | * Map a single buffer of the indicated size for DMA in streaming mode. | ||
111 | * The 32-bit bus address to use is returned. | ||
112 | * | ||
113 | * Once the device is given the dma address, the device owns this memory | ||
114 | * until either dma_unmap_single or pci_dma_sync_single is performed. | ||
115 | */ | ||
116 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 109 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, |
117 | enum dma_data_direction direction) | 110 | enum dma_data_direction direction) |
118 | { | 111 | { |
@@ -125,22 +118,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
125 | 118 | ||
126 | EXPORT_SYMBOL(dma_map_single); | 119 | EXPORT_SYMBOL(dma_map_single); |
127 | 120 | ||
128 | /* | ||
129 | * Map a set of buffers described by scatterlist in streaming | ||
130 | * mode for DMA. This is the scather-gather version of the | ||
131 | * above dma_map_single interface. Here the scatter gather list | ||
132 | * elements are each tagged with the appropriate dma address | ||
133 | * and length. They are obtained via sg_dma_{address,length}(SG). | ||
134 | * | ||
135 | * NOTE: An implementation may be able to use a smaller number of | ||
136 | * DMA address/length pairs than there are SG table elements. | ||
137 | * (for example via virtual mapping capabilities) | ||
138 | * The routine returns the number of addr/length pairs actually | ||
139 | * used, at most nents. | ||
140 | * | ||
141 | * Device ownership issues as mentioned above for dma_map_single are | ||
142 | * the same here. | ||
143 | */ | ||
144 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 121 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, |
145 | enum dma_data_direction direction) | 122 | enum dma_data_direction direction) |
146 | { | 123 | { |
@@ -157,13 +134,6 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
157 | 134 | ||
158 | EXPORT_SYMBOL(dma_map_sg); | 135 | EXPORT_SYMBOL(dma_map_sg); |
159 | 136 | ||
160 | /* | ||
161 | * Map a single page of the indicated size for DMA in streaming mode. | ||
162 | * The 32-bit bus address to use is returned. | ||
163 | * | ||
164 | * Device ownership issues as mentioned above for dma_map_single are | ||
165 | * the same here. | ||
166 | */ | ||
167 | dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, | 137 | dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, |
168 | size_t size, enum dma_data_direction direction) | 138 | size_t size, enum dma_data_direction direction) |
169 | { | 139 | { |
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c index 45954f0813dc..2c912e805162 100644 --- a/arch/frv/mb93090-mb00/pci-dma.c +++ b/arch/frv/mb93090-mb00/pci-dma.c | |||
@@ -38,13 +38,6 @@ void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_ | |||
38 | 38 | ||
39 | EXPORT_SYMBOL(dma_free_coherent); | 39 | EXPORT_SYMBOL(dma_free_coherent); |
40 | 40 | ||
41 | /* | ||
42 | * Map a single buffer of the indicated size for DMA in streaming mode. | ||
43 | * The 32-bit bus address to use is returned. | ||
44 | * | ||
45 | * Once the device is given the dma address, the device owns this memory | ||
46 | * until either pci_unmap_single or pci_dma_sync_single is performed. | ||
47 | */ | ||
48 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 41 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, |
49 | enum dma_data_direction direction) | 42 | enum dma_data_direction direction) |
50 | { | 43 | { |
@@ -57,22 +50,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
57 | 50 | ||
58 | EXPORT_SYMBOL(dma_map_single); | 51 | EXPORT_SYMBOL(dma_map_single); |
59 | 52 | ||
60 | /* | ||
61 | * Map a set of buffers described by scatterlist in streaming | ||
62 | * mode for DMA. This is the scather-gather version of the | ||
63 | * above dma_map_single interface. Here the scatter gather list | ||
64 | * elements are each tagged with the appropriate dma address | ||
65 | * and length. They are obtained via sg_dma_{address,length}(SG). | ||
66 | * | ||
67 | * NOTE: An implementation may be able to use a smaller number of | ||
68 | * DMA address/length pairs than there are SG table elements. | ||
69 | * (for example via virtual mapping capabilities) | ||
70 | * The routine returns the number of addr/length pairs actually | ||
71 | * used, at most nents. | ||
72 | * | ||
73 | * Device ownership issues as mentioned above for dma_map_single are | ||
74 | * the same here. | ||
75 | */ | ||
76 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 53 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, |
77 | enum dma_data_direction direction) | 54 | enum dma_data_direction direction) |
78 | { | 55 | { |
@@ -103,13 +80,6 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
103 | 80 | ||
104 | EXPORT_SYMBOL(dma_map_sg); | 81 | EXPORT_SYMBOL(dma_map_sg); |
105 | 82 | ||
106 | /* | ||
107 | * Map a single page of the indicated size for DMA in streaming mode. | ||
108 | * The 32-bit bus address to use is returned. | ||
109 | * | ||
110 | * Device ownership issues as mentioned above for dma_map_single are | ||
111 | * the same here. | ||
112 | */ | ||
113 | dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, | 83 | dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, |
114 | size_t size, enum dma_data_direction direction) | 84 | size_t size, enum dma_data_direction direction) |
115 | { | 85 | { |
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h index c2e05e4b512e..d866c0efba87 100644 --- a/arch/h8300/include/asm/ptrace.h +++ b/arch/h8300/include/asm/ptrace.h | |||
@@ -55,6 +55,8 @@ struct pt_regs { | |||
55 | /* Find the stack offset for a register, relative to thread.esp0. */ | 55 | /* Find the stack offset for a register, relative to thread.esp0. */ |
56 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) | 56 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) |
57 | 57 | ||
58 | #define arch_has_single_step() (1) | ||
59 | |||
58 | #define user_mode(regs) (!((regs)->ccr & PS_S)) | 60 | #define user_mode(regs) (!((regs)->ccr & PS_S)) |
59 | #define instruction_pointer(regs) ((regs)->pc) | 61 | #define instruction_pointer(regs) ((regs)->pc) |
60 | #define profile_pc(regs) instruction_pointer(regs) | 62 | #define profile_pc(regs) instruction_pointer(regs) |
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h index 99f3c3561ecb..50f2c5a36591 100644 --- a/arch/h8300/include/asm/unistd.h +++ b/arch/h8300/include/asm/unistd.h | |||
@@ -336,6 +336,7 @@ | |||
336 | #define __ARCH_WANT_STAT64 | 336 | #define __ARCH_WANT_STAT64 |
337 | #define __ARCH_WANT_SYS_ALARM | 337 | #define __ARCH_WANT_SYS_ALARM |
338 | #define __ARCH_WANT_SYS_GETHOSTNAME | 338 | #define __ARCH_WANT_SYS_GETHOSTNAME |
339 | #define __ARCH_WANT_SYS_IPC | ||
339 | #define __ARCH_WANT_SYS_PAUSE | 340 | #define __ARCH_WANT_SYS_PAUSE |
340 | #define __ARCH_WANT_SYS_SGETMASK | 341 | #define __ARCH_WANT_SYS_SGETMASK |
341 | #define __ARCH_WANT_SYS_SIGNAL | 342 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -348,6 +349,8 @@ | |||
348 | #define __ARCH_WANT_SYS_LLSEEK | 349 | #define __ARCH_WANT_SYS_LLSEEK |
349 | #define __ARCH_WANT_SYS_NICE | 350 | #define __ARCH_WANT_SYS_NICE |
350 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 351 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
352 | #define __ARCH_WANT_SYS_OLD_MMAP | ||
353 | #define __ARCH_WANT_SYS_OLD_SELECT | ||
351 | #define __ARCH_WANT_SYS_OLDUMOUNT | 354 | #define __ARCH_WANT_SYS_OLDUMOUNT |
352 | #define __ARCH_WANT_SYS_SIGPENDING | 355 | #define __ARCH_WANT_SYS_SIGPENDING |
353 | #define __ARCH_WANT_SYS_SIGPROCMASK | 356 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index d32bbf02fc48..df114122ebdf 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c | |||
@@ -34,25 +34,20 @@ | |||
34 | /* cpu depend functions */ | 34 | /* cpu depend functions */ |
35 | extern long h8300_get_reg(struct task_struct *task, int regno); | 35 | extern long h8300_get_reg(struct task_struct *task, int regno); |
36 | extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data); | 36 | extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data); |
37 | extern void h8300_disable_trace(struct task_struct *child); | 37 | |
38 | extern void h8300_enable_trace(struct task_struct *child); | 38 | |
39 | void user_disable_single_step(struct task_struct *child) | ||
40 | { | ||
41 | } | ||
39 | 42 | ||
40 | /* | 43 | /* |
41 | * does not yet catch signals sent when the child dies. | 44 | * does not yet catch signals sent when the child dies. |
42 | * in exit.c or in signal.c. | 45 | * in exit.c or in signal.c. |
43 | */ | 46 | */ |
44 | 47 | ||
45 | inline | ||
46 | static int read_long(struct task_struct * tsk, unsigned long addr, | ||
47 | unsigned long * result) | ||
48 | { | ||
49 | *result = *(unsigned long *)addr; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | void ptrace_disable(struct task_struct *child) | 48 | void ptrace_disable(struct task_struct *child) |
54 | { | 49 | { |
55 | h8300_disable_trace(child); | 50 | user_disable_single_step(child); |
56 | } | 51 | } |
57 | 52 | ||
58 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 53 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
@@ -60,17 +55,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
60 | int ret; | 55 | int ret; |
61 | 56 | ||
62 | switch (request) { | 57 | switch (request) { |
63 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
64 | case PTRACE_PEEKDATA: { | ||
65 | unsigned long tmp; | ||
66 | |||
67 | ret = read_long(child, addr, &tmp); | ||
68 | if (ret < 0) | ||
69 | break ; | ||
70 | ret = put_user(tmp, (unsigned long *) data); | ||
71 | break ; | ||
72 | } | ||
73 | |||
74 | /* read the word at location addr in the USER area. */ | 58 | /* read the word at location addr in the USER area. */ |
75 | case PTRACE_PEEKUSR: { | 59 | case PTRACE_PEEKUSR: { |
76 | unsigned long tmp = 0; | 60 | unsigned long tmp = 0; |
@@ -109,11 +93,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
109 | } | 93 | } |
110 | 94 | ||
111 | /* when I and D space are separate, this will have to be fixed. */ | 95 | /* when I and D space are separate, this will have to be fixed. */ |
112 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
113 | case PTRACE_POKEDATA: | ||
114 | ret = generic_ptrace_pokedata(child, addr, data); | ||
115 | break; | ||
116 | |||
117 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 96 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
118 | if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { | 97 | if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { |
119 | ret = -EIO; | 98 | ret = -EIO; |
@@ -131,53 +110,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
131 | } | 110 | } |
132 | ret = -EIO; | 111 | ret = -EIO; |
133 | break ; | 112 | break ; |
134 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
135 | case PTRACE_CONT: { /* restart after signal. */ | ||
136 | ret = -EIO; | ||
137 | if (!valid_signal(data)) | ||
138 | break ; | ||
139 | if (request == PTRACE_SYSCALL) | ||
140 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
141 | else | ||
142 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
143 | child->exit_code = data; | ||
144 | wake_up_process(child); | ||
145 | /* make sure the single step bit is not set. */ | ||
146 | h8300_disable_trace(child); | ||
147 | ret = 0; | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * make the child exit. Best I can do is send it a sigkill. | ||
152 | * perhaps it should be put in the status that it wants to | ||
153 | * exit. | ||
154 | */ | ||
155 | case PTRACE_KILL: { | ||
156 | |||
157 | ret = 0; | ||
158 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
159 | break; | ||
160 | child->exit_code = SIGKILL; | ||
161 | h8300_disable_trace(child); | ||
162 | wake_up_process(child); | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
167 | ret = -EIO; | ||
168 | if (!valid_signal(data)) | ||
169 | break; | ||
170 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
171 | child->exit_code = data; | ||
172 | h8300_enable_trace(child); | ||
173 | wake_up_process(child); | ||
174 | ret = 0; | ||
175 | break; | ||
176 | } | ||
177 | |||
178 | case PTRACE_DETACH: /* detach a process that was attached. */ | ||
179 | ret = ptrace_detach(child, data); | ||
180 | break; | ||
181 | 113 | ||
182 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 114 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ |
183 | int i; | 115 | int i; |
@@ -210,7 +142,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
210 | } | 142 | } |
211 | 143 | ||
212 | default: | 144 | default: |
213 | ret = -EIO; | 145 | ret = ptrace_request(child, request, addr, data); |
214 | break; | 146 | break; |
215 | } | 147 | } |
216 | return ret; | 148 | return ret; |
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c index b5969db0ca10..f9b3f44da69f 100644 --- a/arch/h8300/kernel/sys_h8300.c +++ b/arch/h8300/kernel/sys_h8300.c | |||
@@ -26,144 +26,6 @@ | |||
26 | #include <asm/traps.h> | 26 | #include <asm/traps.h> |
27 | #include <asm/unistd.h> | 27 | #include <asm/unistd.h> |
28 | 28 | ||
29 | /* | ||
30 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
31 | * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to | ||
32 | * handle more than 4 system call parameters, so these system calls | ||
33 | * used a memory block for parameter passing.. | ||
34 | */ | ||
35 | |||
36 | struct mmap_arg_struct { | ||
37 | unsigned long addr; | ||
38 | unsigned long len; | ||
39 | unsigned long prot; | ||
40 | unsigned long flags; | ||
41 | unsigned long fd; | ||
42 | unsigned long offset; | ||
43 | }; | ||
44 | |||
45 | asmlinkage int old_mmap(struct mmap_arg_struct *arg) | ||
46 | { | ||
47 | struct mmap_arg_struct a; | ||
48 | int error = -EFAULT; | ||
49 | |||
50 | if (copy_from_user(&a, arg, sizeof(a))) | ||
51 | goto out; | ||
52 | |||
53 | error = -EINVAL; | ||
54 | if (a.offset & ~PAGE_MASK) | ||
55 | goto out; | ||
56 | |||
57 | error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, | ||
58 | a.offset >> PAGE_SHIFT); | ||
59 | out: | ||
60 | return error; | ||
61 | } | ||
62 | |||
63 | struct sel_arg_struct { | ||
64 | unsigned long n; | ||
65 | fd_set *inp, *outp, *exp; | ||
66 | struct timeval *tvp; | ||
67 | }; | ||
68 | |||
69 | asmlinkage int old_select(struct sel_arg_struct *arg) | ||
70 | { | ||
71 | struct sel_arg_struct a; | ||
72 | |||
73 | if (copy_from_user(&a, arg, sizeof(a))) | ||
74 | return -EFAULT; | ||
75 | /* sys_select() does the appropriate kernel locking */ | ||
76 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
81 | * | ||
82 | * This is really horribly ugly. | ||
83 | */ | ||
84 | asmlinkage int sys_ipc (uint call, int first, int second, | ||
85 | int third, void *ptr, long fifth) | ||
86 | { | ||
87 | int version, ret; | ||
88 | |||
89 | version = call >> 16; /* hack for backward compatibility */ | ||
90 | call &= 0xffff; | ||
91 | |||
92 | if (call <= SEMCTL) | ||
93 | switch (call) { | ||
94 | case SEMOP: | ||
95 | return sys_semop (first, (struct sembuf *)ptr, second); | ||
96 | case SEMGET: | ||
97 | return sys_semget (first, second, third); | ||
98 | case SEMCTL: { | ||
99 | union semun fourth; | ||
100 | if (!ptr) | ||
101 | return -EINVAL; | ||
102 | if (get_user(fourth.__pad, (void **) ptr)) | ||
103 | return -EFAULT; | ||
104 | return sys_semctl (first, second, third, fourth); | ||
105 | } | ||
106 | default: | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | if (call <= MSGCTL) | ||
110 | switch (call) { | ||
111 | case MSGSND: | ||
112 | return sys_msgsnd (first, (struct msgbuf *) ptr, | ||
113 | second, third); | ||
114 | case MSGRCV: | ||
115 | switch (version) { | ||
116 | case 0: { | ||
117 | struct ipc_kludge tmp; | ||
118 | if (!ptr) | ||
119 | return -EINVAL; | ||
120 | if (copy_from_user (&tmp, | ||
121 | (struct ipc_kludge *)ptr, | ||
122 | sizeof (tmp))) | ||
123 | return -EFAULT; | ||
124 | return sys_msgrcv (first, tmp.msgp, second, | ||
125 | tmp.msgtyp, third); | ||
126 | } | ||
127 | default: | ||
128 | return sys_msgrcv (first, | ||
129 | (struct msgbuf *) ptr, | ||
130 | second, fifth, third); | ||
131 | } | ||
132 | case MSGGET: | ||
133 | return sys_msgget ((key_t) first, second); | ||
134 | case MSGCTL: | ||
135 | return sys_msgctl (first, second, | ||
136 | (struct msqid_ds *) ptr); | ||
137 | default: | ||
138 | return -EINVAL; | ||
139 | } | ||
140 | if (call <= SHMCTL) | ||
141 | switch (call) { | ||
142 | case SHMAT: | ||
143 | switch (version) { | ||
144 | default: { | ||
145 | ulong raddr; | ||
146 | ret = do_shmat (first, (char *) ptr, | ||
147 | second, &raddr); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | return put_user (raddr, (ulong *) third); | ||
151 | } | ||
152 | } | ||
153 | case SHMDT: | ||
154 | return sys_shmdt ((char *)ptr); | ||
155 | case SHMGET: | ||
156 | return sys_shmget (first, second, third); | ||
157 | case SHMCTL: | ||
158 | return sys_shmctl (first, second, | ||
159 | (struct shmid_ds *) ptr); | ||
160 | default: | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | /* sys_cacheflush -- no support. */ | 29 | /* sys_cacheflush -- no support. */ |
168 | asmlinkage int | 30 | asmlinkage int |
169 | sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) | 31 | sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) |
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index 2d69881eda6a..faefaff7d43d 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S | |||
@@ -96,7 +96,7 @@ SYMBOL_NAME_LABEL(sys_call_table) | |||
96 | .long SYMBOL_NAME(sys_settimeofday) | 96 | .long SYMBOL_NAME(sys_settimeofday) |
97 | .long SYMBOL_NAME(sys_getgroups16) /* 80 */ | 97 | .long SYMBOL_NAME(sys_getgroups16) /* 80 */ |
98 | .long SYMBOL_NAME(sys_setgroups16) | 98 | .long SYMBOL_NAME(sys_setgroups16) |
99 | .long SYMBOL_NAME(old_select) | 99 | .long SYMBOL_NAME(sys_old_select) |
100 | .long SYMBOL_NAME(sys_symlink) | 100 | .long SYMBOL_NAME(sys_symlink) |
101 | .long SYMBOL_NAME(sys_lstat) | 101 | .long SYMBOL_NAME(sys_lstat) |
102 | .long SYMBOL_NAME(sys_readlink) /* 85 */ | 102 | .long SYMBOL_NAME(sys_readlink) /* 85 */ |
@@ -104,7 +104,7 @@ SYMBOL_NAME_LABEL(sys_call_table) | |||
104 | .long SYMBOL_NAME(sys_swapon) | 104 | .long SYMBOL_NAME(sys_swapon) |
105 | .long SYMBOL_NAME(sys_reboot) | 105 | .long SYMBOL_NAME(sys_reboot) |
106 | .long SYMBOL_NAME(sys_old_readdir) | 106 | .long SYMBOL_NAME(sys_old_readdir) |
107 | .long SYMBOL_NAME(old_mmap) /* 90 */ | 107 | .long SYMBOL_NAME(sys_old_mmap) /* 90 */ |
108 | .long SYMBOL_NAME(sys_munmap) | 108 | .long SYMBOL_NAME(sys_munmap) |
109 | .long SYMBOL_NAME(sys_truncate) | 109 | .long SYMBOL_NAME(sys_truncate) |
110 | .long SYMBOL_NAME(sys_ftruncate) | 110 | .long SYMBOL_NAME(sys_ftruncate) |
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c index 746b1ae672a1..4f1ed0279633 100644 --- a/arch/h8300/platform/h8300h/ptrace_h8300h.c +++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c | |||
@@ -60,7 +60,7 @@ int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | /* disable singlestep */ | 62 | /* disable singlestep */ |
63 | void h8300_disable_trace(struct task_struct *child) | 63 | void user_disable_single_step(struct task_struct *child) |
64 | { | 64 | { |
65 | if((long)child->thread.breakinfo.addr != -1L) { | 65 | if((long)child->thread.breakinfo.addr != -1L) { |
66 | *child->thread.breakinfo.addr = child->thread.breakinfo.inst; | 66 | *child->thread.breakinfo.addr = child->thread.breakinfo.inst; |
@@ -264,7 +264,7 @@ static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc) | |||
264 | 264 | ||
265 | /* Set breakpoint(s) to simulate a single step from the current PC. */ | 265 | /* Set breakpoint(s) to simulate a single step from the current PC. */ |
266 | 266 | ||
267 | void h8300_enable_trace(struct task_struct *child) | 267 | void user_enable_single_step(struct task_struct *child) |
268 | { | 268 | { |
269 | unsigned short *nextpc; | 269 | unsigned short *nextpc; |
270 | nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC)); | 270 | nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC)); |
@@ -276,7 +276,7 @@ void h8300_enable_trace(struct task_struct *child) | |||
276 | asmlinkage void trace_trap(unsigned long bp) | 276 | asmlinkage void trace_trap(unsigned long bp) |
277 | { | 277 | { |
278 | if ((unsigned long)current->thread.breakinfo.addr == bp) { | 278 | if ((unsigned long)current->thread.breakinfo.addr == bp) { |
279 | h8300_disable_trace(current); | 279 | user_disable_single_step(current); |
280 | force_sig(SIGTRAP,current); | 280 | force_sig(SIGTRAP,current); |
281 | } else | 281 | } else |
282 | force_sig(SIGILL,current); | 282 | force_sig(SIGILL,current); |
diff --git a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c index e8cd46f9255c..c058ab1a8495 100644 --- a/arch/h8300/platform/h8s/ptrace_h8s.c +++ b/arch/h8300/platform/h8s/ptrace_h8s.c | |||
@@ -65,13 +65,13 @@ int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) | |||
65 | } | 65 | } |
66 | 66 | ||
67 | /* disable singlestep */ | 67 | /* disable singlestep */ |
68 | void h8300_disable_trace(struct task_struct *child) | 68 | void user_disable_single_step(struct task_struct *child) |
69 | { | 69 | { |
70 | *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE; | 70 | *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE; |
71 | } | 71 | } |
72 | 72 | ||
73 | /* enable singlestep */ | 73 | /* enable singlestep */ |
74 | void h8300_enable_trace(struct task_struct *child) | 74 | void user_enable_single_step(struct task_struct *child) |
75 | { | 75 | { |
76 | *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE; | 76 | *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE; |
77 | } | 77 | } |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 9a50d7dd2a0b..4d4f4188cdf1 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -53,6 +53,9 @@ config MMU | |||
53 | bool | 53 | bool |
54 | default y | 54 | default y |
55 | 55 | ||
56 | config NEED_DMA_MAP_STATE | ||
57 | def_bool y | ||
58 | |||
56 | config SWIOTLB | 59 | config SWIOTLB |
57 | bool | 60 | bool |
58 | 61 | ||
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index dfcf75b8426d..f90edc85b509 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h | |||
@@ -5,7 +5,8 @@ | |||
5 | */ | 5 | */ |
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | 7 | ||
8 | #define COMPAT_USER_HZ 100 | 8 | #define COMPAT_USER_HZ 100 |
9 | #define COMPAT_UTS_MACHINE "i686\0\0\0" | ||
9 | 10 | ||
10 | typedef u32 compat_size_t; | 11 | typedef u32 compat_size_t; |
11 | typedef s32 compat_ssize_t; | 12 | typedef s32 compat_ssize_t; |
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h index 55281aabe5f2..73b5f785e70c 100644 --- a/arch/ia64/include/asm/pci.h +++ b/arch/ia64/include/asm/pci.h | |||
@@ -56,20 +56,6 @@ pcibios_penalize_isa_irq (int irq, int active) | |||
56 | 56 | ||
57 | #include <asm-generic/pci-dma-compat.h> | 57 | #include <asm-generic/pci-dma-compat.h> |
58 | 58 | ||
59 | /* pci_unmap_{single,page} is not a nop, thus... */ | ||
60 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | ||
61 | dma_addr_t ADDR_NAME; | ||
62 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | ||
63 | __u32 LEN_NAME; | ||
64 | #define pci_unmap_addr(PTR, ADDR_NAME) \ | ||
65 | ((PTR)->ADDR_NAME) | ||
66 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
67 | (((PTR)->ADDR_NAME) = (VAL)) | ||
68 | #define pci_unmap_len(PTR, LEN_NAME) \ | ||
69 | ((PTR)->LEN_NAME) | ||
70 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
71 | (((PTR)->LEN_NAME) = (VAL)) | ||
72 | |||
73 | #ifdef CONFIG_PCI | 59 | #ifdef CONFIG_PCI |
74 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, | 60 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, |
75 | enum pci_dma_burst_strategy *strat, | 61 | enum pci_dma_burst_strategy *strat, |
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h index 14055c636adf..7ae9c3f15a1c 100644 --- a/arch/ia64/include/asm/ptrace.h +++ b/arch/ia64/include/asm/ptrace.h | |||
@@ -319,11 +319,7 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) | |||
319 | ptrace_attach_sync_user_rbs(child) | 319 | ptrace_attach_sync_user_rbs(child) |
320 | 320 | ||
321 | #define arch_has_single_step() (1) | 321 | #define arch_has_single_step() (1) |
322 | extern void user_enable_single_step(struct task_struct *); | ||
323 | extern void user_disable_single_step(struct task_struct *); | ||
324 | |||
325 | #define arch_has_block_step() (1) | 322 | #define arch_has_block_step() (1) |
326 | extern void user_enable_block_step(struct task_struct *); | ||
327 | 323 | ||
328 | #endif /* !__KERNEL__ */ | 324 | #endif /* !__KERNEL__ */ |
329 | 325 | ||
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 8f060352e129..b3a5818088d9 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c | |||
@@ -282,7 +282,7 @@ static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char * | |||
282 | return ret; | 282 | return ret; |
283 | } | 283 | } |
284 | 284 | ||
285 | static struct sysfs_ops cache_sysfs_ops = { | 285 | static const struct sysfs_ops cache_sysfs_ops = { |
286 | .show = cache_show | 286 | .show = cache_show |
287 | }; | 287 | }; |
288 | 288 | ||
diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h index a0755b982028..840a1231edeb 100644 --- a/arch/m32r/include/asm/ptrace.h +++ b/arch/m32r/include/asm/ptrace.h | |||
@@ -120,6 +120,8 @@ struct pt_regs { | |||
120 | 120 | ||
121 | #include <asm/m32r.h> /* M32R_PSW_BSM, M32R_PSW_BPM */ | 121 | #include <asm/m32r.h> /* M32R_PSW_BSM, M32R_PSW_BPM */ |
122 | 122 | ||
123 | #define arch_has_single_step() (1) | ||
124 | |||
123 | struct task_struct; | 125 | struct task_struct; |
124 | extern void init_debug_traps(struct task_struct *); | 126 | extern void init_debug_traps(struct task_struct *); |
125 | #define arch_ptrace_attach(child) \ | 127 | #define arch_ptrace_attach(child) \ |
diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h index cf701c933249..76125777483c 100644 --- a/arch/m32r/include/asm/unistd.h +++ b/arch/m32r/include/asm/unistd.h | |||
@@ -339,6 +339,7 @@ | |||
339 | #define __ARCH_WANT_STAT64 | 339 | #define __ARCH_WANT_STAT64 |
340 | #define __ARCH_WANT_SYS_ALARM | 340 | #define __ARCH_WANT_SYS_ALARM |
341 | #define __ARCH_WANT_SYS_GETHOSTNAME | 341 | #define __ARCH_WANT_SYS_GETHOSTNAME |
342 | #define __ARCH_WANT_SYS_IPC | ||
342 | #define __ARCH_WANT_SYS_PAUSE | 343 | #define __ARCH_WANT_SYS_PAUSE |
343 | #define __ARCH_WANT_SYS_TIME | 344 | #define __ARCH_WANT_SYS_TIME |
344 | #define __ARCH_WANT_SYS_UTIME | 345 | #define __ARCH_WANT_SYS_UTIME |
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 98682bba0ed9..e555091eb97c 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c | |||
@@ -580,6 +580,35 @@ init_debug_traps(struct task_struct *child) | |||
580 | } | 580 | } |
581 | } | 581 | } |
582 | 582 | ||
583 | void user_enable_single_step(struct task_struct *child) | ||
584 | { | ||
585 | unsigned long next_pc; | ||
586 | unsigned long pc, insn; | ||
587 | |||
588 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
589 | |||
590 | /* Compute next pc. */ | ||
591 | pc = get_stack_long(child, PT_BPC); | ||
592 | |||
593 | if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) | ||
594 | != sizeof(insn)) | ||
595 | break; | ||
596 | |||
597 | compute_next_pc(insn, pc, &next_pc, child); | ||
598 | if (next_pc & 0x80000000) | ||
599 | break; | ||
600 | |||
601 | if (embed_debug_trap(child, next_pc)) | ||
602 | break; | ||
603 | |||
604 | invalidate_cache(); | ||
605 | } | ||
606 | |||
607 | void user_disable_single_step(struct task_struct *child) | ||
608 | { | ||
609 | unregister_all_debug_traps(child); | ||
610 | invalidate_cache(); | ||
611 | } | ||
583 | 612 | ||
584 | /* | 613 | /* |
585 | * Called by kernel/ptrace.c when detaching.. | 614 | * Called by kernel/ptrace.c when detaching.. |
@@ -630,74 +659,6 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
630 | ret = ptrace_write_user(child, addr, data); | 659 | ret = ptrace_write_user(child, addr, data); |
631 | break; | 660 | break; |
632 | 661 | ||
633 | /* | ||
634 | * continue/restart and stop at next (return from) syscall | ||
635 | */ | ||
636 | case PTRACE_SYSCALL: | ||
637 | case PTRACE_CONT: | ||
638 | ret = -EIO; | ||
639 | if (!valid_signal(data)) | ||
640 | break; | ||
641 | if (request == PTRACE_SYSCALL) | ||
642 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
643 | else | ||
644 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
645 | child->exit_code = data; | ||
646 | wake_up_process(child); | ||
647 | ret = 0; | ||
648 | break; | ||
649 | |||
650 | /* | ||
651 | * make the child exit. Best I can do is send it a sigkill. | ||
652 | * perhaps it should be put in the status that it wants to | ||
653 | * exit. | ||
654 | */ | ||
655 | case PTRACE_KILL: { | ||
656 | ret = 0; | ||
657 | unregister_all_debug_traps(child); | ||
658 | invalidate_cache(); | ||
659 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
660 | break; | ||
661 | child->exit_code = SIGKILL; | ||
662 | wake_up_process(child); | ||
663 | break; | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * execute single instruction. | ||
668 | */ | ||
669 | case PTRACE_SINGLESTEP: { | ||
670 | unsigned long next_pc; | ||
671 | unsigned long pc, insn; | ||
672 | |||
673 | ret = -EIO; | ||
674 | if (!valid_signal(data)) | ||
675 | break; | ||
676 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
677 | |||
678 | /* Compute next pc. */ | ||
679 | pc = get_stack_long(child, PT_BPC); | ||
680 | |||
681 | if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) | ||
682 | != sizeof(insn)) | ||
683 | break; | ||
684 | |||
685 | compute_next_pc(insn, pc, &next_pc, child); | ||
686 | if (next_pc & 0x80000000) | ||
687 | break; | ||
688 | |||
689 | if (embed_debug_trap(child, next_pc)) | ||
690 | break; | ||
691 | |||
692 | invalidate_cache(); | ||
693 | child->exit_code = data; | ||
694 | |||
695 | /* give it a chance to run. */ | ||
696 | wake_up_process(child); | ||
697 | ret = 0; | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | case PTRACE_GETREGS: | 662 | case PTRACE_GETREGS: |
702 | ret = ptrace_getregs(child, (void __user *)data); | 663 | ret = ptrace_getregs(child, (void __user *)data); |
703 | break; | 664 | break; |
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index d3c865c5a6ba..0a00f467edfa 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c | |||
@@ -76,98 +76,6 @@ asmlinkage int sys_tas(int __user *addr) | |||
76 | return oldval; | 76 | return oldval; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* | ||
80 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
81 | * | ||
82 | * This is really horribly ugly. | ||
83 | */ | ||
84 | asmlinkage int sys_ipc(uint call, int first, int second, | ||
85 | int third, void __user *ptr, long fifth) | ||
86 | { | ||
87 | int version, ret; | ||
88 | |||
89 | version = call >> 16; /* hack for backward compatibility */ | ||
90 | call &= 0xffff; | ||
91 | |||
92 | switch (call) { | ||
93 | case SEMOP: | ||
94 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
95 | second, NULL); | ||
96 | case SEMTIMEDOP: | ||
97 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
98 | second, (const struct timespec __user *)fifth); | ||
99 | case SEMGET: | ||
100 | return sys_semget (first, second, third); | ||
101 | case SEMCTL: { | ||
102 | union semun fourth; | ||
103 | if (!ptr) | ||
104 | return -EINVAL; | ||
105 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
106 | return -EFAULT; | ||
107 | return sys_semctl (first, second, third, fourth); | ||
108 | } | ||
109 | |||
110 | case MSGSND: | ||
111 | return sys_msgsnd (first, (struct msgbuf __user *) ptr, | ||
112 | second, third); | ||
113 | case MSGRCV: | ||
114 | switch (version) { | ||
115 | case 0: { | ||
116 | struct ipc_kludge tmp; | ||
117 | if (!ptr) | ||
118 | return -EINVAL; | ||
119 | |||
120 | if (copy_from_user(&tmp, | ||
121 | (struct ipc_kludge __user *) ptr, | ||
122 | sizeof (tmp))) | ||
123 | return -EFAULT; | ||
124 | return sys_msgrcv (first, tmp.msgp, second, | ||
125 | tmp.msgtyp, third); | ||
126 | } | ||
127 | default: | ||
128 | return sys_msgrcv (first, | ||
129 | (struct msgbuf __user *) ptr, | ||
130 | second, fifth, third); | ||
131 | } | ||
132 | case MSGGET: | ||
133 | return sys_msgget ((key_t) first, second); | ||
134 | case MSGCTL: | ||
135 | return sys_msgctl (first, second, | ||
136 | (struct msqid_ds __user *) ptr); | ||
137 | case SHMAT: { | ||
138 | ulong raddr; | ||
139 | |||
140 | if (!access_ok(VERIFY_WRITE, (ulong __user *) third, | ||
141 | sizeof(ulong))) | ||
142 | return -EFAULT; | ||
143 | ret = do_shmat (first, (char __user *) ptr, second, &raddr); | ||
144 | if (ret) | ||
145 | return ret; | ||
146 | return put_user (raddr, (ulong __user *) third); | ||
147 | } | ||
148 | case SHMDT: | ||
149 | return sys_shmdt ((char __user *)ptr); | ||
150 | case SHMGET: | ||
151 | return sys_shmget (first, second, third); | ||
152 | case SHMCTL: | ||
153 | return sys_shmctl (first, second, | ||
154 | (struct shmid_ds __user *) ptr); | ||
155 | default: | ||
156 | return -ENOSYS; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | asmlinkage int sys_uname(struct old_utsname __user * name) | ||
161 | { | ||
162 | int err; | ||
163 | if (!name) | ||
164 | return -EFAULT; | ||
165 | down_read(&uts_sem); | ||
166 | err = copy_to_user(name, utsname(), sizeof (*name)); | ||
167 | up_read(&uts_sem); | ||
168 | return err?-EFAULT:0; | ||
169 | } | ||
170 | |||
171 | asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) | 79 | asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) |
172 | { | 80 | { |
173 | /* This should flush more selectively ... */ | 81 | /* This should flush more selectively ... */ |
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h index 21605c736f69..6e6e3ac1d913 100644 --- a/arch/m68k/include/asm/ptrace.h +++ b/arch/m68k/include/asm/ptrace.h | |||
@@ -87,18 +87,10 @@ struct switch_stack { | |||
87 | #define profile_pc(regs) instruction_pointer(regs) | 87 | #define profile_pc(regs) instruction_pointer(regs) |
88 | extern void show_regs(struct pt_regs *); | 88 | extern void show_regs(struct pt_regs *); |
89 | 89 | ||
90 | /* | ||
91 | * These are defined as per linux/ptrace.h. | ||
92 | */ | ||
93 | struct task_struct; | ||
94 | |||
95 | #define arch_has_single_step() (1) | 90 | #define arch_has_single_step() (1) |
96 | extern void user_enable_single_step(struct task_struct *); | ||
97 | extern void user_disable_single_step(struct task_struct *); | ||
98 | 91 | ||
99 | #ifdef CONFIG_MMU | 92 | #ifdef CONFIG_MMU |
100 | #define arch_has_block_step() (1) | 93 | #define arch_has_block_step() (1) |
101 | extern void user_enable_block_step(struct task_struct *); | ||
102 | #endif | 94 | #endif |
103 | 95 | ||
104 | #endif /* __KERNEL__ */ | 96 | #endif /* __KERNEL__ */ |
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index d72a71dabecb..60b15d0aa072 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h | |||
@@ -351,6 +351,7 @@ | |||
351 | #define __ARCH_WANT_STAT64 | 351 | #define __ARCH_WANT_STAT64 |
352 | #define __ARCH_WANT_SYS_ALARM | 352 | #define __ARCH_WANT_SYS_ALARM |
353 | #define __ARCH_WANT_SYS_GETHOSTNAME | 353 | #define __ARCH_WANT_SYS_GETHOSTNAME |
354 | #define __ARCH_WANT_SYS_IPC | ||
354 | #define __ARCH_WANT_SYS_PAUSE | 355 | #define __ARCH_WANT_SYS_PAUSE |
355 | #define __ARCH_WANT_SYS_SGETMASK | 356 | #define __ARCH_WANT_SYS_SGETMASK |
356 | #define __ARCH_WANT_SYS_SIGNAL | 357 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -363,6 +364,8 @@ | |||
363 | #define __ARCH_WANT_SYS_LLSEEK | 364 | #define __ARCH_WANT_SYS_LLSEEK |
364 | #define __ARCH_WANT_SYS_NICE | 365 | #define __ARCH_WANT_SYS_NICE |
365 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 366 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
367 | #define __ARCH_WANT_SYS_OLD_MMAP | ||
368 | #define __ARCH_WANT_SYS_OLD_SELECT | ||
366 | #define __ARCH_WANT_SYS_OLDUMOUNT | 369 | #define __ARCH_WANT_SYS_OLDUMOUNT |
367 | #define __ARCH_WANT_SYS_SIGPENDING | 370 | #define __ARCH_WANT_SYS_SIGPENDING |
368 | #define __ARCH_WANT_SYS_SIGPROCMASK | 371 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index e136b8cbe9b9..2391bdff0996 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -510,7 +510,7 @@ sys_call_table: | |||
510 | .long sys_settimeofday | 510 | .long sys_settimeofday |
511 | .long sys_getgroups16 /* 80 */ | 511 | .long sys_getgroups16 /* 80 */ |
512 | .long sys_setgroups16 | 512 | .long sys_setgroups16 |
513 | .long old_select | 513 | .long sys_old_select |
514 | .long sys_symlink | 514 | .long sys_symlink |
515 | .long sys_lstat | 515 | .long sys_lstat |
516 | .long sys_readlink /* 85 */ | 516 | .long sys_readlink /* 85 */ |
@@ -518,7 +518,7 @@ sys_call_table: | |||
518 | .long sys_swapon | 518 | .long sys_swapon |
519 | .long sys_reboot | 519 | .long sys_reboot |
520 | .long sys_old_readdir | 520 | .long sys_old_readdir |
521 | .long old_mmap /* 90 */ | 521 | .long sys_old_mmap /* 90 */ |
522 | .long sys_munmap | 522 | .long sys_munmap |
523 | .long sys_truncate | 523 | .long sys_truncate |
524 | .long sys_ftruncate | 524 | .long sys_ftruncate |
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index e3ad2d671973..77896692eb0a 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c | |||
@@ -46,137 +46,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | |||
46 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); | 46 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); |
47 | } | 47 | } |
48 | 48 | ||
49 | /* | ||
50 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
51 | * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to | ||
52 | * handle more than 4 system call parameters, so these system calls | ||
53 | * used a memory block for parameter passing.. | ||
54 | */ | ||
55 | |||
56 | struct mmap_arg_struct { | ||
57 | unsigned long addr; | ||
58 | unsigned long len; | ||
59 | unsigned long prot; | ||
60 | unsigned long flags; | ||
61 | unsigned long fd; | ||
62 | unsigned long offset; | ||
63 | }; | ||
64 | |||
65 | asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) | ||
66 | { | ||
67 | struct mmap_arg_struct a; | ||
68 | int error = -EFAULT; | ||
69 | |||
70 | if (copy_from_user(&a, arg, sizeof(a))) | ||
71 | goto out; | ||
72 | |||
73 | error = -EINVAL; | ||
74 | if (a.offset & ~PAGE_MASK) | ||
75 | goto out; | ||
76 | |||
77 | error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, | ||
78 | a.offset >> PAGE_SHIFT); | ||
79 | out: | ||
80 | return error; | ||
81 | } | ||
82 | |||
83 | struct sel_arg_struct { | ||
84 | unsigned long n; | ||
85 | fd_set __user *inp, *outp, *exp; | ||
86 | struct timeval __user *tvp; | ||
87 | }; | ||
88 | |||
89 | asmlinkage int old_select(struct sel_arg_struct __user *arg) | ||
90 | { | ||
91 | struct sel_arg_struct a; | ||
92 | |||
93 | if (copy_from_user(&a, arg, sizeof(a))) | ||
94 | return -EFAULT; | ||
95 | /* sys_select() does the appropriate kernel locking */ | ||
96 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
101 | * | ||
102 | * This is really horribly ugly. | ||
103 | */ | ||
104 | asmlinkage int sys_ipc (uint call, int first, int second, | ||
105 | int third, void __user *ptr, long fifth) | ||
106 | { | ||
107 | int version, ret; | ||
108 | |||
109 | version = call >> 16; /* hack for backward compatibility */ | ||
110 | call &= 0xffff; | ||
111 | |||
112 | if (call <= SEMCTL) | ||
113 | switch (call) { | ||
114 | case SEMOP: | ||
115 | return sys_semop (first, ptr, second); | ||
116 | case SEMGET: | ||
117 | return sys_semget (first, second, third); | ||
118 | case SEMCTL: { | ||
119 | union semun fourth; | ||
120 | if (!ptr) | ||
121 | return -EINVAL; | ||
122 | if (get_user(fourth.__pad, (void __user *__user *) ptr)) | ||
123 | return -EFAULT; | ||
124 | return sys_semctl (first, second, third, fourth); | ||
125 | } | ||
126 | default: | ||
127 | return -ENOSYS; | ||
128 | } | ||
129 | if (call <= MSGCTL) | ||
130 | switch (call) { | ||
131 | case MSGSND: | ||
132 | return sys_msgsnd (first, ptr, second, third); | ||
133 | case MSGRCV: | ||
134 | switch (version) { | ||
135 | case 0: { | ||
136 | struct ipc_kludge tmp; | ||
137 | if (!ptr) | ||
138 | return -EINVAL; | ||
139 | if (copy_from_user (&tmp, ptr, sizeof (tmp))) | ||
140 | return -EFAULT; | ||
141 | return sys_msgrcv (first, tmp.msgp, second, | ||
142 | tmp.msgtyp, third); | ||
143 | } | ||
144 | default: | ||
145 | return sys_msgrcv (first, ptr, | ||
146 | second, fifth, third); | ||
147 | } | ||
148 | case MSGGET: | ||
149 | return sys_msgget ((key_t) first, second); | ||
150 | case MSGCTL: | ||
151 | return sys_msgctl (first, second, ptr); | ||
152 | default: | ||
153 | return -ENOSYS; | ||
154 | } | ||
155 | if (call <= SHMCTL) | ||
156 | switch (call) { | ||
157 | case SHMAT: | ||
158 | switch (version) { | ||
159 | default: { | ||
160 | ulong raddr; | ||
161 | ret = do_shmat (first, ptr, second, &raddr); | ||
162 | if (ret) | ||
163 | return ret; | ||
164 | return put_user (raddr, (ulong __user *) third); | ||
165 | } | ||
166 | } | ||
167 | case SHMDT: | ||
168 | return sys_shmdt (ptr); | ||
169 | case SHMGET: | ||
170 | return sys_shmget (first, second, third); | ||
171 | case SHMCTL: | ||
172 | return sys_shmctl (first, second, ptr); | ||
173 | default: | ||
174 | return -ENOSYS; | ||
175 | } | ||
176 | |||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | /* Convert virtual (user) address VADDR to physical address PADDR */ | 49 | /* Convert virtual (user) address VADDR to physical address PADDR */ |
181 | #define virt_to_phys_040(vaddr) \ | 50 | #define virt_to_phys_040(vaddr) \ |
182 | ({ \ | 51 | ({ \ |
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 85ed2f988f98..f6be1248d216 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c | |||
@@ -116,12 +116,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
116 | int ret; | 116 | int ret; |
117 | 117 | ||
118 | switch (request) { | 118 | switch (request) { |
119 | /* when I and D space are separate, these will need to be fixed. */ | ||
120 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
121 | case PTRACE_PEEKDATA: | ||
122 | ret = generic_ptrace_peekdata(child, addr, data); | ||
123 | break; | ||
124 | |||
125 | /* read the word at location addr in the USER area. */ | 119 | /* read the word at location addr in the USER area. */ |
126 | case PTRACE_PEEKUSR: { | 120 | case PTRACE_PEEKUSR: { |
127 | unsigned long tmp; | 121 | unsigned long tmp; |
@@ -160,12 +154,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
160 | break; | 154 | break; |
161 | } | 155 | } |
162 | 156 | ||
163 | /* when I and D space are separate, this will have to be fixed. */ | ||
164 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
165 | case PTRACE_POKEDATA: | ||
166 | ret = generic_ptrace_pokedata(child, addr, data); | ||
167 | break; | ||
168 | |||
169 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 157 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
170 | ret = -EIO; | 158 | ret = -EIO; |
171 | if ((addr & 3) || addr < 0 || | 159 | if ((addr & 3) || addr < 0 || |
@@ -202,66 +190,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
202 | } | 190 | } |
203 | break; | 191 | break; |
204 | 192 | ||
205 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
206 | case PTRACE_CONT: { /* restart after signal. */ | ||
207 | long tmp; | ||
208 | |||
209 | ret = -EIO; | ||
210 | if (!valid_signal(data)) | ||
211 | break; | ||
212 | if (request == PTRACE_SYSCALL) | ||
213 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
214 | else | ||
215 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
216 | child->exit_code = data; | ||
217 | /* make sure the single step bit is not set. */ | ||
218 | tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | ||
219 | put_reg(child, PT_SR, tmp); | ||
220 | wake_up_process(child); | ||
221 | ret = 0; | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * make the child exit. Best I can do is send it a sigkill. | ||
227 | * perhaps it should be put in the status that it wants to | ||
228 | * exit. | ||
229 | */ | ||
230 | case PTRACE_KILL: { | ||
231 | long tmp; | ||
232 | |||
233 | ret = 0; | ||
234 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
235 | break; | ||
236 | child->exit_code = SIGKILL; | ||
237 | /* make sure the single step bit is not set. */ | ||
238 | tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | ||
239 | put_reg(child, PT_SR, tmp); | ||
240 | wake_up_process(child); | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
245 | long tmp; | ||
246 | |||
247 | ret = -EIO; | ||
248 | if (!valid_signal(data)) | ||
249 | break; | ||
250 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
251 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); | ||
252 | put_reg(child, PT_SR, tmp); | ||
253 | |||
254 | child->exit_code = data; | ||
255 | /* give it a chance to run. */ | ||
256 | wake_up_process(child); | ||
257 | ret = 0; | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | case PTRACE_DETACH: /* detach a process that was attached. */ | ||
262 | ret = ptrace_detach(child, data); | ||
263 | break; | ||
264 | |||
265 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 193 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ |
266 | int i; | 194 | int i; |
267 | unsigned long tmp; | 195 | unsigned long tmp; |
@@ -325,7 +253,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
325 | break; | 253 | break; |
326 | 254 | ||
327 | default: | 255 | default: |
328 | ret = -EIO; | 256 | ret = ptrace_request(child, request, addr, data); |
329 | break; | 257 | break; |
330 | } | 258 | } |
331 | return ret; | 259 | return ret; |
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c index 923dd4aab875..d65e9c4c930c 100644 --- a/arch/m68knommu/kernel/sys_m68k.c +++ b/arch/m68knommu/kernel/sys_m68k.c | |||
@@ -27,142 +27,6 @@ | |||
27 | #include <asm/cacheflush.h> | 27 | #include <asm/cacheflush.h> |
28 | #include <asm/unistd.h> | 28 | #include <asm/unistd.h> |
29 | 29 | ||
30 | /* | ||
31 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
32 | * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to | ||
33 | * handle more than 4 system call parameters, so these system calls | ||
34 | * used a memory block for parameter passing.. | ||
35 | */ | ||
36 | |||
37 | struct mmap_arg_struct { | ||
38 | unsigned long addr; | ||
39 | unsigned long len; | ||
40 | unsigned long prot; | ||
41 | unsigned long flags; | ||
42 | unsigned long fd; | ||
43 | unsigned long offset; | ||
44 | }; | ||
45 | |||
46 | asmlinkage int old_mmap(struct mmap_arg_struct *arg) | ||
47 | { | ||
48 | struct mmap_arg_struct a; | ||
49 | int error = -EFAULT; | ||
50 | |||
51 | if (copy_from_user(&a, arg, sizeof(a))) | ||
52 | goto out; | ||
53 | |||
54 | error = -EINVAL; | ||
55 | if (a.offset & ~PAGE_MASK) | ||
56 | goto out; | ||
57 | |||
58 | error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, | ||
59 | a.offset >> PAGE_SHIFT); | ||
60 | out: | ||
61 | return error; | ||
62 | } | ||
63 | |||
64 | struct sel_arg_struct { | ||
65 | unsigned long n; | ||
66 | fd_set *inp, *outp, *exp; | ||
67 | struct timeval *tvp; | ||
68 | }; | ||
69 | |||
70 | asmlinkage int old_select(struct sel_arg_struct *arg) | ||
71 | { | ||
72 | struct sel_arg_struct a; | ||
73 | |||
74 | if (copy_from_user(&a, arg, sizeof(a))) | ||
75 | return -EFAULT; | ||
76 | /* sys_select() does the appropriate kernel locking */ | ||
77 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
82 | * | ||
83 | * This is really horribly ugly. | ||
84 | */ | ||
85 | asmlinkage int sys_ipc (uint call, int first, int second, | ||
86 | int third, void *ptr, long fifth) | ||
87 | { | ||
88 | int version, ret; | ||
89 | |||
90 | version = call >> 16; /* hack for backward compatibility */ | ||
91 | call &= 0xffff; | ||
92 | |||
93 | if (call <= SEMCTL) | ||
94 | switch (call) { | ||
95 | case SEMOP: | ||
96 | return sys_semop (first, (struct sembuf *)ptr, second); | ||
97 | case SEMGET: | ||
98 | return sys_semget (first, second, third); | ||
99 | case SEMCTL: { | ||
100 | union semun fourth; | ||
101 | if (!ptr) | ||
102 | return -EINVAL; | ||
103 | if (get_user(fourth.__pad, (void **) ptr)) | ||
104 | return -EFAULT; | ||
105 | return sys_semctl (first, second, third, fourth); | ||
106 | } | ||
107 | default: | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | if (call <= MSGCTL) | ||
111 | switch (call) { | ||
112 | case MSGSND: | ||
113 | return sys_msgsnd (first, (struct msgbuf *) ptr, | ||
114 | second, third); | ||
115 | case MSGRCV: | ||
116 | switch (version) { | ||
117 | case 0: { | ||
118 | struct ipc_kludge tmp; | ||
119 | if (!ptr) | ||
120 | return -EINVAL; | ||
121 | if (copy_from_user (&tmp, | ||
122 | (struct ipc_kludge *)ptr, | ||
123 | sizeof (tmp))) | ||
124 | return -EFAULT; | ||
125 | return sys_msgrcv (first, tmp.msgp, second, | ||
126 | tmp.msgtyp, third); | ||
127 | } | ||
128 | default: | ||
129 | return sys_msgrcv (first, | ||
130 | (struct msgbuf *) ptr, | ||
131 | second, fifth, third); | ||
132 | } | ||
133 | case MSGGET: | ||
134 | return sys_msgget ((key_t) first, second); | ||
135 | case MSGCTL: | ||
136 | return sys_msgctl (first, second, | ||
137 | (struct msqid_ds *) ptr); | ||
138 | default: | ||
139 | return -EINVAL; | ||
140 | } | ||
141 | if (call <= SHMCTL) | ||
142 | switch (call) { | ||
143 | case SHMAT: | ||
144 | switch (version) { | ||
145 | default: { | ||
146 | ulong raddr; | ||
147 | ret = do_shmat (first, ptr, second, &raddr); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | return put_user (raddr, (ulong __user *) third); | ||
151 | } | ||
152 | } | ||
153 | case SHMDT: | ||
154 | return sys_shmdt (ptr); | ||
155 | case SHMGET: | ||
156 | return sys_shmget (first, second, third); | ||
157 | case SHMCTL: | ||
158 | return sys_shmctl (first, second, ptr); | ||
159 | default: | ||
160 | return -ENOSYS; | ||
161 | } | ||
162 | |||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | /* sys_cacheflush -- flush (part of) the processor cache. */ | 30 | /* sys_cacheflush -- flush (part of) the processor cache. */ |
167 | asmlinkage int | 31 | asmlinkage int |
168 | sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) | 32 | sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) |
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index 56dd01ded148..b30b3eb197a5 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S | |||
@@ -100,7 +100,7 @@ ENTRY(sys_call_table) | |||
100 | .long sys_settimeofday | 100 | .long sys_settimeofday |
101 | .long sys_getgroups16 /* 80 */ | 101 | .long sys_getgroups16 /* 80 */ |
102 | .long sys_setgroups16 | 102 | .long sys_setgroups16 |
103 | .long old_select | 103 | .long sys_old_select |
104 | .long sys_symlink | 104 | .long sys_symlink |
105 | .long sys_lstat | 105 | .long sys_lstat |
106 | .long sys_readlink /* 85 */ | 106 | .long sys_readlink /* 85 */ |
@@ -108,7 +108,7 @@ ENTRY(sys_call_table) | |||
108 | .long sys_ni_syscall /* sys_swapon */ | 108 | .long sys_ni_syscall /* sys_swapon */ |
109 | .long sys_reboot | 109 | .long sys_reboot |
110 | .long sys_old_readdir | 110 | .long sys_old_readdir |
111 | .long old_mmap /* 90 */ | 111 | .long sys_old_mmap /* 90 */ |
112 | .long sys_munmap | 112 | .long sys_munmap |
113 | .long sys_truncate | 113 | .long sys_truncate |
114 | .long sys_ftruncate | 114 | .long sys_ftruncate |
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index 4b3ac32754de..6d6349a145f9 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c | |||
@@ -78,26 +78,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
78 | unsigned long copied; | 78 | unsigned long copied; |
79 | 79 | ||
80 | switch (request) { | 80 | switch (request) { |
81 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
82 | case PTRACE_PEEKDATA: | ||
83 | pr_debug("PEEKTEXT/PEEKDATA at %08lX\n", addr); | ||
84 | copied = access_process_vm(child, addr, &val, sizeof(val), 0); | ||
85 | rval = -EIO; | ||
86 | if (copied != sizeof(val)) | ||
87 | break; | ||
88 | rval = put_user(val, (unsigned long *)data); | ||
89 | break; | ||
90 | |||
91 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
92 | case PTRACE_POKEDATA: | ||
93 | pr_debug("POKETEXT/POKEDATA to %08lX\n", addr); | ||
94 | rval = 0; | ||
95 | if (access_process_vm(child, addr, &data, sizeof(data), 1) | ||
96 | == sizeof(data)) | ||
97 | break; | ||
98 | rval = -EIO; | ||
99 | break; | ||
100 | |||
101 | /* Read/write the word at location ADDR in the registers. */ | 81 | /* Read/write the word at location ADDR in the registers. */ |
102 | case PTRACE_PEEKUSR: | 82 | case PTRACE_PEEKUSR: |
103 | case PTRACE_POKEUSR: | 83 | case PTRACE_POKEUSR: |
@@ -130,50 +110,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
130 | if (rval == 0 && request == PTRACE_PEEKUSR) | 110 | if (rval == 0 && request == PTRACE_PEEKUSR) |
131 | rval = put_user(val, (unsigned long *)data); | 111 | rval = put_user(val, (unsigned long *)data); |
132 | break; | 112 | break; |
133 | /* Continue and stop at next (return from) syscall */ | ||
134 | case PTRACE_SYSCALL: | ||
135 | pr_debug("PTRACE_SYSCALL\n"); | ||
136 | case PTRACE_SINGLESTEP: | ||
137 | pr_debug("PTRACE_SINGLESTEP\n"); | ||
138 | /* Restart after a signal. */ | ||
139 | case PTRACE_CONT: | ||
140 | pr_debug("PTRACE_CONT\n"); | ||
141 | rval = -EIO; | ||
142 | if (!valid_signal(data)) | ||
143 | break; | ||
144 | |||
145 | if (request == PTRACE_SYSCALL) | ||
146 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
147 | else | ||
148 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
149 | |||
150 | child->exit_code = data; | ||
151 | pr_debug("wakeup_process\n"); | ||
152 | wake_up_process(child); | ||
153 | rval = 0; | ||
154 | break; | ||
155 | |||
156 | /* | ||
157 | * make the child exit. Best I can do is send it a sigkill. | ||
158 | * perhaps it should be put in the status that it wants to | ||
159 | * exit. | ||
160 | */ | ||
161 | case PTRACE_KILL: | ||
162 | pr_debug("PTRACE_KILL\n"); | ||
163 | rval = 0; | ||
164 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
165 | break; | ||
166 | child->exit_code = SIGKILL; | ||
167 | wake_up_process(child); | ||
168 | break; | ||
169 | |||
170 | case PTRACE_DETACH: /* detach a process that was attached. */ | ||
171 | pr_debug("PTRACE_DETACH\n"); | ||
172 | rval = ptrace_detach(child, data); | ||
173 | break; | ||
174 | default: | 113 | default: |
175 | /* rval = ptrace_request(child, request, addr, data); noMMU */ | 114 | rval = ptrace_request(child, request, addr, data); |
176 | rval = -EIO; | ||
177 | } | 115 | } |
178 | return rval; | 116 | return rval; |
179 | } | 117 | } |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 591ca0cd4c24..29e86923d1bf 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -812,9 +812,9 @@ config DMA_COHERENT | |||
812 | 812 | ||
813 | config DMA_NONCOHERENT | 813 | config DMA_NONCOHERENT |
814 | bool | 814 | bool |
815 | select DMA_NEED_PCI_MAP_STATE | 815 | select NEED_DMA_MAP_STATE |
816 | 816 | ||
817 | config DMA_NEED_PCI_MAP_STATE | 817 | config NEED_DMA_MAP_STATE |
818 | bool | 818 | bool |
819 | 819 | ||
820 | config SYS_HAS_EARLY_PRINTK | 820 | config SYS_HAS_EARLY_PRINTK |
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index f58aed354bfd..613f6912dfc1 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h | |||
@@ -8,7 +8,8 @@ | |||
8 | #include <asm/page.h> | 8 | #include <asm/page.h> |
9 | #include <asm/ptrace.h> | 9 | #include <asm/ptrace.h> |
10 | 10 | ||
11 | #define COMPAT_USER_HZ 100 | 11 | #define COMPAT_USER_HZ 100 |
12 | #define COMPAT_UTS_MACHINE "mips\0\0\0" | ||
12 | 13 | ||
13 | typedef u32 compat_size_t; | 14 | typedef u32 compat_size_t; |
14 | typedef s32 compat_ssize_t; | 15 | typedef s32 compat_ssize_t; |
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 5ebf82572ec0..3beea1479b43 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h | |||
@@ -102,28 +102,6 @@ struct pci_dev; | |||
102 | */ | 102 | */ |
103 | extern unsigned int PCI_DMA_BUS_IS_PHYS; | 103 | extern unsigned int PCI_DMA_BUS_IS_PHYS; |
104 | 104 | ||
105 | #ifdef CONFIG_DMA_NEED_PCI_MAP_STATE | ||
106 | |||
107 | /* pci_unmap_{single,page} is not a nop, thus... */ | ||
108 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME; | ||
109 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME; | ||
110 | #define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) | ||
111 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) | ||
112 | #define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) | ||
113 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) | ||
114 | |||
115 | #else /* CONFIG_DMA_NEED_PCI_MAP_STATE */ | ||
116 | |||
117 | /* pci_unmap_{page,single} is a nop so... */ | ||
118 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
119 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
120 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
121 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
122 | #define pci_unmap_len(PTR, LEN_NAME) (0) | ||
123 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
124 | |||
125 | #endif /* CONFIG_DMA_NEED_PCI_MAP_STATE */ | ||
126 | |||
127 | #ifdef CONFIG_PCI | 105 | #ifdef CONFIG_PCI |
128 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, | 106 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, |
129 | enum pci_dma_burst_strategy *strat, | 107 | enum pci_dma_burst_strategy *strat, |
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 65c679ecbe6b..1b5a6648eb86 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h | |||
@@ -1004,6 +1004,7 @@ | |||
1004 | #define __ARCH_WANT_OLD_READDIR | 1004 | #define __ARCH_WANT_OLD_READDIR |
1005 | #define __ARCH_WANT_SYS_ALARM | 1005 | #define __ARCH_WANT_SYS_ALARM |
1006 | #define __ARCH_WANT_SYS_GETHOSTNAME | 1006 | #define __ARCH_WANT_SYS_GETHOSTNAME |
1007 | #define __ARCH_WANT_SYS_IPC | ||
1007 | #define __ARCH_WANT_SYS_PAUSE | 1008 | #define __ARCH_WANT_SYS_PAUSE |
1008 | #define __ARCH_WANT_SYS_SGETMASK | 1009 | #define __ARCH_WANT_SYS_SGETMASK |
1009 | #define __ARCH_WANT_SYS_UTIME | 1010 | #define __ARCH_WANT_SYS_UTIME |
@@ -1013,6 +1014,7 @@ | |||
1013 | #define __ARCH_WANT_SYS_LLSEEK | 1014 | #define __ARCH_WANT_SYS_LLSEEK |
1014 | #define __ARCH_WANT_SYS_NICE | 1015 | #define __ARCH_WANT_SYS_NICE |
1015 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 1016 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
1017 | #define __ARCH_WANT_SYS_OLD_UNAME | ||
1016 | #define __ARCH_WANT_SYS_OLDUMOUNT | 1018 | #define __ARCH_WANT_SYS_OLDUMOUNT |
1017 | #define __ARCH_WANT_SYS_SIGPENDING | 1019 | #define __ARCH_WANT_SYS_SIGPENDING |
1018 | #define __ARCH_WANT_SYS_SIGPROCMASK | 1020 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index bde79ef602e6..a39d0597a375 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -249,22 +249,6 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz, | |||
249 | } | 249 | } |
250 | #endif | 250 | #endif |
251 | 251 | ||
252 | SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name) | ||
253 | { | ||
254 | int ret = 0; | ||
255 | |||
256 | down_read(&uts_sem); | ||
257 | if (copy_to_user(name, utsname(), sizeof *name)) | ||
258 | ret = -EFAULT; | ||
259 | up_read(&uts_sem); | ||
260 | |||
261 | if (current->personality == PER_LINUX32 && !ret) | ||
262 | if (copy_to_user(name->machine, "mips\0\0\0", 8)) | ||
263 | ret = -EFAULT; | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | SYSCALL_DEFINE1(32_personality, unsigned long, personality) | 252 | SYSCALL_DEFINE1(32_personality, unsigned long, personality) |
269 | { | 253 | { |
270 | int ret; | 254 | int ret; |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 054861ccb4dd..c51b95ff8644 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -493,36 +493,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
493 | ret = ptrace_setfpregs(child, (__u32 __user *) data); | 493 | ret = ptrace_setfpregs(child, (__u32 __user *) data); |
494 | break; | 494 | break; |
495 | 495 | ||
496 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
497 | case PTRACE_CONT: { /* restart after signal. */ | ||
498 | ret = -EIO; | ||
499 | if (!valid_signal(data)) | ||
500 | break; | ||
501 | if (request == PTRACE_SYSCALL) { | ||
502 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
503 | } | ||
504 | else { | ||
505 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
506 | } | ||
507 | child->exit_code = data; | ||
508 | wake_up_process(child); | ||
509 | ret = 0; | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * make the child exit. Best I can do is send it a sigkill. | ||
515 | * perhaps it should be put in the status that it wants to | ||
516 | * exit. | ||
517 | */ | ||
518 | case PTRACE_KILL: | ||
519 | ret = 0; | ||
520 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
521 | break; | ||
522 | child->exit_code = SIGKILL; | ||
523 | wake_up_process(child); | ||
524 | break; | ||
525 | |||
526 | case PTRACE_GET_THREAD_AREA: | 496 | case PTRACE_GET_THREAD_AREA: |
527 | ret = put_user(task_thread_info(child)->tp_value, | 497 | ret = put_user(task_thread_info(child)->tp_value, |
528 | (unsigned long __user *) data); | 498 | (unsigned long __user *) data); |
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 66b5a48676dd..44337ba03717 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S | |||
@@ -181,7 +181,7 @@ EXPORT(sysn32_call_table) | |||
181 | PTR sys_exit | 181 | PTR sys_exit |
182 | PTR compat_sys_wait4 | 182 | PTR compat_sys_wait4 |
183 | PTR sys_kill /* 6060 */ | 183 | PTR sys_kill /* 6060 */ |
184 | PTR sys_32_newuname | 184 | PTR sys_newuname |
185 | PTR sys_semget | 185 | PTR sys_semget |
186 | PTR sys_semop | 186 | PTR sys_semop |
187 | PTR sys_n32_semctl | 187 | PTR sys_n32_semctl |
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 515f9eab2b28..813689ef2384 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
@@ -325,7 +325,7 @@ sys_call_table: | |||
325 | PTR sys32_sigreturn | 325 | PTR sys32_sigreturn |
326 | PTR sys32_clone /* 4120 */ | 326 | PTR sys32_clone /* 4120 */ |
327 | PTR sys_setdomainname | 327 | PTR sys_setdomainname |
328 | PTR sys_32_newuname | 328 | PTR sys_newuname |
329 | PTR sys_ni_syscall /* sys_modify_ldt */ | 329 | PTR sys_ni_syscall /* sys_modify_ldt */ |
330 | PTR compat_sys_adjtimex | 330 | PTR compat_sys_adjtimex |
331 | PTR sys_mprotect /* 4125 */ | 331 | PTR sys_mprotect /* 4125 */ |
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 3f7f466190b4..e96b1c30c7aa 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
@@ -215,48 +215,6 @@ out: | |||
215 | return error; | 215 | return error; |
216 | } | 216 | } |
217 | 217 | ||
218 | /* | ||
219 | * Compacrapability ... | ||
220 | */ | ||
221 | SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) | ||
222 | { | ||
223 | if (name && !copy_to_user(name, utsname(), sizeof (*name))) | ||
224 | return 0; | ||
225 | return -EFAULT; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Compacrapability ... | ||
230 | */ | ||
231 | SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name) | ||
232 | { | ||
233 | int error; | ||
234 | |||
235 | if (!name) | ||
236 | return -EFAULT; | ||
237 | if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) | ||
238 | return -EFAULT; | ||
239 | |||
240 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
241 | __OLD_UTS_LEN); | ||
242 | error -= __put_user(0, name->sysname + __OLD_UTS_LEN); | ||
243 | error -= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
244 | __OLD_UTS_LEN); | ||
245 | error -= __put_user(0, name->nodename + __OLD_UTS_LEN); | ||
246 | error -= __copy_to_user(&name->release, &utsname()->release, | ||
247 | __OLD_UTS_LEN); | ||
248 | error -= __put_user(0, name->release + __OLD_UTS_LEN); | ||
249 | error -= __copy_to_user(&name->version, &utsname()->version, | ||
250 | __OLD_UTS_LEN); | ||
251 | error -= __put_user(0, name->version + __OLD_UTS_LEN); | ||
252 | error -= __copy_to_user(&name->machine, &utsname()->machine, | ||
253 | __OLD_UTS_LEN); | ||
254 | error = __put_user(0, name->machine + __OLD_UTS_LEN); | ||
255 | error = error ? -EFAULT : 0; | ||
256 | |||
257 | return error; | ||
258 | } | ||
259 | |||
260 | SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) | 218 | SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) |
261 | { | 219 | { |
262 | struct thread_info *ti = task_thread_info(current); | 220 | struct thread_info *ti = task_thread_info(current); |
@@ -407,94 +365,6 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs) | |||
407 | } | 365 | } |
408 | 366 | ||
409 | /* | 367 | /* |
410 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
411 | * | ||
412 | * This is really horribly ugly. | ||
413 | */ | ||
414 | SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second, | ||
415 | unsigned long, third, void __user *, ptr, long, fifth) | ||
416 | { | ||
417 | int version, ret; | ||
418 | |||
419 | version = call >> 16; /* hack for backward compatibility */ | ||
420 | call &= 0xffff; | ||
421 | |||
422 | switch (call) { | ||
423 | case SEMOP: | ||
424 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
425 | second, NULL); | ||
426 | case SEMTIMEDOP: | ||
427 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
428 | second, | ||
429 | (const struct timespec __user *)fifth); | ||
430 | case SEMGET: | ||
431 | return sys_semget(first, second, third); | ||
432 | case SEMCTL: { | ||
433 | union semun fourth; | ||
434 | if (!ptr) | ||
435 | return -EINVAL; | ||
436 | if (get_user(fourth.__pad, (void __user *__user *) ptr)) | ||
437 | return -EFAULT; | ||
438 | return sys_semctl(first, second, third, fourth); | ||
439 | } | ||
440 | |||
441 | case MSGSND: | ||
442 | return sys_msgsnd(first, (struct msgbuf __user *) ptr, | ||
443 | second, third); | ||
444 | case MSGRCV: | ||
445 | switch (version) { | ||
446 | case 0: { | ||
447 | struct ipc_kludge tmp; | ||
448 | if (!ptr) | ||
449 | return -EINVAL; | ||
450 | |||
451 | if (copy_from_user(&tmp, | ||
452 | (struct ipc_kludge __user *) ptr, | ||
453 | sizeof(tmp))) | ||
454 | return -EFAULT; | ||
455 | return sys_msgrcv(first, tmp.msgp, second, | ||
456 | tmp.msgtyp, third); | ||
457 | } | ||
458 | default: | ||
459 | return sys_msgrcv(first, | ||
460 | (struct msgbuf __user *) ptr, | ||
461 | second, fifth, third); | ||
462 | } | ||
463 | case MSGGET: | ||
464 | return sys_msgget((key_t) first, second); | ||
465 | case MSGCTL: | ||
466 | return sys_msgctl(first, second, | ||
467 | (struct msqid_ds __user *) ptr); | ||
468 | |||
469 | case SHMAT: | ||
470 | switch (version) { | ||
471 | default: { | ||
472 | unsigned long raddr; | ||
473 | ret = do_shmat(first, (char __user *) ptr, second, | ||
474 | &raddr); | ||
475 | if (ret) | ||
476 | return ret; | ||
477 | return put_user(raddr, (unsigned long __user *) third); | ||
478 | } | ||
479 | case 1: /* iBCS2 emulator entry point */ | ||
480 | if (!segment_eq(get_fs(), get_ds())) | ||
481 | return -EINVAL; | ||
482 | return do_shmat(first, (char __user *) ptr, second, | ||
483 | (unsigned long *) third); | ||
484 | } | ||
485 | case SHMDT: | ||
486 | return sys_shmdt((char __user *)ptr); | ||
487 | case SHMGET: | ||
488 | return sys_shmget(first, second, third); | ||
489 | case SHMCTL: | ||
490 | return sys_shmctl(first, second, | ||
491 | (struct shmid_ds __user *) ptr); | ||
492 | default: | ||
493 | return -ENOSYS; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | * No implemented yet ... | 368 | * No implemented yet ... |
499 | */ | 369 | */ |
500 | SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) | 370 | SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) |
diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c index 727ab21b6618..7f8416f86222 100644 --- a/arch/mips/txx9/generic/7segled.c +++ b/arch/mips/txx9/generic/7segled.c | |||
@@ -58,13 +58,16 @@ static ssize_t raw_store(struct sys_device *dev, | |||
58 | static SYSDEV_ATTR(ascii, 0200, NULL, ascii_store); | 58 | static SYSDEV_ATTR(ascii, 0200, NULL, ascii_store); |
59 | static SYSDEV_ATTR(raw, 0200, NULL, raw_store); | 59 | static SYSDEV_ATTR(raw, 0200, NULL, raw_store); |
60 | 60 | ||
61 | static ssize_t map_seg7_show(struct sysdev_class *class, char *buf) | 61 | static ssize_t map_seg7_show(struct sysdev_class *class, |
62 | struct sysdev_class_attribute *attr, | ||
63 | char *buf) | ||
62 | { | 64 | { |
63 | memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map)); | 65 | memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map)); |
64 | return sizeof(txx9_seg7map); | 66 | return sizeof(txx9_seg7map); |
65 | } | 67 | } |
66 | 68 | ||
67 | static ssize_t map_seg7_store(struct sysdev_class *class, | 69 | static ssize_t map_seg7_store(struct sysdev_class *class, |
70 | struct sysdev_class_attribute *attr, | ||
68 | const char *buf, size_t size) | 71 | const char *buf, size_t size) |
69 | { | 72 | { |
70 | if (size != sizeof(txx9_seg7map)) | 73 | if (size != sizeof(txx9_seg7map)) |
diff --git a/arch/mn10300/include/asm/dma-mapping.h b/arch/mn10300/include/asm/dma-mapping.h index ccae8f6c6326..4ed1522b38d2 100644 --- a/arch/mn10300/include/asm/dma-mapping.h +++ b/arch/mn10300/include/asm/dma-mapping.h | |||
@@ -17,6 +17,11 @@ | |||
17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | 19 | ||
20 | /* | ||
21 | * See Documentation/DMA-API.txt for the description of how the | ||
22 | * following DMA API should work. | ||
23 | */ | ||
24 | |||
20 | extern void *dma_alloc_coherent(struct device *dev, size_t size, | 25 | extern void *dma_alloc_coherent(struct device *dev, size_t size, |
21 | dma_addr_t *dma_handle, int flag); | 26 | dma_addr_t *dma_handle, int flag); |
22 | 27 | ||
@@ -26,13 +31,6 @@ extern void dma_free_coherent(struct device *dev, size_t size, | |||
26 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f)) | 31 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f)) |
27 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent((d), (s), (v), (h)) | 32 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent((d), (s), (v), (h)) |
28 | 33 | ||
29 | /* | ||
30 | * Map a single buffer of the indicated size for DMA in streaming mode. The | ||
31 | * 32-bit bus address to use is returned. | ||
32 | * | ||
33 | * Once the device is given the dma address, the device owns this memory until | ||
34 | * either pci_unmap_single or pci_dma_sync_single is performed. | ||
35 | */ | ||
36 | static inline | 34 | static inline |
37 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 35 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, |
38 | enum dma_data_direction direction) | 36 | enum dma_data_direction direction) |
@@ -42,14 +40,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
42 | return virt_to_bus(ptr); | 40 | return virt_to_bus(ptr); |
43 | } | 41 | } |
44 | 42 | ||
45 | /* | ||
46 | * Unmap a single streaming mode DMA translation. The dma_addr and size must | ||
47 | * match what was provided for in a previous pci_map_single call. All other | ||
48 | * usages are undefined. | ||
49 | * | ||
50 | * After this call, reads by the cpu to the buffer are guarenteed to see | ||
51 | * whatever the device wrote there. | ||
52 | */ | ||
53 | static inline | 43 | static inline |
54 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 44 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, |
55 | enum dma_data_direction direction) | 45 | enum dma_data_direction direction) |
@@ -57,20 +47,6 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
57 | BUG_ON(direction == DMA_NONE); | 47 | BUG_ON(direction == DMA_NONE); |
58 | } | 48 | } |
59 | 49 | ||
60 | /* | ||
61 | * Map a set of buffers described by scatterlist in streaming mode for DMA. | ||
62 | * This is the scather-gather version of the above pci_map_single interface. | ||
63 | * Here the scatter gather list elements are each tagged with the appropriate | ||
64 | * dma address and length. They are obtained via sg_dma_{address,length}(SG). | ||
65 | * | ||
66 | * NOTE: An implementation may be able to use a smaller number of DMA | ||
67 | * address/length pairs than there are SG table elements. (for example | ||
68 | * via virtual mapping capabilities) The routine returns the number of | ||
69 | * addr/length pairs actually used, at most nents. | ||
70 | * | ||
71 | * Device ownership issues as mentioned above for pci_map_single are the same | ||
72 | * here. | ||
73 | */ | ||
74 | static inline | 50 | static inline |
75 | int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, | 51 | int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, |
76 | enum dma_data_direction direction) | 52 | enum dma_data_direction direction) |
@@ -91,11 +67,6 @@ int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, | |||
91 | return nents; | 67 | return nents; |
92 | } | 68 | } |
93 | 69 | ||
94 | /* | ||
95 | * Unmap a set of streaming mode DMA translations. | ||
96 | * Again, cpu read rules concerning calls here are the same as for | ||
97 | * pci_unmap_single() above. | ||
98 | */ | ||
99 | static inline | 70 | static inline |
100 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | 71 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, |
101 | enum dma_data_direction direction) | 72 | enum dma_data_direction direction) |
@@ -103,10 +74,6 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | |||
103 | BUG_ON(!valid_dma_direction(direction)); | 74 | BUG_ON(!valid_dma_direction(direction)); |
104 | } | 75 | } |
105 | 76 | ||
106 | /* | ||
107 | * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical | ||
108 | * to pci_map_single, but takes a struct page instead of a virtual address | ||
109 | */ | ||
110 | static inline | 77 | static inline |
111 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | 78 | dma_addr_t dma_map_page(struct device *dev, struct page *page, |
112 | unsigned long offset, size_t size, | 79 | unsigned long offset, size_t size, |
@@ -123,15 +90,6 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | |||
123 | BUG_ON(direction == DMA_NONE); | 90 | BUG_ON(direction == DMA_NONE); |
124 | } | 91 | } |
125 | 92 | ||
126 | /* | ||
127 | * Make physical memory consistent for a single streaming mode DMA translation | ||
128 | * after a transfer. | ||
129 | * | ||
130 | * If you perform a pci_map_single() but wish to interrogate the buffer using | ||
131 | * the cpu, yet do not wish to teardown the PCI dma mapping, you must call this | ||
132 | * function before doing so. At the next point you give the PCI dma address | ||
133 | * back to the card, the device again owns the buffer. | ||
134 | */ | ||
135 | static inline | 93 | static inline |
136 | void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | 94 | void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, |
137 | size_t size, enum dma_data_direction direction) | 95 | size_t size, enum dma_data_direction direction) |
@@ -161,13 +119,6 @@ dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, | |||
161 | } | 119 | } |
162 | 120 | ||
163 | 121 | ||
164 | /* | ||
165 | * Make physical memory consistent for a set of streaming mode DMA translations | ||
166 | * after a transfer. | ||
167 | * | ||
168 | * The same as pci_dma_sync_single but for a scatter-gather list, same rules | ||
169 | * and usage. | ||
170 | */ | ||
171 | static inline | 122 | static inline |
172 | void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | 123 | void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, |
173 | int nelems, enum dma_data_direction direction) | 124 | int nelems, enum dma_data_direction direction) |
@@ -187,12 +138,6 @@ int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | |||
187 | return 0; | 138 | return 0; |
188 | } | 139 | } |
189 | 140 | ||
190 | /* | ||
191 | * Return whether the given PCI device DMA address mask can be supported | ||
192 | * properly. For example, if your device can only drive the low 24-bits during | ||
193 | * PCI bus mastering, then you would pass 0x00ffffff as the mask to this | ||
194 | * function. | ||
195 | */ | ||
196 | static inline | 141 | static inline |
197 | int dma_supported(struct device *dev, u64 mask) | 142 | int dma_supported(struct device *dev, u64 mask) |
198 | { | 143 | { |
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h index 1b0ba5e182b0..7c2e911052b6 100644 --- a/arch/mn10300/include/asm/ptrace.h +++ b/arch/mn10300/include/asm/ptrace.h | |||
@@ -99,8 +99,6 @@ struct task_struct; | |||
99 | extern void show_regs(struct pt_regs *); | 99 | extern void show_regs(struct pt_regs *); |
100 | 100 | ||
101 | #define arch_has_single_step() (1) | 101 | #define arch_has_single_step() (1) |
102 | extern void user_enable_single_step(struct task_struct *); | ||
103 | extern void user_disable_single_step(struct task_struct *); | ||
104 | 102 | ||
105 | #endif /* !__ASSEMBLY */ | 103 | #endif /* !__ASSEMBLY */ |
106 | 104 | ||
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h index c05acb95c2a9..9d056f515929 100644 --- a/arch/mn10300/include/asm/unistd.h +++ b/arch/mn10300/include/asm/unistd.h | |||
@@ -363,6 +363,7 @@ | |||
363 | #define __ARCH_WANT_STAT64 | 363 | #define __ARCH_WANT_STAT64 |
364 | #define __ARCH_WANT_SYS_ALARM | 364 | #define __ARCH_WANT_SYS_ALARM |
365 | #define __ARCH_WANT_SYS_GETHOSTNAME | 365 | #define __ARCH_WANT_SYS_GETHOSTNAME |
366 | #define __ARCH_WANT_SYS_IPC | ||
366 | #define __ARCH_WANT_SYS_PAUSE | 367 | #define __ARCH_WANT_SYS_PAUSE |
367 | #define __ARCH_WANT_SYS_SGETMASK | 368 | #define __ARCH_WANT_SYS_SGETMASK |
368 | #define __ARCH_WANT_SYS_SIGNAL | 369 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -375,6 +376,7 @@ | |||
375 | #define __ARCH_WANT_SYS_LLSEEK | 376 | #define __ARCH_WANT_SYS_LLSEEK |
376 | #define __ARCH_WANT_SYS_NICE | 377 | #define __ARCH_WANT_SYS_NICE |
377 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 378 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
379 | #define __ARCH_WANT_SYS_OLD_SELECT | ||
378 | #define __ARCH_WANT_SYS_OLDUMOUNT | 380 | #define __ARCH_WANT_SYS_OLDUMOUNT |
379 | #define __ARCH_WANT_SYS_SIGPENDING | 381 | #define __ARCH_WANT_SYS_SIGPENDING |
380 | #define __ARCH_WANT_SYS_SIGPROCMASK | 382 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 88e3e1c3cc21..d9ed5a15c547 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S | |||
@@ -468,7 +468,7 @@ ENTRY(sys_call_table) | |||
468 | .long sys_settimeofday | 468 | .long sys_settimeofday |
469 | .long sys_getgroups16 /* 80 */ | 469 | .long sys_getgroups16 /* 80 */ |
470 | .long sys_setgroups16 | 470 | .long sys_setgroups16 |
471 | .long old_select | 471 | .long sys_old_select |
472 | .long sys_symlink | 472 | .long sys_symlink |
473 | .long sys_lstat | 473 | .long sys_lstat |
474 | .long sys_readlink /* 85 */ | 474 | .long sys_readlink /* 85 */ |
diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c index 17cc6ce04e84..815f1355fad4 100644 --- a/arch/mn10300/kernel/sys_mn10300.c +++ b/arch/mn10300/kernel/sys_mn10300.c | |||
@@ -31,109 +31,3 @@ asmlinkage long old_mmap(unsigned long addr, unsigned long len, | |||
31 | return -EINVAL; | 31 | return -EINVAL; |
32 | return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); | 32 | return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); |
33 | } | 33 | } |
34 | |||
35 | struct sel_arg_struct { | ||
36 | unsigned long n; | ||
37 | fd_set *inp; | ||
38 | fd_set *outp; | ||
39 | fd_set *exp; | ||
40 | struct timeval *tvp; | ||
41 | }; | ||
42 | |||
43 | asmlinkage int old_select(struct sel_arg_struct __user *arg) | ||
44 | { | ||
45 | struct sel_arg_struct a; | ||
46 | |||
47 | if (copy_from_user(&a, arg, sizeof(a))) | ||
48 | return -EFAULT; | ||
49 | /* sys_select() does the appropriate kernel locking */ | ||
50 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
55 | * | ||
56 | * This is really horribly ugly. | ||
57 | */ | ||
58 | asmlinkage long sys_ipc(uint call, int first, int second, | ||
59 | int third, void __user *ptr, long fifth) | ||
60 | { | ||
61 | int version, ret; | ||
62 | |||
63 | version = call >> 16; /* hack for backward compatibility */ | ||
64 | call &= 0xffff; | ||
65 | |||
66 | switch (call) { | ||
67 | case SEMOP: | ||
68 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
69 | second, NULL); | ||
70 | case SEMTIMEDOP: | ||
71 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
72 | second, | ||
73 | (const struct timespec __user *)fifth); | ||
74 | case SEMGET: | ||
75 | return sys_semget(first, second, third); | ||
76 | case SEMCTL: { | ||
77 | union semun fourth; | ||
78 | if (!ptr) | ||
79 | return -EINVAL; | ||
80 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
81 | return -EFAULT; | ||
82 | return sys_semctl(first, second, third, fourth); | ||
83 | } | ||
84 | |||
85 | case MSGSND: | ||
86 | return sys_msgsnd(first, (struct msgbuf __user *) ptr, | ||
87 | second, third); | ||
88 | case MSGRCV: | ||
89 | switch (version) { | ||
90 | case 0: { | ||
91 | struct ipc_kludge tmp; | ||
92 | if (!ptr) | ||
93 | return -EINVAL; | ||
94 | |||
95 | if (copy_from_user(&tmp, | ||
96 | (struct ipc_kludge __user *) ptr, | ||
97 | sizeof(tmp))) | ||
98 | return -EFAULT; | ||
99 | return sys_msgrcv(first, tmp.msgp, second, | ||
100 | tmp.msgtyp, third); | ||
101 | } | ||
102 | default: | ||
103 | return sys_msgrcv(first, | ||
104 | (struct msgbuf __user *) ptr, | ||
105 | second, fifth, third); | ||
106 | } | ||
107 | case MSGGET: | ||
108 | return sys_msgget((key_t) first, second); | ||
109 | case MSGCTL: | ||
110 | return sys_msgctl(first, second, | ||
111 | (struct msqid_ds __user *) ptr); | ||
112 | |||
113 | case SHMAT: | ||
114 | switch (version) { | ||
115 | default: { | ||
116 | ulong raddr; | ||
117 | ret = do_shmat(first, (char __user *) ptr, second, | ||
118 | &raddr); | ||
119 | if (ret) | ||
120 | return ret; | ||
121 | return put_user(raddr, (ulong *) third); | ||
122 | } | ||
123 | case 1: /* iBCS2 emulator entry point */ | ||
124 | if (!segment_eq(get_fs(), get_ds())) | ||
125 | return -EINVAL; | ||
126 | return do_shmat(first, (char __user *) ptr, second, | ||
127 | (ulong *) third); | ||
128 | } | ||
129 | case SHMDT: | ||
130 | return sys_shmdt((char __user *)ptr); | ||
131 | case SHMGET: | ||
132 | return sys_shmget(first, second, third); | ||
133 | case SHMCTL: | ||
134 | return sys_shmctl(first, second, | ||
135 | (struct shmid_ds __user *) ptr); | ||
136 | default: | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | } | ||
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index f388dc68f605..9c4da3d63bfb 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -95,6 +95,9 @@ config PM | |||
95 | config STACKTRACE_SUPPORT | 95 | config STACKTRACE_SUPPORT |
96 | def_bool y | 96 | def_bool y |
97 | 97 | ||
98 | config NEED_DMA_MAP_STATE | ||
99 | def_bool y | ||
100 | |||
98 | config ISA_DMA_API | 101 | config ISA_DMA_API |
99 | bool | 102 | bool |
100 | 103 | ||
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 7f32611a7a5e..02b77baa5da6 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h | |||
@@ -7,7 +7,8 @@ | |||
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/thread_info.h> | 8 | #include <linux/thread_info.h> |
9 | 9 | ||
10 | #define COMPAT_USER_HZ 100 | 10 | #define COMPAT_USER_HZ 100 |
11 | #define COMPAT_UTS_MACHINE "parisc\0\0" | ||
11 | 12 | ||
12 | typedef u32 compat_size_t; | 13 | typedef u32 compat_size_t; |
13 | typedef s32 compat_ssize_t; | 14 | typedef s32 compat_ssize_t; |
diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h index 64c7aa590ae5..2242a5c636c2 100644 --- a/arch/parisc/include/asm/pci.h +++ b/arch/parisc/include/asm/pci.h | |||
@@ -183,20 +183,6 @@ struct pci_bios_ops { | |||
183 | void (*fixup_bus)(struct pci_bus *bus); | 183 | void (*fixup_bus)(struct pci_bus *bus); |
184 | }; | 184 | }; |
185 | 185 | ||
186 | /* pci_unmap_{single,page} is not a nop, thus... */ | ||
187 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | ||
188 | dma_addr_t ADDR_NAME; | ||
189 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | ||
190 | __u32 LEN_NAME; | ||
191 | #define pci_unmap_addr(PTR, ADDR_NAME) \ | ||
192 | ((PTR)->ADDR_NAME) | ||
193 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
194 | (((PTR)->ADDR_NAME) = (VAL)) | ||
195 | #define pci_unmap_len(PTR, LEN_NAME) \ | ||
196 | ((PTR)->LEN_NAME) | ||
197 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
198 | (((PTR)->LEN_NAME) = (VAL)) | ||
199 | |||
200 | /* | 186 | /* |
201 | ** Stuff declared in arch/parisc/kernel/pci.c | 187 | ** Stuff declared in arch/parisc/kernel/pci.c |
202 | */ | 188 | */ |
diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h index aead40b16dd8..7f09533da771 100644 --- a/arch/parisc/include/asm/ptrace.h +++ b/arch/parisc/include/asm/ptrace.h | |||
@@ -47,13 +47,8 @@ struct pt_regs { | |||
47 | 47 | ||
48 | #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) | 48 | #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) |
49 | 49 | ||
50 | struct task_struct; | ||
51 | #define arch_has_single_step() 1 | 50 | #define arch_has_single_step() 1 |
52 | void user_disable_single_step(struct task_struct *task); | ||
53 | void user_enable_single_step(struct task_struct *task); | ||
54 | |||
55 | #define arch_has_block_step() 1 | 51 | #define arch_has_block_step() 1 |
56 | void user_enable_block_step(struct task_struct *task); | ||
57 | 52 | ||
58 | /* XXX should we use iaoq[1] or iaoq[0] ? */ | 53 | /* XXX should we use iaoq[1] or iaoq[0] ? */ |
59 | #define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0) | 54 | #define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0) |
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 9147391afb03..c9b932260f47 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c | |||
@@ -234,18 +234,3 @@ long parisc_personality(unsigned long personality) | |||
234 | 234 | ||
235 | return err; | 235 | return err; |
236 | } | 236 | } |
237 | |||
238 | long parisc_newuname(struct new_utsname __user *name) | ||
239 | { | ||
240 | int err = sys_newuname(name); | ||
241 | |||
242 | #ifdef CONFIG_COMPAT | ||
243 | if (!err && personality(current->personality) == PER_LINUX32) { | ||
244 | if (__put_user(0, name->machine + 6) || | ||
245 | __put_user(0, name->machine + 7)) | ||
246 | err = -EFAULT; | ||
247 | } | ||
248 | #endif | ||
249 | |||
250 | return err; | ||
251 | } | ||
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index de5f6dab48b7..3d52c978738f 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S | |||
@@ -127,7 +127,7 @@ | |||
127 | ENTRY_SAME(socketpair) | 127 | ENTRY_SAME(socketpair) |
128 | ENTRY_SAME(setpgid) | 128 | ENTRY_SAME(setpgid) |
129 | ENTRY_SAME(send) | 129 | ENTRY_SAME(send) |
130 | ENTRY_OURS(newuname) | 130 | ENTRY_SAME(newuname) |
131 | ENTRY_SAME(umask) /* 60 */ | 131 | ENTRY_SAME(umask) /* 60 */ |
132 | ENTRY_SAME(chroot) | 132 | ENTRY_SAME(chroot) |
133 | ENTRY_COMP(ustat) | 133 | ENTRY_COMP(ustat) |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 155d571f5e26..8a54eb8e3768 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -672,6 +672,9 @@ config ZONE_DMA | |||
672 | bool | 672 | bool |
673 | default y | 673 | default y |
674 | 674 | ||
675 | config NEED_DMA_MAP_STATE | ||
676 | def_bool (PPC64 || NOT_COHERENT_CACHE) | ||
677 | |||
675 | config GENERIC_ISA_DMA | 678 | config GENERIC_ISA_DMA |
676 | bool | 679 | bool |
677 | depends on PPC64 || POWER4 || 6xx && !CPM2 | 680 | depends on PPC64 || POWER4 || 6xx && !CPM2 |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 4774c2f92232..396d21a80058 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
@@ -7,7 +7,8 @@ | |||
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | 9 | ||
10 | #define COMPAT_USER_HZ 100 | 10 | #define COMPAT_USER_HZ 100 |
11 | #define COMPAT_UTS_MACHINE "ppc\0\0" | ||
11 | 12 | ||
12 | typedef u32 compat_size_t; | 13 | typedef u32 compat_size_t; |
13 | typedef s32 compat_ssize_t; | 14 | typedef s32 compat_ssize_t; |
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index 80a973bb9e71..c85ef230135b 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h | |||
@@ -127,9 +127,6 @@ static inline int dma_supported(struct device *dev, u64 mask) | |||
127 | return dma_ops->dma_supported(dev, mask); | 127 | return dma_ops->dma_supported(dev, mask); |
128 | } | 128 | } |
129 | 129 | ||
130 | /* We have our own implementation of pci_set_dma_mask() */ | ||
131 | #define HAVE_ARCH_PCI_SET_DMA_MASK | ||
132 | |||
133 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | 130 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) |
134 | { | 131 | { |
135 | struct dma_map_ops *dma_ops = get_dma_ops(dev); | 132 | struct dma_map_ops *dma_ops = get_dma_ops(dev); |
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index b5ea626eea2d..a20a9ad2258b 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h | |||
@@ -141,38 +141,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus, | |||
141 | 141 | ||
142 | #define HAVE_PCI_LEGACY 1 | 142 | #define HAVE_PCI_LEGACY 1 |
143 | 143 | ||
144 | #if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE) | ||
145 | /* | ||
146 | * For 64-bit kernels, pci_unmap_{single,page} is not a nop. | ||
147 | * For 32-bit non-coherent kernels, pci_dma_sync_single_for_cpu() and | ||
148 | * so on are not nops. | ||
149 | * and thus... | ||
150 | */ | ||
151 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | ||
152 | dma_addr_t ADDR_NAME; | ||
153 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | ||
154 | __u32 LEN_NAME; | ||
155 | #define pci_unmap_addr(PTR, ADDR_NAME) \ | ||
156 | ((PTR)->ADDR_NAME) | ||
157 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
158 | (((PTR)->ADDR_NAME) = (VAL)) | ||
159 | #define pci_unmap_len(PTR, LEN_NAME) \ | ||
160 | ((PTR)->LEN_NAME) | ||
161 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
162 | (((PTR)->LEN_NAME) = (VAL)) | ||
163 | |||
164 | #else /* 32-bit && coherent */ | ||
165 | |||
166 | /* pci_unmap_{page,single} is a nop so... */ | ||
167 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
168 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
169 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
170 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
171 | #define pci_unmap_len(PTR, LEN_NAME) (0) | ||
172 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
173 | |||
174 | #endif /* CONFIG_PPC64 || CONFIG_NOT_COHERENT_CACHE */ | ||
175 | |||
176 | #ifdef CONFIG_PPC64 | 144 | #ifdef CONFIG_PPC64 |
177 | 145 | ||
178 | /* The PCI address space does not equal the physical memory address | 146 | /* The PCI address space does not equal the physical memory address |
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index b45108126562..9e2d84c06b74 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h | |||
@@ -137,15 +137,8 @@ do { \ | |||
137 | } while (0) | 137 | } while (0) |
138 | #endif /* __powerpc64__ */ | 138 | #endif /* __powerpc64__ */ |
139 | 139 | ||
140 | /* | ||
141 | * These are defined as per linux/ptrace.h, which see. | ||
142 | */ | ||
143 | #define arch_has_single_step() (1) | 140 | #define arch_has_single_step() (1) |
144 | #define arch_has_block_step() (!cpu_has_feature(CPU_FTR_601)) | 141 | #define arch_has_block_step() (!cpu_has_feature(CPU_FTR_601)) |
145 | extern void user_enable_single_step(struct task_struct *); | ||
146 | extern void user_enable_block_step(struct task_struct *); | ||
147 | extern void user_disable_single_step(struct task_struct *); | ||
148 | |||
149 | #define ARCH_HAS_USER_SINGLE_STEP_INFO | 142 | #define ARCH_HAS_USER_SINGLE_STEP_INFO |
150 | 143 | ||
151 | #endif /* __ASSEMBLY__ */ | 144 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h index eb8eb400c664..4084e567d28e 100644 --- a/arch/powerpc/include/asm/syscalls.h +++ b/arch/powerpc/include/asm/syscalls.h | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <asm/signal.h> | 8 | #include <asm/signal.h> |
9 | 9 | ||
10 | struct new_utsname; | ||
11 | struct pt_regs; | 10 | struct pt_regs; |
12 | struct rtas_args; | 11 | struct rtas_args; |
13 | struct sigaction; | 12 | struct sigaction; |
@@ -35,12 +34,9 @@ asmlinkage long sys_pipe2(int __user *fildes, int flags); | |||
35 | asmlinkage long sys_rt_sigaction(int sig, | 34 | asmlinkage long sys_rt_sigaction(int sig, |
36 | const struct sigaction __user *act, | 35 | const struct sigaction __user *act, |
37 | struct sigaction __user *oact, size_t sigsetsize); | 36 | struct sigaction __user *oact, size_t sigsetsize); |
38 | asmlinkage int sys_ipc(uint call, int first, unsigned long second, | ||
39 | long third, void __user *ptr, long fifth); | ||
40 | asmlinkage long ppc64_personality(unsigned long personality); | 37 | asmlinkage long ppc64_personality(unsigned long personality); |
41 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs); | 38 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs); |
42 | asmlinkage time_t sys64_time(time_t __user * tloc); | 39 | asmlinkage time_t sys64_time(time_t __user * tloc); |
43 | asmlinkage long ppc_newuname(struct new_utsname __user * name); | ||
44 | 40 | ||
45 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, | 41 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, |
46 | size_t sigsetsize); | 42 | size_t sigsetsize); |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 07d2d19ab5e9..a5ee345b6a5c 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
@@ -125,7 +125,7 @@ SYSCALL_SPU(fsync) | |||
125 | SYS32ONLY(sigreturn) | 125 | SYS32ONLY(sigreturn) |
126 | PPC_SYS(clone) | 126 | PPC_SYS(clone) |
127 | COMPAT_SYS_SPU(setdomainname) | 127 | COMPAT_SYS_SPU(setdomainname) |
128 | PPC_SYS_SPU(newuname) | 128 | SYSCALL_SPU(newuname) |
129 | SYSCALL(ni_syscall) | 129 | SYSCALL(ni_syscall) |
130 | COMPAT_SYS_SPU(adjtimex) | 130 | COMPAT_SYS_SPU(adjtimex) |
131 | SYSCALL_SPU(mprotect) | 131 | SYSCALL_SPU(mprotect) |
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index f6ca76176766..f0a10266e7f7 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
@@ -364,6 +364,7 @@ | |||
364 | #define __ARCH_WANT_STAT64 | 364 | #define __ARCH_WANT_STAT64 |
365 | #define __ARCH_WANT_SYS_ALARM | 365 | #define __ARCH_WANT_SYS_ALARM |
366 | #define __ARCH_WANT_SYS_GETHOSTNAME | 366 | #define __ARCH_WANT_SYS_GETHOSTNAME |
367 | #define __ARCH_WANT_SYS_IPC | ||
367 | #define __ARCH_WANT_SYS_PAUSE | 368 | #define __ARCH_WANT_SYS_PAUSE |
368 | #define __ARCH_WANT_SYS_SGETMASK | 369 | #define __ARCH_WANT_SYS_SGETMASK |
369 | #define __ARCH_WANT_SYS_SIGNAL | 370 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -376,6 +377,7 @@ | |||
376 | #define __ARCH_WANT_SYS_LLSEEK | 377 | #define __ARCH_WANT_SYS_LLSEEK |
377 | #define __ARCH_WANT_SYS_NICE | 378 | #define __ARCH_WANT_SYS_NICE |
378 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 379 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
380 | #define __ARCH_WANT_SYS_OLD_UNAME | ||
379 | #define __ARCH_WANT_SYS_OLDUMOUNT | 381 | #define __ARCH_WANT_SYS_OLDUMOUNT |
380 | #define __ARCH_WANT_SYS_SIGPENDING | 382 | #define __ARCH_WANT_SYS_SIGPENDING |
381 | #define __ARCH_WANT_SYS_SIGPROCMASK | 383 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index bb37b1d19a58..01fe9ce28379 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c | |||
@@ -642,7 +642,7 @@ static struct kobj_attribute *cache_index_opt_attrs[] = { | |||
642 | &cache_assoc_attr, | 642 | &cache_assoc_attr, |
643 | }; | 643 | }; |
644 | 644 | ||
645 | static struct sysfs_ops cache_index_ops = { | 645 | static const struct sysfs_ops cache_index_ops = { |
646 | .show = cache_index_show, | 646 | .show = cache_index_show, |
647 | }; | 647 | }; |
648 | 648 | ||
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 2597f9545d8a..f3c42ce516e7 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -63,21 +63,6 @@ struct dma_map_ops *get_pci_dma_ops(void) | |||
63 | } | 63 | } |
64 | EXPORT_SYMBOL(get_pci_dma_ops); | 64 | EXPORT_SYMBOL(get_pci_dma_ops); |
65 | 65 | ||
66 | int pci_set_dma_mask(struct pci_dev *dev, u64 mask) | ||
67 | { | ||
68 | return dma_set_mask(&dev->dev, mask); | ||
69 | } | ||
70 | |||
71 | int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | ||
72 | { | ||
73 | int rc; | ||
74 | |||
75 | rc = dma_set_mask(&dev->dev, mask); | ||
76 | dev->dev.coherent_dma_mask = dev->dma_mask; | ||
77 | |||
78 | return rc; | ||
79 | } | ||
80 | |||
81 | struct pci_controller *pcibios_alloc_controller(struct device_node *dev) | 66 | struct pci_controller *pcibios_alloc_controller(struct device_node *dev) |
82 | { | 67 | { |
83 | struct pci_controller *phb; | 68 | struct pci_controller *phb; |
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index 3370e62e43d4..f2496f2faecc 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c | |||
@@ -42,100 +42,6 @@ | |||
42 | #include <asm/time.h> | 42 | #include <asm/time.h> |
43 | #include <asm/unistd.h> | 43 | #include <asm/unistd.h> |
44 | 44 | ||
45 | /* | ||
46 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
47 | * | ||
48 | * This is really horribly ugly. | ||
49 | */ | ||
50 | int sys_ipc(uint call, int first, unsigned long second, long third, | ||
51 | void __user *ptr, long fifth) | ||
52 | { | ||
53 | int version, ret; | ||
54 | |||
55 | version = call >> 16; /* hack for backward compatibility */ | ||
56 | call &= 0xffff; | ||
57 | |||
58 | ret = -ENOSYS; | ||
59 | switch (call) { | ||
60 | case SEMOP: | ||
61 | ret = sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
62 | (unsigned)second, NULL); | ||
63 | break; | ||
64 | case SEMTIMEDOP: | ||
65 | ret = sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
66 | (unsigned)second, | ||
67 | (const struct timespec __user *) fifth); | ||
68 | break; | ||
69 | case SEMGET: | ||
70 | ret = sys_semget (first, (int)second, third); | ||
71 | break; | ||
72 | case SEMCTL: { | ||
73 | union semun fourth; | ||
74 | |||
75 | ret = -EINVAL; | ||
76 | if (!ptr) | ||
77 | break; | ||
78 | if ((ret = get_user(fourth.__pad, (void __user * __user *)ptr))) | ||
79 | break; | ||
80 | ret = sys_semctl(first, (int)second, third, fourth); | ||
81 | break; | ||
82 | } | ||
83 | case MSGSND: | ||
84 | ret = sys_msgsnd(first, (struct msgbuf __user *)ptr, | ||
85 | (size_t)second, third); | ||
86 | break; | ||
87 | case MSGRCV: | ||
88 | switch (version) { | ||
89 | case 0: { | ||
90 | struct ipc_kludge tmp; | ||
91 | |||
92 | ret = -EINVAL; | ||
93 | if (!ptr) | ||
94 | break; | ||
95 | if ((ret = copy_from_user(&tmp, | ||
96 | (struct ipc_kludge __user *) ptr, | ||
97 | sizeof (tmp)) ? -EFAULT : 0)) | ||
98 | break; | ||
99 | ret = sys_msgrcv(first, tmp.msgp, (size_t) second, | ||
100 | tmp.msgtyp, third); | ||
101 | break; | ||
102 | } | ||
103 | default: | ||
104 | ret = sys_msgrcv (first, (struct msgbuf __user *) ptr, | ||
105 | (size_t)second, fifth, third); | ||
106 | break; | ||
107 | } | ||
108 | break; | ||
109 | case MSGGET: | ||
110 | ret = sys_msgget((key_t)first, (int)second); | ||
111 | break; | ||
112 | case MSGCTL: | ||
113 | ret = sys_msgctl(first, (int)second, | ||
114 | (struct msqid_ds __user *)ptr); | ||
115 | break; | ||
116 | case SHMAT: { | ||
117 | ulong raddr; | ||
118 | ret = do_shmat(first, (char __user *)ptr, (int)second, &raddr); | ||
119 | if (ret) | ||
120 | break; | ||
121 | ret = put_user(raddr, (ulong __user *) third); | ||
122 | break; | ||
123 | } | ||
124 | case SHMDT: | ||
125 | ret = sys_shmdt((char __user *)ptr); | ||
126 | break; | ||
127 | case SHMGET: | ||
128 | ret = sys_shmget(first, (size_t)second, third); | ||
129 | break; | ||
130 | case SHMCTL: | ||
131 | ret = sys_shmctl(first, (int)second, | ||
132 | (struct shmid_ds __user *)ptr); | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static inline unsigned long do_mmap2(unsigned long addr, size_t len, | 45 | static inline unsigned long do_mmap2(unsigned long addr, size_t len, |
140 | unsigned long prot, unsigned long flags, | 46 | unsigned long prot, unsigned long flags, |
141 | unsigned long fd, unsigned long off, int shift) | 47 | unsigned long fd, unsigned long off, int shift) |
@@ -210,76 +116,6 @@ long ppc64_personality(unsigned long personality) | |||
210 | } | 116 | } |
211 | #endif | 117 | #endif |
212 | 118 | ||
213 | #ifdef CONFIG_PPC64 | ||
214 | #define OVERRIDE_MACHINE (personality(current->personality) == PER_LINUX32) | ||
215 | #else | ||
216 | #define OVERRIDE_MACHINE 0 | ||
217 | #endif | ||
218 | |||
219 | static inline int override_machine(char __user *mach) | ||
220 | { | ||
221 | if (OVERRIDE_MACHINE) { | ||
222 | /* change ppc64 to ppc */ | ||
223 | if (__put_user(0, mach+3) || __put_user(0, mach+4)) | ||
224 | return -EFAULT; | ||
225 | } | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | long ppc_newuname(struct new_utsname __user * name) | ||
230 | { | ||
231 | int err = 0; | ||
232 | |||
233 | down_read(&uts_sem); | ||
234 | if (copy_to_user(name, utsname(), sizeof(*name))) | ||
235 | err = -EFAULT; | ||
236 | up_read(&uts_sem); | ||
237 | if (!err) | ||
238 | err = override_machine(name->machine); | ||
239 | return err; | ||
240 | } | ||
241 | |||
242 | int sys_uname(struct old_utsname __user *name) | ||
243 | { | ||
244 | int err = 0; | ||
245 | |||
246 | down_read(&uts_sem); | ||
247 | if (copy_to_user(name, utsname(), sizeof(*name))) | ||
248 | err = -EFAULT; | ||
249 | up_read(&uts_sem); | ||
250 | if (!err) | ||
251 | err = override_machine(name->machine); | ||
252 | return err; | ||
253 | } | ||
254 | |||
255 | int sys_olduname(struct oldold_utsname __user *name) | ||
256 | { | ||
257 | int error; | ||
258 | |||
259 | if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) | ||
260 | return -EFAULT; | ||
261 | |||
262 | down_read(&uts_sem); | ||
263 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
264 | __OLD_UTS_LEN); | ||
265 | error |= __put_user(0, name->sysname + __OLD_UTS_LEN); | ||
266 | error |= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
267 | __OLD_UTS_LEN); | ||
268 | error |= __put_user(0, name->nodename + __OLD_UTS_LEN); | ||
269 | error |= __copy_to_user(&name->release, &utsname()->release, | ||
270 | __OLD_UTS_LEN); | ||
271 | error |= __put_user(0, name->release + __OLD_UTS_LEN); | ||
272 | error |= __copy_to_user(&name->version, &utsname()->version, | ||
273 | __OLD_UTS_LEN); | ||
274 | error |= __put_user(0, name->version + __OLD_UTS_LEN); | ||
275 | error |= __copy_to_user(&name->machine, &utsname()->machine, | ||
276 | __OLD_UTS_LEN); | ||
277 | error |= override_machine(name->machine); | ||
278 | up_read(&uts_sem); | ||
279 | |||
280 | return error? -EFAULT: 0; | ||
281 | } | ||
282 | |||
283 | long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, | 119 | long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, |
284 | u32 len_high, u32 len_low) | 120 | u32 len_high, u32 len_low) |
285 | { | 121 | { |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index 6f8ebe1085b3..072b948b2e2d 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c | |||
@@ -553,7 +553,7 @@ static ssize_t mpc52xx_wdt_write(struct file *file, const char __user *data, | |||
553 | return 0; | 553 | return 0; |
554 | } | 554 | } |
555 | 555 | ||
556 | static struct watchdog_info mpc5200_wdt_info = { | 556 | static const struct watchdog_info mpc5200_wdt_info = { |
557 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 557 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
558 | .identity = WDT_IDENTITY, | 558 | .identity = WDT_IDENTITY, |
559 | }; | 559 | }; |
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 01a08020bc0e..104f2007f097 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h | |||
@@ -35,7 +35,8 @@ | |||
35 | 35 | ||
36 | extern long psw32_user_bits; | 36 | extern long psw32_user_bits; |
37 | 37 | ||
38 | #define COMPAT_USER_HZ 100 | 38 | #define COMPAT_USER_HZ 100 |
39 | #define COMPAT_UTS_MACHINE "s390\0\0\0\0" | ||
39 | 40 | ||
40 | typedef u32 compat_size_t; | 41 | typedef u32 compat_size_t; |
41 | typedef s32 compat_ssize_t; | 42 | typedef s32 compat_ssize_t; |
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index dd2d913afcae..fef9b33cdd59 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h | |||
@@ -489,9 +489,6 @@ struct user_regs_struct | |||
489 | * These are defined as per linux/ptrace.h, which see. | 489 | * These are defined as per linux/ptrace.h, which see. |
490 | */ | 490 | */ |
491 | #define arch_has_single_step() (1) | 491 | #define arch_has_single_step() (1) |
492 | struct task_struct; | ||
493 | extern void user_enable_single_step(struct task_struct *); | ||
494 | extern void user_disable_single_step(struct task_struct *); | ||
495 | extern void show_regs(struct pt_regs * regs); | 492 | extern void show_regs(struct pt_regs * regs); |
496 | 493 | ||
497 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) | 494 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) |
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index c666bfe5e984..9b04b1102bbc 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h | |||
@@ -321,11 +321,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, | |||
321 | #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 | 321 | #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 |
322 | #define QDIO_ERROR_SLSB_STATE 0x80 | 322 | #define QDIO_ERROR_SLSB_STATE 0x80 |
323 | 323 | ||
324 | /* for qdio_initialize */ | ||
325 | #define QDIO_INBOUND_0COPY_SBALS 0x01 | ||
326 | #define QDIO_OUTBOUND_0COPY_SBALS 0x02 | ||
327 | #define QDIO_USE_OUTBOUND_PCIS 0x04 | ||
328 | |||
329 | /* for qdio_cleanup */ | 324 | /* for qdio_cleanup */ |
330 | #define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01 | 325 | #define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01 |
331 | #define QDIO_FLAG_CLEANUP_USING_HALT 0x02 | 326 | #define QDIO_FLAG_CLEANUP_USING_HALT 0x02 |
@@ -344,7 +339,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, | |||
344 | * @input_handler: handler to be called for input queues | 339 | * @input_handler: handler to be called for input queues |
345 | * @output_handler: handler to be called for output queues | 340 | * @output_handler: handler to be called for output queues |
346 | * @int_parm: interruption parameter | 341 | * @int_parm: interruption parameter |
347 | * @flags: initialization flags | ||
348 | * @input_sbal_addr_array: address of no_input_qs * 128 pointers | 342 | * @input_sbal_addr_array: address of no_input_qs * 128 pointers |
349 | * @output_sbal_addr_array: address of no_output_qs * 128 pointers | 343 | * @output_sbal_addr_array: address of no_output_qs * 128 pointers |
350 | */ | 344 | */ |
@@ -361,7 +355,6 @@ struct qdio_initialize { | |||
361 | qdio_handler_t *input_handler; | 355 | qdio_handler_t *input_handler; |
362 | qdio_handler_t *output_handler; | 356 | qdio_handler_t *output_handler; |
363 | unsigned long int_parm; | 357 | unsigned long int_parm; |
364 | unsigned long flags; | ||
365 | void **input_sbal_addr_array; | 358 | void **input_sbal_addr_array; |
366 | void **output_sbal_addr_array; | 359 | void **output_sbal_addr_array; |
367 | }; | 360 | }; |
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 6e9f049fa823..5f0075150a65 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h | |||
@@ -392,6 +392,7 @@ | |||
392 | #define __ARCH_WANT_SYS_LLSEEK | 392 | #define __ARCH_WANT_SYS_LLSEEK |
393 | #define __ARCH_WANT_SYS_NICE | 393 | #define __ARCH_WANT_SYS_NICE |
394 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 394 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
395 | #define __ARCH_WANT_SYS_OLD_MMAP | ||
395 | #define __ARCH_WANT_SYS_OLDUMOUNT | 396 | #define __ARCH_WANT_SYS_OLDUMOUNT |
396 | #define __ARCH_WANT_SYS_SIGPENDING | 397 | #define __ARCH_WANT_SYS_SIGPENDING |
397 | #define __ARCH_WANT_SYS_SIGPROCMASK | 398 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 30de2d0e52bb..672ce52341b4 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
@@ -547,7 +547,7 @@ sys32_setdomainname_wrapper: | |||
547 | .globl sys32_newuname_wrapper | 547 | .globl sys32_newuname_wrapper |
548 | sys32_newuname_wrapper: | 548 | sys32_newuname_wrapper: |
549 | llgtr %r2,%r2 # struct new_utsname * | 549 | llgtr %r2,%r2 # struct new_utsname * |
550 | jg sys_s390_newuname # branch to system call | 550 | jg sys_newuname # branch to system call |
551 | 551 | ||
552 | .globl compat_sys_adjtimex_wrapper | 552 | .globl compat_sys_adjtimex_wrapper |
553 | compat_sys_adjtimex_wrapper: | 553 | compat_sys_adjtimex_wrapper: |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index e1e5e767ab56..eb15c12ec158 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
@@ -24,17 +24,13 @@ int __cpuinit start_secondary(void *cpuvoid); | |||
24 | void __init startup_init(void); | 24 | void __init startup_init(void); |
25 | void die(const char * str, struct pt_regs * regs, long err); | 25 | void die(const char * str, struct pt_regs * regs, long err); |
26 | 26 | ||
27 | struct new_utsname; | 27 | struct s390_mmap_arg_struct; |
28 | struct mmap_arg_struct; | ||
29 | struct fadvise64_64_args; | 28 | struct fadvise64_64_args; |
30 | struct old_sigaction; | 29 | struct old_sigaction; |
31 | struct sel_arg_struct; | ||
32 | 30 | ||
33 | long sys_mmap2(struct mmap_arg_struct __user *arg); | 31 | long sys_mmap2(struct s390_mmap_arg_struct __user *arg); |
34 | long sys_s390_old_mmap(struct mmap_arg_struct __user *arg); | 32 | long sys_s390_ipc(uint call, int first, unsigned long second, |
35 | long sys_ipc(uint call, int first, unsigned long second, | ||
36 | unsigned long third, void __user *ptr); | 33 | unsigned long third, void __user *ptr); |
37 | long sys_s390_newuname(struct new_utsname __user *name); | ||
38 | long sys_s390_personality(unsigned long personality); | 34 | long sys_s390_personality(unsigned long personality); |
39 | long sys_s390_fadvise64(int fd, u32 offset_high, u32 offset_low, | 35 | long sys_s390_fadvise64(int fd, u32 offset_high, u32 offset_low, |
40 | size_t len, int advice); | 36 | size_t len, int advice); |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 8b10127c00ad..29f65bce55e1 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -1020,7 +1020,9 @@ out: | |||
1020 | return rc; | 1020 | return rc; |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf, | 1023 | static ssize_t __ref rescan_store(struct sysdev_class *class, |
1024 | struct sysdev_class_attribute *attr, | ||
1025 | const char *buf, | ||
1024 | size_t count) | 1026 | size_t count) |
1025 | { | 1027 | { |
1026 | int rc; | 1028 | int rc; |
@@ -1031,7 +1033,9 @@ static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf, | |||
1031 | static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store); | 1033 | static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store); |
1032 | #endif /* CONFIG_HOTPLUG_CPU */ | 1034 | #endif /* CONFIG_HOTPLUG_CPU */ |
1033 | 1035 | ||
1034 | static ssize_t dispatching_show(struct sysdev_class *class, char *buf) | 1036 | static ssize_t dispatching_show(struct sysdev_class *class, |
1037 | struct sysdev_class_attribute *attr, | ||
1038 | char *buf) | ||
1035 | { | 1039 | { |
1036 | ssize_t count; | 1040 | ssize_t count; |
1037 | 1041 | ||
@@ -1041,7 +1045,9 @@ static ssize_t dispatching_show(struct sysdev_class *class, char *buf) | |||
1041 | return count; | 1045 | return count; |
1042 | } | 1046 | } |
1043 | 1047 | ||
1044 | static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf, | 1048 | static ssize_t dispatching_store(struct sysdev_class *dev, |
1049 | struct sysdev_class_attribute *attr, | ||
1050 | const char *buf, | ||
1045 | size_t count) | 1051 | size_t count) |
1046 | { | 1052 | { |
1047 | int val, rc; | 1053 | int val, rc; |
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index 86a74c9c9e63..7b6b0f81a283 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c | |||
@@ -33,13 +33,12 @@ | |||
33 | #include "entry.h" | 33 | #include "entry.h" |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Perform the select(nd, in, out, ex, tv) and mmap() system | 36 | * Perform the mmap() system call. Linux for S/390 isn't able to handle more |
37 | * calls. Linux for S/390 isn't able to handle more than 5 | 37 | * than 5 system call parameters, so this system call uses a memory block |
38 | * system call parameters, so these system calls used a memory | 38 | * for parameter passing. |
39 | * block for parameter passing.. | ||
40 | */ | 39 | */ |
41 | 40 | ||
42 | struct mmap_arg_struct { | 41 | struct s390_mmap_arg_struct { |
43 | unsigned long addr; | 42 | unsigned long addr; |
44 | unsigned long len; | 43 | unsigned long len; |
45 | unsigned long prot; | 44 | unsigned long prot; |
@@ -48,9 +47,9 @@ struct mmap_arg_struct { | |||
48 | unsigned long offset; | 47 | unsigned long offset; |
49 | }; | 48 | }; |
50 | 49 | ||
51 | SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg) | 50 | SYSCALL_DEFINE1(mmap2, struct s390_mmap_arg_struct __user *, arg) |
52 | { | 51 | { |
53 | struct mmap_arg_struct a; | 52 | struct s390_mmap_arg_struct a; |
54 | int error = -EFAULT; | 53 | int error = -EFAULT; |
55 | 54 | ||
56 | if (copy_from_user(&a, arg, sizeof(a))) | 55 | if (copy_from_user(&a, arg, sizeof(a))) |
@@ -60,29 +59,12 @@ out: | |||
60 | return error; | 59 | return error; |
61 | } | 60 | } |
62 | 61 | ||
63 | SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg) | ||
64 | { | ||
65 | struct mmap_arg_struct a; | ||
66 | long error = -EFAULT; | ||
67 | |||
68 | if (copy_from_user(&a, arg, sizeof(a))) | ||
69 | goto out; | ||
70 | |||
71 | error = -EINVAL; | ||
72 | if (a.offset & ~PAGE_MASK) | ||
73 | goto out; | ||
74 | |||
75 | error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); | ||
76 | out: | ||
77 | return error; | ||
78 | } | ||
79 | |||
80 | /* | 62 | /* |
81 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | 63 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. |
82 | * | 64 | * |
83 | * This is really horribly ugly. | 65 | * This is really horribly ugly. |
84 | */ | 66 | */ |
85 | SYSCALL_DEFINE5(ipc, uint, call, int, first, unsigned long, second, | 67 | SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second, |
86 | unsigned long, third, void __user *, ptr) | 68 | unsigned long, third, void __user *, ptr) |
87 | { | 69 | { |
88 | struct ipc_kludge tmp; | 70 | struct ipc_kludge tmp; |
@@ -149,17 +131,6 @@ SYSCALL_DEFINE5(ipc, uint, call, int, first, unsigned long, second, | |||
149 | } | 131 | } |
150 | 132 | ||
151 | #ifdef CONFIG_64BIT | 133 | #ifdef CONFIG_64BIT |
152 | SYSCALL_DEFINE1(s390_newuname, struct new_utsname __user *, name) | ||
153 | { | ||
154 | int ret = sys_newuname(name); | ||
155 | |||
156 | if (personality(current->personality) == PER_LINUX32 && !ret) { | ||
157 | ret = copy_to_user(name->machine, "s390\0\0\0\0", 8); | ||
158 | if (ret) ret = -EFAULT; | ||
159 | } | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | SYSCALL_DEFINE1(s390_personality, unsigned long, personality) | 134 | SYSCALL_DEFINE1(s390_personality, unsigned long, personality) |
164 | { | 135 | { |
165 | int ret; | 136 | int ret; |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 30eca070d426..201ce6bed34e 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
@@ -98,7 +98,7 @@ SYSCALL(sys_uselib,sys_uselib,sys32_uselib_wrapper) | |||
98 | SYSCALL(sys_swapon,sys_swapon,sys32_swapon_wrapper) | 98 | SYSCALL(sys_swapon,sys_swapon,sys32_swapon_wrapper) |
99 | SYSCALL(sys_reboot,sys_reboot,sys32_reboot_wrapper) | 99 | SYSCALL(sys_reboot,sys_reboot,sys32_reboot_wrapper) |
100 | SYSCALL(sys_ni_syscall,sys_ni_syscall,old32_readdir_wrapper) /* old readdir syscall */ | 100 | SYSCALL(sys_ni_syscall,sys_ni_syscall,old32_readdir_wrapper) /* old readdir syscall */ |
101 | SYSCALL(sys_s390_old_mmap,sys_s390_old_mmap,old32_mmap_wrapper) /* 90 */ | 101 | SYSCALL(sys_old_mmap,sys_old_mmap,old32_mmap_wrapper) /* 90 */ |
102 | SYSCALL(sys_munmap,sys_munmap,sys32_munmap_wrapper) | 102 | SYSCALL(sys_munmap,sys_munmap,sys32_munmap_wrapper) |
103 | SYSCALL(sys_truncate,sys_truncate,sys32_truncate_wrapper) | 103 | SYSCALL(sys_truncate,sys_truncate,sys32_truncate_wrapper) |
104 | SYSCALL(sys_ftruncate,sys_ftruncate,sys32_ftruncate_wrapper) | 104 | SYSCALL(sys_ftruncate,sys_ftruncate,sys32_ftruncate_wrapper) |
@@ -125,12 +125,12 @@ NI_SYSCALL /* vm86old for i386 */ | |||
125 | SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4_wrapper) | 125 | SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4_wrapper) |
126 | SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper) /* 115 */ | 126 | SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper) /* 115 */ |
127 | SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) | 127 | SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) |
128 | SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) | 128 | SYSCALL(sys_s390_ipc,sys_s390_ipc,sys32_ipc_wrapper) |
129 | SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) | 129 | SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) |
130 | SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) | 130 | SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) |
131 | SYSCALL(sys_clone,sys_clone,sys_clone_wrapper) /* 120 */ | 131 | SYSCALL(sys_clone,sys_clone,sys_clone_wrapper) /* 120 */ |
132 | SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) | 132 | SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) |
133 | SYSCALL(sys_newuname,sys_s390_newuname,sys32_newuname_wrapper) | 133 | SYSCALL(sys_newuname,sys_newuname,sys32_newuname_wrapper) |
134 | NI_SYSCALL /* modify_ldt for i386 */ | 134 | NI_SYSCALL /* modify_ldt for i386 */ |
135 | SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper) | 135 | SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper) |
136 | SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */ | 136 | SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */ |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index a8f93f1705ad..aa2483e460f3 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -73,15 +73,15 @@ unsigned long long monotonic_clock(void) | |||
73 | } | 73 | } |
74 | EXPORT_SYMBOL(monotonic_clock); | 74 | EXPORT_SYMBOL(monotonic_clock); |
75 | 75 | ||
76 | void tod_to_timeval(__u64 todval, struct timespec *xtime) | 76 | void tod_to_timeval(__u64 todval, struct timespec *xt) |
77 | { | 77 | { |
78 | unsigned long long sec; | 78 | unsigned long long sec; |
79 | 79 | ||
80 | sec = todval >> 12; | 80 | sec = todval >> 12; |
81 | do_div(sec, 1000000); | 81 | do_div(sec, 1000000); |
82 | xtime->tv_sec = sec; | 82 | xt->tv_sec = sec; |
83 | todval -= (sec * 1000000) << 12; | 83 | todval -= (sec * 1000000) << 12; |
84 | xtime->tv_nsec = ((todval * 1000) >> 12); | 84 | xt->tv_nsec = ((todval * 1000) >> 12); |
85 | } | 85 | } |
86 | EXPORT_SYMBOL(tod_to_timeval); | 86 | EXPORT_SYMBOL(tod_to_timeval); |
87 | 87 | ||
@@ -216,8 +216,8 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, | |||
216 | ++vdso_data->tb_update_count; | 216 | ++vdso_data->tb_update_count; |
217 | smp_wmb(); | 217 | smp_wmb(); |
218 | vdso_data->xtime_tod_stamp = clock->cycle_last; | 218 | vdso_data->xtime_tod_stamp = clock->cycle_last; |
219 | vdso_data->xtime_clock_sec = xtime.tv_sec; | 219 | vdso_data->xtime_clock_sec = wall_time->tv_sec; |
220 | vdso_data->xtime_clock_nsec = xtime.tv_nsec; | 220 | vdso_data->xtime_clock_nsec = wall_time->tv_nsec; |
221 | vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; | 221 | vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; |
222 | vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; | 222 | vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; |
223 | smp_wmb(); | 223 | smp_wmb(); |
@@ -1116,14 +1116,18 @@ static struct sys_device etr_port1_dev = { | |||
1116 | /* | 1116 | /* |
1117 | * ETR class attributes | 1117 | * ETR class attributes |
1118 | */ | 1118 | */ |
1119 | static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf) | 1119 | static ssize_t etr_stepping_port_show(struct sysdev_class *class, |
1120 | struct sysdev_class_attribute *attr, | ||
1121 | char *buf) | ||
1120 | { | 1122 | { |
1121 | return sprintf(buf, "%i\n", etr_port0.esw.p); | 1123 | return sprintf(buf, "%i\n", etr_port0.esw.p); |
1122 | } | 1124 | } |
1123 | 1125 | ||
1124 | static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL); | 1126 | static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL); |
1125 | 1127 | ||
1126 | static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf) | 1128 | static ssize_t etr_stepping_mode_show(struct sysdev_class *class, |
1129 | struct sysdev_class_attribute *attr, | ||
1130 | char *buf) | ||
1127 | { | 1131 | { |
1128 | char *mode_str; | 1132 | char *mode_str; |
1129 | 1133 | ||
@@ -1584,7 +1588,9 @@ static struct sysdev_class stp_sysclass = { | |||
1584 | .name = "stp", | 1588 | .name = "stp", |
1585 | }; | 1589 | }; |
1586 | 1590 | ||
1587 | static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf) | 1591 | static ssize_t stp_ctn_id_show(struct sysdev_class *class, |
1592 | struct sysdev_class_attribute *attr, | ||
1593 | char *buf) | ||
1588 | { | 1594 | { |
1589 | if (!stp_online) | 1595 | if (!stp_online) |
1590 | return -ENODATA; | 1596 | return -ENODATA; |
@@ -1594,7 +1600,9 @@ static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf) | |||
1594 | 1600 | ||
1595 | static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL); | 1601 | static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL); |
1596 | 1602 | ||
1597 | static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf) | 1603 | static ssize_t stp_ctn_type_show(struct sysdev_class *class, |
1604 | struct sysdev_class_attribute *attr, | ||
1605 | char *buf) | ||
1598 | { | 1606 | { |
1599 | if (!stp_online) | 1607 | if (!stp_online) |
1600 | return -ENODATA; | 1608 | return -ENODATA; |
@@ -1603,7 +1611,9 @@ static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf) | |||
1603 | 1611 | ||
1604 | static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL); | 1612 | static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL); |
1605 | 1613 | ||
1606 | static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf) | 1614 | static ssize_t stp_dst_offset_show(struct sysdev_class *class, |
1615 | struct sysdev_class_attribute *attr, | ||
1616 | char *buf) | ||
1607 | { | 1617 | { |
1608 | if (!stp_online || !(stp_info.vbits & 0x2000)) | 1618 | if (!stp_online || !(stp_info.vbits & 0x2000)) |
1609 | return -ENODATA; | 1619 | return -ENODATA; |
@@ -1612,7 +1622,9 @@ static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf) | |||
1612 | 1622 | ||
1613 | static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL); | 1623 | static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL); |
1614 | 1624 | ||
1615 | static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf) | 1625 | static ssize_t stp_leap_seconds_show(struct sysdev_class *class, |
1626 | struct sysdev_class_attribute *attr, | ||
1627 | char *buf) | ||
1616 | { | 1628 | { |
1617 | if (!stp_online || !(stp_info.vbits & 0x8000)) | 1629 | if (!stp_online || !(stp_info.vbits & 0x8000)) |
1618 | return -ENODATA; | 1630 | return -ENODATA; |
@@ -1621,7 +1633,9 @@ static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf) | |||
1621 | 1633 | ||
1622 | static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL); | 1634 | static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL); |
1623 | 1635 | ||
1624 | static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf) | 1636 | static ssize_t stp_stratum_show(struct sysdev_class *class, |
1637 | struct sysdev_class_attribute *attr, | ||
1638 | char *buf) | ||
1625 | { | 1639 | { |
1626 | if (!stp_online) | 1640 | if (!stp_online) |
1627 | return -ENODATA; | 1641 | return -ENODATA; |
@@ -1630,7 +1644,9 @@ static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf) | |||
1630 | 1644 | ||
1631 | static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL); | 1645 | static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL); |
1632 | 1646 | ||
1633 | static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf) | 1647 | static ssize_t stp_time_offset_show(struct sysdev_class *class, |
1648 | struct sysdev_class_attribute *attr, | ||
1649 | char *buf) | ||
1634 | { | 1650 | { |
1635 | if (!stp_online || !(stp_info.vbits & 0x0800)) | 1651 | if (!stp_online || !(stp_info.vbits & 0x0800)) |
1636 | return -ENODATA; | 1652 | return -ENODATA; |
@@ -1639,7 +1655,9 @@ static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf) | |||
1639 | 1655 | ||
1640 | static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL); | 1656 | static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL); |
1641 | 1657 | ||
1642 | static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf) | 1658 | static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, |
1659 | struct sysdev_class_attribute *attr, | ||
1660 | char *buf) | ||
1643 | { | 1661 | { |
1644 | if (!stp_online || !(stp_info.vbits & 0x4000)) | 1662 | if (!stp_online || !(stp_info.vbits & 0x4000)) |
1645 | return -ENODATA; | 1663 | return -ENODATA; |
@@ -1649,7 +1667,9 @@ static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf) | |||
1649 | static SYSDEV_CLASS_ATTR(time_zone_offset, 0400, | 1667 | static SYSDEV_CLASS_ATTR(time_zone_offset, 0400, |
1650 | stp_time_zone_offset_show, NULL); | 1668 | stp_time_zone_offset_show, NULL); |
1651 | 1669 | ||
1652 | static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf) | 1670 | static ssize_t stp_timing_mode_show(struct sysdev_class *class, |
1671 | struct sysdev_class_attribute *attr, | ||
1672 | char *buf) | ||
1653 | { | 1673 | { |
1654 | if (!stp_online) | 1674 | if (!stp_online) |
1655 | return -ENODATA; | 1675 | return -ENODATA; |
@@ -1658,7 +1678,9 @@ static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf) | |||
1658 | 1678 | ||
1659 | static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL); | 1679 | static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL); |
1660 | 1680 | ||
1661 | static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf) | 1681 | static ssize_t stp_timing_state_show(struct sysdev_class *class, |
1682 | struct sysdev_class_attribute *attr, | ||
1683 | char *buf) | ||
1662 | { | 1684 | { |
1663 | if (!stp_online) | 1685 | if (!stp_online) |
1664 | return -ENODATA; | 1686 | return -ENODATA; |
@@ -1667,12 +1689,15 @@ static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf) | |||
1667 | 1689 | ||
1668 | static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL); | 1690 | static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL); |
1669 | 1691 | ||
1670 | static ssize_t stp_online_show(struct sysdev_class *class, char *buf) | 1692 | static ssize_t stp_online_show(struct sysdev_class *class, |
1693 | struct sysdev_class_attribute *attr, | ||
1694 | char *buf) | ||
1671 | { | 1695 | { |
1672 | return sprintf(buf, "%i\n", stp_online); | 1696 | return sprintf(buf, "%i\n", stp_online); |
1673 | } | 1697 | } |
1674 | 1698 | ||
1675 | static ssize_t stp_online_store(struct sysdev_class *class, | 1699 | static ssize_t stp_online_store(struct sysdev_class *class, |
1700 | struct sysdev_class_attribute *attr, | ||
1676 | const char *buf, size_t count) | 1701 | const char *buf, size_t count) |
1677 | { | 1702 | { |
1678 | unsigned int value; | 1703 | unsigned int value; |
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index cd54a1c352af..761ab8b56afc 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile | |||
@@ -2,7 +2,8 @@ | |||
2 | # Makefile for s390-specific library files.. | 2 | # Makefile for s390-specific library files.. |
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o usercopy.o | 5 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o |
6 | obj-y += usercopy.o | ||
6 | obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o | 7 | obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o |
7 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o | 8 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o |
8 | lib-$(CONFIG_SMP) += spinlock.o | 9 | lib-$(CONFIG_SMP) += spinlock.o |
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 76a3637b88e0..f16bd04e39e9 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c | |||
@@ -374,7 +374,7 @@ static struct ctl_table cmm_dir_table[] = { | |||
374 | #ifdef CONFIG_CMM_IUCV | 374 | #ifdef CONFIG_CMM_IUCV |
375 | #define SMSG_PREFIX "CMM" | 375 | #define SMSG_PREFIX "CMM" |
376 | static void | 376 | static void |
377 | cmm_smsg_target(char *from, char *msg) | 377 | cmm_smsg_target(const char *from, char *msg) |
378 | { | 378 | { |
379 | long nr, seconds; | 379 | long nr, seconds; |
380 | 380 | ||
diff --git a/arch/score/include/asm/ptrace.h b/arch/score/include/asm/ptrace.h index d40e691f23e2..e89dc9b1ef49 100644 --- a/arch/score/include/asm/ptrace.h +++ b/arch/score/include/asm/ptrace.h | |||
@@ -90,8 +90,7 @@ extern int read_tsk_short(struct task_struct *, unsigned long, | |||
90 | unsigned short *); | 90 | unsigned short *); |
91 | 91 | ||
92 | #define arch_has_single_step() (1) | 92 | #define arch_has_single_step() (1) |
93 | extern void user_enable_single_step(struct task_struct *); | 93 | |
94 | extern void user_disable_single_step(struct task_struct *); | ||
95 | #endif /* __KERNEL__ */ | 94 | #endif /* __KERNEL__ */ |
96 | 95 | ||
97 | #endif /* _ASM_SCORE_PTRACE_H */ | 96 | #endif /* _ASM_SCORE_PTRACE_H */ |
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 05cef5061293..8d90564c2bcf 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -183,6 +183,9 @@ config DMA_COHERENT | |||
183 | config DMA_NONCOHERENT | 183 | config DMA_NONCOHERENT |
184 | def_bool !DMA_COHERENT | 184 | def_bool !DMA_COHERENT |
185 | 185 | ||
186 | config NEED_DMA_MAP_STATE | ||
187 | def_bool DMA_NONCOHERENT | ||
188 | |||
186 | source "init/Kconfig" | 189 | source "init/Kconfig" |
187 | 190 | ||
188 | source "kernel/Kconfig.freezer" | 191 | source "kernel/Kconfig.freezer" |
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h index 1042f7f0a48b..8bd952fcf3ba 100644 --- a/arch/sh/include/asm/pci.h +++ b/arch/sh/include/asm/pci.h | |||
@@ -83,25 +83,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) | |||
83 | */ | 83 | */ |
84 | #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) | 84 | #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) |
85 | 85 | ||
86 | /* pci_unmap_{single,page} being a nop depends upon the | ||
87 | * configuration. | ||
88 | */ | ||
89 | #ifdef CONFIG_DMA_NONCOHERENT | ||
90 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME; | ||
91 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME; | ||
92 | #define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) | ||
93 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) | ||
94 | #define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) | ||
95 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) | ||
96 | #else | ||
97 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
98 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
99 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
100 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
101 | #define pci_unmap_len(PTR, LEN_NAME) (0) | ||
102 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
103 | #endif | ||
104 | |||
105 | #ifdef CONFIG_PCI | 86 | #ifdef CONFIG_PCI |
106 | /* | 87 | /* |
107 | * None of the SH PCI controllers support MWI, it is always treated as a | 88 | * None of the SH PCI controllers support MWI, it is always treated as a |
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index e11b14ea2c43..2168fde25611 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h | |||
@@ -123,8 +123,6 @@ extern void show_regs(struct pt_regs *); | |||
123 | struct task_struct; | 123 | struct task_struct; |
124 | 124 | ||
125 | #define arch_has_single_step() (1) | 125 | #define arch_has_single_step() (1) |
126 | extern void user_enable_single_step(struct task_struct *); | ||
127 | extern void user_disable_single_step(struct task_struct *); | ||
128 | 126 | ||
129 | struct perf_event; | 127 | struct perf_event; |
130 | struct perf_sample_data; | 128 | struct perf_sample_data; |
diff --git a/arch/sh/include/asm/syscalls.h b/arch/sh/include/asm/syscalls.h index c1e2b8deb837..507725af2e54 100644 --- a/arch/sh/include/asm/syscalls.h +++ b/arch/sh/include/asm/syscalls.h | |||
@@ -3,17 +3,12 @@ | |||
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | struct old_utsname; | ||
7 | |||
8 | asmlinkage int old_mmap(unsigned long addr, unsigned long len, | 6 | asmlinkage int old_mmap(unsigned long addr, unsigned long len, |
9 | unsigned long prot, unsigned long flags, | 7 | unsigned long prot, unsigned long flags, |
10 | int fd, unsigned long off); | 8 | int fd, unsigned long off); |
11 | asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | 9 | asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, |
12 | unsigned long prot, unsigned long flags, | 10 | unsigned long prot, unsigned long flags, |
13 | unsigned long fd, unsigned long pgoff); | 11 | unsigned long fd, unsigned long pgoff); |
14 | asmlinkage int sys_ipc(uint call, int first, int second, | ||
15 | int third, void __user *ptr, long fifth); | ||
16 | asmlinkage int sys_uname(struct old_utsname __user *name); | ||
17 | 12 | ||
18 | #ifdef CONFIG_SUPERH32 | 13 | #ifdef CONFIG_SUPERH32 |
19 | # include "syscalls_32.h" | 14 | # include "syscalls_32.h" |
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index 365744b05269..0e7f0fc8f086 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h | |||
@@ -358,6 +358,7 @@ | |||
358 | #define __ARCH_WANT_STAT64 | 358 | #define __ARCH_WANT_STAT64 |
359 | #define __ARCH_WANT_SYS_ALARM | 359 | #define __ARCH_WANT_SYS_ALARM |
360 | #define __ARCH_WANT_SYS_GETHOSTNAME | 360 | #define __ARCH_WANT_SYS_GETHOSTNAME |
361 | #define __ARCH_WANT_SYS_IPC | ||
361 | #define __ARCH_WANT_SYS_PAUSE | 362 | #define __ARCH_WANT_SYS_PAUSE |
362 | #define __ARCH_WANT_SYS_SGETMASK | 363 | #define __ARCH_WANT_SYS_SGETMASK |
363 | #define __ARCH_WANT_SYS_SIGNAL | 364 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -370,6 +371,7 @@ | |||
370 | #define __ARCH_WANT_SYS_LLSEEK | 371 | #define __ARCH_WANT_SYS_LLSEEK |
371 | #define __ARCH_WANT_SYS_NICE | 372 | #define __ARCH_WANT_SYS_NICE |
372 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 373 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
374 | #define __ARCH_WANT_SYS_OLD_UNAME | ||
373 | #define __ARCH_WANT_SYS_OLDUMOUNT | 375 | #define __ARCH_WANT_SYS_OLDUMOUNT |
374 | #define __ARCH_WANT_SYS_SIGPENDING | 376 | #define __ARCH_WANT_SYS_SIGPENDING |
375 | #define __ARCH_WANT_SYS_SIGPROCMASK | 377 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index 25de158aac3a..0580c33a1e04 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h | |||
@@ -398,6 +398,7 @@ | |||
398 | #define __ARCH_WANT_STAT64 | 398 | #define __ARCH_WANT_STAT64 |
399 | #define __ARCH_WANT_SYS_ALARM | 399 | #define __ARCH_WANT_SYS_ALARM |
400 | #define __ARCH_WANT_SYS_GETHOSTNAME | 400 | #define __ARCH_WANT_SYS_GETHOSTNAME |
401 | #define __ARCH_WANT_SYS_IPC | ||
401 | #define __ARCH_WANT_SYS_PAUSE | 402 | #define __ARCH_WANT_SYS_PAUSE |
402 | #define __ARCH_WANT_SYS_SGETMASK | 403 | #define __ARCH_WANT_SYS_SGETMASK |
403 | #define __ARCH_WANT_SYS_SIGNAL | 404 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -410,6 +411,7 @@ | |||
410 | #define __ARCH_WANT_SYS_LLSEEK | 411 | #define __ARCH_WANT_SYS_LLSEEK |
411 | #define __ARCH_WANT_SYS_NICE | 412 | #define __ARCH_WANT_SYS_NICE |
412 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 413 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
414 | #define __ARCH_WANT_SYS_OLD_UNAME | ||
413 | #define __ARCH_WANT_SYS_OLDUMOUNT | 415 | #define __ARCH_WANT_SYS_OLDUMOUNT |
414 | #define __ARCH_WANT_SYS_SIGPENDING | 416 | #define __ARCH_WANT_SYS_SIGPENDING |
415 | #define __ARCH_WANT_SYS_SIGPROCMASK | 417 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index fc065f9da6e5..14726eef1ce0 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c | |||
@@ -326,7 +326,7 @@ static struct attribute *sq_sysfs_attrs[] = { | |||
326 | NULL, | 326 | NULL, |
327 | }; | 327 | }; |
328 | 328 | ||
329 | static struct sysfs_ops sq_sysfs_ops = { | 329 | static const struct sysfs_ops sq_sysfs_ops = { |
330 | .show = sq_sysfs_show, | 330 | .show = sq_sysfs_show, |
331 | .store = sq_sysfs_store, | 331 | .store = sq_sysfs_store, |
332 | }; | 332 | }; |
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 71399cde03b5..81f58371613d 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c | |||
@@ -53,110 +53,6 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | |||
53 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); | 53 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); |
54 | } | 54 | } |
55 | 55 | ||
56 | /* | ||
57 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
58 | * | ||
59 | * This is really horribly ugly. | ||
60 | */ | ||
61 | asmlinkage int sys_ipc(uint call, int first, int second, | ||
62 | int third, void __user *ptr, long fifth) | ||
63 | { | ||
64 | int version, ret; | ||
65 | |||
66 | version = call >> 16; /* hack for backward compatibility */ | ||
67 | call &= 0xffff; | ||
68 | |||
69 | if (call <= SEMTIMEDOP) | ||
70 | switch (call) { | ||
71 | case SEMOP: | ||
72 | return sys_semtimedop(first, | ||
73 | (struct sembuf __user *)ptr, | ||
74 | second, NULL); | ||
75 | case SEMTIMEDOP: | ||
76 | return sys_semtimedop(first, | ||
77 | (struct sembuf __user *)ptr, second, | ||
78 | (const struct timespec __user *)fifth); | ||
79 | case SEMGET: | ||
80 | return sys_semget (first, second, third); | ||
81 | case SEMCTL: { | ||
82 | union semun fourth; | ||
83 | if (!ptr) | ||
84 | return -EINVAL; | ||
85 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
86 | return -EFAULT; | ||
87 | return sys_semctl (first, second, third, fourth); | ||
88 | } | ||
89 | default: | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | if (call <= MSGCTL) | ||
94 | switch (call) { | ||
95 | case MSGSND: | ||
96 | return sys_msgsnd (first, (struct msgbuf __user *) ptr, | ||
97 | second, third); | ||
98 | case MSGRCV: | ||
99 | switch (version) { | ||
100 | case 0: | ||
101 | { | ||
102 | struct ipc_kludge tmp; | ||
103 | |||
104 | if (!ptr) | ||
105 | return -EINVAL; | ||
106 | |||
107 | if (copy_from_user(&tmp, | ||
108 | (struct ipc_kludge __user *) ptr, | ||
109 | sizeof (tmp))) | ||
110 | return -EFAULT; | ||
111 | |||
112 | return sys_msgrcv (first, tmp.msgp, second, | ||
113 | tmp.msgtyp, third); | ||
114 | } | ||
115 | default: | ||
116 | return sys_msgrcv (first, | ||
117 | (struct msgbuf __user *) ptr, | ||
118 | second, fifth, third); | ||
119 | } | ||
120 | case MSGGET: | ||
121 | return sys_msgget ((key_t) first, second); | ||
122 | case MSGCTL: | ||
123 | return sys_msgctl (first, second, | ||
124 | (struct msqid_ds __user *) ptr); | ||
125 | default: | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | if (call <= SHMCTL) | ||
129 | switch (call) { | ||
130 | case SHMAT: | ||
131 | switch (version) { | ||
132 | default: { | ||
133 | ulong raddr; | ||
134 | ret = do_shmat (first, (char __user *) ptr, | ||
135 | second, &raddr); | ||
136 | if (ret) | ||
137 | return ret; | ||
138 | return put_user (raddr, (ulong __user *) third); | ||
139 | } | ||
140 | case 1: /* iBCS2 emulator entry point */ | ||
141 | if (!segment_eq(get_fs(), get_ds())) | ||
142 | return -EINVAL; | ||
143 | return do_shmat (first, (char __user *) ptr, | ||
144 | second, (ulong *) third); | ||
145 | } | ||
146 | case SHMDT: | ||
147 | return sys_shmdt ((char __user *)ptr); | ||
148 | case SHMGET: | ||
149 | return sys_shmget (first, second, third); | ||
150 | case SHMCTL: | ||
151 | return sys_shmctl (first, second, | ||
152 | (struct shmid_ds __user *) ptr); | ||
153 | default: | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | return -EINVAL; | ||
158 | } | ||
159 | |||
160 | /* sys_cacheflush -- flush (part of) the processor cache. */ | 56 | /* sys_cacheflush -- flush (part of) the processor cache. */ |
161 | asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op) | 57 | asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op) |
162 | { | 58 | { |
@@ -197,14 +93,3 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op) | |||
197 | up_read(¤t->mm->mmap_sem); | 93 | up_read(¤t->mm->mmap_sem); |
198 | return 0; | 94 | return 0; |
199 | } | 95 | } |
200 | |||
201 | asmlinkage int sys_uname(struct old_utsname __user *name) | ||
202 | { | ||
203 | int err; | ||
204 | if (!name) | ||
205 | return -EFAULT; | ||
206 | down_read(&uts_sem); | ||
207 | err = copy_to_user(name, utsname(), sizeof(*name)); | ||
208 | up_read(&uts_sem); | ||
209 | return err?-EFAULT:0; | ||
210 | } | ||
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 4097f6a10860..6db513674050 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -127,6 +127,9 @@ config ZONE_DMA | |||
127 | bool | 127 | bool |
128 | default y if SPARC32 | 128 | default y if SPARC32 |
129 | 129 | ||
130 | config NEED_DMA_MAP_STATE | ||
131 | def_bool y | ||
132 | |||
130 | config GENERIC_ISA_DMA | 133 | config GENERIC_ISA_DMA |
131 | bool | 134 | bool |
132 | default y if SPARC32 | 135 | default y if SPARC32 |
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 0e706257918f..5016f76ea98a 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h | |||
@@ -5,7 +5,8 @@ | |||
5 | */ | 5 | */ |
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | 7 | ||
8 | #define COMPAT_USER_HZ 100 | 8 | #define COMPAT_USER_HZ 100 |
9 | #define COMPAT_UTS_MACHINE "sparc\0\0" | ||
9 | 10 | ||
10 | typedef u32 compat_size_t; | 11 | typedef u32 compat_size_t; |
11 | typedef s32 compat_ssize_t; | 12 | typedef s32 compat_ssize_t; |
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h index 5a8c308e2b5c..4b4a0c0b0ccd 100644 --- a/arch/sparc/include/asm/dma-mapping.h +++ b/arch/sparc/include/asm/dma-mapping.h | |||
@@ -8,7 +8,6 @@ | |||
8 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) | 8 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) |
9 | 9 | ||
10 | extern int dma_supported(struct device *dev, u64 mask); | 10 | extern int dma_supported(struct device *dev, u64 mask); |
11 | extern int dma_set_mask(struct device *dev, u64 dma_mask); | ||
12 | 11 | ||
13 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | 12 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) |
14 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | 13 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) |
@@ -62,4 +61,17 @@ static inline int dma_get_cache_alignment(void) | |||
62 | return (1 << INTERNODE_CACHE_SHIFT); | 61 | return (1 << INTERNODE_CACHE_SHIFT); |
63 | } | 62 | } |
64 | 63 | ||
64 | static inline int dma_set_mask(struct device *dev, u64 mask) | ||
65 | { | ||
66 | #ifdef CONFIG_PCI | ||
67 | if (dev->bus == &pci_bus_type) { | ||
68 | if (!dev->dma_mask || !dma_supported(dev, mask)) | ||
69 | return -EINVAL; | ||
70 | *dev->dma_mask = mask; | ||
71 | return 0; | ||
72 | } | ||
73 | #endif | ||
74 | return -EINVAL; | ||
75 | } | ||
76 | |||
65 | #endif | 77 | #endif |
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h index e769f668a4b5..332ac9ab36bc 100644 --- a/arch/sparc/include/asm/pci_32.h +++ b/arch/sparc/include/asm/pci_32.h | |||
@@ -32,20 +32,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) | |||
32 | 32 | ||
33 | struct pci_dev; | 33 | struct pci_dev; |
34 | 34 | ||
35 | /* pci_unmap_{single,page} is not a nop, thus... */ | ||
36 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | ||
37 | dma_addr_t ADDR_NAME; | ||
38 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | ||
39 | __u32 LEN_NAME; | ||
40 | #define pci_unmap_addr(PTR, ADDR_NAME) \ | ||
41 | ((PTR)->ADDR_NAME) | ||
42 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
43 | (((PTR)->ADDR_NAME) = (VAL)) | ||
44 | #define pci_unmap_len(PTR, LEN_NAME) \ | ||
45 | ((PTR)->LEN_NAME) | ||
46 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
47 | (((PTR)->LEN_NAME) = (VAL)) | ||
48 | |||
49 | #ifdef CONFIG_PCI | 35 | #ifdef CONFIG_PCI |
50 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, | 36 | static inline void pci_dma_burst_advice(struct pci_dev *pdev, |
51 | enum pci_dma_burst_strategy *strat, | 37 | enum pci_dma_burst_strategy *strat, |
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h index b0576df6ec83..5312782f0b5e 100644 --- a/arch/sparc/include/asm/pci_64.h +++ b/arch/sparc/include/asm/pci_64.h | |||
@@ -32,20 +32,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) | |||
32 | */ | 32 | */ |
33 | #define PCI_DMA_BUS_IS_PHYS (0) | 33 | #define PCI_DMA_BUS_IS_PHYS (0) |
34 | 34 | ||
35 | /* pci_unmap_{single,page} is not a nop, thus... */ | ||
36 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | ||
37 | dma_addr_t ADDR_NAME; | ||
38 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | ||
39 | __u32 LEN_NAME; | ||
40 | #define pci_unmap_addr(PTR, ADDR_NAME) \ | ||
41 | ((PTR)->ADDR_NAME) | ||
42 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
43 | (((PTR)->ADDR_NAME) = (VAL)) | ||
44 | #define pci_unmap_len(PTR, LEN_NAME) \ | ||
45 | ((PTR)->LEN_NAME) | ||
46 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
47 | (((PTR)->LEN_NAME) = (VAL)) | ||
48 | |||
49 | /* PCI IOMMU mapping bypass support. */ | 35 | /* PCI IOMMU mapping bypass support. */ |
50 | 36 | ||
51 | /* PCI 64-bit addressing works for all slots on all controller | 37 | /* PCI 64-bit addressing works for all slots on all controller |
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index cb4b9bfd0d87..d0b3b01ac9d4 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h | |||
@@ -432,7 +432,9 @@ | |||
432 | #define __ARCH_WANT_SYS_SIGPENDING | 432 | #define __ARCH_WANT_SYS_SIGPENDING |
433 | #define __ARCH_WANT_SYS_SIGPROCMASK | 433 | #define __ARCH_WANT_SYS_SIGPROCMASK |
434 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 434 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
435 | #ifndef __32bit_syscall_numbers__ | 435 | #ifdef __32bit_syscall_numbers__ |
436 | #define __ARCH_WANT_SYS_IPC | ||
437 | #else | ||
436 | #define __ARCH_WANT_COMPAT_SYS_TIME | 438 | #define __ARCH_WANT_COMPAT_SYS_TIME |
437 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 439 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
438 | #endif | 440 | #endif |
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 5fad94950e76..8414549c1834 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c | |||
@@ -862,13 +862,3 @@ int dma_supported(struct device *dev, u64 device_mask) | |||
862 | return 0; | 862 | return 0; |
863 | } | 863 | } |
864 | EXPORT_SYMBOL(dma_supported); | 864 | EXPORT_SYMBOL(dma_supported); |
865 | |||
866 | int dma_set_mask(struct device *dev, u64 dma_mask) | ||
867 | { | ||
868 | #ifdef CONFIG_PCI | ||
869 | if (dev->bus == &pci_bus_type) | ||
870 | return pci_set_dma_mask(to_pci_dev(dev), dma_mask); | ||
871 | #endif | ||
872 | return -EINVAL; | ||
873 | } | ||
874 | EXPORT_SYMBOL(dma_set_mask); | ||
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 3c8c44f6a41c..84e5386714cd 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c | |||
@@ -676,17 +676,6 @@ int dma_supported(struct device *dev, u64 mask) | |||
676 | } | 676 | } |
677 | EXPORT_SYMBOL(dma_supported); | 677 | EXPORT_SYMBOL(dma_supported); |
678 | 678 | ||
679 | int dma_set_mask(struct device *dev, u64 dma_mask) | ||
680 | { | ||
681 | #ifdef CONFIG_PCI | ||
682 | if (dev->bus == &pci_bus_type) | ||
683 | return pci_set_dma_mask(to_pci_dev(dev), dma_mask); | ||
684 | #endif | ||
685 | return -EOPNOTSUPP; | ||
686 | } | ||
687 | EXPORT_SYMBOL(dma_set_mask); | ||
688 | |||
689 | |||
690 | #ifdef CONFIG_PROC_FS | 679 | #ifdef CONFIG_PROC_FS |
691 | 680 | ||
692 | static int sparc_io_proc_show(struct seq_file *m, void *v) | 681 | static int sparc_io_proc_show(struct seq_file *m, void *v) |
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 3a82e65d8db2..ee995b7dae7e 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c | |||
@@ -98,119 +98,6 @@ out: | |||
98 | return error; | 98 | return error; |
99 | } | 99 | } |
100 | 100 | ||
101 | /* | ||
102 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
103 | * | ||
104 | * This is really horribly ugly. | ||
105 | */ | ||
106 | |||
107 | asmlinkage int sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth) | ||
108 | { | ||
109 | int version, err; | ||
110 | |||
111 | version = call >> 16; /* hack for backward compatibility */ | ||
112 | call &= 0xffff; | ||
113 | |||
114 | if (call <= SEMCTL) | ||
115 | switch (call) { | ||
116 | case SEMOP: | ||
117 | err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); | ||
118 | goto out; | ||
119 | case SEMTIMEDOP: | ||
120 | err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, (const struct timespec __user *) fifth); | ||
121 | goto out; | ||
122 | case SEMGET: | ||
123 | err = sys_semget (first, second, third); | ||
124 | goto out; | ||
125 | case SEMCTL: { | ||
126 | union semun fourth; | ||
127 | err = -EINVAL; | ||
128 | if (!ptr) | ||
129 | goto out; | ||
130 | err = -EFAULT; | ||
131 | if (get_user(fourth.__pad, | ||
132 | (void __user * __user *)ptr)) | ||
133 | goto out; | ||
134 | err = sys_semctl (first, second, third, fourth); | ||
135 | goto out; | ||
136 | } | ||
137 | default: | ||
138 | err = -ENOSYS; | ||
139 | goto out; | ||
140 | } | ||
141 | if (call <= MSGCTL) | ||
142 | switch (call) { | ||
143 | case MSGSND: | ||
144 | err = sys_msgsnd (first, (struct msgbuf __user *) ptr, | ||
145 | second, third); | ||
146 | goto out; | ||
147 | case MSGRCV: | ||
148 | switch (version) { | ||
149 | case 0: { | ||
150 | struct ipc_kludge tmp; | ||
151 | err = -EINVAL; | ||
152 | if (!ptr) | ||
153 | goto out; | ||
154 | err = -EFAULT; | ||
155 | if (copy_from_user(&tmp, (struct ipc_kludge __user *) ptr, sizeof (tmp))) | ||
156 | goto out; | ||
157 | err = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); | ||
158 | goto out; | ||
159 | } | ||
160 | case 1: default: | ||
161 | err = sys_msgrcv (first, | ||
162 | (struct msgbuf __user *) ptr, | ||
163 | second, fifth, third); | ||
164 | goto out; | ||
165 | } | ||
166 | case MSGGET: | ||
167 | err = sys_msgget ((key_t) first, second); | ||
168 | goto out; | ||
169 | case MSGCTL: | ||
170 | err = sys_msgctl (first, second, (struct msqid_ds __user *) ptr); | ||
171 | goto out; | ||
172 | default: | ||
173 | err = -ENOSYS; | ||
174 | goto out; | ||
175 | } | ||
176 | if (call <= SHMCTL) | ||
177 | switch (call) { | ||
178 | case SHMAT: | ||
179 | switch (version) { | ||
180 | case 0: default: { | ||
181 | ulong raddr; | ||
182 | err = do_shmat (first, (char __user *) ptr, second, &raddr); | ||
183 | if (err) | ||
184 | goto out; | ||
185 | err = -EFAULT; | ||
186 | if (put_user (raddr, (ulong __user *) third)) | ||
187 | goto out; | ||
188 | err = 0; | ||
189 | goto out; | ||
190 | } | ||
191 | case 1: /* iBCS2 emulator entry point */ | ||
192 | err = -EINVAL; | ||
193 | goto out; | ||
194 | } | ||
195 | case SHMDT: | ||
196 | err = sys_shmdt ((char __user *)ptr); | ||
197 | goto out; | ||
198 | case SHMGET: | ||
199 | err = sys_shmget (first, second, third); | ||
200 | goto out; | ||
201 | case SHMCTL: | ||
202 | err = sys_shmctl (first, second, (struct shmid_ds __user *) ptr); | ||
203 | goto out; | ||
204 | default: | ||
205 | err = -ENOSYS; | ||
206 | goto out; | ||
207 | } | ||
208 | else | ||
209 | err = -ENOSYS; | ||
210 | out: | ||
211 | return err; | ||
212 | } | ||
213 | |||
214 | int sparc_mmap_check(unsigned long addr, unsigned long len) | 101 | int sparc_mmap_check(unsigned long addr, unsigned long len) |
215 | { | 102 | { |
216 | if (ARCH_SUN4C && | 103 | if (ARCH_SUN4C && |
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index cb1bef6f14b7..3d435c42e6db 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c | |||
@@ -426,7 +426,7 @@ out: | |||
426 | * This is really horribly ugly. | 426 | * This is really horribly ugly. |
427 | */ | 427 | */ |
428 | 428 | ||
429 | SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, | 429 | SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second, |
430 | unsigned long, third, void __user *, ptr, long, fifth) | 430 | unsigned long, third, void __user *, ptr, long, fifth) |
431 | { | 431 | { |
432 | long err; | 432 | long err; |
@@ -510,17 +510,6 @@ out: | |||
510 | return err; | 510 | return err; |
511 | } | 511 | } |
512 | 512 | ||
513 | SYSCALL_DEFINE1(sparc64_newuname, struct new_utsname __user *, name) | ||
514 | { | ||
515 | int ret = sys_newuname(name); | ||
516 | |||
517 | if (current->personality == PER_LINUX32 && !ret) { | ||
518 | ret = (copy_to_user(name->machine, "sparc\0\0", 8) | ||
519 | ? -EFAULT : 0); | ||
520 | } | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) | 513 | SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) |
525 | { | 514 | { |
526 | int ret; | 515 | int ret; |
diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h index 68312fe8da74..118759cd7342 100644 --- a/arch/sparc/kernel/systbls.h +++ b/arch/sparc/kernel/systbls.h | |||
@@ -6,15 +6,12 @@ | |||
6 | #include <asm/utrap.h> | 6 | #include <asm/utrap.h> |
7 | #include <asm/signal.h> | 7 | #include <asm/signal.h> |
8 | 8 | ||
9 | struct new_utsname; | ||
10 | |||
11 | extern asmlinkage unsigned long sys_getpagesize(void); | 9 | extern asmlinkage unsigned long sys_getpagesize(void); |
12 | extern asmlinkage long sparc_pipe(struct pt_regs *regs); | 10 | extern asmlinkage long sparc_pipe(struct pt_regs *regs); |
13 | extern asmlinkage long sys_ipc(unsigned int call, int first, | 11 | extern asmlinkage long sys_sparc_ipc(unsigned int call, int first, |
14 | unsigned long second, | 12 | unsigned long second, |
15 | unsigned long third, | 13 | unsigned long third, |
16 | void __user *ptr, long fifth); | 14 | void __user *ptr, long fifth); |
17 | extern asmlinkage long sparc64_newuname(struct new_utsname __user *name); | ||
18 | extern asmlinkage long sparc64_personality(unsigned long personality); | 15 | extern asmlinkage long sparc64_personality(unsigned long personality); |
19 | extern asmlinkage long sys64_munmap(unsigned long addr, size_t len); | 16 | extern asmlinkage long sys64_munmap(unsigned long addr, size_t len); |
20 | extern asmlinkage unsigned long sys64_mremap(unsigned long addr, | 17 | extern asmlinkage unsigned long sys64_mremap(unsigned long addr, |
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 17614251fb6d..9db058dd039e 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S | |||
@@ -55,7 +55,7 @@ sys_call_table32: | |||
55 | /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents | 55 | /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents |
56 | .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr | 56 | .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr |
57 | /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall | 57 | /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall |
58 | .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sys_sparc64_newuname | 58 | .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sys_newuname |
59 | /*190*/ .word sys32_init_module, sys_sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl | 59 | /*190*/ .word sys32_init_module, sys_sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl |
60 | .word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask | 60 | .word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask |
61 | /*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir | 61 | /*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir |
@@ -130,13 +130,13 @@ sys_call_table: | |||
130 | /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents | 130 | /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents |
131 | .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr | 131 | .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr |
132 | /*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall | 132 | /*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall |
133 | .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_sparc64_newuname | 133 | .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname |
134 | /*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl | 134 | /*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl |
135 | .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask | 135 | .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask |
136 | /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall | 136 | /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall |
137 | .word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64 | 137 | .word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64 |
138 | /*210*/ .word sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo | 138 | /*210*/ .word sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo |
139 | .word sys_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex | 139 | .word sys_sparc_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex |
140 | /*220*/ .word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid | 140 | /*220*/ .word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid |
141 | .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid | 141 | .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid |
142 | /*230*/ .word sys_select, sys_nis_syscall, sys_splice, sys_stime, sys_statfs64 | 142 | /*230*/ .word sys_select, sys_nis_syscall, sys_splice, sys_stime, sys_statfs64 |
diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h index 378de4bbf49f..b948c14a7867 100644 --- a/arch/um/include/asm/dma-mapping.h +++ b/arch/um/include/asm/dma-mapping.h | |||
@@ -104,14 +104,6 @@ dma_get_cache_alignment(void) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | static inline void | 106 | static inline void |
107 | dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, | ||
108 | unsigned long offset, size_t size, | ||
109 | enum dma_data_direction direction) | ||
110 | { | ||
111 | BUG(); | ||
112 | } | ||
113 | |||
114 | static inline void | ||
115 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, | 107 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
116 | enum dma_data_direction direction) | 108 | enum dma_data_direction direction) |
117 | { | 109 | { |
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h index 6c8899013c92..2cd899f75a3c 100644 --- a/arch/um/include/asm/ptrace-generic.h +++ b/arch/um/include/asm/ptrace-generic.h | |||
@@ -16,6 +16,8 @@ struct pt_regs { | |||
16 | struct uml_pt_regs regs; | 16 | struct uml_pt_regs regs; |
17 | }; | 17 | }; |
18 | 18 | ||
19 | #define arch_has_single_step() (1) | ||
20 | |||
19 | #define EMPTY_REGS { .regs = EMPTY_UML_PT_REGS } | 21 | #define EMPTY_REGS { .regs = EMPTY_UML_PT_REGS } |
20 | 22 | ||
21 | #define PT_REGS_IP(r) UPT_IP(&(r)->regs) | 23 | #define PT_REGS_IP(r) UPT_IP(&(r)->regs) |
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 8e3d69e4fcb5..484509948ee9 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
@@ -12,16 +12,25 @@ | |||
12 | #endif | 12 | #endif |
13 | #include "skas_ptrace.h" | 13 | #include "skas_ptrace.h" |
14 | 14 | ||
15 | static inline void set_singlestepping(struct task_struct *child, int on) | 15 | |
16 | |||
17 | void user_enable_single_step(struct task_struct *child) | ||
16 | { | 18 | { |
17 | if (on) | 19 | child->ptrace |= PT_DTRACE; |
18 | child->ptrace |= PT_DTRACE; | ||
19 | else | ||
20 | child->ptrace &= ~PT_DTRACE; | ||
21 | child->thread.singlestep_syscall = 0; | 20 | child->thread.singlestep_syscall = 0; |
22 | 21 | ||
23 | #ifdef SUBARCH_SET_SINGLESTEPPING | 22 | #ifdef SUBARCH_SET_SINGLESTEPPING |
24 | SUBARCH_SET_SINGLESTEPPING(child, on); | 23 | SUBARCH_SET_SINGLESTEPPING(child, 1); |
24 | #endif | ||
25 | } | ||
26 | |||
27 | void user_disable_single_step(struct task_struct *child) | ||
28 | { | ||
29 | child->ptrace &= ~PT_DTRACE; | ||
30 | child->thread.singlestep_syscall = 0; | ||
31 | |||
32 | #ifdef SUBARCH_SET_SINGLESTEPPING | ||
33 | SUBARCH_SET_SINGLESTEPPING(child, 0); | ||
25 | #endif | 34 | #endif |
26 | } | 35 | } |
27 | 36 | ||
@@ -30,7 +39,7 @@ static inline void set_singlestepping(struct task_struct *child, int on) | |||
30 | */ | 39 | */ |
31 | void ptrace_disable(struct task_struct *child) | 40 | void ptrace_disable(struct task_struct *child) |
32 | { | 41 | { |
33 | set_singlestepping(child,0); | 42 | user_disable_single_step(child); |
34 | } | 43 | } |
35 | 44 | ||
36 | extern int peek_user(struct task_struct * child, long addr, long data); | 45 | extern int peek_user(struct task_struct * child, long addr, long data); |
@@ -69,53 +78,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
69 | ret = -EIO; | 78 | ret = -EIO; |
70 | break; | 79 | break; |
71 | 80 | ||
72 | /* continue and stop at next (return from) syscall */ | ||
73 | case PTRACE_SYSCALL: | ||
74 | /* restart after signal. */ | ||
75 | case PTRACE_CONT: { | ||
76 | ret = -EIO; | ||
77 | if (!valid_signal(data)) | ||
78 | break; | ||
79 | |||
80 | set_singlestepping(child, 0); | ||
81 | if (request == PTRACE_SYSCALL) | ||
82 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
83 | else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
84 | child->exit_code = data; | ||
85 | wake_up_process(child); | ||
86 | ret = 0; | ||
87 | break; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * make the child exit. Best I can do is send it a sigkill. | ||
92 | * perhaps it should be put in the status that it wants to | ||
93 | * exit. | ||
94 | */ | ||
95 | case PTRACE_KILL: { | ||
96 | ret = 0; | ||
97 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
98 | break; | ||
99 | |||
100 | set_singlestepping(child, 0); | ||
101 | child->exit_code = SIGKILL; | ||
102 | wake_up_process(child); | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
107 | ret = -EIO; | ||
108 | if (!valid_signal(data)) | ||
109 | break; | ||
110 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
111 | set_singlestepping(child, 1); | ||
112 | child->exit_code = data; | ||
113 | /* give it a chance to run. */ | ||
114 | wake_up_process(child); | ||
115 | ret = 0; | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | #ifdef PTRACE_GETREGS | 81 | #ifdef PTRACE_GETREGS |
120 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 82 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ |
121 | if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { | 83 | if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { |
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index cccab850c27e..4393173923f5 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -51,51 +51,6 @@ long old_mmap(unsigned long addr, unsigned long len, | |||
51 | return err; | 51 | return err; |
52 | } | 52 | } |
53 | 53 | ||
54 | long sys_uname(struct old_utsname __user * name) | ||
55 | { | ||
56 | long err; | ||
57 | if (!name) | ||
58 | return -EFAULT; | ||
59 | down_read(&uts_sem); | ||
60 | err = copy_to_user(name, utsname(), sizeof (*name)); | ||
61 | up_read(&uts_sem); | ||
62 | return err?-EFAULT:0; | ||
63 | } | ||
64 | |||
65 | long sys_olduname(struct oldold_utsname __user * name) | ||
66 | { | ||
67 | long error; | ||
68 | |||
69 | if (!name) | ||
70 | return -EFAULT; | ||
71 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) | ||
72 | return -EFAULT; | ||
73 | |||
74 | down_read(&uts_sem); | ||
75 | |||
76 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
77 | __OLD_UTS_LEN); | ||
78 | error |= __put_user(0, name->sysname + __OLD_UTS_LEN); | ||
79 | error |= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
80 | __OLD_UTS_LEN); | ||
81 | error |= __put_user(0, name->nodename + __OLD_UTS_LEN); | ||
82 | error |= __copy_to_user(&name->release, &utsname()->release, | ||
83 | __OLD_UTS_LEN); | ||
84 | error |= __put_user(0, name->release + __OLD_UTS_LEN); | ||
85 | error |= __copy_to_user(&name->version, &utsname()->version, | ||
86 | __OLD_UTS_LEN); | ||
87 | error |= __put_user(0, name->version + __OLD_UTS_LEN); | ||
88 | error |= __copy_to_user(&name->machine, &utsname()->machine, | ||
89 | __OLD_UTS_LEN); | ||
90 | error |= __put_user(0, name->machine + __OLD_UTS_LEN); | ||
91 | |||
92 | up_read(&uts_sem); | ||
93 | |||
94 | error = error ? -EFAULT : 0; | ||
95 | |||
96 | return error; | ||
97 | } | ||
98 | |||
99 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]) | 54 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]) |
100 | { | 55 | { |
101 | mm_segment_t fs; | 56 | mm_segment_t fs; |
diff --git a/arch/um/sys-i386/shared/sysdep/syscalls.h b/arch/um/sys-i386/shared/sysdep/syscalls.h index e7787679e317..05cb796aecb5 100644 --- a/arch/um/sys-i386/shared/sysdep/syscalls.h +++ b/arch/um/sys-i386/shared/sysdep/syscalls.h | |||
@@ -13,8 +13,6 @@ typedef long syscall_handler_t(struct pt_regs); | |||
13 | */ | 13 | */ |
14 | extern syscall_handler_t sys_rt_sigaction; | 14 | extern syscall_handler_t sys_rt_sigaction; |
15 | 15 | ||
16 | extern syscall_handler_t old_mmap_i386; | ||
17 | |||
18 | extern syscall_handler_t *sys_call_table[]; | 16 | extern syscall_handler_t *sys_call_table[]; |
19 | 17 | ||
20 | #define EXECUTE_SYSCALL(syscall, regs) \ | 18 | #define EXECUTE_SYSCALL(syscall, regs) \ |
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S index c6260dd6ebb9..de274071455d 100644 --- a/arch/um/sys-i386/sys_call_table.S +++ b/arch/um/sys-i386/sys_call_table.S | |||
@@ -7,7 +7,7 @@ | |||
7 | #define sys_vm86old sys_ni_syscall | 7 | #define sys_vm86old sys_ni_syscall |
8 | #define sys_vm86 sys_ni_syscall | 8 | #define sys_vm86 sys_ni_syscall |
9 | 9 | ||
10 | #define old_mmap old_mmap_i386 | 10 | #define old_mmap sys_old_mmap |
11 | 11 | ||
12 | #define ptregs_fork sys_fork | 12 | #define ptregs_fork sys_fork |
13 | #define ptregs_execve sys_execve | 13 | #define ptregs_execve sys_execve |
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c index 857ca0b3bdef..70ca357393b8 100644 --- a/arch/um/sys-i386/syscalls.c +++ b/arch/um/sys-i386/syscalls.c | |||
@@ -12,57 +12,6 @@ | |||
12 | #include "asm/unistd.h" | 12 | #include "asm/unistd.h" |
13 | 13 | ||
14 | /* | 14 | /* |
15 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
16 | * calls. Linux/i386 didn't use to be able to handle more than | ||
17 | * 4 system call parameters, so these system calls used a memory | ||
18 | * block for parameter passing.. | ||
19 | */ | ||
20 | |||
21 | struct mmap_arg_struct { | ||
22 | unsigned long addr; | ||
23 | unsigned long len; | ||
24 | unsigned long prot; | ||
25 | unsigned long flags; | ||
26 | unsigned long fd; | ||
27 | unsigned long offset; | ||
28 | }; | ||
29 | |||
30 | extern int old_mmap(unsigned long addr, unsigned long len, | ||
31 | unsigned long prot, unsigned long flags, | ||
32 | unsigned long fd, unsigned long offset); | ||
33 | |||
34 | long old_mmap_i386(struct mmap_arg_struct __user *arg) | ||
35 | { | ||
36 | struct mmap_arg_struct a; | ||
37 | int err = -EFAULT; | ||
38 | |||
39 | if (copy_from_user(&a, arg, sizeof(a))) | ||
40 | goto out; | ||
41 | |||
42 | err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); | ||
43 | out: | ||
44 | return err; | ||
45 | } | ||
46 | |||
47 | struct sel_arg_struct { | ||
48 | unsigned long n; | ||
49 | fd_set __user *inp; | ||
50 | fd_set __user *outp; | ||
51 | fd_set __user *exp; | ||
52 | struct timeval __user *tvp; | ||
53 | }; | ||
54 | |||
55 | long old_select(struct sel_arg_struct __user *arg) | ||
56 | { | ||
57 | struct sel_arg_struct a; | ||
58 | |||
59 | if (copy_from_user(&a, arg, sizeof(a))) | ||
60 | return -EFAULT; | ||
61 | /* sys_select() does the appropriate kernel locking */ | ||
62 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * The prototype on i386 is: | 15 | * The prototype on i386 is: |
67 | * | 16 | * |
68 | * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) | 17 | * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) |
@@ -85,92 +34,6 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, | |||
85 | return ret; | 34 | return ret; |
86 | } | 35 | } |
87 | 36 | ||
88 | /* | ||
89 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
90 | * | ||
91 | * This is really horribly ugly. | ||
92 | */ | ||
93 | long sys_ipc (uint call, int first, int second, | ||
94 | int third, void __user *ptr, long fifth) | ||
95 | { | ||
96 | int version, ret; | ||
97 | |||
98 | version = call >> 16; /* hack for backward compatibility */ | ||
99 | call &= 0xffff; | ||
100 | |||
101 | switch (call) { | ||
102 | case SEMOP: | ||
103 | return sys_semtimedop(first, (struct sembuf __user *) ptr, | ||
104 | second, NULL); | ||
105 | case SEMTIMEDOP: | ||
106 | return sys_semtimedop(first, (struct sembuf __user *) ptr, | ||
107 | second, | ||
108 | (const struct timespec __user *) fifth); | ||
109 | case SEMGET: | ||
110 | return sys_semget (first, second, third); | ||
111 | case SEMCTL: { | ||
112 | union semun fourth; | ||
113 | if (!ptr) | ||
114 | return -EINVAL; | ||
115 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
116 | return -EFAULT; | ||
117 | return sys_semctl (first, second, third, fourth); | ||
118 | } | ||
119 | |||
120 | case MSGSND: | ||
121 | return sys_msgsnd (first, (struct msgbuf *) ptr, | ||
122 | second, third); | ||
123 | case MSGRCV: | ||
124 | switch (version) { | ||
125 | case 0: { | ||
126 | struct ipc_kludge tmp; | ||
127 | if (!ptr) | ||
128 | return -EINVAL; | ||
129 | |||
130 | if (copy_from_user(&tmp, | ||
131 | (struct ipc_kludge *) ptr, | ||
132 | sizeof (tmp))) | ||
133 | return -EFAULT; | ||
134 | return sys_msgrcv (first, tmp.msgp, second, | ||
135 | tmp.msgtyp, third); | ||
136 | } | ||
137 | default: | ||
138 | panic("msgrcv with version != 0"); | ||
139 | return sys_msgrcv (first, | ||
140 | (struct msgbuf *) ptr, | ||
141 | second, fifth, third); | ||
142 | } | ||
143 | case MSGGET: | ||
144 | return sys_msgget ((key_t) first, second); | ||
145 | case MSGCTL: | ||
146 | return sys_msgctl (first, second, (struct msqid_ds *) ptr); | ||
147 | |||
148 | case SHMAT: | ||
149 | switch (version) { | ||
150 | default: { | ||
151 | ulong raddr; | ||
152 | ret = do_shmat (first, (char *) ptr, second, &raddr); | ||
153 | if (ret) | ||
154 | return ret; | ||
155 | return put_user (raddr, (ulong *) third); | ||
156 | } | ||
157 | case 1: /* iBCS2 emulator entry point */ | ||
158 | if (!segment_eq(get_fs(), get_ds())) | ||
159 | return -EINVAL; | ||
160 | return do_shmat (first, (char *) ptr, second, (ulong *) third); | ||
161 | } | ||
162 | case SHMDT: | ||
163 | return sys_shmdt ((char *)ptr); | ||
164 | case SHMGET: | ||
165 | return sys_shmget (first, second, third); | ||
166 | case SHMCTL: | ||
167 | return sys_shmctl (first, second, | ||
168 | (struct shmid_ds *) ptr); | ||
169 | default: | ||
170 | return -ENOSYS; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 37 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
175 | struct old_sigaction __user *oact) | 38 | struct old_sigaction __user *oact) |
176 | { | 39 | { |
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c index dd21d69715e6..47d469e7e7ce 100644 --- a/arch/um/sys-x86_64/syscall_table.c +++ b/arch/um/sys-x86_64/syscall_table.c | |||
@@ -26,11 +26,6 @@ | |||
26 | 26 | ||
27 | /* On UML we call it this way ("old" means it's not mmap2) */ | 27 | /* On UML we call it this way ("old" means it's not mmap2) */ |
28 | #define sys_mmap old_mmap | 28 | #define sys_mmap old_mmap |
29 | /* | ||
30 | * On x86-64 sys_uname is actually sys_newuname plus a compatibility trick. | ||
31 | * See arch/x86_64/kernel/sys_x86_64.c | ||
32 | */ | ||
33 | #define sys_uname sys_uname64 | ||
34 | 29 | ||
35 | #define stub_clone sys_clone | 30 | #define stub_clone sys_clone |
36 | #define stub_fork sys_fork | 31 | #define stub_fork sys_fork |
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index f1199fd34d38..f3d82bb6e15a 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c | |||
@@ -12,20 +12,6 @@ | |||
12 | #include "asm/uaccess.h" | 12 | #include "asm/uaccess.h" |
13 | #include "os.h" | 13 | #include "os.h" |
14 | 14 | ||
15 | asmlinkage long sys_uname64(struct new_utsname __user * name) | ||
16 | { | ||
17 | int err; | ||
18 | |||
19 | down_read(&uts_sem); | ||
20 | err = copy_to_user(name, utsname(), sizeof (*name)); | ||
21 | up_read(&uts_sem); | ||
22 | |||
23 | if (personality(current->personality) == PER_LINUX32) | ||
24 | err |= copy_to_user(&name->machine, "i686", 5); | ||
25 | |||
26 | return err ? -EFAULT : 0; | ||
27 | } | ||
28 | |||
29 | long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) | 15 | long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) |
30 | { | 16 | { |
31 | unsigned long *ptr = addr, tmp; | 17 | unsigned long *ptr = addr, tmp; |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e98440371525..93936de67796 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -102,6 +102,9 @@ config ZONE_DMA | |||
102 | config SBUS | 102 | config SBUS |
103 | bool | 103 | bool |
104 | 104 | ||
105 | config NEED_DMA_MAP_STATE | ||
106 | def_bool (X86_64 || DMAR || DMA_API_DEBUG) | ||
107 | |||
105 | config GENERIC_ISA_DMA | 108 | config GENERIC_ISA_DMA |
106 | def_bool y | 109 | def_bool y |
107 | 110 | ||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 53147ad85b96..59b4556a5b92 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -563,7 +563,7 @@ ia32_sys_call_table: | |||
563 | .quad quiet_ni_syscall /* old mpx syscall holder */ | 563 | .quad quiet_ni_syscall /* old mpx syscall holder */ |
564 | .quad sys_setpgid | 564 | .quad sys_setpgid |
565 | .quad quiet_ni_syscall /* old ulimit syscall holder */ | 565 | .quad quiet_ni_syscall /* old ulimit syscall holder */ |
566 | .quad sys32_olduname | 566 | .quad sys_olduname |
567 | .quad sys_umask /* 60 */ | 567 | .quad sys_umask /* 60 */ |
568 | .quad sys_chroot | 568 | .quad sys_chroot |
569 | .quad compat_sys_ustat | 569 | .quad compat_sys_ustat |
@@ -586,7 +586,7 @@ ia32_sys_call_table: | |||
586 | .quad compat_sys_settimeofday | 586 | .quad compat_sys_settimeofday |
587 | .quad sys_getgroups16 /* 80 */ | 587 | .quad sys_getgroups16 /* 80 */ |
588 | .quad sys_setgroups16 | 588 | .quad sys_setgroups16 |
589 | .quad sys32_old_select | 589 | .quad compat_sys_old_select |
590 | .quad sys_symlink | 590 | .quad sys_symlink |
591 | .quad sys_lstat | 591 | .quad sys_lstat |
592 | .quad sys_readlink /* 85 */ | 592 | .quad sys_readlink /* 85 */ |
@@ -613,7 +613,7 @@ ia32_sys_call_table: | |||
613 | .quad compat_sys_newstat | 613 | .quad compat_sys_newstat |
614 | .quad compat_sys_newlstat | 614 | .quad compat_sys_newlstat |
615 | .quad compat_sys_newfstat | 615 | .quad compat_sys_newfstat |
616 | .quad sys32_uname | 616 | .quad sys_uname |
617 | .quad stub32_iopl /* 110 */ | 617 | .quad stub32_iopl /* 110 */ |
618 | .quad sys_vhangup | 618 | .quad sys_vhangup |
619 | .quad quiet_ni_syscall /* old "idle" system call */ | 619 | .quad quiet_ni_syscall /* old "idle" system call */ |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 422572c77923..74c35431b7d8 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -143,7 +143,7 @@ asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename, | |||
143 | * block for parameter passing.. | 143 | * block for parameter passing.. |
144 | */ | 144 | */ |
145 | 145 | ||
146 | struct mmap_arg_struct { | 146 | struct mmap_arg_struct32 { |
147 | unsigned int addr; | 147 | unsigned int addr; |
148 | unsigned int len; | 148 | unsigned int len; |
149 | unsigned int prot; | 149 | unsigned int prot; |
@@ -152,9 +152,9 @@ struct mmap_arg_struct { | |||
152 | unsigned int offset; | 152 | unsigned int offset; |
153 | }; | 153 | }; |
154 | 154 | ||
155 | asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg) | 155 | asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *arg) |
156 | { | 156 | { |
157 | struct mmap_arg_struct a; | 157 | struct mmap_arg_struct32 a; |
158 | 158 | ||
159 | if (copy_from_user(&a, arg, sizeof(a))) | 159 | if (copy_from_user(&a, arg, sizeof(a))) |
160 | return -EFAULT; | 160 | return -EFAULT; |
@@ -332,24 +332,6 @@ asmlinkage long sys32_alarm(unsigned int seconds) | |||
332 | return alarm_setitimer(seconds); | 332 | return alarm_setitimer(seconds); |
333 | } | 333 | } |
334 | 334 | ||
335 | struct sel_arg_struct { | ||
336 | unsigned int n; | ||
337 | unsigned int inp; | ||
338 | unsigned int outp; | ||
339 | unsigned int exp; | ||
340 | unsigned int tvp; | ||
341 | }; | ||
342 | |||
343 | asmlinkage long sys32_old_select(struct sel_arg_struct __user *arg) | ||
344 | { | ||
345 | struct sel_arg_struct a; | ||
346 | |||
347 | if (copy_from_user(&a, arg, sizeof(a))) | ||
348 | return -EFAULT; | ||
349 | return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp), | ||
350 | compat_ptr(a.exp), compat_ptr(a.tvp)); | ||
351 | } | ||
352 | |||
353 | asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, | 335 | asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, |
354 | int options) | 336 | int options) |
355 | { | 337 | { |
@@ -466,58 +448,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, | |||
466 | return ret; | 448 | return ret; |
467 | } | 449 | } |
468 | 450 | ||
469 | asmlinkage long sys32_olduname(struct oldold_utsname __user *name) | ||
470 | { | ||
471 | char *arch = "x86_64"; | ||
472 | int err; | ||
473 | |||
474 | if (!name) | ||
475 | return -EFAULT; | ||
476 | if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) | ||
477 | return -EFAULT; | ||
478 | |||
479 | down_read(&uts_sem); | ||
480 | |||
481 | err = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
482 | __OLD_UTS_LEN); | ||
483 | err |= __put_user(0, name->sysname+__OLD_UTS_LEN); | ||
484 | err |= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
485 | __OLD_UTS_LEN); | ||
486 | err |= __put_user(0, name->nodename+__OLD_UTS_LEN); | ||
487 | err |= __copy_to_user(&name->release, &utsname()->release, | ||
488 | __OLD_UTS_LEN); | ||
489 | err |= __put_user(0, name->release+__OLD_UTS_LEN); | ||
490 | err |= __copy_to_user(&name->version, &utsname()->version, | ||
491 | __OLD_UTS_LEN); | ||
492 | err |= __put_user(0, name->version+__OLD_UTS_LEN); | ||
493 | |||
494 | if (personality(current->personality) == PER_LINUX32) | ||
495 | arch = "i686"; | ||
496 | |||
497 | err |= __copy_to_user(&name->machine, arch, strlen(arch) + 1); | ||
498 | |||
499 | up_read(&uts_sem); | ||
500 | |||
501 | err = err ? -EFAULT : 0; | ||
502 | |||
503 | return err; | ||
504 | } | ||
505 | |||
506 | long sys32_uname(struct old_utsname __user *name) | ||
507 | { | ||
508 | int err; | ||
509 | |||
510 | if (!name) | ||
511 | return -EFAULT; | ||
512 | down_read(&uts_sem); | ||
513 | err = copy_to_user(name, utsname(), sizeof(*name)); | ||
514 | up_read(&uts_sem); | ||
515 | if (personality(current->personality) == PER_LINUX32) | ||
516 | err |= copy_to_user(&name->machine, "i686", 5); | ||
517 | |||
518 | return err ? -EFAULT : 0; | ||
519 | } | ||
520 | |||
521 | asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, | 451 | asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, |
522 | compat_uptr_t __user *envp, struct pt_regs *regs) | 452 | compat_uptr_t __user *envp, struct pt_regs *regs) |
523 | { | 453 | { |
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 9a9c7bdc923d..306160e58b48 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h | |||
@@ -8,7 +8,8 @@ | |||
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <asm/user32.h> | 9 | #include <asm/user32.h> |
10 | 10 | ||
11 | #define COMPAT_USER_HZ 100 | 11 | #define COMPAT_USER_HZ 100 |
12 | #define COMPAT_UTS_MACHINE "i686\0\0" | ||
12 | 13 | ||
13 | typedef u32 compat_size_t; | 14 | typedef u32 compat_size_t; |
14 | typedef s32 compat_ssize_t; | 15 | typedef s32 compat_ssize_t; |
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 3e002ca5a287..404a880ea325 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -97,34 +97,6 @@ extern void pci_iommu_alloc(void); | |||
97 | 97 | ||
98 | #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) | 98 | #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) |
99 | 99 | ||
100 | #if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG) | ||
101 | |||
102 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ | ||
103 | dma_addr_t ADDR_NAME; | ||
104 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ | ||
105 | __u32 LEN_NAME; | ||
106 | #define pci_unmap_addr(PTR, ADDR_NAME) \ | ||
107 | ((PTR)->ADDR_NAME) | ||
108 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
109 | (((PTR)->ADDR_NAME) = (VAL)) | ||
110 | #define pci_unmap_len(PTR, LEN_NAME) \ | ||
111 | ((PTR)->LEN_NAME) | ||
112 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
113 | (((PTR)->LEN_NAME) = (VAL)) | ||
114 | |||
115 | #else | ||
116 | |||
117 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME[0]; | ||
118 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) unsigned LEN_NAME[0]; | ||
119 | #define pci_unmap_addr(PTR, ADDR_NAME) sizeof((PTR)->ADDR_NAME) | ||
120 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ | ||
121 | do { break; } while (pci_unmap_addr(PTR, ADDR_NAME)) | ||
122 | #define pci_unmap_len(PTR, LEN_NAME) sizeof((PTR)->LEN_NAME) | ||
123 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ | ||
124 | do { break; } while (pci_unmap_len(PTR, LEN_NAME)) | ||
125 | |||
126 | #endif | ||
127 | |||
128 | #endif /* __KERNEL__ */ | 100 | #endif /* __KERNEL__ */ |
129 | 101 | ||
130 | #ifdef CONFIG_X86_64 | 102 | #ifdef CONFIG_X86_64 |
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 20102808b191..69a686a7dff0 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h | |||
@@ -274,14 +274,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, | |||
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
276 | 276 | ||
277 | /* | ||
278 | * These are defined as per linux/ptrace.h, which see. | ||
279 | */ | ||
280 | #define arch_has_single_step() (1) | 277 | #define arch_has_single_step() (1) |
281 | extern void user_enable_single_step(struct task_struct *); | ||
282 | extern void user_disable_single_step(struct task_struct *); | ||
283 | |||
284 | extern void user_enable_block_step(struct task_struct *); | ||
285 | #ifdef CONFIG_X86_DEBUGCTLMSR | 278 | #ifdef CONFIG_X86_DEBUGCTLMSR |
286 | #define arch_has_block_step() (1) | 279 | #define arch_has_block_step() (1) |
287 | #else | 280 | #else |
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index d5f69045c100..3ad421784ae7 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h | |||
@@ -26,8 +26,8 @@ asmlinkage long sys32_lstat64(char __user *, struct stat64 __user *); | |||
26 | asmlinkage long sys32_fstat64(unsigned int, struct stat64 __user *); | 26 | asmlinkage long sys32_fstat64(unsigned int, struct stat64 __user *); |
27 | asmlinkage long sys32_fstatat(unsigned int, char __user *, | 27 | asmlinkage long sys32_fstatat(unsigned int, char __user *, |
28 | struct stat64 __user *, int); | 28 | struct stat64 __user *, int); |
29 | struct mmap_arg_struct; | 29 | struct mmap_arg_struct32; |
30 | asmlinkage long sys32_mmap(struct mmap_arg_struct __user *); | 30 | asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *); |
31 | asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long); | 31 | asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long); |
32 | 32 | ||
33 | struct sigaction32; | 33 | struct sigaction32; |
@@ -40,8 +40,6 @@ asmlinkage long sys32_rt_sigprocmask(int, compat_sigset_t __user *, | |||
40 | compat_sigset_t __user *, unsigned int); | 40 | compat_sigset_t __user *, unsigned int); |
41 | asmlinkage long sys32_alarm(unsigned int); | 41 | asmlinkage long sys32_alarm(unsigned int); |
42 | 42 | ||
43 | struct sel_arg_struct; | ||
44 | asmlinkage long sys32_old_select(struct sel_arg_struct __user *); | ||
45 | asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int); | 43 | asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int); |
46 | asmlinkage long sys32_sysfs(int, u32, u32); | 44 | asmlinkage long sys32_sysfs(int, u32, u32); |
47 | 45 | ||
@@ -56,11 +54,6 @@ asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32); | |||
56 | asmlinkage long sys32_personality(unsigned long); | 54 | asmlinkage long sys32_personality(unsigned long); |
57 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); | 55 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); |
58 | 56 | ||
59 | struct oldold_utsname; | ||
60 | struct old_utsname; | ||
61 | asmlinkage long sys32_olduname(struct oldold_utsname __user *); | ||
62 | long sys32_uname(struct old_utsname __user *); | ||
63 | |||
64 | asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *, | 57 | asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *, |
65 | compat_uptr_t __user *, struct pt_regs *); | 58 | compat_uptr_t __user *, struct pt_regs *); |
66 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); | 59 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); |
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index 8868b9420b0e..5c044b43e9a7 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h | |||
@@ -50,18 +50,6 @@ asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, | |||
50 | struct old_sigaction __user *); | 50 | struct old_sigaction __user *); |
51 | unsigned long sys_sigreturn(struct pt_regs *); | 51 | unsigned long sys_sigreturn(struct pt_regs *); |
52 | 52 | ||
53 | /* kernel/sys_i386_32.c */ | ||
54 | struct mmap_arg_struct; | ||
55 | struct sel_arg_struct; | ||
56 | struct oldold_utsname; | ||
57 | struct old_utsname; | ||
58 | |||
59 | asmlinkage int old_mmap(struct mmap_arg_struct __user *); | ||
60 | asmlinkage int old_select(struct sel_arg_struct __user *); | ||
61 | asmlinkage int sys_ipc(uint, int, int, int, void __user *, long); | ||
62 | asmlinkage int sys_uname(struct old_utsname __user *); | ||
63 | asmlinkage int sys_olduname(struct oldold_utsname __user *); | ||
64 | |||
65 | /* kernel/vm86_32.c */ | 53 | /* kernel/vm86_32.c */ |
66 | int sys_vm86old(struct vm86_struct __user *, struct pt_regs *); | 54 | int sys_vm86old(struct vm86_struct __user *, struct pt_regs *); |
67 | int sys_vm86(unsigned long, unsigned long, struct pt_regs *); | 55 | int sys_vm86(unsigned long, unsigned long, struct pt_regs *); |
@@ -73,11 +61,8 @@ int sys_vm86(unsigned long, unsigned long, struct pt_regs *); | |||
73 | long sys_arch_prctl(int, unsigned long); | 61 | long sys_arch_prctl(int, unsigned long); |
74 | 62 | ||
75 | /* kernel/sys_x86_64.c */ | 63 | /* kernel/sys_x86_64.c */ |
76 | struct new_utsname; | ||
77 | |||
78 | asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long, | 64 | asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long, |
79 | unsigned long, unsigned long, unsigned long); | 65 | unsigned long, unsigned long, unsigned long); |
80 | asmlinkage long sys_uname(struct new_utsname __user *); | ||
81 | 66 | ||
82 | #endif /* CONFIG_X86_32 */ | 67 | #endif /* CONFIG_X86_32 */ |
83 | #endif /* _ASM_X86_SYSCALLS_H */ | 68 | #endif /* _ASM_X86_SYSCALLS_H */ |
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h index 3baf379fa840..beb9b5f8f8a4 100644 --- a/arch/x86/include/asm/unistd_32.h +++ b/arch/x86/include/asm/unistd_32.h | |||
@@ -354,6 +354,7 @@ | |||
354 | #define __ARCH_WANT_STAT64 | 354 | #define __ARCH_WANT_STAT64 |
355 | #define __ARCH_WANT_SYS_ALARM | 355 | #define __ARCH_WANT_SYS_ALARM |
356 | #define __ARCH_WANT_SYS_GETHOSTNAME | 356 | #define __ARCH_WANT_SYS_GETHOSTNAME |
357 | #define __ARCH_WANT_SYS_IPC | ||
357 | #define __ARCH_WANT_SYS_PAUSE | 358 | #define __ARCH_WANT_SYS_PAUSE |
358 | #define __ARCH_WANT_SYS_SGETMASK | 359 | #define __ARCH_WANT_SYS_SGETMASK |
359 | #define __ARCH_WANT_SYS_SIGNAL | 360 | #define __ARCH_WANT_SYS_SIGNAL |
@@ -366,6 +367,9 @@ | |||
366 | #define __ARCH_WANT_SYS_LLSEEK | 367 | #define __ARCH_WANT_SYS_LLSEEK |
367 | #define __ARCH_WANT_SYS_NICE | 368 | #define __ARCH_WANT_SYS_NICE |
368 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 369 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
370 | #define __ARCH_WANT_SYS_OLD_UNAME | ||
371 | #define __ARCH_WANT_SYS_OLD_MMAP | ||
372 | #define __ARCH_WANT_SYS_OLD_SELECT | ||
369 | #define __ARCH_WANT_SYS_OLDUMOUNT | 373 | #define __ARCH_WANT_SYS_OLDUMOUNT |
370 | #define __ARCH_WANT_SYS_SIGPENDING | 374 | #define __ARCH_WANT_SYS_SIGPENDING |
371 | #define __ARCH_WANT_SYS_SIGPROCMASK | 375 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h index 4843f7ba754a..ff4307b0e81e 100644 --- a/arch/x86/include/asm/unistd_64.h +++ b/arch/x86/include/asm/unistd_64.h | |||
@@ -146,7 +146,7 @@ __SYSCALL(__NR_wait4, sys_wait4) | |||
146 | #define __NR_kill 62 | 146 | #define __NR_kill 62 |
147 | __SYSCALL(__NR_kill, sys_kill) | 147 | __SYSCALL(__NR_kill, sys_kill) |
148 | #define __NR_uname 63 | 148 | #define __NR_uname 63 |
149 | __SYSCALL(__NR_uname, sys_uname) | 149 | __SYSCALL(__NR_uname, sys_newuname) |
150 | 150 | ||
151 | #define __NR_semget 64 | 151 | #define __NR_semget 64 |
152 | __SYSCALL(__NR_semget, sys_semget) | 152 | __SYSCALL(__NR_semget, sys_semget) |
@@ -680,6 +680,7 @@ __SYSCALL(__NR_recvmmsg, sys_recvmmsg) | |||
680 | #define __ARCH_WANT_SYS_LLSEEK | 680 | #define __ARCH_WANT_SYS_LLSEEK |
681 | #define __ARCH_WANT_SYS_NICE | 681 | #define __ARCH_WANT_SYS_NICE |
682 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT | 682 | #define __ARCH_WANT_SYS_OLD_GETRLIMIT |
683 | #define __ARCH_WANT_SYS_OLD_UNAME | ||
683 | #define __ARCH_WANT_SYS_OLDUMOUNT | 684 | #define __ARCH_WANT_SYS_OLDUMOUNT |
684 | #define __ARCH_WANT_SYS_SIGPENDING | 685 | #define __ARCH_WANT_SYS_SIGPENDING |
685 | #define __ARCH_WANT_SYS_SIGPROCMASK | 686 | #define __ARCH_WANT_SYS_SIGPROCMASK |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index eddb1bdd1b8f..b3eeb66c0a51 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -903,7 +903,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, | |||
903 | return ret; | 903 | return ret; |
904 | } | 904 | } |
905 | 905 | ||
906 | static struct sysfs_ops sysfs_ops = { | 906 | static const struct sysfs_ops sysfs_ops = { |
907 | .show = show, | 907 | .show = show, |
908 | .store = store, | 908 | .store = store, |
909 | }; | 909 | }; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index a8aacd4b513c..28cba46bf32c 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -2044,6 +2044,7 @@ static __init void mce_init_banks(void) | |||
2044 | struct mce_bank *b = &mce_banks[i]; | 2044 | struct mce_bank *b = &mce_banks[i]; |
2045 | struct sysdev_attribute *a = &b->attr; | 2045 | struct sysdev_attribute *a = &b->attr; |
2046 | 2046 | ||
2047 | sysfs_attr_init(&a->attr); | ||
2047 | a->attr.name = b->attrname; | 2048 | a->attr.name = b->attrname; |
2048 | snprintf(b->attrname, ATTR_LEN, "bank%d", i); | 2049 | snprintf(b->attrname, ATTR_LEN, "bank%d", i); |
2049 | 2050 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 83a3d1f4efca..cda932ca3ade 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c | |||
@@ -388,7 +388,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, | |||
388 | return ret; | 388 | return ret; |
389 | } | 389 | } |
390 | 390 | ||
391 | static struct sysfs_ops threshold_ops = { | 391 | static const struct sysfs_ops threshold_ops = { |
392 | .show = show, | 392 | .show = show, |
393 | .store = store, | 393 | .store = store, |
394 | }; | 394 | }; |
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index dee1ff7cba58..196552bb412c 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c | |||
@@ -25,191 +25,6 @@ | |||
25 | #include <asm/syscalls.h> | 25 | #include <asm/syscalls.h> |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
29 | * calls. Linux/i386 didn't use to be able to handle more than | ||
30 | * 4 system call parameters, so these system calls used a memory | ||
31 | * block for parameter passing.. | ||
32 | */ | ||
33 | |||
34 | struct mmap_arg_struct { | ||
35 | unsigned long addr; | ||
36 | unsigned long len; | ||
37 | unsigned long prot; | ||
38 | unsigned long flags; | ||
39 | unsigned long fd; | ||
40 | unsigned long offset; | ||
41 | }; | ||
42 | |||
43 | asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) | ||
44 | { | ||
45 | struct mmap_arg_struct a; | ||
46 | int err = -EFAULT; | ||
47 | |||
48 | if (copy_from_user(&a, arg, sizeof(a))) | ||
49 | goto out; | ||
50 | |||
51 | err = -EINVAL; | ||
52 | if (a.offset & ~PAGE_MASK) | ||
53 | goto out; | ||
54 | |||
55 | err = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, | ||
56 | a.fd, a.offset >> PAGE_SHIFT); | ||
57 | out: | ||
58 | return err; | ||
59 | } | ||
60 | |||
61 | |||
62 | struct sel_arg_struct { | ||
63 | unsigned long n; | ||
64 | fd_set __user *inp, *outp, *exp; | ||
65 | struct timeval __user *tvp; | ||
66 | }; | ||
67 | |||
68 | asmlinkage int old_select(struct sel_arg_struct __user *arg) | ||
69 | { | ||
70 | struct sel_arg_struct a; | ||
71 | |||
72 | if (copy_from_user(&a, arg, sizeof(a))) | ||
73 | return -EFAULT; | ||
74 | /* sys_select() does the appropriate kernel locking */ | ||
75 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
80 | * | ||
81 | * This is really horribly ugly. | ||
82 | */ | ||
83 | asmlinkage int sys_ipc(uint call, int first, int second, | ||
84 | int third, void __user *ptr, long fifth) | ||
85 | { | ||
86 | int version, ret; | ||
87 | |||
88 | version = call >> 16; /* hack for backward compatibility */ | ||
89 | call &= 0xffff; | ||
90 | |||
91 | switch (call) { | ||
92 | case SEMOP: | ||
93 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL); | ||
94 | case SEMTIMEDOP: | ||
95 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, | ||
96 | (const struct timespec __user *)fifth); | ||
97 | |||
98 | case SEMGET: | ||
99 | return sys_semget(first, second, third); | ||
100 | case SEMCTL: { | ||
101 | union semun fourth; | ||
102 | if (!ptr) | ||
103 | return -EINVAL; | ||
104 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
105 | return -EFAULT; | ||
106 | return sys_semctl(first, second, third, fourth); | ||
107 | } | ||
108 | |||
109 | case MSGSND: | ||
110 | return sys_msgsnd(first, (struct msgbuf __user *) ptr, | ||
111 | second, third); | ||
112 | case MSGRCV: | ||
113 | switch (version) { | ||
114 | case 0: { | ||
115 | struct ipc_kludge tmp; | ||
116 | if (!ptr) | ||
117 | return -EINVAL; | ||
118 | |||
119 | if (copy_from_user(&tmp, | ||
120 | (struct ipc_kludge __user *) ptr, | ||
121 | sizeof(tmp))) | ||
122 | return -EFAULT; | ||
123 | return sys_msgrcv(first, tmp.msgp, second, | ||
124 | tmp.msgtyp, third); | ||
125 | } | ||
126 | default: | ||
127 | return sys_msgrcv(first, | ||
128 | (struct msgbuf __user *) ptr, | ||
129 | second, fifth, third); | ||
130 | } | ||
131 | case MSGGET: | ||
132 | return sys_msgget((key_t) first, second); | ||
133 | case MSGCTL: | ||
134 | return sys_msgctl(first, second, (struct msqid_ds __user *) ptr); | ||
135 | |||
136 | case SHMAT: | ||
137 | switch (version) { | ||
138 | default: { | ||
139 | ulong raddr; | ||
140 | ret = do_shmat(first, (char __user *) ptr, second, &raddr); | ||
141 | if (ret) | ||
142 | return ret; | ||
143 | return put_user(raddr, (ulong __user *) third); | ||
144 | } | ||
145 | case 1: /* iBCS2 emulator entry point */ | ||
146 | if (!segment_eq(get_fs(), get_ds())) | ||
147 | return -EINVAL; | ||
148 | /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */ | ||
149 | return do_shmat(first, (char __user *) ptr, second, (ulong *) third); | ||
150 | } | ||
151 | case SHMDT: | ||
152 | return sys_shmdt((char __user *)ptr); | ||
153 | case SHMGET: | ||
154 | return sys_shmget(first, second, third); | ||
155 | case SHMCTL: | ||
156 | return sys_shmctl(first, second, | ||
157 | (struct shmid_ds __user *) ptr); | ||
158 | default: | ||
159 | return -ENOSYS; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Old cruft | ||
165 | */ | ||
166 | asmlinkage int sys_uname(struct old_utsname __user *name) | ||
167 | { | ||
168 | int err; | ||
169 | if (!name) | ||
170 | return -EFAULT; | ||
171 | down_read(&uts_sem); | ||
172 | err = copy_to_user(name, utsname(), sizeof(*name)); | ||
173 | up_read(&uts_sem); | ||
174 | return err? -EFAULT:0; | ||
175 | } | ||
176 | |||
177 | asmlinkage int sys_olduname(struct oldold_utsname __user *name) | ||
178 | { | ||
179 | int error; | ||
180 | |||
181 | if (!name) | ||
182 | return -EFAULT; | ||
183 | if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) | ||
184 | return -EFAULT; | ||
185 | |||
186 | down_read(&uts_sem); | ||
187 | |||
188 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
189 | __OLD_UTS_LEN); | ||
190 | error |= __put_user(0, name->sysname + __OLD_UTS_LEN); | ||
191 | error |= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
192 | __OLD_UTS_LEN); | ||
193 | error |= __put_user(0, name->nodename + __OLD_UTS_LEN); | ||
194 | error |= __copy_to_user(&name->release, &utsname()->release, | ||
195 | __OLD_UTS_LEN); | ||
196 | error |= __put_user(0, name->release + __OLD_UTS_LEN); | ||
197 | error |= __copy_to_user(&name->version, &utsname()->version, | ||
198 | __OLD_UTS_LEN); | ||
199 | error |= __put_user(0, name->version + __OLD_UTS_LEN); | ||
200 | error |= __copy_to_user(&name->machine, &utsname()->machine, | ||
201 | __OLD_UTS_LEN); | ||
202 | error |= __put_user(0, name->machine + __OLD_UTS_LEN); | ||
203 | |||
204 | up_read(&uts_sem); | ||
205 | |||
206 | error = error ? -EFAULT : 0; | ||
207 | |||
208 | return error; | ||
209 | } | ||
210 | |||
211 | |||
212 | /* | ||
213 | * Do a system call from kernel instead of calling sys_execve so we | 28 | * Do a system call from kernel instead of calling sys_execve so we |
214 | * end up with proper pt_regs. | 29 | * end up with proper pt_regs. |
215 | */ | 30 | */ |
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 8aa2057efd12..ff14a5044ce6 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c | |||
@@ -209,15 +209,3 @@ bottomup: | |||
209 | 209 | ||
210 | return addr; | 210 | return addr; |
211 | } | 211 | } |
212 | |||
213 | |||
214 | SYSCALL_DEFINE1(uname, struct new_utsname __user *, name) | ||
215 | { | ||
216 | int err; | ||
217 | down_read(&uts_sem); | ||
218 | err = copy_to_user(name, utsname(), sizeof(*name)); | ||
219 | up_read(&uts_sem); | ||
220 | if (personality(current->personality) == PER_LINUX32) | ||
221 | err |= copy_to_user(&name->machine, "i686", 5); | ||
222 | return err ? -EFAULT : 0; | ||
223 | } | ||
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S index 15228b5d3eb7..8b3729341216 100644 --- a/arch/x86/kernel/syscall_table_32.S +++ b/arch/x86/kernel/syscall_table_32.S | |||
@@ -81,7 +81,7 @@ ENTRY(sys_call_table) | |||
81 | .long sys_settimeofday | 81 | .long sys_settimeofday |
82 | .long sys_getgroups16 /* 80 */ | 82 | .long sys_getgroups16 /* 80 */ |
83 | .long sys_setgroups16 | 83 | .long sys_setgroups16 |
84 | .long old_select | 84 | .long sys_old_select |
85 | .long sys_symlink | 85 | .long sys_symlink |
86 | .long sys_lstat | 86 | .long sys_lstat |
87 | .long sys_readlink /* 85 */ | 87 | .long sys_readlink /* 85 */ |
@@ -89,7 +89,7 @@ ENTRY(sys_call_table) | |||
89 | .long sys_swapon | 89 | .long sys_swapon |
90 | .long sys_reboot | 90 | .long sys_reboot |
91 | .long sys_old_readdir | 91 | .long sys_old_readdir |
92 | .long old_mmap /* 90 */ | 92 | .long sys_old_mmap /* 90 */ |
93 | .long sys_munmap | 93 | .long sys_munmap |
94 | .long sys_truncate | 94 | .long sys_truncate |
95 | .long sys_ftruncate | 95 | .long sys_ftruncate |
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h index 66410acf18b4..4609b0f15f1f 100644 --- a/arch/xtensa/include/asm/pci.h +++ b/arch/xtensa/include/asm/pci.h | |||
@@ -56,14 +56,6 @@ struct pci_dev; | |||
56 | 56 | ||
57 | #define PCI_DMA_BUS_IS_PHYS (1) | 57 | #define PCI_DMA_BUS_IS_PHYS (1) |
58 | 58 | ||
59 | /* pci_unmap_{page,single} is a no-op, so */ | ||
60 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) | ||
61 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) | ||
62 | #define pci_unmap_addr(PTR, ADDR_NAME) (0) | ||
63 | #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
64 | #define pci_ubnmap_len(PTR, LEN_NAME) (0) | ||
65 | #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
66 | |||
67 | /* Map a range of PCI memory or I/O space for a device into user space */ | 59 | /* Map a range of PCI memory or I/O space for a device into user space */ |
68 | int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, | 60 | int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, |
69 | enum pci_mmap_state mmap_state, int write_combine); | 61 | enum pci_mmap_state mmap_state, int write_combine); |
diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h index 905e1e619654..3c549f798727 100644 --- a/arch/xtensa/include/asm/ptrace.h +++ b/arch/xtensa/include/asm/ptrace.h | |||
@@ -113,6 +113,7 @@ struct pt_regs { | |||
113 | 113 | ||
114 | #include <variant/core.h> | 114 | #include <variant/core.h> |
115 | 115 | ||
116 | # define arch_has_single_step() (1) | ||
116 | # define task_pt_regs(tsk) ((struct pt_regs*) \ | 117 | # define task_pt_regs(tsk) ((struct pt_regs*) \ |
117 | (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1) | 118 | (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1) |
118 | # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) | 119 | # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) |
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 9486882ef0af..9d4e1ceb3f09 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c | |||
@@ -30,6 +30,17 @@ | |||
30 | #include <asm/elf.h> | 30 | #include <asm/elf.h> |
31 | #include <asm/coprocessor.h> | 31 | #include <asm/coprocessor.h> |
32 | 32 | ||
33 | |||
34 | void user_enable_single_step(struct task_struct *child) | ||
35 | { | ||
36 | child->ptrace |= PT_SINGLESTEP; | ||
37 | } | ||
38 | |||
39 | void user_disable_single_step(struct task_struct *child) | ||
40 | { | ||
41 | child->ptrace &= ~PT_SINGLESTEP; | ||
42 | } | ||
43 | |||
33 | /* | 44 | /* |
34 | * Called by kernel/ptrace.c when detaching to disable single stepping. | 45 | * Called by kernel/ptrace.c when detaching to disable single stepping. |
35 | */ | 46 | */ |
@@ -268,51 +279,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
268 | ret = ptrace_pokeusr(child, addr, data); | 279 | ret = ptrace_pokeusr(child, addr, data); |
269 | break; | 280 | break; |
270 | 281 | ||
271 | /* continue and stop at next (return from) syscall */ | ||
272 | |||
273 | case PTRACE_SYSCALL: | ||
274 | case PTRACE_CONT: /* restart after signal. */ | ||
275 | { | ||
276 | ret = -EIO; | ||
277 | if (!valid_signal(data)) | ||
278 | break; | ||
279 | if (request == PTRACE_SYSCALL) | ||
280 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
281 | else | ||
282 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
283 | child->exit_code = data; | ||
284 | /* Make sure the single step bit is not set. */ | ||
285 | child->ptrace &= ~PT_SINGLESTEP; | ||
286 | wake_up_process(child); | ||
287 | ret = 0; | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * make the child exit. Best I can do is send it a sigkill. | ||
293 | * perhaps it should be put in the status that it wants to | ||
294 | * exit. | ||
295 | */ | ||
296 | case PTRACE_KILL: | ||
297 | ret = 0; | ||
298 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
299 | break; | ||
300 | child->exit_code = SIGKILL; | ||
301 | child->ptrace &= ~PT_SINGLESTEP; | ||
302 | wake_up_process(child); | ||
303 | break; | ||
304 | |||
305 | case PTRACE_SINGLESTEP: | ||
306 | ret = -EIO; | ||
307 | if (!valid_signal(data)) | ||
308 | break; | ||
309 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
310 | child->ptrace |= PT_SINGLESTEP; | ||
311 | child->exit_code = data; | ||
312 | wake_up_process(child); | ||
313 | ret = 0; | ||
314 | break; | ||
315 | |||
316 | case PTRACE_GETREGS: | 282 | case PTRACE_GETREGS: |
317 | ret = ptrace_getregs(child, (void __user *) data); | 283 | ret = ptrace_getregs(child, (void __user *) data); |
318 | break; | 284 | break; |
diff --git a/block/Kconfig b/block/Kconfig index e20fbde0875c..62a5921321cd 100644 --- a/block/Kconfig +++ b/block/Kconfig | |||
@@ -78,7 +78,7 @@ config BLK_DEV_INTEGRITY | |||
78 | Protection. If in doubt, say N. | 78 | Protection. If in doubt, say N. |
79 | 79 | ||
80 | config BLK_CGROUP | 80 | config BLK_CGROUP |
81 | bool | 81 | tristate |
82 | depends on CGROUPS | 82 | depends on CGROUPS |
83 | default n | 83 | default n |
84 | ---help--- | 84 | ---help--- |
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index b71abfb0d726..fc71cf071fb2 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched | |||
@@ -23,6 +23,7 @@ config IOSCHED_DEADLINE | |||
23 | 23 | ||
24 | config IOSCHED_CFQ | 24 | config IOSCHED_CFQ |
25 | tristate "CFQ I/O scheduler" | 25 | tristate "CFQ I/O scheduler" |
26 | select BLK_CGROUP if CFQ_GROUP_IOSCHED | ||
26 | default y | 27 | default y |
27 | ---help--- | 28 | ---help--- |
28 | The CFQ I/O scheduler tries to distribute bandwidth equally | 29 | The CFQ I/O scheduler tries to distribute bandwidth equally |
@@ -35,7 +36,6 @@ config IOSCHED_CFQ | |||
35 | config CFQ_GROUP_IOSCHED | 36 | config CFQ_GROUP_IOSCHED |
36 | bool "CFQ Group Scheduling support" | 37 | bool "CFQ Group Scheduling support" |
37 | depends on IOSCHED_CFQ && CGROUPS | 38 | depends on IOSCHED_CFQ && CGROUPS |
38 | select BLK_CGROUP | ||
39 | default n | 39 | default n |
40 | ---help--- | 40 | ---help--- |
41 | Enable group IO scheduling in CFQ. | 41 | Enable group IO scheduling in CFQ. |
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index c85d74cae200..4b686ad08eaa 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -23,6 +23,31 @@ static LIST_HEAD(blkio_list); | |||
23 | struct blkio_cgroup blkio_root_cgroup = { .weight = 2*BLKIO_WEIGHT_DEFAULT }; | 23 | struct blkio_cgroup blkio_root_cgroup = { .weight = 2*BLKIO_WEIGHT_DEFAULT }; |
24 | EXPORT_SYMBOL_GPL(blkio_root_cgroup); | 24 | EXPORT_SYMBOL_GPL(blkio_root_cgroup); |
25 | 25 | ||
26 | static struct cgroup_subsys_state *blkiocg_create(struct cgroup_subsys *, | ||
27 | struct cgroup *); | ||
28 | static int blkiocg_can_attach(struct cgroup_subsys *, struct cgroup *, | ||
29 | struct task_struct *, bool); | ||
30 | static void blkiocg_attach(struct cgroup_subsys *, struct cgroup *, | ||
31 | struct cgroup *, struct task_struct *, bool); | ||
32 | static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *); | ||
33 | static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *); | ||
34 | |||
35 | struct cgroup_subsys blkio_subsys = { | ||
36 | .name = "blkio", | ||
37 | .create = blkiocg_create, | ||
38 | .can_attach = blkiocg_can_attach, | ||
39 | .attach = blkiocg_attach, | ||
40 | .destroy = blkiocg_destroy, | ||
41 | .populate = blkiocg_populate, | ||
42 | #ifdef CONFIG_BLK_CGROUP | ||
43 | /* note: blkio_subsys_id is otherwise defined in blk-cgroup.h */ | ||
44 | .subsys_id = blkio_subsys_id, | ||
45 | #endif | ||
46 | .use_id = 1, | ||
47 | .module = THIS_MODULE, | ||
48 | }; | ||
49 | EXPORT_SYMBOL_GPL(blkio_subsys); | ||
50 | |||
26 | struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup) | 51 | struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup) |
27 | { | 52 | { |
28 | return container_of(cgroup_subsys_state(cgroup, blkio_subsys_id), | 53 | return container_of(cgroup_subsys_state(cgroup, blkio_subsys_id), |
@@ -253,7 +278,8 @@ remove_entry: | |||
253 | done: | 278 | done: |
254 | free_css_id(&blkio_subsys, &blkcg->css); | 279 | free_css_id(&blkio_subsys, &blkcg->css); |
255 | rcu_read_unlock(); | 280 | rcu_read_unlock(); |
256 | kfree(blkcg); | 281 | if (blkcg != &blkio_root_cgroup) |
282 | kfree(blkcg); | ||
257 | } | 283 | } |
258 | 284 | ||
259 | static struct cgroup_subsys_state * | 285 | static struct cgroup_subsys_state * |
@@ -319,17 +345,6 @@ static void blkiocg_attach(struct cgroup_subsys *subsys, struct cgroup *cgroup, | |||
319 | task_unlock(tsk); | 345 | task_unlock(tsk); |
320 | } | 346 | } |
321 | 347 | ||
322 | struct cgroup_subsys blkio_subsys = { | ||
323 | .name = "blkio", | ||
324 | .create = blkiocg_create, | ||
325 | .can_attach = blkiocg_can_attach, | ||
326 | .attach = blkiocg_attach, | ||
327 | .destroy = blkiocg_destroy, | ||
328 | .populate = blkiocg_populate, | ||
329 | .subsys_id = blkio_subsys_id, | ||
330 | .use_id = 1, | ||
331 | }; | ||
332 | |||
333 | void blkio_policy_register(struct blkio_policy_type *blkiop) | 348 | void blkio_policy_register(struct blkio_policy_type *blkiop) |
334 | { | 349 | { |
335 | spin_lock(&blkio_list_lock); | 350 | spin_lock(&blkio_list_lock); |
@@ -345,3 +360,17 @@ void blkio_policy_unregister(struct blkio_policy_type *blkiop) | |||
345 | spin_unlock(&blkio_list_lock); | 360 | spin_unlock(&blkio_list_lock); |
346 | } | 361 | } |
347 | EXPORT_SYMBOL_GPL(blkio_policy_unregister); | 362 | EXPORT_SYMBOL_GPL(blkio_policy_unregister); |
363 | |||
364 | static int __init init_cgroup_blkio(void) | ||
365 | { | ||
366 | return cgroup_load_subsys(&blkio_subsys); | ||
367 | } | ||
368 | |||
369 | static void __exit exit_cgroup_blkio(void) | ||
370 | { | ||
371 | cgroup_unload_subsys(&blkio_subsys); | ||
372 | } | ||
373 | |||
374 | module_init(init_cgroup_blkio); | ||
375 | module_exit(exit_cgroup_blkio); | ||
376 | MODULE_LICENSE("GPL"); | ||
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 84bf745fa775..8ccc20464dae 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h | |||
@@ -15,7 +15,13 @@ | |||
15 | 15 | ||
16 | #include <linux/cgroup.h> | 16 | #include <linux/cgroup.h> |
17 | 17 | ||
18 | #ifdef CONFIG_BLK_CGROUP | 18 | #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) |
19 | |||
20 | #ifndef CONFIG_BLK_CGROUP | ||
21 | /* When blk-cgroup is a module, its subsys_id isn't a compile-time constant */ | ||
22 | extern struct cgroup_subsys blkio_subsys; | ||
23 | #define blkio_subsys_id blkio_subsys.subsys_id | ||
24 | #endif | ||
19 | 25 | ||
20 | struct blkio_cgroup { | 26 | struct blkio_cgroup { |
21 | struct cgroup_subsys_state css; | 27 | struct cgroup_subsys_state css; |
@@ -91,7 +97,7 @@ static inline void blkiocg_update_blkio_group_dequeue_stats( | |||
91 | struct blkio_group *blkg, unsigned long dequeue) {} | 97 | struct blkio_group *blkg, unsigned long dequeue) {} |
92 | #endif | 98 | #endif |
93 | 99 | ||
94 | #ifdef CONFIG_BLK_CGROUP | 100 | #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) |
95 | extern struct blkio_cgroup blkio_root_cgroup; | 101 | extern struct blkio_cgroup blkio_root_cgroup; |
96 | extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); | 102 | extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); |
97 | extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, | 103 | extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, |
diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 15c630813b1c..96e83c2bdb94 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c | |||
@@ -278,7 +278,7 @@ static struct attribute *integrity_attrs[] = { | |||
278 | NULL, | 278 | NULL, |
279 | }; | 279 | }; |
280 | 280 | ||
281 | static struct sysfs_ops integrity_ops = { | 281 | static const struct sysfs_ops integrity_ops = { |
282 | .show = &integrity_attr_show, | 282 | .show = &integrity_attr_show, |
283 | .store = &integrity_attr_store, | 283 | .store = &integrity_attr_store, |
284 | }; | 284 | }; |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index e85442415db3..2ae2cb3f362f 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -450,7 +450,7 @@ static void blk_release_queue(struct kobject *kobj) | |||
450 | kmem_cache_free(blk_requestq_cachep, q); | 450 | kmem_cache_free(blk_requestq_cachep, q); |
451 | } | 451 | } |
452 | 452 | ||
453 | static struct sysfs_ops queue_sysfs_ops = { | 453 | static const struct sysfs_ops queue_sysfs_ops = { |
454 | .show = queue_attr_show, | 454 | .show = queue_attr_show, |
455 | .store = queue_attr_store, | 455 | .store = queue_attr_store, |
456 | }; | 456 | }; |
diff --git a/block/elevator.c b/block/elevator.c index ee3a883840f2..df75676f6671 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -892,7 +892,7 @@ elv_attr_store(struct kobject *kobj, struct attribute *attr, | |||
892 | return error; | 892 | return error; |
893 | } | 893 | } |
894 | 894 | ||
895 | static struct sysfs_ops elv_sysfs_ops = { | 895 | static const struct sysfs_ops elv_sysfs_ops = { |
896 | .show = elv_attr_show, | 896 | .show = elv_attr_show, |
897 | .store = elv_attr_store, | 897 | .store = elv_attr_store, |
898 | }; | 898 | }; |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index a206a12da78a..743f2445e2a1 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
@@ -101,6 +101,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | |||
101 | struct acpi_table_header *header = NULL; | 101 | struct acpi_table_header *header = NULL; |
102 | struct acpi_table_attr *attr = NULL; | 102 | struct acpi_table_attr *attr = NULL; |
103 | 103 | ||
104 | sysfs_attr_init(&table_attr->attr.attr); | ||
104 | if (table_header->signature[0] != '\0') | 105 | if (table_header->signature[0] != '\0') |
105 | memcpy(table_attr->name, table_header->signature, | 106 | memcpy(table_attr->name, table_header->signature, |
106 | ACPI_NAME_SIZE); | 107 | ACPI_NAME_SIZE); |
@@ -475,6 +476,7 @@ void acpi_irq_stats_init(void) | |||
475 | goto fail; | 476 | goto fail; |
476 | strncpy(name, buffer, strlen(buffer) + 1); | 477 | strncpy(name, buffer, strlen(buffer) + 1); |
477 | 478 | ||
479 | sysfs_attr_init(&counter_attrs[i].attr); | ||
478 | counter_attrs[i].attr.name = name; | 480 | counter_attrs[i].attr.name = name; |
479 | counter_attrs[i].attr.mode = 0644; | 481 | counter_attrs[i].attr.mode = 0644; |
480 | counter_attrs[i].show = counter_show; | 482 | counter_attrs[i].show = counter_show; |
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c index fe3a865be4e5..b0ca5a47f47d 100644 --- a/drivers/auxdisplay/cfag12864bfb.c +++ b/drivers/auxdisplay/cfag12864bfb.c | |||
@@ -81,7 +81,7 @@ static struct fb_ops cfag12864bfb_ops = { | |||
81 | .fb_mmap = cfag12864bfb_mmap, | 81 | .fb_mmap = cfag12864bfb_mmap, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static int __init cfag12864bfb_probe(struct platform_device *device) | 84 | static int __devinit cfag12864bfb_probe(struct platform_device *device) |
85 | { | 85 | { |
86 | int ret = -EINVAL; | 86 | int ret = -EINVAL; |
87 | struct fb_info *info = framebuffer_alloc(0, &device->dev); | 87 | struct fb_info *info = framebuffer_alloc(0, &device->dev); |
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index ee377270beb9..fd52c48ee762 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -3,35 +3,50 @@ menu "Generic Driver Options" | |||
3 | config UEVENT_HELPER_PATH | 3 | config UEVENT_HELPER_PATH |
4 | string "path to uevent helper" | 4 | string "path to uevent helper" |
5 | depends on HOTPLUG | 5 | depends on HOTPLUG |
6 | default "/sbin/hotplug" | 6 | default "" |
7 | help | 7 | help |
8 | Path to uevent helper program forked by the kernel for | 8 | Path to uevent helper program forked by the kernel for |
9 | every uevent. | 9 | every uevent. |
10 | Before the switch to the netlink-based uevent source, this was | ||
11 | used to hook hotplug scripts into kernel device events. It | ||
12 | usually pointed to a shell script at /sbin/hotplug. | ||
13 | This should not be used today, because usual systems create | ||
14 | many events at bootup or device discovery in a very short time | ||
15 | frame. One forked process per event can create so many processes | ||
16 | that it creates a high system load, or on smaller systems | ||
17 | it is known to create out-of-memory situations during bootup. | ||
10 | 18 | ||
11 | config DEVTMPFS | 19 | config DEVTMPFS |
12 | bool "Create a kernel maintained /dev tmpfs (EXPERIMENTAL)" | 20 | bool "Maintain a devtmpfs filesystem to mount at /dev" |
13 | depends on HOTPLUG && SHMEM && TMPFS | 21 | depends on HOTPLUG && SHMEM && TMPFS |
14 | help | 22 | help |
15 | This creates a tmpfs filesystem, and mounts it at bootup | 23 | This creates a tmpfs filesystem instance early at bootup. |
16 | and mounts it at /dev. The kernel driver core creates device | 24 | In this filesystem, the kernel driver core maintains device |
17 | nodes for all registered devices in that filesystem. All device | 25 | nodes with their default names and permissions for all |
18 | nodes are owned by root and have the default mode of 0600. | 26 | registered devices with an assigned major/minor number. |
19 | Userspace can add and delete the nodes as needed. This is | 27 | Userspace can modify the filesystem content as needed, add |
20 | intended to simplify bootup, and make it possible to delay | 28 | symlinks, and apply needed permissions. |
21 | the initial coldplug at bootup done by udev in userspace. | 29 | It provides a fully functional /dev directory, where usually |
22 | It should also provide a simpler way for rescue systems | 30 | udev runs on top, managing permissions and adding meaningful |
23 | to bring up a kernel with dynamic major/minor numbers. | 31 | symlinks. |
24 | Meaningful symlinks, permissions and device ownership must | 32 | In very limited environments, it may provide a sufficient |
25 | still be handled by userspace. | 33 | functional /dev without any further help. It also allows simple |
26 | If unsure, say N here. | 34 | rescue systems, and reliably handles dynamic major/minor numbers. |
27 | 35 | ||
28 | config DEVTMPFS_MOUNT | 36 | config DEVTMPFS_MOUNT |
29 | bool "Automount devtmpfs at /dev" | 37 | bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs" |
30 | depends on DEVTMPFS | 38 | depends on DEVTMPFS |
31 | help | 39 | help |
32 | This will mount devtmpfs at /dev if the kernel mounts the root | 40 | This will instruct the kernel to automatically mount the |
33 | filesystem. It will not affect initramfs based mounting. | 41 | devtmpfs filesystem at /dev, directly after the kernel has |
34 | If unsure, say N here. | 42 | mounted the root filesystem. The behavior can be overridden |
43 | with the commandline parameter: devtmpfs.mount=0|1. | ||
44 | This option does not affect initramfs based booting, here | ||
45 | the devtmpfs filesystem always needs to be mounted manually | ||
46 | after the roots is mounted. | ||
47 | With this option enabled, it allows to bring up a system in | ||
48 | rescue mode with init=/bin/sh, even when the /dev directory | ||
49 | on the rootfs is completely empty. | ||
35 | 50 | ||
36 | config STANDALONE | 51 | config STANDALONE |
37 | bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL | 52 | bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c0c5a43d9fb3..71f6af5c8b0b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -70,7 +70,7 @@ static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr, | |||
70 | return ret; | 70 | return ret; |
71 | } | 71 | } |
72 | 72 | ||
73 | static struct sysfs_ops driver_sysfs_ops = { | 73 | static const struct sysfs_ops driver_sysfs_ops = { |
74 | .show = drv_attr_show, | 74 | .show = drv_attr_show, |
75 | .store = drv_attr_store, | 75 | .store = drv_attr_store, |
76 | }; | 76 | }; |
@@ -115,7 +115,7 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr, | |||
115 | return ret; | 115 | return ret; |
116 | } | 116 | } |
117 | 117 | ||
118 | static struct sysfs_ops bus_sysfs_ops = { | 118 | static const struct sysfs_ops bus_sysfs_ops = { |
119 | .show = bus_attr_show, | 119 | .show = bus_attr_show, |
120 | .store = bus_attr_store, | 120 | .store = bus_attr_store, |
121 | }; | 121 | }; |
@@ -154,7 +154,7 @@ static int bus_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
154 | return 0; | 154 | return 0; |
155 | } | 155 | } |
156 | 156 | ||
157 | static struct kset_uevent_ops bus_uevent_ops = { | 157 | static const struct kset_uevent_ops bus_uevent_ops = { |
158 | .filter = bus_uevent_filter, | 158 | .filter = bus_uevent_filter, |
159 | }; | 159 | }; |
160 | 160 | ||
@@ -173,10 +173,10 @@ static ssize_t driver_unbind(struct device_driver *drv, | |||
173 | dev = bus_find_device_by_name(bus, NULL, buf); | 173 | dev = bus_find_device_by_name(bus, NULL, buf); |
174 | if (dev && dev->driver == drv) { | 174 | if (dev && dev->driver == drv) { |
175 | if (dev->parent) /* Needed for USB */ | 175 | if (dev->parent) /* Needed for USB */ |
176 | down(&dev->parent->sem); | 176 | device_lock(dev->parent); |
177 | device_release_driver(dev); | 177 | device_release_driver(dev); |
178 | if (dev->parent) | 178 | if (dev->parent) |
179 | up(&dev->parent->sem); | 179 | device_unlock(dev->parent); |
180 | err = count; | 180 | err = count; |
181 | } | 181 | } |
182 | put_device(dev); | 182 | put_device(dev); |
@@ -200,12 +200,12 @@ static ssize_t driver_bind(struct device_driver *drv, | |||
200 | dev = bus_find_device_by_name(bus, NULL, buf); | 200 | dev = bus_find_device_by_name(bus, NULL, buf); |
201 | if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { | 201 | if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { |
202 | if (dev->parent) /* Needed for USB */ | 202 | if (dev->parent) /* Needed for USB */ |
203 | down(&dev->parent->sem); | 203 | device_lock(dev->parent); |
204 | down(&dev->sem); | 204 | device_lock(dev); |
205 | err = driver_probe_device(drv, dev); | 205 | err = driver_probe_device(drv, dev); |
206 | up(&dev->sem); | 206 | device_unlock(dev); |
207 | if (dev->parent) | 207 | if (dev->parent) |
208 | up(&dev->parent->sem); | 208 | device_unlock(dev->parent); |
209 | 209 | ||
210 | if (err > 0) { | 210 | if (err > 0) { |
211 | /* success */ | 211 | /* success */ |
@@ -744,10 +744,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, | |||
744 | 744 | ||
745 | if (!dev->driver) { | 745 | if (!dev->driver) { |
746 | if (dev->parent) /* Needed for USB */ | 746 | if (dev->parent) /* Needed for USB */ |
747 | down(&dev->parent->sem); | 747 | device_lock(dev->parent); |
748 | ret = device_attach(dev); | 748 | ret = device_attach(dev); |
749 | if (dev->parent) | 749 | if (dev->parent) |
750 | up(&dev->parent->sem); | 750 | device_unlock(dev->parent); |
751 | } | 751 | } |
752 | return ret < 0 ? ret : 0; | 752 | return ret < 0 ? ret : 0; |
753 | } | 753 | } |
@@ -779,10 +779,10 @@ int device_reprobe(struct device *dev) | |||
779 | { | 779 | { |
780 | if (dev->driver) { | 780 | if (dev->driver) { |
781 | if (dev->parent) /* Needed for USB */ | 781 | if (dev->parent) /* Needed for USB */ |
782 | down(&dev->parent->sem); | 782 | device_lock(dev->parent); |
783 | device_release_driver(dev); | 783 | device_release_driver(dev); |
784 | if (dev->parent) | 784 | if (dev->parent) |
785 | up(&dev->parent->sem); | 785 | device_unlock(dev->parent); |
786 | } | 786 | } |
787 | return bus_rescan_devices_helper(dev, NULL); | 787 | return bus_rescan_devices_helper(dev, NULL); |
788 | } | 788 | } |
diff --git a/drivers/base/class.c b/drivers/base/class.c index 6e2c3b064f53..0147f476b8a9 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -31,7 +31,7 @@ static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, | |||
31 | ssize_t ret = -EIO; | 31 | ssize_t ret = -EIO; |
32 | 32 | ||
33 | if (class_attr->show) | 33 | if (class_attr->show) |
34 | ret = class_attr->show(cp->class, buf); | 34 | ret = class_attr->show(cp->class, class_attr, buf); |
35 | return ret; | 35 | return ret; |
36 | } | 36 | } |
37 | 37 | ||
@@ -43,7 +43,7 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, | |||
43 | ssize_t ret = -EIO; | 43 | ssize_t ret = -EIO; |
44 | 44 | ||
45 | if (class_attr->store) | 45 | if (class_attr->store) |
46 | ret = class_attr->store(cp->class, buf, count); | 46 | ret = class_attr->store(cp->class, class_attr, buf, count); |
47 | return ret; | 47 | return ret; |
48 | } | 48 | } |
49 | 49 | ||
@@ -63,7 +63,7 @@ static void class_release(struct kobject *kobj) | |||
63 | kfree(cp); | 63 | kfree(cp); |
64 | } | 64 | } |
65 | 65 | ||
66 | static struct sysfs_ops class_sysfs_ops = { | 66 | static const struct sysfs_ops class_sysfs_ops = { |
67 | .show = class_attr_show, | 67 | .show = class_attr_show, |
68 | .store = class_attr_store, | 68 | .store = class_attr_store, |
69 | }; | 69 | }; |
@@ -490,6 +490,16 @@ void class_interface_unregister(struct class_interface *class_intf) | |||
490 | class_put(parent); | 490 | class_put(parent); |
491 | } | 491 | } |
492 | 492 | ||
493 | ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr, | ||
494 | char *buf) | ||
495 | { | ||
496 | struct class_attribute_string *cs; | ||
497 | cs = container_of(attr, struct class_attribute_string, attr); | ||
498 | return snprintf(buf, PAGE_SIZE, "%s\n", cs->str); | ||
499 | } | ||
500 | |||
501 | EXPORT_SYMBOL_GPL(show_class_attr_string); | ||
502 | |||
493 | struct class_compat { | 503 | struct class_compat { |
494 | struct kobject *kobj; | 504 | struct kobject *kobj; |
495 | }; | 505 | }; |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 282025770429..ef55df34ddd0 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -100,7 +100,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, | |||
100 | return ret; | 100 | return ret; |
101 | } | 101 | } |
102 | 102 | ||
103 | static struct sysfs_ops dev_sysfs_ops = { | 103 | static const struct sysfs_ops dev_sysfs_ops = { |
104 | .show = dev_attr_show, | 104 | .show = dev_attr_show, |
105 | .store = dev_attr_store, | 105 | .store = dev_attr_store, |
106 | }; | 106 | }; |
@@ -252,7 +252,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, | |||
252 | return retval; | 252 | return retval; |
253 | } | 253 | } |
254 | 254 | ||
255 | static struct kset_uevent_ops device_uevent_ops = { | 255 | static const struct kset_uevent_ops device_uevent_ops = { |
256 | .filter = dev_uevent_filter, | 256 | .filter = dev_uevent_filter, |
257 | .name = dev_uevent_name, | 257 | .name = dev_uevent_name, |
258 | .uevent = dev_uevent, | 258 | .uevent = dev_uevent, |
@@ -306,15 +306,10 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | |||
306 | { | 306 | { |
307 | enum kobject_action action; | 307 | enum kobject_action action; |
308 | 308 | ||
309 | if (kobject_action_type(buf, count, &action) == 0) { | 309 | if (kobject_action_type(buf, count, &action) == 0) |
310 | kobject_uevent(&dev->kobj, action); | 310 | kobject_uevent(&dev->kobj, action); |
311 | goto out; | 311 | else |
312 | } | 312 | dev_err(dev, "uevent: unknown action-string\n"); |
313 | |||
314 | dev_err(dev, "uevent: unsupported action-string; this will " | ||
315 | "be ignored in a future kernel version\n"); | ||
316 | kobject_uevent(&dev->kobj, KOBJ_ADD); | ||
317 | out: | ||
318 | return count; | 313 | return count; |
319 | } | 314 | } |
320 | 315 | ||
@@ -607,6 +602,7 @@ static struct kobject *get_device_parent(struct device *dev, | |||
607 | int retval; | 602 | int retval; |
608 | 603 | ||
609 | if (dev->class) { | 604 | if (dev->class) { |
605 | static DEFINE_MUTEX(gdp_mutex); | ||
610 | struct kobject *kobj = NULL; | 606 | struct kobject *kobj = NULL; |
611 | struct kobject *parent_kobj; | 607 | struct kobject *parent_kobj; |
612 | struct kobject *k; | 608 | struct kobject *k; |
@@ -623,6 +619,8 @@ static struct kobject *get_device_parent(struct device *dev, | |||
623 | else | 619 | else |
624 | parent_kobj = &parent->kobj; | 620 | parent_kobj = &parent->kobj; |
625 | 621 | ||
622 | mutex_lock(&gdp_mutex); | ||
623 | |||
626 | /* find our class-directory at the parent and reference it */ | 624 | /* find our class-directory at the parent and reference it */ |
627 | spin_lock(&dev->class->p->class_dirs.list_lock); | 625 | spin_lock(&dev->class->p->class_dirs.list_lock); |
628 | list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) | 626 | list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) |
@@ -631,20 +629,26 @@ static struct kobject *get_device_parent(struct device *dev, | |||
631 | break; | 629 | break; |
632 | } | 630 | } |
633 | spin_unlock(&dev->class->p->class_dirs.list_lock); | 631 | spin_unlock(&dev->class->p->class_dirs.list_lock); |
634 | if (kobj) | 632 | if (kobj) { |
633 | mutex_unlock(&gdp_mutex); | ||
635 | return kobj; | 634 | return kobj; |
635 | } | ||
636 | 636 | ||
637 | /* or create a new class-directory at the parent device */ | 637 | /* or create a new class-directory at the parent device */ |
638 | k = kobject_create(); | 638 | k = kobject_create(); |
639 | if (!k) | 639 | if (!k) { |
640 | mutex_unlock(&gdp_mutex); | ||
640 | return NULL; | 641 | return NULL; |
642 | } | ||
641 | k->kset = &dev->class->p->class_dirs; | 643 | k->kset = &dev->class->p->class_dirs; |
642 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); | 644 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); |
643 | if (retval < 0) { | 645 | if (retval < 0) { |
646 | mutex_unlock(&gdp_mutex); | ||
644 | kobject_put(k); | 647 | kobject_put(k); |
645 | return NULL; | 648 | return NULL; |
646 | } | 649 | } |
647 | /* do not emit an uevent for this simple "glue" directory */ | 650 | /* do not emit an uevent for this simple "glue" directory */ |
651 | mutex_unlock(&gdp_mutex); | ||
648 | return k; | 652 | return k; |
649 | } | 653 | } |
650 | 654 | ||
@@ -1574,22 +1578,16 @@ int device_rename(struct device *dev, char *new_name) | |||
1574 | if (old_class_name) { | 1578 | if (old_class_name) { |
1575 | new_class_name = make_class_name(dev->class->name, &dev->kobj); | 1579 | new_class_name = make_class_name(dev->class->name, &dev->kobj); |
1576 | if (new_class_name) { | 1580 | if (new_class_name) { |
1577 | error = sysfs_create_link_nowarn(&dev->parent->kobj, | 1581 | error = sysfs_rename_link(&dev->parent->kobj, |
1578 | &dev->kobj, | 1582 | &dev->kobj, |
1579 | new_class_name); | 1583 | old_class_name, |
1580 | if (error) | 1584 | new_class_name); |
1581 | goto out; | ||
1582 | sysfs_remove_link(&dev->parent->kobj, old_class_name); | ||
1583 | } | 1585 | } |
1584 | } | 1586 | } |
1585 | #else | 1587 | #else |
1586 | if (dev->class) { | 1588 | if (dev->class) { |
1587 | error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj, | 1589 | error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, |
1588 | &dev->kobj, dev_name(dev)); | 1590 | &dev->kobj, old_device_name, new_name); |
1589 | if (error) | ||
1590 | goto out; | ||
1591 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, | ||
1592 | old_device_name); | ||
1593 | } | 1591 | } |
1594 | #endif | 1592 | #endif |
1595 | 1593 | ||
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 958bd1540c30..7036e8e96ab8 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -13,8 +13,11 @@ | |||
13 | 13 | ||
14 | #include "base.h" | 14 | #include "base.h" |
15 | 15 | ||
16 | static struct sysdev_class_attribute *cpu_sysdev_class_attrs[]; | ||
17 | |||
16 | struct sysdev_class cpu_sysdev_class = { | 18 | struct sysdev_class cpu_sysdev_class = { |
17 | .name = "cpu", | 19 | .name = "cpu", |
20 | .attrs = cpu_sysdev_class_attrs, | ||
18 | }; | 21 | }; |
19 | EXPORT_SYMBOL(cpu_sysdev_class); | 22 | EXPORT_SYMBOL(cpu_sysdev_class); |
20 | 23 | ||
@@ -76,34 +79,24 @@ void unregister_cpu(struct cpu *cpu) | |||
76 | } | 79 | } |
77 | 80 | ||
78 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | 81 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE |
79 | static ssize_t cpu_probe_store(struct class *class, const char *buf, | 82 | static ssize_t cpu_probe_store(struct sys_device *dev, |
83 | struct sysdev_attribute *attr, | ||
84 | const char *buf, | ||
80 | size_t count) | 85 | size_t count) |
81 | { | 86 | { |
82 | return arch_cpu_probe(buf, count); | 87 | return arch_cpu_probe(buf, count); |
83 | } | 88 | } |
84 | 89 | ||
85 | static ssize_t cpu_release_store(struct class *class, const char *buf, | 90 | static ssize_t cpu_release_store(struct sys_device *dev, |
91 | struct sysdev_attribute *attr, | ||
92 | const char *buf, | ||
86 | size_t count) | 93 | size_t count) |
87 | { | 94 | { |
88 | return arch_cpu_release(buf, count); | 95 | return arch_cpu_release(buf, count); |
89 | } | 96 | } |
90 | 97 | ||
91 | static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); | 98 | static SYSDEV_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); |
92 | static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); | 99 | static SYSDEV_ATTR(release, S_IWUSR, NULL, cpu_release_store); |
93 | |||
94 | int __init cpu_probe_release_init(void) | ||
95 | { | ||
96 | int rc; | ||
97 | |||
98 | rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, | ||
99 | &class_attr_probe.attr); | ||
100 | if (!rc) | ||
101 | rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, | ||
102 | &class_attr_release.attr); | ||
103 | |||
104 | return rc; | ||
105 | } | ||
106 | device_initcall(cpu_probe_release_init); | ||
107 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | 100 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ |
108 | 101 | ||
109 | #else /* ... !CONFIG_HOTPLUG_CPU */ | 102 | #else /* ... !CONFIG_HOTPLUG_CPU */ |
@@ -141,31 +134,39 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); | |||
141 | /* | 134 | /* |
142 | * Print cpu online, possible, present, and system maps | 135 | * Print cpu online, possible, present, and system maps |
143 | */ | 136 | */ |
144 | static ssize_t print_cpus_map(char *buf, const struct cpumask *map) | 137 | |
138 | struct cpu_attr { | ||
139 | struct sysdev_class_attribute attr; | ||
140 | const struct cpumask *const * const map; | ||
141 | }; | ||
142 | |||
143 | static ssize_t show_cpus_attr(struct sysdev_class *class, | ||
144 | struct sysdev_class_attribute *attr, | ||
145 | char *buf) | ||
145 | { | 146 | { |
146 | int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map); | 147 | struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); |
148 | int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map)); | ||
147 | 149 | ||
148 | buf[n++] = '\n'; | 150 | buf[n++] = '\n'; |
149 | buf[n] = '\0'; | 151 | buf[n] = '\0'; |
150 | return n; | 152 | return n; |
151 | } | 153 | } |
152 | 154 | ||
153 | #define print_cpus_func(type) \ | 155 | #define _CPU_ATTR(name, map) \ |
154 | static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \ | 156 | { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } |
155 | { \ | ||
156 | return print_cpus_map(buf, cpu_##type##_mask); \ | ||
157 | } \ | ||
158 | static struct sysdev_class_attribute attr_##type##_map = \ | ||
159 | _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) | ||
160 | 157 | ||
161 | print_cpus_func(online); | 158 | /* Keep in sync with cpu_sysdev_class_attrs */ |
162 | print_cpus_func(possible); | 159 | static struct cpu_attr cpu_attrs[] = { |
163 | print_cpus_func(present); | 160 | _CPU_ATTR(online, &cpu_online_mask), |
161 | _CPU_ATTR(possible, &cpu_possible_mask), | ||
162 | _CPU_ATTR(present, &cpu_present_mask), | ||
163 | }; | ||
164 | 164 | ||
165 | /* | 165 | /* |
166 | * Print values for NR_CPUS and offlined cpus | 166 | * Print values for NR_CPUS and offlined cpus |
167 | */ | 167 | */ |
168 | static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf) | 168 | static ssize_t print_cpus_kernel_max(struct sysdev_class *class, |
169 | struct sysdev_class_attribute *attr, char *buf) | ||
169 | { | 170 | { |
170 | int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); | 171 | int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); |
171 | return n; | 172 | return n; |
@@ -175,7 +176,8 @@ static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); | |||
175 | /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ | 176 | /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ |
176 | unsigned int total_cpus; | 177 | unsigned int total_cpus; |
177 | 178 | ||
178 | static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf) | 179 | static ssize_t print_cpus_offline(struct sysdev_class *class, |
180 | struct sysdev_class_attribute *attr, char *buf) | ||
179 | { | 181 | { |
180 | int n = 0, len = PAGE_SIZE-2; | 182 | int n = 0, len = PAGE_SIZE-2; |
181 | cpumask_var_t offline; | 183 | cpumask_var_t offline; |
@@ -204,29 +206,6 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf) | |||
204 | } | 206 | } |
205 | static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); | 207 | static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); |
206 | 208 | ||
207 | static struct sysdev_class_attribute *cpu_state_attr[] = { | ||
208 | &attr_online_map, | ||
209 | &attr_possible_map, | ||
210 | &attr_present_map, | ||
211 | &attr_kernel_max, | ||
212 | &attr_offline, | ||
213 | }; | ||
214 | |||
215 | static int cpu_states_init(void) | ||
216 | { | ||
217 | int i; | ||
218 | int err = 0; | ||
219 | |||
220 | for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) { | ||
221 | int ret; | ||
222 | ret = sysdev_class_create_file(&cpu_sysdev_class, | ||
223 | cpu_state_attr[i]); | ||
224 | if (!err) | ||
225 | err = ret; | ||
226 | } | ||
227 | return err; | ||
228 | } | ||
229 | |||
230 | /* | 209 | /* |
231 | * register_cpu - Setup a sysfs device for a CPU. | 210 | * register_cpu - Setup a sysfs device for a CPU. |
232 | * @cpu - cpu->hotpluggable field set to 1 will generate a control file in | 211 | * @cpu - cpu->hotpluggable field set to 1 will generate a control file in |
@@ -272,9 +251,6 @@ int __init cpu_dev_init(void) | |||
272 | int err; | 251 | int err; |
273 | 252 | ||
274 | err = sysdev_class_register(&cpu_sysdev_class); | 253 | err = sysdev_class_register(&cpu_sysdev_class); |
275 | if (!err) | ||
276 | err = cpu_states_init(); | ||
277 | |||
278 | #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) | 254 | #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) |
279 | if (!err) | 255 | if (!err) |
280 | err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); | 256 | err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); |
@@ -282,3 +258,16 @@ int __init cpu_dev_init(void) | |||
282 | 258 | ||
283 | return err; | 259 | return err; |
284 | } | 260 | } |
261 | |||
262 | static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = { | ||
263 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
264 | &attr_probe, | ||
265 | &attr_release, | ||
266 | #endif | ||
267 | &cpu_attrs[0].attr, | ||
268 | &cpu_attrs[1].attr, | ||
269 | &cpu_attrs[2].attr, | ||
270 | &attr_kernel_max, | ||
271 | &attr_offline, | ||
272 | NULL | ||
273 | }; | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index ee95c76bfd3d..c89291f8a16b 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -85,7 +85,7 @@ static void driver_sysfs_remove(struct device *dev) | |||
85 | * for before calling this. (It is ok to call with no other effort | 85 | * for before calling this. (It is ok to call with no other effort |
86 | * from a driver's probe() method.) | 86 | * from a driver's probe() method.) |
87 | * | 87 | * |
88 | * This function must be called with @dev->sem held. | 88 | * This function must be called with the device lock held. |
89 | */ | 89 | */ |
90 | int device_bind_driver(struct device *dev) | 90 | int device_bind_driver(struct device *dev) |
91 | { | 91 | { |
@@ -190,8 +190,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe); | |||
190 | * This function returns -ENODEV if the device is not registered, | 190 | * This function returns -ENODEV if the device is not registered, |
191 | * 1 if the device is bound successfully and 0 otherwise. | 191 | * 1 if the device is bound successfully and 0 otherwise. |
192 | * | 192 | * |
193 | * This function must be called with @dev->sem held. When called for a | 193 | * This function must be called with @dev lock held. When called for a |
194 | * USB interface, @dev->parent->sem must be held as well. | 194 | * USB interface, @dev->parent lock must be held as well. |
195 | */ | 195 | */ |
196 | int driver_probe_device(struct device_driver *drv, struct device *dev) | 196 | int driver_probe_device(struct device_driver *drv, struct device *dev) |
197 | { | 197 | { |
@@ -233,13 +233,13 @@ static int __device_attach(struct device_driver *drv, void *data) | |||
233 | * 0 if no matching driver was found; | 233 | * 0 if no matching driver was found; |
234 | * -ENODEV if the device is not registered. | 234 | * -ENODEV if the device is not registered. |
235 | * | 235 | * |
236 | * When called for a USB interface, @dev->parent->sem must be held. | 236 | * When called for a USB interface, @dev->parent lock must be held. |
237 | */ | 237 | */ |
238 | int device_attach(struct device *dev) | 238 | int device_attach(struct device *dev) |
239 | { | 239 | { |
240 | int ret = 0; | 240 | int ret = 0; |
241 | 241 | ||
242 | down(&dev->sem); | 242 | device_lock(dev); |
243 | if (dev->driver) { | 243 | if (dev->driver) { |
244 | ret = device_bind_driver(dev); | 244 | ret = device_bind_driver(dev); |
245 | if (ret == 0) | 245 | if (ret == 0) |
@@ -253,7 +253,7 @@ int device_attach(struct device *dev) | |||
253 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); | 253 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); |
254 | pm_runtime_put_sync(dev); | 254 | pm_runtime_put_sync(dev); |
255 | } | 255 | } |
256 | up(&dev->sem); | 256 | device_unlock(dev); |
257 | return ret; | 257 | return ret; |
258 | } | 258 | } |
259 | EXPORT_SYMBOL_GPL(device_attach); | 259 | EXPORT_SYMBOL_GPL(device_attach); |
@@ -276,13 +276,13 @@ static int __driver_attach(struct device *dev, void *data) | |||
276 | return 0; | 276 | return 0; |
277 | 277 | ||
278 | if (dev->parent) /* Needed for USB */ | 278 | if (dev->parent) /* Needed for USB */ |
279 | down(&dev->parent->sem); | 279 | device_lock(dev->parent); |
280 | down(&dev->sem); | 280 | device_lock(dev); |
281 | if (!dev->driver) | 281 | if (!dev->driver) |
282 | driver_probe_device(drv, dev); | 282 | driver_probe_device(drv, dev); |
283 | up(&dev->sem); | 283 | device_unlock(dev); |
284 | if (dev->parent) | 284 | if (dev->parent) |
285 | up(&dev->parent->sem); | 285 | device_unlock(dev->parent); |
286 | 286 | ||
287 | return 0; | 287 | return 0; |
288 | } | 288 | } |
@@ -303,8 +303,8 @@ int driver_attach(struct device_driver *drv) | |||
303 | EXPORT_SYMBOL_GPL(driver_attach); | 303 | EXPORT_SYMBOL_GPL(driver_attach); |
304 | 304 | ||
305 | /* | 305 | /* |
306 | * __device_release_driver() must be called with @dev->sem held. | 306 | * __device_release_driver() must be called with @dev lock held. |
307 | * When called for a USB interface, @dev->parent->sem must be held as well. | 307 | * When called for a USB interface, @dev->parent lock must be held as well. |
308 | */ | 308 | */ |
309 | static void __device_release_driver(struct device *dev) | 309 | static void __device_release_driver(struct device *dev) |
310 | { | 310 | { |
@@ -343,7 +343,7 @@ static void __device_release_driver(struct device *dev) | |||
343 | * @dev: device. | 343 | * @dev: device. |
344 | * | 344 | * |
345 | * Manually detach device from driver. | 345 | * Manually detach device from driver. |
346 | * When called for a USB interface, @dev->parent->sem must be held. | 346 | * When called for a USB interface, @dev->parent lock must be held. |
347 | */ | 347 | */ |
348 | void device_release_driver(struct device *dev) | 348 | void device_release_driver(struct device *dev) |
349 | { | 349 | { |
@@ -352,9 +352,9 @@ void device_release_driver(struct device *dev) | |||
352 | * within their ->remove callback for the same device, they | 352 | * within their ->remove callback for the same device, they |
353 | * will deadlock right here. | 353 | * will deadlock right here. |
354 | */ | 354 | */ |
355 | down(&dev->sem); | 355 | device_lock(dev); |
356 | __device_release_driver(dev); | 356 | __device_release_driver(dev); |
357 | up(&dev->sem); | 357 | device_unlock(dev); |
358 | } | 358 | } |
359 | EXPORT_SYMBOL_GPL(device_release_driver); | 359 | EXPORT_SYMBOL_GPL(device_release_driver); |
360 | 360 | ||
@@ -381,13 +381,13 @@ void driver_detach(struct device_driver *drv) | |||
381 | spin_unlock(&drv->p->klist_devices.k_lock); | 381 | spin_unlock(&drv->p->klist_devices.k_lock); |
382 | 382 | ||
383 | if (dev->parent) /* Needed for USB */ | 383 | if (dev->parent) /* Needed for USB */ |
384 | down(&dev->parent->sem); | 384 | device_lock(dev->parent); |
385 | down(&dev->sem); | 385 | device_lock(dev); |
386 | if (dev->driver == drv) | 386 | if (dev->driver == drv) |
387 | __device_release_driver(dev); | 387 | __device_release_driver(dev); |
388 | up(&dev->sem); | 388 | device_unlock(dev); |
389 | if (dev->parent) | 389 | if (dev->parent) |
390 | up(&dev->parent->sem); | 390 | device_unlock(dev->parent); |
391 | put_device(dev); | 391 | put_device(dev); |
392 | } | 392 | } |
393 | } | 393 | } |
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 42ae452b36b0..dac478c6e460 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
@@ -301,6 +301,19 @@ int devtmpfs_delete_node(struct device *dev) | |||
301 | if (dentry->d_inode) { | 301 | if (dentry->d_inode) { |
302 | err = vfs_getattr(nd.path.mnt, dentry, &stat); | 302 | err = vfs_getattr(nd.path.mnt, dentry, &stat); |
303 | if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { | 303 | if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { |
304 | struct iattr newattrs; | ||
305 | /* | ||
306 | * before unlinking this node, reset permissions | ||
307 | * of possible references like hardlinks | ||
308 | */ | ||
309 | newattrs.ia_uid = 0; | ||
310 | newattrs.ia_gid = 0; | ||
311 | newattrs.ia_mode = stat.mode & ~0777; | ||
312 | newattrs.ia_valid = | ||
313 | ATTR_UID|ATTR_GID|ATTR_MODE; | ||
314 | mutex_lock(&dentry->d_inode->i_mutex); | ||
315 | notify_change(dentry, &newattrs); | ||
316 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
304 | err = vfs_unlink(nd.path.dentry->d_inode, | 317 | err = vfs_unlink(nd.path.dentry->d_inode, |
305 | dentry); | 318 | dentry); |
306 | if (!err || err == -ENOENT) | 319 | if (!err || err == -ENOENT) |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index a95024166b66..d0dc26ad5387 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/kthread.h> | 19 | #include <linux/kthread.h> |
20 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
21 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
22 | #include "base.h" | ||
23 | 22 | ||
24 | #define to_dev(obj) container_of(obj, struct device, kobj) | 23 | #define to_dev(obj) container_of(obj, struct device, kobj) |
25 | 24 | ||
@@ -69,7 +68,9 @@ fw_load_abort(struct firmware_priv *fw_priv) | |||
69 | } | 68 | } |
70 | 69 | ||
71 | static ssize_t | 70 | static ssize_t |
72 | firmware_timeout_show(struct class *class, char *buf) | 71 | firmware_timeout_show(struct class *class, |
72 | struct class_attribute *attr, | ||
73 | char *buf) | ||
73 | { | 74 | { |
74 | return sprintf(buf, "%d\n", loading_timeout); | 75 | return sprintf(buf, "%d\n", loading_timeout); |
75 | } | 76 | } |
@@ -87,7 +88,9 @@ firmware_timeout_show(struct class *class, char *buf) | |||
87 | * Note: zero means 'wait forever'. | 88 | * Note: zero means 'wait forever'. |
88 | **/ | 89 | **/ |
89 | static ssize_t | 90 | static ssize_t |
90 | firmware_timeout_store(struct class *class, const char *buf, size_t count) | 91 | firmware_timeout_store(struct class *class, |
92 | struct class_attribute *attr, | ||
93 | const char *buf, size_t count) | ||
91 | { | 94 | { |
92 | loading_timeout = simple_strtol(buf, NULL, 10); | 95 | loading_timeout = simple_strtol(buf, NULL, 10); |
93 | if (loading_timeout < 0) | 96 | if (loading_timeout < 0) |
@@ -610,7 +613,7 @@ request_firmware_work_func(void *arg) | |||
610 | } | 613 | } |
611 | 614 | ||
612 | /** | 615 | /** |
613 | * request_firmware_nowait: asynchronous version of request_firmware | 616 | * request_firmware_nowait - asynchronous version of request_firmware |
614 | * @module: module requesting the firmware | 617 | * @module: module requesting the firmware |
615 | * @uevent: sends uevent to copy the firmware image if this flag | 618 | * @uevent: sends uevent to copy the firmware image if this flag |
616 | * is non-zero else the firmware copy must be done manually. | 619 | * is non-zero else the firmware copy must be done manually. |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index bd025059711f..2f8691511190 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -44,7 +44,7 @@ static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uev | |||
44 | return retval; | 44 | return retval; |
45 | } | 45 | } |
46 | 46 | ||
47 | static struct kset_uevent_ops memory_uevent_ops = { | 47 | static const struct kset_uevent_ops memory_uevent_ops = { |
48 | .name = memory_uevent_name, | 48 | .name = memory_uevent_name, |
49 | .uevent = memory_uevent, | 49 | .uevent = memory_uevent, |
50 | }; | 50 | }; |
@@ -309,17 +309,18 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); | |||
309 | * Block size attribute stuff | 309 | * Block size attribute stuff |
310 | */ | 310 | */ |
311 | static ssize_t | 311 | static ssize_t |
312 | print_block_size(struct class *class, char *buf) | 312 | print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr, |
313 | char *buf) | ||
313 | { | 314 | { |
314 | return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); | 315 | return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); |
315 | } | 316 | } |
316 | 317 | ||
317 | static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); | 318 | static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); |
318 | 319 | ||
319 | static int block_size_init(void) | 320 | static int block_size_init(void) |
320 | { | 321 | { |
321 | return sysfs_create_file(&memory_sysdev_class.kset.kobj, | 322 | return sysfs_create_file(&memory_sysdev_class.kset.kobj, |
322 | &class_attr_block_size_bytes.attr); | 323 | &attr_block_size_bytes.attr); |
323 | } | 324 | } |
324 | 325 | ||
325 | /* | 326 | /* |
@@ -330,7 +331,8 @@ static int block_size_init(void) | |||
330 | */ | 331 | */ |
331 | #ifdef CONFIG_ARCH_MEMORY_PROBE | 332 | #ifdef CONFIG_ARCH_MEMORY_PROBE |
332 | static ssize_t | 333 | static ssize_t |
333 | memory_probe_store(struct class *class, const char *buf, size_t count) | 334 | memory_probe_store(struct class *class, struct class_attribute *attr, |
335 | const char *buf, size_t count) | ||
334 | { | 336 | { |
335 | u64 phys_addr; | 337 | u64 phys_addr; |
336 | int nid; | 338 | int nid; |
@@ -367,7 +369,9 @@ static inline int memory_probe_init(void) | |||
367 | 369 | ||
368 | /* Soft offline a page */ | 370 | /* Soft offline a page */ |
369 | static ssize_t | 371 | static ssize_t |
370 | store_soft_offline_page(struct class *class, const char *buf, size_t count) | 372 | store_soft_offline_page(struct class *class, |
373 | struct class_attribute *attr, | ||
374 | const char *buf, size_t count) | ||
371 | { | 375 | { |
372 | int ret; | 376 | int ret; |
373 | u64 pfn; | 377 | u64 pfn; |
@@ -384,7 +388,9 @@ store_soft_offline_page(struct class *class, const char *buf, size_t count) | |||
384 | 388 | ||
385 | /* Forcibly offline a page, including killing processes. */ | 389 | /* Forcibly offline a page, including killing processes. */ |
386 | static ssize_t | 390 | static ssize_t |
387 | store_hard_offline_page(struct class *class, const char *buf, size_t count) | 391 | store_hard_offline_page(struct class *class, |
392 | struct class_attribute *attr, | ||
393 | const char *buf, size_t count) | ||
388 | { | 394 | { |
389 | int ret; | 395 | int ret; |
390 | u64 pfn; | 396 | u64 pfn; |
diff --git a/drivers/base/node.c b/drivers/base/node.c index 70122791683d..ad43185ec15a 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -16,8 +16,11 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/swap.h> | 17 | #include <linux/swap.h> |
18 | 18 | ||
19 | static struct sysdev_class_attribute *node_state_attrs[]; | ||
20 | |||
19 | static struct sysdev_class node_class = { | 21 | static struct sysdev_class node_class = { |
20 | .name = "node", | 22 | .name = "node", |
23 | .attrs = node_state_attrs, | ||
21 | }; | 24 | }; |
22 | 25 | ||
23 | 26 | ||
@@ -544,76 +547,52 @@ static ssize_t print_nodes_state(enum node_states state, char *buf) | |||
544 | return n; | 547 | return n; |
545 | } | 548 | } |
546 | 549 | ||
547 | static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf) | 550 | struct node_attr { |
548 | { | 551 | struct sysdev_class_attribute attr; |
549 | return print_nodes_state(N_POSSIBLE, buf); | 552 | enum node_states state; |
550 | } | 553 | }; |
551 | |||
552 | static ssize_t print_nodes_online(struct sysdev_class *class, char *buf) | ||
553 | { | ||
554 | return print_nodes_state(N_ONLINE, buf); | ||
555 | } | ||
556 | |||
557 | static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class, | ||
558 | char *buf) | ||
559 | { | ||
560 | return print_nodes_state(N_NORMAL_MEMORY, buf); | ||
561 | } | ||
562 | 554 | ||
563 | static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf) | 555 | static ssize_t show_node_state(struct sysdev_class *class, |
556 | struct sysdev_class_attribute *attr, char *buf) | ||
564 | { | 557 | { |
565 | return print_nodes_state(N_CPU, buf); | 558 | struct node_attr *na = container_of(attr, struct node_attr, attr); |
559 | return print_nodes_state(na->state, buf); | ||
566 | } | 560 | } |
567 | 561 | ||
568 | static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL); | 562 | #define _NODE_ATTR(name, state) \ |
569 | static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL); | 563 | { _SYSDEV_CLASS_ATTR(name, 0444, show_node_state, NULL), state } |
570 | static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory, | ||
571 | NULL); | ||
572 | static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL); | ||
573 | 564 | ||
565 | static struct node_attr node_state_attr[] = { | ||
566 | _NODE_ATTR(possible, N_POSSIBLE), | ||
567 | _NODE_ATTR(online, N_ONLINE), | ||
568 | _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY), | ||
569 | _NODE_ATTR(has_cpu, N_CPU), | ||
574 | #ifdef CONFIG_HIGHMEM | 570 | #ifdef CONFIG_HIGHMEM |
575 | static ssize_t print_nodes_has_high_memory(struct sysdev_class *class, | 571 | _NODE_ATTR(has_high_memory, N_HIGH_MEMORY), |
576 | char *buf) | ||
577 | { | ||
578 | return print_nodes_state(N_HIGH_MEMORY, buf); | ||
579 | } | ||
580 | |||
581 | static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory, | ||
582 | NULL); | ||
583 | #endif | 572 | #endif |
573 | }; | ||
584 | 574 | ||
585 | struct sysdev_class_attribute *node_state_attr[] = { | 575 | static struct sysdev_class_attribute *node_state_attrs[] = { |
586 | &attr_possible, | 576 | &node_state_attr[0].attr, |
587 | &attr_online, | 577 | &node_state_attr[1].attr, |
588 | &attr_has_normal_memory, | 578 | &node_state_attr[2].attr, |
579 | &node_state_attr[3].attr, | ||
589 | #ifdef CONFIG_HIGHMEM | 580 | #ifdef CONFIG_HIGHMEM |
590 | &attr_has_high_memory, | 581 | &node_state_attr[4].attr, |
591 | #endif | 582 | #endif |
592 | &attr_has_cpu, | 583 | NULL |
593 | }; | 584 | }; |
594 | 585 | ||
595 | static int node_states_init(void) | ||
596 | { | ||
597 | int i; | ||
598 | int err = 0; | ||
599 | |||
600 | for (i = 0; i < NR_NODE_STATES; i++) { | ||
601 | int ret; | ||
602 | ret = sysdev_class_create_file(&node_class, node_state_attr[i]); | ||
603 | if (!err) | ||
604 | err = ret; | ||
605 | } | ||
606 | return err; | ||
607 | } | ||
608 | |||
609 | #define NODE_CALLBACK_PRI 2 /* lower than SLAB */ | 586 | #define NODE_CALLBACK_PRI 2 /* lower than SLAB */ |
610 | static int __init register_node_type(void) | 587 | static int __init register_node_type(void) |
611 | { | 588 | { |
612 | int ret; | 589 | int ret; |
613 | 590 | ||
591 | BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES); | ||
592 | BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES); | ||
593 | |||
614 | ret = sysdev_class_register(&node_class); | 594 | ret = sysdev_class_register(&node_class); |
615 | if (!ret) { | 595 | if (!ret) { |
616 | ret = node_states_init(); | ||
617 | hotplug_memory_notifier(node_memory_callback, | 596 | hotplug_memory_notifier(node_memory_callback, |
618 | NODE_CALLBACK_PRI); | 597 | NODE_CALLBACK_PRI); |
619 | } | 598 | } |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 58efaf2f1259..1ba9d617d241 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -128,7 +128,7 @@ struct platform_object { | |||
128 | }; | 128 | }; |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * platform_device_put | 131 | * platform_device_put - destroy a platform device |
132 | * @pdev: platform device to free | 132 | * @pdev: platform device to free |
133 | * | 133 | * |
134 | * Free all memory associated with a platform device. This function must | 134 | * Free all memory associated with a platform device. This function must |
@@ -152,7 +152,7 @@ static void platform_device_release(struct device *dev) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | /** | 154 | /** |
155 | * platform_device_alloc | 155 | * platform_device_alloc - create a platform device |
156 | * @name: base name of the device we're adding | 156 | * @name: base name of the device we're adding |
157 | * @id: instance id | 157 | * @id: instance id |
158 | * | 158 | * |
@@ -177,7 +177,7 @@ struct platform_device *platform_device_alloc(const char *name, int id) | |||
177 | EXPORT_SYMBOL_GPL(platform_device_alloc); | 177 | EXPORT_SYMBOL_GPL(platform_device_alloc); |
178 | 178 | ||
179 | /** | 179 | /** |
180 | * platform_device_add_resources | 180 | * platform_device_add_resources - add resources to a platform device |
181 | * @pdev: platform device allocated by platform_device_alloc to add resources to | 181 | * @pdev: platform device allocated by platform_device_alloc to add resources to |
182 | * @res: set of resources that needs to be allocated for the device | 182 | * @res: set of resources that needs to be allocated for the device |
183 | * @num: number of resources | 183 | * @num: number of resources |
@@ -202,7 +202,7 @@ int platform_device_add_resources(struct platform_device *pdev, | |||
202 | EXPORT_SYMBOL_GPL(platform_device_add_resources); | 202 | EXPORT_SYMBOL_GPL(platform_device_add_resources); |
203 | 203 | ||
204 | /** | 204 | /** |
205 | * platform_device_add_data | 205 | * platform_device_add_data - add platform-specific data to a platform device |
206 | * @pdev: platform device allocated by platform_device_alloc to add resources to | 206 | * @pdev: platform device allocated by platform_device_alloc to add resources to |
207 | * @data: platform specific data for this platform device | 207 | * @data: platform specific data for this platform device |
208 | * @size: size of platform specific data | 208 | * @size: size of platform specific data |
@@ -344,7 +344,7 @@ void platform_device_unregister(struct platform_device *pdev) | |||
344 | EXPORT_SYMBOL_GPL(platform_device_unregister); | 344 | EXPORT_SYMBOL_GPL(platform_device_unregister); |
345 | 345 | ||
346 | /** | 346 | /** |
347 | * platform_device_register_simple | 347 | * platform_device_register_simple - add a platform-level device and its resources |
348 | * @name: base name of the device we're adding | 348 | * @name: base name of the device we're adding |
349 | * @id: instance id | 349 | * @id: instance id |
350 | * @res: set of resources that needs to be allocated for the device | 350 | * @res: set of resources that needs to be allocated for the device |
@@ -396,7 +396,7 @@ error: | |||
396 | EXPORT_SYMBOL_GPL(platform_device_register_simple); | 396 | EXPORT_SYMBOL_GPL(platform_device_register_simple); |
397 | 397 | ||
398 | /** | 398 | /** |
399 | * platform_device_register_data | 399 | * platform_device_register_data - add a platform-level device with platform-specific data |
400 | * @parent: parent device for the device we're adding | 400 | * @parent: parent device for the device we're adding |
401 | * @name: base name of the device we're adding | 401 | * @name: base name of the device we're adding |
402 | * @id: instance id | 402 | * @id: instance id |
@@ -473,7 +473,7 @@ static void platform_drv_shutdown(struct device *_dev) | |||
473 | } | 473 | } |
474 | 474 | ||
475 | /** | 475 | /** |
476 | * platform_driver_register | 476 | * platform_driver_register - register a driver for platform-level devices |
477 | * @drv: platform driver structure | 477 | * @drv: platform driver structure |
478 | */ | 478 | */ |
479 | int platform_driver_register(struct platform_driver *drv) | 479 | int platform_driver_register(struct platform_driver *drv) |
@@ -491,7 +491,7 @@ int platform_driver_register(struct platform_driver *drv) | |||
491 | EXPORT_SYMBOL_GPL(platform_driver_register); | 491 | EXPORT_SYMBOL_GPL(platform_driver_register); |
492 | 492 | ||
493 | /** | 493 | /** |
494 | * platform_driver_unregister | 494 | * platform_driver_unregister - unregister a driver for platform-level devices |
495 | * @drv: platform driver structure | 495 | * @drv: platform driver structure |
496 | */ | 496 | */ |
497 | void platform_driver_unregister(struct platform_driver *drv) | 497 | void platform_driver_unregister(struct platform_driver *drv) |
@@ -548,6 +548,64 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, | |||
548 | } | 548 | } |
549 | EXPORT_SYMBOL_GPL(platform_driver_probe); | 549 | EXPORT_SYMBOL_GPL(platform_driver_probe); |
550 | 550 | ||
551 | /** | ||
552 | * platform_create_bundle - register driver and create corresponding device | ||
553 | * @driver: platform driver structure | ||
554 | * @probe: the driver probe routine, probably from an __init section | ||
555 | * @res: set of resources that needs to be allocated for the device | ||
556 | * @n_res: number of resources | ||
557 | * @data: platform specific data for this platform device | ||
558 | * @size: size of platform specific data | ||
559 | * | ||
560 | * Use this in legacy-style modules that probe hardware directly and | ||
561 | * register a single platform device and corresponding platform driver. | ||
562 | */ | ||
563 | struct platform_device * __init_or_module platform_create_bundle( | ||
564 | struct platform_driver *driver, | ||
565 | int (*probe)(struct platform_device *), | ||
566 | struct resource *res, unsigned int n_res, | ||
567 | const void *data, size_t size) | ||
568 | { | ||
569 | struct platform_device *pdev; | ||
570 | int error; | ||
571 | |||
572 | pdev = platform_device_alloc(driver->driver.name, -1); | ||
573 | if (!pdev) { | ||
574 | error = -ENOMEM; | ||
575 | goto err_out; | ||
576 | } | ||
577 | |||
578 | if (res) { | ||
579 | error = platform_device_add_resources(pdev, res, n_res); | ||
580 | if (error) | ||
581 | goto err_pdev_put; | ||
582 | } | ||
583 | |||
584 | if (data) { | ||
585 | error = platform_device_add_data(pdev, data, size); | ||
586 | if (error) | ||
587 | goto err_pdev_put; | ||
588 | } | ||
589 | |||
590 | error = platform_device_add(pdev); | ||
591 | if (error) | ||
592 | goto err_pdev_put; | ||
593 | |||
594 | error = platform_driver_probe(driver, probe); | ||
595 | if (error) | ||
596 | goto err_pdev_del; | ||
597 | |||
598 | return pdev; | ||
599 | |||
600 | err_pdev_del: | ||
601 | platform_device_del(pdev); | ||
602 | err_pdev_put: | ||
603 | platform_device_put(pdev); | ||
604 | err_out: | ||
605 | return ERR_PTR(error); | ||
606 | } | ||
607 | EXPORT_SYMBOL_GPL(platform_create_bundle); | ||
608 | |||
551 | /* modalias support enables more hands-off userspace setup: | 609 | /* modalias support enables more hands-off userspace setup: |
552 | * (a) environment variable lets new-style hotplug events work once system is | 610 | * (a) environment variable lets new-style hotplug events work once system is |
553 | * fully running: "modprobe $MODALIAS" | 611 | * fully running: "modprobe $MODALIAS" |
@@ -578,7 +636,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
578 | } | 636 | } |
579 | 637 | ||
580 | static const struct platform_device_id *platform_match_id( | 638 | static const struct platform_device_id *platform_match_id( |
581 | struct platform_device_id *id, | 639 | const struct platform_device_id *id, |
582 | struct platform_device *pdev) | 640 | struct platform_device *pdev) |
583 | { | 641 | { |
584 | while (id->name[0]) { | 642 | while (id->name[0]) { |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 0e26a6f6fd48..d477f4dc5e51 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -35,8 +35,8 @@ | |||
35 | * because children are guaranteed to be discovered after parents, and | 35 | * because children are guaranteed to be discovered after parents, and |
36 | * are inserted at the back of the list on discovery. | 36 | * are inserted at the back of the list on discovery. |
37 | * | 37 | * |
38 | * Since device_pm_add() may be called with a device semaphore held, | 38 | * Since device_pm_add() may be called with a device lock held, |
39 | * we must never try to acquire a device semaphore while holding | 39 | * we must never try to acquire a device lock while holding |
40 | * dpm_list_mutex. | 40 | * dpm_list_mutex. |
41 | */ | 41 | */ |
42 | 42 | ||
@@ -508,7 +508,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
508 | TRACE_RESUME(0); | 508 | TRACE_RESUME(0); |
509 | 509 | ||
510 | dpm_wait(dev->parent, async); | 510 | dpm_wait(dev->parent, async); |
511 | down(&dev->sem); | 511 | device_lock(dev); |
512 | 512 | ||
513 | dev->power.status = DPM_RESUMING; | 513 | dev->power.status = DPM_RESUMING; |
514 | 514 | ||
@@ -543,7 +543,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
543 | } | 543 | } |
544 | } | 544 | } |
545 | End: | 545 | End: |
546 | up(&dev->sem); | 546 | device_unlock(dev); |
547 | complete_all(&dev->power.completion); | 547 | complete_all(&dev->power.completion); |
548 | 548 | ||
549 | TRACE_RESUME(error); | 549 | TRACE_RESUME(error); |
@@ -629,7 +629,7 @@ static void dpm_resume(pm_message_t state) | |||
629 | */ | 629 | */ |
630 | static void device_complete(struct device *dev, pm_message_t state) | 630 | static void device_complete(struct device *dev, pm_message_t state) |
631 | { | 631 | { |
632 | down(&dev->sem); | 632 | device_lock(dev); |
633 | 633 | ||
634 | if (dev->class && dev->class->pm && dev->class->pm->complete) { | 634 | if (dev->class && dev->class->pm && dev->class->pm->complete) { |
635 | pm_dev_dbg(dev, state, "completing class "); | 635 | pm_dev_dbg(dev, state, "completing class "); |
@@ -646,7 +646,7 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
646 | dev->bus->pm->complete(dev); | 646 | dev->bus->pm->complete(dev); |
647 | } | 647 | } |
648 | 648 | ||
649 | up(&dev->sem); | 649 | device_unlock(dev); |
650 | } | 650 | } |
651 | 651 | ||
652 | /** | 652 | /** |
@@ -809,7 +809,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
809 | int error = 0; | 809 | int error = 0; |
810 | 810 | ||
811 | dpm_wait_for_children(dev, async); | 811 | dpm_wait_for_children(dev, async); |
812 | down(&dev->sem); | 812 | device_lock(dev); |
813 | 813 | ||
814 | if (async_error) | 814 | if (async_error) |
815 | goto End; | 815 | goto End; |
@@ -849,7 +849,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
849 | dev->power.status = DPM_OFF; | 849 | dev->power.status = DPM_OFF; |
850 | 850 | ||
851 | End: | 851 | End: |
852 | up(&dev->sem); | 852 | device_unlock(dev); |
853 | complete_all(&dev->power.completion); | 853 | complete_all(&dev->power.completion); |
854 | 854 | ||
855 | return error; | 855 | return error; |
@@ -938,7 +938,7 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
938 | { | 938 | { |
939 | int error = 0; | 939 | int error = 0; |
940 | 940 | ||
941 | down(&dev->sem); | 941 | device_lock(dev); |
942 | 942 | ||
943 | if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) { | 943 | if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) { |
944 | pm_dev_dbg(dev, state, "preparing "); | 944 | pm_dev_dbg(dev, state, "preparing "); |
@@ -962,7 +962,7 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
962 | suspend_report_result(dev->class->pm->prepare, error); | 962 | suspend_report_result(dev->class->pm->prepare, error); |
963 | } | 963 | } |
964 | End: | 964 | End: |
965 | up(&dev->sem); | 965 | device_unlock(dev); |
966 | 966 | ||
967 | return error; | 967 | return error; |
968 | } | 968 | } |
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 0d903909af7e..8980feec5d14 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
@@ -54,7 +54,7 @@ sysdev_store(struct kobject *kobj, struct attribute *attr, | |||
54 | return -EIO; | 54 | return -EIO; |
55 | } | 55 | } |
56 | 56 | ||
57 | static struct sysfs_ops sysfs_ops = { | 57 | static const struct sysfs_ops sysfs_ops = { |
58 | .show = sysdev_show, | 58 | .show = sysdev_show, |
59 | .store = sysdev_store, | 59 | .store = sysdev_store, |
60 | }; | 60 | }; |
@@ -89,7 +89,7 @@ static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, | |||
89 | struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); | 89 | struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); |
90 | 90 | ||
91 | if (class_attr->show) | 91 | if (class_attr->show) |
92 | return class_attr->show(class, buffer); | 92 | return class_attr->show(class, class_attr, buffer); |
93 | return -EIO; | 93 | return -EIO; |
94 | } | 94 | } |
95 | 95 | ||
@@ -100,11 +100,11 @@ static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, | |||
100 | struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); | 100 | struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); |
101 | 101 | ||
102 | if (class_attr->store) | 102 | if (class_attr->store) |
103 | return class_attr->store(class, buffer, count); | 103 | return class_attr->store(class, class_attr, buffer, count); |
104 | return -EIO; | 104 | return -EIO; |
105 | } | 105 | } |
106 | 106 | ||
107 | static struct sysfs_ops sysfs_class_ops = { | 107 | static const struct sysfs_ops sysfs_class_ops = { |
108 | .show = sysdev_class_show, | 108 | .show = sysdev_class_show, |
109 | .store = sysdev_class_store, | 109 | .store = sysdev_class_store, |
110 | }; | 110 | }; |
@@ -145,13 +145,20 @@ int sysdev_class_register(struct sysdev_class *cls) | |||
145 | if (retval) | 145 | if (retval) |
146 | return retval; | 146 | return retval; |
147 | 147 | ||
148 | return kset_register(&cls->kset); | 148 | retval = kset_register(&cls->kset); |
149 | if (!retval && cls->attrs) | ||
150 | retval = sysfs_create_files(&cls->kset.kobj, | ||
151 | (const struct attribute **)cls->attrs); | ||
152 | return retval; | ||
149 | } | 153 | } |
150 | 154 | ||
151 | void sysdev_class_unregister(struct sysdev_class *cls) | 155 | void sysdev_class_unregister(struct sysdev_class *cls) |
152 | { | 156 | { |
153 | pr_debug("Unregistering sysdev class '%s'\n", | 157 | pr_debug("Unregistering sysdev class '%s'\n", |
154 | kobject_name(&cls->kset.kobj)); | 158 | kobject_name(&cls->kset.kobj)); |
159 | if (cls->attrs) | ||
160 | sysfs_remove_files(&cls->kset.kobj, | ||
161 | (const struct attribute **)cls->attrs); | ||
155 | kset_unregister(&cls->kset); | 162 | kset_unregister(&cls->kset); |
156 | } | 163 | } |
157 | 164 | ||
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b9b117059b62..90c4038702da 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -144,13 +144,23 @@ | |||
144 | * Better audit of register_blkdev. | 144 | * Better audit of register_blkdev. |
145 | */ | 145 | */ |
146 | 146 | ||
147 | #define FLOPPY_SANITY_CHECK | ||
148 | #undef FLOPPY_SILENT_DCL_CLEAR | 147 | #undef FLOPPY_SILENT_DCL_CLEAR |
149 | 148 | ||
150 | #define REALLY_SLOW_IO | 149 | #define REALLY_SLOW_IO |
151 | 150 | ||
152 | #define DEBUGT 2 | 151 | #define DEBUGT 2 |
153 | #define DCL_DEBUG /* debug disk change line */ | 152 | |
153 | #define DPRINT(format, args...) \ | ||
154 | pr_info("floppy%d: " format, current_drive, ##args) | ||
155 | |||
156 | #define DCL_DEBUG /* debug disk change line */ | ||
157 | #ifdef DCL_DEBUG | ||
158 | #define debug_dcl(test, fmt, args...) \ | ||
159 | do { if ((test) & FD_DEBUG) DPRINT(fmt, ##args); } while (0) | ||
160 | #else | ||
161 | #define debug_dcl(test, fmt, args...) \ | ||
162 | do { if (0) DPRINT(fmt, ##args); } while (0) | ||
163 | #endif | ||
154 | 164 | ||
155 | /* do print messages for unexpected interrupts */ | 165 | /* do print messages for unexpected interrupts */ |
156 | static int print_unex = 1; | 166 | static int print_unex = 1; |
@@ -180,6 +190,8 @@ static int print_unex = 1; | |||
180 | #include <linux/mod_devicetable.h> | 190 | #include <linux/mod_devicetable.h> |
181 | #include <linux/buffer_head.h> /* for invalidate_buffers() */ | 191 | #include <linux/buffer_head.h> /* for invalidate_buffers() */ |
182 | #include <linux/mutex.h> | 192 | #include <linux/mutex.h> |
193 | #include <linux/io.h> | ||
194 | #include <linux/uaccess.h> | ||
183 | 195 | ||
184 | /* | 196 | /* |
185 | * PS/2 floppies have much slower step rates than regular floppies. | 197 | * PS/2 floppies have much slower step rates than regular floppies. |
@@ -191,8 +203,6 @@ static int slow_floppy; | |||
191 | #include <asm/dma.h> | 203 | #include <asm/dma.h> |
192 | #include <asm/irq.h> | 204 | #include <asm/irq.h> |
193 | #include <asm/system.h> | 205 | #include <asm/system.h> |
194 | #include <asm/io.h> | ||
195 | #include <asm/uaccess.h> | ||
196 | 206 | ||
197 | static int FLOPPY_IRQ = 6; | 207 | static int FLOPPY_IRQ = 6; |
198 | static int FLOPPY_DMA = 2; | 208 | static int FLOPPY_DMA = 2; |
@@ -241,8 +251,6 @@ static int allowed_drive_mask = 0x33; | |||
241 | 251 | ||
242 | static int irqdma_allocated; | 252 | static int irqdma_allocated; |
243 | 253 | ||
244 | #define DEVICE_NAME "floppy" | ||
245 | |||
246 | #include <linux/blkdev.h> | 254 | #include <linux/blkdev.h> |
247 | #include <linux/blkpg.h> | 255 | #include <linux/blkpg.h> |
248 | #include <linux/cdrom.h> /* for the compatibility eject ioctl */ | 256 | #include <linux/cdrom.h> /* for the compatibility eject ioctl */ |
@@ -250,7 +258,7 @@ static int irqdma_allocated; | |||
250 | 258 | ||
251 | static struct request *current_req; | 259 | static struct request *current_req; |
252 | static struct request_queue *floppy_queue; | 260 | static struct request_queue *floppy_queue; |
253 | static void do_fd_request(struct request_queue * q); | 261 | static void do_fd_request(struct request_queue *q); |
254 | 262 | ||
255 | #ifndef fd_get_dma_residue | 263 | #ifndef fd_get_dma_residue |
256 | #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) | 264 | #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) |
@@ -263,7 +271,7 @@ static void do_fd_request(struct request_queue * q); | |||
263 | #endif | 271 | #endif |
264 | 272 | ||
265 | #ifndef fd_dma_mem_alloc | 273 | #ifndef fd_dma_mem_alloc |
266 | #define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size)) | 274 | #define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL, get_order(size)) |
267 | #endif | 275 | #endif |
268 | 276 | ||
269 | static inline void fallback_on_nodma_alloc(char **addr, size_t l) | 277 | static inline void fallback_on_nodma_alloc(char **addr, size_t l) |
@@ -273,7 +281,7 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) | |||
273 | return; /* we have the memory */ | 281 | return; /* we have the memory */ |
274 | if (can_use_virtual_dma != 2) | 282 | if (can_use_virtual_dma != 2) |
275 | return; /* no fallback allowed */ | 283 | return; /* no fallback allowed */ |
276 | printk("DMA memory shortage. Temporarily falling back on virtual DMA\n"); | 284 | pr_info("DMA memory shortage. Temporarily falling back on virtual DMA\n"); |
277 | *addr = (char *)nodma_mem_alloc(l); | 285 | *addr = (char *)nodma_mem_alloc(l); |
278 | #else | 286 | #else |
279 | return; | 287 | return; |
@@ -283,59 +291,50 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) | |||
283 | /* End dma memory related stuff */ | 291 | /* End dma memory related stuff */ |
284 | 292 | ||
285 | static unsigned long fake_change; | 293 | static unsigned long fake_change; |
286 | static int initialising = 1; | 294 | static bool initialized; |
287 | 295 | ||
288 | #define ITYPE(x) (((x)>>2) & 0x1f) | 296 | #define ITYPE(x) (((x) >> 2) & 0x1f) |
289 | #define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) | 297 | #define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) |
290 | #define UNIT(x) ((x) & 0x03) /* drive on fdc */ | 298 | #define UNIT(x) ((x) & 0x03) /* drive on fdc */ |
291 | #define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ | 299 | #define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ |
292 | /* reverse mapping from unit and fdc to drive */ | 300 | /* reverse mapping from unit and fdc to drive */ |
293 | #define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) | 301 | #define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) |
294 | #define DP (&drive_params[current_drive]) | ||
295 | #define DRS (&drive_state[current_drive]) | ||
296 | #define DRWE (&write_errors[current_drive]) | ||
297 | #define FDCS (&fdc_state[fdc]) | ||
298 | #define CLEARF(x) clear_bit(x##_BIT, &DRS->flags) | ||
299 | #define SETF(x) set_bit(x##_BIT, &DRS->flags) | ||
300 | #define TESTF(x) test_bit(x##_BIT, &DRS->flags) | ||
301 | 302 | ||
302 | #define UDP (&drive_params[drive]) | 303 | #define DP (&drive_params[current_drive]) |
303 | #define UDRS (&drive_state[drive]) | 304 | #define DRS (&drive_state[current_drive]) |
304 | #define UDRWE (&write_errors[drive]) | 305 | #define DRWE (&write_errors[current_drive]) |
305 | #define UFDCS (&fdc_state[FDC(drive)]) | 306 | #define FDCS (&fdc_state[fdc]) |
306 | #define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags) | ||
307 | #define USETF(x) set_bit(x##_BIT, &UDRS->flags) | ||
308 | #define UTESTF(x) test_bit(x##_BIT, &UDRS->flags) | ||
309 | 307 | ||
310 | #define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args) | 308 | #define UDP (&drive_params[drive]) |
309 | #define UDRS (&drive_state[drive]) | ||
310 | #define UDRWE (&write_errors[drive]) | ||
311 | #define UFDCS (&fdc_state[FDC(drive)]) | ||
311 | 312 | ||
312 | #define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2) | 313 | #define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2) |
313 | #define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) | 314 | #define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) |
314 | |||
315 | #define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x))) | ||
316 | 315 | ||
317 | /* read/write */ | 316 | /* read/write */ |
318 | #define COMMAND raw_cmd->cmd[0] | 317 | #define COMMAND (raw_cmd->cmd[0]) |
319 | #define DR_SELECT raw_cmd->cmd[1] | 318 | #define DR_SELECT (raw_cmd->cmd[1]) |
320 | #define TRACK raw_cmd->cmd[2] | 319 | #define TRACK (raw_cmd->cmd[2]) |
321 | #define HEAD raw_cmd->cmd[3] | 320 | #define HEAD (raw_cmd->cmd[3]) |
322 | #define SECTOR raw_cmd->cmd[4] | 321 | #define SECTOR (raw_cmd->cmd[4]) |
323 | #define SIZECODE raw_cmd->cmd[5] | 322 | #define SIZECODE (raw_cmd->cmd[5]) |
324 | #define SECT_PER_TRACK raw_cmd->cmd[6] | 323 | #define SECT_PER_TRACK (raw_cmd->cmd[6]) |
325 | #define GAP raw_cmd->cmd[7] | 324 | #define GAP (raw_cmd->cmd[7]) |
326 | #define SIZECODE2 raw_cmd->cmd[8] | 325 | #define SIZECODE2 (raw_cmd->cmd[8]) |
327 | #define NR_RW 9 | 326 | #define NR_RW 9 |
328 | 327 | ||
329 | /* format */ | 328 | /* format */ |
330 | #define F_SIZECODE raw_cmd->cmd[2] | 329 | #define F_SIZECODE (raw_cmd->cmd[2]) |
331 | #define F_SECT_PER_TRACK raw_cmd->cmd[3] | 330 | #define F_SECT_PER_TRACK (raw_cmd->cmd[3]) |
332 | #define F_GAP raw_cmd->cmd[4] | 331 | #define F_GAP (raw_cmd->cmd[4]) |
333 | #define F_FILL raw_cmd->cmd[5] | 332 | #define F_FILL (raw_cmd->cmd[5]) |
334 | #define NR_F 6 | 333 | #define NR_F 6 |
335 | 334 | ||
336 | /* | 335 | /* |
337 | * Maximum disk size (in kilobytes). This default is used whenever the | 336 | * Maximum disk size (in kilobytes). |
338 | * current disk size is unknown. | 337 | * This default is used whenever the current disk size is unknown. |
339 | * [Now it is rather a minimum] | 338 | * [Now it is rather a minimum] |
340 | */ | 339 | */ |
341 | #define MAX_DISK_SIZE 4 /* 3984 */ | 340 | #define MAX_DISK_SIZE 4 /* 3984 */ |
@@ -345,16 +344,17 @@ static int initialising = 1; | |||
345 | */ | 344 | */ |
346 | #define MAX_REPLIES 16 | 345 | #define MAX_REPLIES 16 |
347 | static unsigned char reply_buffer[MAX_REPLIES]; | 346 | static unsigned char reply_buffer[MAX_REPLIES]; |
348 | static int inr; /* size of reply buffer, when called from interrupt */ | 347 | static int inr; /* size of reply buffer, when called from interrupt */ |
349 | #define ST0 (reply_buffer[0]) | 348 | #define ST0 (reply_buffer[0]) |
350 | #define ST1 (reply_buffer[1]) | 349 | #define ST1 (reply_buffer[1]) |
351 | #define ST2 (reply_buffer[2]) | 350 | #define ST2 (reply_buffer[2]) |
352 | #define ST3 (reply_buffer[0]) /* result of GETSTATUS */ | 351 | #define ST3 (reply_buffer[0]) /* result of GETSTATUS */ |
353 | #define R_TRACK (reply_buffer[3]) | 352 | #define R_TRACK (reply_buffer[3]) |
354 | #define R_HEAD (reply_buffer[4]) | 353 | #define R_HEAD (reply_buffer[4]) |
355 | #define R_SECTOR (reply_buffer[5]) | 354 | #define R_SECTOR (reply_buffer[5]) |
356 | #define R_SIZECODE (reply_buffer[6]) | 355 | #define R_SIZECODE (reply_buffer[6]) |
357 | #define SEL_DLY (2*HZ/100) | 356 | |
357 | #define SEL_DLY (2 * HZ / 100) | ||
358 | 358 | ||
359 | /* | 359 | /* |
360 | * this struct defines the different floppy drive types. | 360 | * this struct defines the different floppy drive types. |
@@ -505,9 +505,9 @@ static char floppy_device_name[] = "floppy"; | |||
505 | static int probing; | 505 | static int probing; |
506 | 506 | ||
507 | /* Synchronization of FDC access. */ | 507 | /* Synchronization of FDC access. */ |
508 | #define FD_COMMAND_NONE -1 | 508 | #define FD_COMMAND_NONE -1 |
509 | #define FD_COMMAND_ERROR 2 | 509 | #define FD_COMMAND_ERROR 2 |
510 | #define FD_COMMAND_OKAY 3 | 510 | #define FD_COMMAND_OKAY 3 |
511 | 511 | ||
512 | static volatile int command_status = FD_COMMAND_NONE; | 512 | static volatile int command_status = FD_COMMAND_NONE; |
513 | static unsigned long fdc_busy; | 513 | static unsigned long fdc_busy; |
@@ -515,11 +515,6 @@ static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); | |||
515 | static DECLARE_WAIT_QUEUE_HEAD(command_done); | 515 | static DECLARE_WAIT_QUEUE_HEAD(command_done); |
516 | 516 | ||
517 | #define NO_SIGNAL (!interruptible || !signal_pending(current)) | 517 | #define NO_SIGNAL (!interruptible || !signal_pending(current)) |
518 | #define CALL(x) if ((x) == -EINTR) return -EINTR | ||
519 | #define ECALL(x) if ((ret = (x))) return ret; | ||
520 | #define _WAIT(x,i) CALL(ret=wait_til_done((x),i)) | ||
521 | #define WAIT(x) _WAIT((x),interruptible) | ||
522 | #define IWAIT(x) _WAIT((x),1) | ||
523 | 518 | ||
524 | /* Errors during formatting are counted here. */ | 519 | /* Errors during formatting are counted here. */ |
525 | static int format_errors; | 520 | static int format_errors; |
@@ -545,8 +540,9 @@ static int max_buffer_sectors; | |||
545 | static int *errors; | 540 | static int *errors; |
546 | typedef void (*done_f)(int); | 541 | typedef void (*done_f)(int); |
547 | static struct cont_t { | 542 | static struct cont_t { |
548 | void (*interrupt)(void); /* this is called after the interrupt of the | 543 | void (*interrupt)(void); |
549 | * main command */ | 544 | /* this is called after the interrupt of the |
545 | * main command */ | ||
550 | void (*redo)(void); /* this is called to retry the operation */ | 546 | void (*redo)(void); /* this is called to retry the operation */ |
551 | void (*error)(void); /* this is called to tally an error */ | 547 | void (*error)(void); /* this is called to tally an error */ |
552 | done_f done; /* this is called to say if the operation has | 548 | done_f done; /* this is called to say if the operation has |
@@ -571,7 +567,6 @@ static void floppy_release_irq_and_dma(void); | |||
571 | * reset doesn't need to be tested before sending commands, because | 567 | * reset doesn't need to be tested before sending commands, because |
572 | * output_byte is automatically disabled when reset is set. | 568 | * output_byte is automatically disabled when reset is set. |
573 | */ | 569 | */ |
574 | #define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } } | ||
575 | static void reset_fdc(void); | 570 | static void reset_fdc(void); |
576 | 571 | ||
577 | /* | 572 | /* |
@@ -579,9 +574,9 @@ static void reset_fdc(void); | |||
579 | * information to interrupts. They are the data used for the current | 574 | * information to interrupts. They are the data used for the current |
580 | * request. | 575 | * request. |
581 | */ | 576 | */ |
582 | #define NO_TRACK -1 | 577 | #define NO_TRACK -1 |
583 | #define NEED_1_RECAL -2 | 578 | #define NEED_1_RECAL -2 |
584 | #define NEED_2_RECAL -3 | 579 | #define NEED_2_RECAL -3 |
585 | 580 | ||
586 | static int usage_count; | 581 | static int usage_count; |
587 | 582 | ||
@@ -621,39 +616,35 @@ static inline void set_debugt(void) | |||
621 | debugtimer = jiffies; | 616 | debugtimer = jiffies; |
622 | } | 617 | } |
623 | 618 | ||
624 | static inline void debugt(const char *message) | 619 | static inline void debugt(const char *func, const char *msg) |
625 | { | 620 | { |
626 | if (DP->flags & DEBUGT) | 621 | if (DP->flags & DEBUGT) |
627 | printk("%s dtime=%lu\n", message, jiffies - debugtimer); | 622 | pr_info("%s:%s dtime=%lu\n", func, msg, jiffies - debugtimer); |
628 | } | 623 | } |
629 | #else | 624 | #else |
630 | static inline void set_debugt(void) { } | 625 | static inline void set_debugt(void) { } |
631 | static inline void debugt(const char *message) { } | 626 | static inline void debugt(const char *func, const char *msg) { } |
632 | #endif /* DEBUGT */ | 627 | #endif /* DEBUGT */ |
633 | 628 | ||
634 | typedef void (*timeout_fn) (unsigned long); | 629 | typedef void (*timeout_fn)(unsigned long); |
635 | static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0); | 630 | static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0); |
636 | 631 | ||
637 | static const char *timeout_message; | 632 | static const char *timeout_message; |
638 | 633 | ||
639 | #ifdef FLOPPY_SANITY_CHECK | 634 | static void is_alive(const char *func, const char *message) |
640 | static void is_alive(const char *message) | ||
641 | { | 635 | { |
642 | /* this routine checks whether the floppy driver is "alive" */ | 636 | /* this routine checks whether the floppy driver is "alive" */ |
643 | if (test_bit(0, &fdc_busy) && command_status < 2 | 637 | if (test_bit(0, &fdc_busy) && command_status < 2 && |
644 | && !timer_pending(&fd_timeout)) { | 638 | !timer_pending(&fd_timeout)) { |
645 | DPRINT("timeout handler died: %s\n", message); | 639 | DPRINT("%s: timeout handler died. %s\n", func, message); |
646 | } | 640 | } |
647 | } | 641 | } |
648 | #endif | ||
649 | 642 | ||
650 | static void (*do_floppy) (void) = NULL; | 643 | static void (*do_floppy)(void) = NULL; |
651 | |||
652 | #ifdef FLOPPY_SANITY_CHECK | ||
653 | 644 | ||
654 | #define OLOGSIZE 20 | 645 | #define OLOGSIZE 20 |
655 | 646 | ||
656 | static void (*lasthandler) (void); | 647 | static void (*lasthandler)(void); |
657 | static unsigned long interruptjiffies; | 648 | static unsigned long interruptjiffies; |
658 | static unsigned long resultjiffies; | 649 | static unsigned long resultjiffies; |
659 | static int resultsize; | 650 | static int resultsize; |
@@ -666,12 +657,11 @@ static struct output_log { | |||
666 | } output_log[OLOGSIZE]; | 657 | } output_log[OLOGSIZE]; |
667 | 658 | ||
668 | static int output_log_pos; | 659 | static int output_log_pos; |
669 | #endif | ||
670 | 660 | ||
671 | #define current_reqD -1 | 661 | #define current_reqD -1 |
672 | #define MAXTIMEOUT -2 | 662 | #define MAXTIMEOUT -2 |
673 | 663 | ||
674 | static void __reschedule_timeout(int drive, const char *message, int marg) | 664 | static void __reschedule_timeout(int drive, const char *message) |
675 | { | 665 | { |
676 | if (drive == current_reqD) | 666 | if (drive == current_reqD) |
677 | drive = current_drive; | 667 | drive = current_drive; |
@@ -682,25 +672,22 @@ static void __reschedule_timeout(int drive, const char *message, int marg) | |||
682 | } else | 672 | } else |
683 | fd_timeout.expires = jiffies + UDP->timeout; | 673 | fd_timeout.expires = jiffies + UDP->timeout; |
684 | add_timer(&fd_timeout); | 674 | add_timer(&fd_timeout); |
685 | if (UDP->flags & FD_DEBUG) { | 675 | if (UDP->flags & FD_DEBUG) |
686 | DPRINT("reschedule timeout "); | 676 | DPRINT("reschedule timeout %s\n", message); |
687 | printk(message, marg); | ||
688 | printk("\n"); | ||
689 | } | ||
690 | timeout_message = message; | 677 | timeout_message = message; |
691 | } | 678 | } |
692 | 679 | ||
693 | static void reschedule_timeout(int drive, const char *message, int marg) | 680 | static void reschedule_timeout(int drive, const char *message) |
694 | { | 681 | { |
695 | unsigned long flags; | 682 | unsigned long flags; |
696 | 683 | ||
697 | spin_lock_irqsave(&floppy_lock, flags); | 684 | spin_lock_irqsave(&floppy_lock, flags); |
698 | __reschedule_timeout(drive, message, marg); | 685 | __reschedule_timeout(drive, message); |
699 | spin_unlock_irqrestore(&floppy_lock, flags); | 686 | spin_unlock_irqrestore(&floppy_lock, flags); |
700 | } | 687 | } |
701 | 688 | ||
702 | #define INFBOUND(a,b) (a)=max_t(int, a, b) | 689 | #define INFBOUND(a, b) (a) = max_t(int, a, b) |
703 | #define SUPBOUND(a,b) (a)=min_t(int, a, b) | 690 | #define SUPBOUND(a, b) (a) = min_t(int, a, b) |
704 | 691 | ||
705 | /* | 692 | /* |
706 | * Bottom half floppy driver. | 693 | * Bottom half floppy driver. |
@@ -739,7 +726,6 @@ static int disk_change(int drive) | |||
739 | { | 726 | { |
740 | int fdc = FDC(drive); | 727 | int fdc = FDC(drive); |
741 | 728 | ||
742 | #ifdef FLOPPY_SANITY_CHECK | ||
743 | if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) | 729 | if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) |
744 | DPRINT("WARNING disk change called early\n"); | 730 | DPRINT("WARNING disk change called early\n"); |
745 | if (!(FDCS->dor & (0x10 << UNIT(drive))) || | 731 | if (!(FDCS->dor & (0x10 << UNIT(drive))) || |
@@ -748,31 +734,27 @@ static int disk_change(int drive) | |||
748 | DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive), | 734 | DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive), |
749 | (unsigned int)FDCS->dor); | 735 | (unsigned int)FDCS->dor); |
750 | } | 736 | } |
751 | #endif | ||
752 | 737 | ||
753 | #ifdef DCL_DEBUG | 738 | debug_dcl(UDP->flags, |
754 | if (UDP->flags & FD_DEBUG) { | 739 | "checking disk change line for drive %d\n", drive); |
755 | DPRINT("checking disk change line for drive %d\n", drive); | 740 | debug_dcl(UDP->flags, "jiffies=%lu\n", jiffies); |
756 | DPRINT("jiffies=%lu\n", jiffies); | 741 | debug_dcl(UDP->flags, "disk change line=%x\n", fd_inb(FD_DIR) & 0x80); |
757 | DPRINT("disk change line=%x\n", fd_inb(FD_DIR) & 0x80); | 742 | debug_dcl(UDP->flags, "flags=%lx\n", UDRS->flags); |
758 | DPRINT("flags=%lx\n", UDRS->flags); | 743 | |
759 | } | ||
760 | #endif | ||
761 | if (UDP->flags & FD_BROKEN_DCL) | 744 | if (UDP->flags & FD_BROKEN_DCL) |
762 | return UTESTF(FD_DISK_CHANGED); | 745 | return test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); |
763 | if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) { | 746 | if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) { |
764 | USETF(FD_VERIFY); /* verify write protection */ | 747 | set_bit(FD_VERIFY_BIT, &UDRS->flags); |
765 | if (UDRS->maxblock) { | 748 | /* verify write protection */ |
766 | /* mark it changed */ | 749 | |
767 | USETF(FD_DISK_CHANGED); | 750 | if (UDRS->maxblock) /* mark it changed */ |
768 | } | 751 | set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); |
769 | 752 | ||
770 | /* invalidate its geometry */ | 753 | /* invalidate its geometry */ |
771 | if (UDRS->keep_data >= 0) { | 754 | if (UDRS->keep_data >= 0) { |
772 | if ((UDP->flags & FTD_MSG) && | 755 | if ((UDP->flags & FTD_MSG) && |
773 | current_type[drive] != NULL) | 756 | current_type[drive] != NULL) |
774 | DPRINT("Disk type is undefined after " | 757 | DPRINT("Disk type is undefined after disk change\n"); |
775 | "disk change\n"); | ||
776 | current_type[drive] = NULL; | 758 | current_type[drive] = NULL; |
777 | floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1; | 759 | floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1; |
778 | } | 760 | } |
@@ -780,7 +762,7 @@ static int disk_change(int drive) | |||
780 | return 1; | 762 | return 1; |
781 | } else { | 763 | } else { |
782 | UDRS->last_checked = jiffies; | 764 | UDRS->last_checked = jiffies; |
783 | UCLEARF(FD_DISK_NEWCHANGE); | 765 | clear_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); |
784 | } | 766 | } |
785 | return 0; | 767 | return 0; |
786 | } | 768 | } |
@@ -790,6 +772,12 @@ static inline int is_selected(int dor, int unit) | |||
790 | return ((dor & (0x10 << unit)) && (dor & 3) == unit); | 772 | return ((dor & (0x10 << unit)) && (dor & 3) == unit); |
791 | } | 773 | } |
792 | 774 | ||
775 | static bool is_ready_state(int status) | ||
776 | { | ||
777 | int state = status & (STATUS_READY | STATUS_DIR | STATUS_DMA); | ||
778 | return state == STATUS_READY; | ||
779 | } | ||
780 | |||
793 | static int set_dor(int fdc, char mask, char data) | 781 | static int set_dor(int fdc, char mask, char data) |
794 | { | 782 | { |
795 | unsigned char unit; | 783 | unsigned char unit; |
@@ -806,11 +794,8 @@ static int set_dor(int fdc, char mask, char data) | |||
806 | unit = olddor & 0x3; | 794 | unit = olddor & 0x3; |
807 | if (is_selected(olddor, unit) && !is_selected(newdor, unit)) { | 795 | if (is_selected(olddor, unit) && !is_selected(newdor, unit)) { |
808 | drive = REVDRIVE(fdc, unit); | 796 | drive = REVDRIVE(fdc, unit); |
809 | #ifdef DCL_DEBUG | 797 | debug_dcl(UDP->flags, |
810 | if (UDP->flags & FD_DEBUG) { | 798 | "calling disk change from set_dor\n"); |
811 | DPRINT("calling disk change from set_dor\n"); | ||
812 | } | ||
813 | #endif | ||
814 | disk_change(drive); | 799 | disk_change(drive); |
815 | } | 800 | } |
816 | FDCS->dor = newdor; | 801 | FDCS->dor = newdor; |
@@ -834,8 +819,10 @@ static void twaddle(void) | |||
834 | DRS->select_date = jiffies; | 819 | DRS->select_date = jiffies; |
835 | } | 820 | } |
836 | 821 | ||
837 | /* reset all driver information about the current fdc. This is needed after | 822 | /* |
838 | * a reset, and after a raw command. */ | 823 | * Reset all driver information about the current fdc. |
824 | * This is needed after a reset, and after a raw command. | ||
825 | */ | ||
839 | static void reset_fdc_info(int mode) | 826 | static void reset_fdc_info(int mode) |
840 | { | 827 | { |
841 | int drive; | 828 | int drive; |
@@ -857,7 +844,7 @@ static void set_fdc(int drive) | |||
857 | current_drive = drive; | 844 | current_drive = drive; |
858 | } | 845 | } |
859 | if (fdc != 1 && fdc != 0) { | 846 | if (fdc != 1 && fdc != 0) { |
860 | printk("bad fdc value\n"); | 847 | pr_info("bad fdc value\n"); |
861 | return; | 848 | return; |
862 | } | 849 | } |
863 | set_dor(fdc, ~0, 8); | 850 | set_dor(fdc, ~0, 8); |
@@ -871,11 +858,10 @@ static void set_fdc(int drive) | |||
871 | } | 858 | } |
872 | 859 | ||
873 | /* locks the driver */ | 860 | /* locks the driver */ |
874 | static int _lock_fdc(int drive, int interruptible, int line) | 861 | static int _lock_fdc(int drive, bool interruptible, int line) |
875 | { | 862 | { |
876 | if (!usage_count) { | 863 | if (!usage_count) { |
877 | printk(KERN_ERR | 864 | pr_err("Trying to lock fdc while usage count=0 at line %d\n", |
878 | "Trying to lock fdc while usage count=0 at line %d\n", | ||
879 | line); | 865 | line); |
880 | return -1; | 866 | return -1; |
881 | } | 867 | } |
@@ -904,15 +890,13 @@ static int _lock_fdc(int drive, int interruptible, int line) | |||
904 | } | 890 | } |
905 | command_status = FD_COMMAND_NONE; | 891 | command_status = FD_COMMAND_NONE; |
906 | 892 | ||
907 | __reschedule_timeout(drive, "lock fdc", 0); | 893 | __reschedule_timeout(drive, "lock fdc"); |
908 | set_fdc(drive); | 894 | set_fdc(drive); |
909 | return 0; | 895 | return 0; |
910 | } | 896 | } |
911 | 897 | ||
912 | #define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__) | 898 | #define lock_fdc(drive, interruptible) \ |
913 | 899 | _lock_fdc(drive, interruptible, __LINE__) | |
914 | #define LOCK_FDC(drive,interruptible) \ | ||
915 | if (lock_fdc(drive,interruptible)) return -EINTR; | ||
916 | 900 | ||
917 | /* unlocks the driver */ | 901 | /* unlocks the driver */ |
918 | static inline void unlock_fdc(void) | 902 | static inline void unlock_fdc(void) |
@@ -924,7 +908,7 @@ static inline void unlock_fdc(void) | |||
924 | DPRINT("FDC access conflict!\n"); | 908 | DPRINT("FDC access conflict!\n"); |
925 | 909 | ||
926 | if (do_floppy) | 910 | if (do_floppy) |
927 | DPRINT("device interrupt still active at FDC release: %p!\n", | 911 | DPRINT("device interrupt still active at FDC release: %pf!\n", |
928 | do_floppy); | 912 | do_floppy); |
929 | command_status = FD_COMMAND_NONE; | 913 | command_status = FD_COMMAND_NONE; |
930 | spin_lock_irqsave(&floppy_lock, flags); | 914 | spin_lock_irqsave(&floppy_lock, flags); |
@@ -1003,7 +987,7 @@ static void empty(void) | |||
1003 | 987 | ||
1004 | static DECLARE_WORK(floppy_work, NULL); | 988 | static DECLARE_WORK(floppy_work, NULL); |
1005 | 989 | ||
1006 | static void schedule_bh(void (*handler) (void)) | 990 | static void schedule_bh(void (*handler)(void)) |
1007 | { | 991 | { |
1008 | PREPARE_WORK(&floppy_work, (work_func_t)handler); | 992 | PREPARE_WORK(&floppy_work, (work_func_t)handler); |
1009 | schedule_work(&floppy_work); | 993 | schedule_work(&floppy_work); |
@@ -1026,11 +1010,7 @@ static void cancel_activity(void) | |||
1026 | * transfer */ | 1010 | * transfer */ |
1027 | static void fd_watchdog(void) | 1011 | static void fd_watchdog(void) |
1028 | { | 1012 | { |
1029 | #ifdef DCL_DEBUG | 1013 | debug_dcl(DP->flags, "calling disk change from watchdog\n"); |
1030 | if (DP->flags & FD_DEBUG) { | ||
1031 | DPRINT("calling disk change from watchdog\n"); | ||
1032 | } | ||
1033 | #endif | ||
1034 | 1014 | ||
1035 | if (disk_change(current_drive)) { | 1015 | if (disk_change(current_drive)) { |
1036 | DPRINT("disk removed during i/o\n"); | 1016 | DPRINT("disk removed during i/o\n"); |
@@ -1039,7 +1019,7 @@ static void fd_watchdog(void) | |||
1039 | reset_fdc(); | 1019 | reset_fdc(); |
1040 | } else { | 1020 | } else { |
1041 | del_timer(&fd_timer); | 1021 | del_timer(&fd_timer); |
1042 | fd_timer.function = (timeout_fn) fd_watchdog; | 1022 | fd_timer.function = (timeout_fn)fd_watchdog; |
1043 | fd_timer.expires = jiffies + HZ / 10; | 1023 | fd_timer.expires = jiffies + HZ / 10; |
1044 | add_timer(&fd_timer); | 1024 | add_timer(&fd_timer); |
1045 | } | 1025 | } |
@@ -1105,25 +1085,23 @@ static void setup_DMA(void) | |||
1105 | { | 1085 | { |
1106 | unsigned long f; | 1086 | unsigned long f; |
1107 | 1087 | ||
1108 | #ifdef FLOPPY_SANITY_CHECK | ||
1109 | if (raw_cmd->length == 0) { | 1088 | if (raw_cmd->length == 0) { |
1110 | int i; | 1089 | int i; |
1111 | 1090 | ||
1112 | printk("zero dma transfer size:"); | 1091 | pr_info("zero dma transfer size:"); |
1113 | for (i = 0; i < raw_cmd->cmd_count; i++) | 1092 | for (i = 0; i < raw_cmd->cmd_count; i++) |
1114 | printk("%x,", raw_cmd->cmd[i]); | 1093 | pr_cont("%x,", raw_cmd->cmd[i]); |
1115 | printk("\n"); | 1094 | pr_cont("\n"); |
1116 | cont->done(0); | 1095 | cont->done(0); |
1117 | FDCS->reset = 1; | 1096 | FDCS->reset = 1; |
1118 | return; | 1097 | return; |
1119 | } | 1098 | } |
1120 | if (((unsigned long)raw_cmd->kernel_data) % 512) { | 1099 | if (((unsigned long)raw_cmd->kernel_data) % 512) { |
1121 | printk("non aligned address: %p\n", raw_cmd->kernel_data); | 1100 | pr_info("non aligned address: %p\n", raw_cmd->kernel_data); |
1122 | cont->done(0); | 1101 | cont->done(0); |
1123 | FDCS->reset = 1; | 1102 | FDCS->reset = 1; |
1124 | return; | 1103 | return; |
1125 | } | 1104 | } |
1126 | #endif | ||
1127 | f = claim_dma_lock(); | 1105 | f = claim_dma_lock(); |
1128 | fd_disable_dma(); | 1106 | fd_disable_dma(); |
1129 | #ifdef fd_dma_setup | 1107 | #ifdef fd_dma_setup |
@@ -1165,7 +1143,7 @@ static int wait_til_ready(void) | |||
1165 | if (status & STATUS_READY) | 1143 | if (status & STATUS_READY) |
1166 | return status; | 1144 | return status; |
1167 | } | 1145 | } |
1168 | if (!initialising) { | 1146 | if (initialized) { |
1169 | DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc); | 1147 | DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc); |
1170 | show_floppy(); | 1148 | show_floppy(); |
1171 | } | 1149 | } |
@@ -1176,22 +1154,21 @@ static int wait_til_ready(void) | |||
1176 | /* sends a command byte to the fdc */ | 1154 | /* sends a command byte to the fdc */ |
1177 | static int output_byte(char byte) | 1155 | static int output_byte(char byte) |
1178 | { | 1156 | { |
1179 | int status; | 1157 | int status = wait_til_ready(); |
1180 | 1158 | ||
1181 | if ((status = wait_til_ready()) < 0) | 1159 | if (status < 0) |
1182 | return -1; | 1160 | return -1; |
1183 | if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) { | 1161 | |
1162 | if (is_ready_state(status)) { | ||
1184 | fd_outb(byte, FD_DATA); | 1163 | fd_outb(byte, FD_DATA); |
1185 | #ifdef FLOPPY_SANITY_CHECK | ||
1186 | output_log[output_log_pos].data = byte; | 1164 | output_log[output_log_pos].data = byte; |
1187 | output_log[output_log_pos].status = status; | 1165 | output_log[output_log_pos].status = status; |
1188 | output_log[output_log_pos].jiffies = jiffies; | 1166 | output_log[output_log_pos].jiffies = jiffies; |
1189 | output_log_pos = (output_log_pos + 1) % OLOGSIZE; | 1167 | output_log_pos = (output_log_pos + 1) % OLOGSIZE; |
1190 | #endif | ||
1191 | return 0; | 1168 | return 0; |
1192 | } | 1169 | } |
1193 | FDCS->reset = 1; | 1170 | FDCS->reset = 1; |
1194 | if (!initialising) { | 1171 | if (initialized) { |
1195 | DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n", | 1172 | DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n", |
1196 | byte, fdc, status); | 1173 | byte, fdc, status); |
1197 | show_floppy(); | 1174 | show_floppy(); |
@@ -1199,8 +1176,6 @@ static int output_byte(char byte) | |||
1199 | return -1; | 1176 | return -1; |
1200 | } | 1177 | } |
1201 | 1178 | ||
1202 | #define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;} | ||
1203 | |||
1204 | /* gets the response from the fdc */ | 1179 | /* gets the response from the fdc */ |
1205 | static int result(void) | 1180 | static int result(void) |
1206 | { | 1181 | { |
@@ -1208,14 +1183,13 @@ static int result(void) | |||
1208 | int status = 0; | 1183 | int status = 0; |
1209 | 1184 | ||
1210 | for (i = 0; i < MAX_REPLIES; i++) { | 1185 | for (i = 0; i < MAX_REPLIES; i++) { |
1211 | if ((status = wait_til_ready()) < 0) | 1186 | status = wait_til_ready(); |
1187 | if (status < 0) | ||
1212 | break; | 1188 | break; |
1213 | status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA; | 1189 | status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA; |
1214 | if ((status & ~STATUS_BUSY) == STATUS_READY) { | 1190 | if ((status & ~STATUS_BUSY) == STATUS_READY) { |
1215 | #ifdef FLOPPY_SANITY_CHECK | ||
1216 | resultjiffies = jiffies; | 1191 | resultjiffies = jiffies; |
1217 | resultsize = i; | 1192 | resultsize = i; |
1218 | #endif | ||
1219 | return i; | 1193 | return i; |
1220 | } | 1194 | } |
1221 | if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY)) | 1195 | if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY)) |
@@ -1223,10 +1197,9 @@ static int result(void) | |||
1223 | else | 1197 | else |
1224 | break; | 1198 | break; |
1225 | } | 1199 | } |
1226 | if (!initialising) { | 1200 | if (initialized) { |
1227 | DPRINT | 1201 | DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n", |
1228 | ("get result error. Fdc=%d Last status=%x Read bytes=%d\n", | 1202 | fdc, status, i); |
1229 | fdc, status, i); | ||
1230 | show_floppy(); | 1203 | show_floppy(); |
1231 | } | 1204 | } |
1232 | FDCS->reset = 1; | 1205 | FDCS->reset = 1; |
@@ -1237,12 +1210,14 @@ static int result(void) | |||
1237 | /* does the fdc need more output? */ | 1210 | /* does the fdc need more output? */ |
1238 | static int need_more_output(void) | 1211 | static int need_more_output(void) |
1239 | { | 1212 | { |
1240 | int status; | 1213 | int status = wait_til_ready(); |
1241 | 1214 | ||
1242 | if ((status = wait_til_ready()) < 0) | 1215 | if (status < 0) |
1243 | return -1; | 1216 | return -1; |
1244 | if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) | 1217 | |
1218 | if (is_ready_state(status)) | ||
1245 | return MORE_OUTPUT; | 1219 | return MORE_OUTPUT; |
1220 | |||
1246 | return result(); | 1221 | return result(); |
1247 | } | 1222 | } |
1248 | 1223 | ||
@@ -1264,9 +1239,12 @@ static inline void perpendicular_mode(void) | |||
1264 | default: | 1239 | default: |
1265 | DPRINT("Invalid data rate for perpendicular mode!\n"); | 1240 | DPRINT("Invalid data rate for perpendicular mode!\n"); |
1266 | cont->done(0); | 1241 | cont->done(0); |
1267 | FDCS->reset = 1; /* convenient way to return to | 1242 | FDCS->reset = 1; |
1268 | * redo without to much hassle (deep | 1243 | /* |
1269 | * stack et al. */ | 1244 | * convenient way to return to |
1245 | * redo without too much hassle | ||
1246 | * (deep stack et al.) | ||
1247 | */ | ||
1270 | return; | 1248 | return; |
1271 | } | 1249 | } |
1272 | } else | 1250 | } else |
@@ -1366,9 +1344,9 @@ static void fdc_specify(void) | |||
1366 | 1344 | ||
1367 | /* Convert step rate from microseconds to milliseconds and 4 bits */ | 1345 | /* Convert step rate from microseconds to milliseconds and 4 bits */ |
1368 | srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR); | 1346 | srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR); |
1369 | if (slow_floppy) { | 1347 | if (slow_floppy) |
1370 | srt = srt / 4; | 1348 | srt = srt / 4; |
1371 | } | 1349 | |
1372 | SUPBOUND(srt, 0xf); | 1350 | SUPBOUND(srt, 0xf); |
1373 | INFBOUND(srt, 0); | 1351 | INFBOUND(srt, 0); |
1374 | 1352 | ||
@@ -1415,16 +1393,46 @@ static int fdc_dtr(void) | |||
1415 | * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) | 1393 | * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) |
1416 | */ | 1394 | */ |
1417 | FDCS->dtr = raw_cmd->rate & 3; | 1395 | FDCS->dtr = raw_cmd->rate & 3; |
1418 | return (fd_wait_for_completion(jiffies + 2UL * HZ / 100, | 1396 | return fd_wait_for_completion(jiffies + 2UL * HZ / 100, |
1419 | (timeout_fn) floppy_ready)); | 1397 | (timeout_fn)floppy_ready); |
1420 | } /* fdc_dtr */ | 1398 | } /* fdc_dtr */ |
1421 | 1399 | ||
1422 | static void tell_sector(void) | 1400 | static void tell_sector(void) |
1423 | { | 1401 | { |
1424 | printk(": track %d, head %d, sector %d, size %d", | 1402 | pr_cont(": track %d, head %d, sector %d, size %d", |
1425 | R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); | 1403 | R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); |
1426 | } /* tell_sector */ | 1404 | } /* tell_sector */ |
1427 | 1405 | ||
1406 | static void print_errors(void) | ||
1407 | { | ||
1408 | DPRINT(""); | ||
1409 | if (ST0 & ST0_ECE) { | ||
1410 | pr_cont("Recalibrate failed!"); | ||
1411 | } else if (ST2 & ST2_CRC) { | ||
1412 | pr_cont("data CRC error"); | ||
1413 | tell_sector(); | ||
1414 | } else if (ST1 & ST1_CRC) { | ||
1415 | pr_cont("CRC error"); | ||
1416 | tell_sector(); | ||
1417 | } else if ((ST1 & (ST1_MAM | ST1_ND)) || | ||
1418 | (ST2 & ST2_MAM)) { | ||
1419 | if (!probing) { | ||
1420 | pr_cont("sector not found"); | ||
1421 | tell_sector(); | ||
1422 | } else | ||
1423 | pr_cont("probe failed..."); | ||
1424 | } else if (ST2 & ST2_WC) { /* seek error */ | ||
1425 | pr_cont("wrong cylinder"); | ||
1426 | } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ | ||
1427 | pr_cont("bad cylinder"); | ||
1428 | } else { | ||
1429 | pr_cont("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", | ||
1430 | ST0, ST1, ST2); | ||
1431 | tell_sector(); | ||
1432 | } | ||
1433 | pr_cont("\n"); | ||
1434 | } | ||
1435 | |||
1428 | /* | 1436 | /* |
1429 | * OK, this error interpreting routine is called after a | 1437 | * OK, this error interpreting routine is called after a |
1430 | * DMA read/write has succeeded | 1438 | * DMA read/write has succeeded |
@@ -1437,7 +1445,7 @@ static int interpret_errors(void) | |||
1437 | char bad; | 1445 | char bad; |
1438 | 1446 | ||
1439 | if (inr != 7) { | 1447 | if (inr != 7) { |
1440 | DPRINT("-- FDC reply error"); | 1448 | DPRINT("-- FDC reply error\n"); |
1441 | FDCS->reset = 1; | 1449 | FDCS->reset = 1; |
1442 | return 1; | 1450 | return 1; |
1443 | } | 1451 | } |
@@ -1450,43 +1458,17 @@ static int interpret_errors(void) | |||
1450 | bad = 1; | 1458 | bad = 1; |
1451 | if (ST1 & ST1_WP) { | 1459 | if (ST1 & ST1_WP) { |
1452 | DPRINT("Drive is write protected\n"); | 1460 | DPRINT("Drive is write protected\n"); |
1453 | CLEARF(FD_DISK_WRITABLE); | 1461 | clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); |
1454 | cont->done(0); | 1462 | cont->done(0); |
1455 | bad = 2; | 1463 | bad = 2; |
1456 | } else if (ST1 & ST1_ND) { | 1464 | } else if (ST1 & ST1_ND) { |
1457 | SETF(FD_NEED_TWADDLE); | 1465 | set_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); |
1458 | } else if (ST1 & ST1_OR) { | 1466 | } else if (ST1 & ST1_OR) { |
1459 | if (DP->flags & FTD_MSG) | 1467 | if (DP->flags & FTD_MSG) |
1460 | DPRINT("Over/Underrun - retrying\n"); | 1468 | DPRINT("Over/Underrun - retrying\n"); |
1461 | bad = 0; | 1469 | bad = 0; |
1462 | } else if (*errors >= DP->max_errors.reporting) { | 1470 | } else if (*errors >= DP->max_errors.reporting) { |
1463 | DPRINT(""); | 1471 | print_errors(); |
1464 | if (ST0 & ST0_ECE) { | ||
1465 | printk("Recalibrate failed!"); | ||
1466 | } else if (ST2 & ST2_CRC) { | ||
1467 | printk("data CRC error"); | ||
1468 | tell_sector(); | ||
1469 | } else if (ST1 & ST1_CRC) { | ||
1470 | printk("CRC error"); | ||
1471 | tell_sector(); | ||
1472 | } else if ((ST1 & (ST1_MAM | ST1_ND)) | ||
1473 | || (ST2 & ST2_MAM)) { | ||
1474 | if (!probing) { | ||
1475 | printk("sector not found"); | ||
1476 | tell_sector(); | ||
1477 | } else | ||
1478 | printk("probe failed..."); | ||
1479 | } else if (ST2 & ST2_WC) { /* seek error */ | ||
1480 | printk("wrong cylinder"); | ||
1481 | } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ | ||
1482 | printk("bad cylinder"); | ||
1483 | } else { | ||
1484 | printk | ||
1485 | ("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", | ||
1486 | ST0, ST1, ST2); | ||
1487 | tell_sector(); | ||
1488 | } | ||
1489 | printk("\n"); | ||
1490 | } | 1472 | } |
1491 | if (ST2 & ST2_WC || ST2 & ST2_BC) | 1473 | if (ST2 & ST2_WC || ST2 & ST2_BC) |
1492 | /* wrong cylinder => recal */ | 1474 | /* wrong cylinder => recal */ |
@@ -1531,9 +1513,9 @@ static void setup_rw_floppy(void) | |||
1531 | */ | 1513 | */ |
1532 | if (time_after(ready_date, jiffies + DP->select_delay)) { | 1514 | if (time_after(ready_date, jiffies + DP->select_delay)) { |
1533 | ready_date -= DP->select_delay; | 1515 | ready_date -= DP->select_delay; |
1534 | function = (timeout_fn) floppy_start; | 1516 | function = (timeout_fn)floppy_start; |
1535 | } else | 1517 | } else |
1536 | function = (timeout_fn) setup_rw_floppy; | 1518 | function = (timeout_fn)setup_rw_floppy; |
1537 | 1519 | ||
1538 | /* wait until the floppy is spinning fast enough */ | 1520 | /* wait until the floppy is spinning fast enough */ |
1539 | if (fd_wait_for_completion(ready_date, function)) | 1521 | if (fd_wait_for_completion(ready_date, function)) |
@@ -1551,7 +1533,7 @@ static void setup_rw_floppy(void) | |||
1551 | for (i = 0; i < raw_cmd->cmd_count; i++) | 1533 | for (i = 0; i < raw_cmd->cmd_count; i++) |
1552 | r |= output_byte(raw_cmd->cmd[i]); | 1534 | r |= output_byte(raw_cmd->cmd[i]); |
1553 | 1535 | ||
1554 | debugt("rw_command: "); | 1536 | debugt(__func__, "rw_command"); |
1555 | 1537 | ||
1556 | if (r) { | 1538 | if (r) { |
1557 | cont->error(); | 1539 | cont->error(); |
@@ -1574,7 +1556,7 @@ static int blind_seek; | |||
1574 | */ | 1556 | */ |
1575 | static void seek_interrupt(void) | 1557 | static void seek_interrupt(void) |
1576 | { | 1558 | { |
1577 | debugt("seek interrupt:"); | 1559 | debugt(__func__, ""); |
1578 | if (inr != 2 || (ST0 & 0xF8) != 0x20) { | 1560 | if (inr != 2 || (ST0 & 0xF8) != 0x20) { |
1579 | DPRINT("seek failed\n"); | 1561 | DPRINT("seek failed\n"); |
1580 | DRS->track = NEED_2_RECAL; | 1562 | DRS->track = NEED_2_RECAL; |
@@ -1583,14 +1565,11 @@ static void seek_interrupt(void) | |||
1583 | return; | 1565 | return; |
1584 | } | 1566 | } |
1585 | if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) { | 1567 | if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) { |
1586 | #ifdef DCL_DEBUG | 1568 | debug_dcl(DP->flags, |
1587 | if (DP->flags & FD_DEBUG) { | 1569 | "clearing NEWCHANGE flag because of effective seek\n"); |
1588 | DPRINT | 1570 | debug_dcl(DP->flags, "jiffies=%lu\n", jiffies); |
1589 | ("clearing NEWCHANGE flag because of effective seek\n"); | 1571 | clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); |
1590 | DPRINT("jiffies=%lu\n", jiffies); | 1572 | /* effective seek */ |
1591 | } | ||
1592 | #endif | ||
1593 | CLEARF(FD_DISK_NEWCHANGE); /* effective seek */ | ||
1594 | DRS->select_date = jiffies; | 1573 | DRS->select_date = jiffies; |
1595 | } | 1574 | } |
1596 | DRS->track = ST1; | 1575 | DRS->track = ST1; |
@@ -1599,26 +1578,23 @@ static void seek_interrupt(void) | |||
1599 | 1578 | ||
1600 | static void check_wp(void) | 1579 | static void check_wp(void) |
1601 | { | 1580 | { |
1602 | if (TESTF(FD_VERIFY)) { | 1581 | if (test_bit(FD_VERIFY_BIT, &DRS->flags)) { |
1603 | /* check write protection */ | 1582 | /* check write protection */ |
1604 | output_byte(FD_GETSTATUS); | 1583 | output_byte(FD_GETSTATUS); |
1605 | output_byte(UNIT(current_drive)); | 1584 | output_byte(UNIT(current_drive)); |
1606 | if (result() != 1) { | 1585 | if (result() != 1) { |
1607 | FDCS->reset = 1; | 1586 | FDCS->reset = 1; |
1608 | return; | 1587 | return; |
1609 | } | 1588 | } |
1610 | CLEARF(FD_VERIFY); | 1589 | clear_bit(FD_VERIFY_BIT, &DRS->flags); |
1611 | CLEARF(FD_NEED_TWADDLE); | 1590 | clear_bit(FD_NEED_TWADDLE_BIT, &DRS->flags); |
1612 | #ifdef DCL_DEBUG | 1591 | debug_dcl(DP->flags, |
1613 | if (DP->flags & FD_DEBUG) { | 1592 | "checking whether disk is write protected\n"); |
1614 | DPRINT("checking whether disk is write protected\n"); | 1593 | debug_dcl(DP->flags, "wp=%x\n", ST3 & 0x40); |
1615 | DPRINT("wp=%x\n", ST3 & 0x40); | ||
1616 | } | ||
1617 | #endif | ||
1618 | if (!(ST3 & 0x40)) | 1594 | if (!(ST3 & 0x40)) |
1619 | SETF(FD_DISK_WRITABLE); | 1595 | set_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); |
1620 | else | 1596 | else |
1621 | CLEARF(FD_DISK_WRITABLE); | 1597 | clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags); |
1622 | } | 1598 | } |
1623 | } | 1599 | } |
1624 | 1600 | ||
@@ -1628,19 +1604,15 @@ static void seek_floppy(void) | |||
1628 | 1604 | ||
1629 | blind_seek = 0; | 1605 | blind_seek = 0; |
1630 | 1606 | ||
1631 | #ifdef DCL_DEBUG | 1607 | debug_dcl(DP->flags, "calling disk change from %s\n", __func__); |
1632 | if (DP->flags & FD_DEBUG) { | ||
1633 | DPRINT("calling disk change from seek\n"); | ||
1634 | } | ||
1635 | #endif | ||
1636 | 1608 | ||
1637 | if (!TESTF(FD_DISK_NEWCHANGE) && | 1609 | if (!test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && |
1638 | disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) { | 1610 | disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) { |
1639 | /* the media changed flag should be cleared after the seek. | 1611 | /* the media changed flag should be cleared after the seek. |
1640 | * If it isn't, this means that there is really no disk in | 1612 | * If it isn't, this means that there is really no disk in |
1641 | * the drive. | 1613 | * the drive. |
1642 | */ | 1614 | */ |
1643 | SETF(FD_DISK_CHANGED); | 1615 | set_bit(FD_DISK_CHANGED_BIT, &DRS->flags); |
1644 | cont->done(0); | 1616 | cont->done(0); |
1645 | cont->redo(); | 1617 | cont->redo(); |
1646 | return; | 1618 | return; |
@@ -1648,7 +1620,7 @@ static void seek_floppy(void) | |||
1648 | if (DRS->track <= NEED_1_RECAL) { | 1620 | if (DRS->track <= NEED_1_RECAL) { |
1649 | recalibrate_floppy(); | 1621 | recalibrate_floppy(); |
1650 | return; | 1622 | return; |
1651 | } else if (TESTF(FD_DISK_NEWCHANGE) && | 1623 | } else if (test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) && |
1652 | (raw_cmd->flags & FD_RAW_NEED_DISK) && | 1624 | (raw_cmd->flags & FD_RAW_NEED_DISK) && |
1653 | (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { | 1625 | (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { |
1654 | /* we seek to clear the media-changed condition. Does anybody | 1626 | /* we seek to clear the media-changed condition. Does anybody |
@@ -1677,19 +1649,22 @@ static void seek_floppy(void) | |||
1677 | do_floppy = seek_interrupt; | 1649 | do_floppy = seek_interrupt; |
1678 | output_byte(FD_SEEK); | 1650 | output_byte(FD_SEEK); |
1679 | output_byte(UNIT(current_drive)); | 1651 | output_byte(UNIT(current_drive)); |
1680 | LAST_OUT(track); | 1652 | if (output_byte(track) < 0) { |
1681 | debugt("seek command:"); | 1653 | reset_fdc(); |
1654 | return; | ||
1655 | } | ||
1656 | debugt(__func__, ""); | ||
1682 | } | 1657 | } |
1683 | 1658 | ||
1684 | static void recal_interrupt(void) | 1659 | static void recal_interrupt(void) |
1685 | { | 1660 | { |
1686 | debugt("recal interrupt:"); | 1661 | debugt(__func__, ""); |
1687 | if (inr != 2) | 1662 | if (inr != 2) |
1688 | FDCS->reset = 1; | 1663 | FDCS->reset = 1; |
1689 | else if (ST0 & ST0_ECE) { | 1664 | else if (ST0 & ST0_ECE) { |
1690 | switch (DRS->track) { | 1665 | switch (DRS->track) { |
1691 | case NEED_1_RECAL: | 1666 | case NEED_1_RECAL: |
1692 | debugt("recal interrupt need 1 recal:"); | 1667 | debugt(__func__, "need 1 recal"); |
1693 | /* after a second recalibrate, we still haven't | 1668 | /* after a second recalibrate, we still haven't |
1694 | * reached track 0. Probably no drive. Raise an | 1669 | * reached track 0. Probably no drive. Raise an |
1695 | * error, as failing immediately might upset | 1670 | * error, as failing immediately might upset |
@@ -1698,25 +1673,21 @@ static void recal_interrupt(void) | |||
1698 | cont->redo(); | 1673 | cont->redo(); |
1699 | return; | 1674 | return; |
1700 | case NEED_2_RECAL: | 1675 | case NEED_2_RECAL: |
1701 | debugt("recal interrupt need 2 recal:"); | 1676 | debugt(__func__, "need 2 recal"); |
1702 | /* If we already did a recalibrate, | 1677 | /* If we already did a recalibrate, |
1703 | * and we are not at track 0, this | 1678 | * and we are not at track 0, this |
1704 | * means we have moved. (The only way | 1679 | * means we have moved. (The only way |
1705 | * not to move at recalibration is to | 1680 | * not to move at recalibration is to |
1706 | * be already at track 0.) Clear the | 1681 | * be already at track 0.) Clear the |
1707 | * new change flag */ | 1682 | * new change flag */ |
1708 | #ifdef DCL_DEBUG | 1683 | debug_dcl(DP->flags, |
1709 | if (DP->flags & FD_DEBUG) { | 1684 | "clearing NEWCHANGE flag because of second recalibrate\n"); |
1710 | DPRINT | ||
1711 | ("clearing NEWCHANGE flag because of second recalibrate\n"); | ||
1712 | } | ||
1713 | #endif | ||
1714 | 1685 | ||
1715 | CLEARF(FD_DISK_NEWCHANGE); | 1686 | clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); |
1716 | DRS->select_date = jiffies; | 1687 | DRS->select_date = jiffies; |
1717 | /* fall through */ | 1688 | /* fall through */ |
1718 | default: | 1689 | default: |
1719 | debugt("recal interrupt default:"); | 1690 | debugt(__func__, "default"); |
1720 | /* Recalibrate moves the head by at | 1691 | /* Recalibrate moves the head by at |
1721 | * most 80 steps. If after one | 1692 | * most 80 steps. If after one |
1722 | * recalibrate we don't have reached | 1693 | * recalibrate we don't have reached |
@@ -1738,8 +1709,8 @@ static void print_result(char *message, int inr) | |||
1738 | DPRINT("%s ", message); | 1709 | DPRINT("%s ", message); |
1739 | if (inr >= 0) | 1710 | if (inr >= 0) |
1740 | for (i = 0; i < inr; i++) | 1711 | for (i = 0; i < inr; i++) |
1741 | printk("repl[%d]=%x ", i, reply_buffer[i]); | 1712 | pr_cont("repl[%d]=%x ", i, reply_buffer[i]); |
1742 | printk("\n"); | 1713 | pr_cont("\n"); |
1743 | } | 1714 | } |
1744 | 1715 | ||
1745 | /* interrupt handler. Note that this can be called externally on the Sparc */ | 1716 | /* interrupt handler. Note that this can be called externally on the Sparc */ |
@@ -1760,10 +1731,10 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) | |||
1760 | do_floppy = NULL; | 1731 | do_floppy = NULL; |
1761 | if (fdc >= N_FDC || FDCS->address == -1) { | 1732 | if (fdc >= N_FDC || FDCS->address == -1) { |
1762 | /* we don't even know which FDC is the culprit */ | 1733 | /* we don't even know which FDC is the culprit */ |
1763 | printk("DOR0=%x\n", fdc_state[0].dor); | 1734 | pr_info("DOR0=%x\n", fdc_state[0].dor); |
1764 | printk("floppy interrupt on bizarre fdc %d\n", fdc); | 1735 | pr_info("floppy interrupt on bizarre fdc %d\n", fdc); |
1765 | printk("handler=%p\n", handler); | 1736 | pr_info("handler=%pf\n", handler); |
1766 | is_alive("bizarre fdc"); | 1737 | is_alive(__func__, "bizarre fdc"); |
1767 | return IRQ_NONE; | 1738 | return IRQ_NONE; |
1768 | } | 1739 | } |
1769 | 1740 | ||
@@ -1777,7 +1748,7 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) | |||
1777 | * activity. | 1748 | * activity. |
1778 | */ | 1749 | */ |
1779 | 1750 | ||
1780 | do_print = !handler && print_unex && !initialising; | 1751 | do_print = !handler && print_unex && initialized; |
1781 | 1752 | ||
1782 | inr = result(); | 1753 | inr = result(); |
1783 | if (do_print) | 1754 | if (do_print) |
@@ -1790,15 +1761,15 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) | |||
1790 | if (do_print) | 1761 | if (do_print) |
1791 | print_result("sensei", inr); | 1762 | print_result("sensei", inr); |
1792 | max_sensei--; | 1763 | max_sensei--; |
1793 | } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 | 1764 | } while ((ST0 & 0x83) != UNIT(current_drive) && |
1794 | && max_sensei); | 1765 | inr == 2 && max_sensei); |
1795 | } | 1766 | } |
1796 | if (!handler) { | 1767 | if (!handler) { |
1797 | FDCS->reset = 1; | 1768 | FDCS->reset = 1; |
1798 | return IRQ_NONE; | 1769 | return IRQ_NONE; |
1799 | } | 1770 | } |
1800 | schedule_bh(handler); | 1771 | schedule_bh(handler); |
1801 | is_alive("normal interrupt end"); | 1772 | is_alive(__func__, "normal interrupt end"); |
1802 | 1773 | ||
1803 | /* FIXME! Was it really for us? */ | 1774 | /* FIXME! Was it really for us? */ |
1804 | return IRQ_HANDLED; | 1775 | return IRQ_HANDLED; |
@@ -1806,10 +1777,11 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id) | |||
1806 | 1777 | ||
1807 | static void recalibrate_floppy(void) | 1778 | static void recalibrate_floppy(void) |
1808 | { | 1779 | { |
1809 | debugt("recalibrate floppy:"); | 1780 | debugt(__func__, ""); |
1810 | do_floppy = recal_interrupt; | 1781 | do_floppy = recal_interrupt; |
1811 | output_byte(FD_RECALIBRATE); | 1782 | output_byte(FD_RECALIBRATE); |
1812 | LAST_OUT(UNIT(current_drive)); | 1783 | if (output_byte(UNIT(current_drive)) < 0) |
1784 | reset_fdc(); | ||
1813 | } | 1785 | } |
1814 | 1786 | ||
1815 | /* | 1787 | /* |
@@ -1817,10 +1789,10 @@ static void recalibrate_floppy(void) | |||
1817 | */ | 1789 | */ |
1818 | static void reset_interrupt(void) | 1790 | static void reset_interrupt(void) |
1819 | { | 1791 | { |
1820 | debugt("reset interrupt:"); | 1792 | debugt(__func__, ""); |
1821 | result(); /* get the status ready for set_fdc */ | 1793 | result(); /* get the status ready for set_fdc */ |
1822 | if (FDCS->reset) { | 1794 | if (FDCS->reset) { |
1823 | printk("reset set in interrupt, calling %p\n", cont->error); | 1795 | pr_info("reset set in interrupt, calling %pf\n", cont->error); |
1824 | cont->error(); /* a reset just after a reset. BAD! */ | 1796 | cont->error(); /* a reset just after a reset. BAD! */ |
1825 | } | 1797 | } |
1826 | cont->redo(); | 1798 | cont->redo(); |
@@ -1858,53 +1830,49 @@ static void show_floppy(void) | |||
1858 | { | 1830 | { |
1859 | int i; | 1831 | int i; |
1860 | 1832 | ||
1861 | printk("\n"); | 1833 | pr_info("\n"); |
1862 | printk("floppy driver state\n"); | 1834 | pr_info("floppy driver state\n"); |
1863 | printk("-------------------\n"); | 1835 | pr_info("-------------------\n"); |
1864 | printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n", | 1836 | pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%pf\n", |
1865 | jiffies, interruptjiffies, jiffies - interruptjiffies, | 1837 | jiffies, interruptjiffies, jiffies - interruptjiffies, |
1866 | lasthandler); | 1838 | lasthandler); |
1867 | 1839 | ||
1868 | #ifdef FLOPPY_SANITY_CHECK | 1840 | pr_info("timeout_message=%s\n", timeout_message); |
1869 | printk("timeout_message=%s\n", timeout_message); | 1841 | pr_info("last output bytes:\n"); |
1870 | printk("last output bytes:\n"); | ||
1871 | for (i = 0; i < OLOGSIZE; i++) | 1842 | for (i = 0; i < OLOGSIZE; i++) |
1872 | printk("%2x %2x %lu\n", | 1843 | pr_info("%2x %2x %lu\n", |
1873 | output_log[(i + output_log_pos) % OLOGSIZE].data, | 1844 | output_log[(i + output_log_pos) % OLOGSIZE].data, |
1874 | output_log[(i + output_log_pos) % OLOGSIZE].status, | 1845 | output_log[(i + output_log_pos) % OLOGSIZE].status, |
1875 | output_log[(i + output_log_pos) % OLOGSIZE].jiffies); | 1846 | output_log[(i + output_log_pos) % OLOGSIZE].jiffies); |
1876 | printk("last result at %lu\n", resultjiffies); | 1847 | pr_info("last result at %lu\n", resultjiffies); |
1877 | printk("last redo_fd_request at %lu\n", lastredo); | 1848 | pr_info("last redo_fd_request at %lu\n", lastredo); |
1878 | for (i = 0; i < resultsize; i++) { | 1849 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, |
1879 | printk("%2x ", reply_buffer[i]); | 1850 | reply_buffer, resultsize, true); |
1880 | } | 1851 | |
1881 | printk("\n"); | 1852 | pr_info("status=%x\n", fd_inb(FD_STATUS)); |
1882 | #endif | 1853 | pr_info("fdc_busy=%lu\n", fdc_busy); |
1883 | |||
1884 | printk("status=%x\n", fd_inb(FD_STATUS)); | ||
1885 | printk("fdc_busy=%lu\n", fdc_busy); | ||
1886 | if (do_floppy) | 1854 | if (do_floppy) |
1887 | printk("do_floppy=%p\n", do_floppy); | 1855 | pr_info("do_floppy=%pf\n", do_floppy); |
1888 | if (work_pending(&floppy_work)) | 1856 | if (work_pending(&floppy_work)) |
1889 | printk("floppy_work.func=%p\n", floppy_work.func); | 1857 | pr_info("floppy_work.func=%pf\n", floppy_work.func); |
1890 | if (timer_pending(&fd_timer)) | 1858 | if (timer_pending(&fd_timer)) |
1891 | printk("fd_timer.function=%p\n", fd_timer.function); | 1859 | pr_info("fd_timer.function=%pf\n", fd_timer.function); |
1892 | if (timer_pending(&fd_timeout)) { | 1860 | if (timer_pending(&fd_timeout)) { |
1893 | printk("timer_function=%p\n", fd_timeout.function); | 1861 | pr_info("timer_function=%pf\n", fd_timeout.function); |
1894 | printk("expires=%lu\n", fd_timeout.expires - jiffies); | 1862 | pr_info("expires=%lu\n", fd_timeout.expires - jiffies); |
1895 | printk("now=%lu\n", jiffies); | 1863 | pr_info("now=%lu\n", jiffies); |
1896 | } | 1864 | } |
1897 | printk("cont=%p\n", cont); | 1865 | pr_info("cont=%p\n", cont); |
1898 | printk("current_req=%p\n", current_req); | 1866 | pr_info("current_req=%p\n", current_req); |
1899 | printk("command_status=%d\n", command_status); | 1867 | pr_info("command_status=%d\n", command_status); |
1900 | printk("\n"); | 1868 | pr_info("\n"); |
1901 | } | 1869 | } |
1902 | 1870 | ||
1903 | static void floppy_shutdown(unsigned long data) | 1871 | static void floppy_shutdown(unsigned long data) |
1904 | { | 1872 | { |
1905 | unsigned long flags; | 1873 | unsigned long flags; |
1906 | 1874 | ||
1907 | if (!initialising) | 1875 | if (initialized) |
1908 | show_floppy(); | 1876 | show_floppy(); |
1909 | cancel_activity(); | 1877 | cancel_activity(); |
1910 | 1878 | ||
@@ -1916,17 +1884,17 @@ static void floppy_shutdown(unsigned long data) | |||
1916 | 1884 | ||
1917 | /* avoid dma going to a random drive after shutdown */ | 1885 | /* avoid dma going to a random drive after shutdown */ |
1918 | 1886 | ||
1919 | if (!initialising) | 1887 | if (initialized) |
1920 | DPRINT("floppy timeout called\n"); | 1888 | DPRINT("floppy timeout called\n"); |
1921 | FDCS->reset = 1; | 1889 | FDCS->reset = 1; |
1922 | if (cont) { | 1890 | if (cont) { |
1923 | cont->done(0); | 1891 | cont->done(0); |
1924 | cont->redo(); /* this will recall reset when needed */ | 1892 | cont->redo(); /* this will recall reset when needed */ |
1925 | } else { | 1893 | } else { |
1926 | printk("no cont in shutdown!\n"); | 1894 | pr_info("no cont in shutdown!\n"); |
1927 | process_fd_request(); | 1895 | process_fd_request(); |
1928 | } | 1896 | } |
1929 | is_alive("floppy shutdown"); | 1897 | is_alive(__func__, ""); |
1930 | } | 1898 | } |
1931 | 1899 | ||
1932 | /* start motor, check media-changed condition and write protection */ | 1900 | /* start motor, check media-changed condition and write protection */ |
@@ -1954,27 +1922,26 @@ static int start_motor(void (*function)(void)) | |||
1954 | set_dor(fdc, mask, data); | 1922 | set_dor(fdc, mask, data); |
1955 | 1923 | ||
1956 | /* wait_for_completion also schedules reset if needed. */ | 1924 | /* wait_for_completion also schedules reset if needed. */ |
1957 | return (fd_wait_for_completion(DRS->select_date + DP->select_delay, | 1925 | return fd_wait_for_completion(DRS->select_date + DP->select_delay, |
1958 | (timeout_fn) function)); | 1926 | (timeout_fn)function); |
1959 | } | 1927 | } |
1960 | 1928 | ||
1961 | static void floppy_ready(void) | 1929 | static void floppy_ready(void) |
1962 | { | 1930 | { |
1963 | CHECK_RESET; | 1931 | if (FDCS->reset) { |
1932 | reset_fdc(); | ||
1933 | return; | ||
1934 | } | ||
1964 | if (start_motor(floppy_ready)) | 1935 | if (start_motor(floppy_ready)) |
1965 | return; | 1936 | return; |
1966 | if (fdc_dtr()) | 1937 | if (fdc_dtr()) |
1967 | return; | 1938 | return; |
1968 | 1939 | ||
1969 | #ifdef DCL_DEBUG | 1940 | debug_dcl(DP->flags, "calling disk change from floppy_ready\n"); |
1970 | if (DP->flags & FD_DEBUG) { | ||
1971 | DPRINT("calling disk change from floppy_ready\n"); | ||
1972 | } | ||
1973 | #endif | ||
1974 | if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) && | 1941 | if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) && |
1975 | disk_change(current_drive) && !DP->select_delay) | 1942 | disk_change(current_drive) && !DP->select_delay) |
1976 | twaddle(); /* this clears the dcl on certain drive/controller | 1943 | twaddle(); /* this clears the dcl on certain |
1977 | * combinations */ | 1944 | * drive/controller combinations */ |
1978 | 1945 | ||
1979 | #ifdef fd_chose_dma_mode | 1946 | #ifdef fd_chose_dma_mode |
1980 | if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) { | 1947 | if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) { |
@@ -1998,15 +1965,11 @@ static void floppy_ready(void) | |||
1998 | 1965 | ||
1999 | static void floppy_start(void) | 1966 | static void floppy_start(void) |
2000 | { | 1967 | { |
2001 | reschedule_timeout(current_reqD, "floppy start", 0); | 1968 | reschedule_timeout(current_reqD, "floppy start"); |
2002 | 1969 | ||
2003 | scandrives(); | 1970 | scandrives(); |
2004 | #ifdef DCL_DEBUG | 1971 | debug_dcl(DP->flags, "setting NEWCHANGE in floppy_start\n"); |
2005 | if (DP->flags & FD_DEBUG) { | 1972 | set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); |
2006 | DPRINT("setting NEWCHANGE in floppy_start\n"); | ||
2007 | } | ||
2008 | #endif | ||
2009 | SETF(FD_DISK_NEWCHANGE); | ||
2010 | floppy_ready(); | 1973 | floppy_ready(); |
2011 | } | 1974 | } |
2012 | 1975 | ||
@@ -2026,7 +1989,7 @@ static void floppy_start(void) | |||
2026 | 1989 | ||
2027 | static void do_wakeup(void) | 1990 | static void do_wakeup(void) |
2028 | { | 1991 | { |
2029 | reschedule_timeout(MAXTIMEOUT, "do wakeup", 0); | 1992 | reschedule_timeout(MAXTIMEOUT, "do wakeup"); |
2030 | cont = NULL; | 1993 | cont = NULL; |
2031 | command_status += 2; | 1994 | command_status += 2; |
2032 | wake_up(&command_done); | 1995 | wake_up(&command_done); |
@@ -2046,7 +2009,7 @@ static struct cont_t intr_cont = { | |||
2046 | .done = (done_f)empty | 2009 | .done = (done_f)empty |
2047 | }; | 2010 | }; |
2048 | 2011 | ||
2049 | static int wait_til_done(void (*handler)(void), int interruptible) | 2012 | static int wait_til_done(void (*handler)(void), bool interruptible) |
2050 | { | 2013 | { |
2051 | int ret; | 2014 | int ret; |
2052 | 2015 | ||
@@ -2064,7 +2027,7 @@ static int wait_til_done(void (*handler)(void), int interruptible) | |||
2064 | if (command_status >= 2 || !NO_SIGNAL) | 2027 | if (command_status >= 2 || !NO_SIGNAL) |
2065 | break; | 2028 | break; |
2066 | 2029 | ||
2067 | is_alive("wait_til_done"); | 2030 | is_alive(__func__, ""); |
2068 | schedule(); | 2031 | schedule(); |
2069 | } | 2032 | } |
2070 | 2033 | ||
@@ -2180,9 +2143,9 @@ static void format_interrupt(void) | |||
2180 | cont->redo(); | 2143 | cont->redo(); |
2181 | } | 2144 | } |
2182 | 2145 | ||
2183 | #define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2) | 2146 | #define FM_MODE(x, y) ((y) & ~(((x)->rate & 0x80) >> 1)) |
2184 | #define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1)) | ||
2185 | #define CT(x) ((x) | 0xc0) | 2147 | #define CT(x) ((x) | 0xc0) |
2148 | |||
2186 | static void setup_format_params(int track) | 2149 | static void setup_format_params(int track) |
2187 | { | 2150 | { |
2188 | int n; | 2151 | int n; |
@@ -2197,8 +2160,8 @@ static void setup_format_params(int track) | |||
2197 | raw_cmd = &default_raw_cmd; | 2160 | raw_cmd = &default_raw_cmd; |
2198 | raw_cmd->track = track; | 2161 | raw_cmd->track = track; |
2199 | 2162 | ||
2200 | raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | | 2163 | raw_cmd->flags = (FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | |
2201 | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; | 2164 | FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK); |
2202 | raw_cmd->rate = _floppy->rate & 0x43; | 2165 | raw_cmd->rate = _floppy->rate & 0x43; |
2203 | raw_cmd->cmd_count = NR_F; | 2166 | raw_cmd->cmd_count = NR_F; |
2204 | COMMAND = FM_MODE(_floppy, FD_FORMAT); | 2167 | COMMAND = FM_MODE(_floppy, FD_FORMAT); |
@@ -2257,7 +2220,7 @@ static void redo_format(void) | |||
2257 | buffer_track = -1; | 2220 | buffer_track = -1; |
2258 | setup_format_params(format_req.track << STRETCH(_floppy)); | 2221 | setup_format_params(format_req.track << STRETCH(_floppy)); |
2259 | floppy_start(); | 2222 | floppy_start(); |
2260 | debugt("queue format request"); | 2223 | debugt(__func__, "queue format request"); |
2261 | } | 2224 | } |
2262 | 2225 | ||
2263 | static struct cont_t format_cont = { | 2226 | static struct cont_t format_cont = { |
@@ -2271,7 +2234,9 @@ static int do_format(int drive, struct format_descr *tmp_format_req) | |||
2271 | { | 2234 | { |
2272 | int ret; | 2235 | int ret; |
2273 | 2236 | ||
2274 | LOCK_FDC(drive, 1); | 2237 | if (lock_fdc(drive, true)) |
2238 | return -EINTR; | ||
2239 | |||
2275 | set_floppy(drive); | 2240 | set_floppy(drive); |
2276 | if (!_floppy || | 2241 | if (!_floppy || |
2277 | _floppy->track > DP->tracks || | 2242 | _floppy->track > DP->tracks || |
@@ -2286,7 +2251,9 @@ static int do_format(int drive, struct format_descr *tmp_format_req) | |||
2286 | format_errors = 0; | 2251 | format_errors = 0; |
2287 | cont = &format_cont; | 2252 | cont = &format_cont; |
2288 | errors = &format_errors; | 2253 | errors = &format_errors; |
2289 | IWAIT(redo_format); | 2254 | ret = wait_til_done(redo_format, true); |
2255 | if (ret == -EINTR) | ||
2256 | return -EINTR; | ||
2290 | process_fd_request(); | 2257 | process_fd_request(); |
2291 | return ret; | 2258 | return ret; |
2292 | } | 2259 | } |
@@ -2320,12 +2287,14 @@ static void request_done(int uptodate) | |||
2320 | struct request *req = current_req; | 2287 | struct request *req = current_req; |
2321 | unsigned long flags; | 2288 | unsigned long flags; |
2322 | int block; | 2289 | int block; |
2290 | char msg[sizeof("request done ") + sizeof(int) * 3]; | ||
2323 | 2291 | ||
2324 | probing = 0; | 2292 | probing = 0; |
2325 | reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate); | 2293 | snprintf(msg, sizeof(msg), "request done %d", uptodate); |
2294 | reschedule_timeout(MAXTIMEOUT, msg); | ||
2326 | 2295 | ||
2327 | if (!req) { | 2296 | if (!req) { |
2328 | printk("floppy.c: no request in request_done\n"); | 2297 | pr_info("floppy.c: no request in request_done\n"); |
2329 | return; | 2298 | return; |
2330 | } | 2299 | } |
2331 | 2300 | ||
@@ -2377,7 +2346,7 @@ static void rw_interrupt(void) | |||
2377 | DRS->first_read_date = jiffies; | 2346 | DRS->first_read_date = jiffies; |
2378 | 2347 | ||
2379 | nr_sectors = 0; | 2348 | nr_sectors = 0; |
2380 | CODE2SIZE; | 2349 | ssize = DIV_ROUND_UP(1 << SIZECODE, 4); |
2381 | 2350 | ||
2382 | if (ST1 & ST1_EOC) | 2351 | if (ST1 & ST1_EOC) |
2383 | eoc = 1; | 2352 | eoc = 1; |
@@ -2393,20 +2362,18 @@ static void rw_interrupt(void) | |||
2393 | R_HEAD - HEAD) * SECT_PER_TRACK + | 2362 | R_HEAD - HEAD) * SECT_PER_TRACK + |
2394 | R_SECTOR - SECTOR + eoc) << SIZECODE >> 2; | 2363 | R_SECTOR - SECTOR + eoc) << SIZECODE >> 2; |
2395 | 2364 | ||
2396 | #ifdef FLOPPY_SANITY_CHECK | ||
2397 | if (nr_sectors / ssize > | 2365 | if (nr_sectors / ssize > |
2398 | DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) { | 2366 | DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) { |
2399 | DPRINT("long rw: %x instead of %lx\n", | 2367 | DPRINT("long rw: %x instead of %lx\n", |
2400 | nr_sectors, current_count_sectors); | 2368 | nr_sectors, current_count_sectors); |
2401 | printk("rs=%d s=%d\n", R_SECTOR, SECTOR); | 2369 | pr_info("rs=%d s=%d\n", R_SECTOR, SECTOR); |
2402 | printk("rh=%d h=%d\n", R_HEAD, HEAD); | 2370 | pr_info("rh=%d h=%d\n", R_HEAD, HEAD); |
2403 | printk("rt=%d t=%d\n", R_TRACK, TRACK); | 2371 | pr_info("rt=%d t=%d\n", R_TRACK, TRACK); |
2404 | printk("heads=%d eoc=%d\n", heads, eoc); | 2372 | pr_info("heads=%d eoc=%d\n", heads, eoc); |
2405 | printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, | 2373 | pr_info("spt=%d st=%d ss=%d\n", |
2406 | fsector_t, ssize); | 2374 | SECT_PER_TRACK, fsector_t, ssize); |
2407 | printk("in_sector_offset=%d\n", in_sector_offset); | 2375 | pr_info("in_sector_offset=%d\n", in_sector_offset); |
2408 | } | 2376 | } |
2409 | #endif | ||
2410 | 2377 | ||
2411 | nr_sectors -= in_sector_offset; | 2378 | nr_sectors -= in_sector_offset; |
2412 | INFBOUND(nr_sectors, 0); | 2379 | INFBOUND(nr_sectors, 0); |
@@ -2511,19 +2478,17 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) | |||
2511 | blk_rq_sectors(current_req)); | 2478 | blk_rq_sectors(current_req)); |
2512 | 2479 | ||
2513 | remaining = current_count_sectors << 9; | 2480 | remaining = current_count_sectors << 9; |
2514 | #ifdef FLOPPY_SANITY_CHECK | ||
2515 | if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) { | 2481 | if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) { |
2516 | DPRINT("in copy buffer\n"); | 2482 | DPRINT("in copy buffer\n"); |
2517 | printk("current_count_sectors=%ld\n", current_count_sectors); | 2483 | pr_info("current_count_sectors=%ld\n", current_count_sectors); |
2518 | printk("remaining=%d\n", remaining >> 9); | 2484 | pr_info("remaining=%d\n", remaining >> 9); |
2519 | printk("current_req->nr_sectors=%u\n", | 2485 | pr_info("current_req->nr_sectors=%u\n", |
2520 | blk_rq_sectors(current_req)); | 2486 | blk_rq_sectors(current_req)); |
2521 | printk("current_req->current_nr_sectors=%u\n", | 2487 | pr_info("current_req->current_nr_sectors=%u\n", |
2522 | blk_rq_cur_sectors(current_req)); | 2488 | blk_rq_cur_sectors(current_req)); |
2523 | printk("max_sector=%d\n", max_sector); | 2489 | pr_info("max_sector=%d\n", max_sector); |
2524 | printk("ssize=%d\n", ssize); | 2490 | pr_info("ssize=%d\n", ssize); |
2525 | } | 2491 | } |
2526 | #endif | ||
2527 | 2492 | ||
2528 | buffer_max = max(max_sector, buffer_max); | 2493 | buffer_max = max(max_sector, buffer_max); |
2529 | 2494 | ||
@@ -2539,26 +2504,24 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) | |||
2539 | SUPBOUND(size, remaining); | 2504 | SUPBOUND(size, remaining); |
2540 | 2505 | ||
2541 | buffer = page_address(bv->bv_page) + bv->bv_offset; | 2506 | buffer = page_address(bv->bv_page) + bv->bv_offset; |
2542 | #ifdef FLOPPY_SANITY_CHECK | ||
2543 | if (dma_buffer + size > | 2507 | if (dma_buffer + size > |
2544 | floppy_track_buffer + (max_buffer_sectors << 10) || | 2508 | floppy_track_buffer + (max_buffer_sectors << 10) || |
2545 | dma_buffer < floppy_track_buffer) { | 2509 | dma_buffer < floppy_track_buffer) { |
2546 | DPRINT("buffer overrun in copy buffer %d\n", | 2510 | DPRINT("buffer overrun in copy buffer %d\n", |
2547 | (int)((floppy_track_buffer - | 2511 | (int)((floppy_track_buffer - dma_buffer) >> 9)); |
2548 | dma_buffer) >> 9)); | 2512 | pr_info("fsector_t=%d buffer_min=%d\n", |
2549 | printk("fsector_t=%d buffer_min=%d\n", | 2513 | fsector_t, buffer_min); |
2550 | fsector_t, buffer_min); | 2514 | pr_info("current_count_sectors=%ld\n", |
2551 | printk("current_count_sectors=%ld\n", | 2515 | current_count_sectors); |
2552 | current_count_sectors); | ||
2553 | if (CT(COMMAND) == FD_READ) | 2516 | if (CT(COMMAND) == FD_READ) |
2554 | printk("read\n"); | 2517 | pr_info("read\n"); |
2555 | if (CT(COMMAND) == FD_WRITE) | 2518 | if (CT(COMMAND) == FD_WRITE) |
2556 | printk("write\n"); | 2519 | pr_info("write\n"); |
2557 | break; | 2520 | break; |
2558 | } | 2521 | } |
2559 | if (((unsigned long)buffer) % 512) | 2522 | if (((unsigned long)buffer) % 512) |
2560 | DPRINT("%p buffer not aligned\n", buffer); | 2523 | DPRINT("%p buffer not aligned\n", buffer); |
2561 | #endif | 2524 | |
2562 | if (CT(COMMAND) == FD_READ) | 2525 | if (CT(COMMAND) == FD_READ) |
2563 | memcpy(buffer, dma_buffer, size); | 2526 | memcpy(buffer, dma_buffer, size); |
2564 | else | 2527 | else |
@@ -2567,13 +2530,11 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) | |||
2567 | remaining -= size; | 2530 | remaining -= size; |
2568 | dma_buffer += size; | 2531 | dma_buffer += size; |
2569 | } | 2532 | } |
2570 | #ifdef FLOPPY_SANITY_CHECK | ||
2571 | if (remaining) { | 2533 | if (remaining) { |
2572 | if (remaining > 0) | 2534 | if (remaining > 0) |
2573 | max_sector -= remaining >> 9; | 2535 | max_sector -= remaining >> 9; |
2574 | DPRINT("weirdness: remaining %d\n", remaining >> 9); | 2536 | DPRINT("weirdness: remaining %d\n", remaining >> 9); |
2575 | } | 2537 | } |
2576 | #endif | ||
2577 | } | 2538 | } |
2578 | 2539 | ||
2579 | /* work around a bug in pseudo DMA | 2540 | /* work around a bug in pseudo DMA |
@@ -2593,15 +2554,14 @@ static void virtualdmabug_workaround(void) | |||
2593 | 2554 | ||
2594 | hard_sectors = raw_cmd->length >> (7 + SIZECODE); | 2555 | hard_sectors = raw_cmd->length >> (7 + SIZECODE); |
2595 | end_sector = SECTOR + hard_sectors - 1; | 2556 | end_sector = SECTOR + hard_sectors - 1; |
2596 | #ifdef FLOPPY_SANITY_CHECK | ||
2597 | if (end_sector > SECT_PER_TRACK) { | 2557 | if (end_sector > SECT_PER_TRACK) { |
2598 | printk("too many sectors %d > %d\n", | 2558 | pr_info("too many sectors %d > %d\n", |
2599 | end_sector, SECT_PER_TRACK); | 2559 | end_sector, SECT_PER_TRACK); |
2600 | return; | 2560 | return; |
2601 | } | 2561 | } |
2602 | #endif | 2562 | SECT_PER_TRACK = end_sector; |
2603 | SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points | 2563 | /* make sure SECT_PER_TRACK |
2604 | * to end of transfer */ | 2564 | * points to end of transfer */ |
2605 | } | 2565 | } |
2606 | } | 2566 | } |
2607 | 2567 | ||
@@ -2624,7 +2584,7 @@ static int make_raw_rw_request(void) | |||
2624 | int ssize; | 2584 | int ssize; |
2625 | 2585 | ||
2626 | if (max_buffer_sectors == 0) { | 2586 | if (max_buffer_sectors == 0) { |
2627 | printk("VFS: Block I/O scheduled on unopened device\n"); | 2587 | pr_info("VFS: Block I/O scheduled on unopened device\n"); |
2628 | return 0; | 2588 | return 0; |
2629 | } | 2589 | } |
2630 | 2590 | ||
@@ -2641,7 +2601,7 @@ static int make_raw_rw_request(void) | |||
2641 | raw_cmd->flags |= FD_RAW_WRITE; | 2601 | raw_cmd->flags |= FD_RAW_WRITE; |
2642 | COMMAND = FM_MODE(_floppy, FD_WRITE); | 2602 | COMMAND = FM_MODE(_floppy, FD_WRITE); |
2643 | } else { | 2603 | } else { |
2644 | DPRINT("make_raw_rw_request: unknown command\n"); | 2604 | DPRINT("%s: unknown command\n", __func__); |
2645 | return 0; | 2605 | return 0; |
2646 | } | 2606 | } |
2647 | 2607 | ||
@@ -2659,7 +2619,8 @@ static int make_raw_rw_request(void) | |||
2659 | HEAD = fsector_t / _floppy->sect; | 2619 | HEAD = fsector_t / _floppy->sect; |
2660 | 2620 | ||
2661 | if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || | 2621 | if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || |
2662 | TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect) | 2622 | test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) && |
2623 | fsector_t < _floppy->sect) | ||
2663 | max_sector = _floppy->sect; | 2624 | max_sector = _floppy->sect; |
2664 | 2625 | ||
2665 | /* 2M disks have phantom sectors on the first track */ | 2626 | /* 2M disks have phantom sectors on the first track */ |
@@ -2685,7 +2646,7 @@ static int make_raw_rw_request(void) | |||
2685 | raw_cmd->track = TRACK << STRETCH(_floppy); | 2646 | raw_cmd->track = TRACK << STRETCH(_floppy); |
2686 | DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD); | 2647 | DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD); |
2687 | GAP = _floppy->gap; | 2648 | GAP = _floppy->gap; |
2688 | CODE2SIZE; | 2649 | ssize = DIV_ROUND_UP(1 << SIZECODE, 4); |
2689 | SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; | 2650 | SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; |
2690 | SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + | 2651 | SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + |
2691 | FD_SECTBASE(_floppy); | 2652 | FD_SECTBASE(_floppy); |
@@ -2730,8 +2691,10 @@ static int make_raw_rw_request(void) | |||
2730 | } | 2691 | } |
2731 | } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) { | 2692 | } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) { |
2732 | if (CT(COMMAND) == FD_WRITE) { | 2693 | if (CT(COMMAND) == FD_WRITE) { |
2733 | if (fsector_t + blk_rq_sectors(current_req) > ssize && | 2694 | unsigned int sectors; |
2734 | fsector_t + blk_rq_sectors(current_req) < ssize + ssize) | 2695 | |
2696 | sectors = fsector_t + blk_rq_sectors(current_req); | ||
2697 | if (sectors > ssize && sectors < ssize + ssize) | ||
2735 | max_size = ssize + ssize; | 2698 | max_size = ssize + ssize; |
2736 | else | 2699 | else |
2737 | max_size = ssize; | 2700 | max_size = ssize; |
@@ -2752,12 +2715,10 @@ static int make_raw_rw_request(void) | |||
2752 | * on a 64 bit machine! | 2715 | * on a 64 bit machine! |
2753 | */ | 2716 | */ |
2754 | max_size = buffer_chain_size(); | 2717 | max_size = buffer_chain_size(); |
2755 | dma_limit = | 2718 | dma_limit = (MAX_DMA_ADDRESS - |
2756 | (MAX_DMA_ADDRESS - | 2719 | ((unsigned long)current_req->buffer)) >> 9; |
2757 | ((unsigned long)current_req->buffer)) >> 9; | 2720 | if ((unsigned long)max_size > dma_limit) |
2758 | if ((unsigned long)max_size > dma_limit) { | ||
2759 | max_size = dma_limit; | 2721 | max_size = dma_limit; |
2760 | } | ||
2761 | /* 64 kb boundaries */ | 2722 | /* 64 kb boundaries */ |
2762 | if (CROSS_64KB(current_req->buffer, max_size << 9)) | 2723 | if (CROSS_64KB(current_req->buffer, max_size << 9)) |
2763 | max_size = (K_64 - | 2724 | max_size = (K_64 - |
@@ -2773,16 +2734,16 @@ static int make_raw_rw_request(void) | |||
2773 | */ | 2734 | */ |
2774 | if (!direct || | 2735 | if (!direct || |
2775 | (indirect * 2 > direct * 3 && | 2736 | (indirect * 2 > direct * 3 && |
2776 | *errors < DP->max_errors.read_track && ((!probing | 2737 | *errors < DP->max_errors.read_track && |
2777 | || (DP->read_track & (1 << DRS->probed_format)))))) { | 2738 | ((!probing || |
2739 | (DP->read_track & (1 << DRS->probed_format)))))) { | ||
2778 | max_size = blk_rq_sectors(current_req); | 2740 | max_size = blk_rq_sectors(current_req); |
2779 | } else { | 2741 | } else { |
2780 | raw_cmd->kernel_data = current_req->buffer; | 2742 | raw_cmd->kernel_data = current_req->buffer; |
2781 | raw_cmd->length = current_count_sectors << 9; | 2743 | raw_cmd->length = current_count_sectors << 9; |
2782 | if (raw_cmd->length == 0) { | 2744 | if (raw_cmd->length == 0) { |
2783 | DPRINT | 2745 | DPRINT("%s: zero dma transfer attempted\n", __func__); |
2784 | ("zero dma transfer attempted from make_raw_request\n"); | 2746 | DPRINT("indirect=%d direct=%d fsector_t=%d\n", |
2785 | DPRINT("indirect=%d direct=%d fsector_t=%d", | ||
2786 | indirect, direct, fsector_t); | 2747 | indirect, direct, fsector_t); |
2787 | return 0; | 2748 | return 0; |
2788 | } | 2749 | } |
@@ -2802,25 +2763,22 @@ static int make_raw_rw_request(void) | |||
2802 | ((CT(COMMAND) == FD_READ || | 2763 | ((CT(COMMAND) == FD_READ || |
2803 | (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) && | 2764 | (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) && |
2804 | max_sector > 2 * max_buffer_sectors + buffer_min && | 2765 | max_sector > 2 * max_buffer_sectors + buffer_min && |
2805 | max_size + fsector_t > 2 * max_buffer_sectors + buffer_min) | 2766 | max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)) { |
2806 | /* not enough space */ | 2767 | /* not enough space */ |
2807 | ) { | ||
2808 | buffer_track = -1; | 2768 | buffer_track = -1; |
2809 | buffer_drive = current_drive; | 2769 | buffer_drive = current_drive; |
2810 | buffer_max = buffer_min = aligned_sector_t; | 2770 | buffer_max = buffer_min = aligned_sector_t; |
2811 | } | 2771 | } |
2812 | raw_cmd->kernel_data = floppy_track_buffer + | 2772 | raw_cmd->kernel_data = floppy_track_buffer + |
2813 | ((aligned_sector_t - buffer_min) << 9); | 2773 | ((aligned_sector_t - buffer_min) << 9); |
2814 | 2774 | ||
2815 | if (CT(COMMAND) == FD_WRITE) { | 2775 | if (CT(COMMAND) == FD_WRITE) { |
2816 | /* copy write buffer to track buffer. | 2776 | /* copy write buffer to track buffer. |
2817 | * if we get here, we know that the write | 2777 | * if we get here, we know that the write |
2818 | * is either aligned or the data already in the buffer | 2778 | * is either aligned or the data already in the buffer |
2819 | * (buffer will be overwritten) */ | 2779 | * (buffer will be overwritten) */ |
2820 | #ifdef FLOPPY_SANITY_CHECK | ||
2821 | if (in_sector_offset && buffer_track == -1) | 2780 | if (in_sector_offset && buffer_track == -1) |
2822 | DPRINT("internal error offset !=0 on write\n"); | 2781 | DPRINT("internal error offset !=0 on write\n"); |
2823 | #endif | ||
2824 | buffer_track = raw_cmd->track; | 2782 | buffer_track = raw_cmd->track; |
2825 | buffer_drive = current_drive; | 2783 | buffer_drive = current_drive; |
2826 | copy_buffer(ssize, max_sector, | 2784 | copy_buffer(ssize, max_sector, |
@@ -2834,7 +2792,6 @@ static int make_raw_rw_request(void) | |||
2834 | raw_cmd->length = in_sector_offset + current_count_sectors; | 2792 | raw_cmd->length = in_sector_offset + current_count_sectors; |
2835 | raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; | 2793 | raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1; |
2836 | raw_cmd->length <<= 9; | 2794 | raw_cmd->length <<= 9; |
2837 | #ifdef FLOPPY_SANITY_CHECK | ||
2838 | if ((raw_cmd->length < current_count_sectors << 9) || | 2795 | if ((raw_cmd->length < current_count_sectors << 9) || |
2839 | (raw_cmd->kernel_data != current_req->buffer && | 2796 | (raw_cmd->kernel_data != current_req->buffer && |
2840 | CT(COMMAND) == FD_WRITE && | 2797 | CT(COMMAND) == FD_WRITE && |
@@ -2845,19 +2802,19 @@ static int make_raw_rw_request(void) | |||
2845 | DPRINT("fractionary current count b=%lx s=%lx\n", | 2802 | DPRINT("fractionary current count b=%lx s=%lx\n", |
2846 | raw_cmd->length, current_count_sectors); | 2803 | raw_cmd->length, current_count_sectors); |
2847 | if (raw_cmd->kernel_data != current_req->buffer) | 2804 | if (raw_cmd->kernel_data != current_req->buffer) |
2848 | printk("addr=%d, length=%ld\n", | 2805 | pr_info("addr=%d, length=%ld\n", |
2849 | (int)((raw_cmd->kernel_data - | 2806 | (int)((raw_cmd->kernel_data - |
2850 | floppy_track_buffer) >> 9), | 2807 | floppy_track_buffer) >> 9), |
2851 | current_count_sectors); | 2808 | current_count_sectors); |
2852 | printk("st=%d ast=%d mse=%d msi=%d\n", | 2809 | pr_info("st=%d ast=%d mse=%d msi=%d\n", |
2853 | fsector_t, aligned_sector_t, max_sector, max_size); | 2810 | fsector_t, aligned_sector_t, max_sector, max_size); |
2854 | printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); | 2811 | pr_info("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); |
2855 | printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", | 2812 | pr_info("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", |
2856 | COMMAND, SECTOR, HEAD, TRACK); | 2813 | COMMAND, SECTOR, HEAD, TRACK); |
2857 | printk("buffer drive=%d\n", buffer_drive); | 2814 | pr_info("buffer drive=%d\n", buffer_drive); |
2858 | printk("buffer track=%d\n", buffer_track); | 2815 | pr_info("buffer track=%d\n", buffer_track); |
2859 | printk("buffer_min=%d\n", buffer_min); | 2816 | pr_info("buffer_min=%d\n", buffer_min); |
2860 | printk("buffer_max=%d\n", buffer_max); | 2817 | pr_info("buffer_max=%d\n", buffer_max); |
2861 | return 0; | 2818 | return 0; |
2862 | } | 2819 | } |
2863 | 2820 | ||
@@ -2868,14 +2825,14 @@ static int make_raw_rw_request(void) | |||
2868 | raw_cmd->kernel_data + raw_cmd->length > | 2825 | raw_cmd->kernel_data + raw_cmd->length > |
2869 | floppy_track_buffer + (max_buffer_sectors << 10)) { | 2826 | floppy_track_buffer + (max_buffer_sectors << 10)) { |
2870 | DPRINT("buffer overrun in schedule dma\n"); | 2827 | DPRINT("buffer overrun in schedule dma\n"); |
2871 | printk("fsector_t=%d buffer_min=%d current_count=%ld\n", | 2828 | pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n", |
2872 | fsector_t, buffer_min, raw_cmd->length >> 9); | 2829 | fsector_t, buffer_min, raw_cmd->length >> 9); |
2873 | printk("current_count_sectors=%ld\n", | 2830 | pr_info("current_count_sectors=%ld\n", |
2874 | current_count_sectors); | 2831 | current_count_sectors); |
2875 | if (CT(COMMAND) == FD_READ) | 2832 | if (CT(COMMAND) == FD_READ) |
2876 | printk("read\n"); | 2833 | pr_info("read\n"); |
2877 | if (CT(COMMAND) == FD_WRITE) | 2834 | if (CT(COMMAND) == FD_WRITE) |
2878 | printk("write\n"); | 2835 | pr_info("write\n"); |
2879 | return 0; | 2836 | return 0; |
2880 | } | 2837 | } |
2881 | } else if (raw_cmd->length > blk_rq_bytes(current_req) || | 2838 | } else if (raw_cmd->length > blk_rq_bytes(current_req) || |
@@ -2884,14 +2841,13 @@ static int make_raw_rw_request(void) | |||
2884 | return 0; | 2841 | return 0; |
2885 | } else if (raw_cmd->length < current_count_sectors << 9) { | 2842 | } else if (raw_cmd->length < current_count_sectors << 9) { |
2886 | DPRINT("more sectors than bytes\n"); | 2843 | DPRINT("more sectors than bytes\n"); |
2887 | printk("bytes=%ld\n", raw_cmd->length >> 9); | 2844 | pr_info("bytes=%ld\n", raw_cmd->length >> 9); |
2888 | printk("sectors=%ld\n", current_count_sectors); | 2845 | pr_info("sectors=%ld\n", current_count_sectors); |
2889 | } | 2846 | } |
2890 | if (raw_cmd->length == 0) { | 2847 | if (raw_cmd->length == 0) { |
2891 | DPRINT("zero dma transfer attempted from make_raw_request\n"); | 2848 | DPRINT("zero dma transfer attempted from make_raw_request\n"); |
2892 | return 0; | 2849 | return 0; |
2893 | } | 2850 | } |
2894 | #endif | ||
2895 | 2851 | ||
2896 | virtualdmabug_workaround(); | 2852 | virtualdmabug_workaround(); |
2897 | return 2; | 2853 | return 2; |
@@ -2899,7 +2855,6 @@ static int make_raw_rw_request(void) | |||
2899 | 2855 | ||
2900 | static void redo_fd_request(void) | 2856 | static void redo_fd_request(void) |
2901 | { | 2857 | { |
2902 | #define REPEAT {request_done(0); continue; } | ||
2903 | int drive; | 2858 | int drive; |
2904 | int tmp; | 2859 | int tmp; |
2905 | 2860 | ||
@@ -2907,63 +2862,63 @@ static void redo_fd_request(void) | |||
2907 | if (current_drive < N_DRIVE) | 2862 | if (current_drive < N_DRIVE) |
2908 | floppy_off(current_drive); | 2863 | floppy_off(current_drive); |
2909 | 2864 | ||
2910 | for (;;) { | 2865 | do_request: |
2911 | if (!current_req) { | 2866 | if (!current_req) { |
2912 | struct request *req; | 2867 | struct request *req; |
2913 | |||
2914 | spin_lock_irq(floppy_queue->queue_lock); | ||
2915 | req = blk_fetch_request(floppy_queue); | ||
2916 | spin_unlock_irq(floppy_queue->queue_lock); | ||
2917 | if (!req) { | ||
2918 | do_floppy = NULL; | ||
2919 | unlock_fdc(); | ||
2920 | return; | ||
2921 | } | ||
2922 | current_req = req; | ||
2923 | } | ||
2924 | drive = (long)current_req->rq_disk->private_data; | ||
2925 | set_fdc(drive); | ||
2926 | reschedule_timeout(current_reqD, "redo fd request", 0); | ||
2927 | 2868 | ||
2928 | set_floppy(drive); | 2869 | spin_lock_irq(floppy_queue->queue_lock); |
2929 | raw_cmd = &default_raw_cmd; | 2870 | req = blk_fetch_request(floppy_queue); |
2930 | raw_cmd->flags = 0; | 2871 | spin_unlock_irq(floppy_queue->queue_lock); |
2931 | if (start_motor(redo_fd_request)) | 2872 | if (!req) { |
2873 | do_floppy = NULL; | ||
2874 | unlock_fdc(); | ||
2932 | return; | 2875 | return; |
2933 | disk_change(current_drive); | ||
2934 | if (test_bit(current_drive, &fake_change) || | ||
2935 | TESTF(FD_DISK_CHANGED)) { | ||
2936 | DPRINT("disk absent or changed during operation\n"); | ||
2937 | REPEAT; | ||
2938 | } | ||
2939 | if (!_floppy) { /* Autodetection */ | ||
2940 | if (!probing) { | ||
2941 | DRS->probed_format = 0; | ||
2942 | if (next_valid_format()) { | ||
2943 | DPRINT("no autodetectable formats\n"); | ||
2944 | _floppy = NULL; | ||
2945 | REPEAT; | ||
2946 | } | ||
2947 | } | ||
2948 | probing = 1; | ||
2949 | _floppy = | ||
2950 | floppy_type + DP->autodetect[DRS->probed_format]; | ||
2951 | } else | ||
2952 | probing = 0; | ||
2953 | errors = &(current_req->errors); | ||
2954 | tmp = make_raw_rw_request(); | ||
2955 | if (tmp < 2) { | ||
2956 | request_done(tmp); | ||
2957 | continue; | ||
2958 | } | 2876 | } |
2877 | current_req = req; | ||
2878 | } | ||
2879 | drive = (long)current_req->rq_disk->private_data; | ||
2880 | set_fdc(drive); | ||
2881 | reschedule_timeout(current_reqD, "redo fd request"); | ||
2959 | 2882 | ||
2960 | if (TESTF(FD_NEED_TWADDLE)) | 2883 | set_floppy(drive); |
2961 | twaddle(); | 2884 | raw_cmd = &default_raw_cmd; |
2962 | schedule_bh(floppy_start); | 2885 | raw_cmd->flags = 0; |
2963 | debugt("queue fd request"); | 2886 | if (start_motor(redo_fd_request)) |
2964 | return; | 2887 | return; |
2888 | |||
2889 | disk_change(current_drive); | ||
2890 | if (test_bit(current_drive, &fake_change) || | ||
2891 | test_bit(FD_DISK_CHANGED_BIT, &DRS->flags)) { | ||
2892 | DPRINT("disk absent or changed during operation\n"); | ||
2893 | request_done(0); | ||
2894 | goto do_request; | ||
2895 | } | ||
2896 | if (!_floppy) { /* Autodetection */ | ||
2897 | if (!probing) { | ||
2898 | DRS->probed_format = 0; | ||
2899 | if (next_valid_format()) { | ||
2900 | DPRINT("no autodetectable formats\n"); | ||
2901 | _floppy = NULL; | ||
2902 | request_done(0); | ||
2903 | goto do_request; | ||
2904 | } | ||
2905 | } | ||
2906 | probing = 1; | ||
2907 | _floppy = floppy_type + DP->autodetect[DRS->probed_format]; | ||
2908 | } else | ||
2909 | probing = 0; | ||
2910 | errors = &(current_req->errors); | ||
2911 | tmp = make_raw_rw_request(); | ||
2912 | if (tmp < 2) { | ||
2913 | request_done(tmp); | ||
2914 | goto do_request; | ||
2965 | } | 2915 | } |
2966 | #undef REPEAT | 2916 | |
2917 | if (test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) | ||
2918 | twaddle(); | ||
2919 | schedule_bh(floppy_start); | ||
2920 | debugt(__func__, "queue fd request"); | ||
2921 | return; | ||
2967 | } | 2922 | } |
2968 | 2923 | ||
2969 | static struct cont_t rw_cont = { | 2924 | static struct cont_t rw_cont = { |
@@ -2979,30 +2934,30 @@ static void process_fd_request(void) | |||
2979 | schedule_bh(redo_fd_request); | 2934 | schedule_bh(redo_fd_request); |
2980 | } | 2935 | } |
2981 | 2936 | ||
2982 | static void do_fd_request(struct request_queue * q) | 2937 | static void do_fd_request(struct request_queue *q) |
2983 | { | 2938 | { |
2984 | if (max_buffer_sectors == 0) { | 2939 | if (max_buffer_sectors == 0) { |
2985 | printk("VFS: do_fd_request called on non-open device\n"); | 2940 | pr_info("VFS: %s called on non-open device\n", __func__); |
2986 | return; | 2941 | return; |
2987 | } | 2942 | } |
2988 | 2943 | ||
2989 | if (usage_count == 0) { | 2944 | if (usage_count == 0) { |
2990 | printk("warning: usage count=0, current_req=%p exiting\n", | 2945 | pr_info("warning: usage count=0, current_req=%p exiting\n", |
2991 | current_req); | 2946 | current_req); |
2992 | printk("sect=%ld type=%x flags=%x\n", | 2947 | pr_info("sect=%ld type=%x flags=%x\n", |
2993 | (long)blk_rq_pos(current_req), current_req->cmd_type, | 2948 | (long)blk_rq_pos(current_req), current_req->cmd_type, |
2994 | current_req->cmd_flags); | 2949 | current_req->cmd_flags); |
2995 | return; | 2950 | return; |
2996 | } | 2951 | } |
2997 | if (test_bit(0, &fdc_busy)) { | 2952 | if (test_bit(0, &fdc_busy)) { |
2998 | /* fdc busy, this new request will be treated when the | 2953 | /* fdc busy, this new request will be treated when the |
2999 | current one is done */ | 2954 | current one is done */ |
3000 | is_alive("do fd request, old request running"); | 2955 | is_alive(__func__, "old request running"); |
3001 | return; | 2956 | return; |
3002 | } | 2957 | } |
3003 | lock_fdc(MAXTIMEOUT, 0); | 2958 | lock_fdc(MAXTIMEOUT, false); |
3004 | process_fd_request(); | 2959 | process_fd_request(); |
3005 | is_alive("do fd request"); | 2960 | is_alive(__func__, ""); |
3006 | } | 2961 | } |
3007 | 2962 | ||
3008 | static struct cont_t poll_cont = { | 2963 | static struct cont_t poll_cont = { |
@@ -3012,24 +2967,18 @@ static struct cont_t poll_cont = { | |||
3012 | .done = generic_done | 2967 | .done = generic_done |
3013 | }; | 2968 | }; |
3014 | 2969 | ||
3015 | static int poll_drive(int interruptible, int flag) | 2970 | static int poll_drive(bool interruptible, int flag) |
3016 | { | 2971 | { |
3017 | int ret; | ||
3018 | |||
3019 | /* no auto-sense, just clear dcl */ | 2972 | /* no auto-sense, just clear dcl */ |
3020 | raw_cmd = &default_raw_cmd; | 2973 | raw_cmd = &default_raw_cmd; |
3021 | raw_cmd->flags = flag; | 2974 | raw_cmd->flags = flag; |
3022 | raw_cmd->track = 0; | 2975 | raw_cmd->track = 0; |
3023 | raw_cmd->cmd_count = 0; | 2976 | raw_cmd->cmd_count = 0; |
3024 | cont = &poll_cont; | 2977 | cont = &poll_cont; |
3025 | #ifdef DCL_DEBUG | 2978 | debug_dcl(DP->flags, "setting NEWCHANGE in poll_drive\n"); |
3026 | if (DP->flags & FD_DEBUG) { | 2979 | set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags); |
3027 | DPRINT("setting NEWCHANGE in poll_drive\n"); | 2980 | |
3028 | } | 2981 | return wait_til_done(floppy_ready, interruptible); |
3029 | #endif | ||
3030 | SETF(FD_DISK_NEWCHANGE); | ||
3031 | WAIT(floppy_ready); | ||
3032 | return ret; | ||
3033 | } | 2982 | } |
3034 | 2983 | ||
3035 | /* | 2984 | /* |
@@ -3039,7 +2988,7 @@ static int poll_drive(int interruptible, int flag) | |||
3039 | 2988 | ||
3040 | static void reset_intr(void) | 2989 | static void reset_intr(void) |
3041 | { | 2990 | { |
3042 | printk("weird, reset interrupt called\n"); | 2991 | pr_info("weird, reset interrupt called\n"); |
3043 | } | 2992 | } |
3044 | 2993 | ||
3045 | static struct cont_t reset_cont = { | 2994 | static struct cont_t reset_cont = { |
@@ -3049,20 +2998,23 @@ static struct cont_t reset_cont = { | |||
3049 | .done = generic_done | 2998 | .done = generic_done |
3050 | }; | 2999 | }; |
3051 | 3000 | ||
3052 | static int user_reset_fdc(int drive, int arg, int interruptible) | 3001 | static int user_reset_fdc(int drive, int arg, bool interruptible) |
3053 | { | 3002 | { |
3054 | int ret; | 3003 | int ret; |
3055 | 3004 | ||
3056 | ret = 0; | 3005 | if (lock_fdc(drive, interruptible)) |
3057 | LOCK_FDC(drive, interruptible); | 3006 | return -EINTR; |
3007 | |||
3058 | if (arg == FD_RESET_ALWAYS) | 3008 | if (arg == FD_RESET_ALWAYS) |
3059 | FDCS->reset = 1; | 3009 | FDCS->reset = 1; |
3060 | if (FDCS->reset) { | 3010 | if (FDCS->reset) { |
3061 | cont = &reset_cont; | 3011 | cont = &reset_cont; |
3062 | WAIT(reset_fdc); | 3012 | ret = wait_til_done(reset_fdc, interruptible); |
3013 | if (ret == -EINTR) | ||
3014 | return -EINTR; | ||
3063 | } | 3015 | } |
3064 | process_fd_request(); | 3016 | process_fd_request(); |
3065 | return ret; | 3017 | return 0; |
3066 | } | 3018 | } |
3067 | 3019 | ||
3068 | /* | 3020 | /* |
@@ -3075,17 +3027,12 @@ static inline int fd_copyout(void __user *param, const void *address, | |||
3075 | return copy_to_user(param, address, size) ? -EFAULT : 0; | 3027 | return copy_to_user(param, address, size) ? -EFAULT : 0; |
3076 | } | 3028 | } |
3077 | 3029 | ||
3078 | static inline int fd_copyin(void __user *param, void *address, unsigned long size) | 3030 | static inline int fd_copyin(void __user *param, void *address, |
3031 | unsigned long size) | ||
3079 | { | 3032 | { |
3080 | return copy_from_user(address, param, size) ? -EFAULT : 0; | 3033 | return copy_from_user(address, param, size) ? -EFAULT : 0; |
3081 | } | 3034 | } |
3082 | 3035 | ||
3083 | #define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0) | ||
3084 | #define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0) | ||
3085 | |||
3086 | #define COPYOUT(x) ECALL(_COPYOUT(x)) | ||
3087 | #define COPYIN(x) ECALL(_COPYIN(x)) | ||
3088 | |||
3089 | static inline const char *drive_name(int type, int drive) | 3036 | static inline const char *drive_name(int type, int drive) |
3090 | { | 3037 | { |
3091 | struct floppy_struct *floppy; | 3038 | struct floppy_struct *floppy; |
@@ -3156,23 +3103,29 @@ static struct cont_t raw_cmd_cont = { | |||
3156 | .done = raw_cmd_done | 3103 | .done = raw_cmd_done |
3157 | }; | 3104 | }; |
3158 | 3105 | ||
3159 | static inline int raw_cmd_copyout(int cmd, char __user *param, | 3106 | static inline int raw_cmd_copyout(int cmd, void __user *param, |
3160 | struct floppy_raw_cmd *ptr) | 3107 | struct floppy_raw_cmd *ptr) |
3161 | { | 3108 | { |
3162 | int ret; | 3109 | int ret; |
3163 | 3110 | ||
3164 | while (ptr) { | 3111 | while (ptr) { |
3165 | COPYOUT(*ptr); | 3112 | ret = copy_to_user(param, ptr, sizeof(*ptr)); |
3113 | if (ret) | ||
3114 | return -EFAULT; | ||
3166 | param += sizeof(struct floppy_raw_cmd); | 3115 | param += sizeof(struct floppy_raw_cmd); |
3167 | if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) { | 3116 | if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) { |
3168 | if (ptr->length >= 0 | 3117 | if (ptr->length >= 0 && |
3169 | && ptr->length <= ptr->buffer_length) | 3118 | ptr->length <= ptr->buffer_length) { |
3170 | ECALL(fd_copyout | 3119 | long length = ptr->buffer_length - ptr->length; |
3171 | (ptr->data, ptr->kernel_data, | 3120 | ret = fd_copyout(ptr->data, ptr->kernel_data, |
3172 | ptr->buffer_length - ptr->length)); | 3121 | length); |
3122 | if (ret) | ||
3123 | return ret; | ||
3124 | } | ||
3173 | } | 3125 | } |
3174 | ptr = ptr->next; | 3126 | ptr = ptr->next; |
3175 | } | 3127 | } |
3128 | |||
3176 | return 0; | 3129 | return 0; |
3177 | } | 3130 | } |
3178 | 3131 | ||
@@ -3195,7 +3148,7 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr) | |||
3195 | } | 3148 | } |
3196 | } | 3149 | } |
3197 | 3150 | ||
3198 | static inline int raw_cmd_copyin(int cmd, char __user *param, | 3151 | static inline int raw_cmd_copyin(int cmd, void __user *param, |
3199 | struct floppy_raw_cmd **rcmd) | 3152 | struct floppy_raw_cmd **rcmd) |
3200 | { | 3153 | { |
3201 | struct floppy_raw_cmd *ptr; | 3154 | struct floppy_raw_cmd *ptr; |
@@ -3203,17 +3156,19 @@ static inline int raw_cmd_copyin(int cmd, char __user *param, | |||
3203 | int i; | 3156 | int i; |
3204 | 3157 | ||
3205 | *rcmd = NULL; | 3158 | *rcmd = NULL; |
3206 | while (1) { | 3159 | |
3207 | ptr = (struct floppy_raw_cmd *) | 3160 | loop: |
3208 | kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); | 3161 | ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); |
3209 | if (!ptr) | 3162 | if (!ptr) |
3210 | return -ENOMEM; | 3163 | return -ENOMEM; |
3211 | *rcmd = ptr; | 3164 | *rcmd = ptr; |
3212 | COPYIN(*ptr); | 3165 | ret = copy_from_user(ptr, param, sizeof(*ptr)); |
3213 | ptr->next = NULL; | 3166 | if (ret) |
3214 | ptr->buffer_length = 0; | 3167 | return -EFAULT; |
3215 | param += sizeof(struct floppy_raw_cmd); | 3168 | ptr->next = NULL; |
3216 | if (ptr->cmd_count > 33) | 3169 | ptr->buffer_length = 0; |
3170 | param += sizeof(struct floppy_raw_cmd); | ||
3171 | if (ptr->cmd_count > 33) | ||
3217 | /* the command may now also take up the space | 3172 | /* the command may now also take up the space |
3218 | * initially intended for the reply & the | 3173 | * initially intended for the reply & the |
3219 | * reply count. Needed for long 82078 commands | 3174 | * reply count. Needed for long 82078 commands |
@@ -3222,31 +3177,35 @@ static inline int raw_cmd_copyin(int cmd, char __user *param, | |||
3222 | * 16 bytes for a structure, you'll one day | 3177 | * 16 bytes for a structure, you'll one day |
3223 | * discover that you really need 17... | 3178 | * discover that you really need 17... |
3224 | */ | 3179 | */ |
3180 | return -EINVAL; | ||
3181 | |||
3182 | for (i = 0; i < 16; i++) | ||
3183 | ptr->reply[i] = 0; | ||
3184 | ptr->resultcode = 0; | ||
3185 | ptr->kernel_data = NULL; | ||
3186 | |||
3187 | if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { | ||
3188 | if (ptr->length <= 0) | ||
3225 | return -EINVAL; | 3189 | return -EINVAL; |
3190 | ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length); | ||
3191 | fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); | ||
3192 | if (!ptr->kernel_data) | ||
3193 | return -ENOMEM; | ||
3194 | ptr->buffer_length = ptr->length; | ||
3195 | } | ||
3196 | if (ptr->flags & FD_RAW_WRITE) { | ||
3197 | ret = fd_copyin(ptr->data, ptr->kernel_data, ptr->length); | ||
3198 | if (ret) | ||
3199 | return ret; | ||
3200 | } | ||
3226 | 3201 | ||
3227 | for (i = 0; i < 16; i++) | 3202 | if (ptr->flags & FD_RAW_MORE) { |
3228 | ptr->reply[i] = 0; | ||
3229 | ptr->resultcode = 0; | ||
3230 | ptr->kernel_data = NULL; | ||
3231 | |||
3232 | if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { | ||
3233 | if (ptr->length <= 0) | ||
3234 | return -EINVAL; | ||
3235 | ptr->kernel_data = | ||
3236 | (char *)fd_dma_mem_alloc(ptr->length); | ||
3237 | fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); | ||
3238 | if (!ptr->kernel_data) | ||
3239 | return -ENOMEM; | ||
3240 | ptr->buffer_length = ptr->length; | ||
3241 | } | ||
3242 | if (ptr->flags & FD_RAW_WRITE) | ||
3243 | ECALL(fd_copyin(ptr->data, ptr->kernel_data, | ||
3244 | ptr->length)); | ||
3245 | rcmd = &(ptr->next); | 3203 | rcmd = &(ptr->next); |
3246 | if (!(ptr->flags & FD_RAW_MORE)) | ||
3247 | return 0; | ||
3248 | ptr->rate &= 0x43; | 3204 | ptr->rate &= 0x43; |
3205 | goto loop; | ||
3249 | } | 3206 | } |
3207 | |||
3208 | return 0; | ||
3250 | } | 3209 | } |
3251 | 3210 | ||
3252 | static int raw_cmd_ioctl(int cmd, void __user *param) | 3211 | static int raw_cmd_ioctl(int cmd, void __user *param) |
@@ -3283,12 +3242,8 @@ static int raw_cmd_ioctl(int cmd, void __user *param) | |||
3283 | 3242 | ||
3284 | raw_cmd = my_raw_cmd; | 3243 | raw_cmd = my_raw_cmd; |
3285 | cont = &raw_cmd_cont; | 3244 | cont = &raw_cmd_cont; |
3286 | ret = wait_til_done(floppy_start, 1); | 3245 | ret = wait_til_done(floppy_start, true); |
3287 | #ifdef DCL_DEBUG | 3246 | debug_dcl(DP->flags, "calling disk change from raw_cmd ioctl\n"); |
3288 | if (DP->flags & FD_DEBUG) { | ||
3289 | DPRINT("calling disk change from raw_cmd ioctl\n"); | ||
3290 | } | ||
3291 | #endif | ||
3292 | 3247 | ||
3293 | if (ret != -EINTR && FDCS->reset) | 3248 | if (ret != -EINTR && FDCS->reset) |
3294 | ret = -EIO; | 3249 | ret = -EIO; |
@@ -3327,7 +3282,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, | |||
3327 | if (!capable(CAP_SYS_ADMIN)) | 3282 | if (!capable(CAP_SYS_ADMIN)) |
3328 | return -EPERM; | 3283 | return -EPERM; |
3329 | mutex_lock(&open_lock); | 3284 | mutex_lock(&open_lock); |
3330 | if (lock_fdc(drive, 1)) { | 3285 | if (lock_fdc(drive, true)) { |
3331 | mutex_unlock(&open_lock); | 3286 | mutex_unlock(&open_lock); |
3332 | return -EINTR; | 3287 | return -EINTR; |
3333 | } | 3288 | } |
@@ -3346,11 +3301,15 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, | |||
3346 | mutex_unlock(&open_lock); | 3301 | mutex_unlock(&open_lock); |
3347 | } else { | 3302 | } else { |
3348 | int oldStretch; | 3303 | int oldStretch; |
3349 | LOCK_FDC(drive, 1); | 3304 | |
3350 | if (cmd != FDDEFPRM) | 3305 | if (lock_fdc(drive, true)) |
3306 | return -EINTR; | ||
3307 | if (cmd != FDDEFPRM) { | ||
3351 | /* notice a disk change immediately, else | 3308 | /* notice a disk change immediately, else |
3352 | * we lose our settings immediately*/ | 3309 | * we lose our settings immediately*/ |
3353 | CALL(poll_drive(1, FD_RAW_NEED_DISK)); | 3310 | if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) |
3311 | return -EINTR; | ||
3312 | } | ||
3354 | oldStretch = g->stretch; | 3313 | oldStretch = g->stretch; |
3355 | user_params[drive] = *g; | 3314 | user_params[drive] = *g; |
3356 | if (buffer_drive == drive) | 3315 | if (buffer_drive == drive) |
@@ -3415,7 +3374,7 @@ static inline int normalize_ioctl(int *cmd, int *size) | |||
3415 | *size = _IOC_SIZE(*cmd); | 3374 | *size = _IOC_SIZE(*cmd); |
3416 | *cmd = ioctl_table[i]; | 3375 | *cmd = ioctl_table[i]; |
3417 | if (*size > _IOC_SIZE(*cmd)) { | 3376 | if (*size > _IOC_SIZE(*cmd)) { |
3418 | printk("ioctl not yet supported\n"); | 3377 | pr_info("ioctl not yet supported\n"); |
3419 | return -EFAULT; | 3378 | return -EFAULT; |
3420 | } | 3379 | } |
3421 | return 0; | 3380 | return 0; |
@@ -3429,8 +3388,10 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) | |||
3429 | if (type) | 3388 | if (type) |
3430 | *g = &floppy_type[type]; | 3389 | *g = &floppy_type[type]; |
3431 | else { | 3390 | else { |
3432 | LOCK_FDC(drive, 0); | 3391 | if (lock_fdc(drive, false)) |
3433 | CALL(poll_drive(0, 0)); | 3392 | return -EINTR; |
3393 | if (poll_drive(false, 0) == -EINTR) | ||
3394 | return -EINTR; | ||
3434 | process_fd_request(); | 3395 | process_fd_request(); |
3435 | *g = current_type[drive]; | 3396 | *g = current_type[drive]; |
3436 | } | 3397 | } |
@@ -3459,10 +3420,6 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
3459 | static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | 3420 | static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, |
3460 | unsigned long param) | 3421 | unsigned long param) |
3461 | { | 3422 | { |
3462 | #define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL)) | ||
3463 | #define OUT(c,x) case c: outparam = (const char *) (x); break | ||
3464 | #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 | ||
3465 | |||
3466 | int drive = (long)bdev->bd_disk->private_data; | 3423 | int drive = (long)bdev->bd_disk->private_data; |
3467 | int type = ITYPE(UDRS->fd_device); | 3424 | int type = ITYPE(UDRS->fd_device); |
3468 | int i; | 3425 | int i; |
@@ -3474,26 +3431,28 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | |||
3474 | struct floppy_max_errors max_errors; | 3431 | struct floppy_max_errors max_errors; |
3475 | struct floppy_drive_params dp; | 3432 | struct floppy_drive_params dp; |
3476 | } inparam; /* parameters coming from user space */ | 3433 | } inparam; /* parameters coming from user space */ |
3477 | const char *outparam; /* parameters passed back to user space */ | 3434 | const void *outparam; /* parameters passed back to user space */ |
3478 | 3435 | ||
3479 | /* convert compatibility eject ioctls into floppy eject ioctl. | 3436 | /* convert compatibility eject ioctls into floppy eject ioctl. |
3480 | * We do this in order to provide a means to eject floppy disks before | 3437 | * We do this in order to provide a means to eject floppy disks before |
3481 | * installing the new fdutils package */ | 3438 | * installing the new fdutils package */ |
3482 | if (cmd == CDROMEJECT || /* CD-ROM eject */ | 3439 | if (cmd == CDROMEJECT || /* CD-ROM eject */ |
3483 | cmd == 0x6470 /* SunOS floppy eject */ ) { | 3440 | cmd == 0x6470) { /* SunOS floppy eject */ |
3484 | DPRINT("obsolete eject ioctl\n"); | 3441 | DPRINT("obsolete eject ioctl\n"); |
3485 | DPRINT("please use floppycontrol --eject\n"); | 3442 | DPRINT("please use floppycontrol --eject\n"); |
3486 | cmd = FDEJECT; | 3443 | cmd = FDEJECT; |
3487 | } | 3444 | } |
3488 | 3445 | ||
3489 | /* convert the old style command into a new style command */ | 3446 | if (!((cmd & 0xff00) == 0x0200)) |
3490 | if ((cmd & 0xff00) == 0x0200) { | ||
3491 | ECALL(normalize_ioctl(&cmd, &size)); | ||
3492 | } else | ||
3493 | return -EINVAL; | 3447 | return -EINVAL; |
3494 | 3448 | ||
3449 | /* convert the old style command into a new style command */ | ||
3450 | ret = normalize_ioctl(&cmd, &size); | ||
3451 | if (ret) | ||
3452 | return ret; | ||
3453 | |||
3495 | /* permission checks */ | 3454 | /* permission checks */ |
3496 | if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) || | 3455 | if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) || |
3497 | ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) | 3456 | ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) |
3498 | return -EPERM; | 3457 | return -EPERM; |
3499 | 3458 | ||
@@ -3501,129 +3460,142 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | |||
3501 | return -EINVAL; | 3460 | return -EINVAL; |
3502 | 3461 | ||
3503 | /* copyin */ | 3462 | /* copyin */ |
3504 | CLEARSTRUCT(&inparam); | 3463 | memset(&inparam, 0, sizeof(inparam)); |
3505 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 3464 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
3506 | ECALL(fd_copyin((void __user *)param, &inparam, size)) | 3465 | ret = fd_copyin((void __user *)param, &inparam, size); |
3507 | 3466 | if (ret) | |
3508 | switch (cmd) { | ||
3509 | case FDEJECT: | ||
3510 | if (UDRS->fd_ref != 1) | ||
3511 | /* somebody else has this drive open */ | ||
3512 | return -EBUSY; | ||
3513 | LOCK_FDC(drive, 1); | ||
3514 | |||
3515 | /* do the actual eject. Fails on | ||
3516 | * non-Sparc architectures */ | ||
3517 | ret = fd_eject(UNIT(drive)); | ||
3518 | |||
3519 | USETF(FD_DISK_CHANGED); | ||
3520 | USETF(FD_VERIFY); | ||
3521 | process_fd_request(); | ||
3522 | return ret; | 3467 | return ret; |
3523 | case FDCLRPRM: | 3468 | } |
3524 | LOCK_FDC(drive, 1); | ||
3525 | current_type[drive] = NULL; | ||
3526 | floppy_sizes[drive] = MAX_DISK_SIZE << 1; | ||
3527 | UDRS->keep_data = 0; | ||
3528 | return invalidate_drive(bdev); | ||
3529 | case FDSETPRM: | ||
3530 | case FDDEFPRM: | ||
3531 | return set_geometry(cmd, &inparam.g, | ||
3532 | drive, type, bdev); | ||
3533 | case FDGETPRM: | ||
3534 | ECALL(get_floppy_geometry(drive, type, | ||
3535 | (struct floppy_struct **) | ||
3536 | &outparam)); | ||
3537 | break; | ||
3538 | |||
3539 | case FDMSGON: | ||
3540 | UDP->flags |= FTD_MSG; | ||
3541 | return 0; | ||
3542 | case FDMSGOFF: | ||
3543 | UDP->flags &= ~FTD_MSG; | ||
3544 | return 0; | ||
3545 | |||
3546 | case FDFMTBEG: | ||
3547 | LOCK_FDC(drive, 1); | ||
3548 | CALL(poll_drive(1, FD_RAW_NEED_DISK)); | ||
3549 | ret = UDRS->flags; | ||
3550 | process_fd_request(); | ||
3551 | if (ret & FD_VERIFY) | ||
3552 | return -ENODEV; | ||
3553 | if (!(ret & FD_DISK_WRITABLE)) | ||
3554 | return -EROFS; | ||
3555 | return 0; | ||
3556 | case FDFMTTRK: | ||
3557 | if (UDRS->fd_ref != 1) | ||
3558 | return -EBUSY; | ||
3559 | return do_format(drive, &inparam.f); | ||
3560 | case FDFMTEND: | ||
3561 | case FDFLUSH: | ||
3562 | LOCK_FDC(drive, 1); | ||
3563 | return invalidate_drive(bdev); | ||
3564 | |||
3565 | case FDSETEMSGTRESH: | ||
3566 | UDP->max_errors.reporting = | ||
3567 | (unsigned short)(param & 0x0f); | ||
3568 | return 0; | ||
3569 | OUT(FDGETMAXERRS, &UDP->max_errors); | ||
3570 | IN(FDSETMAXERRS, &UDP->max_errors, max_errors); | ||
3571 | |||
3572 | case FDGETDRVTYP: | ||
3573 | outparam = drive_name(type, drive); | ||
3574 | SUPBOUND(size, strlen(outparam) + 1); | ||
3575 | break; | ||
3576 | |||
3577 | IN(FDSETDRVPRM, UDP, dp); | ||
3578 | OUT(FDGETDRVPRM, UDP); | ||
3579 | |||
3580 | case FDPOLLDRVSTAT: | ||
3581 | LOCK_FDC(drive, 1); | ||
3582 | CALL(poll_drive(1, FD_RAW_NEED_DISK)); | ||
3583 | process_fd_request(); | ||
3584 | /* fall through */ | ||
3585 | OUT(FDGETDRVSTAT, UDRS); | ||
3586 | |||
3587 | case FDRESET: | ||
3588 | return user_reset_fdc(drive, (int)param, 1); | ||
3589 | |||
3590 | OUT(FDGETFDCSTAT, UFDCS); | ||
3591 | 3469 | ||
3592 | case FDWERRORCLR: | 3470 | switch (cmd) { |
3593 | CLEARSTRUCT(UDRWE); | 3471 | case FDEJECT: |
3594 | return 0; | 3472 | if (UDRS->fd_ref != 1) |
3595 | OUT(FDWERRORGET, UDRWE); | 3473 | /* somebody else has this drive open */ |
3596 | 3474 | return -EBUSY; | |
3597 | case FDRAWCMD: | 3475 | if (lock_fdc(drive, true)) |
3598 | if (type) | 3476 | return -EINTR; |
3599 | return -EINVAL; | ||
3600 | LOCK_FDC(drive, 1); | ||
3601 | set_floppy(drive); | ||
3602 | CALL(i = raw_cmd_ioctl(cmd, (void __user *)param)); | ||
3603 | process_fd_request(); | ||
3604 | return i; | ||
3605 | 3477 | ||
3606 | case FDTWADDLE: | 3478 | /* do the actual eject. Fails on |
3607 | LOCK_FDC(drive, 1); | 3479 | * non-Sparc architectures */ |
3608 | twaddle(); | 3480 | ret = fd_eject(UNIT(drive)); |
3609 | process_fd_request(); | ||
3610 | return 0; | ||
3611 | 3481 | ||
3612 | default: | 3482 | set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); |
3483 | set_bit(FD_VERIFY_BIT, &UDRS->flags); | ||
3484 | process_fd_request(); | ||
3485 | return ret; | ||
3486 | case FDCLRPRM: | ||
3487 | if (lock_fdc(drive, true)) | ||
3488 | return -EINTR; | ||
3489 | current_type[drive] = NULL; | ||
3490 | floppy_sizes[drive] = MAX_DISK_SIZE << 1; | ||
3491 | UDRS->keep_data = 0; | ||
3492 | return invalidate_drive(bdev); | ||
3493 | case FDSETPRM: | ||
3494 | case FDDEFPRM: | ||
3495 | return set_geometry(cmd, &inparam.g, drive, type, bdev); | ||
3496 | case FDGETPRM: | ||
3497 | ret = get_floppy_geometry(drive, type, | ||
3498 | (struct floppy_struct **)&outparam); | ||
3499 | if (ret) | ||
3500 | return ret; | ||
3501 | break; | ||
3502 | case FDMSGON: | ||
3503 | UDP->flags |= FTD_MSG; | ||
3504 | return 0; | ||
3505 | case FDMSGOFF: | ||
3506 | UDP->flags &= ~FTD_MSG; | ||
3507 | return 0; | ||
3508 | case FDFMTBEG: | ||
3509 | if (lock_fdc(drive, true)) | ||
3510 | return -EINTR; | ||
3511 | if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) | ||
3512 | return -EINTR; | ||
3513 | ret = UDRS->flags; | ||
3514 | process_fd_request(); | ||
3515 | if (ret & FD_VERIFY) | ||
3516 | return -ENODEV; | ||
3517 | if (!(ret & FD_DISK_WRITABLE)) | ||
3518 | return -EROFS; | ||
3519 | return 0; | ||
3520 | case FDFMTTRK: | ||
3521 | if (UDRS->fd_ref != 1) | ||
3522 | return -EBUSY; | ||
3523 | return do_format(drive, &inparam.f); | ||
3524 | case FDFMTEND: | ||
3525 | case FDFLUSH: | ||
3526 | if (lock_fdc(drive, true)) | ||
3527 | return -EINTR; | ||
3528 | return invalidate_drive(bdev); | ||
3529 | case FDSETEMSGTRESH: | ||
3530 | UDP->max_errors.reporting = (unsigned short)(param & 0x0f); | ||
3531 | return 0; | ||
3532 | case FDGETMAXERRS: | ||
3533 | outparam = &UDP->max_errors; | ||
3534 | break; | ||
3535 | case FDSETMAXERRS: | ||
3536 | UDP->max_errors = inparam.max_errors; | ||
3537 | break; | ||
3538 | case FDGETDRVTYP: | ||
3539 | outparam = drive_name(type, drive); | ||
3540 | SUPBOUND(size, strlen((const char *)outparam) + 1); | ||
3541 | break; | ||
3542 | case FDSETDRVPRM: | ||
3543 | *UDP = inparam.dp; | ||
3544 | break; | ||
3545 | case FDGETDRVPRM: | ||
3546 | outparam = UDP; | ||
3547 | break; | ||
3548 | case FDPOLLDRVSTAT: | ||
3549 | if (lock_fdc(drive, true)) | ||
3550 | return -EINTR; | ||
3551 | if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) | ||
3552 | return -EINTR; | ||
3553 | process_fd_request(); | ||
3554 | /* fall through */ | ||
3555 | case FDGETDRVSTAT: | ||
3556 | outparam = UDRS; | ||
3557 | break; | ||
3558 | case FDRESET: | ||
3559 | return user_reset_fdc(drive, (int)param, true); | ||
3560 | case FDGETFDCSTAT: | ||
3561 | outparam = UFDCS; | ||
3562 | break; | ||
3563 | case FDWERRORCLR: | ||
3564 | memset(UDRWE, 0, sizeof(*UDRWE)); | ||
3565 | return 0; | ||
3566 | case FDWERRORGET: | ||
3567 | outparam = UDRWE; | ||
3568 | break; | ||
3569 | case FDRAWCMD: | ||
3570 | if (type) | ||
3613 | return -EINVAL; | 3571 | return -EINVAL; |
3614 | } | 3572 | if (lock_fdc(drive, true)) |
3573 | return -EINTR; | ||
3574 | set_floppy(drive); | ||
3575 | i = raw_cmd_ioctl(cmd, (void __user *)param); | ||
3576 | if (i == -EINTR) | ||
3577 | return -EINTR; | ||
3578 | process_fd_request(); | ||
3579 | return i; | ||
3580 | case FDTWADDLE: | ||
3581 | if (lock_fdc(drive, true)) | ||
3582 | return -EINTR; | ||
3583 | twaddle(); | ||
3584 | process_fd_request(); | ||
3585 | return 0; | ||
3586 | default: | ||
3587 | return -EINVAL; | ||
3588 | } | ||
3615 | 3589 | ||
3616 | if (_IOC_DIR(cmd) & _IOC_READ) | 3590 | if (_IOC_DIR(cmd) & _IOC_READ) |
3617 | return fd_copyout((void __user *)param, outparam, size); | 3591 | return fd_copyout((void __user *)param, outparam, size); |
3618 | else | 3592 | |
3619 | return 0; | 3593 | return 0; |
3620 | #undef OUT | ||
3621 | #undef IN | ||
3622 | } | 3594 | } |
3623 | 3595 | ||
3624 | static void __init config_types(void) | 3596 | static void __init config_types(void) |
3625 | { | 3597 | { |
3626 | int first = 1; | 3598 | bool has_drive = false; |
3627 | int drive; | 3599 | int drive; |
3628 | 3600 | ||
3629 | /* read drive info out of physical CMOS */ | 3601 | /* read drive info out of physical CMOS */ |
@@ -3655,17 +3627,22 @@ static void __init config_types(void) | |||
3655 | name = temparea; | 3627 | name = temparea; |
3656 | } | 3628 | } |
3657 | if (name) { | 3629 | if (name) { |
3658 | const char *prepend = ","; | 3630 | const char *prepend; |
3659 | if (first) { | 3631 | if (!has_drive) { |
3660 | prepend = KERN_INFO "Floppy drive(s):"; | 3632 | prepend = ""; |
3661 | first = 0; | 3633 | has_drive = true; |
3634 | pr_info("Floppy drive(s):"); | ||
3635 | } else { | ||
3636 | prepend = ","; | ||
3662 | } | 3637 | } |
3663 | printk("%s fd%d is %s", prepend, drive, name); | 3638 | |
3639 | pr_cont("%s fd%d is %s", prepend, drive, name); | ||
3664 | } | 3640 | } |
3665 | *UDP = *params; | 3641 | *UDP = *params; |
3666 | } | 3642 | } |
3667 | if (!first) | 3643 | |
3668 | printk("\n"); | 3644 | if (has_drive) |
3645 | pr_cont("\n"); | ||
3669 | } | 3646 | } |
3670 | 3647 | ||
3671 | static int floppy_release(struct gendisk *disk, fmode_t mode) | 3648 | static int floppy_release(struct gendisk *disk, fmode_t mode) |
@@ -3705,8 +3682,8 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3705 | goto out2; | 3682 | goto out2; |
3706 | 3683 | ||
3707 | if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) { | 3684 | if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) { |
3708 | USETF(FD_DISK_CHANGED); | 3685 | set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); |
3709 | USETF(FD_VERIFY); | 3686 | set_bit(FD_VERIFY_BIT, &UDRS->flags); |
3710 | } | 3687 | } |
3711 | 3688 | ||
3712 | if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL))) | 3689 | if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL))) |
@@ -3735,9 +3712,8 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3735 | INFBOUND(try, 16); | 3712 | INFBOUND(try, 16); |
3736 | tmp = (char *)fd_dma_mem_alloc(1024 * try); | 3713 | tmp = (char *)fd_dma_mem_alloc(1024 * try); |
3737 | } | 3714 | } |
3738 | if (!tmp && !floppy_track_buffer) { | 3715 | if (!tmp && !floppy_track_buffer) |
3739 | fallback_on_nodma_alloc(&tmp, 2048 * try); | 3716 | fallback_on_nodma_alloc(&tmp, 2048 * try); |
3740 | } | ||
3741 | if (!tmp && !floppy_track_buffer) { | 3717 | if (!tmp && !floppy_track_buffer) { |
3742 | DPRINT("Unable to allocate DMA memory\n"); | 3718 | DPRINT("Unable to allocate DMA memory\n"); |
3743 | goto out; | 3719 | goto out; |
@@ -3767,11 +3743,12 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3767 | if (mode & (FMODE_READ|FMODE_WRITE)) { | 3743 | if (mode & (FMODE_READ|FMODE_WRITE)) { |
3768 | UDRS->last_checked = 0; | 3744 | UDRS->last_checked = 0; |
3769 | check_disk_change(bdev); | 3745 | check_disk_change(bdev); |
3770 | if (UTESTF(FD_DISK_CHANGED)) | 3746 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) |
3771 | goto out; | 3747 | goto out; |
3772 | } | 3748 | } |
3773 | res = -EROFS; | 3749 | res = -EROFS; |
3774 | if ((mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE))) | 3750 | if ((mode & FMODE_WRITE) && |
3751 | !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) | ||
3775 | goto out; | 3752 | goto out; |
3776 | } | 3753 | } |
3777 | mutex_unlock(&open_lock); | 3754 | mutex_unlock(&open_lock); |
@@ -3795,17 +3772,18 @@ static int check_floppy_change(struct gendisk *disk) | |||
3795 | { | 3772 | { |
3796 | int drive = (long)disk->private_data; | 3773 | int drive = (long)disk->private_data; |
3797 | 3774 | ||
3798 | if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) | 3775 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || |
3776 | test_bit(FD_VERIFY_BIT, &UDRS->flags)) | ||
3799 | return 1; | 3777 | return 1; |
3800 | 3778 | ||
3801 | if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { | 3779 | if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { |
3802 | lock_fdc(drive, 0); | 3780 | lock_fdc(drive, false); |
3803 | poll_drive(0, 0); | 3781 | poll_drive(false, 0); |
3804 | process_fd_request(); | 3782 | process_fd_request(); |
3805 | } | 3783 | } |
3806 | 3784 | ||
3807 | if (UTESTF(FD_DISK_CHANGED) || | 3785 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || |
3808 | UTESTF(FD_VERIFY) || | 3786 | test_bit(FD_VERIFY_BIT, &UDRS->flags) || |
3809 | test_bit(drive, &fake_change) || | 3787 | test_bit(drive, &fake_change) || |
3810 | (!ITYPE(UDRS->fd_device) && !current_type[drive])) | 3788 | (!ITYPE(UDRS->fd_device) && !current_type[drive])) |
3811 | return 1; | 3789 | return 1; |
@@ -3818,8 +3796,7 @@ static int check_floppy_change(struct gendisk *disk) | |||
3818 | * a disk in the drive, and whether that disk is writable. | 3796 | * a disk in the drive, and whether that disk is writable. |
3819 | */ | 3797 | */ |
3820 | 3798 | ||
3821 | static void floppy_rb0_complete(struct bio *bio, | 3799 | static void floppy_rb0_complete(struct bio *bio, int err) |
3822 | int err) | ||
3823 | { | 3800 | { |
3824 | complete((struct completion *)bio->bi_private); | 3801 | complete((struct completion *)bio->bi_private); |
3825 | } | 3802 | } |
@@ -3877,14 +3854,16 @@ static int floppy_revalidate(struct gendisk *disk) | |||
3877 | int cf; | 3854 | int cf; |
3878 | int res = 0; | 3855 | int res = 0; |
3879 | 3856 | ||
3880 | if (UTESTF(FD_DISK_CHANGED) || | 3857 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || |
3881 | UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) { | 3858 | test_bit(FD_VERIFY_BIT, &UDRS->flags) || |
3859 | test_bit(drive, &fake_change) || NO_GEOM) { | ||
3882 | if (usage_count == 0) { | 3860 | if (usage_count == 0) { |
3883 | printk("VFS: revalidate called on non-open device.\n"); | 3861 | pr_info("VFS: revalidate called on non-open device.\n"); |
3884 | return -EFAULT; | 3862 | return -EFAULT; |
3885 | } | 3863 | } |
3886 | lock_fdc(drive, 0); | 3864 | lock_fdc(drive, false); |
3887 | cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY); | 3865 | cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || |
3866 | test_bit(FD_VERIFY_BIT, &UDRS->flags)); | ||
3888 | if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) { | 3867 | if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) { |
3889 | process_fd_request(); /*already done by another thread */ | 3868 | process_fd_request(); /*already done by another thread */ |
3890 | return 0; | 3869 | return 0; |
@@ -3894,7 +3873,7 @@ static int floppy_revalidate(struct gendisk *disk) | |||
3894 | if (buffer_drive == drive) | 3873 | if (buffer_drive == drive) |
3895 | buffer_track = -1; | 3874 | buffer_track = -1; |
3896 | clear_bit(drive, &fake_change); | 3875 | clear_bit(drive, &fake_change); |
3897 | UCLEARF(FD_DISK_CHANGED); | 3876 | clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); |
3898 | if (cf) | 3877 | if (cf) |
3899 | UDRS->generation++; | 3878 | UDRS->generation++; |
3900 | if (NO_GEOM) { | 3879 | if (NO_GEOM) { |
@@ -3902,7 +3881,7 @@ static int floppy_revalidate(struct gendisk *disk) | |||
3902 | res = __floppy_read_block_0(opened_bdev[drive]); | 3881 | res = __floppy_read_block_0(opened_bdev[drive]); |
3903 | } else { | 3882 | } else { |
3904 | if (cf) | 3883 | if (cf) |
3905 | poll_drive(0, FD_RAW_NEED_DISK); | 3884 | poll_drive(false, FD_RAW_NEED_DISK); |
3906 | process_fd_request(); | 3885 | process_fd_request(); |
3907 | } | 3886 | } |
3908 | } | 3887 | } |
@@ -3934,21 +3913,21 @@ static char __init get_fdc_version(void) | |||
3934 | output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */ | 3913 | output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */ |
3935 | if (FDCS->reset) | 3914 | if (FDCS->reset) |
3936 | return FDC_NONE; | 3915 | return FDC_NONE; |
3937 | if ((r = result()) <= 0x00) | 3916 | r = result(); |
3917 | if (r <= 0x00) | ||
3938 | return FDC_NONE; /* No FDC present ??? */ | 3918 | return FDC_NONE; /* No FDC present ??? */ |
3939 | if ((r == 1) && (reply_buffer[0] == 0x80)) { | 3919 | if ((r == 1) && (reply_buffer[0] == 0x80)) { |
3940 | printk(KERN_INFO "FDC %d is an 8272A\n", fdc); | 3920 | pr_info("FDC %d is an 8272A\n", fdc); |
3941 | return FDC_8272A; /* 8272a/765 don't know DUMPREGS */ | 3921 | return FDC_8272A; /* 8272a/765 don't know DUMPREGS */ |
3942 | } | 3922 | } |
3943 | if (r != 10) { | 3923 | if (r != 10) { |
3944 | printk | 3924 | pr_info("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n", |
3945 | ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n", | 3925 | fdc, r); |
3946 | fdc, r); | ||
3947 | return FDC_UNKNOWN; | 3926 | return FDC_UNKNOWN; |
3948 | } | 3927 | } |
3949 | 3928 | ||
3950 | if (!fdc_configure()) { | 3929 | if (!fdc_configure()) { |
3951 | printk(KERN_INFO "FDC %d is an 82072\n", fdc); | 3930 | pr_info("FDC %d is an 82072\n", fdc); |
3952 | return FDC_82072; /* 82072 doesn't know CONFIGURE */ | 3931 | return FDC_82072; /* 82072 doesn't know CONFIGURE */ |
3953 | } | 3932 | } |
3954 | 3933 | ||
@@ -3956,52 +3935,50 @@ static char __init get_fdc_version(void) | |||
3956 | if (need_more_output() == MORE_OUTPUT) { | 3935 | if (need_more_output() == MORE_OUTPUT) { |
3957 | output_byte(0); | 3936 | output_byte(0); |
3958 | } else { | 3937 | } else { |
3959 | printk(KERN_INFO "FDC %d is an 82072A\n", fdc); | 3938 | pr_info("FDC %d is an 82072A\n", fdc); |
3960 | return FDC_82072A; /* 82072A as found on Sparcs. */ | 3939 | return FDC_82072A; /* 82072A as found on Sparcs. */ |
3961 | } | 3940 | } |
3962 | 3941 | ||
3963 | output_byte(FD_UNLOCK); | 3942 | output_byte(FD_UNLOCK); |
3964 | r = result(); | 3943 | r = result(); |
3965 | if ((r == 1) && (reply_buffer[0] == 0x80)) { | 3944 | if ((r == 1) && (reply_buffer[0] == 0x80)) { |
3966 | printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc); | 3945 | pr_info("FDC %d is a pre-1991 82077\n", fdc); |
3967 | return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know | 3946 | return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know |
3968 | * LOCK/UNLOCK */ | 3947 | * LOCK/UNLOCK */ |
3969 | } | 3948 | } |
3970 | if ((r != 1) || (reply_buffer[0] != 0x00)) { | 3949 | if ((r != 1) || (reply_buffer[0] != 0x00)) { |
3971 | printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n", | 3950 | pr_info("FDC %d init: UNLOCK: unexpected return of %d bytes.\n", |
3972 | fdc, r); | 3951 | fdc, r); |
3973 | return FDC_UNKNOWN; | 3952 | return FDC_UNKNOWN; |
3974 | } | 3953 | } |
3975 | output_byte(FD_PARTID); | 3954 | output_byte(FD_PARTID); |
3976 | r = result(); | 3955 | r = result(); |
3977 | if (r != 1) { | 3956 | if (r != 1) { |
3978 | printk("FDC %d init: PARTID: unexpected return of %d bytes.\n", | 3957 | pr_info("FDC %d init: PARTID: unexpected return of %d bytes.\n", |
3979 | fdc, r); | 3958 | fdc, r); |
3980 | return FDC_UNKNOWN; | 3959 | return FDC_UNKNOWN; |
3981 | } | 3960 | } |
3982 | if (reply_buffer[0] == 0x80) { | 3961 | if (reply_buffer[0] == 0x80) { |
3983 | printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc); | 3962 | pr_info("FDC %d is a post-1991 82077\n", fdc); |
3984 | return FDC_82077; /* Revised 82077AA passes all the tests */ | 3963 | return FDC_82077; /* Revised 82077AA passes all the tests */ |
3985 | } | 3964 | } |
3986 | switch (reply_buffer[0] >> 5) { | 3965 | switch (reply_buffer[0] >> 5) { |
3987 | case 0x0: | 3966 | case 0x0: |
3988 | /* Either a 82078-1 or a 82078SL running at 5Volt */ | 3967 | /* Either a 82078-1 or a 82078SL running at 5Volt */ |
3989 | printk(KERN_INFO "FDC %d is an 82078.\n", fdc); | 3968 | pr_info("FDC %d is an 82078.\n", fdc); |
3990 | return FDC_82078; | 3969 | return FDC_82078; |
3991 | case 0x1: | 3970 | case 0x1: |
3992 | printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc); | 3971 | pr_info("FDC %d is a 44pin 82078\n", fdc); |
3993 | return FDC_82078; | 3972 | return FDC_82078; |
3994 | case 0x2: | 3973 | case 0x2: |
3995 | printk(KERN_INFO "FDC %d is a S82078B\n", fdc); | 3974 | pr_info("FDC %d is a S82078B\n", fdc); |
3996 | return FDC_S82078B; | 3975 | return FDC_S82078B; |
3997 | case 0x3: | 3976 | case 0x3: |
3998 | printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n", | 3977 | pr_info("FDC %d is a National Semiconductor PC87306\n", fdc); |
3999 | fdc); | ||
4000 | return FDC_87306; | 3978 | return FDC_87306; |
4001 | default: | 3979 | default: |
4002 | printk(KERN_INFO | 3980 | pr_info("FDC %d init: 82078 variant with unknown PARTID=%d.\n", |
4003 | "FDC %d init: 82078 variant with unknown PARTID=%d.\n", | 3981 | fdc, reply_buffer[0] >> 5); |
4004 | fdc, reply_buffer[0] >> 5); | ||
4005 | return FDC_82078_UNKN; | 3982 | return FDC_82078_UNKN; |
4006 | } | 3983 | } |
4007 | } /* get_fdc_version */ | 3984 | } /* get_fdc_version */ |
@@ -4113,9 +4090,9 @@ static int __init floppy_setup(char *str) | |||
4113 | else | 4090 | else |
4114 | param = config_params[i].def_param; | 4091 | param = config_params[i].def_param; |
4115 | if (config_params[i].fn) | 4092 | if (config_params[i].fn) |
4116 | config_params[i]. | 4093 | config_params[i].fn(ints, param, |
4117 | fn(ints, param, | 4094 | config_params[i]. |
4118 | config_params[i].param2); | 4095 | param2); |
4119 | if (config_params[i].var) { | 4096 | if (config_params[i].var) { |
4120 | DPRINT("%s=%d\n", str, param); | 4097 | DPRINT("%s=%d\n", str, param); |
4121 | *config_params[i].var = param; | 4098 | *config_params[i].var = param; |
@@ -4129,8 +4106,8 @@ static int __init floppy_setup(char *str) | |||
4129 | 4106 | ||
4130 | DPRINT("allowed options are:"); | 4107 | DPRINT("allowed options are:"); |
4131 | for (i = 0; i < ARRAY_SIZE(config_params); i++) | 4108 | for (i = 0; i < ARRAY_SIZE(config_params); i++) |
4132 | printk(" %s", config_params[i].name); | 4109 | pr_cont(" %s", config_params[i].name); |
4133 | printk("\n"); | 4110 | pr_cont("\n"); |
4134 | } else | 4111 | } else |
4135 | DPRINT("botched floppy option\n"); | 4112 | DPRINT("botched floppy option\n"); |
4136 | DPRINT("Read Documentation/blockdev/floppy.txt\n"); | 4113 | DPRINT("Read Documentation/blockdev/floppy.txt\n"); |
@@ -4148,7 +4125,8 @@ static ssize_t floppy_cmos_show(struct device *dev, | |||
4148 | drive = p->id; | 4125 | drive = p->id; |
4149 | return sprintf(buf, "%X\n", UDP->cmos); | 4126 | return sprintf(buf, "%X\n", UDP->cmos); |
4150 | } | 4127 | } |
4151 | DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL); | 4128 | |
4129 | DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL); | ||
4152 | 4130 | ||
4153 | static void floppy_device_release(struct device *dev) | 4131 | static void floppy_device_release(struct device *dev) |
4154 | { | 4132 | { |
@@ -4160,7 +4138,7 @@ static int floppy_resume(struct device *dev) | |||
4160 | 4138 | ||
4161 | for (fdc = 0; fdc < N_FDC; fdc++) | 4139 | for (fdc = 0; fdc < N_FDC; fdc++) |
4162 | if (FDCS->address != -1) | 4140 | if (FDCS->address != -1) |
4163 | user_reset_fdc(-1, FD_RESET_ALWAYS, 0); | 4141 | user_reset_fdc(-1, FD_RESET_ALWAYS, false); |
4164 | 4142 | ||
4165 | return 0; | 4143 | return 0; |
4166 | } | 4144 | } |
@@ -4172,8 +4150,8 @@ static const struct dev_pm_ops floppy_pm_ops = { | |||
4172 | 4150 | ||
4173 | static struct platform_driver floppy_driver = { | 4151 | static struct platform_driver floppy_driver = { |
4174 | .driver = { | 4152 | .driver = { |
4175 | .name = "floppy", | 4153 | .name = "floppy", |
4176 | .pm = &floppy_pm_ops, | 4154 | .pm = &floppy_pm_ops, |
4177 | }, | 4155 | }, |
4178 | }; | 4156 | }; |
4179 | 4157 | ||
@@ -4245,16 +4223,16 @@ static int __init floppy_init(void) | |||
4245 | else | 4223 | else |
4246 | floppy_sizes[i] = MAX_DISK_SIZE << 1; | 4224 | floppy_sizes[i] = MAX_DISK_SIZE << 1; |
4247 | 4225 | ||
4248 | reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT); | 4226 | reschedule_timeout(MAXTIMEOUT, "floppy init"); |
4249 | config_types(); | 4227 | config_types(); |
4250 | 4228 | ||
4251 | for (i = 0; i < N_FDC; i++) { | 4229 | for (i = 0; i < N_FDC; i++) { |
4252 | fdc = i; | 4230 | fdc = i; |
4253 | CLEARSTRUCT(FDCS); | 4231 | memset(FDCS, 0, sizeof(*FDCS)); |
4254 | FDCS->dtr = -1; | 4232 | FDCS->dtr = -1; |
4255 | FDCS->dor = 0x4; | 4233 | FDCS->dor = 0x4; |
4256 | #if defined(__sparc__) || defined(__mc68000__) | 4234 | #if defined(__sparc__) || defined(__mc68000__) |
4257 | /*sparcs/sun3x don't have a DOR reset which we can fall back on to */ | 4235 | /*sparcs/sun3x don't have a DOR reset which we can fall back on to */ |
4258 | #ifdef __mc68000__ | 4236 | #ifdef __mc68000__ |
4259 | if (MACH_IS_SUN3X) | 4237 | if (MACH_IS_SUN3X) |
4260 | #endif | 4238 | #endif |
@@ -4283,11 +4261,11 @@ static int __init floppy_init(void) | |||
4283 | 4261 | ||
4284 | /* initialise drive state */ | 4262 | /* initialise drive state */ |
4285 | for (drive = 0; drive < N_DRIVE; drive++) { | 4263 | for (drive = 0; drive < N_DRIVE; drive++) { |
4286 | CLEARSTRUCT(UDRS); | 4264 | memset(UDRS, 0, sizeof(*UDRS)); |
4287 | CLEARSTRUCT(UDRWE); | 4265 | memset(UDRWE, 0, sizeof(*UDRWE)); |
4288 | USETF(FD_DISK_NEWCHANGE); | 4266 | set_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags); |
4289 | USETF(FD_DISK_CHANGED); | 4267 | set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags); |
4290 | USETF(FD_VERIFY); | 4268 | set_bit(FD_VERIFY_BIT, &UDRS->flags); |
4291 | UDRS->fd_device = -1; | 4269 | UDRS->fd_device = -1; |
4292 | floppy_track_buffer = NULL; | 4270 | floppy_track_buffer = NULL; |
4293 | max_buffer_sectors = 0; | 4271 | max_buffer_sectors = 0; |
@@ -4307,7 +4285,7 @@ static int __init floppy_init(void) | |||
4307 | if (FDCS->address == -1) | 4285 | if (FDCS->address == -1) |
4308 | continue; | 4286 | continue; |
4309 | FDCS->rawcmd = 2; | 4287 | FDCS->rawcmd = 2; |
4310 | if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) { | 4288 | if (user_reset_fdc(-1, FD_RESET_ALWAYS, false)) { |
4311 | /* free ioports reserved by floppy_grab_irq_and_dma() */ | 4289 | /* free ioports reserved by floppy_grab_irq_and_dma() */ |
4312 | floppy_release_regions(fdc); | 4290 | floppy_release_regions(fdc); |
4313 | FDCS->address = -1; | 4291 | FDCS->address = -1; |
@@ -4330,12 +4308,12 @@ static int __init floppy_init(void) | |||
4330 | * properly, so force a reset for the standard FDC clones, | 4308 | * properly, so force a reset for the standard FDC clones, |
4331 | * to avoid interrupt garbage. | 4309 | * to avoid interrupt garbage. |
4332 | */ | 4310 | */ |
4333 | user_reset_fdc(-1, FD_RESET_ALWAYS, 0); | 4311 | user_reset_fdc(-1, FD_RESET_ALWAYS, false); |
4334 | } | 4312 | } |
4335 | fdc = 0; | 4313 | fdc = 0; |
4336 | del_timer(&fd_timeout); | 4314 | del_timer(&fd_timeout); |
4337 | current_drive = 0; | 4315 | current_drive = 0; |
4338 | initialising = 0; | 4316 | initialized = true; |
4339 | if (have_no_fdc) { | 4317 | if (have_no_fdc) { |
4340 | DPRINT("no floppy controllers found\n"); | 4318 | DPRINT("no floppy controllers found\n"); |
4341 | err = have_no_fdc; | 4319 | err = have_no_fdc; |
@@ -4356,7 +4334,8 @@ static int __init floppy_init(void) | |||
4356 | if (err) | 4334 | if (err) |
4357 | goto out_flush_work; | 4335 | goto out_flush_work; |
4358 | 4336 | ||
4359 | err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos); | 4337 | err = device_create_file(&floppy_device[drive].dev, |
4338 | &dev_attr_cmos); | ||
4360 | if (err) | 4339 | if (err) |
4361 | goto out_unreg_platform_dev; | 4340 | goto out_unreg_platform_dev; |
4362 | 4341 | ||
@@ -4420,8 +4399,10 @@ static int floppy_request_regions(int fdc) | |||
4420 | const struct io_region *p; | 4399 | const struct io_region *p; |
4421 | 4400 | ||
4422 | for (p = io_regions; p < ARRAY_END(io_regions); p++) { | 4401 | for (p = io_regions; p < ARRAY_END(io_regions); p++) { |
4423 | if (!request_region(FDCS->address + p->offset, p->size, "floppy")) { | 4402 | if (!request_region(FDCS->address + p->offset, |
4424 | DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + p->offset); | 4403 | p->size, "floppy")) { |
4404 | DPRINT("Floppy io-port 0x%04lx in use\n", | ||
4405 | FDCS->address + p->offset); | ||
4425 | floppy_release_allocated_regions(fdc, p); | 4406 | floppy_release_allocated_regions(fdc, p); |
4426 | return -EBUSY; | 4407 | return -EBUSY; |
4427 | } | 4408 | } |
@@ -4512,11 +4493,9 @@ cleanup: | |||
4512 | static void floppy_release_irq_and_dma(void) | 4493 | static void floppy_release_irq_and_dma(void) |
4513 | { | 4494 | { |
4514 | int old_fdc; | 4495 | int old_fdc; |
4515 | #ifdef FLOPPY_SANITY_CHECK | ||
4516 | #ifndef __sparc__ | 4496 | #ifndef __sparc__ |
4517 | int drive; | 4497 | int drive; |
4518 | #endif | 4498 | #endif |
4519 | #endif | ||
4520 | long tmpsize; | 4499 | long tmpsize; |
4521 | unsigned long tmpaddr; | 4500 | unsigned long tmpaddr; |
4522 | unsigned long flags; | 4501 | unsigned long flags; |
@@ -4547,20 +4526,18 @@ static void floppy_release_irq_and_dma(void) | |||
4547 | buffer_min = buffer_max = -1; | 4526 | buffer_min = buffer_max = -1; |
4548 | fd_dma_mem_free(tmpaddr, tmpsize); | 4527 | fd_dma_mem_free(tmpaddr, tmpsize); |
4549 | } | 4528 | } |
4550 | #ifdef FLOPPY_SANITY_CHECK | ||
4551 | #ifndef __sparc__ | 4529 | #ifndef __sparc__ |
4552 | for (drive = 0; drive < N_FDC * 4; drive++) | 4530 | for (drive = 0; drive < N_FDC * 4; drive++) |
4553 | if (timer_pending(motor_off_timer + drive)) | 4531 | if (timer_pending(motor_off_timer + drive)) |
4554 | printk("motor off timer %d still active\n", drive); | 4532 | pr_info("motor off timer %d still active\n", drive); |
4555 | #endif | 4533 | #endif |
4556 | 4534 | ||
4557 | if (timer_pending(&fd_timeout)) | 4535 | if (timer_pending(&fd_timeout)) |
4558 | printk("floppy timer still active:%s\n", timeout_message); | 4536 | pr_info("floppy timer still active:%s\n", timeout_message); |
4559 | if (timer_pending(&fd_timer)) | 4537 | if (timer_pending(&fd_timer)) |
4560 | printk("auxiliary floppy timer still active\n"); | 4538 | pr_info("auxiliary floppy timer still active\n"); |
4561 | if (work_pending(&floppy_work)) | 4539 | if (work_pending(&floppy_work)) |
4562 | printk("work still pending\n"); | 4540 | pr_info("work still pending\n"); |
4563 | #endif | ||
4564 | old_fdc = fdc; | 4541 | old_fdc = fdc; |
4565 | for (fdc = 0; fdc < N_FDC; fdc++) | 4542 | for (fdc = 0; fdc < N_FDC; fdc++) |
4566 | if (FDCS->address != -1) | 4543 | if (FDCS->address != -1) |
@@ -4577,7 +4554,9 @@ static void __init parse_floppy_cfg_string(char *cfg) | |||
4577 | char *ptr; | 4554 | char *ptr; |
4578 | 4555 | ||
4579 | while (*cfg) { | 4556 | while (*cfg) { |
4580 | for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ; | 4557 | ptr = cfg; |
4558 | while (*cfg && *cfg != ' ' && *cfg != '\t') | ||
4559 | cfg++; | ||
4581 | if (*cfg) { | 4560 | if (*cfg) { |
4582 | *cfg = '\0'; | 4561 | *cfg = '\0'; |
4583 | cfg++; | 4562 | cfg++; |
@@ -4625,6 +4604,7 @@ static void __exit floppy_module_exit(void) | |||
4625 | /* eject disk, if any */ | 4604 | /* eject disk, if any */ |
4626 | fd_eject(0); | 4605 | fd_eject(0); |
4627 | } | 4606 | } |
4607 | |||
4628 | module_exit(floppy_module_exit); | 4608 | module_exit(floppy_module_exit); |
4629 | 4609 | ||
4630 | module_param(floppy, charp, 0); | 4610 | module_param(floppy, charp, 0); |
@@ -4636,9 +4616,10 @@ MODULE_LICENSE("GPL"); | |||
4636 | 4616 | ||
4637 | /* This doesn't actually get used other than for module information */ | 4617 | /* This doesn't actually get used other than for module information */ |
4638 | static const struct pnp_device_id floppy_pnpids[] = { | 4618 | static const struct pnp_device_id floppy_pnpids[] = { |
4639 | { "PNP0700", 0 }, | 4619 | {"PNP0700", 0}, |
4640 | { } | 4620 | {} |
4641 | }; | 4621 | }; |
4622 | |||
4642 | MODULE_DEVICE_TABLE(pnp, floppy_pnpids); | 4623 | MODULE_DEVICE_TABLE(pnp, floppy_pnpids); |
4643 | 4624 | ||
4644 | #else | 4625 | #else |
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index a808b1530b3b..eb2091aa1c19 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c | |||
@@ -476,7 +476,9 @@ static void class_osdblk_release(struct class *cls) | |||
476 | kfree(cls); | 476 | kfree(cls); |
477 | } | 477 | } |
478 | 478 | ||
479 | static ssize_t class_osdblk_list(struct class *c, char *data) | 479 | static ssize_t class_osdblk_list(struct class *c, |
480 | struct class_attribute *attr, | ||
481 | char *data) | ||
480 | { | 482 | { |
481 | int n = 0; | 483 | int n = 0; |
482 | struct list_head *tmp; | 484 | struct list_head *tmp; |
@@ -500,7 +502,9 @@ static ssize_t class_osdblk_list(struct class *c, char *data) | |||
500 | return n; | 502 | return n; |
501 | } | 503 | } |
502 | 504 | ||
503 | static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count) | 505 | static ssize_t class_osdblk_add(struct class *c, |
506 | struct class_attribute *attr, | ||
507 | const char *buf, size_t count) | ||
504 | { | 508 | { |
505 | struct osdblk_device *osdev; | 509 | struct osdblk_device *osdev; |
506 | ssize_t rc; | 510 | ssize_t rc; |
@@ -592,7 +596,9 @@ err_out_mod: | |||
592 | return rc; | 596 | return rc; |
593 | } | 597 | } |
594 | 598 | ||
595 | static ssize_t class_osdblk_remove(struct class *c, const char *buf, | 599 | static ssize_t class_osdblk_remove(struct class *c, |
600 | struct class_attribute *attr, | ||
601 | const char *buf, | ||
596 | size_t count) | 602 | size_t count) |
597 | { | 603 | { |
598 | struct osdblk_device *osdev = NULL; | 604 | struct osdblk_device *osdev = NULL; |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index b72935b8f203..39c8514442eb 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -284,7 +284,7 @@ static ssize_t kobj_pkt_store(struct kobject *kobj, | |||
284 | return len; | 284 | return len; |
285 | } | 285 | } |
286 | 286 | ||
287 | static struct sysfs_ops kobj_pkt_ops = { | 287 | static const struct sysfs_ops kobj_pkt_ops = { |
288 | .show = kobj_pkt_show, | 288 | .show = kobj_pkt_show, |
289 | .store = kobj_pkt_store | 289 | .store = kobj_pkt_store |
290 | }; | 290 | }; |
@@ -337,7 +337,9 @@ static void class_pktcdvd_release(struct class *cls) | |||
337 | { | 337 | { |
338 | kfree(cls); | 338 | kfree(cls); |
339 | } | 339 | } |
340 | static ssize_t class_pktcdvd_show_map(struct class *c, char *data) | 340 | static ssize_t class_pktcdvd_show_map(struct class *c, |
341 | struct class_attribute *attr, | ||
342 | char *data) | ||
341 | { | 343 | { |
342 | int n = 0; | 344 | int n = 0; |
343 | int idx; | 345 | int idx; |
@@ -356,7 +358,9 @@ static ssize_t class_pktcdvd_show_map(struct class *c, char *data) | |||
356 | return n; | 358 | return n; |
357 | } | 359 | } |
358 | 360 | ||
359 | static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, | 361 | static ssize_t class_pktcdvd_store_add(struct class *c, |
362 | struct class_attribute *attr, | ||
363 | const char *buf, | ||
360 | size_t count) | 364 | size_t count) |
361 | { | 365 | { |
362 | unsigned int major, minor; | 366 | unsigned int major, minor; |
@@ -376,7 +380,9 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, | |||
376 | return -EINVAL; | 380 | return -EINVAL; |
377 | } | 381 | } |
378 | 382 | ||
379 | static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf, | 383 | static ssize_t class_pktcdvd_store_remove(struct class *c, |
384 | struct class_attribute *attr, | ||
385 | const char *buf, | ||
380 | size_t count) | 386 | size_t count) |
381 | { | 387 | { |
382 | unsigned int major, minor; | 388 | unsigned int major, minor; |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 21681a81cc35..37b0542a4eeb 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -139,6 +139,8 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) | |||
139 | * | 139 | * |
140 | * This function allocates a new struct iucv_tty_buffer element and, optionally, | 140 | * This function allocates a new struct iucv_tty_buffer element and, optionally, |
141 | * allocates an internal data buffer with the specified size @size. | 141 | * allocates an internal data buffer with the specified size @size. |
142 | * The internal data buffer is always allocated with GFP_DMA which is | ||
143 | * required for receiving and sending data with IUCV. | ||
142 | * Note: The total message size arises from the internal buffer size and the | 144 | * Note: The total message size arises from the internal buffer size and the |
143 | * members of the iucv_tty_msg structure. | 145 | * members of the iucv_tty_msg structure. |
144 | * The function returns NULL if memory allocation has failed. | 146 | * The function returns NULL if memory allocation has failed. |
@@ -154,7 +156,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) | |||
154 | 156 | ||
155 | if (size > 0) { | 157 | if (size > 0) { |
156 | bufp->msg.length = MSG_SIZE(size); | 158 | bufp->msg.length = MSG_SIZE(size); |
157 | bufp->mbuf = kmalloc(bufp->msg.length, flags); | 159 | bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA); |
158 | if (!bufp->mbuf) { | 160 | if (!bufp->mbuf) { |
159 | mempool_free(bufp, hvc_iucv_mempool); | 161 | mempool_free(bufp, hvc_iucv_mempool); |
160 | return NULL; | 162 | return NULL; |
@@ -237,7 +239,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
237 | if (!rb->mbuf) { /* message not yet received ... */ | 239 | if (!rb->mbuf) { /* message not yet received ... */ |
238 | /* allocate mem to store msg data; if no memory is available | 240 | /* allocate mem to store msg data; if no memory is available |
239 | * then leave the buffer on the list and re-try later */ | 241 | * then leave the buffer on the list and re-try later */ |
240 | rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC); | 242 | rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA); |
241 | if (!rb->mbuf) | 243 | if (!rb->mbuf) |
242 | return -ENOMEM; | 244 | return -ENOMEM; |
243 | 245 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 176f1751237f..4462b113ba3f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -295,6 +295,9 @@ struct smi_info { | |||
295 | static int force_kipmid[SI_MAX_PARMS]; | 295 | static int force_kipmid[SI_MAX_PARMS]; |
296 | static int num_force_kipmid; | 296 | static int num_force_kipmid; |
297 | 297 | ||
298 | static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; | ||
299 | static int num_max_busy_us; | ||
300 | |||
298 | static int unload_when_empty = 1; | 301 | static int unload_when_empty = 1; |
299 | 302 | ||
300 | static int try_smi_init(struct smi_info *smi); | 303 | static int try_smi_init(struct smi_info *smi); |
@@ -925,23 +928,77 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion) | |||
925 | } | 928 | } |
926 | } | 929 | } |
927 | 930 | ||
931 | /* | ||
932 | * Use -1 in the nsec value of the busy waiting timespec to tell that | ||
933 | * we are spinning in kipmid looking for something and not delaying | ||
934 | * between checks | ||
935 | */ | ||
936 | static inline void ipmi_si_set_not_busy(struct timespec *ts) | ||
937 | { | ||
938 | ts->tv_nsec = -1; | ||
939 | } | ||
940 | static inline int ipmi_si_is_busy(struct timespec *ts) | ||
941 | { | ||
942 | return ts->tv_nsec != -1; | ||
943 | } | ||
944 | |||
945 | static int ipmi_thread_busy_wait(enum si_sm_result smi_result, | ||
946 | const struct smi_info *smi_info, | ||
947 | struct timespec *busy_until) | ||
948 | { | ||
949 | unsigned int max_busy_us = 0; | ||
950 | |||
951 | if (smi_info->intf_num < num_max_busy_us) | ||
952 | max_busy_us = kipmid_max_busy_us[smi_info->intf_num]; | ||
953 | if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY) | ||
954 | ipmi_si_set_not_busy(busy_until); | ||
955 | else if (!ipmi_si_is_busy(busy_until)) { | ||
956 | getnstimeofday(busy_until); | ||
957 | timespec_add_ns(busy_until, max_busy_us*NSEC_PER_USEC); | ||
958 | } else { | ||
959 | struct timespec now; | ||
960 | getnstimeofday(&now); | ||
961 | if (unlikely(timespec_compare(&now, busy_until) > 0)) { | ||
962 | ipmi_si_set_not_busy(busy_until); | ||
963 | return 0; | ||
964 | } | ||
965 | } | ||
966 | return 1; | ||
967 | } | ||
968 | |||
969 | |||
970 | /* | ||
971 | * A busy-waiting loop for speeding up IPMI operation. | ||
972 | * | ||
973 | * Lousy hardware makes this hard. This is only enabled for systems | ||
974 | * that are not BT and do not have interrupts. It starts spinning | ||
975 | * when an operation is complete or until max_busy tells it to stop | ||
976 | * (if that is enabled). See the paragraph on kimid_max_busy_us in | ||
977 | * Documentation/IPMI.txt for details. | ||
978 | */ | ||
928 | static int ipmi_thread(void *data) | 979 | static int ipmi_thread(void *data) |
929 | { | 980 | { |
930 | struct smi_info *smi_info = data; | 981 | struct smi_info *smi_info = data; |
931 | unsigned long flags; | 982 | unsigned long flags; |
932 | enum si_sm_result smi_result; | 983 | enum si_sm_result smi_result; |
984 | struct timespec busy_until; | ||
933 | 985 | ||
986 | ipmi_si_set_not_busy(&busy_until); | ||
934 | set_user_nice(current, 19); | 987 | set_user_nice(current, 19); |
935 | while (!kthread_should_stop()) { | 988 | while (!kthread_should_stop()) { |
989 | int busy_wait; | ||
990 | |||
936 | spin_lock_irqsave(&(smi_info->si_lock), flags); | 991 | spin_lock_irqsave(&(smi_info->si_lock), flags); |
937 | smi_result = smi_event_handler(smi_info, 0); | 992 | smi_result = smi_event_handler(smi_info, 0); |
938 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); | 993 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); |
994 | busy_wait = ipmi_thread_busy_wait(smi_result, smi_info, | ||
995 | &busy_until); | ||
939 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) | 996 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) |
940 | ; /* do nothing */ | 997 | ; /* do nothing */ |
941 | else if (smi_result == SI_SM_CALL_WITH_DELAY) | 998 | else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) |
942 | schedule(); | 999 | schedule(); |
943 | else | 1000 | else |
944 | schedule_timeout_interruptible(1); | 1001 | schedule_timeout_interruptible(0); |
945 | } | 1002 | } |
946 | return 0; | 1003 | return 0; |
947 | } | 1004 | } |
@@ -1144,7 +1201,7 @@ static int regsizes[SI_MAX_PARMS]; | |||
1144 | static unsigned int num_regsizes; | 1201 | static unsigned int num_regsizes; |
1145 | static int regshifts[SI_MAX_PARMS]; | 1202 | static int regshifts[SI_MAX_PARMS]; |
1146 | static unsigned int num_regshifts; | 1203 | static unsigned int num_regshifts; |
1147 | static int slave_addrs[SI_MAX_PARMS]; | 1204 | static int slave_addrs[SI_MAX_PARMS]; /* Leaving 0 chooses the default value */ |
1148 | static unsigned int num_slave_addrs; | 1205 | static unsigned int num_slave_addrs; |
1149 | 1206 | ||
1150 | #define IPMI_IO_ADDR_SPACE 0 | 1207 | #define IPMI_IO_ADDR_SPACE 0 |
@@ -1212,6 +1269,11 @@ module_param(unload_when_empty, int, 0); | |||
1212 | MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" | 1269 | MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" |
1213 | " specified or found, default is 1. Setting to 0" | 1270 | " specified or found, default is 1. Setting to 0" |
1214 | " is useful for hot add of devices using hotmod."); | 1271 | " is useful for hot add of devices using hotmod."); |
1272 | module_param_array(kipmid_max_busy_us, uint, &num_max_busy_us, 0644); | ||
1273 | MODULE_PARM_DESC(kipmid_max_busy_us, | ||
1274 | "Max time (in microseconds) to busy-wait for IPMI data before" | ||
1275 | " sleeping. 0 (default) means to wait forever. Set to 100-500" | ||
1276 | " if kipmid is using up a lot of CPU time."); | ||
1215 | 1277 | ||
1216 | 1278 | ||
1217 | static void std_irq_cleanup(struct smi_info *info) | 1279 | static void std_irq_cleanup(struct smi_info *info) |
@@ -1607,7 +1669,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1607 | regsize = 1; | 1669 | regsize = 1; |
1608 | regshift = 0; | 1670 | regshift = 0; |
1609 | irq = 0; | 1671 | irq = 0; |
1610 | ipmb = 0x20; | 1672 | ipmb = 0; /* Choose the default if not specified */ |
1611 | 1673 | ||
1612 | next = strchr(curr, ':'); | 1674 | next = strchr(curr, ':'); |
1613 | if (next) { | 1675 | if (next) { |
@@ -1799,6 +1861,7 @@ static __devinit void hardcode_find_bmc(void) | |||
1799 | info->irq = irqs[i]; | 1861 | info->irq = irqs[i]; |
1800 | if (info->irq) | 1862 | if (info->irq) |
1801 | info->irq_setup = std_irq_setup; | 1863 | info->irq_setup = std_irq_setup; |
1864 | info->slave_addr = slave_addrs[i]; | ||
1802 | 1865 | ||
1803 | try_smi_init(info); | 1866 | try_smi_init(info); |
1804 | } | 1867 | } |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 48788db4e280..1f3215ac085b 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 4 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * | 5 | * |
6 | * Added devfs support. | 6 | * Added devfs support. |
7 | * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu> | 7 | * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu> |
8 | * Shared /dev/zero mmapping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com> | 8 | * Shared /dev/zero mmapping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com> |
9 | */ | 9 | */ |
@@ -44,36 +44,6 @@ static inline unsigned long size_inside_page(unsigned long start, | |||
44 | return min(sz, size); | 44 | return min(sz, size); |
45 | } | 45 | } |
46 | 46 | ||
47 | /* | ||
48 | * Architectures vary in how they handle caching for addresses | ||
49 | * outside of main memory. | ||
50 | * | ||
51 | */ | ||
52 | static inline int uncached_access(struct file *file, unsigned long addr) | ||
53 | { | ||
54 | #if defined(CONFIG_IA64) | ||
55 | /* | ||
56 | * On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases. | ||
57 | */ | ||
58 | return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); | ||
59 | #elif defined(CONFIG_MIPS) | ||
60 | { | ||
61 | extern int __uncached_access(struct file *file, | ||
62 | unsigned long addr); | ||
63 | |||
64 | return __uncached_access(file, addr); | ||
65 | } | ||
66 | #else | ||
67 | /* | ||
68 | * Accessing memory above the top the kernel knows about or through a file pointer | ||
69 | * that was marked O_DSYNC will be done non-cached. | ||
70 | */ | ||
71 | if (file->f_flags & O_DSYNC) | ||
72 | return 1; | ||
73 | return addr >= __pa(high_memory); | ||
74 | #endif | ||
75 | } | ||
76 | |||
77 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE | 47 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE |
78 | static inline int valid_phys_addr_range(unsigned long addr, size_t count) | 48 | static inline int valid_phys_addr_range(unsigned long addr, size_t count) |
79 | { | 49 | { |
@@ -115,15 +85,15 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) | |||
115 | } | 85 | } |
116 | #endif | 86 | #endif |
117 | 87 | ||
118 | void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr) | 88 | void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) |
119 | { | 89 | { |
120 | } | 90 | } |
121 | 91 | ||
122 | /* | 92 | /* |
123 | * This funcion reads the *physical* memory. The f_pos points directly to the | 93 | * This funcion reads the *physical* memory. The f_pos points directly to the |
124 | * memory location. | 94 | * memory location. |
125 | */ | 95 | */ |
126 | static ssize_t read_mem(struct file * file, char __user * buf, | 96 | static ssize_t read_mem(struct file *file, char __user *buf, |
127 | size_t count, loff_t *ppos) | 97 | size_t count, loff_t *ppos) |
128 | { | 98 | { |
129 | unsigned long p = *ppos; | 99 | unsigned long p = *ppos; |
@@ -140,10 +110,10 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
140 | if (sz > 0) { | 110 | if (sz > 0) { |
141 | if (clear_user(buf, sz)) | 111 | if (clear_user(buf, sz)) |
142 | return -EFAULT; | 112 | return -EFAULT; |
143 | buf += sz; | 113 | buf += sz; |
144 | p += sz; | 114 | p += sz; |
145 | count -= sz; | 115 | count -= sz; |
146 | read += sz; | 116 | read += sz; |
147 | } | 117 | } |
148 | } | 118 | } |
149 | #endif | 119 | #endif |
@@ -157,9 +127,9 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
157 | return -EPERM; | 127 | return -EPERM; |
158 | 128 | ||
159 | /* | 129 | /* |
160 | * On ia64 if a page has been mapped somewhere as | 130 | * On ia64 if a page has been mapped somewhere as uncached, then |
161 | * uncached, then it must also be accessed uncached | 131 | * it must also be accessed uncached by the kernel or data |
162 | * by the kernel or data corruption may occur | 132 | * corruption may occur. |
163 | */ | 133 | */ |
164 | ptr = xlate_dev_mem_ptr(p); | 134 | ptr = xlate_dev_mem_ptr(p); |
165 | if (!ptr) | 135 | if (!ptr) |
@@ -180,7 +150,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
180 | return read; | 150 | return read; |
181 | } | 151 | } |
182 | 152 | ||
183 | static ssize_t write_mem(struct file * file, const char __user * buf, | 153 | static ssize_t write_mem(struct file *file, const char __user *buf, |
184 | size_t count, loff_t *ppos) | 154 | size_t count, loff_t *ppos) |
185 | { | 155 | { |
186 | unsigned long p = *ppos; | 156 | unsigned long p = *ppos; |
@@ -212,9 +182,9 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
212 | return -EPERM; | 182 | return -EPERM; |
213 | 183 | ||
214 | /* | 184 | /* |
215 | * On ia64 if a page has been mapped somewhere as | 185 | * On ia64 if a page has been mapped somewhere as uncached, then |
216 | * uncached, then it must also be accessed uncached | 186 | * it must also be accessed uncached by the kernel or data |
217 | * by the kernel or data corruption may occur | 187 | * corruption may occur. |
218 | */ | 188 | */ |
219 | ptr = xlate_dev_mem_ptr(p); | 189 | ptr = xlate_dev_mem_ptr(p); |
220 | if (!ptr) { | 190 | if (!ptr) { |
@@ -242,13 +212,46 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
242 | return written; | 212 | return written; |
243 | } | 213 | } |
244 | 214 | ||
245 | int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file, | 215 | int __weak phys_mem_access_prot_allowed(struct file *file, |
246 | unsigned long pfn, unsigned long size, pgprot_t *vma_prot) | 216 | unsigned long pfn, unsigned long size, pgprot_t *vma_prot) |
247 | { | 217 | { |
248 | return 1; | 218 | return 1; |
249 | } | 219 | } |
250 | 220 | ||
251 | #ifndef __HAVE_PHYS_MEM_ACCESS_PROT | 221 | #ifndef __HAVE_PHYS_MEM_ACCESS_PROT |
222 | |||
223 | /* | ||
224 | * Architectures vary in how they handle caching for addresses | ||
225 | * outside of main memory. | ||
226 | * | ||
227 | */ | ||
228 | static int uncached_access(struct file *file, unsigned long addr) | ||
229 | { | ||
230 | #if defined(CONFIG_IA64) | ||
231 | /* | ||
232 | * On ia64, we ignore O_DSYNC because we cannot tolerate memory | ||
233 | * attribute aliases. | ||
234 | */ | ||
235 | return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); | ||
236 | #elif defined(CONFIG_MIPS) | ||
237 | { | ||
238 | extern int __uncached_access(struct file *file, | ||
239 | unsigned long addr); | ||
240 | |||
241 | return __uncached_access(file, addr); | ||
242 | } | ||
243 | #else | ||
244 | /* | ||
245 | * Accessing memory above the top the kernel knows about or through a | ||
246 | * file pointer | ||
247 | * that was marked O_DSYNC will be done non-cached. | ||
248 | */ | ||
249 | if (file->f_flags & O_DSYNC) | ||
250 | return 1; | ||
251 | return addr >= __pa(high_memory); | ||
252 | #endif | ||
253 | } | ||
254 | |||
252 | static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | 255 | static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
253 | unsigned long size, pgprot_t vma_prot) | 256 | unsigned long size, pgprot_t vma_prot) |
254 | { | 257 | { |
@@ -294,7 +297,7 @@ static const struct vm_operations_struct mmap_mem_ops = { | |||
294 | #endif | 297 | #endif |
295 | }; | 298 | }; |
296 | 299 | ||
297 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) | 300 | static int mmap_mem(struct file *file, struct vm_area_struct *vma) |
298 | { | 301 | { |
299 | size_t size = vma->vm_end - vma->vm_start; | 302 | size_t size = vma->vm_end - vma->vm_start; |
300 | 303 | ||
@@ -329,7 +332,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) | |||
329 | } | 332 | } |
330 | 333 | ||
331 | #ifdef CONFIG_DEVKMEM | 334 | #ifdef CONFIG_DEVKMEM |
332 | static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | 335 | static int mmap_kmem(struct file *file, struct vm_area_struct *vma) |
333 | { | 336 | { |
334 | unsigned long pfn; | 337 | unsigned long pfn; |
335 | 338 | ||
@@ -337,9 +340,9 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
337 | pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; | 340 | pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; |
338 | 341 | ||
339 | /* | 342 | /* |
340 | * RED-PEN: on some architectures there is more mapped memory | 343 | * RED-PEN: on some architectures there is more mapped memory than |
341 | * than available in mem_map which pfn_valid checks | 344 | * available in mem_map which pfn_valid checks for. Perhaps should add a |
342 | * for. Perhaps should add a new macro here. | 345 | * new macro here. |
343 | * | 346 | * |
344 | * RED-PEN: vmalloc is not supported right now. | 347 | * RED-PEN: vmalloc is not supported right now. |
345 | */ | 348 | */ |
@@ -389,7 +392,7 @@ static ssize_t read_oldmem(struct file *file, char __user *buf, | |||
389 | /* | 392 | /* |
390 | * This function reads the *virtual* memory as seen by the kernel. | 393 | * This function reads the *virtual* memory as seen by the kernel. |
391 | */ | 394 | */ |
392 | static ssize_t read_kmem(struct file *file, char __user *buf, | 395 | static ssize_t read_kmem(struct file *file, char __user *buf, |
393 | size_t count, loff_t *ppos) | 396 | size_t count, loff_t *ppos) |
394 | { | 397 | { |
395 | unsigned long p = *ppos; | 398 | unsigned long p = *ppos; |
@@ -400,8 +403,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
400 | read = 0; | 403 | read = 0; |
401 | if (p < (unsigned long) high_memory) { | 404 | if (p < (unsigned long) high_memory) { |
402 | low_count = count; | 405 | low_count = count; |
403 | if (count > (unsigned long) high_memory - p) | 406 | if (count > (unsigned long)high_memory - p) |
404 | low_count = (unsigned long) high_memory - p; | 407 | low_count = (unsigned long)high_memory - p; |
405 | 408 | ||
406 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED | 409 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
407 | /* we don't have page 0 mapped on sparc and m68k.. */ | 410 | /* we don't have page 0 mapped on sparc and m68k.. */ |
@@ -465,9 +468,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
465 | } | 468 | } |
466 | 469 | ||
467 | 470 | ||
468 | static inline ssize_t | 471 | static ssize_t do_write_kmem(unsigned long p, const char __user *buf, |
469 | do_write_kmem(unsigned long p, const char __user *buf, | 472 | size_t count, loff_t *ppos) |
470 | size_t count, loff_t *ppos) | ||
471 | { | 473 | { |
472 | ssize_t written, sz; | 474 | ssize_t written, sz; |
473 | unsigned long copied; | 475 | unsigned long copied; |
@@ -491,9 +493,9 @@ do_write_kmem(unsigned long p, const char __user *buf, | |||
491 | sz = size_inside_page(p, count); | 493 | sz = size_inside_page(p, count); |
492 | 494 | ||
493 | /* | 495 | /* |
494 | * On ia64 if a page has been mapped somewhere as | 496 | * On ia64 if a page has been mapped somewhere as uncached, then |
495 | * uncached, then it must also be accessed uncached | 497 | * it must also be accessed uncached by the kernel or data |
496 | * by the kernel or data corruption may occur | 498 | * corruption may occur. |
497 | */ | 499 | */ |
498 | ptr = xlate_dev_kmem_ptr((char *)p); | 500 | ptr = xlate_dev_kmem_ptr((char *)p); |
499 | 501 | ||
@@ -514,11 +516,10 @@ do_write_kmem(unsigned long p, const char __user *buf, | |||
514 | return written; | 516 | return written; |
515 | } | 517 | } |
516 | 518 | ||
517 | |||
518 | /* | 519 | /* |
519 | * This function writes to the *virtual* memory as seen by the kernel. | 520 | * This function writes to the *virtual* memory as seen by the kernel. |
520 | */ | 521 | */ |
521 | static ssize_t write_kmem(struct file * file, const char __user * buf, | 522 | static ssize_t write_kmem(struct file *file, const char __user *buf, |
522 | size_t count, loff_t *ppos) | 523 | size_t count, loff_t *ppos) |
523 | { | 524 | { |
524 | unsigned long p = *ppos; | 525 | unsigned long p = *ppos; |
@@ -570,17 +571,17 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
570 | #endif | 571 | #endif |
571 | 572 | ||
572 | #ifdef CONFIG_DEVPORT | 573 | #ifdef CONFIG_DEVPORT |
573 | static ssize_t read_port(struct file * file, char __user * buf, | 574 | static ssize_t read_port(struct file *file, char __user *buf, |
574 | size_t count, loff_t *ppos) | 575 | size_t count, loff_t *ppos) |
575 | { | 576 | { |
576 | unsigned long i = *ppos; | 577 | unsigned long i = *ppos; |
577 | char __user *tmp = buf; | 578 | char __user *tmp = buf; |
578 | 579 | ||
579 | if (!access_ok(VERIFY_WRITE, buf, count)) | 580 | if (!access_ok(VERIFY_WRITE, buf, count)) |
580 | return -EFAULT; | 581 | return -EFAULT; |
581 | while (count-- > 0 && i < 65536) { | 582 | while (count-- > 0 && i < 65536) { |
582 | if (__put_user(inb(i),tmp) < 0) | 583 | if (__put_user(inb(i), tmp) < 0) |
583 | return -EFAULT; | 584 | return -EFAULT; |
584 | i++; | 585 | i++; |
585 | tmp++; | 586 | tmp++; |
586 | } | 587 | } |
@@ -588,22 +589,22 @@ static ssize_t read_port(struct file * file, char __user * buf, | |||
588 | return tmp-buf; | 589 | return tmp-buf; |
589 | } | 590 | } |
590 | 591 | ||
591 | static ssize_t write_port(struct file * file, const char __user * buf, | 592 | static ssize_t write_port(struct file *file, const char __user *buf, |
592 | size_t count, loff_t *ppos) | 593 | size_t count, loff_t *ppos) |
593 | { | 594 | { |
594 | unsigned long i = *ppos; | 595 | unsigned long i = *ppos; |
595 | const char __user * tmp = buf; | 596 | const char __user * tmp = buf; |
596 | 597 | ||
597 | if (!access_ok(VERIFY_READ,buf,count)) | 598 | if (!access_ok(VERIFY_READ, buf, count)) |
598 | return -EFAULT; | 599 | return -EFAULT; |
599 | while (count-- > 0 && i < 65536) { | 600 | while (count-- > 0 && i < 65536) { |
600 | char c; | 601 | char c; |
601 | if (__get_user(c, tmp)) { | 602 | if (__get_user(c, tmp)) { |
602 | if (tmp > buf) | 603 | if (tmp > buf) |
603 | break; | 604 | break; |
604 | return -EFAULT; | 605 | return -EFAULT; |
605 | } | 606 | } |
606 | outb(c,i); | 607 | outb(c, i); |
607 | i++; | 608 | i++; |
608 | tmp++; | 609 | tmp++; |
609 | } | 610 | } |
@@ -612,13 +613,13 @@ static ssize_t write_port(struct file * file, const char __user * buf, | |||
612 | } | 613 | } |
613 | #endif | 614 | #endif |
614 | 615 | ||
615 | static ssize_t read_null(struct file * file, char __user * buf, | 616 | static ssize_t read_null(struct file *file, char __user *buf, |
616 | size_t count, loff_t *ppos) | 617 | size_t count, loff_t *ppos) |
617 | { | 618 | { |
618 | return 0; | 619 | return 0; |
619 | } | 620 | } |
620 | 621 | ||
621 | static ssize_t write_null(struct file * file, const char __user * buf, | 622 | static ssize_t write_null(struct file *file, const char __user *buf, |
622 | size_t count, loff_t *ppos) | 623 | size_t count, loff_t *ppos) |
623 | { | 624 | { |
624 | return count; | 625 | return count; |
@@ -630,13 +631,13 @@ static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf, | |||
630 | return sd->len; | 631 | return sd->len; |
631 | } | 632 | } |
632 | 633 | ||
633 | static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out, | 634 | static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out, |
634 | loff_t *ppos, size_t len, unsigned int flags) | 635 | loff_t *ppos, size_t len, unsigned int flags) |
635 | { | 636 | { |
636 | return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); | 637 | return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null); |
637 | } | 638 | } |
638 | 639 | ||
639 | static ssize_t read_zero(struct file * file, char __user * buf, | 640 | static ssize_t read_zero(struct file *file, char __user *buf, |
640 | size_t count, loff_t *ppos) | 641 | size_t count, loff_t *ppos) |
641 | { | 642 | { |
642 | size_t written; | 643 | size_t written; |
@@ -667,7 +668,7 @@ static ssize_t read_zero(struct file * file, char __user * buf, | |||
667 | return written ? written : -EFAULT; | 668 | return written ? written : -EFAULT; |
668 | } | 669 | } |
669 | 670 | ||
670 | static int mmap_zero(struct file * file, struct vm_area_struct * vma) | 671 | static int mmap_zero(struct file *file, struct vm_area_struct *vma) |
671 | { | 672 | { |
672 | #ifndef CONFIG_MMU | 673 | #ifndef CONFIG_MMU |
673 | return -ENOSYS; | 674 | return -ENOSYS; |
@@ -677,7 +678,7 @@ static int mmap_zero(struct file * file, struct vm_area_struct * vma) | |||
677 | return 0; | 678 | return 0; |
678 | } | 679 | } |
679 | 680 | ||
680 | static ssize_t write_full(struct file * file, const char __user * buf, | 681 | static ssize_t write_full(struct file *file, const char __user *buf, |
681 | size_t count, loff_t *ppos) | 682 | size_t count, loff_t *ppos) |
682 | { | 683 | { |
683 | return -ENOSPC; | 684 | return -ENOSPC; |
@@ -688,8 +689,7 @@ static ssize_t write_full(struct file * file, const char __user * buf, | |||
688 | * can fopen() both devices with "a" now. This was previously impossible. | 689 | * can fopen() both devices with "a" now. This was previously impossible. |
689 | * -- SRB. | 690 | * -- SRB. |
690 | */ | 691 | */ |
691 | 692 | static loff_t null_lseek(struct file *file, loff_t offset, int orig) | |
692 | static loff_t null_lseek(struct file * file, loff_t offset, int orig) | ||
693 | { | 693 | { |
694 | return file->f_pos = 0; | 694 | return file->f_pos = 0; |
695 | } | 695 | } |
@@ -702,24 +702,31 @@ static loff_t null_lseek(struct file * file, loff_t offset, int orig) | |||
702 | * also note that seeking relative to the "end of file" isn't supported: | 702 | * also note that seeking relative to the "end of file" isn't supported: |
703 | * it has no meaning, so it returns -EINVAL. | 703 | * it has no meaning, so it returns -EINVAL. |
704 | */ | 704 | */ |
705 | static loff_t memory_lseek(struct file * file, loff_t offset, int orig) | 705 | static loff_t memory_lseek(struct file *file, loff_t offset, int orig) |
706 | { | 706 | { |
707 | loff_t ret; | 707 | loff_t ret; |
708 | 708 | ||
709 | mutex_lock(&file->f_path.dentry->d_inode->i_mutex); | 709 | mutex_lock(&file->f_path.dentry->d_inode->i_mutex); |
710 | switch (orig) { | 710 | switch (orig) { |
711 | case 0: | 711 | case SEEK_CUR: |
712 | file->f_pos = offset; | 712 | offset += file->f_pos; |
713 | ret = file->f_pos; | 713 | if ((unsigned long long)offset < |
714 | force_successful_syscall_return(); | 714 | (unsigned long long)file->f_pos) { |
715 | ret = -EOVERFLOW; | ||
715 | break; | 716 | break; |
716 | case 1: | 717 | } |
717 | file->f_pos += offset; | 718 | case SEEK_SET: |
718 | ret = file->f_pos; | 719 | /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */ |
719 | force_successful_syscall_return(); | 720 | if ((unsigned long long)offset >= ~0xFFFULL) { |
721 | ret = -EOVERFLOW; | ||
720 | break; | 722 | break; |
721 | default: | 723 | } |
722 | ret = -EINVAL; | 724 | file->f_pos = offset; |
725 | ret = file->f_pos; | ||
726 | force_successful_syscall_return(); | ||
727 | break; | ||
728 | default: | ||
729 | ret = -EINVAL; | ||
723 | } | 730 | } |
724 | mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); | 731 | mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); |
725 | return ret; | 732 | return ret; |
@@ -803,7 +810,7 @@ static const struct file_operations oldmem_fops = { | |||
803 | }; | 810 | }; |
804 | #endif | 811 | #endif |
805 | 812 | ||
806 | static ssize_t kmsg_write(struct file * file, const char __user * buf, | 813 | static ssize_t kmsg_write(struct file *file, const char __user *buf, |
807 | size_t count, loff_t *ppos) | 814 | size_t count, loff_t *ppos) |
808 | { | 815 | { |
809 | char *tmp; | 816 | char *tmp; |
@@ -825,7 +832,7 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, | |||
825 | } | 832 | } |
826 | 833 | ||
827 | static const struct file_operations kmsg_fops = { | 834 | static const struct file_operations kmsg_fops = { |
828 | .write = kmsg_write, | 835 | .write = kmsg_write, |
829 | }; | 836 | }; |
830 | 837 | ||
831 | static const struct memdev { | 838 | static const struct memdev { |
@@ -876,7 +883,7 @@ static int memory_open(struct inode *inode, struct file *filp) | |||
876 | } | 883 | } |
877 | 884 | ||
878 | static const struct file_operations memory_fops = { | 885 | static const struct file_operations memory_fops = { |
879 | .open = memory_open, | 886 | .open = memory_open, |
880 | }; | 887 | }; |
881 | 888 | ||
882 | static char *mem_devnode(struct device *dev, mode_t *mode) | 889 | static char *mem_devnode(struct device *dev, mode_t *mode) |
@@ -897,7 +904,7 @@ static int __init chr_dev_init(void) | |||
897 | if (err) | 904 | if (err) |
898 | return err; | 905 | return err; |
899 | 906 | ||
900 | if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) | 907 | if (register_chrdev(MEM_MAJOR, "mem", &memory_fops)) |
901 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); | 908 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); |
902 | 909 | ||
903 | mem_class = class_create(THIS_MODULE, "mem"); | 910 | mem_class = class_create(THIS_MODULE, "mem"); |
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 918711aa56f3..04fd0d843b3b 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c | |||
@@ -546,7 +546,7 @@ static void mmtimer_tasklet(unsigned long data) | |||
546 | { | 546 | { |
547 | int nodeid = data; | 547 | int nodeid = data; |
548 | struct mmtimer_node *mn = &timers[nodeid]; | 548 | struct mmtimer_node *mn = &timers[nodeid]; |
549 | struct mmtimer *x = rb_entry(mn->next, struct mmtimer, list); | 549 | struct mmtimer *x; |
550 | struct k_itimer *t; | 550 | struct k_itimer *t; |
551 | unsigned long flags; | 551 | unsigned long flags; |
552 | 552 | ||
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 2e50f4dfc79c..bdae8327143c 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/audit.h> | 48 | #include <linux/audit.h> |
49 | #include <linux/file.h> | 49 | #include <linux/file.h> |
50 | #include <linux/uaccess.h> | 50 | #include <linux/uaccess.h> |
51 | #include <linux/module.h> | ||
51 | 52 | ||
52 | #include <asm/system.h> | 53 | #include <asm/system.h> |
53 | 54 | ||
@@ -2091,3 +2092,19 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { | |||
2091 | .receive_buf = n_tty_receive_buf, | 2092 | .receive_buf = n_tty_receive_buf, |
2092 | .write_wakeup = n_tty_write_wakeup | 2093 | .write_wakeup = n_tty_write_wakeup |
2093 | }; | 2094 | }; |
2095 | |||
2096 | /** | ||
2097 | * n_tty_inherit_ops - inherit N_TTY methods | ||
2098 | * @ops: struct tty_ldisc_ops where to save N_TTY methods | ||
2099 | * | ||
2100 | * Used by a generic struct tty_ldisc_ops to easily inherit N_TTY | ||
2101 | * methods. | ||
2102 | */ | ||
2103 | |||
2104 | void n_tty_inherit_ops(struct tty_ldisc_ops *ops) | ||
2105 | { | ||
2106 | *ops = tty_ldisc_N_TTY; | ||
2107 | ops->owner = NULL; | ||
2108 | ops->refcount = ops->flags = 0; | ||
2109 | } | ||
2110 | EXPORT_SYMBOL_GPL(n_tty_inherit_ops); | ||
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index ac16fbec72d0..283a15bc84e3 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c | |||
@@ -148,7 +148,6 @@ void tty_audit_fork(struct signal_struct *sig) | |||
148 | spin_lock_irq(¤t->sighand->siglock); | 148 | spin_lock_irq(¤t->sighand->siglock); |
149 | sig->audit_tty = current->signal->audit_tty; | 149 | sig->audit_tty = current->signal->audit_tty; |
150 | spin_unlock_irq(¤t->sighand->siglock); | 150 | spin_unlock_irq(¤t->sighand->siglock); |
151 | sig->tty_audit_buf = NULL; | ||
152 | } | 151 | } |
153 | 152 | ||
154 | /** | 153 | /** |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 67bc2ece7b4b..2d5d575e889d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -766,7 +766,7 @@ static void cpufreq_sysfs_release(struct kobject *kobj) | |||
766 | complete(&policy->kobj_unregister); | 766 | complete(&policy->kobj_unregister); |
767 | } | 767 | } |
768 | 768 | ||
769 | static struct sysfs_ops sysfs_ops = { | 769 | static const struct sysfs_ops sysfs_ops = { |
770 | .show = show, | 770 | .show = show, |
771 | .store = store, | 771 | .store = store, |
772 | }; | 772 | }; |
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 97b003839fb6..8719b36e1a4d 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
@@ -22,6 +22,7 @@ static int __init cpuidle_sysfs_setup(char *unused) | |||
22 | __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup); | 22 | __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup); |
23 | 23 | ||
24 | static ssize_t show_available_governors(struct sysdev_class *class, | 24 | static ssize_t show_available_governors(struct sysdev_class *class, |
25 | struct sysdev_class_attribute *attr, | ||
25 | char *buf) | 26 | char *buf) |
26 | { | 27 | { |
27 | ssize_t i = 0; | 28 | ssize_t i = 0; |
@@ -41,6 +42,7 @@ out: | |||
41 | } | 42 | } |
42 | 43 | ||
43 | static ssize_t show_current_driver(struct sysdev_class *class, | 44 | static ssize_t show_current_driver(struct sysdev_class *class, |
45 | struct sysdev_class_attribute *attr, | ||
44 | char *buf) | 46 | char *buf) |
45 | { | 47 | { |
46 | ssize_t ret; | 48 | ssize_t ret; |
@@ -56,6 +58,7 @@ static ssize_t show_current_driver(struct sysdev_class *class, | |||
56 | } | 58 | } |
57 | 59 | ||
58 | static ssize_t show_current_governor(struct sysdev_class *class, | 60 | static ssize_t show_current_governor(struct sysdev_class *class, |
61 | struct sysdev_class_attribute *attr, | ||
59 | char *buf) | 62 | char *buf) |
60 | { | 63 | { |
61 | ssize_t ret; | 64 | ssize_t ret; |
@@ -71,6 +74,7 @@ static ssize_t show_current_governor(struct sysdev_class *class, | |||
71 | } | 74 | } |
72 | 75 | ||
73 | static ssize_t store_current_governor(struct sysdev_class *class, | 76 | static ssize_t store_current_governor(struct sysdev_class *class, |
77 | struct sysdev_class_attribute *attr, | ||
74 | const char *buf, size_t count) | 78 | const char *buf, size_t count) |
75 | { | 79 | { |
76 | char gov_name[CPUIDLE_NAME_LEN]; | 80 | char gov_name[CPUIDLE_NAME_LEN]; |
@@ -191,7 +195,7 @@ static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr, | |||
191 | return ret; | 195 | return ret; |
192 | } | 196 | } |
193 | 197 | ||
194 | static struct sysfs_ops cpuidle_sysfs_ops = { | 198 | static const struct sysfs_ops cpuidle_sysfs_ops = { |
195 | .show = cpuidle_show, | 199 | .show = cpuidle_show, |
196 | .store = cpuidle_store, | 200 | .store = cpuidle_store, |
197 | }; | 201 | }; |
@@ -277,7 +281,7 @@ static ssize_t cpuidle_state_show(struct kobject * kobj, | |||
277 | return ret; | 281 | return ret; |
278 | } | 282 | } |
279 | 283 | ||
280 | static struct sysfs_ops cpuidle_state_sysfs_ops = { | 284 | static const struct sysfs_ops cpuidle_state_sysfs_ops = { |
281 | .show = cpuidle_state_show, | 285 | .show = cpuidle_state_show, |
282 | }; | 286 | }; |
283 | 287 | ||
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index af14c9a5b8d4..0099340b9616 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c | |||
@@ -1138,7 +1138,7 @@ ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page) | |||
1138 | return entry->show(&chan->common, page); | 1138 | return entry->show(&chan->common, page); |
1139 | } | 1139 | } |
1140 | 1140 | ||
1141 | struct sysfs_ops ioat_sysfs_ops = { | 1141 | const struct sysfs_ops ioat_sysfs_ops = { |
1142 | .show = ioat_attr_show, | 1142 | .show = ioat_attr_show, |
1143 | }; | 1143 | }; |
1144 | 1144 | ||
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 4f747a254074..86b97ac8774e 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h | |||
@@ -346,7 +346,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan, | |||
346 | unsigned long *phys_complete); | 346 | unsigned long *phys_complete); |
347 | void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type); | 347 | void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type); |
348 | void ioat_kobject_del(struct ioatdma_device *device); | 348 | void ioat_kobject_del(struct ioatdma_device *device); |
349 | extern struct sysfs_ops ioat_sysfs_ops; | 349 | extern const struct sysfs_ops ioat_sysfs_ops; |
350 | extern struct ioat_sysfs_entry ioat_version_attr; | 350 | extern struct ioat_sysfs_entry ioat_version_attr; |
351 | extern struct ioat_sysfs_entry ioat_cap_attr; | 351 | extern struct ioat_sysfs_entry ioat_cap_attr; |
352 | #endif /* IOATDMA_H */ | 352 | #endif /* IOATDMA_H */ |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index d205d493a68a..243e9aacad69 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -75,6 +75,14 @@ static struct edac_pci_ctl_info *e752x_pci; | |||
75 | #define E752X_NR_CSROWS 8 /* number of csrows */ | 75 | #define E752X_NR_CSROWS 8 /* number of csrows */ |
76 | 76 | ||
77 | /* E752X register addresses - device 0 function 0 */ | 77 | /* E752X register addresses - device 0 function 0 */ |
78 | #define E752X_MCHSCRB 0x52 /* Memory Scrub register (16b) */ | ||
79 | /* | ||
80 | * 6:5 Scrub Completion Count | ||
81 | * 3:2 Scrub Rate (i3100 only) | ||
82 | * 01=fast 10=normal | ||
83 | * 1:0 Scrub Mode enable | ||
84 | * 00=off 10=on | ||
85 | */ | ||
78 | #define E752X_DRB 0x60 /* DRAM row boundary register (8b) */ | 86 | #define E752X_DRB 0x60 /* DRAM row boundary register (8b) */ |
79 | #define E752X_DRA 0x70 /* DRAM row attribute register (8b) */ | 87 | #define E752X_DRA 0x70 /* DRAM row attribute register (8b) */ |
80 | /* | 88 | /* |
@@ -240,6 +248,41 @@ static const struct e752x_dev_info e752x_devs[] = { | |||
240 | .ctl_name = "3100"}, | 248 | .ctl_name = "3100"}, |
241 | }; | 249 | }; |
242 | 250 | ||
251 | /* Valid scrub rates for the e752x/3100 hardware memory scrubber. We | ||
252 | * map the scrubbing bandwidth to a hardware register value. The 'set' | ||
253 | * operation finds the 'matching or higher value'. Note that scrubbing | ||
254 | * on the e752x can only be enabled/disabled. The 3100 supports | ||
255 | * a normal and fast mode. | ||
256 | */ | ||
257 | |||
258 | #define SDRATE_EOT 0xFFFFFFFF | ||
259 | |||
260 | struct scrubrate { | ||
261 | u32 bandwidth; /* bandwidth consumed by scrubbing in bytes/sec */ | ||
262 | u16 scrubval; /* register value for scrub rate */ | ||
263 | }; | ||
264 | |||
265 | /* Rate below assumes same performance as i3100 using PC3200 DDR2 in | ||
266 | * normal mode. e752x bridges don't support choosing normal or fast mode, | ||
267 | * so the scrubbing bandwidth value isn't all that important - scrubbing is | ||
268 | * either on or off. | ||
269 | */ | ||
270 | static const struct scrubrate scrubrates_e752x[] = { | ||
271 | {0, 0x00}, /* Scrubbing Off */ | ||
272 | {500000, 0x02}, /* Scrubbing On */ | ||
273 | {SDRATE_EOT, 0x00} /* End of Table */ | ||
274 | }; | ||
275 | |||
276 | /* Fast mode: 2 GByte PC3200 DDR2 scrubbed in 33s = 63161283 bytes/s | ||
277 | * Normal mode: 125 (32000 / 256) times slower than fast mode. | ||
278 | */ | ||
279 | static const struct scrubrate scrubrates_i3100[] = { | ||
280 | {0, 0x00}, /* Scrubbing Off */ | ||
281 | {500000, 0x0a}, /* Normal mode - 32k clocks */ | ||
282 | {62500000, 0x06}, /* Fast mode - 256 clocks */ | ||
283 | {SDRATE_EOT, 0x00} /* End of Table */ | ||
284 | }; | ||
285 | |||
243 | static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, | 286 | static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, |
244 | unsigned long page) | 287 | unsigned long page) |
245 | { | 288 | { |
@@ -915,6 +958,68 @@ static void e752x_check(struct mem_ctl_info *mci) | |||
915 | e752x_process_error_info(mci, &info, 1); | 958 | e752x_process_error_info(mci, &info, 1); |
916 | } | 959 | } |
917 | 960 | ||
961 | /* Program byte/sec bandwidth scrub rate to hardware */ | ||
962 | static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *new_bw) | ||
963 | { | ||
964 | const struct scrubrate *scrubrates; | ||
965 | struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; | ||
966 | struct pci_dev *pdev = pvt->dev_d0f0; | ||
967 | int i; | ||
968 | |||
969 | if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0) | ||
970 | scrubrates = scrubrates_i3100; | ||
971 | else | ||
972 | scrubrates = scrubrates_e752x; | ||
973 | |||
974 | /* Translate the desired scrub rate to a e752x/3100 register value. | ||
975 | * Search for the bandwidth that is equal or greater than the | ||
976 | * desired rate and program the cooresponding register value. | ||
977 | */ | ||
978 | for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++) | ||
979 | if (scrubrates[i].bandwidth >= *new_bw) | ||
980 | break; | ||
981 | |||
982 | if (scrubrates[i].bandwidth == SDRATE_EOT) | ||
983 | return -1; | ||
984 | |||
985 | pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); | ||
986 | |||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | /* Convert current scrub rate value into byte/sec bandwidth */ | ||
991 | static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | ||
992 | { | ||
993 | const struct scrubrate *scrubrates; | ||
994 | struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; | ||
995 | struct pci_dev *pdev = pvt->dev_d0f0; | ||
996 | u16 scrubval; | ||
997 | int i; | ||
998 | |||
999 | if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0) | ||
1000 | scrubrates = scrubrates_i3100; | ||
1001 | else | ||
1002 | scrubrates = scrubrates_e752x; | ||
1003 | |||
1004 | /* Find the bandwidth matching the memory scrubber configuration */ | ||
1005 | pci_read_config_word(pdev, E752X_MCHSCRB, &scrubval); | ||
1006 | scrubval = scrubval & 0x0f; | ||
1007 | |||
1008 | for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++) | ||
1009 | if (scrubrates[i].scrubval == scrubval) | ||
1010 | break; | ||
1011 | |||
1012 | if (scrubrates[i].bandwidth == SDRATE_EOT) { | ||
1013 | e752x_printk(KERN_WARNING, | ||
1014 | "Invalid sdram scrub control value: 0x%x\n", scrubval); | ||
1015 | return -1; | ||
1016 | } | ||
1017 | |||
1018 | *bw = scrubrates[i].bandwidth; | ||
1019 | |||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
918 | /* Return 1 if dual channel mode is active. Else return 0. */ | 1023 | /* Return 1 if dual channel mode is active. Else return 0. */ |
919 | static inline int dual_channel_active(u16 ddrcsr) | 1024 | static inline int dual_channel_active(u16 ddrcsr) |
920 | { | 1025 | { |
@@ -1073,10 +1178,7 @@ fail: | |||
1073 | 1178 | ||
1074 | /* Setup system bus parity mask register. | 1179 | /* Setup system bus parity mask register. |
1075 | * Sysbus parity supported on: | 1180 | * Sysbus parity supported on: |
1076 | * e7320/e7520/e7525 + Xeon | 1181 | * e7320/e7520/e7525 + Xeon |
1077 | * i3100 + Xeon/Celeron | ||
1078 | * Sysbus parity not supported on: | ||
1079 | * i3100 + Pentium M/Celeron M/Core Duo/Core2 Duo | ||
1080 | */ | 1182 | */ |
1081 | static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt) | 1183 | static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt) |
1082 | { | 1184 | { |
@@ -1087,10 +1189,7 @@ static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt) | |||
1087 | /* Allow module parameter override, else see if CPU supports parity */ | 1189 | /* Allow module parameter override, else see if CPU supports parity */ |
1088 | if (sysbus_parity != -1) { | 1190 | if (sysbus_parity != -1) { |
1089 | enable = sysbus_parity; | 1191 | enable = sysbus_parity; |
1090 | } else if (cpu_id[0] && | 1192 | } else if (cpu_id[0] && !strstr(cpu_id, "Xeon")) { |
1091 | ((strstr(cpu_id, "Pentium") && strstr(cpu_id, " M ")) || | ||
1092 | (strstr(cpu_id, "Celeron") && strstr(cpu_id, " M ")) || | ||
1093 | (strstr(cpu_id, "Core") && strstr(cpu_id, "Duo")))) { | ||
1094 | e752x_printk(KERN_INFO, "System Bus Parity not " | 1193 | e752x_printk(KERN_INFO, "System Bus Parity not " |
1095 | "supported by CPU, disabling\n"); | 1194 | "supported by CPU, disabling\n"); |
1096 | enable = 0; | 1195 | enable = 0; |
@@ -1187,6 +1286,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) | |||
1187 | mci->dev_name = pci_name(pdev); | 1286 | mci->dev_name = pci_name(pdev); |
1188 | mci->edac_check = e752x_check; | 1287 | mci->edac_check = e752x_check; |
1189 | mci->ctl_page_to_phys = ctl_page_to_phys; | 1288 | mci->ctl_page_to_phys = ctl_page_to_phys; |
1289 | mci->set_sdram_scrub_rate = set_sdram_scrub_rate; | ||
1290 | mci->get_sdram_scrub_rate = get_sdram_scrub_rate; | ||
1190 | 1291 | ||
1191 | /* set the map type. 1 = normal, 0 = reversed | 1292 | /* set the map type. 1 = normal, 0 = reversed |
1192 | * Must be set before e752x_init_csrows in case csrow mapping | 1293 | * Must be set before e752x_init_csrows in case csrow mapping |
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index 53764577035f..5fdedbc0f545 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c | |||
@@ -137,7 +137,7 @@ static ssize_t edac_dev_ctl_info_store(struct kobject *kobj, | |||
137 | } | 137 | } |
138 | 138 | ||
139 | /* edac_dev file operations for an 'ctl_info' */ | 139 | /* edac_dev file operations for an 'ctl_info' */ |
140 | static struct sysfs_ops device_ctl_info_ops = { | 140 | static const struct sysfs_ops device_ctl_info_ops = { |
141 | .show = edac_dev_ctl_info_show, | 141 | .show = edac_dev_ctl_info_show, |
142 | .store = edac_dev_ctl_info_store | 142 | .store = edac_dev_ctl_info_store |
143 | }; | 143 | }; |
@@ -373,7 +373,7 @@ static ssize_t edac_dev_instance_store(struct kobject *kobj, | |||
373 | } | 373 | } |
374 | 374 | ||
375 | /* edac_dev file operations for an 'instance' */ | 375 | /* edac_dev file operations for an 'instance' */ |
376 | static struct sysfs_ops device_instance_ops = { | 376 | static const struct sysfs_ops device_instance_ops = { |
377 | .show = edac_dev_instance_show, | 377 | .show = edac_dev_instance_show, |
378 | .store = edac_dev_instance_store | 378 | .store = edac_dev_instance_store |
379 | }; | 379 | }; |
@@ -476,7 +476,7 @@ static ssize_t edac_dev_block_store(struct kobject *kobj, | |||
476 | } | 476 | } |
477 | 477 | ||
478 | /* edac_dev file operations for a 'block' */ | 478 | /* edac_dev file operations for a 'block' */ |
479 | static struct sysfs_ops device_block_ops = { | 479 | static const struct sysfs_ops device_block_ops = { |
480 | .show = edac_dev_block_show, | 480 | .show = edac_dev_block_show, |
481 | .store = edac_dev_block_store | 481 | .store = edac_dev_block_store |
482 | }; | 482 | }; |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index e1d4ce083481..88840e9fa3e0 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -245,7 +245,7 @@ static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, | |||
245 | return -EIO; | 245 | return -EIO; |
246 | } | 246 | } |
247 | 247 | ||
248 | static struct sysfs_ops csrowfs_ops = { | 248 | static const struct sysfs_ops csrowfs_ops = { |
249 | .show = csrowdev_show, | 249 | .show = csrowdev_show, |
250 | .store = csrowdev_store | 250 | .store = csrowdev_store |
251 | }; | 251 | }; |
@@ -575,7 +575,7 @@ static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr, | |||
575 | } | 575 | } |
576 | 576 | ||
577 | /* Intermediate show/store table */ | 577 | /* Intermediate show/store table */ |
578 | static struct sysfs_ops mci_ops = { | 578 | static const struct sysfs_ops mci_ops = { |
579 | .show = mcidev_show, | 579 | .show = mcidev_show, |
580 | .store = mcidev_store | 580 | .store = mcidev_store |
581 | }; | 581 | }; |
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index fb60a877d768..bef94e3d9944 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c | |||
@@ -121,7 +121,7 @@ static ssize_t edac_pci_instance_store(struct kobject *kobj, | |||
121 | } | 121 | } |
122 | 122 | ||
123 | /* fs_ops table */ | 123 | /* fs_ops table */ |
124 | static struct sysfs_ops pci_instance_ops = { | 124 | static const struct sysfs_ops pci_instance_ops = { |
125 | .show = edac_pci_instance_show, | 125 | .show = edac_pci_instance_show, |
126 | .store = edac_pci_instance_store | 126 | .store = edac_pci_instance_store |
127 | }; | 127 | }; |
@@ -261,7 +261,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj, | |||
261 | return -EIO; | 261 | return -EIO; |
262 | } | 262 | } |
263 | 263 | ||
264 | static struct sysfs_ops edac_pci_sysfs_ops = { | 264 | static const struct sysfs_ops edac_pci_sysfs_ops = { |
265 | .show = edac_pci_dev_show, | 265 | .show = edac_pci_dev_show, |
266 | .store = edac_pci_dev_store | 266 | .store = edac_pci_dev_store |
267 | }; | 267 | }; |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index ecd5928d7110..94cac0aacea3 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -239,16 +239,15 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op, | |||
239 | /* we only need the error registers */ | 239 | /* we only need the error registers */ |
240 | r.start += 0xe00; | 240 | r.start += 0xe00; |
241 | 241 | ||
242 | if (!devm_request_mem_region(&op->dev, r.start, | 242 | if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r), |
243 | r.end - r.start + 1, pdata->name)) { | 243 | pdata->name)) { |
244 | printk(KERN_ERR "%s: Error while requesting mem region\n", | 244 | printk(KERN_ERR "%s: Error while requesting mem region\n", |
245 | __func__); | 245 | __func__); |
246 | res = -EBUSY; | 246 | res = -EBUSY; |
247 | goto err; | 247 | goto err; |
248 | } | 248 | } |
249 | 249 | ||
250 | pdata->pci_vbase = devm_ioremap(&op->dev, r.start, | 250 | pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r)); |
251 | r.end - r.start + 1); | ||
252 | if (!pdata->pci_vbase) { | 251 | if (!pdata->pci_vbase) { |
253 | printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); | 252 | printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); |
254 | res = -ENOMEM; | 253 | res = -ENOMEM; |
@@ -668,15 +667,125 @@ static struct of_platform_driver mpc85xx_l2_err_driver = { | |||
668 | 667 | ||
669 | /**************************** MC Err device ***************************/ | 668 | /**************************** MC Err device ***************************/ |
670 | 669 | ||
670 | /* | ||
671 | * Taken from table 8-55 in the MPC8641 User's Manual and/or 9-61 in the | ||
672 | * MPC8572 User's Manual. Each line represents a syndrome bit column as a | ||
673 | * 64-bit value, but split into an upper and lower 32-bit chunk. The labels | ||
674 | * below correspond to Freescale's manuals. | ||
675 | */ | ||
676 | static unsigned int ecc_table[16] = { | ||
677 | /* MSB LSB */ | ||
678 | /* [0:31] [32:63] */ | ||
679 | 0xf00fe11e, 0xc33c0ff7, /* Syndrome bit 7 */ | ||
680 | 0x00ff00ff, 0x00fff0ff, | ||
681 | 0x0f0f0f0f, 0x0f0fff00, | ||
682 | 0x11113333, 0x7777000f, | ||
683 | 0x22224444, 0x8888222f, | ||
684 | 0x44448888, 0xffff4441, | ||
685 | 0x8888ffff, 0x11118882, | ||
686 | 0xffff1111, 0x22221114, /* Syndrome bit 0 */ | ||
687 | }; | ||
688 | |||
689 | /* | ||
690 | * Calculate the correct ECC value for a 64-bit value specified by high:low | ||
691 | */ | ||
692 | static u8 calculate_ecc(u32 high, u32 low) | ||
693 | { | ||
694 | u32 mask_low; | ||
695 | u32 mask_high; | ||
696 | int bit_cnt; | ||
697 | u8 ecc = 0; | ||
698 | int i; | ||
699 | int j; | ||
700 | |||
701 | for (i = 0; i < 8; i++) { | ||
702 | mask_high = ecc_table[i * 2]; | ||
703 | mask_low = ecc_table[i * 2 + 1]; | ||
704 | bit_cnt = 0; | ||
705 | |||
706 | for (j = 0; j < 32; j++) { | ||
707 | if ((mask_high >> j) & 1) | ||
708 | bit_cnt ^= (high >> j) & 1; | ||
709 | if ((mask_low >> j) & 1) | ||
710 | bit_cnt ^= (low >> j) & 1; | ||
711 | } | ||
712 | |||
713 | ecc |= bit_cnt << i; | ||
714 | } | ||
715 | |||
716 | return ecc; | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * Create the syndrome code which is generated if the data line specified by | ||
721 | * 'bit' failed. Eg generate an 8-bit codes seen in Table 8-55 in the MPC8641 | ||
722 | * User's Manual and 9-61 in the MPC8572 User's Manual. | ||
723 | */ | ||
724 | static u8 syndrome_from_bit(unsigned int bit) { | ||
725 | int i; | ||
726 | u8 syndrome = 0; | ||
727 | |||
728 | /* | ||
729 | * Cycle through the upper or lower 32-bit portion of each value in | ||
730 | * ecc_table depending on if 'bit' is in the upper or lower half of | ||
731 | * 64-bit data. | ||
732 | */ | ||
733 | for (i = bit < 32; i < 16; i += 2) | ||
734 | syndrome |= ((ecc_table[i] >> (bit % 32)) & 1) << (i / 2); | ||
735 | |||
736 | return syndrome; | ||
737 | } | ||
738 | |||
739 | /* | ||
740 | * Decode data and ecc syndrome to determine what went wrong | ||
741 | * Note: This can only decode single-bit errors | ||
742 | */ | ||
743 | static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc, | ||
744 | int *bad_data_bit, int *bad_ecc_bit) | ||
745 | { | ||
746 | int i; | ||
747 | u8 syndrome; | ||
748 | |||
749 | *bad_data_bit = -1; | ||
750 | *bad_ecc_bit = -1; | ||
751 | |||
752 | /* | ||
753 | * Calculate the ECC of the captured data and XOR it with the captured | ||
754 | * ECC to find an ECC syndrome value we can search for | ||
755 | */ | ||
756 | syndrome = calculate_ecc(cap_high, cap_low) ^ cap_ecc; | ||
757 | |||
758 | /* Check if a data line is stuck... */ | ||
759 | for (i = 0; i < 64; i++) { | ||
760 | if (syndrome == syndrome_from_bit(i)) { | ||
761 | *bad_data_bit = i; | ||
762 | return; | ||
763 | } | ||
764 | } | ||
765 | |||
766 | /* If data is correct, check ECC bits for errors... */ | ||
767 | for (i = 0; i < 8; i++) { | ||
768 | if ((syndrome >> i) & 0x1) { | ||
769 | *bad_ecc_bit = i; | ||
770 | return; | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | |||
671 | static void mpc85xx_mc_check(struct mem_ctl_info *mci) | 775 | static void mpc85xx_mc_check(struct mem_ctl_info *mci) |
672 | { | 776 | { |
673 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | 777 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; |
674 | struct csrow_info *csrow; | 778 | struct csrow_info *csrow; |
779 | u32 bus_width; | ||
675 | u32 err_detect; | 780 | u32 err_detect; |
676 | u32 syndrome; | 781 | u32 syndrome; |
677 | u32 err_addr; | 782 | u32 err_addr; |
678 | u32 pfn; | 783 | u32 pfn; |
679 | int row_index; | 784 | int row_index; |
785 | u32 cap_high; | ||
786 | u32 cap_low; | ||
787 | int bad_data_bit; | ||
788 | int bad_ecc_bit; | ||
680 | 789 | ||
681 | err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); | 790 | err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); |
682 | if (!err_detect) | 791 | if (!err_detect) |
@@ -692,6 +801,15 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) | |||
692 | } | 801 | } |
693 | 802 | ||
694 | syndrome = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ECC); | 803 | syndrome = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ECC); |
804 | |||
805 | /* Mask off appropriate bits of syndrome based on bus width */ | ||
806 | bus_width = (in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG) & | ||
807 | DSC_DBW_MASK) ? 32 : 64; | ||
808 | if (bus_width == 64) | ||
809 | syndrome &= 0xff; | ||
810 | else | ||
811 | syndrome &= 0xffff; | ||
812 | |||
695 | err_addr = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS); | 813 | err_addr = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS); |
696 | pfn = err_addr >> PAGE_SHIFT; | 814 | pfn = err_addr >> PAGE_SHIFT; |
697 | 815 | ||
@@ -701,14 +819,35 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) | |||
701 | break; | 819 | break; |
702 | } | 820 | } |
703 | 821 | ||
704 | mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data High: %#8.8x\n", | 822 | cap_high = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_HI); |
705 | in_be32(pdata->mc_vbase + | 823 | cap_low = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_LO); |
706 | MPC85XX_MC_CAPTURE_DATA_HI)); | 824 | |
707 | mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data Low: %#8.8x\n", | 825 | /* |
708 | in_be32(pdata->mc_vbase + | 826 | * Analyze single-bit errors on 64-bit wide buses |
709 | MPC85XX_MC_CAPTURE_DATA_LO)); | 827 | * TODO: Add support for 32-bit wide buses |
710 | mpc85xx_mc_printk(mci, KERN_ERR, "syndrome: %#8.8x\n", syndrome); | 828 | */ |
711 | mpc85xx_mc_printk(mci, KERN_ERR, "err addr: %#8.8x\n", err_addr); | 829 | if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) { |
830 | sbe_ecc_decode(cap_high, cap_low, syndrome, | ||
831 | &bad_data_bit, &bad_ecc_bit); | ||
832 | |||
833 | if (bad_data_bit != -1) | ||
834 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
835 | "Faulty Data bit: %d\n", bad_data_bit); | ||
836 | if (bad_ecc_bit != -1) | ||
837 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
838 | "Faulty ECC bit: %d\n", bad_ecc_bit); | ||
839 | |||
840 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
841 | "Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n", | ||
842 | cap_high ^ (1 << (bad_data_bit - 32)), | ||
843 | cap_low ^ (1 << bad_data_bit), | ||
844 | syndrome ^ (1 << bad_ecc_bit)); | ||
845 | } | ||
846 | |||
847 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
848 | "Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n", | ||
849 | cap_high, cap_low, syndrome); | ||
850 | mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8x\n", err_addr); | ||
712 | mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn); | 851 | mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn); |
713 | 852 | ||
714 | /* we are out of range */ | 853 | /* we are out of range */ |
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index 52432ee7c4b9..cb24df839460 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h | |||
@@ -48,6 +48,9 @@ | |||
48 | #define DSC_MEM_EN 0x80000000 | 48 | #define DSC_MEM_EN 0x80000000 |
49 | #define DSC_ECC_EN 0x20000000 | 49 | #define DSC_ECC_EN 0x20000000 |
50 | #define DSC_RD_EN 0x10000000 | 50 | #define DSC_RD_EN 0x10000000 |
51 | #define DSC_DBW_MASK 0x00180000 | ||
52 | #define DSC_DBW_32 0x00080000 | ||
53 | #define DSC_DBW_64 0x00000000 | ||
51 | 54 | ||
52 | #define DSC_SDTYPE_MASK 0x07000000 | 55 | #define DSC_SDTYPE_MASK 0x07000000 |
53 | 56 | ||
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 014cabd3afda..5db0518c66da 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | #include <linux/rwsem.h> | 35 | #include <linux/rwsem.h> |
36 | #include <linux/semaphore.h> | ||
37 | #include <linux/spinlock.h> | 36 | #include <linux/spinlock.h> |
38 | #include <linux/string.h> | 37 | #include <linux/string.h> |
39 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
@@ -828,9 +827,9 @@ static int update_unit(struct device *dev, void *data) | |||
828 | struct fw_driver *driver = (struct fw_driver *)dev->driver; | 827 | struct fw_driver *driver = (struct fw_driver *)dev->driver; |
829 | 828 | ||
830 | if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { | 829 | if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { |
831 | down(&dev->sem); | 830 | device_lock(dev); |
832 | driver->update(unit); | 831 | driver->update(unit); |
833 | up(&dev->sem); | 832 | device_unlock(dev); |
834 | } | 833 | } |
835 | 834 | ||
836 | return 0; | 835 | return 0; |
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 9e4f59dc7f1e..110e24e50883 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c | |||
@@ -122,7 +122,7 @@ edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) | |||
122 | return ret; | 122 | return ret; |
123 | } | 123 | } |
124 | 124 | ||
125 | static struct sysfs_ops edd_attr_ops = { | 125 | static const struct sysfs_ops edd_attr_ops = { |
126 | .show = edd_attr_show, | 126 | .show = edd_attr_show, |
127 | }; | 127 | }; |
128 | 128 | ||
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index f4f709d1370b..082f06ecd327 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -362,7 +362,7 @@ static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr, | |||
362 | return ret; | 362 | return ret; |
363 | } | 363 | } |
364 | 364 | ||
365 | static struct sysfs_ops efivar_attr_ops = { | 365 | static const struct sysfs_ops efivar_attr_ops = { |
366 | .show = efivar_attr_show, | 366 | .show = efivar_attr_show, |
367 | .store = efivar_attr_store, | 367 | .store = efivar_attr_store, |
368 | }; | 368 | }; |
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index a3600e3ed0fa..ed2801c378de 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c | |||
@@ -519,7 +519,7 @@ static ssize_t ibft_show_attribute(struct kobject *kobj, | |||
519 | return ret; | 519 | return ret; |
520 | } | 520 | } |
521 | 521 | ||
522 | static struct sysfs_ops ibft_attr_ops = { | 522 | static const struct sysfs_ops ibft_attr_ops = { |
523 | .show = ibft_show_attribute, | 523 | .show = ibft_show_attribute, |
524 | }; | 524 | }; |
525 | 525 | ||
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index 20f645743ead..d59f7cad2269 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c | |||
@@ -74,7 +74,7 @@ static struct attribute *def_attrs[] = { | |||
74 | NULL | 74 | NULL |
75 | }; | 75 | }; |
76 | 76 | ||
77 | static struct sysfs_ops memmap_attr_ops = { | 77 | static const struct sysfs_ops memmap_attr_ops = { |
78 | .show = memmap_attr_show, | 78 | .show = memmap_attr_show, |
79 | }; | 79 | }; |
80 | 80 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9006fdb26fea..6d1b86661e63 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -623,7 +623,9 @@ static const struct attribute_group gpiochip_attr_group = { | |||
623 | * /sys/class/gpio/unexport ... write-only | 623 | * /sys/class/gpio/unexport ... write-only |
624 | * integer N ... number of GPIO to unexport | 624 | * integer N ... number of GPIO to unexport |
625 | */ | 625 | */ |
626 | static ssize_t export_store(struct class *class, const char *buf, size_t len) | 626 | static ssize_t export_store(struct class *class, |
627 | struct class_attribute *attr, | ||
628 | const char *buf, size_t len) | ||
627 | { | 629 | { |
628 | long gpio; | 630 | long gpio; |
629 | int status; | 631 | int status; |
@@ -653,7 +655,9 @@ done: | |||
653 | return status ? : len; | 655 | return status ? : len; |
654 | } | 656 | } |
655 | 657 | ||
656 | static ssize_t unexport_store(struct class *class, const char *buf, size_t len) | 658 | static ssize_t unexport_store(struct class *class, |
659 | struct class_attribute *attr, | ||
660 | const char *buf, size_t len) | ||
657 | { | 661 | { |
658 | long gpio; | 662 | long gpio; |
659 | int status; | 663 | int status; |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 7e42b7e9d43a..014ce24761b9 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
@@ -70,19 +70,17 @@ static int drm_class_resume(struct device *dev) | |||
70 | return 0; | 70 | return 0; |
71 | } | 71 | } |
72 | 72 | ||
73 | /* Display the version of drm_core. This doesn't work right in current design */ | ||
74 | static ssize_t version_show(struct class *dev, char *buf) | ||
75 | { | ||
76 | return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR, | ||
77 | CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE); | ||
78 | } | ||
79 | |||
80 | static char *drm_devnode(struct device *dev, mode_t *mode) | 73 | static char *drm_devnode(struct device *dev, mode_t *mode) |
81 | { | 74 | { |
82 | return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); | 75 | return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); |
83 | } | 76 | } |
84 | 77 | ||
85 | static CLASS_ATTR(version, S_IRUGO, version_show, NULL); | 78 | static CLASS_ATTR_STRING(version, S_IRUGO, |
79 | CORE_NAME " " | ||
80 | __stringify(CORE_MAJOR) "." | ||
81 | __stringify(CORE_MINOR) "." | ||
82 | __stringify(CORE_PATCHLEVEL) " " | ||
83 | CORE_DATE); | ||
86 | 84 | ||
87 | /** | 85 | /** |
88 | * drm_sysfs_create - create a struct drm_sysfs_class structure | 86 | * drm_sysfs_create - create a struct drm_sysfs_class structure |
@@ -109,7 +107,7 @@ struct class *drm_sysfs_create(struct module *owner, char *name) | |||
109 | class->suspend = drm_class_suspend; | 107 | class->suspend = drm_class_suspend; |
110 | class->resume = drm_class_resume; | 108 | class->resume = drm_class_resume; |
111 | 109 | ||
112 | err = class_create_file(class, &class_attr_version); | 110 | err = class_create_file(class, &class_attr_version.attr); |
113 | if (err) | 111 | if (err) |
114 | goto err_out_class; | 112 | goto err_out_class; |
115 | 113 | ||
@@ -132,7 +130,7 @@ void drm_sysfs_destroy(void) | |||
132 | { | 130 | { |
133 | if ((drm_class == NULL) || (IS_ERR(drm_class))) | 131 | if ((drm_class == NULL) || (IS_ERR(drm_class))) |
134 | return; | 132 | return; |
135 | class_remove_file(drm_class, &class_attr_version); | 133 | class_remove_file(drm_class, &class_attr_version.attr); |
136 | class_destroy(drm_class); | 134 | class_destroy(drm_class); |
137 | } | 135 | } |
138 | 136 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c7320ce4567d..89c38c49066f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -128,7 +128,7 @@ static struct attribute *ttm_bo_global_attrs[] = { | |||
128 | NULL | 128 | NULL |
129 | }; | 129 | }; |
130 | 130 | ||
131 | static struct sysfs_ops ttm_bo_global_ops = { | 131 | static const struct sysfs_ops ttm_bo_global_ops = { |
132 | .show = &ttm_bo_global_show | 132 | .show = &ttm_bo_global_show |
133 | }; | 133 | }; |
134 | 134 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index f5245c02b8fd..eb143e04d402 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c | |||
@@ -152,7 +152,7 @@ static struct attribute *ttm_mem_zone_attrs[] = { | |||
152 | NULL | 152 | NULL |
153 | }; | 153 | }; |
154 | 154 | ||
155 | static struct sysfs_ops ttm_mem_zone_ops = { | 155 | static const struct sysfs_ops ttm_mem_zone_ops = { |
156 | .show = &ttm_mem_zone_show, | 156 | .show = &ttm_mem_zone_show, |
157 | .store = &ttm_mem_zone_store | 157 | .store = &ttm_mem_zone_store |
158 | }; | 158 | }; |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 913abd7c172f..c7c237537f81 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -850,7 +850,7 @@ static const struct i2c_algorithm omap_i2c_algo = { | |||
850 | .functionality = omap_i2c_func, | 850 | .functionality = omap_i2c_func, |
851 | }; | 851 | }; |
852 | 852 | ||
853 | static int __init | 853 | static int __devinit |
854 | omap_i2c_probe(struct platform_device *pdev) | 854 | omap_i2c_probe(struct platform_device *pdev) |
855 | { | 855 | { |
856 | struct omap_i2c_dev *dev; | 856 | struct omap_i2c_dev *dev; |
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 5122b5a8aa2d..18350213479e 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/moduleparam.h> | 19 | #include <linux/moduleparam.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/freezer.h> | 21 | #include <linux/freezer.h> |
22 | #include <linux/semaphore.h> | ||
23 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
24 | 23 | ||
25 | #include "csr.h" | 24 | #include "csr.h" |
@@ -1397,9 +1396,9 @@ static int update_pdrv(struct device *dev, void *data) | |||
1397 | pdrv = container_of(drv, struct hpsb_protocol_driver, | 1396 | pdrv = container_of(drv, struct hpsb_protocol_driver, |
1398 | driver); | 1397 | driver); |
1399 | if (pdrv->update) { | 1398 | if (pdrv->update) { |
1400 | down(&ud->device.sem); | 1399 | device_lock(&ud->device); |
1401 | error = pdrv->update(ud); | 1400 | error = pdrv->update(ud); |
1402 | up(&ud->device.sem); | 1401 | device_unlock(&ud->device); |
1403 | } | 1402 | } |
1404 | if (error) | 1403 | if (error) |
1405 | device_release_driver(&ud->device); | 1404 | device_release_driver(&ud->device); |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 5130fc55b8e2..764787ebe8d8 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -3597,7 +3597,7 @@ static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr, | |||
3597 | atomic_long_read(&group->counter[cm_attr->index])); | 3597 | atomic_long_read(&group->counter[cm_attr->index])); |
3598 | } | 3598 | } |
3599 | 3599 | ||
3600 | static struct sysfs_ops cm_counter_ops = { | 3600 | static const struct sysfs_ops cm_counter_ops = { |
3601 | .show = cm_show_counter | 3601 | .show = cm_show_counter |
3602 | }; | 3602 | }; |
3603 | 3603 | ||
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 158a214da2f7..1558bb7fc74d 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
@@ -79,7 +79,7 @@ static ssize_t port_attr_show(struct kobject *kobj, | |||
79 | return port_attr->show(p, port_attr, buf); | 79 | return port_attr->show(p, port_attr, buf); |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct sysfs_ops port_sysfs_ops = { | 82 | static const struct sysfs_ops port_sysfs_ops = { |
83 | .show = port_attr_show | 83 | .show = port_attr_show |
84 | }; | 84 | }; |
85 | 85 | ||
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 1b09b735c5a8..017d6e24448f 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -1336,11 +1336,8 @@ static void ib_ucm_remove_one(struct ib_device *device) | |||
1336 | device_unregister(&ucm_dev->dev); | 1336 | device_unregister(&ucm_dev->dev); |
1337 | } | 1337 | } |
1338 | 1338 | ||
1339 | static ssize_t show_abi_version(struct class *class, char *buf) | 1339 | static CLASS_ATTR_STRING(abi_version, S_IRUGO, |
1340 | { | 1340 | __stringify(IB_USER_CM_ABI_VERSION)); |
1341 | return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION); | ||
1342 | } | ||
1343 | static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); | ||
1344 | 1341 | ||
1345 | static int __init ib_ucm_init(void) | 1342 | static int __init ib_ucm_init(void) |
1346 | { | 1343 | { |
@@ -1353,7 +1350,7 @@ static int __init ib_ucm_init(void) | |||
1353 | goto error1; | 1350 | goto error1; |
1354 | } | 1351 | } |
1355 | 1352 | ||
1356 | ret = class_create_file(&cm_class, &class_attr_abi_version); | 1353 | ret = class_create_file(&cm_class, &class_attr_abi_version.attr); |
1357 | if (ret) { | 1354 | if (ret) { |
1358 | printk(KERN_ERR "ucm: couldn't create abi_version attribute\n"); | 1355 | printk(KERN_ERR "ucm: couldn't create abi_version attribute\n"); |
1359 | goto error2; | 1356 | goto error2; |
@@ -1367,7 +1364,7 @@ static int __init ib_ucm_init(void) | |||
1367 | return 0; | 1364 | return 0; |
1368 | 1365 | ||
1369 | error3: | 1366 | error3: |
1370 | class_remove_file(&cm_class, &class_attr_abi_version); | 1367 | class_remove_file(&cm_class, &class_attr_abi_version.attr); |
1371 | error2: | 1368 | error2: |
1372 | unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); | 1369 | unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); |
1373 | error1: | 1370 | error1: |
@@ -1377,7 +1374,7 @@ error1: | |||
1377 | static void __exit ib_ucm_cleanup(void) | 1374 | static void __exit ib_ucm_cleanup(void) |
1378 | { | 1375 | { |
1379 | ib_unregister_client(&ucm_client); | 1376 | ib_unregister_client(&ucm_client); |
1380 | class_remove_file(&cm_class, &class_attr_abi_version); | 1377 | class_remove_file(&cm_class, &class_attr_abi_version.attr); |
1381 | unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); | 1378 | unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); |
1382 | if (overflow_maj) | 1379 | if (overflow_maj) |
1383 | unregister_chrdev_region(overflow_maj, IB_UCM_MAX_DEVICES); | 1380 | unregister_chrdev_region(overflow_maj, IB_UCM_MAX_DEVICES); |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 02d360cfc2f7..04b585e86cb2 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -965,11 +965,8 @@ static ssize_t show_port(struct device *dev, struct device_attribute *attr, | |||
965 | } | 965 | } |
966 | static DEVICE_ATTR(port, S_IRUGO, show_port, NULL); | 966 | static DEVICE_ATTR(port, S_IRUGO, show_port, NULL); |
967 | 967 | ||
968 | static ssize_t show_abi_version(struct class *class, char *buf) | 968 | static CLASS_ATTR_STRING(abi_version, S_IRUGO, |
969 | { | 969 | __stringify(IB_USER_MAD_ABI_VERSION)); |
970 | return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION); | ||
971 | } | ||
972 | static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); | ||
973 | 970 | ||
974 | static dev_t overflow_maj; | 971 | static dev_t overflow_maj; |
975 | static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS); | 972 | static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS); |
@@ -1194,7 +1191,7 @@ static int __init ib_umad_init(void) | |||
1194 | goto out_chrdev; | 1191 | goto out_chrdev; |
1195 | } | 1192 | } |
1196 | 1193 | ||
1197 | ret = class_create_file(umad_class, &class_attr_abi_version); | 1194 | ret = class_create_file(umad_class, &class_attr_abi_version.attr); |
1198 | if (ret) { | 1195 | if (ret) { |
1199 | printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n"); | 1196 | printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n"); |
1200 | goto out_class; | 1197 | goto out_class; |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 4fa2e6516441..d805cf365c8d 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -691,11 +691,8 @@ static ssize_t show_dev_abi_version(struct device *device, | |||
691 | } | 691 | } |
692 | static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL); | 692 | static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL); |
693 | 693 | ||
694 | static ssize_t show_abi_version(struct class *class, char *buf) | 694 | static CLASS_ATTR_STRING(abi_version, S_IRUGO, |
695 | { | 695 | __stringify(IB_USER_VERBS_ABI_VERSION)); |
696 | return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION); | ||
697 | } | ||
698 | static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); | ||
699 | 696 | ||
700 | static dev_t overflow_maj; | 697 | static dev_t overflow_maj; |
701 | static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES); | 698 | static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES); |
@@ -841,7 +838,7 @@ static int __init ib_uverbs_init(void) | |||
841 | goto out_chrdev; | 838 | goto out_chrdev; |
842 | } | 839 | } |
843 | 840 | ||
844 | ret = class_create_file(uverbs_class, &class_attr_abi_version); | 841 | ret = class_create_file(uverbs_class, &class_attr_abi_version.attr); |
845 | if (ret) { | 842 | if (ret) { |
846 | printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n"); | 843 | printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n"); |
847 | goto out_class; | 844 | goto out_class; |
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 437f55c5d18d..419795f4a2aa 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c | |||
@@ -321,6 +321,7 @@ int wf_register_sensor(struct wf_sensor *new_sr) | |||
321 | kref_init(&new_sr->ref); | 321 | kref_init(&new_sr->ref); |
322 | list_add(&new_sr->link, &wf_sensors); | 322 | list_add(&new_sr->link, &wf_sensors); |
323 | 323 | ||
324 | sysfs_attr_init(&new_sr->attr.attr); | ||
324 | new_sr->attr.attr.name = new_sr->name; | 325 | new_sr->attr.attr.name = new_sr->name; |
325 | new_sr->attr.attr.mode = 0444; | 326 | new_sr->attr.attr.mode = 0444; |
326 | new_sr->attr.show = wf_show_sensor; | 327 | new_sr->attr.show = wf_show_sensor; |
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 6c68b9e5f5c4..43137b421f92 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c | |||
@@ -173,6 +173,7 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, | |||
173 | 173 | ||
174 | fct->fan_type = pwm_fan; | 174 | fct->fan_type = pwm_fan; |
175 | fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN; | 175 | fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN; |
176 | sysfs_attr_init(&fct->ctrl.attr.attr); | ||
176 | 177 | ||
177 | /* We use the name & location here the same way we do for SMU sensors, | 178 | /* We use the name & location here the same way we do for SMU sensors, |
178 | * see the comment in windfarm_smu_sensors.c. The locations are a bit | 179 | * see the comment in windfarm_smu_sensors.c. The locations are a bit |
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c index f91b40942e07..84d2b91e4efb 100644 --- a/drivers/md/dm-sysfs.c +++ b/drivers/md/dm-sysfs.c | |||
@@ -75,7 +75,7 @@ static struct attribute *dm_attrs[] = { | |||
75 | NULL, | 75 | NULL, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static struct sysfs_ops dm_sysfs_ops = { | 78 | static const struct sysfs_ops dm_sysfs_ops = { |
79 | .show = dm_attr_show, | 79 | .show = dm_attr_show, |
80 | }; | 80 | }; |
81 | 81 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index a20a71e5efd3..fdc1890b6ac5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -2642,7 +2642,7 @@ static void rdev_free(struct kobject *ko) | |||
2642 | mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj); | 2642 | mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj); |
2643 | kfree(rdev); | 2643 | kfree(rdev); |
2644 | } | 2644 | } |
2645 | static struct sysfs_ops rdev_sysfs_ops = { | 2645 | static const struct sysfs_ops rdev_sysfs_ops = { |
2646 | .show = rdev_attr_show, | 2646 | .show = rdev_attr_show, |
2647 | .store = rdev_attr_store, | 2647 | .store = rdev_attr_store, |
2648 | }; | 2648 | }; |
@@ -4059,7 +4059,7 @@ static void md_free(struct kobject *ko) | |||
4059 | kfree(mddev); | 4059 | kfree(mddev); |
4060 | } | 4060 | } |
4061 | 4061 | ||
4062 | static struct sysfs_ops md_sysfs_ops = { | 4062 | static const struct sysfs_ops md_sysfs_ops = { |
4063 | .show = md_attr_show, | 4063 | .show = md_attr_show, |
4064 | .store = md_attr_store, | 4064 | .store = md_attr_store, |
4065 | }; | 4065 | }; |
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 7400eacb4d64..142c327afb32 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c | |||
@@ -1735,7 +1735,7 @@ static struct v4l2_int_device omap24xxcam = { | |||
1735 | * | 1735 | * |
1736 | */ | 1736 | */ |
1737 | 1737 | ||
1738 | static int __init omap24xxcam_probe(struct platform_device *pdev) | 1738 | static int __devinit omap24xxcam_probe(struct platform_device *pdev) |
1739 | { | 1739 | { |
1740 | struct omap24xxcam_device *cam; | 1740 | struct omap24xxcam_device *cam; |
1741 | struct resource *mem; | 1741 | struct resource *mem; |
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 04c27266f567..779aa8ebe4cf 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
@@ -497,12 +497,7 @@ static struct pci_driver phantom_pci_driver = { | |||
497 | .resume = phantom_resume | 497 | .resume = phantom_resume |
498 | }; | 498 | }; |
499 | 499 | ||
500 | static ssize_t phantom_show_version(struct class *cls, char *buf) | 500 | static CLASS_ATTR_STRING(version, 0444, PHANTOM_VERSION); |
501 | { | ||
502 | return sprintf(buf, PHANTOM_VERSION "\n"); | ||
503 | } | ||
504 | |||
505 | static CLASS_ATTR(version, 0444, phantom_show_version, NULL); | ||
506 | 501 | ||
507 | static int __init phantom_init(void) | 502 | static int __init phantom_init(void) |
508 | { | 503 | { |
@@ -515,7 +510,7 @@ static int __init phantom_init(void) | |||
515 | printk(KERN_ERR "phantom: can't register phantom class\n"); | 510 | printk(KERN_ERR "phantom: can't register phantom class\n"); |
516 | goto err; | 511 | goto err; |
517 | } | 512 | } |
518 | retval = class_create_file(phantom_class, &class_attr_version); | 513 | retval = class_create_file(phantom_class, &class_attr_version.attr); |
519 | if (retval) { | 514 | if (retval) { |
520 | printk(KERN_ERR "phantom: can't create sysfs version file\n"); | 515 | printk(KERN_ERR "phantom: can't create sysfs version file\n"); |
521 | goto err_class; | 516 | goto err_class; |
@@ -541,7 +536,7 @@ static int __init phantom_init(void) | |||
541 | err_unchr: | 536 | err_unchr: |
542 | unregister_chrdev_region(dev, PHANTOM_MAX_MINORS); | 537 | unregister_chrdev_region(dev, PHANTOM_MAX_MINORS); |
543 | err_attr: | 538 | err_attr: |
544 | class_remove_file(phantom_class, &class_attr_version); | 539 | class_remove_file(phantom_class, &class_attr_version.attr); |
545 | err_class: | 540 | err_class: |
546 | class_destroy(phantom_class); | 541 | class_destroy(phantom_class); |
547 | err: | 542 | err: |
@@ -554,7 +549,7 @@ static void __exit phantom_exit(void) | |||
554 | 549 | ||
555 | unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS); | 550 | unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS); |
556 | 551 | ||
557 | class_remove_file(phantom_class, &class_attr_version); | 552 | class_remove_file(phantom_class, &class_attr_version.attr); |
558 | class_destroy(phantom_class); | 553 | class_destroy(phantom_class); |
559 | 554 | ||
560 | pr_debug("phantom: module successfully removed\n"); | 555 | pr_debug("phantom: module successfully removed\n"); |
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h index 02a77b8b8eef..7a8b9068ea03 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h | |||
@@ -516,8 +516,7 @@ struct gru_blade_state { | |||
516 | 516 | ||
517 | /* Scan all active GRUs in a GRU bitmap */ | 517 | /* Scan all active GRUs in a GRU bitmap */ |
518 | #define for_each_gru_in_bitmap(gid, map) \ | 518 | #define for_each_gru_in_bitmap(gid, map) \ |
519 | for ((gid) = find_first_bit((map), GRU_MAX_GRUS); (gid) < GRU_MAX_GRUS;\ | 519 | for_each_set_bit((gid), (map), GRU_MAX_GRUS) |
520 | (gid)++, (gid) = find_next_bit((map), GRU_MAX_GRUS, (gid))) | ||
521 | 520 | ||
522 | /* Scan all active GRUs on a specific blade */ | 521 | /* Scan all active GRUs on a specific blade */ |
523 | #define for_each_gru_on_blade(gru, nid, i) \ | 522 | #define for_each_gru_on_blade(gru, nid, i) \ |
@@ -536,23 +535,17 @@ struct gru_blade_state { | |||
536 | 535 | ||
537 | /* Scan each CBR whose bit is set in a TFM (or copy of) */ | 536 | /* Scan each CBR whose bit is set in a TFM (or copy of) */ |
538 | #define for_each_cbr_in_tfm(i, map) \ | 537 | #define for_each_cbr_in_tfm(i, map) \ |
539 | for ((i) = find_first_bit(map, GRU_NUM_CBE); \ | 538 | for_each_set_bit((i), (map), GRU_NUM_CBE) |
540 | (i) < GRU_NUM_CBE; \ | ||
541 | (i)++, (i) = find_next_bit(map, GRU_NUM_CBE, i)) | ||
542 | 539 | ||
543 | /* Scan each CBR in a CBR bitmap. Note: multiple CBRs in an allocation unit */ | 540 | /* Scan each CBR in a CBR bitmap. Note: multiple CBRs in an allocation unit */ |
544 | #define for_each_cbr_in_allocation_map(i, map, k) \ | 541 | #define for_each_cbr_in_allocation_map(i, map, k) \ |
545 | for ((k) = find_first_bit(map, GRU_CBR_AU); (k) < GRU_CBR_AU; \ | 542 | for_each_set_bit((k), (map), GRU_CBR_AU) \ |
546 | (k) = find_next_bit(map, GRU_CBR_AU, (k) + 1)) \ | ||
547 | for ((i) = (k)*GRU_CBR_AU_SIZE; \ | 543 | for ((i) = (k)*GRU_CBR_AU_SIZE; \ |
548 | (i) < ((k) + 1) * GRU_CBR_AU_SIZE; (i)++) | 544 | (i) < ((k) + 1) * GRU_CBR_AU_SIZE; (i)++) |
549 | 545 | ||
550 | /* Scan each DSR in a DSR bitmap. Note: multiple DSRs in an allocation unit */ | 546 | /* Scan each DSR in a DSR bitmap. Note: multiple DSRs in an allocation unit */ |
551 | #define for_each_dsr_in_allocation_map(i, map, k) \ | 547 | #define for_each_dsr_in_allocation_map(i, map, k) \ |
552 | for ((k) = find_first_bit((const unsigned long *)map, GRU_DSR_AU);\ | 548 | for_each_set_bit((k), (const unsigned long *)(map), GRU_DSR_AU) \ |
553 | (k) < GRU_DSR_AU; \ | ||
554 | (k) = find_next_bit((const unsigned long *)map, \ | ||
555 | GRU_DSR_AU, (k) + 1)) \ | ||
556 | for ((i) = (k) * GRU_DSR_AU_CL; \ | 549 | for ((i) = (k) * GRU_DSR_AU_CL; \ |
557 | (i) < ((k) + 1) * GRU_DSR_AU_CL; (i)++) | 550 | (i) < ((k) + 1) * GRU_DSR_AU_CL; (i)++) |
558 | 551 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f4b97d3c3d0f..3168ebd616b2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1089,6 +1089,7 @@ void mmc_rescan(struct work_struct *work) | |||
1089 | mmc_claim_host(host); | 1089 | mmc_claim_host(host); |
1090 | 1090 | ||
1091 | mmc_power_up(host); | 1091 | mmc_power_up(host); |
1092 | sdio_reset(host); | ||
1092 | mmc_go_idle(host); | 1093 | mmc_go_idle(host); |
1093 | 1094 | ||
1094 | mmc_send_if_cond(host, host->ocr_avail); | 1095 | mmc_send_if_cond(host, host->ocr_avail); |
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index 4eb7825fd1a7..dea36d9c22e6 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c | |||
@@ -67,13 +67,13 @@ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
67 | return err; | 67 | return err; |
68 | } | 68 | } |
69 | 69 | ||
70 | int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | 70 | static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn, |
71 | unsigned addr, u8 in, u8* out) | 71 | unsigned addr, u8 in, u8 *out) |
72 | { | 72 | { |
73 | struct mmc_command cmd; | 73 | struct mmc_command cmd; |
74 | int err; | 74 | int err; |
75 | 75 | ||
76 | BUG_ON(!card); | 76 | BUG_ON(!host); |
77 | BUG_ON(fn > 7); | 77 | BUG_ON(fn > 7); |
78 | 78 | ||
79 | /* sanity check */ | 79 | /* sanity check */ |
@@ -90,11 +90,11 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | |||
90 | cmd.arg |= in; | 90 | cmd.arg |= in; |
91 | cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; | 91 | cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; |
92 | 92 | ||
93 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | 93 | err = mmc_wait_for_cmd(host, &cmd, 0); |
94 | if (err) | 94 | if (err) |
95 | return err; | 95 | return err; |
96 | 96 | ||
97 | if (mmc_host_is_spi(card->host)) { | 97 | if (mmc_host_is_spi(host)) { |
98 | /* host driver already reported errors */ | 98 | /* host driver already reported errors */ |
99 | } else { | 99 | } else { |
100 | if (cmd.resp[0] & R5_ERROR) | 100 | if (cmd.resp[0] & R5_ERROR) |
@@ -106,7 +106,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | |||
106 | } | 106 | } |
107 | 107 | ||
108 | if (out) { | 108 | if (out) { |
109 | if (mmc_host_is_spi(card->host)) | 109 | if (mmc_host_is_spi(host)) |
110 | *out = (cmd.resp[0] >> 8) & 0xFF; | 110 | *out = (cmd.resp[0] >> 8) & 0xFF; |
111 | else | 111 | else |
112 | *out = cmd.resp[0] & 0xFF; | 112 | *out = cmd.resp[0] & 0xFF; |
@@ -115,6 +115,13 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | |||
115 | return 0; | 115 | return 0; |
116 | } | 116 | } |
117 | 117 | ||
118 | int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | ||
119 | unsigned addr, u8 in, u8 *out) | ||
120 | { | ||
121 | BUG_ON(!card); | ||
122 | return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out); | ||
123 | } | ||
124 | |||
118 | int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, | 125 | int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, |
119 | unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) | 126 | unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) |
120 | { | 127 | { |
@@ -182,3 +189,20 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, | |||
182 | return 0; | 189 | return 0; |
183 | } | 190 | } |
184 | 191 | ||
192 | int sdio_reset(struct mmc_host *host) | ||
193 | { | ||
194 | int ret; | ||
195 | u8 abort; | ||
196 | |||
197 | /* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */ | ||
198 | |||
199 | ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort); | ||
200 | if (ret) | ||
201 | abort = 0x08; | ||
202 | else | ||
203 | abort |= 0x08; | ||
204 | |||
205 | ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h index e2e74b0d17d8..12a4d3ab174c 100644 --- a/drivers/mmc/core/sdio_ops.h +++ b/drivers/mmc/core/sdio_ops.h | |||
@@ -17,6 +17,7 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | |||
17 | unsigned addr, u8 in, u8* out); | 17 | unsigned addr, u8 in, u8* out); |
18 | int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, | 18 | int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, |
19 | unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); | 19 | unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz); |
20 | int sdio_reset(struct mmc_host *host); | ||
20 | 21 | ||
21 | #endif | 22 | #endif |
22 | 23 | ||
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 60a2b69e54f5..faa7b76a8899 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -708,7 +708,7 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
708 | mmc->max_blk_size = 2048; | 708 | mmc->max_blk_size = 2048; |
709 | mmc->max_blk_count = 65535; | 709 | mmc->max_blk_count = 65535; |
710 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 710 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
711 | mmc->max_seg_size = mmc->max_seg_size; | 711 | mmc->max_seg_size = mmc->max_req_size; |
712 | 712 | ||
713 | host = mmc_priv(mmc); | 713 | host = mmc_priv(mmc); |
714 | host->base = ioremap(r->start, resource_size(r)); | 714 | host->base = ioremap(r->start, resource_size(r)); |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index bc45ef9af17d..fad40aa6f099 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -89,7 +89,8 @@ DEFINE_MUTEX(ubi_devices_mutex); | |||
89 | static DEFINE_SPINLOCK(ubi_devices_lock); | 89 | static DEFINE_SPINLOCK(ubi_devices_lock); |
90 | 90 | ||
91 | /* "Show" method for files in '/<sysfs>/class/ubi/' */ | 91 | /* "Show" method for files in '/<sysfs>/class/ubi/' */ |
92 | static ssize_t ubi_version_show(struct class *class, char *buf) | 92 | static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr, |
93 | char *buf) | ||
93 | { | 94 | { |
94 | return sprintf(buf, "%d\n", UBI_VERSION); | 95 | return sprintf(buf, "%d\n", UBI_VERSION); |
95 | } | 96 | } |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 5acd557cea9b..b8bec086daa1 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -51,7 +51,9 @@ | |||
51 | * "show" function for the bond_masters attribute. | 51 | * "show" function for the bond_masters attribute. |
52 | * The class parameter is ignored. | 52 | * The class parameter is ignored. |
53 | */ | 53 | */ |
54 | static ssize_t bonding_show_bonds(struct class *cls, char *buf) | 54 | static ssize_t bonding_show_bonds(struct class *cls, |
55 | struct class_attribute *attr, | ||
56 | char *buf) | ||
55 | { | 57 | { |
56 | struct net *net = current->nsproxy->net_ns; | 58 | struct net *net = current->nsproxy->net_ns; |
57 | struct bond_net *bn = net_generic(net, bond_net_id); | 59 | struct bond_net *bn = net_generic(net, bond_net_id); |
@@ -98,6 +100,7 @@ static struct net_device *bond_get_by_name(struct net *net, const char *ifname) | |||
98 | */ | 100 | */ |
99 | 101 | ||
100 | static ssize_t bonding_store_bonds(struct class *cls, | 102 | static ssize_t bonding_store_bonds(struct class *cls, |
103 | struct class_attribute *attr, | ||
101 | const char *buffer, size_t count) | 104 | const char *buffer, size_t count) |
102 | { | 105 | { |
103 | struct net *net = current->nsproxy->net_ns; | 106 | struct net *net = current->nsproxy->net_ns; |
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index f2b937966950..0bc777bac9b4 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
@@ -1577,7 +1577,7 @@ static struct attribute * veth_pool_attrs[] = { | |||
1577 | NULL, | 1577 | NULL, |
1578 | }; | 1578 | }; |
1579 | 1579 | ||
1580 | static struct sysfs_ops veth_pool_ops = { | 1580 | static const struct sysfs_ops veth_pool_ops = { |
1581 | .show = veth_pool_show, | 1581 | .show = veth_pool_show, |
1582 | .store = veth_pool_store, | 1582 | .store = veth_pool_store, |
1583 | }; | 1583 | }; |
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 966de5d69521..e6e972d9b7ca 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c | |||
@@ -384,7 +384,7 @@ static struct attribute *veth_cnx_default_attrs[] = { | |||
384 | NULL | 384 | NULL |
385 | }; | 385 | }; |
386 | 386 | ||
387 | static struct sysfs_ops veth_cnx_sysfs_ops = { | 387 | static const struct sysfs_ops veth_cnx_sysfs_ops = { |
388 | .show = veth_cnx_attribute_show | 388 | .show = veth_cnx_attribute_show |
389 | }; | 389 | }; |
390 | 390 | ||
@@ -441,7 +441,7 @@ static struct attribute *veth_port_default_attrs[] = { | |||
441 | NULL | 441 | NULL |
442 | }; | 442 | }; |
443 | 443 | ||
444 | static struct sysfs_ops veth_port_sysfs_ops = { | 444 | static const struct sysfs_ops veth_port_sysfs_ops = { |
445 | .show = veth_port_attribute_show | 445 | .show = veth_port_attribute_show |
446 | }; | 446 | }; |
447 | 447 | ||
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 0bc5d474b168..1062b8ffe244 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c | |||
@@ -481,7 +481,7 @@ pdcspath_attr_store(struct kobject *kobj, struct attribute *attr, | |||
481 | return ret; | 481 | return ret; |
482 | } | 482 | } |
483 | 483 | ||
484 | static struct sysfs_ops pdcspath_attr_ops = { | 484 | static const struct sysfs_ops pdcspath_attr_ops = { |
485 | .show = pdcspath_attr_show, | 485 | .show = pdcspath_attr_show, |
486 | .store = pdcspath_attr_store, | 486 | .store = pdcspath_attr_store, |
487 | }; | 487 | }; |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 712250f5874a..26301cb25e7f 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -288,9 +288,9 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), | |||
288 | next = dev->bus_list.next; | 288 | next = dev->bus_list.next; |
289 | 289 | ||
290 | /* Run device routines with the device locked */ | 290 | /* Run device routines with the device locked */ |
291 | down(&dev->dev.sem); | 291 | device_lock(&dev->dev); |
292 | retval = cb(dev, userdata); | 292 | retval = cb(dev, userdata); |
293 | up(&dev->dev.sem); | 293 | device_unlock(&dev->dev); |
294 | if (retval) | 294 | if (retval) |
295 | break; | 295 | break; |
296 | } | 296 | } |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 6151389fd903..0a894efd4b9b 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -73,7 +73,7 @@ static void legacy_release(struct kobject *kobj) | |||
73 | } | 73 | } |
74 | 74 | ||
75 | static struct kobj_type legacy_ktype = { | 75 | static struct kobj_type legacy_ktype = { |
76 | .sysfs_ops = &(struct sysfs_ops){ | 76 | .sysfs_ops = &(const struct sysfs_ops){ |
77 | .store = legacy_store, .show = legacy_show | 77 | .store = legacy_store, .show = legacy_show |
78 | }, | 78 | }, |
79 | .release = &legacy_release, | 79 | .release = &legacy_release, |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 807224ec8351..de296452c957 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -642,6 +642,7 @@ void pci_create_legacy_files(struct pci_bus *b) | |||
642 | if (!b->legacy_io) | 642 | if (!b->legacy_io) |
643 | goto kzalloc_err; | 643 | goto kzalloc_err; |
644 | 644 | ||
645 | sysfs_bin_attr_init(b->legacy_io); | ||
645 | b->legacy_io->attr.name = "legacy_io"; | 646 | b->legacy_io->attr.name = "legacy_io"; |
646 | b->legacy_io->size = 0xffff; | 647 | b->legacy_io->size = 0xffff; |
647 | b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; | 648 | b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; |
@@ -654,6 +655,7 @@ void pci_create_legacy_files(struct pci_bus *b) | |||
654 | goto legacy_io_err; | 655 | goto legacy_io_err; |
655 | 656 | ||
656 | /* Allocated above after the legacy_io struct */ | 657 | /* Allocated above after the legacy_io struct */ |
658 | sysfs_bin_attr_init(b->legacy_mem); | ||
657 | b->legacy_mem = b->legacy_io + 1; | 659 | b->legacy_mem = b->legacy_io + 1; |
658 | b->legacy_mem->attr.name = "legacy_mem"; | 660 | b->legacy_mem->attr.name = "legacy_mem"; |
659 | b->legacy_mem->size = 1024*1024; | 661 | b->legacy_mem->size = 1024*1024; |
@@ -800,6 +802,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) | |||
800 | if (res_attr) { | 802 | if (res_attr) { |
801 | char *res_attr_name = (char *)(res_attr + 1); | 803 | char *res_attr_name = (char *)(res_attr + 1); |
802 | 804 | ||
805 | sysfs_bin_attr_init(res_attr); | ||
803 | if (write_combine) { | 806 | if (write_combine) { |
804 | pdev->res_attr_wc[num] = res_attr; | 807 | pdev->res_attr_wc[num] = res_attr; |
805 | sprintf(res_attr_name, "resource%d_wc", num); | 808 | sprintf(res_attr_name, "resource%d_wc", num); |
@@ -972,6 +975,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev) | |||
972 | if (!attr) | 975 | if (!attr) |
973 | return -ENOMEM; | 976 | return -ENOMEM; |
974 | 977 | ||
978 | sysfs_bin_attr_init(attr); | ||
975 | attr->size = dev->vpd->len; | 979 | attr->size = dev->vpd->len; |
976 | attr->attr.name = "vpd"; | 980 | attr->attr.name = "vpd"; |
977 | attr->attr.mode = S_IRUSR | S_IWUSR; | 981 | attr->attr.mode = S_IRUSR | S_IWUSR; |
@@ -1038,6 +1042,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
1038 | retval = -ENOMEM; | 1042 | retval = -ENOMEM; |
1039 | goto err_resource_files; | 1043 | goto err_resource_files; |
1040 | } | 1044 | } |
1045 | sysfs_bin_attr_init(attr); | ||
1041 | attr->size = rom_size; | 1046 | attr->size = rom_size; |
1042 | attr->attr.name = "rom"; | 1047 | attr->attr.name = "rom"; |
1043 | attr->attr.mode = S_IRUSR; | 1048 | attr->attr.mode = S_IRUSR; |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 77b493b3d97b..cb1dd5f4988c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1583,8 +1583,10 @@ void pci_pm_init(struct pci_dev *dev) | |||
1583 | int pm; | 1583 | int pm; |
1584 | u16 pmc; | 1584 | u16 pmc; |
1585 | 1585 | ||
1586 | pm_runtime_forbid(&dev->dev); | ||
1586 | device_enable_async_suspend(&dev->dev); | 1587 | device_enable_async_suspend(&dev->dev); |
1587 | dev->wakeup_prepared = false; | 1588 | dev->wakeup_prepared = false; |
1589 | |||
1588 | dev->pm_cap = 0; | 1590 | dev->pm_cap = 0; |
1589 | 1591 | ||
1590 | /* find PCI PM capability in list */ | 1592 | /* find PCI PM capability in list */ |
@@ -2296,35 +2298,6 @@ void pci_msi_off(struct pci_dev *dev) | |||
2296 | } | 2298 | } |
2297 | } | 2299 | } |
2298 | 2300 | ||
2299 | #ifndef HAVE_ARCH_PCI_SET_DMA_MASK | ||
2300 | /* | ||
2301 | * These can be overridden by arch-specific implementations | ||
2302 | */ | ||
2303 | int | ||
2304 | pci_set_dma_mask(struct pci_dev *dev, u64 mask) | ||
2305 | { | ||
2306 | if (!pci_dma_supported(dev, mask)) | ||
2307 | return -EIO; | ||
2308 | |||
2309 | dev->dma_mask = mask; | ||
2310 | dev_dbg(&dev->dev, "using %dbit DMA mask\n", fls64(mask)); | ||
2311 | |||
2312 | return 0; | ||
2313 | } | ||
2314 | |||
2315 | int | ||
2316 | pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | ||
2317 | { | ||
2318 | if (!pci_dma_supported(dev, mask)) | ||
2319 | return -EIO; | ||
2320 | |||
2321 | dev->dev.coherent_dma_mask = mask; | ||
2322 | dev_dbg(&dev->dev, "using %dbit consistent DMA mask\n", fls64(mask)); | ||
2323 | |||
2324 | return 0; | ||
2325 | } | ||
2326 | #endif | ||
2327 | |||
2328 | #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE | 2301 | #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE |
2329 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) | 2302 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) |
2330 | { | 2303 | { |
@@ -2486,7 +2459,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) | |||
2486 | if (!probe) { | 2459 | if (!probe) { |
2487 | pci_block_user_cfg_access(dev); | 2460 | pci_block_user_cfg_access(dev); |
2488 | /* block PM suspend, driver probe, etc. */ | 2461 | /* block PM suspend, driver probe, etc. */ |
2489 | down(&dev->dev.sem); | 2462 | device_lock(&dev->dev); |
2490 | } | 2463 | } |
2491 | 2464 | ||
2492 | rc = pci_dev_specific_reset(dev, probe); | 2465 | rc = pci_dev_specific_reset(dev, probe); |
@@ -2508,7 +2481,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) | |||
2508 | rc = pci_parent_bus_reset(dev, probe); | 2481 | rc = pci_parent_bus_reset(dev, probe); |
2509 | done: | 2482 | done: |
2510 | if (!probe) { | 2483 | if (!probe) { |
2511 | up(&dev->dev.sem); | 2484 | device_unlock(&dev->dev); |
2512 | pci_unblock_user_cfg_access(dev); | 2485 | pci_unblock_user_cfg_access(dev); |
2513 | } | 2486 | } |
2514 | 2487 | ||
@@ -3066,8 +3039,6 @@ EXPORT_SYMBOL(pci_set_mwi); | |||
3066 | EXPORT_SYMBOL(pci_try_set_mwi); | 3039 | EXPORT_SYMBOL(pci_try_set_mwi); |
3067 | EXPORT_SYMBOL(pci_clear_mwi); | 3040 | EXPORT_SYMBOL(pci_clear_mwi); |
3068 | EXPORT_SYMBOL_GPL(pci_intx); | 3041 | EXPORT_SYMBOL_GPL(pci_intx); |
3069 | EXPORT_SYMBOL(pci_set_dma_mask); | ||
3070 | EXPORT_SYMBOL(pci_set_consistent_dma_mask); | ||
3071 | EXPORT_SYMBOL(pci_assign_resource); | 3042 | EXPORT_SYMBOL(pci_assign_resource); |
3072 | EXPORT_SYMBOL(pci_find_parent_resource); | 3043 | EXPORT_SYMBOL(pci_find_parent_resource); |
3073 | EXPORT_SYMBOL(pci_select_bars); | 3044 | EXPORT_SYMBOL(pci_select_bars); |
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 49c9e6c9779a..f75a44d37fbe 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
@@ -29,7 +29,7 @@ static ssize_t pci_slot_attr_store(struct kobject *kobj, | |||
29 | return attribute->store ? attribute->store(slot, buf, len) : -EIO; | 29 | return attribute->store ? attribute->store(slot, buf, len) : -EIO; |
30 | } | 30 | } |
31 | 31 | ||
32 | static struct sysfs_ops pci_slot_sysfs_ops = { | 32 | static const struct sysfs_ops pci_slot_sysfs_ops = { |
33 | .show = pci_slot_attr_show, | 33 | .show = pci_slot_attr_show, |
34 | .store = pci_slot_attr_store, | 34 | .store = pci_slot_attr_store, |
35 | }; | 35 | }; |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0f98be4450b7..ad93ebd7b2a2 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -971,9 +971,9 @@ static int runtime_suspend(struct device *dev) | |||
971 | { | 971 | { |
972 | int rc; | 972 | int rc; |
973 | 973 | ||
974 | down(&dev->sem); | 974 | device_lock(dev); |
975 | rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND); | 975 | rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND); |
976 | up(&dev->sem); | 976 | device_unlock(dev); |
977 | return rc; | 977 | return rc; |
978 | } | 978 | } |
979 | 979 | ||
@@ -981,9 +981,9 @@ static int runtime_resume(struct device *dev) | |||
981 | { | 981 | { |
982 | int rc; | 982 | int rc; |
983 | 983 | ||
984 | down(&dev->sem); | 984 | device_lock(dev); |
985 | rc = pcmcia_dev_resume(dev); | 985 | rc = pcmcia_dev_resume(dev); |
986 | up(&dev->sem); | 986 | device_unlock(dev); |
987 | return rc; | 987 | return rc; |
988 | } | 988 | } |
989 | 989 | ||
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index cd2ee6fce1b4..e631dbeafd79 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -150,6 +150,7 @@ config MSI_LAPTOP | |||
150 | tristate "MSI Laptop Extras" | 150 | tristate "MSI Laptop Extras" |
151 | depends on ACPI | 151 | depends on ACPI |
152 | depends on BACKLIGHT_CLASS_DEVICE | 152 | depends on BACKLIGHT_CLASS_DEVICE |
153 | depends on RFKILL | ||
153 | ---help--- | 154 | ---help--- |
154 | This is a driver for laptops built by MSI (MICRO-STAR | 155 | This is a driver for laptops built by MSI (MICRO-STAR |
155 | INTERNATIONAL): | 156 | INTERNATIONAL): |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 3aa57da8b43b..7ccf33c08967 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -57,7 +57,7 @@ enum hp_wmi_radio { | |||
57 | HPWMI_WWAN = 2, | 57 | HPWMI_WWAN = 2, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static int __init hp_wmi_bios_setup(struct platform_device *device); | 60 | static int __devinit hp_wmi_bios_setup(struct platform_device *device); |
61 | static int __exit hp_wmi_bios_remove(struct platform_device *device); | 61 | static int __exit hp_wmi_bios_remove(struct platform_device *device); |
62 | static int hp_wmi_resume_handler(struct device *device); | 62 | static int hp_wmi_resume_handler(struct device *device); |
63 | 63 | ||
@@ -447,7 +447,7 @@ static void cleanup_sysfs(struct platform_device *device) | |||
447 | device_remove_file(&device->dev, &dev_attr_tablet); | 447 | device_remove_file(&device->dev, &dev_attr_tablet); |
448 | } | 448 | } |
449 | 449 | ||
450 | static int __init hp_wmi_bios_setup(struct platform_device *device) | 450 | static int __devinit hp_wmi_bios_setup(struct platform_device *device) |
451 | { | 451 | { |
452 | int err; | 452 | int err; |
453 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); | 453 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); |
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 759763d18e4c..c2b05da4289a 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/dmi.h> | 58 | #include <linux/dmi.h> |
59 | #include <linux/backlight.h> | 59 | #include <linux/backlight.h> |
60 | #include <linux/platform_device.h> | 60 | #include <linux/platform_device.h> |
61 | #include <linux/rfkill.h> | ||
61 | 62 | ||
62 | #define MSI_DRIVER_VERSION "0.5" | 63 | #define MSI_DRIVER_VERSION "0.5" |
63 | 64 | ||
@@ -66,6 +67,20 @@ | |||
66 | #define MSI_EC_COMMAND_WIRELESS 0x10 | 67 | #define MSI_EC_COMMAND_WIRELESS 0x10 |
67 | #define MSI_EC_COMMAND_LCD_LEVEL 0x11 | 68 | #define MSI_EC_COMMAND_LCD_LEVEL 0x11 |
68 | 69 | ||
70 | #define MSI_STANDARD_EC_COMMAND_ADDRESS 0x2e | ||
71 | #define MSI_STANDARD_EC_BLUETOOTH_MASK (1 << 0) | ||
72 | #define MSI_STANDARD_EC_WEBCAM_MASK (1 << 1) | ||
73 | #define MSI_STANDARD_EC_WLAN_MASK (1 << 3) | ||
74 | #define MSI_STANDARD_EC_3G_MASK (1 << 4) | ||
75 | |||
76 | /* For set SCM load flag to disable BIOS fn key */ | ||
77 | #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d | ||
78 | #define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) | ||
79 | |||
80 | static int msi_laptop_resume(struct platform_device *device); | ||
81 | |||
82 | #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f | ||
83 | |||
69 | static int force; | 84 | static int force; |
70 | module_param(force, bool, 0); | 85 | module_param(force, bool, 0); |
71 | MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); | 86 | MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); |
@@ -74,6 +89,23 @@ static int auto_brightness; | |||
74 | module_param(auto_brightness, int, 0); | 89 | module_param(auto_brightness, int, 0); |
75 | MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); | 90 | MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); |
76 | 91 | ||
92 | static bool old_ec_model; | ||
93 | static int wlan_s, bluetooth_s, threeg_s; | ||
94 | static int threeg_exists; | ||
95 | |||
96 | /* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G, | ||
97 | * those netbook will load the SCM (windows app) to disable the original | ||
98 | * Wlan/Bluetooth control by BIOS when user press fn key, then control | ||
99 | * Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user | ||
100 | * cann't on/off 3G module on those 3G netbook. | ||
101 | * On Linux, msi-laptop driver will do the same thing to disable the | ||
102 | * original BIOS control, then might need use HAL or other userland | ||
103 | * application to do the software control that simulate with SCM. | ||
104 | * e.g. MSI N034 netbook | ||
105 | */ | ||
106 | static bool load_scm_model; | ||
107 | static struct rfkill *rfk_wlan, *rfk_bluetooth, *rfk_threeg; | ||
108 | |||
77 | /* Hardware access */ | 109 | /* Hardware access */ |
78 | 110 | ||
79 | static int set_lcd_level(int level) | 111 | static int set_lcd_level(int level) |
@@ -130,6 +162,35 @@ static int set_auto_brightness(int enable) | |||
130 | return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1); | 162 | return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1); |
131 | } | 163 | } |
132 | 164 | ||
165 | static ssize_t set_device_state(const char *buf, size_t count, u8 mask) | ||
166 | { | ||
167 | int status; | ||
168 | u8 wdata = 0, rdata; | ||
169 | int result; | ||
170 | |||
171 | if (sscanf(buf, "%i", &status) != 1 || (status < 0 || status > 1)) | ||
172 | return -EINVAL; | ||
173 | |||
174 | /* read current device state */ | ||
175 | result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); | ||
176 | if (result < 0) | ||
177 | return -EINVAL; | ||
178 | |||
179 | if (!!(rdata & mask) != status) { | ||
180 | /* reverse device bit */ | ||
181 | if (rdata & mask) | ||
182 | wdata = rdata & ~mask; | ||
183 | else | ||
184 | wdata = rdata | mask; | ||
185 | |||
186 | result = ec_write(MSI_STANDARD_EC_COMMAND_ADDRESS, wdata); | ||
187 | if (result < 0) | ||
188 | return -EINVAL; | ||
189 | } | ||
190 | |||
191 | return count; | ||
192 | } | ||
193 | |||
133 | static int get_wireless_state(int *wlan, int *bluetooth) | 194 | static int get_wireless_state(int *wlan, int *bluetooth) |
134 | { | 195 | { |
135 | u8 wdata = 0, rdata; | 196 | u8 wdata = 0, rdata; |
@@ -148,6 +209,38 @@ static int get_wireless_state(int *wlan, int *bluetooth) | |||
148 | return 0; | 209 | return 0; |
149 | } | 210 | } |
150 | 211 | ||
212 | static int get_wireless_state_ec_standard(void) | ||
213 | { | ||
214 | u8 rdata; | ||
215 | int result; | ||
216 | |||
217 | result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); | ||
218 | if (result < 0) | ||
219 | return -1; | ||
220 | |||
221 | wlan_s = !!(rdata & MSI_STANDARD_EC_WLAN_MASK); | ||
222 | |||
223 | bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK); | ||
224 | |||
225 | threeg_s = !!(rdata & MSI_STANDARD_EC_3G_MASK); | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int get_threeg_exists(void) | ||
231 | { | ||
232 | u8 rdata; | ||
233 | int result; | ||
234 | |||
235 | result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata); | ||
236 | if (result < 0) | ||
237 | return -1; | ||
238 | |||
239 | threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
151 | /* Backlight device stuff */ | 244 | /* Backlight device stuff */ |
152 | 245 | ||
153 | static int bl_get_brightness(struct backlight_device *b) | 246 | static int bl_get_brightness(struct backlight_device *b) |
@@ -176,26 +269,71 @@ static ssize_t show_wlan(struct device *dev, | |||
176 | 269 | ||
177 | int ret, enabled; | 270 | int ret, enabled; |
178 | 271 | ||
179 | ret = get_wireless_state(&enabled, NULL); | 272 | if (old_ec_model) { |
273 | ret = get_wireless_state(&enabled, NULL); | ||
274 | } else { | ||
275 | ret = get_wireless_state_ec_standard(); | ||
276 | enabled = wlan_s; | ||
277 | } | ||
180 | if (ret < 0) | 278 | if (ret < 0) |
181 | return ret; | 279 | return ret; |
182 | 280 | ||
183 | return sprintf(buf, "%i\n", enabled); | 281 | return sprintf(buf, "%i\n", enabled); |
184 | } | 282 | } |
185 | 283 | ||
284 | static ssize_t store_wlan(struct device *dev, | ||
285 | struct device_attribute *attr, const char *buf, size_t count) | ||
286 | { | ||
287 | return set_device_state(buf, count, MSI_STANDARD_EC_WLAN_MASK); | ||
288 | } | ||
289 | |||
186 | static ssize_t show_bluetooth(struct device *dev, | 290 | static ssize_t show_bluetooth(struct device *dev, |
187 | struct device_attribute *attr, char *buf) | 291 | struct device_attribute *attr, char *buf) |
188 | { | 292 | { |
189 | 293 | ||
190 | int ret, enabled; | 294 | int ret, enabled; |
191 | 295 | ||
192 | ret = get_wireless_state(NULL, &enabled); | 296 | if (old_ec_model) { |
297 | ret = get_wireless_state(NULL, &enabled); | ||
298 | } else { | ||
299 | ret = get_wireless_state_ec_standard(); | ||
300 | enabled = bluetooth_s; | ||
301 | } | ||
193 | if (ret < 0) | 302 | if (ret < 0) |
194 | return ret; | 303 | return ret; |
195 | 304 | ||
196 | return sprintf(buf, "%i\n", enabled); | 305 | return sprintf(buf, "%i\n", enabled); |
197 | } | 306 | } |
198 | 307 | ||
308 | static ssize_t store_bluetooth(struct device *dev, | ||
309 | struct device_attribute *attr, const char *buf, size_t count) | ||
310 | { | ||
311 | return set_device_state(buf, count, MSI_STANDARD_EC_BLUETOOTH_MASK); | ||
312 | } | ||
313 | |||
314 | static ssize_t show_threeg(struct device *dev, | ||
315 | struct device_attribute *attr, char *buf) | ||
316 | { | ||
317 | |||
318 | int ret; | ||
319 | |||
320 | /* old msi ec not support 3G */ | ||
321 | if (old_ec_model) | ||
322 | return -1; | ||
323 | |||
324 | ret = get_wireless_state_ec_standard(); | ||
325 | if (ret < 0) | ||
326 | return ret; | ||
327 | |||
328 | return sprintf(buf, "%i\n", threeg_s); | ||
329 | } | ||
330 | |||
331 | static ssize_t store_threeg(struct device *dev, | ||
332 | struct device_attribute *attr, const char *buf, size_t count) | ||
333 | { | ||
334 | return set_device_state(buf, count, MSI_STANDARD_EC_3G_MASK); | ||
335 | } | ||
336 | |||
199 | static ssize_t show_lcd_level(struct device *dev, | 337 | static ssize_t show_lcd_level(struct device *dev, |
200 | struct device_attribute *attr, char *buf) | 338 | struct device_attribute *attr, char *buf) |
201 | { | 339 | { |
@@ -258,6 +396,7 @@ static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); | |||
258 | static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness); | 396 | static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness); |
259 | static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); | 397 | static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); |
260 | static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); | 398 | static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); |
399 | static DEVICE_ATTR(threeg, 0444, show_threeg, NULL); | ||
261 | 400 | ||
262 | static struct attribute *msipf_attributes[] = { | 401 | static struct attribute *msipf_attributes[] = { |
263 | &dev_attr_lcd_level.attr, | 402 | &dev_attr_lcd_level.attr, |
@@ -275,7 +414,8 @@ static struct platform_driver msipf_driver = { | |||
275 | .driver = { | 414 | .driver = { |
276 | .name = "msi-laptop-pf", | 415 | .name = "msi-laptop-pf", |
277 | .owner = THIS_MODULE, | 416 | .owner = THIS_MODULE, |
278 | } | 417 | }, |
418 | .resume = msi_laptop_resume, | ||
279 | }; | 419 | }; |
280 | 420 | ||
281 | static struct platform_device *msipf_device; | 421 | static struct platform_device *msipf_device; |
@@ -332,6 +472,192 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { | |||
332 | { } | 472 | { } |
333 | }; | 473 | }; |
334 | 474 | ||
475 | static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = { | ||
476 | { | ||
477 | .ident = "MSI N034", | ||
478 | .matches = { | ||
479 | DMI_MATCH(DMI_SYS_VENDOR, | ||
480 | "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
481 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-N034"), | ||
482 | DMI_MATCH(DMI_CHASSIS_VENDOR, | ||
483 | "MICRO-STAR INTERNATIONAL CO., LTD") | ||
484 | }, | ||
485 | .callback = dmi_check_cb | ||
486 | }, | ||
487 | { } | ||
488 | }; | ||
489 | |||
490 | static int rfkill_bluetooth_set(void *data, bool blocked) | ||
491 | { | ||
492 | /* Do something with blocked...*/ | ||
493 | /* | ||
494 | * blocked == false is on | ||
495 | * blocked == true is off | ||
496 | */ | ||
497 | if (blocked) | ||
498 | set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); | ||
499 | else | ||
500 | set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK); | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | static int rfkill_wlan_set(void *data, bool blocked) | ||
506 | { | ||
507 | if (blocked) | ||
508 | set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK); | ||
509 | else | ||
510 | set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK); | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static int rfkill_threeg_set(void *data, bool blocked) | ||
516 | { | ||
517 | if (blocked) | ||
518 | set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK); | ||
519 | else | ||
520 | set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static struct rfkill_ops rfkill_bluetooth_ops = { | ||
526 | .set_block = rfkill_bluetooth_set | ||
527 | }; | ||
528 | |||
529 | static struct rfkill_ops rfkill_wlan_ops = { | ||
530 | .set_block = rfkill_wlan_set | ||
531 | }; | ||
532 | |||
533 | static struct rfkill_ops rfkill_threeg_ops = { | ||
534 | .set_block = rfkill_threeg_set | ||
535 | }; | ||
536 | |||
537 | static void rfkill_cleanup(void) | ||
538 | { | ||
539 | if (rfk_bluetooth) { | ||
540 | rfkill_unregister(rfk_bluetooth); | ||
541 | rfkill_destroy(rfk_bluetooth); | ||
542 | } | ||
543 | |||
544 | if (rfk_threeg) { | ||
545 | rfkill_unregister(rfk_threeg); | ||
546 | rfkill_destroy(rfk_threeg); | ||
547 | } | ||
548 | |||
549 | if (rfk_wlan) { | ||
550 | rfkill_unregister(rfk_wlan); | ||
551 | rfkill_destroy(rfk_wlan); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | static int rfkill_init(struct platform_device *sdev) | ||
556 | { | ||
557 | /* add rfkill */ | ||
558 | int retval; | ||
559 | |||
560 | rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev, | ||
561 | RFKILL_TYPE_BLUETOOTH, | ||
562 | &rfkill_bluetooth_ops, NULL); | ||
563 | if (!rfk_bluetooth) { | ||
564 | retval = -ENOMEM; | ||
565 | goto err_bluetooth; | ||
566 | } | ||
567 | retval = rfkill_register(rfk_bluetooth); | ||
568 | if (retval) | ||
569 | goto err_bluetooth; | ||
570 | |||
571 | rfk_wlan = rfkill_alloc("msi-wlan", &sdev->dev, RFKILL_TYPE_WLAN, | ||
572 | &rfkill_wlan_ops, NULL); | ||
573 | if (!rfk_wlan) { | ||
574 | retval = -ENOMEM; | ||
575 | goto err_wlan; | ||
576 | } | ||
577 | retval = rfkill_register(rfk_wlan); | ||
578 | if (retval) | ||
579 | goto err_wlan; | ||
580 | |||
581 | if (threeg_exists) { | ||
582 | rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev, | ||
583 | RFKILL_TYPE_WWAN, &rfkill_threeg_ops, NULL); | ||
584 | if (!rfk_threeg) { | ||
585 | retval = -ENOMEM; | ||
586 | goto err_threeg; | ||
587 | } | ||
588 | retval = rfkill_register(rfk_threeg); | ||
589 | if (retval) | ||
590 | goto err_threeg; | ||
591 | } | ||
592 | |||
593 | return 0; | ||
594 | |||
595 | err_threeg: | ||
596 | rfkill_destroy(rfk_threeg); | ||
597 | if (rfk_wlan) | ||
598 | rfkill_unregister(rfk_wlan); | ||
599 | err_wlan: | ||
600 | rfkill_destroy(rfk_wlan); | ||
601 | if (rfk_bluetooth) | ||
602 | rfkill_unregister(rfk_bluetooth); | ||
603 | err_bluetooth: | ||
604 | rfkill_destroy(rfk_bluetooth); | ||
605 | |||
606 | return retval; | ||
607 | } | ||
608 | |||
609 | static int msi_laptop_resume(struct platform_device *device) | ||
610 | { | ||
611 | u8 data; | ||
612 | int result; | ||
613 | |||
614 | if (!load_scm_model) | ||
615 | return 0; | ||
616 | |||
617 | /* set load SCM to disable hardware control by fn key */ | ||
618 | result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data); | ||
619 | if (result < 0) | ||
620 | return result; | ||
621 | |||
622 | result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, | ||
623 | data | MSI_STANDARD_EC_SCM_LOAD_MASK); | ||
624 | if (result < 0) | ||
625 | return result; | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int load_scm_model_init(struct platform_device *sdev) | ||
631 | { | ||
632 | u8 data; | ||
633 | int result; | ||
634 | |||
635 | /* allow userland write sysfs file */ | ||
636 | dev_attr_bluetooth.store = store_bluetooth; | ||
637 | dev_attr_wlan.store = store_wlan; | ||
638 | dev_attr_threeg.store = store_threeg; | ||
639 | dev_attr_bluetooth.attr.mode |= S_IWUSR; | ||
640 | dev_attr_wlan.attr.mode |= S_IWUSR; | ||
641 | dev_attr_threeg.attr.mode |= S_IWUSR; | ||
642 | |||
643 | /* disable hardware control by fn key */ | ||
644 | result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data); | ||
645 | if (result < 0) | ||
646 | return result; | ||
647 | |||
648 | result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, | ||
649 | data | MSI_STANDARD_EC_SCM_LOAD_MASK); | ||
650 | if (result < 0) | ||
651 | return result; | ||
652 | |||
653 | /* initial rfkill */ | ||
654 | result = rfkill_init(sdev); | ||
655 | if (result < 0) | ||
656 | return result; | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
335 | static int __init msi_init(void) | 661 | static int __init msi_init(void) |
336 | { | 662 | { |
337 | int ret; | 663 | int ret; |
@@ -339,8 +665,14 @@ static int __init msi_init(void) | |||
339 | if (acpi_disabled) | 665 | if (acpi_disabled) |
340 | return -ENODEV; | 666 | return -ENODEV; |
341 | 667 | ||
342 | if (!force && !dmi_check_system(msi_dmi_table)) | 668 | if (force || dmi_check_system(msi_dmi_table)) |
343 | return -ENODEV; | 669 | old_ec_model = 1; |
670 | |||
671 | if (!old_ec_model) | ||
672 | get_threeg_exists(); | ||
673 | |||
674 | if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table)) | ||
675 | load_scm_model = 1; | ||
344 | 676 | ||
345 | if (auto_brightness < 0 || auto_brightness > 2) | 677 | if (auto_brightness < 0 || auto_brightness > 2) |
346 | return -EINVAL; | 678 | return -EINVAL; |
@@ -374,10 +706,23 @@ static int __init msi_init(void) | |||
374 | if (ret) | 706 | if (ret) |
375 | goto fail_platform_device1; | 707 | goto fail_platform_device1; |
376 | 708 | ||
709 | if (load_scm_model && (load_scm_model_init(msipf_device) < 0)) { | ||
710 | ret = -EINVAL; | ||
711 | goto fail_platform_device1; | ||
712 | } | ||
713 | |||
377 | ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); | 714 | ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); |
378 | if (ret) | 715 | if (ret) |
379 | goto fail_platform_device2; | 716 | goto fail_platform_device2; |
380 | 717 | ||
718 | if (!old_ec_model) { | ||
719 | if (threeg_exists) | ||
720 | ret = device_create_file(&msipf_device->dev, | ||
721 | &dev_attr_threeg); | ||
722 | if (ret) | ||
723 | goto fail_platform_device2; | ||
724 | } | ||
725 | |||
381 | /* Disable automatic brightness control by default because | 726 | /* Disable automatic brightness control by default because |
382 | * this module was probably loaded to do brightness control in | 727 | * this module was probably loaded to do brightness control in |
383 | * software. */ | 728 | * software. */ |
@@ -412,10 +757,14 @@ static void __exit msi_cleanup(void) | |||
412 | { | 757 | { |
413 | 758 | ||
414 | sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); | 759 | sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); |
760 | if (!old_ec_model && threeg_exists) | ||
761 | device_remove_file(&msipf_device->dev, &dev_attr_threeg); | ||
415 | platform_device_unregister(msipf_device); | 762 | platform_device_unregister(msipf_device); |
416 | platform_driver_unregister(&msipf_driver); | 763 | platform_driver_unregister(&msipf_driver); |
417 | backlight_device_unregister(msibl_device); | 764 | backlight_device_unregister(msibl_device); |
418 | 765 | ||
766 | rfkill_cleanup(); | ||
767 | |||
419 | /* Enable automatic brightness control again */ | 768 | /* Enable automatic brightness control again */ |
420 | if (auto_brightness != 2) | 769 | if (auto_brightness != 2) |
421 | set_auto_brightness(1); | 770 | set_auto_brightness(1); |
@@ -435,3 +784,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARIN | |||
435 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); | 784 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); |
436 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); | 785 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); |
437 | MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); | 786 | MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); |
787 | MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*"); | ||
diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig index cc2eb8edb514..1afe4e03440f 100644 --- a/drivers/pps/Kconfig +++ b/drivers/pps/Kconfig | |||
@@ -30,4 +30,6 @@ config PPS_DEBUG | |||
30 | messages to the system log. Select this if you are having a | 30 | messages to the system log. Select this if you are having a |
31 | problem with PPS support and want to see more of what is going on. | 31 | problem with PPS support and want to see more of what is going on. |
32 | 32 | ||
33 | source drivers/pps/clients/Kconfig | ||
34 | |||
33 | endmenu | 35 | endmenu |
diff --git a/drivers/pps/Makefile b/drivers/pps/Makefile index 19ea582f431d..98960ddd3188 100644 --- a/drivers/pps/Makefile +++ b/drivers/pps/Makefile | |||
@@ -4,5 +4,6 @@ | |||
4 | 4 | ||
5 | pps_core-y := pps.o kapi.o sysfs.o | 5 | pps_core-y := pps.o kapi.o sysfs.o |
6 | obj-$(CONFIG_PPS) := pps_core.o | 6 | obj-$(CONFIG_PPS) := pps_core.o |
7 | obj-y += clients/ | ||
7 | 8 | ||
8 | ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG | 9 | ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG |
diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig new file mode 100644 index 000000000000..4e801bd7254f --- /dev/null +++ b/drivers/pps/clients/Kconfig | |||
@@ -0,0 +1,25 @@ | |||
1 | # | ||
2 | # PPS clients configuration | ||
3 | # | ||
4 | |||
5 | if PPS | ||
6 | |||
7 | comment "PPS clients support" | ||
8 | |||
9 | config PPS_CLIENT_KTIMER | ||
10 | tristate "Kernel timer client (Testing client, use for debug)" | ||
11 | help | ||
12 | If you say yes here you get support for a PPS debugging client | ||
13 | which uses a kernel timer to generate the PPS signal. | ||
14 | |||
15 | This driver can also be built as a module. If so, the module | ||
16 | will be called pps-ktimer. | ||
17 | |||
18 | config PPS_CLIENT_LDISC | ||
19 | tristate "PPS line discipline" | ||
20 | depends on PPS | ||
21 | help | ||
22 | If you say yes here you get support for a PPS source connected | ||
23 | with the CD (Carrier Detect) pin of your serial port. | ||
24 | |||
25 | endif | ||
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile new file mode 100644 index 000000000000..812c9b19b430 --- /dev/null +++ b/drivers/pps/clients/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for PPS clients. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o | ||
6 | obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o | ||
7 | |||
8 | ifeq ($(CONFIG_PPS_DEBUG),y) | ||
9 | EXTRA_CFLAGS += -DDEBUG | ||
10 | endif | ||
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c new file mode 100644 index 000000000000..e7ef5b8186d0 --- /dev/null +++ b/drivers/pps/clients/pps-ktimer.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * pps-ktimer.c -- kernel timer test client | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2005-2006 Rodolfo Giometti <giometti@linux.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/time.h> | ||
27 | #include <linux/timer.h> | ||
28 | #include <linux/pps_kernel.h> | ||
29 | |||
30 | /* | ||
31 | * Global variables | ||
32 | */ | ||
33 | |||
34 | static int source; | ||
35 | static struct timer_list ktimer; | ||
36 | |||
37 | /* | ||
38 | * The kernel timer | ||
39 | */ | ||
40 | |||
41 | static void pps_ktimer_event(unsigned long ptr) | ||
42 | { | ||
43 | struct timespec __ts; | ||
44 | struct pps_ktime ts; | ||
45 | |||
46 | /* First of all we get the time stamp... */ | ||
47 | getnstimeofday(&__ts); | ||
48 | |||
49 | pr_info("PPS event at %lu\n", jiffies); | ||
50 | |||
51 | /* ... and translate it to PPS time data struct */ | ||
52 | ts.sec = __ts.tv_sec; | ||
53 | ts.nsec = __ts.tv_nsec; | ||
54 | |||
55 | pps_event(source, &ts, PPS_CAPTUREASSERT, NULL); | ||
56 | |||
57 | mod_timer(&ktimer, jiffies + HZ); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * The echo function | ||
62 | */ | ||
63 | |||
64 | static void pps_ktimer_echo(int source, int event, void *data) | ||
65 | { | ||
66 | pr_info("echo %s %s for source %d\n", | ||
67 | event & PPS_CAPTUREASSERT ? "assert" : "", | ||
68 | event & PPS_CAPTURECLEAR ? "clear" : "", | ||
69 | source); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * The PPS info struct | ||
74 | */ | ||
75 | |||
76 | static struct pps_source_info pps_ktimer_info = { | ||
77 | .name = "ktimer", | ||
78 | .path = "", | ||
79 | .mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | | ||
80 | PPS_ECHOASSERT | | ||
81 | PPS_CANWAIT | PPS_TSFMT_TSPEC, | ||
82 | .echo = pps_ktimer_echo, | ||
83 | .owner = THIS_MODULE, | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * Module staff | ||
88 | */ | ||
89 | |||
90 | static void __exit pps_ktimer_exit(void) | ||
91 | { | ||
92 | del_timer_sync(&ktimer); | ||
93 | pps_unregister_source(source); | ||
94 | |||
95 | pr_info("ktimer PPS source unregistered\n"); | ||
96 | } | ||
97 | |||
98 | static int __init pps_ktimer_init(void) | ||
99 | { | ||
100 | int ret; | ||
101 | |||
102 | ret = pps_register_source(&pps_ktimer_info, | ||
103 | PPS_CAPTUREASSERT | PPS_OFFSETASSERT); | ||
104 | if (ret < 0) { | ||
105 | printk(KERN_ERR "cannot register ktimer source\n"); | ||
106 | return ret; | ||
107 | } | ||
108 | source = ret; | ||
109 | |||
110 | setup_timer(&ktimer, pps_ktimer_event, 0); | ||
111 | mod_timer(&ktimer, jiffies + HZ); | ||
112 | |||
113 | pr_info("ktimer PPS source registered at %d\n", source); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | module_init(pps_ktimer_init); | ||
119 | module_exit(pps_ktimer_exit); | ||
120 | |||
121 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
122 | MODULE_DESCRIPTION("dummy PPS source by using a kernel timer (just for debug)"); | ||
123 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c new file mode 100644 index 000000000000..8e1932d29fd4 --- /dev/null +++ b/drivers/pps/clients/pps-ldisc.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * pps-ldisc.c -- PPS line discipline | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/serial_core.h> | ||
24 | #include <linux/tty.h> | ||
25 | #include <linux/pps_kernel.h> | ||
26 | |||
27 | #define PPS_TTY_MAGIC 0x0001 | ||
28 | |||
29 | static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, | ||
30 | struct timespec *ts) | ||
31 | { | ||
32 | int id = (long)tty->disc_data; | ||
33 | struct timespec __ts; | ||
34 | struct pps_ktime pps_ts; | ||
35 | |||
36 | /* First of all we get the time stamp... */ | ||
37 | getnstimeofday(&__ts); | ||
38 | |||
39 | /* Does caller give us a timestamp? */ | ||
40 | if (ts) { /* Yes. Let's use it! */ | ||
41 | pps_ts.sec = ts->tv_sec; | ||
42 | pps_ts.nsec = ts->tv_nsec; | ||
43 | } else { /* No. Do it ourself! */ | ||
44 | pps_ts.sec = __ts.tv_sec; | ||
45 | pps_ts.nsec = __ts.tv_nsec; | ||
46 | } | ||
47 | |||
48 | /* Now do the PPS event report */ | ||
49 | pps_event(id, &pps_ts, status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR, | ||
50 | NULL); | ||
51 | |||
52 | pr_debug("PPS %s at %lu on source #%d\n", | ||
53 | status ? "assert" : "clear", jiffies, id); | ||
54 | } | ||
55 | |||
56 | static int (*alias_n_tty_open)(struct tty_struct *tty); | ||
57 | |||
58 | static int pps_tty_open(struct tty_struct *tty) | ||
59 | { | ||
60 | struct pps_source_info info; | ||
61 | struct tty_driver *drv = tty->driver; | ||
62 | int index = tty->index + drv->name_base; | ||
63 | int ret; | ||
64 | |||
65 | info.owner = THIS_MODULE; | ||
66 | info.dev = NULL; | ||
67 | snprintf(info.name, PPS_MAX_NAME_LEN, "%s%d", drv->driver_name, index); | ||
68 | snprintf(info.path, PPS_MAX_NAME_LEN, "/dev/%s%d", drv->name, index); | ||
69 | info.mode = PPS_CAPTUREBOTH | \ | ||
70 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ | ||
71 | PPS_CANWAIT | PPS_TSFMT_TSPEC; | ||
72 | |||
73 | ret = pps_register_source(&info, PPS_CAPTUREBOTH | \ | ||
74 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR); | ||
75 | if (ret < 0) { | ||
76 | pr_err("cannot register PPS source \"%s\"\n", info.path); | ||
77 | return ret; | ||
78 | } | ||
79 | tty->disc_data = (void *)(long)ret; | ||
80 | |||
81 | /* Should open N_TTY ldisc too */ | ||
82 | ret = alias_n_tty_open(tty); | ||
83 | if (ret < 0) | ||
84 | pps_unregister_source((long)tty->disc_data); | ||
85 | |||
86 | pr_info("PPS source #%d \"%s\" added\n", ret, info.path); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static void (*alias_n_tty_close)(struct tty_struct *tty); | ||
92 | |||
93 | static void pps_tty_close(struct tty_struct *tty) | ||
94 | { | ||
95 | int id = (long)tty->disc_data; | ||
96 | |||
97 | pps_unregister_source(id); | ||
98 | alias_n_tty_close(tty); | ||
99 | |||
100 | pr_info("PPS source #%d removed\n", id); | ||
101 | } | ||
102 | |||
103 | static struct tty_ldisc_ops pps_ldisc_ops; | ||
104 | |||
105 | /* | ||
106 | * Module stuff | ||
107 | */ | ||
108 | |||
109 | static int __init pps_tty_init(void) | ||
110 | { | ||
111 | int err; | ||
112 | |||
113 | /* Inherit the N_TTY's ops */ | ||
114 | n_tty_inherit_ops(&pps_ldisc_ops); | ||
115 | |||
116 | /* Save N_TTY's open()/close() methods */ | ||
117 | alias_n_tty_open = pps_ldisc_ops.open; | ||
118 | alias_n_tty_close = pps_ldisc_ops.close; | ||
119 | |||
120 | /* Init PPS_TTY data */ | ||
121 | pps_ldisc_ops.owner = THIS_MODULE; | ||
122 | pps_ldisc_ops.magic = PPS_TTY_MAGIC; | ||
123 | pps_ldisc_ops.name = "pps_tty"; | ||
124 | pps_ldisc_ops.dcd_change = pps_tty_dcd_change; | ||
125 | pps_ldisc_ops.open = pps_tty_open; | ||
126 | pps_ldisc_ops.close = pps_tty_close; | ||
127 | |||
128 | err = tty_register_ldisc(N_PPS, &pps_ldisc_ops); | ||
129 | if (err) | ||
130 | pr_err("can't register PPS line discipline\n"); | ||
131 | else | ||
132 | pr_info("PPS line discipline registered\n"); | ||
133 | |||
134 | return err; | ||
135 | } | ||
136 | |||
137 | static void __exit pps_tty_cleanup(void) | ||
138 | { | ||
139 | int err; | ||
140 | |||
141 | err = tty_unregister_ldisc(N_PPS); | ||
142 | if (err) | ||
143 | pr_err("can't unregister PPS line discipline\n"); | ||
144 | else | ||
145 | pr_info("PPS line discipline removed\n"); | ||
146 | } | ||
147 | |||
148 | module_init(pps_tty_init); | ||
149 | module_exit(pps_tty_cleanup); | ||
150 | |||
151 | MODULE_ALIAS_LDISC(N_PPS); | ||
152 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
153 | MODULE_DESCRIPTION("PPS TTY device driver"); | ||
154 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 33c0e98243ee..bc90b091f195 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c | |||
@@ -22,48 +22,57 @@ | |||
22 | * the best guess is to add 0.5s. | 22 | * the best guess is to add 0.5s. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | int rtc_hctosys_ret = -ENODEV; | ||
26 | |||
25 | static int __init rtc_hctosys(void) | 27 | static int __init rtc_hctosys(void) |
26 | { | 28 | { |
27 | int err; | 29 | int err = -ENODEV; |
28 | struct rtc_time tm; | 30 | struct rtc_time tm; |
31 | struct timespec tv = { | ||
32 | .tv_nsec = NSEC_PER_SEC >> 1, | ||
33 | }; | ||
29 | struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | 34 | struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); |
30 | 35 | ||
31 | if (rtc == NULL) { | 36 | if (rtc == NULL) { |
32 | printk("%s: unable to open rtc device (%s)\n", | 37 | pr_err("%s: unable to open rtc device (%s)\n", |
33 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); | 38 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); |
34 | return -ENODEV; | 39 | goto err_open; |
35 | } | 40 | } |
36 | 41 | ||
37 | err = rtc_read_time(rtc, &tm); | 42 | err = rtc_read_time(rtc, &tm); |
38 | if (err == 0) { | 43 | if (err) { |
39 | err = rtc_valid_tm(&tm); | 44 | dev_err(rtc->dev.parent, |
40 | if (err == 0) { | 45 | "hctosys: unable to read the hardware clock\n"); |
41 | struct timespec tv; | 46 | goto err_read; |
42 | 47 | ||
43 | tv.tv_nsec = NSEC_PER_SEC >> 1; | 48 | } |
44 | 49 | ||
45 | rtc_tm_to_time(&tm, &tv.tv_sec); | 50 | err = rtc_valid_tm(&tm); |
51 | if (err) { | ||
52 | dev_err(rtc->dev.parent, | ||
53 | "hctosys: invalid date/time\n"); | ||
54 | goto err_invalid; | ||
55 | } | ||
46 | 56 | ||
47 | do_settimeofday(&tv); | 57 | rtc_tm_to_time(&tm, &tv.tv_sec); |
48 | 58 | ||
49 | dev_info(rtc->dev.parent, | 59 | do_settimeofday(&tv); |
50 | "setting system clock to " | ||
51 | "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", | ||
52 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
53 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
54 | (unsigned int) tv.tv_sec); | ||
55 | } | ||
56 | else | ||
57 | dev_err(rtc->dev.parent, | ||
58 | "hctosys: invalid date/time\n"); | ||
59 | } | ||
60 | else | ||
61 | dev_err(rtc->dev.parent, | ||
62 | "hctosys: unable to read the hardware clock\n"); | ||
63 | 60 | ||
61 | dev_info(rtc->dev.parent, | ||
62 | "setting system clock to " | ||
63 | "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", | ||
64 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
65 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
66 | (unsigned int) tv.tv_sec); | ||
67 | |||
68 | err_invalid: | ||
69 | err_read: | ||
64 | rtc_class_close(rtc); | 70 | rtc_class_close(rtc); |
65 | 71 | ||
66 | return 0; | 72 | err_open: |
73 | rtc_hctosys_ret = err; | ||
74 | |||
75 | return err; | ||
67 | } | 76 | } |
68 | 77 | ||
69 | late_initcall(rtc_hctosys); | 78 | late_initcall(rtc_hctosys); |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 7dd23a6fc825..380083ca572f 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
@@ -107,8 +107,9 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, | |||
107 | char *buf) | 107 | char *buf) |
108 | { | 108 | { |
109 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE | 109 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE |
110 | if (strcmp(dev_name(&to_rtc_device(dev)->dev), | 110 | if (rtc_hctosys_ret == 0 && |
111 | CONFIG_RTC_HCTOSYS_DEVICE) == 0) | 111 | strcmp(dev_name(&to_rtc_device(dev)->dev), |
112 | CONFIG_RTC_HCTOSYS_DEVICE) == 0) | ||
112 | return sprintf(buf, "1\n"); | 113 | return sprintf(buf, "1\n"); |
113 | else | 114 | else |
114 | #endif | 115 | #endif |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4951aa82e9f5..bbea90baf98f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/ebcdic.h> | 26 | #include <asm/ebcdic.h> |
27 | #include <asm/idals.h> | 27 | #include <asm/idals.h> |
28 | #include <asm/itcw.h> | 28 | #include <asm/itcw.h> |
29 | #include <asm/diag.h> | ||
29 | 30 | ||
30 | /* This is ugly... */ | 31 | /* This is ugly... */ |
31 | #define PRINTK_HEADER "dasd:" | 32 | #define PRINTK_HEADER "dasd:" |
@@ -2212,6 +2213,13 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) | |||
2212 | goto out; | 2213 | goto out; |
2213 | } | 2214 | } |
2214 | 2215 | ||
2216 | if ((mode & FMODE_WRITE) && | ||
2217 | (test_bit(DASD_FLAG_DEVICE_RO, &base->flags) || | ||
2218 | (base->features & DASD_FEATURE_READONLY))) { | ||
2219 | rc = -EROFS; | ||
2220 | goto out; | ||
2221 | } | ||
2222 | |||
2215 | return 0; | 2223 | return 0; |
2216 | 2224 | ||
2217 | out: | 2225 | out: |
@@ -2289,6 +2297,34 @@ dasd_exit(void) | |||
2289 | * SECTION: common functions for ccw_driver use | 2297 | * SECTION: common functions for ccw_driver use |
2290 | */ | 2298 | */ |
2291 | 2299 | ||
2300 | /* | ||
2301 | * Is the device read-only? | ||
2302 | * Note that this function does not report the setting of the | ||
2303 | * readonly device attribute, but how it is configured in z/VM. | ||
2304 | */ | ||
2305 | int dasd_device_is_ro(struct dasd_device *device) | ||
2306 | { | ||
2307 | struct ccw_dev_id dev_id; | ||
2308 | struct diag210 diag_data; | ||
2309 | int rc; | ||
2310 | |||
2311 | if (!MACHINE_IS_VM) | ||
2312 | return 0; | ||
2313 | ccw_device_get_id(device->cdev, &dev_id); | ||
2314 | memset(&diag_data, 0, sizeof(diag_data)); | ||
2315 | diag_data.vrdcdvno = dev_id.devno; | ||
2316 | diag_data.vrdclen = sizeof(diag_data); | ||
2317 | rc = diag210(&diag_data); | ||
2318 | if (rc == 0 || rc == 2) { | ||
2319 | return diag_data.vrdcvfla & 0x80; | ||
2320 | } else { | ||
2321 | DBF_EVENT(DBF_WARNING, "diag210 failed for dev=%04x with rc=%d", | ||
2322 | dev_id.devno, rc); | ||
2323 | return 0; | ||
2324 | } | ||
2325 | } | ||
2326 | EXPORT_SYMBOL_GPL(dasd_device_is_ro); | ||
2327 | |||
2292 | static void dasd_generic_auto_online(void *data, async_cookie_t cookie) | 2328 | static void dasd_generic_auto_online(void *data, async_cookie_t cookie) |
2293 | { | 2329 | { |
2294 | struct ccw_device *cdev = data; | 2330 | struct ccw_device *cdev = data; |
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 44796ba4eb9b..51224f76b980 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -1045,6 +1045,10 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) | |||
1045 | 1045 | ||
1046 | erp->retries = 5; | 1046 | erp->retries = 5; |
1047 | 1047 | ||
1048 | } else if (sense[1] & SNS1_WRITE_INHIBITED) { | ||
1049 | dev_err(&device->cdev->dev, "An I/O request was rejected" | ||
1050 | " because writing is inhibited\n"); | ||
1051 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | ||
1048 | } else { | 1052 | } else { |
1049 | /* fatal error - set status to FAILED | 1053 | /* fatal error - set status to FAILED |
1050 | internal error 09 - Command Reject */ | 1054 | internal error 09 - Command Reject */ |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index d49766f3b940..8e23919c8704 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -742,6 +742,7 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, | |||
742 | const char *buf, size_t count) | 742 | const char *buf, size_t count) |
743 | { | 743 | { |
744 | struct dasd_devmap *devmap; | 744 | struct dasd_devmap *devmap; |
745 | struct dasd_device *device; | ||
745 | int val; | 746 | int val; |
746 | char *endp; | 747 | char *endp; |
747 | 748 | ||
@@ -758,12 +759,14 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr, | |||
758 | devmap->features |= DASD_FEATURE_READONLY; | 759 | devmap->features |= DASD_FEATURE_READONLY; |
759 | else | 760 | else |
760 | devmap->features &= ~DASD_FEATURE_READONLY; | 761 | devmap->features &= ~DASD_FEATURE_READONLY; |
761 | if (devmap->device) | 762 | device = devmap->device; |
762 | devmap->device->features = devmap->features; | 763 | if (device) { |
763 | if (devmap->device && devmap->device->block | 764 | device->features = devmap->features; |
764 | && devmap->device->block->gdp) | 765 | val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags); |
765 | set_disk_ro(devmap->device->block->gdp, val); | 766 | } |
766 | spin_unlock(&dasd_devmap_lock); | 767 | spin_unlock(&dasd_devmap_lock); |
768 | if (device && device->block && device->block->gdp) | ||
769 | set_disk_ro(device->block->gdp, val); | ||
767 | return count; | 770 | return count; |
768 | } | 771 | } |
769 | 772 | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 6e14863f5c70..687f323cdc38 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -145,12 +145,10 @@ dasd_diag_erp(struct dasd_device *device) | |||
145 | mdsk_term_io(device); | 145 | mdsk_term_io(device); |
146 | rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); | 146 | rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); |
147 | if (rc == 4) { | 147 | if (rc == 4) { |
148 | if (!(device->features & DASD_FEATURE_READONLY)) { | 148 | if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags))) |
149 | pr_warning("%s: The access mode of a DIAG device " | 149 | pr_warning("%s: The access mode of a DIAG device " |
150 | "changed to read-only\n", | 150 | "changed to read-only\n", |
151 | dev_name(&device->cdev->dev)); | 151 | dev_name(&device->cdev->dev)); |
152 | device->features |= DASD_FEATURE_READONLY; | ||
153 | } | ||
154 | rc = 0; | 152 | rc = 0; |
155 | } | 153 | } |
156 | if (rc) | 154 | if (rc) |
@@ -449,7 +447,7 @@ dasd_diag_check_device(struct dasd_device *device) | |||
449 | rc = -EIO; | 447 | rc = -EIO; |
450 | } else { | 448 | } else { |
451 | if (rc == 4) | 449 | if (rc == 4) |
452 | device->features |= DASD_FEATURE_READONLY; | 450 | set_bit(DASD_FLAG_DEVICE_RO, &device->flags); |
453 | pr_info("%s: New DASD with %ld byte/block, total size %ld " | 451 | pr_info("%s: New DASD with %ld byte/block, total size %ld " |
454 | "KB%s\n", dev_name(&device->cdev->dev), | 452 | "KB%s\n", dev_name(&device->cdev->dev), |
455 | (unsigned long) block->bp_block, | 453 | (unsigned long) block->bp_block, |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1cca21aafaba..01f4e7a34aa8 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1089,6 +1089,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1089 | struct dasd_eckd_private *private; | 1089 | struct dasd_eckd_private *private; |
1090 | struct dasd_block *block; | 1090 | struct dasd_block *block; |
1091 | int is_known, rc; | 1091 | int is_known, rc; |
1092 | int readonly; | ||
1092 | 1093 | ||
1093 | if (!ccw_device_is_pathgroup(device->cdev)) { | 1094 | if (!ccw_device_is_pathgroup(device->cdev)) { |
1094 | dev_warn(&device->cdev->dev, | 1095 | dev_warn(&device->cdev->dev, |
@@ -1182,15 +1183,20 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1182 | else | 1183 | else |
1183 | private->real_cyl = private->rdc_data.no_cyl; | 1184 | private->real_cyl = private->rdc_data.no_cyl; |
1184 | 1185 | ||
1186 | readonly = dasd_device_is_ro(device); | ||
1187 | if (readonly) | ||
1188 | set_bit(DASD_FLAG_DEVICE_RO, &device->flags); | ||
1189 | |||
1185 | dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) " | 1190 | dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) " |
1186 | "with %d cylinders, %d heads, %d sectors\n", | 1191 | "with %d cylinders, %d heads, %d sectors%s\n", |
1187 | private->rdc_data.dev_type, | 1192 | private->rdc_data.dev_type, |
1188 | private->rdc_data.dev_model, | 1193 | private->rdc_data.dev_model, |
1189 | private->rdc_data.cu_type, | 1194 | private->rdc_data.cu_type, |
1190 | private->rdc_data.cu_model.model, | 1195 | private->rdc_data.cu_model.model, |
1191 | private->real_cyl, | 1196 | private->real_cyl, |
1192 | private->rdc_data.trk_per_cyl, | 1197 | private->rdc_data.trk_per_cyl, |
1193 | private->rdc_data.sec_per_trk); | 1198 | private->rdc_data.sec_per_trk, |
1199 | readonly ? ", read-only device" : ""); | ||
1194 | return 0; | 1200 | return 0; |
1195 | 1201 | ||
1196 | out_err3: | 1202 | out_err3: |
@@ -2839,8 +2845,13 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) | |||
2839 | char *psf_data, *rssd_result; | 2845 | char *psf_data, *rssd_result; |
2840 | struct dasd_ccw_req *cqr; | 2846 | struct dasd_ccw_req *cqr; |
2841 | struct ccw1 *ccw; | 2847 | struct ccw1 *ccw; |
2848 | char psf0, psf1; | ||
2842 | int rc; | 2849 | int rc; |
2843 | 2850 | ||
2851 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) | ||
2852 | return -EACCES; | ||
2853 | psf0 = psf1 = 0; | ||
2854 | |||
2844 | /* Copy parms from caller */ | 2855 | /* Copy parms from caller */ |
2845 | rc = -EFAULT; | 2856 | rc = -EFAULT; |
2846 | if (copy_from_user(&usrparm, argp, sizeof(usrparm))) | 2857 | if (copy_from_user(&usrparm, argp, sizeof(usrparm))) |
@@ -2869,12 +2880,8 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) | |||
2869 | (void __user *)(unsigned long) usrparm.psf_data, | 2880 | (void __user *)(unsigned long) usrparm.psf_data, |
2870 | usrparm.psf_data_len)) | 2881 | usrparm.psf_data_len)) |
2871 | goto out_free; | 2882 | goto out_free; |
2872 | 2883 | psf0 = psf_data[0]; | |
2873 | /* sanity check on syscall header */ | 2884 | psf1 = psf_data[1]; |
2874 | if (psf_data[0] != 0x17 && psf_data[1] != 0xce) { | ||
2875 | rc = -EINVAL; | ||
2876 | goto out_free; | ||
2877 | } | ||
2878 | 2885 | ||
2879 | /* setup CCWs for PSF + RSSD */ | 2886 | /* setup CCWs for PSF + RSSD */ |
2880 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device); | 2887 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device); |
@@ -2925,7 +2932,9 @@ out_free: | |||
2925 | kfree(rssd_result); | 2932 | kfree(rssd_result); |
2926 | kfree(psf_data); | 2933 | kfree(psf_data); |
2927 | out: | 2934 | out: |
2928 | DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc); | 2935 | DBF_DEV_EVENT(DBF_WARNING, device, |
2936 | "Symmetrix ioctl (0x%02x 0x%02x): rc=%d", | ||
2937 | (int) psf0, (int) psf1, rc); | ||
2929 | return rc; | 2938 | return rc; |
2930 | } | 2939 | } |
2931 | 2940 | ||
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 0f152444ac77..37282b90eecc 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -124,6 +124,7 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
124 | struct dasd_fba_private *private; | 124 | struct dasd_fba_private *private; |
125 | struct ccw_device *cdev = device->cdev; | 125 | struct ccw_device *cdev = device->cdev; |
126 | int rc; | 126 | int rc; |
127 | int readonly; | ||
127 | 128 | ||
128 | private = (struct dasd_fba_private *) device->private; | 129 | private = (struct dasd_fba_private *) device->private; |
129 | if (!private) { | 130 | if (!private) { |
@@ -162,16 +163,21 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
162 | return rc; | 163 | return rc; |
163 | } | 164 | } |
164 | 165 | ||
166 | readonly = dasd_device_is_ro(device); | ||
167 | if (readonly) | ||
168 | set_bit(DASD_FLAG_DEVICE_RO, &device->flags); | ||
169 | |||
165 | dev_info(&device->cdev->dev, | 170 | dev_info(&device->cdev->dev, |
166 | "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB " | 171 | "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB " |
167 | "and %d B/blk\n", | 172 | "and %d B/blk%s\n", |
168 | cdev->id.dev_type, | 173 | cdev->id.dev_type, |
169 | cdev->id.dev_model, | 174 | cdev->id.dev_model, |
170 | cdev->id.cu_type, | 175 | cdev->id.cu_type, |
171 | cdev->id.cu_model, | 176 | cdev->id.cu_model, |
172 | ((private->rdc_data.blk_bdsa * | 177 | ((private->rdc_data.blk_bdsa * |
173 | (private->rdc_data.blk_size >> 9)) >> 11), | 178 | (private->rdc_data.blk_size >> 9)) >> 11), |
174 | private->rdc_data.blk_size); | 179 | private->rdc_data.blk_size, |
180 | readonly ? ", read-only device" : ""); | ||
175 | return 0; | 181 | return 0; |
176 | } | 182 | } |
177 | 183 | ||
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 94f92a1247f2..30a1ca3d08b7 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c | |||
@@ -70,7 +70,8 @@ int dasd_gendisk_alloc(struct dasd_block *block) | |||
70 | } | 70 | } |
71 | len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26)); | 71 | len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26)); |
72 | 72 | ||
73 | if (block->base->features & DASD_FEATURE_READONLY) | 73 | if (base->features & DASD_FEATURE_READONLY || |
74 | test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) | ||
74 | set_disk_ro(gdp, 1); | 75 | set_disk_ro(gdp, 1); |
75 | gdp->private_data = block; | 76 | gdp->private_data = block; |
76 | gdp->queue = block->request_queue; | 77 | gdp->queue = block->request_queue; |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index ed73ce550822..a91d4a97d4f2 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -436,6 +436,10 @@ struct dasd_block { | |||
436 | #define DASD_FLAG_OFFLINE 3 /* device is in offline processing */ | 436 | #define DASD_FLAG_OFFLINE 3 /* device is in offline processing */ |
437 | #define DASD_FLAG_EER_SNSS 4 /* A SNSS is required */ | 437 | #define DASD_FLAG_EER_SNSS 4 /* A SNSS is required */ |
438 | #define DASD_FLAG_EER_IN_USE 5 /* A SNSS request is running */ | 438 | #define DASD_FLAG_EER_IN_USE 5 /* A SNSS request is running */ |
439 | #define DASD_FLAG_DEVICE_RO 6 /* The device itself is read-only. Don't | ||
440 | * confuse this with the user specified | ||
441 | * read-only feature. | ||
442 | */ | ||
439 | 443 | ||
440 | void dasd_put_device_wake(struct dasd_device *); | 444 | void dasd_put_device_wake(struct dasd_device *); |
441 | 445 | ||
@@ -609,6 +613,9 @@ char *dasd_get_sense(struct irb *); | |||
609 | void dasd_device_set_stop_bits(struct dasd_device *, int); | 613 | void dasd_device_set_stop_bits(struct dasd_device *, int); |
610 | void dasd_device_remove_stop_bits(struct dasd_device *, int); | 614 | void dasd_device_remove_stop_bits(struct dasd_device *, int); |
611 | 615 | ||
616 | int dasd_device_is_ro(struct dasd_device *); | ||
617 | |||
618 | |||
612 | /* externals in dasd_devmap.c */ | 619 | /* externals in dasd_devmap.c */ |
613 | extern int dasd_max_devindex; | 620 | extern int dasd_max_devindex; |
614 | extern int dasd_probeonly; | 621 | extern int dasd_probeonly; |
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 7039d9cf0fb4..3479f8158a1b 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
@@ -199,7 +199,8 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) | |||
199 | if (!argp) | 199 | if (!argp) |
200 | return -EINVAL; | 200 | return -EINVAL; |
201 | 201 | ||
202 | if (block->base->features & DASD_FEATURE_READONLY) | 202 | if (block->base->features & DASD_FEATURE_READONLY || |
203 | test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags)) | ||
203 | return -EROFS; | 204 | return -EROFS; |
204 | if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) | 205 | if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) |
205 | return -EFAULT; | 206 | return -EFAULT; |
@@ -349,7 +350,8 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp) | |||
349 | return -EINVAL; | 350 | return -EINVAL; |
350 | if (get_user(intval, (int __user *)argp)) | 351 | if (get_user(intval, (int __user *)argp)) |
351 | return -EFAULT; | 352 | return -EFAULT; |
352 | 353 | if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags)) | |
354 | return -EROFS; | ||
353 | set_disk_ro(bdev->bd_disk, intval); | 355 | set_disk_ro(bdev->bd_disk, intval); |
354 | return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval); | 356 | return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval); |
355 | } | 357 | } |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index c6abb75c4615..6d229f3523a0 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -764,7 +764,7 @@ static void sch_create_and_recog_new_device(struct subchannel *sch) | |||
764 | static void io_subchannel_register(struct ccw_device *cdev) | 764 | static void io_subchannel_register(struct ccw_device *cdev) |
765 | { | 765 | { |
766 | struct subchannel *sch; | 766 | struct subchannel *sch; |
767 | int ret; | 767 | int ret, adjust_init_count = 1; |
768 | unsigned long flags; | 768 | unsigned long flags; |
769 | 769 | ||
770 | sch = to_subchannel(cdev->dev.parent); | 770 | sch = to_subchannel(cdev->dev.parent); |
@@ -793,6 +793,7 @@ static void io_subchannel_register(struct ccw_device *cdev) | |||
793 | cdev->private->dev_id.ssid, | 793 | cdev->private->dev_id.ssid, |
794 | cdev->private->dev_id.devno); | 794 | cdev->private->dev_id.devno); |
795 | } | 795 | } |
796 | adjust_init_count = 0; | ||
796 | goto out; | 797 | goto out; |
797 | } | 798 | } |
798 | /* | 799 | /* |
@@ -818,7 +819,7 @@ out: | |||
818 | cdev->private->flags.recog_done = 1; | 819 | cdev->private->flags.recog_done = 1; |
819 | wake_up(&cdev->private->wait_q); | 820 | wake_up(&cdev->private->wait_q); |
820 | out_err: | 821 | out_err: |
821 | if (atomic_dec_and_test(&ccw_device_init_count)) | 822 | if (adjust_init_count && atomic_dec_and_test(&ccw_device_init_count)) |
822 | wake_up(&ccw_device_init_wq); | 823 | wake_up(&ccw_device_init_wq); |
823 | } | 824 | } |
824 | 825 | ||
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index c94eb2a0fa2e..6ce83f56d537 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c | |||
@@ -33,7 +33,6 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data, | |||
33 | DBF_HEX(&init_data->input_handler, sizeof(void *)); | 33 | DBF_HEX(&init_data->input_handler, sizeof(void *)); |
34 | DBF_HEX(&init_data->output_handler, sizeof(void *)); | 34 | DBF_HEX(&init_data->output_handler, sizeof(void *)); |
35 | DBF_HEX(&init_data->int_parm, sizeof(long)); | 35 | DBF_HEX(&init_data->int_parm, sizeof(long)); |
36 | DBF_HEX(&init_data->flags, sizeof(long)); | ||
37 | DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *)); | 36 | DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *)); |
38 | DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *)); | 37 | DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *)); |
39 | DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); | 38 | DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr); |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 232ef047ba34..4f8f74311778 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -588,10 +588,11 @@ static void qdio_kick_handler(struct qdio_q *q) | |||
588 | if (q->is_input_q) { | 588 | if (q->is_input_q) { |
589 | qperf_inc(q, inbound_handler); | 589 | qperf_inc(q, inbound_handler); |
590 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); | 590 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); |
591 | } else | 591 | } else { |
592 | qperf_inc(q, outbound_handler); | 592 | qperf_inc(q, outbound_handler); |
593 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", | 593 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", |
594 | start, count); | 594 | start, count); |
595 | } | ||
595 | 596 | ||
596 | q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, | 597 | q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, |
597 | q->irq_ptr->int_parm); | 598 | q->irq_ptr->int_parm); |
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig index cb909a5b5047..977bb4d4ed15 100644 --- a/drivers/s390/net/Kconfig +++ b/drivers/s390/net/Kconfig | |||
@@ -43,6 +43,16 @@ config SMSGIUCV | |||
43 | Select this option if you want to be able to receive SMSG messages | 43 | Select this option if you want to be able to receive SMSG messages |
44 | from other VM guest systems. | 44 | from other VM guest systems. |
45 | 45 | ||
46 | config SMSGIUCV_EVENT | ||
47 | tristate "Deliver IUCV special messages as uevents (VM only)" | ||
48 | depends on SMSGIUCV | ||
49 | help | ||
50 | Select this option to deliver CP special messages (SMSGs) as | ||
51 | uevents. The driver handles only those special messages that | ||
52 | start with "APP". | ||
53 | |||
54 | To compile as a module, choose M. The module name is "smsgiucv_app". | ||
55 | |||
46 | config CLAW | 56 | config CLAW |
47 | tristate "CLAW device support" | 57 | tristate "CLAW device support" |
48 | depends on CCW && NETDEVICES | 58 | depends on CCW && NETDEVICES |
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 6cab5a62f99e..4dfe8c1092da 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile | |||
@@ -6,6 +6,7 @@ ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o | |||
6 | obj-$(CONFIG_CTCM) += ctcm.o fsm.o | 6 | obj-$(CONFIG_CTCM) += ctcm.o fsm.o |
7 | obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o | 7 | obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o |
8 | obj-$(CONFIG_SMSGIUCV) += smsgiucv.o | 8 | obj-$(CONFIG_SMSGIUCV) += smsgiucv.o |
9 | obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o | ||
9 | obj-$(CONFIG_LCS) += lcs.o | 10 | obj-$(CONFIG_LCS) += lcs.o |
10 | obj-$(CONFIG_CLAW) += claw.o | 11 | obj-$(CONFIG_CLAW) += claw.o |
11 | qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o | 12 | qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index fa8a519218ac..7d25bdd443cd 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -3805,9 +3805,6 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
3805 | init_data.input_handler = card->discipline.input_handler; | 3805 | init_data.input_handler = card->discipline.input_handler; |
3806 | init_data.output_handler = card->discipline.output_handler; | 3806 | init_data.output_handler = card->discipline.output_handler; |
3807 | init_data.int_parm = (unsigned long) card; | 3807 | init_data.int_parm = (unsigned long) card; |
3808 | init_data.flags = QDIO_INBOUND_0COPY_SBALS | | ||
3809 | QDIO_OUTBOUND_0COPY_SBALS | | ||
3810 | QDIO_USE_OUTBOUND_PCIS; | ||
3811 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 3808 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
3812 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; | 3809 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; |
3813 | 3810 | ||
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 67f2485d2372..ecef1edee701 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c | |||
@@ -31,9 +31,9 @@ | |||
31 | 31 | ||
32 | struct smsg_callback { | 32 | struct smsg_callback { |
33 | struct list_head list; | 33 | struct list_head list; |
34 | char *prefix; | 34 | const char *prefix; |
35 | int len; | 35 | int len; |
36 | void (*callback)(char *from, char *str); | 36 | void (*callback)(const char *from, char *str); |
37 | }; | 37 | }; |
38 | 38 | ||
39 | MODULE_AUTHOR | 39 | MODULE_AUTHOR |
@@ -100,8 +100,8 @@ static void smsg_message_pending(struct iucv_path *path, | |||
100 | kfree(buffer); | 100 | kfree(buffer); |
101 | } | 101 | } |
102 | 102 | ||
103 | int smsg_register_callback(char *prefix, | 103 | int smsg_register_callback(const char *prefix, |
104 | void (*callback)(char *from, char *str)) | 104 | void (*callback)(const char *from, char *str)) |
105 | { | 105 | { |
106 | struct smsg_callback *cb; | 106 | struct smsg_callback *cb; |
107 | 107 | ||
@@ -117,8 +117,9 @@ int smsg_register_callback(char *prefix, | |||
117 | return 0; | 117 | return 0; |
118 | } | 118 | } |
119 | 119 | ||
120 | void smsg_unregister_callback(char *prefix, | 120 | void smsg_unregister_callback(const char *prefix, |
121 | void (*callback)(char *from, char *str)) | 121 | void (*callback)(const char *from, |
122 | char *str)) | ||
122 | { | 123 | { |
123 | struct smsg_callback *cb, *tmp; | 124 | struct smsg_callback *cb, *tmp; |
124 | 125 | ||
@@ -176,7 +177,7 @@ static const struct dev_pm_ops smsg_pm_ops = { | |||
176 | 177 | ||
177 | static struct device_driver smsg_driver = { | 178 | static struct device_driver smsg_driver = { |
178 | .owner = THIS_MODULE, | 179 | .owner = THIS_MODULE, |
179 | .name = "SMSGIUCV", | 180 | .name = SMSGIUCV_DRV_NAME, |
180 | .bus = &iucv_bus, | 181 | .bus = &iucv_bus, |
181 | .pm = &smsg_pm_ops, | 182 | .pm = &smsg_pm_ops, |
182 | }; | 183 | }; |
diff --git a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h index 67f5d4f8378d..149a1151608d 100644 --- a/drivers/s390/net/smsgiucv.h +++ b/drivers/s390/net/smsgiucv.h | |||
@@ -5,6 +5,10 @@ | |||
5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | 5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) |
6 | */ | 6 | */ |
7 | 7 | ||
8 | int smsg_register_callback(char *, void (*)(char *, char *)); | 8 | #define SMSGIUCV_DRV_NAME "SMSGIUCV" |
9 | void smsg_unregister_callback(char *, void (*)(char *, char *)); | 9 | |
10 | int smsg_register_callback(const char *, | ||
11 | void (*)(const char *, char *)); | ||
12 | void smsg_unregister_callback(const char *, | ||
13 | void (*)(const char *, char *)); | ||
10 | 14 | ||
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c new file mode 100644 index 000000000000..91579dc6a2b0 --- /dev/null +++ b/drivers/s390/net/smsgiucv_app.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * Deliver z/VM CP special messages (SMSG) as uevents. | ||
3 | * | ||
4 | * The driver registers for z/VM CP special messages with the | ||
5 | * "APP" prefix. Incoming messages are delivered to user space | ||
6 | * as uevents. | ||
7 | * | ||
8 | * Copyright IBM Corp. 2010 | ||
9 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | ||
10 | * | ||
11 | */ | ||
12 | #define KMSG_COMPONENT "smsgiucv_app" | ||
13 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
14 | |||
15 | #include <linux/ctype.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/kobject.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | #include <net/iucv/iucv.h> | ||
24 | #include "smsgiucv.h" | ||
25 | |||
26 | /* prefix used for SMSG registration */ | ||
27 | #define SMSG_PREFIX "APP" | ||
28 | |||
29 | /* SMSG related uevent environment variables */ | ||
30 | #define ENV_SENDER_STR "SMSG_SENDER=" | ||
31 | #define ENV_SENDER_LEN (strlen(ENV_SENDER_STR) + 8 + 1) | ||
32 | #define ENV_PREFIX_STR "SMSG_ID=" | ||
33 | #define ENV_PREFIX_LEN (strlen(ENV_PREFIX_STR) + \ | ||
34 | strlen(SMSG_PREFIX) + 1) | ||
35 | #define ENV_TEXT_STR "SMSG_TEXT=" | ||
36 | #define ENV_TEXT_LEN(msg) (strlen(ENV_TEXT_STR) + strlen((msg)) + 1) | ||
37 | |||
38 | /* z/VM user ID which is permitted to send SMSGs | ||
39 | * If the value is undefined or empty (""), special messages are | ||
40 | * accepted from any z/VM user ID. */ | ||
41 | static char *sender; | ||
42 | module_param(sender, charp, 0400); | ||
43 | MODULE_PARM_DESC(sender, "z/VM user ID from which CP SMSGs are accepted"); | ||
44 | |||
45 | /* SMSG device representation */ | ||
46 | static struct device *smsg_app_dev; | ||
47 | |||
48 | /* list element for queuing received messages for delivery */ | ||
49 | struct smsg_app_event { | ||
50 | struct list_head list; | ||
51 | char *buf; | ||
52 | char *envp[4]; | ||
53 | }; | ||
54 | |||
55 | /* queue for outgoing uevents */ | ||
56 | static LIST_HEAD(smsg_event_queue); | ||
57 | static DEFINE_SPINLOCK(smsg_event_queue_lock); | ||
58 | |||
59 | static void smsg_app_event_free(struct smsg_app_event *ev) | ||
60 | { | ||
61 | kfree(ev->buf); | ||
62 | kfree(ev); | ||
63 | } | ||
64 | |||
65 | static struct smsg_app_event *smsg_app_event_alloc(const char *from, | ||
66 | const char *msg) | ||
67 | { | ||
68 | struct smsg_app_event *ev; | ||
69 | |||
70 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
71 | if (!ev) | ||
72 | return NULL; | ||
73 | |||
74 | ev->buf = kzalloc(ENV_SENDER_LEN + ENV_PREFIX_LEN + | ||
75 | ENV_TEXT_LEN(msg), GFP_ATOMIC); | ||
76 | if (!ev->buf) { | ||
77 | kfree(ev); | ||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | /* setting up environment pointers into buf */ | ||
82 | ev->envp[0] = ev->buf; | ||
83 | ev->envp[1] = ev->envp[0] + ENV_SENDER_LEN; | ||
84 | ev->envp[2] = ev->envp[1] + ENV_PREFIX_LEN; | ||
85 | ev->envp[3] = NULL; | ||
86 | |||
87 | /* setting up environment: sender, prefix name, and message text */ | ||
88 | snprintf(ev->envp[0], ENV_SENDER_LEN, ENV_SENDER_STR "%s", from); | ||
89 | snprintf(ev->envp[1], ENV_PREFIX_LEN, ENV_PREFIX_STR "%s", SMSG_PREFIX); | ||
90 | snprintf(ev->envp[2], ENV_TEXT_LEN(msg), ENV_TEXT_STR "%s", msg); | ||
91 | |||
92 | return ev; | ||
93 | } | ||
94 | |||
95 | static void smsg_event_work_fn(struct work_struct *work) | ||
96 | { | ||
97 | LIST_HEAD(event_queue); | ||
98 | struct smsg_app_event *p, *n; | ||
99 | struct device *dev; | ||
100 | |||
101 | dev = get_device(smsg_app_dev); | ||
102 | if (!dev) | ||
103 | return; | ||
104 | |||
105 | spin_lock_bh(&smsg_event_queue_lock); | ||
106 | list_splice_init(&smsg_event_queue, &event_queue); | ||
107 | spin_unlock_bh(&smsg_event_queue_lock); | ||
108 | |||
109 | list_for_each_entry_safe(p, n, &event_queue, list) { | ||
110 | list_del(&p->list); | ||
111 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, p->envp); | ||
112 | smsg_app_event_free(p); | ||
113 | } | ||
114 | |||
115 | put_device(dev); | ||
116 | } | ||
117 | static DECLARE_WORK(smsg_event_work, smsg_event_work_fn); | ||
118 | |||
119 | static void smsg_app_callback(const char *from, char *msg) | ||
120 | { | ||
121 | struct smsg_app_event *se; | ||
122 | |||
123 | /* check if the originating z/VM user ID matches | ||
124 | * the configured sender. */ | ||
125 | if (sender && strlen(sender) > 0 && strcmp(from, sender) != 0) | ||
126 | return; | ||
127 | |||
128 | /* get start of message text (skip prefix and leading blanks) */ | ||
129 | msg += strlen(SMSG_PREFIX); | ||
130 | while (*msg && isspace(*msg)) | ||
131 | msg++; | ||
132 | if (*msg == '\0') | ||
133 | return; | ||
134 | |||
135 | /* allocate event list element and its environment */ | ||
136 | se = smsg_app_event_alloc(from, msg); | ||
137 | if (!se) | ||
138 | return; | ||
139 | |||
140 | /* queue event and schedule work function */ | ||
141 | spin_lock(&smsg_event_queue_lock); | ||
142 | list_add_tail(&se->list, &smsg_event_queue); | ||
143 | spin_unlock(&smsg_event_queue_lock); | ||
144 | |||
145 | schedule_work(&smsg_event_work); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | static int __init smsgiucv_app_init(void) | ||
150 | { | ||
151 | struct device_driver *smsgiucv_drv; | ||
152 | int rc; | ||
153 | |||
154 | if (!MACHINE_IS_VM) | ||
155 | return -ENODEV; | ||
156 | |||
157 | smsg_app_dev = kzalloc(sizeof(*smsg_app_dev), GFP_KERNEL); | ||
158 | if (!smsg_app_dev) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | smsgiucv_drv = driver_find(SMSGIUCV_DRV_NAME, &iucv_bus); | ||
162 | if (!smsgiucv_drv) { | ||
163 | kfree(smsg_app_dev); | ||
164 | return -ENODEV; | ||
165 | } | ||
166 | |||
167 | rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); | ||
168 | if (rc) { | ||
169 | kfree(smsg_app_dev); | ||
170 | goto fail_put_driver; | ||
171 | } | ||
172 | smsg_app_dev->bus = &iucv_bus; | ||
173 | smsg_app_dev->parent = iucv_root; | ||
174 | smsg_app_dev->release = (void (*)(struct device *)) kfree; | ||
175 | smsg_app_dev->driver = smsgiucv_drv; | ||
176 | rc = device_register(smsg_app_dev); | ||
177 | if (rc) { | ||
178 | put_device(smsg_app_dev); | ||
179 | goto fail_put_driver; | ||
180 | } | ||
181 | |||
182 | /* register with the smsgiucv device driver */ | ||
183 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); | ||
184 | if (rc) { | ||
185 | device_unregister(smsg_app_dev); | ||
186 | goto fail_put_driver; | ||
187 | } | ||
188 | |||
189 | rc = 0; | ||
190 | fail_put_driver: | ||
191 | put_driver(smsgiucv_drv); | ||
192 | return rc; | ||
193 | } | ||
194 | module_init(smsgiucv_app_init); | ||
195 | |||
196 | static void __exit smsgiucv_app_exit(void) | ||
197 | { | ||
198 | /* unregister callback */ | ||
199 | smsg_unregister_callback(SMSG_PREFIX, smsg_app_callback); | ||
200 | |||
201 | /* cancel pending work and flush any queued event work */ | ||
202 | cancel_work_sync(&smsg_event_work); | ||
203 | smsg_event_work_fn(&smsg_event_work); | ||
204 | |||
205 | device_unregister(smsg_app_dev); | ||
206 | } | ||
207 | module_exit(smsgiucv_app_exit); | ||
208 | |||
209 | MODULE_LICENSE("GPL v2"); | ||
210 | MODULE_DESCRIPTION("Deliver z/VM CP SMSG as uevents"); | ||
211 | MODULE_AUTHOR("Hendrik Brueckner <brueckner@linux.vnet.ibm.com>"); | ||
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 71b97ff77cf0..6479273a3094 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -319,8 +319,6 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id, | |||
319 | id->input_handler = zfcp_qdio_int_resp; | 319 | id->input_handler = zfcp_qdio_int_resp; |
320 | id->output_handler = zfcp_qdio_int_req; | 320 | id->output_handler = zfcp_qdio_int_req; |
321 | id->int_parm = (unsigned long) qdio; | 321 | id->int_parm = (unsigned long) qdio; |
322 | id->flags = QDIO_INBOUND_0COPY_SBALS | | ||
323 | QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS; | ||
324 | id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal); | 322 | id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal); |
325 | id->output_sbal_addr_array = (void **) (qdio->req_q.sbal); | 323 | id->output_sbal_addr_array = (void **) (qdio->req_q.sbal); |
326 | 324 | ||
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 1d7a8780e00c..0d9d6f7567f5 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c | |||
@@ -595,8 +595,6 @@ static int ses_intf_add(struct device *cdev, | |||
595 | ses_dev->page10_len = len; | 595 | ses_dev->page10_len = len; |
596 | buf = NULL; | 596 | buf = NULL; |
597 | } | 597 | } |
598 | kfree(hdr_buf); | ||
599 | |||
600 | scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL); | 598 | scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL); |
601 | if (!scomp) | 599 | if (!scomp) |
602 | goto err_free; | 600 | goto err_free; |
@@ -608,6 +606,8 @@ static int ses_intf_add(struct device *cdev, | |||
608 | goto err_free; | 606 | goto err_free; |
609 | } | 607 | } |
610 | 608 | ||
609 | kfree(hdr_buf); | ||
610 | |||
611 | edev->scratch = ses_dev; | 611 | edev->scratch = ses_dev; |
612 | for (i = 0; i < components; i++) | 612 | for (i = 0; i < components; i++) |
613 | edev->component[i].scratch = scomp + i; | 613 | edev->component[i].scratch = scomp + i; |
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index 0807b260268b..fef0e3c75b16 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c | |||
@@ -226,7 +226,7 @@ static struct scsi_host_template sgiwd93_template = { | |||
226 | .use_clustering = DISABLE_CLUSTERING, | 226 | .use_clustering = DISABLE_CLUSTERING, |
227 | }; | 227 | }; |
228 | 228 | ||
229 | static int __init sgiwd93_probe(struct platform_device *pdev) | 229 | static int __devinit sgiwd93_probe(struct platform_device *pdev) |
230 | { | 230 | { |
231 | struct sgiwd93_platform_data *pd = pdev->dev.platform_data; | 231 | struct sgiwd93_platform_data *pd = pdev->dev.platform_data; |
232 | unsigned char *wdregs = pd->wdregs; | 232 | unsigned char *wdregs = pd->wdregs; |
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c index 37b3359e863e..56cf0bb4ed1f 100644 --- a/drivers/scsi/sni_53c710.c +++ b/drivers/scsi/sni_53c710.c | |||
@@ -64,7 +64,7 @@ static struct scsi_host_template snirm710_template = { | |||
64 | .module = THIS_MODULE, | 64 | .module = THIS_MODULE, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static int __init snirm710_probe(struct platform_device *dev) | 67 | static int __devinit snirm710_probe(struct platform_device *dev) |
68 | { | 68 | { |
69 | unsigned long base; | 69 | unsigned long base; |
70 | struct NCR_700_Host_Parameters *hostdata; | 70 | struct NCR_700_Host_Parameters *hostdata; |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7c4ebe6ee18b..c3db16b7afa1 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -2408,6 +2408,21 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2408 | } | 2408 | } |
2409 | 2409 | ||
2410 | static void | 2410 | static void |
2411 | serial8250_set_ldisc(struct uart_port *port) | ||
2412 | { | ||
2413 | int line = port->line; | ||
2414 | |||
2415 | if (line >= port->state->port.tty->driver->num) | ||
2416 | return; | ||
2417 | |||
2418 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | ||
2419 | port->flags |= UPF_HARDPPS_CD; | ||
2420 | serial8250_enable_ms(port); | ||
2421 | } else | ||
2422 | port->flags &= ~UPF_HARDPPS_CD; | ||
2423 | } | ||
2424 | |||
2425 | static void | ||
2411 | serial8250_pm(struct uart_port *port, unsigned int state, | 2426 | serial8250_pm(struct uart_port *port, unsigned int state, |
2412 | unsigned int oldstate) | 2427 | unsigned int oldstate) |
2413 | { | 2428 | { |
@@ -2628,6 +2643,7 @@ static struct uart_ops serial8250_pops = { | |||
2628 | .startup = serial8250_startup, | 2643 | .startup = serial8250_startup, |
2629 | .shutdown = serial8250_shutdown, | 2644 | .shutdown = serial8250_shutdown, |
2630 | .set_termios = serial8250_set_termios, | 2645 | .set_termios = serial8250_set_termios, |
2646 | .set_ldisc = serial8250_set_ldisc, | ||
2631 | .pm = serial8250_pm, | 2647 | .pm = serial8250_pm, |
2632 | .type = serial8250_type, | 2648 | .type = serial8250_type, |
2633 | .release_port = serial8250_release_port, | 2649 | .release_port = serial8250_release_port, |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 429a8ae86933..e4b3c2c88bb6 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -471,6 +471,20 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, | |||
471 | spin_unlock_irqrestore(&uap->port.lock, flags); | 471 | spin_unlock_irqrestore(&uap->port.lock, flags); |
472 | } | 472 | } |
473 | 473 | ||
474 | static void pl010_set_ldisc(struct uart_port *port) | ||
475 | { | ||
476 | int line = port->line; | ||
477 | |||
478 | if (line >= port->state->port.tty->driver->num) | ||
479 | return; | ||
480 | |||
481 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | ||
482 | port->flags |= UPF_HARDPPS_CD; | ||
483 | pl010_enable_ms(port); | ||
484 | } else | ||
485 | port->flags &= ~UPF_HARDPPS_CD; | ||
486 | } | ||
487 | |||
474 | static const char *pl010_type(struct uart_port *port) | 488 | static const char *pl010_type(struct uart_port *port) |
475 | { | 489 | { |
476 | return port->type == PORT_AMBA ? "AMBA" : NULL; | 490 | return port->type == PORT_AMBA ? "AMBA" : NULL; |
@@ -531,6 +545,7 @@ static struct uart_ops amba_pl010_pops = { | |||
531 | .startup = pl010_startup, | 545 | .startup = pl010_startup, |
532 | .shutdown = pl010_shutdown, | 546 | .shutdown = pl010_shutdown, |
533 | .set_termios = pl010_set_termios, | 547 | .set_termios = pl010_set_termios, |
548 | .set_ldisc = pl010_set_ldisc, | ||
534 | .type = pl010_type, | 549 | .type = pl010_type, |
535 | .release_port = pl010_release_port, | 550 | .release_port = pl010_release_port, |
536 | .request_port = pl010_request_port, | 551 | .request_port = pl010_request_port, |
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index cadb6f7321ad..7ebecc92c61b 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c | |||
@@ -770,13 +770,8 @@ static struct usb_driver oled_driver = { | |||
770 | .id_table = id_table, | 770 | .id_table = id_table, |
771 | }; | 771 | }; |
772 | 772 | ||
773 | static ssize_t version_show(struct class *dev, char *buf) | 773 | static CLASS_ATTR_STRING(version, S_IRUGO, |
774 | { | 774 | ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION); |
775 | return sprintf(buf, ASUS_OLED_UNDERSCORE_NAME " %s\n", | ||
776 | ASUS_OLED_VERSION); | ||
777 | } | ||
778 | |||
779 | static CLASS_ATTR(version, S_IRUGO, version_show, NULL); | ||
780 | 775 | ||
781 | static int __init asus_oled_init(void) | 776 | static int __init asus_oled_init(void) |
782 | { | 777 | { |
@@ -788,7 +783,7 @@ static int __init asus_oled_init(void) | |||
788 | return PTR_ERR(oled_class); | 783 | return PTR_ERR(oled_class); |
789 | } | 784 | } |
790 | 785 | ||
791 | retval = class_create_file(oled_class, &class_attr_version); | 786 | retval = class_create_file(oled_class, &class_attr_version.attr); |
792 | if (retval) { | 787 | if (retval) { |
793 | err("Error creating class version file"); | 788 | err("Error creating class version file"); |
794 | goto error; | 789 | goto error; |
@@ -810,7 +805,7 @@ error: | |||
810 | 805 | ||
811 | static void __exit asus_oled_exit(void) | 806 | static void __exit asus_oled_exit(void) |
812 | { | 807 | { |
813 | class_remove_file(oled_class, &class_attr_version); | 808 | class_remove_file(oled_class, &class_attr_version.attr); |
814 | class_destroy(oled_class); | 809 | class_destroy(oled_class); |
815 | 810 | ||
816 | usb_deregister(&oled_driver); | 811 | usb_deregister(&oled_driver); |
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 8aa1955f35ed..1da73ecd9799 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig | |||
@@ -44,17 +44,6 @@ config UIO_PDRV_GENIRQ | |||
44 | 44 | ||
45 | If you don't know what to do here, say N. | 45 | If you don't know what to do here, say N. |
46 | 46 | ||
47 | config UIO_SMX | ||
48 | tristate "SMX cryptengine UIO interface" | ||
49 | help | ||
50 | Userspace IO interface to the Cryptography engine found on the | ||
51 | Nias Digital SMX boards. These will be available from Q4 2008 | ||
52 | from http://www.niasdigital.com. The userspace part of this | ||
53 | driver will be released under the GPL at the same time as the | ||
54 | hardware and will be able to be downloaded from the same site. | ||
55 | |||
56 | If you compile this as a module, it will be called uio_smx. | ||
57 | |||
58 | config UIO_AEC | 47 | config UIO_AEC |
59 | tristate "AEC video timestamp device" | 48 | tristate "AEC video timestamp device" |
60 | depends on PCI | 49 | depends on PCI |
@@ -74,6 +63,7 @@ config UIO_AEC | |||
74 | 63 | ||
75 | config UIO_SERCOS3 | 64 | config UIO_SERCOS3 |
76 | tristate "Automata Sercos III PCI card driver" | 65 | tristate "Automata Sercos III PCI card driver" |
66 | depends on PCI | ||
77 | help | 67 | help |
78 | Userspace I/O interface for the Sercos III PCI card from | 68 | Userspace I/O interface for the Sercos III PCI card from |
79 | Automata GmbH. The userspace part of this driver will be | 69 | Automata GmbH. The userspace part of this driver will be |
@@ -87,11 +77,21 @@ config UIO_SERCOS3 | |||
87 | config UIO_PCI_GENERIC | 77 | config UIO_PCI_GENERIC |
88 | tristate "Generic driver for PCI 2.3 and PCI Express cards" | 78 | tristate "Generic driver for PCI 2.3 and PCI Express cards" |
89 | depends on PCI | 79 | depends on PCI |
90 | default n | ||
91 | help | 80 | help |
92 | Generic driver that you can bind, dynamically, to any | 81 | Generic driver that you can bind, dynamically, to any |
93 | PCI 2.3 compliant and PCI Express card. It is useful, | 82 | PCI 2.3 compliant and PCI Express card. It is useful, |
94 | primarily, for virtualization scenarios. | 83 | primarily, for virtualization scenarios. |
95 | If you compile this as a module, it will be called uio_pci_generic. | 84 | If you compile this as a module, it will be called uio_pci_generic. |
96 | 85 | ||
86 | config UIO_NETX | ||
87 | tristate "Hilscher NetX Card driver" | ||
88 | depends on PCI | ||
89 | help | ||
90 | Driver for Hilscher NetX based fieldbus cards (cifX, comX). | ||
91 | This driver requires a userspace component that comes with the card | ||
92 | or is available from Hilscher (http://www.hilscher.com). | ||
93 | |||
94 | To compile this driver as a module, choose M here; the module | ||
95 | will be called uio_netx. | ||
96 | |||
97 | endif | 97 | endif |
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index 73b2e7516729..18fd818c5b97 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile | |||
@@ -2,7 +2,7 @@ obj-$(CONFIG_UIO) += uio.o | |||
2 | obj-$(CONFIG_UIO_CIF) += uio_cif.o | 2 | obj-$(CONFIG_UIO_CIF) += uio_cif.o |
3 | obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o | 3 | obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o |
4 | obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o | 4 | obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o |
5 | obj-$(CONFIG_UIO_SMX) += uio_smx.o | ||
6 | obj-$(CONFIG_UIO_AEC) += uio_aec.o | 5 | obj-$(CONFIG_UIO_AEC) += uio_aec.o |
7 | obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o | 6 | obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o |
8 | obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o | 7 | obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o |
8 | obj-$(CONFIG_UIO_NETX) += uio_netx.o | ||
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index e941367dd28f..4de382acd8f2 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c | |||
@@ -129,7 +129,7 @@ static ssize_t map_type_show(struct kobject *kobj, struct attribute *attr, | |||
129 | return entry->show(mem, buf); | 129 | return entry->show(mem, buf); |
130 | } | 130 | } |
131 | 131 | ||
132 | static struct sysfs_ops map_sysfs_ops = { | 132 | static const struct sysfs_ops map_sysfs_ops = { |
133 | .show = map_type_show, | 133 | .show = map_type_show, |
134 | }; | 134 | }; |
135 | 135 | ||
@@ -217,7 +217,7 @@ static ssize_t portio_type_show(struct kobject *kobj, struct attribute *attr, | |||
217 | return entry->show(port, buf); | 217 | return entry->show(port, buf); |
218 | } | 218 | } |
219 | 219 | ||
220 | static struct sysfs_ops portio_sysfs_ops = { | 220 | static const struct sysfs_ops portio_sysfs_ops = { |
221 | .show = portio_type_show, | 221 | .show = portio_type_show, |
222 | }; | 222 | }; |
223 | 223 | ||
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c new file mode 100644 index 000000000000..afbf0bd55cc9 --- /dev/null +++ b/drivers/uio/uio_netx.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX). | ||
3 | * See http://www.hilscher.com for details. | ||
4 | * | ||
5 | * (C) 2007 Hans J. Koch <hjk@linutronix.de> | ||
6 | * (C) 2008 Manuel Traut <manut@linutronix.de> | ||
7 | * | ||
8 | * Licensed under GPL version 2 only. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/uio_driver.h> | ||
17 | |||
18 | #define PCI_VENDOR_ID_HILSCHER 0x15CF | ||
19 | #define PCI_DEVICE_ID_HILSCHER_NETX 0x0000 | ||
20 | #define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235 | ||
21 | #define PCI_SUBDEVICE_ID_NXPCA 0x3335 | ||
22 | |||
23 | #define DPM_HOST_INT_EN0 0xfff0 | ||
24 | #define DPM_HOST_INT_STAT0 0xffe0 | ||
25 | |||
26 | #define DPM_HOST_INT_MASK 0xe600ffff | ||
27 | #define DPM_HOST_INT_GLOBAL_EN 0x80000000 | ||
28 | |||
29 | static irqreturn_t netx_handler(int irq, struct uio_info *dev_info) | ||
30 | { | ||
31 | void __iomem *int_enable_reg = dev_info->mem[0].internal_addr | ||
32 | + DPM_HOST_INT_EN0; | ||
33 | void __iomem *int_status_reg = dev_info->mem[0].internal_addr | ||
34 | + DPM_HOST_INT_STAT0; | ||
35 | |||
36 | /* Is one of our interrupts enabled and active ? */ | ||
37 | if (!(ioread32(int_enable_reg) & ioread32(int_status_reg) | ||
38 | & DPM_HOST_INT_MASK)) | ||
39 | return IRQ_NONE; | ||
40 | |||
41 | /* Disable interrupt */ | ||
42 | iowrite32(ioread32(int_enable_reg) & ~DPM_HOST_INT_GLOBAL_EN, | ||
43 | int_enable_reg); | ||
44 | return IRQ_HANDLED; | ||
45 | } | ||
46 | |||
47 | static int __devinit netx_pci_probe(struct pci_dev *dev, | ||
48 | const struct pci_device_id *id) | ||
49 | { | ||
50 | struct uio_info *info; | ||
51 | int bar; | ||
52 | |||
53 | info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); | ||
54 | if (!info) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | if (pci_enable_device(dev)) | ||
58 | goto out_free; | ||
59 | |||
60 | if (pci_request_regions(dev, "netx")) | ||
61 | goto out_disable; | ||
62 | |||
63 | switch (id->device) { | ||
64 | case PCI_DEVICE_ID_HILSCHER_NETX: | ||
65 | bar = 0; | ||
66 | info->name = "netx"; | ||
67 | break; | ||
68 | default: | ||
69 | bar = 2; | ||
70 | info->name = "netx_plx"; | ||
71 | } | ||
72 | |||
73 | /* BAR0 or 2 points to the card's dual port memory */ | ||
74 | info->mem[0].addr = pci_resource_start(dev, bar); | ||
75 | if (!info->mem[0].addr) | ||
76 | goto out_release; | ||
77 | info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar), | ||
78 | pci_resource_len(dev, bar)); | ||
79 | |||
80 | if (!info->mem[0].internal_addr) | ||
81 | goto out_release; | ||
82 | |||
83 | info->mem[0].size = pci_resource_len(dev, bar); | ||
84 | info->mem[0].memtype = UIO_MEM_PHYS; | ||
85 | info->irq = dev->irq; | ||
86 | info->irq_flags = IRQF_SHARED; | ||
87 | info->handler = netx_handler; | ||
88 | info->version = "0.0.1"; | ||
89 | |||
90 | /* Make sure all interrupts are disabled */ | ||
91 | iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0); | ||
92 | |||
93 | if (uio_register_device(&dev->dev, info)) | ||
94 | goto out_unmap; | ||
95 | |||
96 | pci_set_drvdata(dev, info); | ||
97 | dev_info(&dev->dev, "Found %s card, registered UIO device.\n", | ||
98 | info->name); | ||
99 | |||
100 | return 0; | ||
101 | |||
102 | out_unmap: | ||
103 | iounmap(info->mem[0].internal_addr); | ||
104 | out_release: | ||
105 | pci_release_regions(dev); | ||
106 | out_disable: | ||
107 | pci_disable_device(dev); | ||
108 | out_free: | ||
109 | kfree(info); | ||
110 | return -ENODEV; | ||
111 | } | ||
112 | |||
113 | static void netx_pci_remove(struct pci_dev *dev) | ||
114 | { | ||
115 | struct uio_info *info = pci_get_drvdata(dev); | ||
116 | |||
117 | /* Disable all interrupts */ | ||
118 | iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0); | ||
119 | uio_unregister_device(info); | ||
120 | pci_release_regions(dev); | ||
121 | pci_disable_device(dev); | ||
122 | pci_set_drvdata(dev, NULL); | ||
123 | iounmap(info->mem[0].internal_addr); | ||
124 | |||
125 | kfree(info); | ||
126 | } | ||
127 | |||
128 | static struct pci_device_id netx_pci_ids[] = { | ||
129 | { | ||
130 | .vendor = PCI_VENDOR_ID_HILSCHER, | ||
131 | .device = PCI_DEVICE_ID_HILSCHER_NETX, | ||
132 | .subvendor = 0, | ||
133 | .subdevice = 0, | ||
134 | }, | ||
135 | { | ||
136 | .vendor = PCI_VENDOR_ID_PLX, | ||
137 | .device = PCI_DEVICE_ID_PLX_9030, | ||
138 | .subvendor = PCI_VENDOR_ID_PLX, | ||
139 | .subdevice = PCI_SUBDEVICE_ID_NXSB_PCA, | ||
140 | }, | ||
141 | { | ||
142 | .vendor = PCI_VENDOR_ID_PLX, | ||
143 | .device = PCI_DEVICE_ID_PLX_9030, | ||
144 | .subvendor = PCI_VENDOR_ID_PLX, | ||
145 | .subdevice = PCI_SUBDEVICE_ID_NXPCA, | ||
146 | }, | ||
147 | { 0, } | ||
148 | }; | ||
149 | |||
150 | static struct pci_driver netx_pci_driver = { | ||
151 | .name = "netx", | ||
152 | .id_table = netx_pci_ids, | ||
153 | .probe = netx_pci_probe, | ||
154 | .remove = netx_pci_remove, | ||
155 | }; | ||
156 | |||
157 | static int __init netx_init_module(void) | ||
158 | { | ||
159 | return pci_register_driver(&netx_pci_driver); | ||
160 | } | ||
161 | |||
162 | static void __exit netx_exit_module(void) | ||
163 | { | ||
164 | pci_unregister_driver(&netx_pci_driver); | ||
165 | } | ||
166 | |||
167 | module_init(netx_init_module); | ||
168 | module_exit(netx_exit_module); | ||
169 | |||
170 | MODULE_DEVICE_TABLE(pci, netx_pci_ids); | ||
171 | MODULE_LICENSE("GPL v2"); | ||
172 | MODULE_AUTHOR("Hans J. Koch, Manuel Traut"); | ||
diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c deleted file mode 100644 index 44054a650a8a..000000000000 --- a/drivers/uio/uio_smx.c +++ /dev/null | |||
@@ -1,140 +0,0 @@ | |||
1 | /* | ||
2 | * UIO SMX Cryptengine driver. | ||
3 | * | ||
4 | * (C) 2008 Nias Digital P/L <bn@niasdigital.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/uio_driver.h> | ||
16 | #include <linux/io.h> | ||
17 | |||
18 | #define DRV_NAME "smx-ce" | ||
19 | #define DRV_VERSION "0.03" | ||
20 | |||
21 | #define SMX_CSR 0x00000000 | ||
22 | #define SMX_EnD 0x00000001 | ||
23 | #define SMX_RUN 0x00000002 | ||
24 | #define SMX_DRDY 0x00000004 | ||
25 | #define SMX_ERR 0x00000008 | ||
26 | |||
27 | static irqreturn_t smx_handler(int irq, struct uio_info *dev_info) | ||
28 | { | ||
29 | void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR; | ||
30 | |||
31 | u32 status = ioread32(csr); | ||
32 | |||
33 | if (!(status & SMX_DRDY)) | ||
34 | return IRQ_NONE; | ||
35 | |||
36 | /* Disable interrupt */ | ||
37 | iowrite32(status & ~SMX_DRDY, csr); | ||
38 | return IRQ_HANDLED; | ||
39 | } | ||
40 | |||
41 | static int __devinit smx_ce_probe(struct platform_device *dev) | ||
42 | { | ||
43 | |||
44 | int ret = -ENODEV; | ||
45 | struct uio_info *info; | ||
46 | struct resource *regs; | ||
47 | |||
48 | info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); | ||
49 | if (!info) | ||
50 | return -ENOMEM; | ||
51 | |||
52 | regs = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
53 | if (!regs) { | ||
54 | dev_err(&dev->dev, "No memory resource specified\n"); | ||
55 | goto out_free; | ||
56 | } | ||
57 | |||
58 | info->mem[0].addr = regs->start; | ||
59 | if (!info->mem[0].addr) { | ||
60 | dev_err(&dev->dev, "Invalid memory resource\n"); | ||
61 | goto out_free; | ||
62 | } | ||
63 | |||
64 | info->mem[0].size = regs->end - regs->start + 1; | ||
65 | info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size); | ||
66 | |||
67 | if (!info->mem[0].internal_addr) { | ||
68 | dev_err(&dev->dev, "Can't remap memory address range\n"); | ||
69 | goto out_free; | ||
70 | } | ||
71 | |||
72 | info->mem[0].memtype = UIO_MEM_PHYS; | ||
73 | |||
74 | info->name = "smx-ce"; | ||
75 | info->version = "0.03"; | ||
76 | |||
77 | info->irq = platform_get_irq(dev, 0); | ||
78 | if (info->irq < 0) { | ||
79 | ret = info->irq; | ||
80 | dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n"); | ||
81 | goto out_unmap; | ||
82 | } | ||
83 | |||
84 | info->irq_flags = IRQF_SHARED; | ||
85 | info->handler = smx_handler; | ||
86 | |||
87 | platform_set_drvdata(dev, info); | ||
88 | |||
89 | ret = uio_register_device(&dev->dev, info); | ||
90 | |||
91 | if (ret) | ||
92 | goto out_unmap; | ||
93 | |||
94 | return 0; | ||
95 | |||
96 | out_unmap: | ||
97 | iounmap(info->mem[0].internal_addr); | ||
98 | out_free: | ||
99 | kfree(info); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static int __devexit smx_ce_remove(struct platform_device *dev) | ||
105 | { | ||
106 | struct uio_info *info = platform_get_drvdata(dev); | ||
107 | |||
108 | uio_unregister_device(info); | ||
109 | platform_set_drvdata(dev, NULL); | ||
110 | iounmap(info->mem[0].internal_addr); | ||
111 | |||
112 | kfree(info); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static struct platform_driver smx_ce_driver = { | ||
118 | .probe = smx_ce_probe, | ||
119 | .remove = __devexit_p(smx_ce_remove), | ||
120 | .driver = { | ||
121 | .name = DRV_NAME, | ||
122 | .owner = THIS_MODULE, | ||
123 | }, | ||
124 | }; | ||
125 | |||
126 | static int __init smx_ce_init_module(void) | ||
127 | { | ||
128 | return platform_driver_register(&smx_ce_driver); | ||
129 | } | ||
130 | module_init(smx_ce_init_module); | ||
131 | |||
132 | static void __exit smx_ce_exit_module(void) | ||
133 | { | ||
134 | platform_driver_unregister(&smx_ce_driver); | ||
135 | } | ||
136 | module_exit(smx_ce_exit_module); | ||
137 | |||
138 | MODULE_LICENSE("GPL v2"); | ||
139 | MODULE_VERSION(DRV_VERSION); | ||
140 | MODULE_AUTHOR("Ben Nizette <bn@niasdigital.com>"); | ||
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a7037bf81688..f3c233806fa3 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -489,10 +489,10 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
489 | if (device_is_registered(dev)) { | 489 | if (device_is_registered(dev)) { |
490 | device_release_driver(dev); | 490 | device_release_driver(dev); |
491 | } else { | 491 | } else { |
492 | down(&dev->sem); | 492 | device_lock(dev); |
493 | usb_unbind_interface(dev); | 493 | usb_unbind_interface(dev); |
494 | dev->driver = NULL; | 494 | dev->driver = NULL; |
495 | up(&dev->sem); | 495 | device_unlock(dev); |
496 | } | 496 | } |
497 | } | 497 | } |
498 | EXPORT_SYMBOL_GPL(usb_driver_release_interface); | 498 | EXPORT_SYMBOL_GPL(usb_driver_release_interface); |
diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index da77e41de990..08bd6dbfd4a6 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c | |||
@@ -74,13 +74,16 @@ | |||
74 | unsigned long beacon_timeout_ms = 500; | 74 | unsigned long beacon_timeout_ms = 500; |
75 | 75 | ||
76 | static | 76 | static |
77 | ssize_t beacon_timeout_ms_show(struct class *class, char *buf) | 77 | ssize_t beacon_timeout_ms_show(struct class *class, |
78 | struct class_attribute *attr, | ||
79 | char *buf) | ||
78 | { | 80 | { |
79 | return scnprintf(buf, PAGE_SIZE, "%lu\n", beacon_timeout_ms); | 81 | return scnprintf(buf, PAGE_SIZE, "%lu\n", beacon_timeout_ms); |
80 | } | 82 | } |
81 | 83 | ||
82 | static | 84 | static |
83 | ssize_t beacon_timeout_ms_store(struct class *class, | 85 | ssize_t beacon_timeout_ms_store(struct class *class, |
86 | struct class_attribute *attr, | ||
84 | const char *buf, size_t size) | 87 | const char *buf, size_t size) |
85 | { | 88 | { |
86 | unsigned long bt; | 89 | unsigned long bt; |
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c index cdd6c8efc9f8..5fad4e791b3e 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/uwb/umc-bus.c | |||
@@ -62,12 +62,12 @@ int umc_controller_reset(struct umc_dev *umc) | |||
62 | struct device *parent = umc->dev.parent; | 62 | struct device *parent = umc->dev.parent; |
63 | int ret = 0; | 63 | int ret = 0; |
64 | 64 | ||
65 | if(down_trylock(&parent->sem)) | 65 | if (device_trylock(parent)) |
66 | return -EAGAIN; | 66 | return -EAGAIN; |
67 | ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); | 67 | ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); |
68 | if (ret >= 0) | 68 | if (ret >= 0) |
69 | ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper); | 69 | ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper); |
70 | up(&parent->sem); | 70 | device_unlock(parent); |
71 | 71 | ||
72 | return ret; | 72 | return ret; |
73 | } | 73 | } |
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index d5bcfc1c227a..157485c862c0 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h | |||
@@ -366,12 +366,12 @@ struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal); | |||
366 | 366 | ||
367 | static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) | 367 | static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) |
368 | { | 368 | { |
369 | down(&uwb_dev->dev.sem); | 369 | device_lock(&uwb_dev->dev); |
370 | } | 370 | } |
371 | 371 | ||
372 | static inline void uwb_dev_unlock(struct uwb_dev *uwb_dev) | 372 | static inline void uwb_dev_unlock(struct uwb_dev *uwb_dev) |
373 | { | 373 | { |
374 | up(&uwb_dev->dev.sem); | 374 | device_unlock(&uwb_dev->dev); |
375 | } | 375 | } |
376 | 376 | ||
377 | #endif /* #ifndef __UWB_INTERNAL_H__ */ | 377 | #endif /* #ifndef __UWB_INTERNAL_H__ */ |
diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c index 0370399ff4bb..6627c94cc854 100644 --- a/drivers/uwb/wlp/sysfs.c +++ b/drivers/uwb/wlp/sysfs.c | |||
@@ -615,8 +615,7 @@ ssize_t wlp_wss_attr_store(struct kobject *kobj, struct attribute *attr, | |||
615 | return ret; | 615 | return ret; |
616 | } | 616 | } |
617 | 617 | ||
618 | static | 618 | static const struct sysfs_ops wss_sysfs_ops = { |
619 | struct sysfs_ops wss_sysfs_ops = { | ||
620 | .show = wlp_wss_attr_show, | 619 | .show = wlp_wss_attr_show, |
621 | .store = wlp_wss_attr_store, | 620 | .store = wlp_wss_attr_store, |
622 | }; | 621 | }; |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 83d40ed2f2d6..1c60053439a9 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1497,7 +1497,6 @@ config FB_VIA | |||
1497 | select FB_CFB_FILLRECT | 1497 | select FB_CFB_FILLRECT |
1498 | select FB_CFB_COPYAREA | 1498 | select FB_CFB_COPYAREA |
1499 | select FB_CFB_IMAGEBLIT | 1499 | select FB_CFB_IMAGEBLIT |
1500 | select FB_SOFT_CURSOR | ||
1501 | select I2C_ALGOBIT | 1500 | select I2C_ALGOBIT |
1502 | select I2C | 1501 | select I2C |
1503 | help | 1502 | help |
@@ -1948,6 +1947,27 @@ config FB_S3C2410_DEBUG | |||
1948 | Turn on debugging messages. Note that you can set/unset at run time | 1947 | Turn on debugging messages. Note that you can set/unset at run time |
1949 | through sysfs | 1948 | through sysfs |
1950 | 1949 | ||
1950 | config FB_NUC900 | ||
1951 | bool "NUC900 LCD framebuffer support" | ||
1952 | depends on FB && ARCH_W90X900 | ||
1953 | select FB_CFB_FILLRECT | ||
1954 | select FB_CFB_COPYAREA | ||
1955 | select FB_CFB_IMAGEBLIT | ||
1956 | ---help--- | ||
1957 | Frame buffer driver for the built-in LCD controller in the Nuvoton | ||
1958 | NUC900 processor | ||
1959 | |||
1960 | config GPM1040A0_320X240 | ||
1961 | bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD" | ||
1962 | depends on FB_NUC900 | ||
1963 | |||
1964 | config FB_NUC900_DEBUG | ||
1965 | bool "NUC900 lcd debug messages" | ||
1966 | depends on FB_NUC900 | ||
1967 | help | ||
1968 | Turn on debugging messages. Note that you can set/unset at run time | ||
1969 | through sysfs | ||
1970 | |||
1951 | config FB_SM501 | 1971 | config FB_SM501 |
1952 | tristate "Silicon Motion SM501 framebuffer support" | 1972 | tristate "Silicon Motion SM501 framebuffer support" |
1953 | depends on FB && MFD_SM501 | 1973 | depends on FB && MFD_SM501 |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 4ecb30c4f3f2..a42ad55e3a15 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -129,6 +129,7 @@ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o | |||
129 | obj-$(CONFIG_FB_CARMINE) += carminefb.o | 129 | obj-$(CONFIG_FB_CARMINE) += carminefb.o |
130 | obj-$(CONFIG_FB_MB862XX) += mb862xx/ | 130 | obj-$(CONFIG_FB_MB862XX) += mb862xx/ |
131 | obj-$(CONFIG_FB_MSM) += msm/ | 131 | obj-$(CONFIG_FB_MSM) += msm/ |
132 | obj-$(CONFIG_FB_NUC900) += nuc900fb.o | ||
132 | 133 | ||
133 | # Platform or fallback drivers go here | 134 | # Platform or fallback drivers go here |
134 | obj-$(CONFIG_FB_UVESA) += uvesafb.o | 135 | obj-$(CONFIG_FB_UVESA) += uvesafb.o |
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 0bcc59eb37fa..43d7d5067361 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c | |||
@@ -1221,7 +1221,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) | |||
1221 | printk("acornfb: freed %dK memory\n", mb_freed); | 1221 | printk("acornfb: freed %dK memory\n", mb_freed); |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | static int __init acornfb_probe(struct platform_device *dev) | 1224 | static int __devinit acornfb_probe(struct platform_device *dev) |
1225 | { | 1225 | { |
1226 | unsigned long size; | 1226 | unsigned long size; |
1227 | u_int h_sync, v_sync; | 1227 | u_int h_sync, v_sync; |
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index c3431691c9f2..01554d696528 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c | |||
@@ -504,7 +504,7 @@ static struct fb_ops arcfb_ops = { | |||
504 | .fb_ioctl = arcfb_ioctl, | 504 | .fb_ioctl = arcfb_ioctl, |
505 | }; | 505 | }; |
506 | 506 | ||
507 | static int __init arcfb_probe(struct platform_device *dev) | 507 | static int __devinit arcfb_probe(struct platform_device *dev) |
508 | { | 508 | { |
509 | struct fb_info *info; | 509 | struct fb_info *info; |
510 | int retval = -ENOMEM; | 510 | int retval = -ENOMEM; |
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index 9fe90ce928fb..e70bc225fe31 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c | |||
@@ -140,7 +140,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc | |||
140 | 140 | ||
141 | /* 3 <= m <= 257 */ | 141 | /* 3 <= m <= 257 */ |
142 | if (m >= 3 && m <= 257) { | 142 | if (m >= 3 && m <= 257) { |
143 | unsigned new_error = ((Ftarget * n) - (Fref * m)) >= 0 ? | 143 | unsigned new_error = Ftarget * n >= Fref * m ? |
144 | ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n)); | 144 | ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n)); |
145 | if (new_error < best_error) { | 145 | if (new_error < best_error) { |
146 | best_n = n; | 146 | best_n = n; |
@@ -152,7 +152,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc | |||
152 | else if (m <= 1028) { | 152 | else if (m <= 1028) { |
153 | /* remember there are still only 8-bits of precision in m, so | 153 | /* remember there are still only 8-bits of precision in m, so |
154 | * avoid over-optimistic error calculations */ | 154 | * avoid over-optimistic error calculations */ |
155 | unsigned new_error = ((Ftarget * n) - (Fref * (m & ~3))) >= 0 ? | 155 | unsigned new_error = Ftarget * n >= Fref * (m & ~3) ? |
156 | ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n)); | 156 | ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n)); |
157 | if (new_error < best_error) { | 157 | if (new_error < best_error) { |
158 | best_n = n; | 158 | best_n = n; |
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index e49ae5edcc00..814312a7452f 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
@@ -82,7 +82,6 @@ struct bfin_bf54xfb_info { | |||
82 | unsigned char *fb_buffer; /* RGB Buffer */ | 82 | unsigned char *fb_buffer; /* RGB Buffer */ |
83 | 83 | ||
84 | dma_addr_t dma_handle; | 84 | dma_addr_t dma_handle; |
85 | int lq043_mmap; | ||
86 | int lq043_open_cnt; | 85 | int lq043_open_cnt; |
87 | int irq; | 86 | int irq; |
88 | spinlock_t lock; /* lock */ | 87 | spinlock_t lock; /* lock */ |
@@ -316,7 +315,6 @@ static int bfin_bf54x_fb_release(struct fb_info *info, int user) | |||
316 | spin_lock(&fbi->lock); | 315 | spin_lock(&fbi->lock); |
317 | 316 | ||
318 | fbi->lq043_open_cnt--; | 317 | fbi->lq043_open_cnt--; |
319 | fbi->lq043_mmap = 0; | ||
320 | 318 | ||
321 | if (fbi->lq043_open_cnt <= 0) { | 319 | if (fbi->lq043_open_cnt <= 0) { |
322 | 320 | ||
@@ -374,33 +372,6 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var, | |||
374 | return 0; | 372 | return 0; |
375 | } | 373 | } |
376 | 374 | ||
377 | static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
378 | { | ||
379 | |||
380 | struct bfin_bf54xfb_info *fbi = info->par; | ||
381 | |||
382 | if (fbi->lq043_mmap) | ||
383 | return -1; | ||
384 | |||
385 | spin_lock(&fbi->lock); | ||
386 | fbi->lq043_mmap = 1; | ||
387 | spin_unlock(&fbi->lock); | ||
388 | |||
389 | vma->vm_start = (unsigned long)(fbi->fb_buffer); | ||
390 | |||
391 | vma->vm_end = vma->vm_start + info->fix.smem_len; | ||
392 | /* For those who don't understand how mmap works, go read | ||
393 | * Documentation/nommu-mmap.txt. | ||
394 | * For those that do, you will know that the VM_MAYSHARE flag | ||
395 | * must be set in the vma->vm_flags structure on noMMU | ||
396 | * Other flags can be set, and are documented in | ||
397 | * include/linux/mm.h | ||
398 | */ | ||
399 | vma->vm_flags |= VM_MAYSHARE | VM_SHARED; | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 375 | int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) |
405 | { | 376 | { |
406 | if (nocursor) | 377 | if (nocursor) |
@@ -452,7 +423,6 @@ static struct fb_ops bfin_bf54x_fb_ops = { | |||
452 | .fb_fillrect = cfb_fillrect, | 423 | .fb_fillrect = cfb_fillrect, |
453 | .fb_copyarea = cfb_copyarea, | 424 | .fb_copyarea = cfb_copyarea, |
454 | .fb_imageblit = cfb_imageblit, | 425 | .fb_imageblit = cfb_imageblit, |
455 | .fb_mmap = bfin_bf54x_fb_mmap, | ||
456 | .fb_cursor = bfin_bf54x_fb_cursor, | 426 | .fb_cursor = bfin_bf54x_fb_cursor, |
457 | .fb_setcolreg = bfin_bf54x_fb_setcolreg, | 427 | .fb_setcolreg = bfin_bf54x_fb_setcolreg, |
458 | }; | 428 | }; |
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index b690c269784a..03872365a36d 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
25 | #include <linux/dma-mapping.h> | ||
26 | 25 | ||
27 | #include <asm/blackfin.h> | 26 | #include <asm/blackfin.h> |
28 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 2549c53b26a0..5653d083a983 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c | |||
@@ -87,7 +87,6 @@ struct bfin_t350mcqbfb_info { | |||
87 | struct device *dev; | 87 | struct device *dev; |
88 | unsigned char *fb_buffer; /* RGB Buffer */ | 88 | unsigned char *fb_buffer; /* RGB Buffer */ |
89 | dma_addr_t dma_handle; | 89 | dma_addr_t dma_handle; |
90 | int lq043_mmap; | ||
91 | int lq043_open_cnt; | 90 | int lq043_open_cnt; |
92 | int irq; | 91 | int irq; |
93 | spinlock_t lock; /* lock */ | 92 | spinlock_t lock; /* lock */ |
@@ -235,7 +234,6 @@ static int bfin_t350mcqb_fb_release(struct fb_info *info, int user) | |||
235 | spin_lock(&fbi->lock); | 234 | spin_lock(&fbi->lock); |
236 | 235 | ||
237 | fbi->lq043_open_cnt--; | 236 | fbi->lq043_open_cnt--; |
238 | fbi->lq043_mmap = 0; | ||
239 | 237 | ||
240 | if (fbi->lq043_open_cnt <= 0) { | 238 | if (fbi->lq043_open_cnt <= 0) { |
241 | bfin_t350mcqb_disable_ppi(); | 239 | bfin_t350mcqb_disable_ppi(); |
@@ -293,32 +291,6 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var, | |||
293 | return 0; | 291 | return 0; |
294 | } | 292 | } |
295 | 293 | ||
296 | static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
297 | { | ||
298 | struct bfin_t350mcqbfb_info *fbi = info->par; | ||
299 | |||
300 | if (fbi->lq043_mmap) | ||
301 | return -1; | ||
302 | |||
303 | spin_lock(&fbi->lock); | ||
304 | fbi->lq043_mmap = 1; | ||
305 | spin_unlock(&fbi->lock); | ||
306 | |||
307 | vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET); | ||
308 | |||
309 | vma->vm_end = vma->vm_start + info->fix.smem_len; | ||
310 | /* For those who don't understand how mmap works, go read | ||
311 | * Documentation/nommu-mmap.txt. | ||
312 | * For those that do, you will know that the VM_MAYSHARE flag | ||
313 | * must be set in the vma->vm_flags structure on noMMU | ||
314 | * Other flags can be set, and are documented in | ||
315 | * include/linux/mm.h | ||
316 | */ | ||
317 | vma->vm_flags |= VM_MAYSHARE | VM_SHARED; | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 294 | int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) |
323 | { | 295 | { |
324 | if (nocursor) | 296 | if (nocursor) |
@@ -370,7 +342,6 @@ static struct fb_ops bfin_t350mcqb_fb_ops = { | |||
370 | .fb_fillrect = cfb_fillrect, | 342 | .fb_fillrect = cfb_fillrect, |
371 | .fb_copyarea = cfb_copyarea, | 343 | .fb_copyarea = cfb_copyarea, |
372 | .fb_imageblit = cfb_imageblit, | 344 | .fb_imageblit = cfb_imageblit, |
373 | .fb_mmap = bfin_t350mcqb_fb_mmap, | ||
374 | .fb_cursor = bfin_t350mcqb_fb_cursor, | 345 | .fb_cursor = bfin_t350mcqb_fb_cursor, |
375 | .fb_setcolreg = bfin_t350mcqb_fb_setcolreg, | 346 | .fb_setcolreg = bfin_t350mcqb_fb_setcolreg, |
376 | }; | 347 | }; |
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c index df9ccb901d86..ebda6876d3a9 100644 --- a/drivers/video/broadsheetfb.c +++ b/drivers/video/broadsheetfb.c | |||
@@ -29,11 +29,65 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | #include <linux/firmware.h> | ||
32 | #include <linux/uaccess.h> | 33 | #include <linux/uaccess.h> |
33 | 34 | ||
34 | #include <video/broadsheetfb.h> | 35 | #include <video/broadsheetfb.h> |
35 | 36 | ||
36 | /* Display specific information */ | 37 | /* track panel specific parameters */ |
38 | struct panel_info { | ||
39 | int w; | ||
40 | int h; | ||
41 | u16 sdcfg; | ||
42 | u16 gdcfg; | ||
43 | u16 lutfmt; | ||
44 | u16 fsynclen; | ||
45 | u16 fendfbegin; | ||
46 | u16 lsynclen; | ||
47 | u16 lendlbegin; | ||
48 | u16 pixclk; | ||
49 | }; | ||
50 | |||
51 | /* table of panel specific parameters to be indexed into by the board drivers */ | ||
52 | static struct panel_info panel_table[] = { | ||
53 | { /* standard 6" on TFT backplane */ | ||
54 | .w = 800, | ||
55 | .h = 600, | ||
56 | .sdcfg = (100 | (1 << 8) | (1 << 9)), | ||
57 | .gdcfg = 2, | ||
58 | .lutfmt = (4 | (1 << 7)), | ||
59 | .fsynclen = 4, | ||
60 | .fendfbegin = (10 << 8) | 4, | ||
61 | .lsynclen = 10, | ||
62 | .lendlbegin = (100 << 8) | 4, | ||
63 | .pixclk = 6, | ||
64 | }, | ||
65 | { /* custom 3.7" flexible on PET or steel */ | ||
66 | .w = 320, | ||
67 | .h = 240, | ||
68 | .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)), | ||
69 | .gdcfg = 3, | ||
70 | .lutfmt = (4 | (1 << 7)), | ||
71 | .fsynclen = 0, | ||
72 | .fendfbegin = (80 << 8) | 4, | ||
73 | .lsynclen = 10, | ||
74 | .lendlbegin = (80 << 8) | 20, | ||
75 | .pixclk = 14, | ||
76 | }, | ||
77 | { /* standard 9.7" on TFT backplane */ | ||
78 | .w = 1200, | ||
79 | .h = 825, | ||
80 | .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)), | ||
81 | .gdcfg = 2, | ||
82 | .lutfmt = (4 | (1 << 7)), | ||
83 | .fsynclen = 0, | ||
84 | .fendfbegin = (4 << 8) | 4, | ||
85 | .lsynclen = 4, | ||
86 | .lendlbegin = (60 << 8) | 10, | ||
87 | .pixclk = 3, | ||
88 | }, | ||
89 | }; | ||
90 | |||
37 | #define DPY_W 800 | 91 | #define DPY_W 800 |
38 | #define DPY_H 600 | 92 | #define DPY_H 600 |
39 | 93 | ||
@@ -62,30 +116,30 @@ static struct fb_var_screeninfo broadsheetfb_var __devinitdata = { | |||
62 | }; | 116 | }; |
63 | 117 | ||
64 | /* main broadsheetfb functions */ | 118 | /* main broadsheetfb functions */ |
65 | static void broadsheet_issue_data(struct broadsheetfb_par *par, u16 data) | 119 | static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data) |
66 | { | 120 | { |
67 | par->board->set_ctl(par, BS_WR, 0); | 121 | par->board->set_ctl(par, BS_WR, 0); |
68 | par->board->set_hdb(par, data); | 122 | par->board->set_hdb(par, data); |
69 | par->board->set_ctl(par, BS_WR, 1); | 123 | par->board->set_ctl(par, BS_WR, 1); |
70 | } | 124 | } |
71 | 125 | ||
72 | static void broadsheet_issue_cmd(struct broadsheetfb_par *par, u16 data) | 126 | static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data) |
73 | { | 127 | { |
74 | par->board->set_ctl(par, BS_DC, 0); | 128 | par->board->set_ctl(par, BS_DC, 0); |
75 | broadsheet_issue_data(par, data); | 129 | broadsheet_gpio_issue_data(par, data); |
76 | } | 130 | } |
77 | 131 | ||
78 | static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) | 132 | static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data) |
79 | { | 133 | { |
80 | par->board->wait_for_rdy(par); | 134 | par->board->wait_for_rdy(par); |
81 | 135 | ||
82 | par->board->set_ctl(par, BS_CS, 0); | 136 | par->board->set_ctl(par, BS_CS, 0); |
83 | broadsheet_issue_cmd(par, data); | 137 | broadsheet_gpio_issue_cmd(par, data); |
84 | par->board->set_ctl(par, BS_DC, 1); | 138 | par->board->set_ctl(par, BS_DC, 1); |
85 | par->board->set_ctl(par, BS_CS, 1); | 139 | par->board->set_ctl(par, BS_CS, 1); |
86 | } | 140 | } |
87 | 141 | ||
88 | static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, | 142 | static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, |
89 | int argc, u16 *argv) | 143 | int argc, u16 *argv) |
90 | { | 144 | { |
91 | int i; | 145 | int i; |
@@ -93,15 +147,43 @@ static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, | |||
93 | par->board->wait_for_rdy(par); | 147 | par->board->wait_for_rdy(par); |
94 | 148 | ||
95 | par->board->set_ctl(par, BS_CS, 0); | 149 | par->board->set_ctl(par, BS_CS, 0); |
96 | broadsheet_issue_cmd(par, cmd); | 150 | broadsheet_gpio_issue_cmd(par, cmd); |
97 | par->board->set_ctl(par, BS_DC, 1); | 151 | par->board->set_ctl(par, BS_DC, 1); |
98 | 152 | ||
99 | for (i = 0; i < argc; i++) | 153 | for (i = 0; i < argc; i++) |
100 | broadsheet_issue_data(par, argv[i]); | 154 | broadsheet_gpio_issue_data(par, argv[i]); |
101 | par->board->set_ctl(par, BS_CS, 1); | 155 | par->board->set_ctl(par, BS_CS, 1); |
102 | } | 156 | } |
103 | 157 | ||
104 | static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, | 158 | static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, |
159 | int argc, u16 *argv) | ||
160 | { | ||
161 | int i; | ||
162 | |||
163 | par->board->mmio_write(par, BS_MMIO_CMD, cmd); | ||
164 | |||
165 | for (i = 0; i < argc; i++) | ||
166 | par->board->mmio_write(par, BS_MMIO_DATA, argv[i]); | ||
167 | } | ||
168 | |||
169 | static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) | ||
170 | { | ||
171 | if (par->board->mmio_write) | ||
172 | par->board->mmio_write(par, BS_MMIO_CMD, data); | ||
173 | else | ||
174 | broadsheet_gpio_send_command(par, data); | ||
175 | } | ||
176 | |||
177 | static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, | ||
178 | int argc, u16 *argv) | ||
179 | { | ||
180 | if (par->board->mmio_write) | ||
181 | broadsheet_mmio_send_cmdargs(par, cmd, argc, argv); | ||
182 | else | ||
183 | broadsheet_gpio_send_cmdargs(par, cmd, argc, argv); | ||
184 | } | ||
185 | |||
186 | static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size, | ||
105 | u16 *data) | 187 | u16 *data) |
106 | { | 188 | { |
107 | int i; | 189 | int i; |
@@ -121,7 +203,30 @@ static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, | |||
121 | par->board->set_ctl(par, BS_CS, 1); | 203 | par->board->set_ctl(par, BS_CS, 1); |
122 | } | 204 | } |
123 | 205 | ||
124 | static u16 broadsheet_get_data(struct broadsheetfb_par *par) | 206 | static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size, |
207 | u16 *data) | ||
208 | { | ||
209 | int i; | ||
210 | u16 tmp; | ||
211 | |||
212 | for (i = 0; i < size; i++) { | ||
213 | tmp = (data[i] & 0x0F) << 4; | ||
214 | tmp |= (data[i] & 0x0F00) << 4; | ||
215 | par->board->mmio_write(par, BS_MMIO_DATA, tmp); | ||
216 | } | ||
217 | |||
218 | } | ||
219 | |||
220 | static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, | ||
221 | u16 *data) | ||
222 | { | ||
223 | if (par->board->mmio_write) | ||
224 | broadsheet_mmio_burst_write(par, size, data); | ||
225 | else | ||
226 | broadsheet_gpio_burst_write(par, size, data); | ||
227 | } | ||
228 | |||
229 | static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par) | ||
125 | { | 230 | { |
126 | u16 res; | 231 | u16 res; |
127 | /* wait for ready to go hi. (lo is busy) */ | 232 | /* wait for ready to go hi. (lo is busy) */ |
@@ -141,7 +246,16 @@ static u16 broadsheet_get_data(struct broadsheetfb_par *par) | |||
141 | return res; | 246 | return res; |
142 | } | 247 | } |
143 | 248 | ||
144 | static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, | 249 | |
250 | static u16 broadsheet_get_data(struct broadsheetfb_par *par) | ||
251 | { | ||
252 | if (par->board->mmio_read) | ||
253 | return par->board->mmio_read(par); | ||
254 | else | ||
255 | return broadsheet_gpio_get_data(par); | ||
256 | } | ||
257 | |||
258 | static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg, | ||
145 | u16 data) | 259 | u16 data) |
146 | { | 260 | { |
147 | /* wait for ready to go hi. (lo is busy) */ | 261 | /* wait for ready to go hi. (lo is busy) */ |
@@ -150,44 +264,541 @@ static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, | |||
150 | /* cs lo, dc lo for cmd, we lo for each data, db as usual */ | 264 | /* cs lo, dc lo for cmd, we lo for each data, db as usual */ |
151 | par->board->set_ctl(par, BS_CS, 0); | 265 | par->board->set_ctl(par, BS_CS, 0); |
152 | 266 | ||
153 | broadsheet_issue_cmd(par, BS_CMD_WR_REG); | 267 | broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG); |
154 | 268 | ||
155 | par->board->set_ctl(par, BS_DC, 1); | 269 | par->board->set_ctl(par, BS_DC, 1); |
156 | 270 | ||
157 | broadsheet_issue_data(par, reg); | 271 | broadsheet_gpio_issue_data(par, reg); |
158 | broadsheet_issue_data(par, data); | 272 | broadsheet_gpio_issue_data(par, data); |
159 | 273 | ||
160 | par->board->set_ctl(par, BS_CS, 1); | 274 | par->board->set_ctl(par, BS_CS, 1); |
161 | } | 275 | } |
162 | 276 | ||
277 | static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg, | ||
278 | u16 data) | ||
279 | { | ||
280 | par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG); | ||
281 | par->board->mmio_write(par, BS_MMIO_DATA, reg); | ||
282 | par->board->mmio_write(par, BS_MMIO_DATA, data); | ||
283 | |||
284 | } | ||
285 | |||
286 | static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, | ||
287 | u16 data) | ||
288 | { | ||
289 | if (par->board->mmio_write) | ||
290 | broadsheet_mmio_write_reg(par, reg, data); | ||
291 | else | ||
292 | broadsheet_gpio_write_reg(par, reg, data); | ||
293 | } | ||
294 | |||
295 | static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg, | ||
296 | u32 data) | ||
297 | { | ||
298 | broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF); | ||
299 | broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF); | ||
300 | } | ||
301 | |||
302 | |||
163 | static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg) | 303 | static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg) |
164 | { | 304 | { |
165 | broadsheet_send_command(par, reg); | 305 | broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, ®); |
166 | msleep(100); | 306 | par->board->wait_for_rdy(par); |
167 | return broadsheet_get_data(par); | 307 | return broadsheet_get_data(par); |
168 | } | 308 | } |
169 | 309 | ||
310 | /* functions for waveform manipulation */ | ||
311 | static int is_broadsheet_pll_locked(struct broadsheetfb_par *par) | ||
312 | { | ||
313 | return broadsheet_read_reg(par, 0x000A) & 0x0001; | ||
314 | } | ||
315 | |||
316 | static int broadsheet_setup_plls(struct broadsheetfb_par *par) | ||
317 | { | ||
318 | int retry_count = 0; | ||
319 | u16 tmp; | ||
320 | |||
321 | /* disable arral saemipu mode */ | ||
322 | broadsheet_write_reg(par, 0x0006, 0x0000); | ||
323 | |||
324 | broadsheet_write_reg(par, 0x0010, 0x0004); | ||
325 | broadsheet_write_reg(par, 0x0012, 0x5949); | ||
326 | broadsheet_write_reg(par, 0x0014, 0x0040); | ||
327 | broadsheet_write_reg(par, 0x0016, 0x0000); | ||
328 | |||
329 | do { | ||
330 | if (retry_count++ > 100) | ||
331 | return -ETIMEDOUT; | ||
332 | mdelay(1); | ||
333 | } while (!is_broadsheet_pll_locked(par)); | ||
334 | |||
335 | tmp = broadsheet_read_reg(par, 0x0006); | ||
336 | tmp &= ~0x1; | ||
337 | broadsheet_write_reg(par, 0x0006, tmp); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int broadsheet_setup_spi(struct broadsheetfb_par *par) | ||
343 | { | ||
344 | |||
345 | broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); | ||
346 | broadsheet_write_reg(par, 0x0208, 0x0001); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static int broadsheet_setup_spiflash(struct broadsheetfb_par *par, | ||
352 | u16 *orig_sfmcd) | ||
353 | { | ||
354 | |||
355 | *orig_sfmcd = broadsheet_read_reg(par, 0x0204); | ||
356 | broadsheet_write_reg(par, 0x0208, 0); | ||
357 | broadsheet_write_reg(par, 0x0204, 0); | ||
358 | broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par, | ||
364 | u16 reg, int bitnum, int val, | ||
365 | int timeout) | ||
366 | { | ||
367 | u16 tmp; | ||
368 | |||
369 | do { | ||
370 | tmp = broadsheet_read_reg(par, reg); | ||
371 | if (((tmp >> bitnum) & 1) == val) | ||
372 | return 0; | ||
373 | mdelay(1); | ||
374 | } while (timeout--); | ||
375 | |||
376 | return -ETIMEDOUT; | ||
377 | } | ||
378 | |||
379 | static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data) | ||
380 | { | ||
381 | broadsheet_write_reg(par, 0x0202, (data | 0x100)); | ||
382 | |||
383 | return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); | ||
384 | } | ||
385 | |||
386 | static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data) | ||
387 | { | ||
388 | int err; | ||
389 | u16 tmp; | ||
390 | |||
391 | broadsheet_write_reg(par, 0x0202, 0); | ||
392 | |||
393 | err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); | ||
394 | if (err) | ||
395 | return err; | ||
396 | |||
397 | tmp = broadsheet_read_reg(par, 0x200); | ||
398 | |||
399 | *data = tmp & 0xFF; | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par, | ||
405 | int timeout) | ||
406 | { | ||
407 | u8 tmp; | ||
408 | int err; | ||
409 | |||
410 | do { | ||
411 | broadsheet_write_reg(par, 0x0208, 1); | ||
412 | |||
413 | err = broadsheet_spiflash_write_byte(par, 0x05); | ||
414 | if (err) | ||
415 | goto failout; | ||
416 | |||
417 | err = broadsheet_spiflash_read_byte(par, &tmp); | ||
418 | if (err) | ||
419 | goto failout; | ||
420 | |||
421 | broadsheet_write_reg(par, 0x0208, 0); | ||
422 | |||
423 | if (!(tmp & 0x1)) | ||
424 | return 0; | ||
425 | |||
426 | mdelay(5); | ||
427 | } while (timeout--); | ||
428 | |||
429 | dev_err(par->info->device, "Timed out waiting for spiflash status\n"); | ||
430 | return -ETIMEDOUT; | ||
431 | |||
432 | failout: | ||
433 | broadsheet_write_reg(par, 0x0208, 0); | ||
434 | return err; | ||
435 | } | ||
436 | |||
437 | static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par, | ||
438 | u8 op, u32 addr) | ||
439 | { | ||
440 | int i; | ||
441 | u8 tmp; | ||
442 | int err; | ||
443 | |||
444 | broadsheet_write_reg(par, 0x0208, 1); | ||
445 | |||
446 | err = broadsheet_spiflash_write_byte(par, op); | ||
447 | if (err) | ||
448 | return err; | ||
449 | |||
450 | for (i = 2; i >= 0; i--) { | ||
451 | tmp = ((addr >> (i * 8)) & 0xFF); | ||
452 | err = broadsheet_spiflash_write_byte(par, tmp); | ||
453 | if (err) | ||
454 | return err; | ||
455 | } | ||
456 | |||
457 | return err; | ||
458 | } | ||
459 | |||
460 | static int broadsheet_verify_spiflash(struct broadsheetfb_par *par, | ||
461 | int *flash_type) | ||
462 | { | ||
463 | int err = 0; | ||
464 | u8 sig; | ||
465 | |||
466 | err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000); | ||
467 | if (err) | ||
468 | goto failout; | ||
469 | |||
470 | err = broadsheet_spiflash_read_byte(par, &sig); | ||
471 | if (err) | ||
472 | goto failout; | ||
473 | |||
474 | if ((sig != 0x10) && (sig != 0x11)) { | ||
475 | dev_err(par->info->device, "Unexpected flash type\n"); | ||
476 | err = -EINVAL; | ||
477 | goto failout; | ||
478 | } | ||
479 | |||
480 | *flash_type = sig; | ||
481 | |||
482 | failout: | ||
483 | broadsheet_write_reg(par, 0x0208, 0); | ||
484 | return err; | ||
485 | } | ||
486 | |||
487 | static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par, | ||
488 | u16 *initial_sfmcd, int *flash_type) | ||
489 | |||
490 | { | ||
491 | int err; | ||
492 | |||
493 | err = broadsheet_setup_plls(par); | ||
494 | if (err) | ||
495 | return err; | ||
496 | |||
497 | broadsheet_write_reg(par, 0x0106, 0x0203); | ||
498 | |||
499 | err = broadsheet_setup_spi(par); | ||
500 | if (err) | ||
501 | return err; | ||
502 | |||
503 | err = broadsheet_setup_spiflash(par, initial_sfmcd); | ||
504 | if (err) | ||
505 | return err; | ||
506 | |||
507 | return broadsheet_verify_spiflash(par, flash_type); | ||
508 | } | ||
509 | |||
510 | static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par, | ||
511 | int mode) | ||
512 | { | ||
513 | int err; | ||
514 | |||
515 | broadsheet_write_reg(par, 0x0208, 1); | ||
516 | if (mode) | ||
517 | err = broadsheet_spiflash_write_byte(par, 0x06); | ||
518 | else | ||
519 | err = broadsheet_spiflash_write_byte(par, 0x04); | ||
520 | |||
521 | broadsheet_write_reg(par, 0x0208, 0); | ||
522 | return err; | ||
523 | } | ||
524 | |||
525 | static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par, | ||
526 | int addr) | ||
527 | { | ||
528 | int err; | ||
529 | |||
530 | broadsheet_spiflash_write_control(par, 1); | ||
531 | |||
532 | err = broadsheet_spiflash_op_on_address(par, 0xD8, addr); | ||
533 | |||
534 | broadsheet_write_reg(par, 0x0208, 0); | ||
535 | |||
536 | if (err) | ||
537 | return err; | ||
538 | |||
539 | err = broadsheet_spiflash_wait_for_status(par, 1000); | ||
540 | |||
541 | return err; | ||
542 | } | ||
543 | |||
544 | static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par, | ||
545 | int addr, int size, char *data) | ||
546 | { | ||
547 | int err; | ||
548 | int i; | ||
549 | |||
550 | err = broadsheet_spiflash_op_on_address(par, 0x03, addr); | ||
551 | if (err) | ||
552 | goto failout; | ||
553 | |||
554 | for (i = 0; i < size; i++) { | ||
555 | err = broadsheet_spiflash_read_byte(par, &data[i]); | ||
556 | if (err) | ||
557 | goto failout; | ||
558 | } | ||
559 | |||
560 | failout: | ||
561 | broadsheet_write_reg(par, 0x0208, 0); | ||
562 | return err; | ||
563 | } | ||
564 | |||
565 | #define BS_SPIFLASH_PAGE_SIZE 256 | ||
566 | static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par, | ||
567 | int addr, const char *data) | ||
568 | { | ||
569 | int err; | ||
570 | int i; | ||
571 | |||
572 | broadsheet_spiflash_write_control(par, 1); | ||
573 | |||
574 | err = broadsheet_spiflash_op_on_address(par, 0x02, addr); | ||
575 | if (err) | ||
576 | goto failout; | ||
577 | |||
578 | for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) { | ||
579 | err = broadsheet_spiflash_write_byte(par, data[i]); | ||
580 | if (err) | ||
581 | goto failout; | ||
582 | } | ||
583 | |||
584 | broadsheet_write_reg(par, 0x0208, 0); | ||
585 | |||
586 | err = broadsheet_spiflash_wait_for_status(par, 100); | ||
587 | |||
588 | failout: | ||
589 | return err; | ||
590 | } | ||
591 | |||
592 | static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par, | ||
593 | int addr, const char *data, int sector_size) | ||
594 | { | ||
595 | int i; | ||
596 | int err; | ||
597 | |||
598 | for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) { | ||
599 | err = broadsheet_spiflash_write_page(par, addr + i, &data[i]); | ||
600 | if (err) | ||
601 | return err; | ||
602 | } | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | /* | ||
607 | * The caller must guarantee that the data to be rewritten is entirely | ||
608 | * contained within this sector. That is, data_start_addr + data_len | ||
609 | * must be less than sector_start_addr + sector_size. | ||
610 | */ | ||
611 | static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par, | ||
612 | int sector_size, int data_start_addr, | ||
613 | int data_len, const char *data) | ||
614 | { | ||
615 | int err; | ||
616 | char *sector_buffer; | ||
617 | int tail_start_addr; | ||
618 | int start_sector_addr; | ||
619 | |||
620 | sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL); | ||
621 | if (!sector_buffer) | ||
622 | return -ENOMEM; | ||
623 | |||
624 | /* the start address of the sector is the 0th byte of that sector */ | ||
625 | start_sector_addr = (data_start_addr / sector_size) * sector_size; | ||
626 | |||
627 | /* | ||
628 | * check if there is head data that we need to readback into our sector | ||
629 | * buffer first | ||
630 | */ | ||
631 | if (data_start_addr != start_sector_addr) { | ||
632 | /* | ||
633 | * we need to read every byte up till the start address of our | ||
634 | * data and we put it into our sector buffer. | ||
635 | */ | ||
636 | err = broadsheet_spiflash_read_range(par, start_sector_addr, | ||
637 | data_start_addr, sector_buffer); | ||
638 | if (err) | ||
639 | return err; | ||
640 | } | ||
641 | |||
642 | /* now we copy our data into the right place in the sector buffer */ | ||
643 | memcpy(sector_buffer + data_start_addr, data, data_len); | ||
644 | |||
645 | /* | ||
646 | * now we check if there is a tail section of the sector that we need to | ||
647 | * readback. | ||
648 | */ | ||
649 | tail_start_addr = (data_start_addr + data_len) % sector_size; | ||
650 | |||
651 | if (tail_start_addr) { | ||
652 | int tail_len; | ||
653 | |||
654 | tail_len = sector_size - tail_start_addr; | ||
655 | |||
656 | /* now we read this tail into our sector buffer */ | ||
657 | err = broadsheet_spiflash_read_range(par, tail_start_addr, | ||
658 | tail_len, sector_buffer + tail_start_addr); | ||
659 | if (err) | ||
660 | return err; | ||
661 | } | ||
662 | |||
663 | /* if we got here we have the full sector that we want to rewrite. */ | ||
664 | |||
665 | /* first erase the sector */ | ||
666 | err = broadsheet_spiflash_erase_sector(par, start_sector_addr); | ||
667 | if (err) | ||
668 | return err; | ||
669 | |||
670 | /* now write it */ | ||
671 | err = broadsheet_spiflash_write_sector(par, start_sector_addr, | ||
672 | sector_buffer, sector_size); | ||
673 | return err; | ||
674 | } | ||
675 | |||
676 | static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr, | ||
677 | const u8 *wfm, int bytecount, int flash_type) | ||
678 | { | ||
679 | int sector_size; | ||
680 | int err; | ||
681 | int cur_addr; | ||
682 | int writecount; | ||
683 | int maxlen; | ||
684 | int offset = 0; | ||
685 | |||
686 | switch (flash_type) { | ||
687 | case 0x10: | ||
688 | sector_size = 32*1024; | ||
689 | break; | ||
690 | case 0x11: | ||
691 | default: | ||
692 | sector_size = 64*1024; | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | while (bytecount) { | ||
697 | cur_addr = wfm_addr + offset; | ||
698 | maxlen = roundup(cur_addr, sector_size) - cur_addr; | ||
699 | writecount = min(bytecount, maxlen); | ||
700 | |||
701 | err = broadsheet_spiflash_rewrite_sector(par, sector_size, | ||
702 | cur_addr, writecount, wfm + offset); | ||
703 | if (err) | ||
704 | return err; | ||
705 | |||
706 | offset += writecount; | ||
707 | bytecount -= writecount; | ||
708 | } | ||
709 | |||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par, | ||
714 | const u8 *wfm, size_t wfm_size) | ||
715 | { | ||
716 | int err = 0; | ||
717 | u16 initial_sfmcd = 0; | ||
718 | int flash_type = 0; | ||
719 | |||
720 | err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type); | ||
721 | if (err) | ||
722 | goto failout; | ||
723 | |||
724 | err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type); | ||
725 | |||
726 | failout: | ||
727 | broadsheet_write_reg(par, 0x0204, initial_sfmcd); | ||
728 | return err; | ||
729 | } | ||
730 | |||
731 | static ssize_t broadsheet_loadstore_waveform(struct device *dev, | ||
732 | struct device_attribute *attr, | ||
733 | const char *buf, size_t len) | ||
734 | { | ||
735 | int err; | ||
736 | struct fb_info *info = dev_get_drvdata(dev); | ||
737 | struct broadsheetfb_par *par = info->par; | ||
738 | const struct firmware *fw_entry; | ||
739 | |||
740 | if (len < 1) | ||
741 | return -EINVAL; | ||
742 | |||
743 | err = request_firmware(&fw_entry, "broadsheet.wbf", dev); | ||
744 | if (err < 0) { | ||
745 | dev_err(dev, "Failed to get broadsheet waveform\n"); | ||
746 | goto err_failed; | ||
747 | } | ||
748 | |||
749 | /* try to enforce reasonable min max on waveform */ | ||
750 | if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) { | ||
751 | dev_err(dev, "Invalid waveform\n"); | ||
752 | err = -EINVAL; | ||
753 | goto err_failed; | ||
754 | } | ||
755 | |||
756 | mutex_lock(&(par->io_lock)); | ||
757 | err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data, | ||
758 | fw_entry->size); | ||
759 | |||
760 | mutex_unlock(&(par->io_lock)); | ||
761 | if (err < 0) { | ||
762 | dev_err(dev, "Failed to store broadsheet waveform\n"); | ||
763 | goto err_failed; | ||
764 | } | ||
765 | |||
766 | dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size); | ||
767 | |||
768 | return len; | ||
769 | |||
770 | err_failed: | ||
771 | return err; | ||
772 | } | ||
773 | static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL, | ||
774 | broadsheet_loadstore_waveform); | ||
775 | |||
776 | /* upper level functions that manipulate the display and other stuff */ | ||
170 | static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) | 777 | static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) |
171 | { | 778 | { |
172 | u16 args[5]; | 779 | u16 args[5]; |
173 | 780 | int xres = par->info->var.xres; | |
174 | args[0] = DPY_W; | 781 | int yres = par->info->var.yres; |
175 | args[1] = DPY_H; | 782 | |
176 | args[2] = (100 | (1 << 8) | (1 << 9)); /* sdcfg */ | 783 | args[0] = panel_table[par->panel_index].w; |
177 | args[3] = 2; /* gdrv cfg */ | 784 | args[1] = panel_table[par->panel_index].h; |
178 | args[4] = (4 | (1 << 7)); /* lut index format */ | 785 | args[2] = panel_table[par->panel_index].sdcfg; |
786 | args[3] = panel_table[par->panel_index].gdcfg; | ||
787 | args[4] = panel_table[par->panel_index].lutfmt; | ||
179 | broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); | 788 | broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); |
180 | 789 | ||
181 | /* did the controller really set it? */ | 790 | /* did the controller really set it? */ |
182 | broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); | 791 | broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); |
183 | 792 | ||
184 | args[0] = 4; /* fsync len */ | 793 | args[0] = panel_table[par->panel_index].fsynclen; |
185 | args[1] = (10 << 8) | 4; /* fend/fbegin len */ | 794 | args[1] = panel_table[par->panel_index].fendfbegin; |
186 | args[2] = 10; /* line sync len */ | 795 | args[2] = panel_table[par->panel_index].lsynclen; |
187 | args[3] = (100 << 8) | 4; /* line end/begin len */ | 796 | args[3] = panel_table[par->panel_index].lendlbegin; |
188 | args[4] = 6; /* pixel clock cfg */ | 797 | args[4] = panel_table[par->panel_index].pixclk; |
189 | broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); | 798 | broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); |
190 | 799 | ||
800 | broadsheet_write_reg32(par, 0x310, xres*yres*2); | ||
801 | |||
191 | /* setup waveform */ | 802 | /* setup waveform */ |
192 | args[0] = 0x886; | 803 | args[0] = 0x886; |
193 | args[1] = 0; | 804 | args[1] = 0; |
@@ -207,8 +818,9 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) | |||
207 | args[0] = 0x154; | 818 | args[0] = 0x154; |
208 | broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); | 819 | broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); |
209 | 820 | ||
210 | broadsheet_burst_write(par, DPY_W*DPY_H/2, | 821 | broadsheet_burst_write(par, (panel_table[par->panel_index].w * |
211 | (u16 *) par->info->screen_base); | 822 | panel_table[par->panel_index].h)/2, |
823 | (u16 *) par->info->screen_base); | ||
212 | 824 | ||
213 | broadsheet_send_command(par, BS_CMD_LD_IMG_END); | 825 | broadsheet_send_command(par, BS_CMD_LD_IMG_END); |
214 | 826 | ||
@@ -222,6 +834,21 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) | |||
222 | par->board->wait_for_rdy(par); | 834 | par->board->wait_for_rdy(par); |
223 | } | 835 | } |
224 | 836 | ||
837 | static void __devinit broadsheet_identify(struct broadsheetfb_par *par) | ||
838 | { | ||
839 | u16 rev, prc; | ||
840 | struct device *dev = par->info->device; | ||
841 | |||
842 | rev = broadsheet_read_reg(par, BS_REG_REV); | ||
843 | prc = broadsheet_read_reg(par, BS_REG_PRC); | ||
844 | dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc); | ||
845 | |||
846 | if (prc != 0x0047) | ||
847 | dev_warn(dev, "Unrecognized Broadsheet Product Code\n"); | ||
848 | if (rev != 0x0100) | ||
849 | dev_warn(dev, "Unrecognized Broadsheet Revision\n"); | ||
850 | } | ||
851 | |||
225 | static void __devinit broadsheet_init(struct broadsheetfb_par *par) | 852 | static void __devinit broadsheet_init(struct broadsheetfb_par *par) |
226 | { | 853 | { |
227 | broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); | 854 | broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); |
@@ -236,6 +863,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, | |||
236 | u16 args[5]; | 863 | u16 args[5]; |
237 | unsigned char *buf = (unsigned char *)par->info->screen_base; | 864 | unsigned char *buf = (unsigned char *)par->info->screen_base; |
238 | 865 | ||
866 | mutex_lock(&(par->io_lock)); | ||
239 | /* y1 must be a multiple of 4 so drop the lower bits */ | 867 | /* y1 must be a multiple of 4 so drop the lower bits */ |
240 | y1 &= 0xFFFC; | 868 | y1 &= 0xFFFC; |
241 | /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ | 869 | /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ |
@@ -265,6 +893,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, | |||
265 | broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); | 893 | broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); |
266 | 894 | ||
267 | par->board->wait_for_rdy(par); | 895 | par->board->wait_for_rdy(par); |
896 | mutex_unlock(&(par->io_lock)); | ||
268 | 897 | ||
269 | } | 898 | } |
270 | 899 | ||
@@ -272,13 +901,15 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) | |||
272 | { | 901 | { |
273 | u16 args[5]; | 902 | u16 args[5]; |
274 | 903 | ||
904 | mutex_lock(&(par->io_lock)); | ||
275 | args[0] = 0x3 << 4; | 905 | args[0] = 0x3 << 4; |
276 | broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); | 906 | broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); |
277 | 907 | ||
278 | args[0] = 0x154; | 908 | args[0] = 0x154; |
279 | broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); | 909 | broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); |
280 | broadsheet_burst_write(par, DPY_W*DPY_H/2, | 910 | broadsheet_burst_write(par, (panel_table[par->panel_index].w * |
281 | (u16 *) par->info->screen_base); | 911 | panel_table[par->panel_index].h)/2, |
912 | (u16 *) par->info->screen_base); | ||
282 | 913 | ||
283 | broadsheet_send_command(par, BS_CMD_LD_IMG_END); | 914 | broadsheet_send_command(par, BS_CMD_LD_IMG_END); |
284 | 915 | ||
@@ -290,7 +921,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) | |||
290 | broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); | 921 | broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); |
291 | 922 | ||
292 | par->board->wait_for_rdy(par); | 923 | par->board->wait_for_rdy(par); |
293 | 924 | mutex_unlock(&(par->io_lock)); | |
294 | } | 925 | } |
295 | 926 | ||
296 | /* this is called back from the deferred io workqueue */ | 927 | /* this is called back from the deferred io workqueue */ |
@@ -436,6 +1067,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) | |||
436 | unsigned char *videomemory; | 1067 | unsigned char *videomemory; |
437 | struct broadsheetfb_par *par; | 1068 | struct broadsheetfb_par *par; |
438 | int i; | 1069 | int i; |
1070 | int dpyw, dpyh; | ||
1071 | int panel_index; | ||
439 | 1072 | ||
440 | /* pick up board specific routines */ | 1073 | /* pick up board specific routines */ |
441 | board = dev->dev.platform_data; | 1074 | board = dev->dev.platform_data; |
@@ -450,7 +1083,24 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) | |||
450 | if (!info) | 1083 | if (!info) |
451 | goto err; | 1084 | goto err; |
452 | 1085 | ||
453 | videomemorysize = (DPY_W*DPY_H); | 1086 | switch (board->get_panel_type()) { |
1087 | case 37: | ||
1088 | panel_index = 1; | ||
1089 | break; | ||
1090 | case 97: | ||
1091 | panel_index = 2; | ||
1092 | break; | ||
1093 | case 6: | ||
1094 | default: | ||
1095 | panel_index = 0; | ||
1096 | break; | ||
1097 | } | ||
1098 | |||
1099 | dpyw = panel_table[panel_index].w; | ||
1100 | dpyh = panel_table[panel_index].h; | ||
1101 | |||
1102 | videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE); | ||
1103 | |||
454 | videomemory = vmalloc(videomemorysize); | 1104 | videomemory = vmalloc(videomemorysize); |
455 | if (!videomemory) | 1105 | if (!videomemory) |
456 | goto err_fb_rel; | 1106 | goto err_fb_rel; |
@@ -460,16 +1110,25 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) | |||
460 | info->screen_base = (char *)videomemory; | 1110 | info->screen_base = (char *)videomemory; |
461 | info->fbops = &broadsheetfb_ops; | 1111 | info->fbops = &broadsheetfb_ops; |
462 | 1112 | ||
1113 | broadsheetfb_var.xres = dpyw; | ||
1114 | broadsheetfb_var.yres = dpyh; | ||
1115 | broadsheetfb_var.xres_virtual = dpyw; | ||
1116 | broadsheetfb_var.yres_virtual = dpyh; | ||
463 | info->var = broadsheetfb_var; | 1117 | info->var = broadsheetfb_var; |
1118 | |||
1119 | broadsheetfb_fix.line_length = dpyw; | ||
464 | info->fix = broadsheetfb_fix; | 1120 | info->fix = broadsheetfb_fix; |
465 | info->fix.smem_len = videomemorysize; | 1121 | info->fix.smem_len = videomemorysize; |
466 | par = info->par; | 1122 | par = info->par; |
1123 | par->panel_index = panel_index; | ||
467 | par->info = info; | 1124 | par->info = info; |
468 | par->board = board; | 1125 | par->board = board; |
469 | par->write_reg = broadsheet_write_reg; | 1126 | par->write_reg = broadsheet_write_reg; |
470 | par->read_reg = broadsheet_read_reg; | 1127 | par->read_reg = broadsheet_read_reg; |
471 | init_waitqueue_head(&par->waitq); | 1128 | init_waitqueue_head(&par->waitq); |
472 | 1129 | ||
1130 | mutex_init(&par->io_lock); | ||
1131 | |||
473 | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; | 1132 | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; |
474 | 1133 | ||
475 | info->fbdefio = &broadsheetfb_defio; | 1134 | info->fbdefio = &broadsheetfb_defio; |
@@ -496,13 +1155,20 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) | |||
496 | if (retval < 0) | 1155 | if (retval < 0) |
497 | goto err_free_irq; | 1156 | goto err_free_irq; |
498 | 1157 | ||
1158 | broadsheet_identify(par); | ||
1159 | |||
499 | broadsheet_init(par); | 1160 | broadsheet_init(par); |
500 | 1161 | ||
501 | retval = register_framebuffer(info); | 1162 | retval = register_framebuffer(info); |
502 | if (retval < 0) | 1163 | if (retval < 0) |
503 | goto err_free_irq; | 1164 | goto err_free_irq; |
1165 | |||
504 | platform_set_drvdata(dev, info); | 1166 | platform_set_drvdata(dev, info); |
505 | 1167 | ||
1168 | retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform); | ||
1169 | if (retval < 0) | ||
1170 | goto err_unreg_fb; | ||
1171 | |||
506 | printk(KERN_INFO | 1172 | printk(KERN_INFO |
507 | "fb%d: Broadsheet frame buffer, using %dK of video memory\n", | 1173 | "fb%d: Broadsheet frame buffer, using %dK of video memory\n", |
508 | info->node, videomemorysize >> 10); | 1174 | info->node, videomemorysize >> 10); |
@@ -510,6 +1176,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) | |||
510 | 1176 | ||
511 | return 0; | 1177 | return 0; |
512 | 1178 | ||
1179 | err_unreg_fb: | ||
1180 | unregister_framebuffer(info); | ||
513 | err_free_irq: | 1181 | err_free_irq: |
514 | board->cleanup(par); | 1182 | board->cleanup(par); |
515 | err_cmap: | 1183 | err_cmap: |
@@ -530,6 +1198,8 @@ static int __devexit broadsheetfb_remove(struct platform_device *dev) | |||
530 | 1198 | ||
531 | if (info) { | 1199 | if (info) { |
532 | struct broadsheetfb_par *par = info->par; | 1200 | struct broadsheetfb_par *par = info->par; |
1201 | |||
1202 | device_remove_file(info->dev, &dev_attr_loadstore_waveform); | ||
533 | unregister_framebuffer(info); | 1203 | unregister_framebuffer(info); |
534 | fb_deferred_io_cleanup(info); | 1204 | fb_deferred_io_cleanup(info); |
535 | par->board->cleanup(par); | 1205 | par->board->cleanup(par); |
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 108b89e09a80..5eb61b5adfe8 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c | |||
@@ -287,7 +287,7 @@ static struct fb_ops cobalt_lcd_fbops = { | |||
287 | .fb_cursor = cobalt_lcdfb_cursor, | 287 | .fb_cursor = cobalt_lcdfb_cursor, |
288 | }; | 288 | }; |
289 | 289 | ||
290 | static int __init cobalt_lcdfb_probe(struct platform_device *dev) | 290 | static int __devinit cobalt_lcdfb_probe(struct platform_device *dev) |
291 | { | 291 | { |
292 | struct fb_info *info; | 292 | struct fb_info *info; |
293 | struct resource *res; | 293 | struct resource *res; |
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index d25df51bb0d2..581d2dbf675a 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
@@ -210,7 +210,7 @@ static int __init efifb_setup(char *options) | |||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
212 | 212 | ||
213 | static int __init efifb_probe(struct platform_device *dev) | 213 | static int __devinit efifb_probe(struct platform_device *dev) |
214 | { | 214 | { |
215 | struct fb_info *info; | 215 | struct fb_info *info; |
216 | int err; | 216 | int err; |
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 2735b79e52a1..6d755bb3a2bc 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c | |||
@@ -602,7 +602,7 @@ static int epson1355fb_remove(struct platform_device *dev) | |||
602 | return 0; | 602 | return 0; |
603 | } | 603 | } |
604 | 604 | ||
605 | int __init epson1355fb_probe(struct platform_device *dev) | 605 | int __devinit epson1355fb_probe(struct platform_device *dev) |
606 | { | 606 | { |
607 | struct epson1355_par *default_par; | 607 | struct epson1355_par *default_par; |
608 | struct fb_info *info; | 608 | struct fb_info *info; |
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 695fa013fe7e..5643a35c1746 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c | |||
@@ -1128,7 +1128,7 @@ static int __init gbefb_setup(char *options) | |||
1128 | return 0; | 1128 | return 0; |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | static int __init gbefb_probe(struct platform_device *p_dev) | 1131 | static int __devinit gbefb_probe(struct platform_device *p_dev) |
1132 | { | 1132 | { |
1133 | int i, ret = 0; | 1133 | int i, ret = 0; |
1134 | struct fb_info *info; | 1134 | struct fb_info *info; |
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index 0129c044f6d6..db9b785b56eb 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c | |||
@@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = { | |||
551 | * Initialization | 551 | * Initialization |
552 | */ | 552 | */ |
553 | 553 | ||
554 | static int __init hgafb_probe(struct platform_device *pdev) | 554 | static int __devinit hgafb_probe(struct platform_device *pdev) |
555 | { | 555 | { |
556 | struct fb_info *info; | 556 | struct fb_info *info; |
557 | 557 | ||
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 73c83a8de2d3..bf78779199c6 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c | |||
@@ -325,7 +325,7 @@ static struct fb_ops hitfb_ops = { | |||
325 | .fb_imageblit = cfb_imageblit, | 325 | .fb_imageblit = cfb_imageblit, |
326 | }; | 326 | }; |
327 | 327 | ||
328 | static int __init hitfb_probe(struct platform_device *dev) | 328 | static int __devinit hitfb_probe(struct platform_device *dev) |
329 | { | 329 | { |
330 | unsigned short lcdclor, ldr3, ldvndr; | 330 | unsigned short lcdclor, ldr3, ldvndr; |
331 | struct fb_info *info; | 331 | struct fb_info *info; |
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index fabb0c59a211..8280a58a0e55 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c | |||
@@ -31,15 +31,6 @@ | |||
31 | #define CARMINE_MEM_SIZE 0x8000000 | 31 | #define CARMINE_MEM_SIZE 0x8000000 |
32 | #define DRV_NAME "mb862xxfb" | 32 | #define DRV_NAME "mb862xxfb" |
33 | 33 | ||
34 | #if defined(CONFIG_LWMON5) | ||
35 | static struct mb862xx_gc_mode lwmon5_gc_mode = { | ||
36 | /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */ | ||
37 | { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 }, | ||
38 | /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */ | ||
39 | 16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2 | ||
40 | }; | ||
41 | #endif | ||
42 | |||
43 | #if defined(CONFIG_SOCRATES) | 34 | #if defined(CONFIG_SOCRATES) |
44 | static struct mb862xx_gc_mode socrates_gc_mode = { | 35 | static struct mb862xx_gc_mode socrates_gc_mode = { |
45 | /* Mode for Prime View PM070WL4 TFT LCD Panel */ | 36 | /* Mode for Prime View PM070WL4 TFT LCD Panel */ |
@@ -600,10 +591,6 @@ static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, | |||
600 | goto irqdisp; | 591 | goto irqdisp; |
601 | } | 592 | } |
602 | 593 | ||
603 | #if defined(CONFIG_LWMON5) | ||
604 | par->gc_mode = &lwmon5_gc_mode; | ||
605 | #endif | ||
606 | |||
607 | #if defined(CONFIG_SOCRATES) | 594 | #if defined(CONFIG_SOCRATES) |
608 | par->gc_mode = &socrates_gc_mode; | 595 | par->gc_mode = &socrates_gc_mode; |
609 | #endif | 596 | #endif |
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 0129f1bc3522..b895aae41630 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
@@ -893,7 +893,7 @@ const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var, | |||
893 | } | 893 | } |
894 | 894 | ||
895 | /** | 895 | /** |
896 | * fb_add_videomode: adds videomode entry to modelist | 896 | * fb_add_videomode - adds videomode entry to modelist |
897 | * @mode: videomode to add | 897 | * @mode: videomode to add |
898 | * @head: struct list_head of modelist | 898 | * @head: struct list_head of modelist |
899 | * | 899 | * |
@@ -928,7 +928,7 @@ int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head) | |||
928 | } | 928 | } |
929 | 929 | ||
930 | /** | 930 | /** |
931 | * fb_delete_videomode: removed videomode entry from modelist | 931 | * fb_delete_videomode - removed videomode entry from modelist |
932 | * @mode: videomode to remove | 932 | * @mode: videomode to remove |
933 | * @head: struct list_head of modelist | 933 | * @head: struct list_head of modelist |
934 | * | 934 | * |
@@ -953,7 +953,7 @@ void fb_delete_videomode(const struct fb_videomode *mode, | |||
953 | } | 953 | } |
954 | 954 | ||
955 | /** | 955 | /** |
956 | * fb_destroy_modelist: destroy modelist | 956 | * fb_destroy_modelist - destroy modelist |
957 | * @head: struct list_head of modelist | 957 | * @head: struct list_head of modelist |
958 | */ | 958 | */ |
959 | void fb_destroy_modelist(struct list_head *head) | 959 | void fb_destroy_modelist(struct list_head *head) |
@@ -968,7 +968,7 @@ void fb_destroy_modelist(struct list_head *head) | |||
968 | EXPORT_SYMBOL_GPL(fb_destroy_modelist); | 968 | EXPORT_SYMBOL_GPL(fb_destroy_modelist); |
969 | 969 | ||
970 | /** | 970 | /** |
971 | * fb_videomode_to_modelist: convert mode array to mode list | 971 | * fb_videomode_to_modelist - convert mode array to mode list |
972 | * @modedb: array of struct fb_videomode | 972 | * @modedb: array of struct fb_videomode |
973 | * @num: number of entries in array | 973 | * @num: number of entries in array |
974 | * @head: struct list_head of modelist | 974 | * @head: struct list_head of modelist |
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c new file mode 100644 index 000000000000..6bf0d460a738 --- /dev/null +++ b/drivers/video/nuc900fb.c | |||
@@ -0,0 +1,779 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 2009 Nuvoton technology corporation | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * Description: | ||
12 | * Nuvoton LCD Controller Driver | ||
13 | * Author: | ||
14 | * Wang Qiang (rurality.linux@gmail.com) 2009/12/11 | ||
15 | */ | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/tty.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/dma-mapping.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/workqueue.h> | ||
29 | #include <linux/wait.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/clk.h> | ||
32 | #include <linux/cpufreq.h> | ||
33 | #include <linux/io.h> | ||
34 | #include <linux/pm.h> | ||
35 | #include <linux/device.h> | ||
36 | |||
37 | #include <mach/map.h> | ||
38 | #include <mach/regs-clock.h> | ||
39 | #include <mach/regs-ldm.h> | ||
40 | #include <mach/fb.h> | ||
41 | #include <mach/clkdev.h> | ||
42 | |||
43 | #include "nuc900fb.h" | ||
44 | |||
45 | |||
46 | /* | ||
47 | * Initialize the nuc900 video (dual) buffer address | ||
48 | */ | ||
49 | static void nuc900fb_set_lcdaddr(struct fb_info *info) | ||
50 | { | ||
51 | struct nuc900fb_info *fbi = info->par; | ||
52 | void __iomem *regs = fbi->io; | ||
53 | unsigned long vbaddr1, vbaddr2; | ||
54 | |||
55 | vbaddr1 = info->fix.smem_start; | ||
56 | vbaddr2 = info->fix.smem_start; | ||
57 | vbaddr2 += info->fix.line_length * info->var.yres; | ||
58 | |||
59 | /* set frambuffer start phy addr*/ | ||
60 | writel(vbaddr1, regs + REG_LCM_VA_BADDR0); | ||
61 | writel(vbaddr2, regs + REG_LCM_VA_BADDR1); | ||
62 | |||
63 | writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL); | ||
64 | writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE); | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * calculate divider for lcd div | ||
69 | */ | ||
70 | static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi, | ||
71 | unsigned long pixclk) | ||
72 | { | ||
73 | unsigned long clk = fbi->clk_rate; | ||
74 | unsigned long long div; | ||
75 | |||
76 | /* pixclk is in picseconds. our clock is in Hz*/ | ||
77 | /* div = (clk * pixclk)/10^12 */ | ||
78 | div = (unsigned long long)clk * pixclk; | ||
79 | div >>= 12; | ||
80 | do_div(div, 625 * 625UL * 625); | ||
81 | |||
82 | dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div); | ||
83 | |||
84 | return div; | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Check the video params of 'var'. | ||
89 | */ | ||
90 | static int nuc900fb_check_var(struct fb_var_screeninfo *var, | ||
91 | struct fb_info *info) | ||
92 | { | ||
93 | struct nuc900fb_info *fbi = info->par; | ||
94 | struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; | ||
95 | struct nuc900fb_display *display = NULL; | ||
96 | struct nuc900fb_display *default_display = mach_info->displays + | ||
97 | mach_info->default_display; | ||
98 | int i; | ||
99 | |||
100 | dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info); | ||
101 | |||
102 | /* validate x/y resolution */ | ||
103 | /* choose default mode if possible */ | ||
104 | if (var->xres == default_display->xres && | ||
105 | var->yres == default_display->yres && | ||
106 | var->bits_per_pixel == default_display->bpp) | ||
107 | display = default_display; | ||
108 | else | ||
109 | for (i = 0; i < mach_info->num_displays; i++) | ||
110 | if (var->xres == mach_info->displays[i].xres && | ||
111 | var->yres == mach_info->displays[i].yres && | ||
112 | var->bits_per_pixel == mach_info->displays[i].bpp) { | ||
113 | display = mach_info->displays + i; | ||
114 | break; | ||
115 | } | ||
116 | |||
117 | if (display == NULL) { | ||
118 | printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n", | ||
119 | var->xres, var->yres, var->bits_per_pixel); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | /* it should be the same size as the display */ | ||
124 | var->xres_virtual = display->xres; | ||
125 | var->yres_virtual = display->yres; | ||
126 | var->height = display->height; | ||
127 | var->width = display->width; | ||
128 | |||
129 | /* copy lcd settings */ | ||
130 | var->pixclock = display->pixclock; | ||
131 | var->left_margin = display->left_margin; | ||
132 | var->right_margin = display->right_margin; | ||
133 | var->upper_margin = display->upper_margin; | ||
134 | var->lower_margin = display->lower_margin; | ||
135 | var->vsync_len = display->vsync_len; | ||
136 | var->hsync_len = display->hsync_len; | ||
137 | |||
138 | var->transp.offset = 0; | ||
139 | var->transp.length = 0; | ||
140 | |||
141 | fbi->regs.lcd_dccs = display->dccs; | ||
142 | fbi->regs.lcd_device_ctrl = display->devctl; | ||
143 | fbi->regs.lcd_va_fbctrl = display->fbctrl; | ||
144 | fbi->regs.lcd_va_scale = display->scale; | ||
145 | |||
146 | /* set R/G/B possions */ | ||
147 | switch (var->bits_per_pixel) { | ||
148 | case 1: | ||
149 | case 2: | ||
150 | case 4: | ||
151 | case 8: | ||
152 | default: | ||
153 | var->red.offset = 0; | ||
154 | var->red.length = var->bits_per_pixel; | ||
155 | var->green = var->red; | ||
156 | var->blue = var->red; | ||
157 | break; | ||
158 | case 12: | ||
159 | var->red.length = 4; | ||
160 | var->green.length = 4; | ||
161 | var->blue.length = 4; | ||
162 | var->red.offset = 8; | ||
163 | var->green.offset = 4; | ||
164 | var->blue.offset = 0; | ||
165 | break; | ||
166 | case 16: | ||
167 | var->red.length = 5; | ||
168 | var->green.length = 6; | ||
169 | var->blue.length = 5; | ||
170 | var->red.offset = 11; | ||
171 | var->green.offset = 5; | ||
172 | var->blue.offset = 0; | ||
173 | break; | ||
174 | case 18: | ||
175 | var->red.length = 6; | ||
176 | var->green.length = 6; | ||
177 | var->blue.length = 6; | ||
178 | var->red.offset = 12; | ||
179 | var->green.offset = 6; | ||
180 | var->blue.offset = 0; | ||
181 | break; | ||
182 | case 32: | ||
183 | var->red.length = 8; | ||
184 | var->green.length = 8; | ||
185 | var->blue.length = 8; | ||
186 | var->red.offset = 16; | ||
187 | var->green.offset = 8; | ||
188 | var->blue.offset = 0; | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Calculate lcd register values from var setting & save into hw | ||
197 | */ | ||
198 | static void nuc900fb_calculate_lcd_regs(const struct fb_info *info, | ||
199 | struct nuc900fb_hw *regs) | ||
200 | { | ||
201 | const struct fb_var_screeninfo *var = &info->var; | ||
202 | int vtt = var->height + var->upper_margin + var->lower_margin; | ||
203 | int htt = var->width + var->left_margin + var->right_margin; | ||
204 | int hsync = var->width + var->right_margin; | ||
205 | int vsync = var->height + var->lower_margin; | ||
206 | |||
207 | regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) | | ||
208 | LCM_CRTC_SIZE_HTTVAL(htt); | ||
209 | regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) | | ||
210 | LCM_CRTC_DEND_HDENDVAL(var->width); | ||
211 | regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) | | ||
212 | LCM_CRTC_HR_SVAL(var->width + 1); | ||
213 | regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) | | ||
214 | LCM_CRTC_HSYNC_SVAL(hsync); | ||
215 | regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) | | ||
216 | LCM_CRTC_VR_SVAL(vsync); | ||
217 | |||
218 | } | ||
219 | |||
220 | /* | ||
221 | * Activate (set) the controller from the given framebuffer | ||
222 | * information | ||
223 | */ | ||
224 | static void nuc900fb_activate_var(struct fb_info *info) | ||
225 | { | ||
226 | struct nuc900fb_info *fbi = info->par; | ||
227 | void __iomem *regs = fbi->io; | ||
228 | struct fb_var_screeninfo *var = &info->var; | ||
229 | int clkdiv; | ||
230 | |||
231 | clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1; | ||
232 | if (clkdiv < 0) | ||
233 | clkdiv = 0; | ||
234 | |||
235 | nuc900fb_calculate_lcd_regs(info, &fbi->regs); | ||
236 | |||
237 | /* set the new lcd registers*/ | ||
238 | |||
239 | dev_dbg(fbi->dev, "new lcd register set:\n"); | ||
240 | dev_dbg(fbi->dev, "dccs = 0x%08x\n", fbi->regs.lcd_dccs); | ||
241 | dev_dbg(fbi->dev, "dev_ctl = 0x%08x\n", fbi->regs.lcd_device_ctrl); | ||
242 | dev_dbg(fbi->dev, "crtc_size = 0x%08x\n", fbi->regs.lcd_crtc_size); | ||
243 | dev_dbg(fbi->dev, "crtc_dend = 0x%08x\n", fbi->regs.lcd_crtc_dend); | ||
244 | dev_dbg(fbi->dev, "crtc_hr = 0x%08x\n", fbi->regs.lcd_crtc_hr); | ||
245 | dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync); | ||
246 | dev_dbg(fbi->dev, "crtc_vr = 0x%08x\n", fbi->regs.lcd_crtc_vr); | ||
247 | |||
248 | writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL); | ||
249 | writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE); | ||
250 | writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND); | ||
251 | writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR); | ||
252 | writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC); | ||
253 | writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR); | ||
254 | |||
255 | /* set lcd address pointers */ | ||
256 | nuc900fb_set_lcdaddr(info); | ||
257 | |||
258 | writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS); | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * Alters the hardware state. | ||
263 | * | ||
264 | */ | ||
265 | static int nuc900fb_set_par(struct fb_info *info) | ||
266 | { | ||
267 | struct fb_var_screeninfo *var = &info->var; | ||
268 | |||
269 | switch (var->bits_per_pixel) { | ||
270 | case 32: | ||
271 | case 24: | ||
272 | case 18: | ||
273 | case 16: | ||
274 | case 12: | ||
275 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
276 | break; | ||
277 | case 1: | ||
278 | info->fix.visual = FB_VISUAL_MONO01; | ||
279 | break; | ||
280 | default: | ||
281 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
282 | break; | ||
283 | } | ||
284 | |||
285 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; | ||
286 | |||
287 | /* activate this new configuration */ | ||
288 | nuc900fb_activate_var(info); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static inline unsigned int chan_to_field(unsigned int chan, | ||
293 | struct fb_bitfield *bf) | ||
294 | { | ||
295 | chan &= 0xffff; | ||
296 | chan >>= 16 - bf->length; | ||
297 | return chan << bf->offset; | ||
298 | } | ||
299 | |||
300 | static int nuc900fb_setcolreg(unsigned regno, | ||
301 | unsigned red, unsigned green, unsigned blue, | ||
302 | unsigned transp, struct fb_info *info) | ||
303 | { | ||
304 | unsigned int val; | ||
305 | |||
306 | switch (info->fix.visual) { | ||
307 | case FB_VISUAL_TRUECOLOR: | ||
308 | /* true-colour, use pseuo-palette */ | ||
309 | if (regno < 16) { | ||
310 | u32 *pal = info->pseudo_palette; | ||
311 | |||
312 | val = chan_to_field(red, &info->var.red); | ||
313 | val |= chan_to_field(green, &info->var.green); | ||
314 | val |= chan_to_field(blue, &info->var.blue); | ||
315 | pal[regno] = val; | ||
316 | } | ||
317 | break; | ||
318 | |||
319 | default: | ||
320 | return 1; /* unknown type */ | ||
321 | } | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * nuc900fb_blank | ||
327 | * | ||
328 | */ | ||
329 | static int nuc900fb_blank(int blank_mode, struct fb_info *info) | ||
330 | { | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static struct fb_ops nuc900fb_ops = { | ||
336 | .owner = THIS_MODULE, | ||
337 | .fb_check_var = nuc900fb_check_var, | ||
338 | .fb_set_par = nuc900fb_set_par, | ||
339 | .fb_blank = nuc900fb_blank, | ||
340 | .fb_setcolreg = nuc900fb_setcolreg, | ||
341 | .fb_fillrect = cfb_fillrect, | ||
342 | .fb_copyarea = cfb_copyarea, | ||
343 | .fb_imageblit = cfb_imageblit, | ||
344 | }; | ||
345 | |||
346 | |||
347 | static inline void modify_gpio(void __iomem *reg, | ||
348 | unsigned long set, unsigned long mask) | ||
349 | { | ||
350 | unsigned long tmp; | ||
351 | tmp = readl(reg) & ~mask; | ||
352 | writel(tmp | set, reg); | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Initialise LCD-related registers | ||
357 | */ | ||
358 | static int nuc900fb_init_registers(struct fb_info *info) | ||
359 | { | ||
360 | struct nuc900fb_info *fbi = info->par; | ||
361 | struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; | ||
362 | void __iomem *regs = fbi->io; | ||
363 | |||
364 | /*reset the display engine*/ | ||
365 | writel(0, regs + REG_LCM_DCCS); | ||
366 | writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST, | ||
367 | regs + REG_LCM_DCCS); | ||
368 | ndelay(100); | ||
369 | writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST), | ||
370 | regs + REG_LCM_DCCS); | ||
371 | ndelay(100); | ||
372 | |||
373 | writel(0, regs + REG_LCM_DEV_CTRL); | ||
374 | |||
375 | /* config gpio output */ | ||
376 | modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir, | ||
377 | mach_info->gpio_dir_mask); | ||
378 | modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data, | ||
379 | mach_info->gpio_data_mask); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | |||
385 | /* | ||
386 | * Alloc the SDRAM region of NUC900 for the frame buffer. | ||
387 | * The buffer should be a non-cached, non-buffered, memory region | ||
388 | * to allow palette and pixel writes without flushing the cache. | ||
389 | */ | ||
390 | static int __init nuc900fb_map_video_memory(struct fb_info *info) | ||
391 | { | ||
392 | struct nuc900fb_info *fbi = info->par; | ||
393 | dma_addr_t map_dma; | ||
394 | unsigned long map_size = PAGE_ALIGN(info->fix.smem_len); | ||
395 | |||
396 | dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n", | ||
397 | fbi, map_size); | ||
398 | |||
399 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, | ||
400 | &map_dma, GFP_KERNEL); | ||
401 | |||
402 | if (!info->screen_base) | ||
403 | return -ENOMEM; | ||
404 | |||
405 | memset(info->screen_base, 0x00, map_size); | ||
406 | info->fix.smem_start = map_dma; | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static inline void nuc900fb_unmap_video_memory(struct fb_info *info) | ||
412 | { | ||
413 | struct nuc900fb_info *fbi = info->par; | ||
414 | dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), | ||
415 | info->screen_base, info->fix.smem_start); | ||
416 | } | ||
417 | |||
418 | static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id) | ||
419 | { | ||
420 | struct nuc900fb_info *fbi = dev_id; | ||
421 | void __iomem *regs = fbi->io; | ||
422 | void __iomem *irq_base = fbi->irq_base; | ||
423 | unsigned long lcdirq = readl(regs + REG_LCM_INT_CS); | ||
424 | |||
425 | if (lcdirq & LCM_INT_CS_DISP_F_STATUS) { | ||
426 | writel(readl(irq_base) | 1<<30, irq_base); | ||
427 | |||
428 | /* wait VA_EN low */ | ||
429 | if ((readl(regs + REG_LCM_DCCS) & | ||
430 | LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE) | ||
431 | while ((readl(regs + REG_LCM_DCCS) & | ||
432 | LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN) | ||
433 | ; | ||
434 | /* display_out-enable */ | ||
435 | writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN, | ||
436 | regs + REG_LCM_DCCS); | ||
437 | /* va-enable*/ | ||
438 | writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN, | ||
439 | regs + REG_LCM_DCCS); | ||
440 | } else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) { | ||
441 | writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base); | ||
442 | } else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) { | ||
443 | writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base); | ||
444 | } | ||
445 | |||
446 | return IRQ_HANDLED; | ||
447 | } | ||
448 | |||
449 | #ifdef CONFIG_CPU_FREQ | ||
450 | |||
451 | static int nuc900fb_cpufreq_transition(struct notifier_block *nb, | ||
452 | unsigned long val, void *data) | ||
453 | { | ||
454 | struct nuc900fb_info *info; | ||
455 | struct fb_info *fbinfo; | ||
456 | long delta_f; | ||
457 | info = container_of(nb, struct nuc900fb_info, freq_transition); | ||
458 | fbinfo = platform_get_drvdata(to_platform_device(info->dev)); | ||
459 | |||
460 | delta_f = info->clk_rate - clk_get_rate(info->clk); | ||
461 | |||
462 | if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) || | ||
463 | (val == CPUFREQ_PRECHANGE && delta_f < 0)) { | ||
464 | info->clk_rate = clk_get_rate(info->clk); | ||
465 | nuc900fb_activate_var(fbinfo); | ||
466 | } | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi) | ||
472 | { | ||
473 | fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition; | ||
474 | return cpufreq_register_notifier(&fbi->freq_transition, | ||
475 | CPUFREQ_TRANSITION_NOTIFIER); | ||
476 | } | ||
477 | |||
478 | static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi) | ||
479 | { | ||
480 | cpufreq_unregister_notifier(&fbi->freq_transition, | ||
481 | CPUFREQ_TRANSITION_NOTIFIER); | ||
482 | } | ||
483 | #else | ||
484 | static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb, | ||
485 | unsigned long val, void *data) | ||
486 | { | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi) | ||
491 | { | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info) | ||
496 | { | ||
497 | } | ||
498 | #endif | ||
499 | |||
500 | static char driver_name[] = "nuc900fb"; | ||
501 | |||
502 | static int __devinit nuc900fb_probe(struct platform_device *pdev) | ||
503 | { | ||
504 | struct nuc900fb_info *fbi; | ||
505 | struct nuc900fb_display *display; | ||
506 | struct fb_info *fbinfo; | ||
507 | struct nuc900fb_mach_info *mach_info; | ||
508 | struct resource *res; | ||
509 | int ret; | ||
510 | int irq; | ||
511 | int i; | ||
512 | int size; | ||
513 | |||
514 | dev_dbg(&pdev->dev, "devinit\n"); | ||
515 | mach_info = pdev->dev.platform_data; | ||
516 | if (mach_info == NULL) { | ||
517 | dev_err(&pdev->dev, | ||
518 | "no platform data for lcd, cannot attach\n"); | ||
519 | return -EINVAL; | ||
520 | } | ||
521 | |||
522 | if (mach_info->default_display > mach_info->num_displays) { | ||
523 | dev_err(&pdev->dev, | ||
524 | "default display No. is %d but only %d displays \n", | ||
525 | mach_info->default_display, mach_info->num_displays); | ||
526 | return -EINVAL; | ||
527 | } | ||
528 | |||
529 | |||
530 | display = mach_info->displays + mach_info->default_display; | ||
531 | |||
532 | irq = platform_get_irq(pdev, 0); | ||
533 | if (irq < 0) { | ||
534 | dev_err(&pdev->dev, "no irq for device\n"); | ||
535 | return -ENOENT; | ||
536 | } | ||
537 | |||
538 | fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev); | ||
539 | if (!fbinfo) | ||
540 | return -ENOMEM; | ||
541 | |||
542 | platform_set_drvdata(pdev, fbinfo); | ||
543 | |||
544 | fbi = fbinfo->par; | ||
545 | fbi->dev = &pdev->dev; | ||
546 | |||
547 | #ifdef CONFIG_CPU_NUC950 | ||
548 | fbi->drv_type = LCDDRV_NUC950; | ||
549 | #endif | ||
550 | |||
551 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
552 | |||
553 | size = (res->end - res->start) + 1; | ||
554 | fbi->mem = request_mem_region(res->start, size, pdev->name); | ||
555 | if (fbi->mem == NULL) { | ||
556 | dev_err(&pdev->dev, "failed to alloc memory region\n"); | ||
557 | ret = -ENOENT; | ||
558 | goto free_fb; | ||
559 | } | ||
560 | |||
561 | fbi->io = ioremap(res->start, size); | ||
562 | if (fbi->io == NULL) { | ||
563 | dev_err(&pdev->dev, "ioremap() of lcd registers failed\n"); | ||
564 | ret = -ENXIO; | ||
565 | goto release_mem_region; | ||
566 | } | ||
567 | |||
568 | fbi->irq_base = fbi->io + REG_LCM_INT_CS; | ||
569 | |||
570 | |||
571 | /* Stop the LCD */ | ||
572 | writel(0, fbi->io + REG_LCM_DCCS); | ||
573 | |||
574 | /* fill the fbinfo*/ | ||
575 | strcpy(fbinfo->fix.id, driver_name); | ||
576 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; | ||
577 | fbinfo->fix.type_aux = 0; | ||
578 | fbinfo->fix.xpanstep = 0; | ||
579 | fbinfo->fix.ypanstep = 0; | ||
580 | fbinfo->fix.ywrapstep = 0; | ||
581 | fbinfo->fix.accel = FB_ACCEL_NONE; | ||
582 | fbinfo->var.nonstd = 0; | ||
583 | fbinfo->var.activate = FB_ACTIVATE_NOW; | ||
584 | fbinfo->var.accel_flags = 0; | ||
585 | fbinfo->var.vmode = FB_VMODE_NONINTERLACED; | ||
586 | fbinfo->fbops = &nuc900fb_ops; | ||
587 | fbinfo->flags = FBINFO_FLAG_DEFAULT; | ||
588 | fbinfo->pseudo_palette = &fbi->pseudo_pal; | ||
589 | |||
590 | ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED, | ||
591 | pdev->name, fbinfo); | ||
592 | if (ret) { | ||
593 | dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", | ||
594 | irq, ret); | ||
595 | ret = -EBUSY; | ||
596 | goto release_regs; | ||
597 | } | ||
598 | |||
599 | nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2); | ||
600 | |||
601 | fbi->clk = clk_get(&pdev->dev, NULL); | ||
602 | if (!fbi->clk || IS_ERR(fbi->clk)) { | ||
603 | printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); | ||
604 | ret = -ENOENT; | ||
605 | goto release_irq; | ||
606 | } | ||
607 | |||
608 | clk_enable(fbi->clk); | ||
609 | dev_dbg(&pdev->dev, "got and enabled clock\n"); | ||
610 | |||
611 | fbi->clk_rate = clk_get_rate(fbi->clk); | ||
612 | |||
613 | /* calutate the video buffer size */ | ||
614 | for (i = 0; i < mach_info->num_displays; i++) { | ||
615 | unsigned long smem_len = mach_info->displays[i].xres; | ||
616 | smem_len *= mach_info->displays[i].yres; | ||
617 | smem_len *= mach_info->displays[i].bpp; | ||
618 | smem_len >>= 3; | ||
619 | if (fbinfo->fix.smem_len < smem_len) | ||
620 | fbinfo->fix.smem_len = smem_len; | ||
621 | } | ||
622 | |||
623 | /* Initialize Video Memory */ | ||
624 | ret = nuc900fb_map_video_memory(fbinfo); | ||
625 | if (ret) { | ||
626 | printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret); | ||
627 | goto release_clock; | ||
628 | } | ||
629 | |||
630 | dev_dbg(&pdev->dev, "got video memory\n"); | ||
631 | |||
632 | fbinfo->var.xres = display->xres; | ||
633 | fbinfo->var.yres = display->yres; | ||
634 | fbinfo->var.bits_per_pixel = display->bpp; | ||
635 | |||
636 | nuc900fb_init_registers(fbinfo); | ||
637 | |||
638 | nuc900fb_check_var(&fbinfo->var, fbinfo); | ||
639 | |||
640 | ret = nuc900fb_cpufreq_register(fbi); | ||
641 | if (ret < 0) { | ||
642 | dev_err(&pdev->dev, "Failed to register cpufreq\n"); | ||
643 | goto free_video_memory; | ||
644 | } | ||
645 | |||
646 | ret = register_framebuffer(fbinfo); | ||
647 | if (ret) { | ||
648 | printk(KERN_ERR "failed to register framebuffer device: %d\n", | ||
649 | ret); | ||
650 | goto free_cpufreq; | ||
651 | } | ||
652 | |||
653 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | ||
654 | fbinfo->node, fbinfo->fix.id); | ||
655 | |||
656 | return 0; | ||
657 | |||
658 | free_cpufreq: | ||
659 | nuc900fb_cpufreq_deregister(fbi); | ||
660 | free_video_memory: | ||
661 | nuc900fb_unmap_video_memory(fbinfo); | ||
662 | release_clock: | ||
663 | clk_disable(fbi->clk); | ||
664 | clk_put(fbi->clk); | ||
665 | release_irq: | ||
666 | free_irq(irq, fbi); | ||
667 | release_regs: | ||
668 | iounmap(fbi->io); | ||
669 | release_mem_region: | ||
670 | release_mem_region((unsigned long)fbi->mem, size); | ||
671 | free_fb: | ||
672 | framebuffer_release(fbinfo); | ||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | /* | ||
677 | * shutdown the lcd controller | ||
678 | */ | ||
679 | static void nuc900fb_stop_lcd(struct fb_info *info) | ||
680 | { | ||
681 | struct nuc900fb_info *fbi = info->par; | ||
682 | void __iomem *regs = fbi->io; | ||
683 | |||
684 | writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN), | ||
685 | regs + REG_LCM_DCCS); | ||
686 | } | ||
687 | |||
688 | /* | ||
689 | * Cleanup | ||
690 | */ | ||
691 | static int nuc900fb_remove(struct platform_device *pdev) | ||
692 | { | ||
693 | struct fb_info *fbinfo = platform_get_drvdata(pdev); | ||
694 | struct nuc900fb_info *fbi = fbinfo->par; | ||
695 | int irq; | ||
696 | |||
697 | nuc900fb_stop_lcd(fbinfo); | ||
698 | msleep(1); | ||
699 | |||
700 | nuc900fb_unmap_video_memory(fbinfo); | ||
701 | |||
702 | iounmap(fbi->io); | ||
703 | |||
704 | irq = platform_get_irq(pdev, 0); | ||
705 | free_irq(irq, fbi); | ||
706 | |||
707 | release_resource(fbi->mem); | ||
708 | kfree(fbi->mem); | ||
709 | |||
710 | platform_set_drvdata(pdev, NULL); | ||
711 | framebuffer_release(fbinfo); | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | #ifdef CONFIG_PM | ||
717 | |||
718 | /* | ||
719 | * suspend and resume support for the lcd controller | ||
720 | */ | ||
721 | |||
722 | static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state) | ||
723 | { | ||
724 | struct fb_info *fbinfo = platform_get_drvdata(dev); | ||
725 | struct nuc900fb_info *info = fbinfo->par; | ||
726 | |||
727 | nuc900fb_stop_lcd(); | ||
728 | msleep(1); | ||
729 | clk_disable(info->clk); | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static int nuc900fb_resume(struct platform_device *dev) | ||
734 | { | ||
735 | struct fb_info *fbinfo = platform_get_drvdata(dev); | ||
736 | struct nuc900fb_info *fbi = fbinfo->par; | ||
737 | |||
738 | printk(KERN_INFO "nuc900fb resume\n"); | ||
739 | |||
740 | clk_enable(fbi->clk); | ||
741 | msleep(1); | ||
742 | |||
743 | nuc900fb_init_registers(fbinfo); | ||
744 | nuc900fb_activate_var(bfinfo); | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | #else | ||
750 | #define nuc900fb_suspend NULL | ||
751 | #define nuc900fb_resume NULL | ||
752 | #endif | ||
753 | |||
754 | static struct platform_driver nuc900fb_driver = { | ||
755 | .probe = nuc900fb_probe, | ||
756 | .remove = nuc900fb_remove, | ||
757 | .suspend = nuc900fb_suspend, | ||
758 | .resume = nuc900fb_resume, | ||
759 | .driver = { | ||
760 | .name = "nuc900-lcd", | ||
761 | .owner = THIS_MODULE, | ||
762 | }, | ||
763 | }; | ||
764 | |||
765 | int __devinit nuc900fb_init(void) | ||
766 | { | ||
767 | return platform_driver_register(&nuc900fb_driver); | ||
768 | } | ||
769 | |||
770 | static void __exit nuc900fb_cleanup(void) | ||
771 | { | ||
772 | platform_driver_unregister(&nuc900fb_driver); | ||
773 | } | ||
774 | |||
775 | module_init(nuc900fb_init); | ||
776 | module_exit(nuc900fb_cleanup); | ||
777 | |||
778 | MODULE_DESCRIPTION("Framebuffer driver for the NUC900"); | ||
779 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h new file mode 100644 index 000000000000..6c23aa3d3b89 --- /dev/null +++ b/drivers/video/nuc900fb.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 2009 Nuvoton technology corporation | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * Auther: | ||
12 | * Wang Qiang(rurality.linux@gmail.com) 2009/12/16 | ||
13 | */ | ||
14 | |||
15 | #ifndef __NUC900FB_H | ||
16 | #define __NUC900FB_H | ||
17 | |||
18 | #include <mach/map.h> | ||
19 | #include <mach/fb.h> | ||
20 | |||
21 | enum nuc900_lcddrv_type { | ||
22 | LCDDRV_NUC910, | ||
23 | LCDDRV_NUC930, | ||
24 | LCDDRV_NUC932, | ||
25 | LCDDRV_NUC950, | ||
26 | LCDDRV_NUC960, | ||
27 | }; | ||
28 | |||
29 | |||
30 | #define PALETTE_BUFFER_SIZE 256 | ||
31 | #define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */ | ||
32 | |||
33 | struct nuc900fb_info { | ||
34 | struct device *dev; | ||
35 | struct clk *clk; | ||
36 | |||
37 | struct resource *mem; | ||
38 | void __iomem *io; | ||
39 | void __iomem *irq_base; | ||
40 | int drv_type; | ||
41 | struct nuc900fb_hw regs; | ||
42 | unsigned long clk_rate; | ||
43 | |||
44 | #ifdef CONFIG_CPU_FREQ | ||
45 | struct notifier_block freq_transition; | ||
46 | #endif | ||
47 | |||
48 | /* keep these registers in case we need to re-write palette */ | ||
49 | u32 palette_buffer[PALETTE_BUFFER_SIZE]; | ||
50 | u32 pseudo_pal[16]; | ||
51 | }; | ||
52 | |||
53 | int nuc900fb_init(void); | ||
54 | |||
55 | #endif /* __NUC900FB_H */ | ||
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 913142d4cab1..9acef00c47ea 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -341,7 +341,7 @@ static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, | |||
341 | return manager_attr->store(manager, buf, size); | 341 | return manager_attr->store(manager, buf, size); |
342 | } | 342 | } |
343 | 343 | ||
344 | static struct sysfs_ops manager_sysfs_ops = { | 344 | static const struct sysfs_ops manager_sysfs_ops = { |
345 | .show = manager_attr_show, | 345 | .show = manager_attr_show, |
346 | .store = manager_attr_store, | 346 | .store = manager_attr_store, |
347 | }; | 347 | }; |
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 0c5bea263ac6..aed3f3194347 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -320,7 +320,7 @@ static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, | |||
320 | return overlay_attr->store(overlay, buf, size); | 320 | return overlay_attr->store(overlay, buf, size); |
321 | } | 321 | } |
322 | 322 | ||
323 | static struct sysfs_ops overlay_sysfs_ops = { | 323 | static const struct sysfs_ops overlay_sysfs_ops = { |
324 | .show = overlay_attr_show, | 324 | .show = overlay_attr_show, |
325 | .store = overlay_attr_store, | 325 | .store = overlay_attr_store, |
326 | }; | 326 | }; |
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 4beac1df617b..de40a626dc76 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c | |||
@@ -85,7 +85,7 @@ static struct fb_ops q40fb_ops = { | |||
85 | .fb_imageblit = cfb_imageblit, | 85 | .fb_imageblit = cfb_imageblit, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | static int __init q40fb_probe(struct platform_device *dev) | 88 | static int __devinit q40fb_probe(struct platform_device *dev) |
89 | { | 89 | { |
90 | struct fb_info *info; | 90 | struct fb_info *info; |
91 | 91 | ||
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index aac661225c78..2b094dec4a56 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -1004,12 +1004,12 @@ dealloc_fb: | |||
1004 | return ret; | 1004 | return ret; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | static int __init s3c2410fb_probe(struct platform_device *pdev) | 1007 | static int __devinit s3c2410fb_probe(struct platform_device *pdev) |
1008 | { | 1008 | { |
1009 | return s3c24xxfb_probe(pdev, DRV_S3C2410); | 1009 | return s3c24xxfb_probe(pdev, DRV_S3C2410); |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | static int __init s3c2412fb_probe(struct platform_device *pdev) | 1012 | static int __devinit s3c2412fb_probe(struct platform_device *pdev) |
1013 | { | 1013 | { |
1014 | return s3c24xxfb_probe(pdev, DRV_S3C2412); | 1014 | return s3c24xxfb_probe(pdev, DRV_S3C2412); |
1015 | } | 1015 | } |
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index cdaa873a6054..e8b76d65a070 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c | |||
@@ -1435,7 +1435,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) | |||
1435 | return fbi; | 1435 | return fbi; |
1436 | } | 1436 | } |
1437 | 1437 | ||
1438 | static int __init sa1100fb_probe(struct platform_device *pdev) | 1438 | static int __devinit sa1100fb_probe(struct platform_device *pdev) |
1439 | { | 1439 | { |
1440 | struct sa1100fb_info *fbi; | 1440 | struct sa1100fb_info *fbi; |
1441 | int ret, irq; | 1441 | int ret, irq; |
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index f86012239bff..7a3a5e28eca1 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c | |||
@@ -745,7 +745,7 @@ int __init sgivwfb_setup(char *options) | |||
745 | /* | 745 | /* |
746 | * Initialisation | 746 | * Initialisation |
747 | */ | 747 | */ |
748 | static int __init sgivwfb_probe(struct platform_device *dev) | 748 | static int __devinit sgivwfb_probe(struct platform_device *dev) |
749 | { | 749 | { |
750 | struct sgivw_par *par; | 750 | struct sgivw_par *par; |
751 | struct fb_info *info; | 751 | struct fb_info *info; |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 8d7653e56df5..bbd1dbf4026a 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -943,7 +943,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { | |||
943 | 943 | ||
944 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); | 944 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); |
945 | 945 | ||
946 | static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) | 946 | static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) |
947 | { | 947 | { |
948 | struct fb_info *info; | 948 | struct fb_info *info; |
949 | struct sh_mobile_lcdc_priv *priv; | 949 | struct sh_mobile_lcdc_priv *priv; |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 9d2b6bc49036..a531a0f7cdf2 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -1891,9 +1891,6 @@ static struct fb_ops sisfb_ops = { | |||
1891 | .fb_fillrect = fbcon_sis_fillrect, | 1891 | .fb_fillrect = fbcon_sis_fillrect, |
1892 | .fb_copyarea = fbcon_sis_copyarea, | 1892 | .fb_copyarea = fbcon_sis_copyarea, |
1893 | .fb_imageblit = cfb_imageblit, | 1893 | .fb_imageblit = cfb_imageblit, |
1894 | #ifdef CONFIG_FB_SOFT_CURSOR | ||
1895 | .fb_cursor = soft_cursor, | ||
1896 | #endif | ||
1897 | .fb_sync = fbcon_sis_sync, | 1894 | .fb_sync = fbcon_sis_sync, |
1898 | #ifdef SIS_NEW_CONFIG_COMPAT | 1895 | #ifdef SIS_NEW_CONFIG_COMPAT |
1899 | .fb_compat_ioctl= sisfb_ioctl, | 1896 | .fb_compat_ioctl= sisfb_ioctl, |
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index bd37ee1f6a25..ef4128c8e57a 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -226,7 +226,7 @@ static int __init vesafb_setup(char *options) | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int __init vesafb_probe(struct platform_device *dev) | 229 | static int __devinit vesafb_probe(struct platform_device *dev) |
230 | { | 230 | { |
231 | struct fb_info *info; | 231 | struct fb_info *info; |
232 | int i, err; | 232 | int i, err; |
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 050d432c7d95..b8ab995fbda7 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
@@ -479,7 +479,7 @@ static int __init vfb_setup(char *options) | |||
479 | * Initialisation | 479 | * Initialisation |
480 | */ | 480 | */ |
481 | 481 | ||
482 | static int __init vfb_probe(struct platform_device *dev) | 482 | static int __devinit vfb_probe(struct platform_device *dev) |
483 | { | 483 | { |
484 | struct fb_info *info; | 484 | struct fb_info *info; |
485 | int retval = -ENOMEM; | 485 | int retval = -ENOMEM; |
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 5b2938903ac2..76d8dae5b1bb 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
@@ -1293,7 +1293,7 @@ static int vga16fb_setup(char *options) | |||
1293 | } | 1293 | } |
1294 | #endif | 1294 | #endif |
1295 | 1295 | ||
1296 | static int __init vga16fb_probe(struct platform_device *dev) | 1296 | static int __devinit vga16fb_probe(struct platform_device *dev) |
1297 | { | 1297 | { |
1298 | struct fb_info *info; | 1298 | struct fb_info *info; |
1299 | struct vga16fb_par *par; | 1299 | struct vga16fb_par *par; |
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index e533b4b6aba4..eeed238ad6a2 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_FB_VIA) += viafb.o | 5 | obj-$(CONFIG_FB_VIA) += viafb.o |
6 | 6 | ||
7 | viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o | 7 | viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o |
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index 474f428aea92..8c06bd3c0b4d 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h | |||
@@ -107,7 +107,6 @@ | |||
107 | struct tmds_chip_information { | 107 | struct tmds_chip_information { |
108 | int tmds_chip_name; | 108 | int tmds_chip_name; |
109 | int tmds_chip_slave_addr; | 109 | int tmds_chip_slave_addr; |
110 | int dvi_panel_id; | ||
111 | int data_mode; | 110 | int data_mode; |
112 | int output_interface; | 111 | int output_interface; |
113 | int i2c_port; | 112 | int i2c_port; |
@@ -142,14 +141,9 @@ struct tmds_setting_information { | |||
142 | int iga_path; | 141 | int iga_path; |
143 | int h_active; | 142 | int h_active; |
144 | int v_active; | 143 | int v_active; |
145 | int bpp; | ||
146 | int refresh_rate; | ||
147 | int get_dvi_size_method; | ||
148 | int max_pixel_clock; | 144 | int max_pixel_clock; |
149 | int dvi_panel_size; | 145 | int max_hres; |
150 | int dvi_panel_hres; | 146 | int max_vres; |
151 | int dvi_panel_vres; | ||
152 | int native_size; | ||
153 | }; | 147 | }; |
154 | 148 | ||
155 | struct lvds_setting_information { | 149 | struct lvds_setting_information { |
@@ -160,7 +154,6 @@ struct lvds_setting_information { | |||
160 | int refresh_rate; | 154 | int refresh_rate; |
161 | int get_lcd_size_method; | 155 | int get_lcd_size_method; |
162 | int lcd_panel_id; | 156 | int lcd_panel_id; |
163 | int lcd_panel_size; | ||
164 | int lcd_panel_hres; | 157 | int lcd_panel_hres; |
165 | int lcd_panel_vres; | 158 | int lcd_panel_vres; |
166 | int display_method; | 159 | int display_method; |
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index 67b36932212b..abe59b8c7a05 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c | |||
@@ -23,11 +23,10 @@ | |||
23 | static void tmds_register_write(int index, u8 data); | 23 | static void tmds_register_write(int index, u8 data); |
24 | static int tmds_register_read(int index); | 24 | static int tmds_register_read(int index); |
25 | static int tmds_register_read_bytes(int index, u8 *buff, int buff_len); | 25 | static int tmds_register_read_bytes(int index, u8 *buff, int buff_len); |
26 | static int check_reduce_blanking_mode(int mode_index, | 26 | static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information |
27 | int refresh_rate); | 27 | *tmds_chip, struct tmds_setting_information *tmds_setting); |
28 | static int dvi_get_panel_size_from_DDCv1(void); | 28 | static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information |
29 | static int dvi_get_panel_size_from_DDCv2(void); | 29 | *tmds_chip, struct tmds_setting_information *tmds_setting); |
30 | static unsigned char dvi_get_panel_info(void); | ||
31 | static int viafb_dvi_query_EDID(void); | 30 | static int viafb_dvi_query_EDID(void); |
32 | 31 | ||
33 | static int check_tmds_chip(int device_id_subaddr, int device_id) | 32 | static int check_tmds_chip(int device_id_subaddr, int device_id) |
@@ -38,23 +37,24 @@ static int check_tmds_chip(int device_id_subaddr, int device_id) | |||
38 | return FAIL; | 37 | return FAIL; |
39 | } | 38 | } |
40 | 39 | ||
41 | void viafb_init_dvi_size(void) | 40 | void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, |
41 | struct tmds_setting_information *tmds_setting) | ||
42 | { | 42 | { |
43 | DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); | 43 | DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); |
44 | DEBUG_MSG(KERN_INFO | ||
45 | "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n", | ||
46 | viaparinfo->tmds_setting_info->get_dvi_size_method); | ||
47 | 44 | ||
48 | switch (viaparinfo->tmds_setting_info->get_dvi_size_method) { | 45 | viafb_dvi_sense(); |
49 | case GET_DVI_SIZE_BY_SYSTEM_BIOS: | 46 | switch (viafb_dvi_query_EDID()) { |
47 | case 1: | ||
48 | dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting); | ||
50 | break; | 49 | break; |
51 | case GET_DVI_SZIE_BY_HW_STRAPPING: | 50 | case 2: |
51 | dvi_get_panel_size_from_DDCv2(tmds_chip, tmds_setting); | ||
52 | break; | 52 | break; |
53 | case GET_DVI_SIZE_BY_VGA_BIOS: | ||
54 | default: | 53 | default: |
55 | dvi_get_panel_info(); | 54 | printk(KERN_WARNING "viafb_init_dvi_size: DVI panel size undetected!\n"); |
56 | break; | 55 | break; |
57 | } | 56 | } |
57 | |||
58 | return; | 58 | return; |
59 | } | 59 | } |
60 | 60 | ||
@@ -189,42 +189,14 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) | |||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | static int check_reduce_blanking_mode(int mode_index, | ||
193 | int refresh_rate) | ||
194 | { | ||
195 | if (refresh_rate != 60) | ||
196 | return false; | ||
197 | |||
198 | switch (mode_index) { | ||
199 | /* Following modes have reduce blanking mode. */ | ||
200 | case VIA_RES_1360X768: | ||
201 | case VIA_RES_1400X1050: | ||
202 | case VIA_RES_1440X900: | ||
203 | case VIA_RES_1600X900: | ||
204 | case VIA_RES_1680X1050: | ||
205 | case VIA_RES_1920X1080: | ||
206 | case VIA_RES_1920X1200: | ||
207 | break; | ||
208 | |||
209 | default: | ||
210 | DEBUG_MSG(KERN_INFO | ||
211 | "This dvi mode %d have no reduce blanking mode!\n", | ||
212 | mode_index); | ||
213 | return false; | ||
214 | } | ||
215 | |||
216 | return true; | ||
217 | } | ||
218 | |||
219 | /* DVI Set Mode */ | 192 | /* DVI Set Mode */ |
220 | void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) | 193 | void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, |
194 | int set_iga) | ||
221 | { | 195 | { |
222 | struct VideoModeTable *videoMode = NULL; | 196 | struct VideoModeTable *rb_mode; |
223 | struct crt_mode_table *pDviTiming; | 197 | struct crt_mode_table *pDviTiming; |
224 | unsigned long desirePixelClock, maxPixelClock; | 198 | unsigned long desirePixelClock, maxPixelClock; |
225 | int status = 0; | 199 | pDviTiming = mode->crtc; |
226 | videoMode = viafb_get_modetbl_pointer(video_index); | ||
227 | pDviTiming = videoMode->crtc; | ||
228 | desirePixelClock = pDviTiming->clk / 1000000; | 200 | desirePixelClock = pDviTiming->clk / 1000000; |
229 | maxPixelClock = (unsigned long)viaparinfo-> | 201 | maxPixelClock = (unsigned long)viaparinfo-> |
230 | tmds_setting_info->max_pixel_clock; | 202 | tmds_setting_info->max_pixel_clock; |
@@ -232,20 +204,14 @@ void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) | |||
232 | DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); | 204 | DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); |
233 | 205 | ||
234 | if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { | 206 | if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { |
235 | /*Check if reduce-blanking mode is exist */ | 207 | rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr, |
236 | status = | 208 | mode->crtc[0].crtc.ver_addr); |
237 | check_reduce_blanking_mode(video_index, | 209 | if (rb_mode) { |
238 | pDviTiming->refresh_rate); | 210 | mode = rb_mode; |
239 | if (status) { | 211 | pDviTiming = rb_mode->crtc; |
240 | video_index += 100; /*Use reduce-blanking mode */ | ||
241 | videoMode = viafb_get_modetbl_pointer(video_index); | ||
242 | pDviTiming = videoMode->crtc; | ||
243 | DEBUG_MSG(KERN_INFO | ||
244 | "DVI use reduce blanking mode %d!!\n", | ||
245 | video_index); | ||
246 | } | 212 | } |
247 | } | 213 | } |
248 | viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga); | 214 | viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); |
249 | viafb_set_output_path(DEVICE_DVI, set_iga, | 215 | viafb_set_output_path(DEVICE_DVI, set_iga, |
250 | viaparinfo->chip_info->tmds_chip_info.output_interface); | 216 | viaparinfo->chip_info->tmds_chip_info.output_interface); |
251 | } | 217 | } |
@@ -350,25 +316,18 @@ static int viafb_dvi_query_EDID(void) | |||
350 | return false; | 316 | return false; |
351 | } | 317 | } |
352 | 318 | ||
353 | /* | 319 | /* Get Panel Size Using EDID1 Table */ |
354 | * | 320 | static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information |
355 | * int dvi_get_panel_size_from_DDCv1(void) | 321 | *tmds_chip, struct tmds_setting_information *tmds_setting) |
356 | * | ||
357 | * - Get Panel Size Using EDID1 Table | ||
358 | * | ||
359 | * Return Type: int | ||
360 | * | ||
361 | */ | ||
362 | static int dvi_get_panel_size_from_DDCv1(void) | ||
363 | { | 322 | { |
364 | int i, max_h = 0, max_v = 0, tmp, restore; | 323 | int i, max_h = 0, tmp, restore; |
365 | unsigned char rData; | 324 | unsigned char rData; |
366 | unsigned char EDID_DATA[18]; | 325 | unsigned char EDID_DATA[18]; |
367 | 326 | ||
368 | DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); | 327 | DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); |
369 | 328 | ||
370 | restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; | 329 | restore = tmds_chip->tmds_chip_slave_addr; |
371 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; | 330 | tmds_chip->tmds_chip_slave_addr = 0xA0; |
372 | 331 | ||
373 | rData = tmds_register_read(0x23); | 332 | rData = tmds_register_read(0x23); |
374 | if (rData & 0x3C) | 333 | if (rData & 0x3C) |
@@ -414,8 +373,8 @@ static int dvi_get_panel_size_from_DDCv1(void) | |||
414 | /* The first two byte must be zero. */ | 373 | /* The first two byte must be zero. */ |
415 | if (EDID_DATA[3] == 0xFD) { | 374 | if (EDID_DATA[3] == 0xFD) { |
416 | /* To get max pixel clock. */ | 375 | /* To get max pixel clock. */ |
417 | viaparinfo->tmds_setting_info-> | 376 | tmds_setting->max_pixel_clock = |
418 | max_pixel_clock = EDID_DATA[9] * 10; | 377 | EDID_DATA[9] * 10; |
419 | } | 378 | } |
420 | } | 379 | } |
421 | break; | 380 | break; |
@@ -425,154 +384,88 @@ static int dvi_get_panel_size_from_DDCv1(void) | |||
425 | } | 384 | } |
426 | } | 385 | } |
427 | 386 | ||
387 | tmds_setting->max_hres = max_h; | ||
428 | switch (max_h) { | 388 | switch (max_h) { |
429 | case 640: | 389 | case 640: |
430 | viaparinfo->tmds_setting_info->dvi_panel_size = | 390 | tmds_setting->max_vres = 480; |
431 | VIA_RES_640X480; | ||
432 | break; | 391 | break; |
433 | case 800: | 392 | case 800: |
434 | viaparinfo->tmds_setting_info->dvi_panel_size = | 393 | tmds_setting->max_vres = 600; |
435 | VIA_RES_800X600; | ||
436 | break; | 394 | break; |
437 | case 1024: | 395 | case 1024: |
438 | viaparinfo->tmds_setting_info->dvi_panel_size = | 396 | tmds_setting->max_vres = 768; |
439 | VIA_RES_1024X768; | ||
440 | break; | 397 | break; |
441 | case 1280: | 398 | case 1280: |
442 | viaparinfo->tmds_setting_info->dvi_panel_size = | 399 | tmds_setting->max_vres = 1024; |
443 | VIA_RES_1280X1024; | ||
444 | break; | 400 | break; |
445 | case 1400: | 401 | case 1400: |
446 | viaparinfo->tmds_setting_info->dvi_panel_size = | 402 | tmds_setting->max_vres = 1050; |
447 | VIA_RES_1400X1050; | ||
448 | break; | 403 | break; |
449 | case 1440: | 404 | case 1440: |
450 | viaparinfo->tmds_setting_info->dvi_panel_size = | 405 | tmds_setting->max_vres = 1050; |
451 | VIA_RES_1440X1050; | ||
452 | break; | 406 | break; |
453 | case 1600: | 407 | case 1600: |
454 | viaparinfo->tmds_setting_info->dvi_panel_size = | 408 | tmds_setting->max_vres = 1200; |
455 | VIA_RES_1600X1200; | ||
456 | break; | 409 | break; |
457 | case 1920: | 410 | case 1920: |
458 | if (max_v == 1200) { | 411 | tmds_setting->max_vres = 1080; |
459 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
460 | VIA_RES_1920X1200; | ||
461 | } else { | ||
462 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
463 | VIA_RES_1920X1080; | ||
464 | } | ||
465 | |||
466 | break; | 412 | break; |
467 | default: | 413 | default: |
468 | viaparinfo->tmds_setting_info->dvi_panel_size = | 414 | DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d ! " |
469 | VIA_RES_1024X768; | 415 | "set default panel size.\n", max_h); |
470 | DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d !\ | ||
471 | set default panel size.\n", max_h); | ||
472 | break; | 416 | break; |
473 | } | 417 | } |
474 | 418 | ||
475 | DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", | 419 | DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", |
476 | viaparinfo->tmds_setting_info->max_pixel_clock); | 420 | tmds_setting->max_pixel_clock); |
477 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; | 421 | tmds_chip->tmds_chip_slave_addr = restore; |
478 | return viaparinfo->tmds_setting_info->dvi_panel_size; | ||
479 | } | 422 | } |
480 | 423 | ||
481 | /* | 424 | /* Get Panel Size Using EDID2 Table */ |
482 | * | 425 | static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information |
483 | * int dvi_get_panel_size_from_DDCv2(void) | 426 | *tmds_chip, struct tmds_setting_information *tmds_setting) |
484 | * | ||
485 | * - Get Panel Size Using EDID2 Table | ||
486 | * | ||
487 | * Return Type: int | ||
488 | * | ||
489 | */ | ||
490 | static int dvi_get_panel_size_from_DDCv2(void) | ||
491 | { | 427 | { |
492 | int HSize = 0, restore; | 428 | int restore; |
493 | unsigned char R_Buffer[2]; | 429 | unsigned char R_Buffer[2]; |
494 | 430 | ||
495 | DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); | 431 | DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); |
496 | 432 | ||
497 | restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; | 433 | restore = tmds_chip->tmds_chip_slave_addr; |
498 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2; | 434 | tmds_chip->tmds_chip_slave_addr = 0xA2; |
499 | 435 | ||
500 | /* Horizontal: 0x76, 0x77 */ | 436 | /* Horizontal: 0x76, 0x77 */ |
501 | tmds_register_read_bytes(0x76, R_Buffer, 2); | 437 | tmds_register_read_bytes(0x76, R_Buffer, 2); |
502 | HSize = R_Buffer[0]; | 438 | tmds_setting->max_hres = R_Buffer[0] + (R_Buffer[1] << 8); |
503 | HSize += R_Buffer[1] << 8; | ||
504 | 439 | ||
505 | switch (HSize) { | 440 | switch (tmds_setting->max_hres) { |
506 | case 640: | 441 | case 640: |
507 | viaparinfo->tmds_setting_info->dvi_panel_size = | 442 | tmds_setting->max_vres = 480; |
508 | VIA_RES_640X480; | ||
509 | break; | 443 | break; |
510 | case 800: | 444 | case 800: |
511 | viaparinfo->tmds_setting_info->dvi_panel_size = | 445 | tmds_setting->max_vres = 600; |
512 | VIA_RES_800X600; | ||
513 | break; | 446 | break; |
514 | case 1024: | 447 | case 1024: |
515 | viaparinfo->tmds_setting_info->dvi_panel_size = | 448 | tmds_setting->max_vres = 768; |
516 | VIA_RES_1024X768; | ||
517 | break; | 449 | break; |
518 | case 1280: | 450 | case 1280: |
519 | viaparinfo->tmds_setting_info->dvi_panel_size = | 451 | tmds_setting->max_vres = 1024; |
520 | VIA_RES_1280X1024; | ||
521 | break; | 452 | break; |
522 | case 1400: | 453 | case 1400: |
523 | viaparinfo->tmds_setting_info->dvi_panel_size = | 454 | tmds_setting->max_vres = 1050; |
524 | VIA_RES_1400X1050; | ||
525 | break; | 455 | break; |
526 | case 1440: | 456 | case 1440: |
527 | viaparinfo->tmds_setting_info->dvi_panel_size = | 457 | tmds_setting->max_vres = 1050; |
528 | VIA_RES_1440X1050; | ||
529 | break; | 458 | break; |
530 | case 1600: | 459 | case 1600: |
531 | viaparinfo->tmds_setting_info->dvi_panel_size = | 460 | tmds_setting->max_vres = 1200; |
532 | VIA_RES_1600X1200; | ||
533 | break; | ||
534 | default: | ||
535 | viaparinfo->tmds_setting_info->dvi_panel_size = | ||
536 | VIA_RES_1024X768; | ||
537 | DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d!\ | ||
538 | set default panel size.\n", HSize); | ||
539 | break; | ||
540 | } | ||
541 | |||
542 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; | ||
543 | return viaparinfo->tmds_setting_info->dvi_panel_size; | ||
544 | } | ||
545 | |||
546 | /* | ||
547 | * | ||
548 | * unsigned char dvi_get_panel_info(void) | ||
549 | * | ||
550 | * - Get Panel Size | ||
551 | * | ||
552 | * Return Type: unsigned char | ||
553 | */ | ||
554 | static unsigned char dvi_get_panel_info(void) | ||
555 | { | ||
556 | unsigned char dvipanelsize; | ||
557 | DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n"); | ||
558 | |||
559 | viafb_dvi_sense(); | ||
560 | switch (viafb_dvi_query_EDID()) { | ||
561 | case 1: | ||
562 | dvi_get_panel_size_from_DDCv1(); | ||
563 | break; | ||
564 | case 2: | ||
565 | dvi_get_panel_size_from_DDCv2(); | ||
566 | break; | 461 | break; |
567 | default: | 462 | default: |
463 | DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d! " | ||
464 | "set default panel size.\n", tmds_setting->max_hres); | ||
568 | break; | 465 | break; |
569 | } | 466 | } |
570 | 467 | ||
571 | DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n", | 468 | tmds_chip->tmds_chip_slave_addr = restore; |
572 | viaparinfo->tmds_setting_info->dvi_panel_size); | ||
573 | dvipanelsize = (unsigned char)(viaparinfo-> | ||
574 | tmds_setting_info->dvi_panel_size); | ||
575 | return dvipanelsize; | ||
576 | } | 469 | } |
577 | 470 | ||
578 | /* If Disable DVI, turn off pad */ | 471 | /* If Disable DVI, turn off pad */ |
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h index e1ec37fb0dc3..0dffcfd395f3 100644 --- a/drivers/video/via/dvi.h +++ b/drivers/video/via/dvi.h | |||
@@ -53,12 +53,13 @@ | |||
53 | #define DEV_CONNECT_DVI 0x01 | 53 | #define DEV_CONNECT_DVI 0x01 |
54 | #define DEV_CONNECT_HDMI 0x02 | 54 | #define DEV_CONNECT_HDMI 0x02 |
55 | 55 | ||
56 | struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index); | ||
57 | int viafb_dvi_sense(void); | 56 | int viafb_dvi_sense(void); |
58 | void viafb_dvi_disable(void); | 57 | void viafb_dvi_disable(void); |
59 | void viafb_dvi_enable(void); | 58 | void viafb_dvi_enable(void); |
60 | int viafb_tmds_trasmitter_identify(void); | 59 | int viafb_tmds_trasmitter_identify(void); |
61 | void viafb_init_dvi_size(void); | 60 | void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, |
62 | void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga); | 61 | struct tmds_setting_information *tmds_setting); |
62 | void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, | ||
63 | int set_iga); | ||
63 | 64 | ||
64 | #endif /* __DVI_H__ */ | 65 | #endif /* __DVI_H__ */ |
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index b675cdbb03ad..1ee511b73307 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c | |||
@@ -23,15 +23,12 @@ int viafb_platform_epia_dvi = STATE_OFF; | |||
23 | int viafb_device_lcd_dualedge = STATE_OFF; | 23 | int viafb_device_lcd_dualedge = STATE_OFF; |
24 | int viafb_bus_width = 12; | 24 | int viafb_bus_width = 12; |
25 | int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI; | 25 | int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI; |
26 | int viafb_memsize; | ||
27 | int viafb_DeviceStatus = CRT_Device; | 26 | int viafb_DeviceStatus = CRT_Device; |
28 | int viafb_hotplug; | 27 | int viafb_hotplug; |
29 | int viafb_refresh = 60; | 28 | int viafb_refresh = 60; |
30 | int viafb_refresh1 = 60; | 29 | int viafb_refresh1 = 60; |
31 | int viafb_lcd_dsp_method = LCD_EXPANDSION; | 30 | int viafb_lcd_dsp_method = LCD_EXPANDSION; |
32 | int viafb_lcd_mode = LCD_OPENLDI; | 31 | int viafb_lcd_mode = LCD_OPENLDI; |
33 | int viafb_bpp = 32; | ||
34 | int viafb_bpp1 = 32; | ||
35 | int viafb_CRT_ON = 1; | 32 | int viafb_CRT_ON = 1; |
36 | int viafb_DVI_ON; | 33 | int viafb_DVI_ON; |
37 | int viafb_LCD_ON ; | 34 | int viafb_LCD_ON ; |
@@ -42,8 +39,6 @@ int viafb_hotplug_Xres = 640; | |||
42 | int viafb_hotplug_Yres = 480; | 39 | int viafb_hotplug_Yres = 480; |
43 | int viafb_hotplug_bpp = 32; | 40 | int viafb_hotplug_bpp = 32; |
44 | int viafb_hotplug_refresh = 60; | 41 | int viafb_hotplug_refresh = 60; |
45 | unsigned int viafb_second_offset; | ||
46 | int viafb_second_size; | ||
47 | int viafb_primary_dev = None_Device; | 42 | int viafb_primary_dev = None_Device; |
48 | unsigned int viafb_second_xres = 640; | 43 | unsigned int viafb_second_xres = 640; |
49 | unsigned int viafb_second_yres = 480; | 44 | unsigned int viafb_second_yres = 480; |
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index d69d0ca99c2f..8d95d5fd1388 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | #include "debug.h" | 36 | #include "debug.h" |
37 | 37 | ||
38 | #include "iface.h" | ||
39 | #include "viafbdev.h" | 38 | #include "viafbdev.h" |
40 | #include "chip.h" | 39 | #include "chip.h" |
41 | #include "accel.h" | 40 | #include "accel.h" |
@@ -68,8 +67,6 @@ extern int viafb_refresh; | |||
68 | extern int viafb_refresh1; | 67 | extern int viafb_refresh1; |
69 | extern int viafb_lcd_dsp_method; | 68 | extern int viafb_lcd_dsp_method; |
70 | extern int viafb_lcd_mode; | 69 | extern int viafb_lcd_mode; |
71 | extern int viafb_bpp; | ||
72 | extern int viafb_bpp1; | ||
73 | 70 | ||
74 | extern int viafb_CRT_ON; | 71 | extern int viafb_CRT_ON; |
75 | extern int viafb_hotplug_Xres; | 72 | extern int viafb_hotplug_Xres; |
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 3e083ff67ae2..f2583b1b527f 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c | |||
@@ -524,7 +524,6 @@ static void dvi_patch_skew_dvp1(void); | |||
524 | static void dvi_patch_skew_dvp_low(void); | 524 | static void dvi_patch_skew_dvp_low(void); |
525 | static void set_dvi_output_path(int set_iga, int output_interface); | 525 | static void set_dvi_output_path(int set_iga, int output_interface); |
526 | static void set_lcd_output_path(int set_iga, int output_interface); | 526 | static void set_lcd_output_path(int set_iga, int output_interface); |
527 | static int search_mode_setting(int ModeInfoIndex); | ||
528 | static void load_fix_bit_crtc_reg(void); | 527 | static void load_fix_bit_crtc_reg(void); |
529 | static void init_gfx_chip_info(struct pci_dev *pdev, | 528 | static void init_gfx_chip_info(struct pci_dev *pdev, |
530 | const struct pci_device_id *pdi); | 529 | const struct pci_device_id *pdi); |
@@ -686,6 +685,84 @@ void viafb_set_secondary_pitch(u32 pitch) | |||
686 | viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); | 685 | viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); |
687 | } | 686 | } |
688 | 687 | ||
688 | void viafb_set_primary_color_depth(u8 depth) | ||
689 | { | ||
690 | u8 value; | ||
691 | |||
692 | DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth); | ||
693 | switch (depth) { | ||
694 | case 8: | ||
695 | value = 0x00; | ||
696 | break; | ||
697 | case 15: | ||
698 | value = 0x04; | ||
699 | break; | ||
700 | case 16: | ||
701 | value = 0x14; | ||
702 | break; | ||
703 | case 24: | ||
704 | value = 0x0C; | ||
705 | break; | ||
706 | case 30: | ||
707 | value = 0x08; | ||
708 | break; | ||
709 | default: | ||
710 | printk(KERN_WARNING "viafb_set_primary_color_depth: " | ||
711 | "Unsupported depth: %d\n", depth); | ||
712 | return; | ||
713 | } | ||
714 | |||
715 | viafb_write_reg_mask(0x15, VIASR, value, 0x1C); | ||
716 | } | ||
717 | |||
718 | void viafb_set_secondary_color_depth(u8 depth) | ||
719 | { | ||
720 | u8 value; | ||
721 | |||
722 | DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth); | ||
723 | switch (depth) { | ||
724 | case 8: | ||
725 | value = 0x00; | ||
726 | break; | ||
727 | case 16: | ||
728 | value = 0x40; | ||
729 | break; | ||
730 | case 24: | ||
731 | value = 0xC0; | ||
732 | break; | ||
733 | case 30: | ||
734 | value = 0x80; | ||
735 | break; | ||
736 | default: | ||
737 | printk(KERN_WARNING "viafb_set_secondary_color_depth: " | ||
738 | "Unsupported depth: %d\n", depth); | ||
739 | return; | ||
740 | } | ||
741 | |||
742 | viafb_write_reg_mask(0x67, VIACR, value, 0xC0); | ||
743 | } | ||
744 | |||
745 | static void set_color_register(u8 index, u8 red, u8 green, u8 blue) | ||
746 | { | ||
747 | outb(0xFF, 0x3C6); /* bit mask of palette */ | ||
748 | outb(index, 0x3C8); | ||
749 | outb(red, 0x3C9); | ||
750 | outb(green, 0x3C9); | ||
751 | outb(blue, 0x3C9); | ||
752 | } | ||
753 | |||
754 | void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue) | ||
755 | { | ||
756 | viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01); | ||
757 | set_color_register(index, red, green, blue); | ||
758 | } | ||
759 | |||
760 | void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue) | ||
761 | { | ||
762 | viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01); | ||
763 | set_color_register(index, red, green, blue); | ||
764 | } | ||
765 | |||
689 | void viafb_set_output_path(int device, int set_iga, int output_interface) | 766 | void viafb_set_output_path(int device, int set_iga, int output_interface) |
690 | { | 767 | { |
691 | switch (device) { | 768 | switch (device) { |
@@ -710,11 +787,8 @@ static void set_crt_output_path(int set_iga) | |||
710 | viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6); | 787 | viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6); |
711 | break; | 788 | break; |
712 | case IGA2: | 789 | case IGA2: |
713 | case IGA1_IGA2: | ||
714 | viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); | 790 | viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); |
715 | viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6); | 791 | viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6); |
716 | if (set_iga == IGA1_IGA2) | ||
717 | viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); | ||
718 | break; | 792 | break; |
719 | } | 793 | } |
720 | } | 794 | } |
@@ -904,13 +978,6 @@ static void set_lcd_output_path(int set_iga, int output_interface) | |||
904 | 978 | ||
905 | enable_second_display_channel(); | 979 | enable_second_display_channel(); |
906 | break; | 980 | break; |
907 | |||
908 | case IGA1_IGA2: | ||
909 | viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); | ||
910 | viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); | ||
911 | |||
912 | disable_second_display_channel(); | ||
913 | break; | ||
914 | } | 981 | } |
915 | 982 | ||
916 | switch (output_interface) { | 983 | switch (output_interface) { |
@@ -987,49 +1054,6 @@ static void set_lcd_output_path(int set_iga, int output_interface) | |||
987 | } | 1054 | } |
988 | } | 1055 | } |
989 | 1056 | ||
990 | /* Search Mode Index */ | ||
991 | static int search_mode_setting(int ModeInfoIndex) | ||
992 | { | ||
993 | int i = 0; | ||
994 | |||
995 | while ((i < NUM_TOTAL_MODETABLE) && | ||
996 | (ModeInfoIndex != CLE266Modes[i].ModeIndex)) | ||
997 | i++; | ||
998 | if (i >= NUM_TOTAL_MODETABLE) | ||
999 | i = 0; | ||
1000 | return i; | ||
1001 | |||
1002 | } | ||
1003 | |||
1004 | struct VideoModeTable *viafb_get_modetbl_pointer(int Index) | ||
1005 | { | ||
1006 | struct VideoModeTable *TmpTbl = NULL; | ||
1007 | TmpTbl = &CLE266Modes[search_mode_setting(Index)]; | ||
1008 | return TmpTbl; | ||
1009 | } | ||
1010 | |||
1011 | struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index) | ||
1012 | { | ||
1013 | struct VideoModeTable *TmpTbl = NULL; | ||
1014 | int i = 0; | ||
1015 | while ((i < NUM_TOTAL_CEA_MODES) && | ||
1016 | (Index != CEA_HDMI_Modes[i].ModeIndex)) | ||
1017 | i++; | ||
1018 | if ((i < NUM_TOTAL_CEA_MODES)) | ||
1019 | TmpTbl = &CEA_HDMI_Modes[i]; | ||
1020 | else { | ||
1021 | /*Still use general timing if don't find CEA timing */ | ||
1022 | i = 0; | ||
1023 | while ((i < NUM_TOTAL_MODETABLE) && | ||
1024 | (Index != CLE266Modes[i].ModeIndex)) | ||
1025 | i++; | ||
1026 | if (i >= NUM_TOTAL_MODETABLE) | ||
1027 | i = 0; | ||
1028 | TmpTbl = &CLE266Modes[i]; | ||
1029 | } | ||
1030 | return TmpTbl; | ||
1031 | } | ||
1032 | |||
1033 | static void load_fix_bit_crtc_reg(void) | 1057 | static void load_fix_bit_crtc_reg(void) |
1034 | { | 1058 | { |
1035 | /* always set to 1 */ | 1059 | /* always set to 1 */ |
@@ -1121,15 +1145,13 @@ void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) | |||
1121 | struct io_register *reg = NULL; | 1145 | struct io_register *reg = NULL; |
1122 | 1146 | ||
1123 | switch (set_iga) { | 1147 | switch (set_iga) { |
1124 | case IGA1_IGA2: | ||
1125 | case IGA1: | 1148 | case IGA1: |
1126 | reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte); | 1149 | reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte); |
1127 | viafb_load_reg_num = fetch_count_reg. | 1150 | viafb_load_reg_num = fetch_count_reg. |
1128 | iga1_fetch_count_reg.reg_num; | 1151 | iga1_fetch_count_reg.reg_num; |
1129 | reg = fetch_count_reg.iga1_fetch_count_reg.reg; | 1152 | reg = fetch_count_reg.iga1_fetch_count_reg.reg; |
1130 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | 1153 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); |
1131 | if (set_iga == IGA1) | 1154 | break; |
1132 | break; | ||
1133 | case IGA2: | 1155 | case IGA2: |
1134 | reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte); | 1156 | reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte); |
1135 | viafb_load_reg_num = fetch_count_reg. | 1157 | viafb_load_reg_num = fetch_count_reg. |
@@ -1499,7 +1521,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) | |||
1499 | /* H.W. Reset : ON */ | 1521 | /* H.W. Reset : ON */ |
1500 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | 1522 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); |
1501 | 1523 | ||
1502 | if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { | 1524 | if (set_iga == IGA1) { |
1503 | /* Change D,N FOR VCLK */ | 1525 | /* Change D,N FOR VCLK */ |
1504 | switch (viaparinfo->chip_info->gfx_chip_name) { | 1526 | switch (viaparinfo->chip_info->gfx_chip_name) { |
1505 | case UNICHROME_CLE266: | 1527 | case UNICHROME_CLE266: |
@@ -1528,7 +1550,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) | |||
1528 | } | 1550 | } |
1529 | } | 1551 | } |
1530 | 1552 | ||
1531 | if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { | 1553 | if (set_iga == IGA2) { |
1532 | /* Change D,N FOR LCK */ | 1554 | /* Change D,N FOR LCK */ |
1533 | switch (viaparinfo->chip_info->gfx_chip_name) { | 1555 | switch (viaparinfo->chip_info->gfx_chip_name) { |
1534 | case UNICHROME_CLE266: | 1556 | case UNICHROME_CLE266: |
@@ -1557,12 +1579,12 @@ void viafb_set_vclock(u32 CLK, int set_iga) | |||
1557 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | 1579 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); |
1558 | 1580 | ||
1559 | /* Reset PLL */ | 1581 | /* Reset PLL */ |
1560 | if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { | 1582 | if (set_iga == IGA1) { |
1561 | viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); | 1583 | viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); |
1562 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); | 1584 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); |
1563 | } | 1585 | } |
1564 | 1586 | ||
1565 | if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { | 1587 | if (set_iga == IGA2) { |
1566 | viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0); | 1588 | viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0); |
1567 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0); | 1589 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0); |
1568 | } | 1590 | } |
@@ -1805,47 +1827,15 @@ void viafb_load_crtc_timing(struct display_timing device_timing, | |||
1805 | viafb_lock_crt(); | 1827 | viafb_lock_crt(); |
1806 | } | 1828 | } |
1807 | 1829 | ||
1808 | void viafb_set_color_depth(int bpp_byte, int set_iga) | ||
1809 | { | ||
1810 | if (set_iga == IGA1) { | ||
1811 | switch (bpp_byte) { | ||
1812 | case MODE_8BPP: | ||
1813 | viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E); | ||
1814 | break; | ||
1815 | case MODE_16BPP: | ||
1816 | viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE); | ||
1817 | break; | ||
1818 | case MODE_32BPP: | ||
1819 | viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE); | ||
1820 | break; | ||
1821 | } | ||
1822 | } else { | ||
1823 | switch (bpp_byte) { | ||
1824 | case MODE_8BPP: | ||
1825 | viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7); | ||
1826 | break; | ||
1827 | case MODE_16BPP: | ||
1828 | viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7); | ||
1829 | break; | ||
1830 | case MODE_32BPP: | ||
1831 | viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7); | ||
1832 | break; | ||
1833 | } | ||
1834 | } | ||
1835 | } | ||
1836 | |||
1837 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | 1830 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, |
1838 | int mode_index, int bpp_byte, int set_iga) | 1831 | struct VideoModeTable *video_mode, int bpp_byte, int set_iga) |
1839 | { | 1832 | { |
1840 | struct VideoModeTable *video_mode; | ||
1841 | struct display_timing crt_reg; | 1833 | struct display_timing crt_reg; |
1842 | int i; | 1834 | int i; |
1843 | int index = 0; | 1835 | int index = 0; |
1844 | int h_addr, v_addr; | 1836 | int h_addr, v_addr; |
1845 | u32 pll_D_N; | 1837 | u32 pll_D_N; |
1846 | 1838 | ||
1847 | video_mode = &CLE266Modes[search_mode_setting(mode_index)]; | ||
1848 | |||
1849 | for (i = 0; i < video_mode->mode_array; i++) { | 1839 | for (i = 0; i < video_mode->mode_array; i++) { |
1850 | index = i; | 1840 | index = i; |
1851 | 1841 | ||
@@ -1858,8 +1848,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | |||
1858 | 1848 | ||
1859 | /* Mode 640x480 has border, but LCD/DFP didn't have border. */ | 1849 | /* Mode 640x480 has border, but LCD/DFP didn't have border. */ |
1860 | /* So we would delete border. */ | 1850 | /* So we would delete border. */ |
1861 | if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480) | 1851 | if ((viafb_LCD_ON | viafb_DVI_ON) |
1862 | && (viaparinfo->crt_setting_info->refresh_rate == 60)) { | 1852 | && video_mode->crtc[0].crtc.hor_addr == 640 |
1853 | && video_mode->crtc[0].crtc.ver_addr == 480 | ||
1854 | && viaparinfo->crt_setting_info->refresh_rate == 60) { | ||
1863 | /* The border is 8 pixels. */ | 1855 | /* The border is 8 pixels. */ |
1864 | crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; | 1856 | crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; |
1865 | 1857 | ||
@@ -1912,9 +1904,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | |||
1912 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | 1904 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) |
1913 | viafb_load_FIFO_reg(set_iga, h_addr, v_addr); | 1905 | viafb_load_FIFO_reg(set_iga, h_addr, v_addr); |
1914 | 1906 | ||
1915 | /* load SR Register About Memory and Color part */ | ||
1916 | viafb_set_color_depth(bpp_byte, set_iga); | ||
1917 | |||
1918 | pll_D_N = viafb_get_clk_value(crt_table[index].clk); | 1907 | pll_D_N = viafb_get_clk_value(crt_table[index].clk); |
1919 | DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N); | 1908 | DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N); |
1920 | viafb_set_vclock(pll_D_N, set_iga); | 1909 | viafb_set_vclock(pll_D_N, set_iga); |
@@ -1956,9 +1945,6 @@ void viafb_update_device_setting(int hres, int vres, | |||
1956 | 1945 | ||
1957 | viaparinfo->tmds_setting_info->h_active = hres; | 1946 | viaparinfo->tmds_setting_info->h_active = hres; |
1958 | viaparinfo->tmds_setting_info->v_active = vres; | 1947 | viaparinfo->tmds_setting_info->v_active = vres; |
1959 | viaparinfo->tmds_setting_info->bpp = bpp; | ||
1960 | viaparinfo->tmds_setting_info->refresh_rate = | ||
1961 | vmode_refresh; | ||
1962 | 1948 | ||
1963 | viaparinfo->lvds_setting_info->h_active = hres; | 1949 | viaparinfo->lvds_setting_info->h_active = hres; |
1964 | viaparinfo->lvds_setting_info->v_active = vres; | 1950 | viaparinfo->lvds_setting_info->v_active = vres; |
@@ -1975,9 +1961,6 @@ void viafb_update_device_setting(int hres, int vres, | |||
1975 | if (viaparinfo->tmds_setting_info->iga_path == IGA2) { | 1961 | if (viaparinfo->tmds_setting_info->iga_path == IGA2) { |
1976 | viaparinfo->tmds_setting_info->h_active = hres; | 1962 | viaparinfo->tmds_setting_info->h_active = hres; |
1977 | viaparinfo->tmds_setting_info->v_active = vres; | 1963 | viaparinfo->tmds_setting_info->v_active = vres; |
1978 | viaparinfo->tmds_setting_info->bpp = bpp; | ||
1979 | viaparinfo->tmds_setting_info->refresh_rate = | ||
1980 | vmode_refresh; | ||
1981 | } | 1964 | } |
1982 | 1965 | ||
1983 | if (viaparinfo->lvds_setting_info->iga_path == IGA2) { | 1966 | if (viaparinfo->lvds_setting_info->iga_path == IGA2) { |
@@ -2076,9 +2059,8 @@ static void init_tmds_chip_info(void) | |||
2076 | 2059 | ||
2077 | DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", | 2060 | DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", |
2078 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); | 2061 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); |
2079 | viaparinfo->tmds_setting_info->get_dvi_size_method = | 2062 | viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info, |
2080 | GET_DVI_SIZE_BY_VGA_BIOS; | 2063 | &viaparinfo->shared->tmds_setting_info); |
2081 | viafb_init_dvi_size(); | ||
2082 | } | 2064 | } |
2083 | 2065 | ||
2084 | static void init_lvds_chip_info(void) | 2066 | static void init_lvds_chip_info(void) |
@@ -2195,28 +2177,19 @@ static void set_display_channel(void) | |||
2195 | } | 2177 | } |
2196 | } | 2178 | } |
2197 | 2179 | ||
2198 | int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | 2180 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, |
2199 | int vmode_index1, int hor_res1, int ver_res1, int video_bpp1) | 2181 | struct VideoModeTable *vmode_tbl1, int video_bpp1) |
2200 | { | 2182 | { |
2201 | int i, j; | 2183 | int i, j; |
2202 | int port; | 2184 | int port; |
2203 | u8 value, index, mask; | 2185 | u8 value, index, mask; |
2204 | struct VideoModeTable *vmode_tbl; | ||
2205 | struct crt_mode_table *crt_timing; | 2186 | struct crt_mode_table *crt_timing; |
2206 | struct VideoModeTable *vmode_tbl1 = NULL; | ||
2207 | struct crt_mode_table *crt_timing1 = NULL; | 2187 | struct crt_mode_table *crt_timing1 = NULL; |
2208 | 2188 | ||
2209 | DEBUG_MSG(KERN_INFO "Set Mode!!\n"); | ||
2210 | DEBUG_MSG(KERN_INFO | ||
2211 | "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n", | ||
2212 | vmode_index, hor_res, ver_res, video_bpp); | ||
2213 | |||
2214 | device_screen_off(); | 2189 | device_screen_off(); |
2215 | vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)]; | ||
2216 | crt_timing = vmode_tbl->crtc; | 2190 | crt_timing = vmode_tbl->crtc; |
2217 | 2191 | ||
2218 | if (viafb_SAMM_ON == 1) { | 2192 | if (viafb_SAMM_ON == 1) { |
2219 | vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)]; | ||
2220 | crt_timing1 = vmode_tbl1->crtc; | 2193 | crt_timing1 = vmode_tbl1->crtc; |
2221 | } | 2194 | } |
2222 | 2195 | ||
@@ -2267,12 +2240,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | |||
2267 | outb(VPIT.SR[i - 1], VIASR + 1); | 2240 | outb(VPIT.SR[i - 1], VIASR + 1); |
2268 | } | 2241 | } |
2269 | 2242 | ||
2270 | viafb_set_primary_address(0); | 2243 | viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); |
2271 | viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); | ||
2272 | viafb_set_iga_path(); | 2244 | viafb_set_iga_path(); |
2273 | 2245 | ||
2274 | /* Write CRTC */ | 2246 | /* Write CRTC */ |
2275 | viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1); | 2247 | viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1); |
2276 | 2248 | ||
2277 | /* Write Graphic Controller */ | 2249 | /* Write Graphic Controller */ |
2278 | for (i = 0; i < StdGR; i++) { | 2250 | for (i = 0; i < StdGR; i++) { |
@@ -2292,65 +2264,25 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | |||
2292 | 2264 | ||
2293 | /* Update Patch Register */ | 2265 | /* Update Patch Register */ |
2294 | 2266 | ||
2295 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | 2267 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 |
2296 | || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) { | 2268 | || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) |
2297 | for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { | 2269 | && vmode_tbl->crtc[0].crtc.hor_addr == 1024 |
2298 | if (res_patch_table[i].mode_index == vmode_index) { | 2270 | && vmode_tbl->crtc[0].crtc.ver_addr == 768) { |
2299 | for (j = 0; | 2271 | for (j = 0; j < res_patch_table[0].table_length; j++) { |
2300 | j < res_patch_table[i].table_length; j++) { | 2272 | index = res_patch_table[0].io_reg_table[j].index; |
2301 | index = | 2273 | port = res_patch_table[0].io_reg_table[j].port; |
2302 | res_patch_table[i]. | 2274 | value = res_patch_table[0].io_reg_table[j].value; |
2303 | io_reg_table[j].index; | 2275 | mask = res_patch_table[0].io_reg_table[j].mask; |
2304 | port = | 2276 | viafb_write_reg_mask(index, port, value, mask); |
2305 | res_patch_table[i]. | ||
2306 | io_reg_table[j].port; | ||
2307 | value = | ||
2308 | res_patch_table[i]. | ||
2309 | io_reg_table[j].value; | ||
2310 | mask = | ||
2311 | res_patch_table[i]. | ||
2312 | io_reg_table[j].mask; | ||
2313 | viafb_write_reg_mask(index, port, value, | ||
2314 | mask); | ||
2315 | } | ||
2316 | } | ||
2317 | } | ||
2318 | } | ||
2319 | |||
2320 | if (viafb_SAMM_ON == 1) { | ||
2321 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
2322 | || (viaparinfo->chip_info->gfx_chip_name == | ||
2323 | UNICHROME_K400)) { | ||
2324 | for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { | ||
2325 | if (res_patch_table[i].mode_index == | ||
2326 | vmode_index1) { | ||
2327 | for (j = 0; | ||
2328 | j < | ||
2329 | res_patch_table[i]. | ||
2330 | table_length; j++) { | ||
2331 | index = | ||
2332 | res_patch_table[i]. | ||
2333 | io_reg_table[j].index; | ||
2334 | port = | ||
2335 | res_patch_table[i]. | ||
2336 | io_reg_table[j].port; | ||
2337 | value = | ||
2338 | res_patch_table[i]. | ||
2339 | io_reg_table[j].value; | ||
2340 | mask = | ||
2341 | res_patch_table[i]. | ||
2342 | io_reg_table[j].mask; | ||
2343 | viafb_write_reg_mask(index, | ||
2344 | port, value, mask); | ||
2345 | } | ||
2346 | } | ||
2347 | } | ||
2348 | } | 2277 | } |
2349 | } | 2278 | } |
2350 | 2279 | ||
2351 | viafb_set_primary_pitch(viafbinfo->fix.line_length); | 2280 | viafb_set_primary_pitch(viafbinfo->fix.line_length); |
2352 | viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length | 2281 | viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length |
2353 | : viafbinfo->fix.line_length); | 2282 | : viafbinfo->fix.line_length); |
2283 | viafb_set_primary_color_depth(viaparinfo->depth); | ||
2284 | viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth | ||
2285 | : viaparinfo->depth); | ||
2354 | /* Update Refresh Rate Setting */ | 2286 | /* Update Refresh Rate Setting */ |
2355 | 2287 | ||
2356 | /* Clear On Screen */ | 2288 | /* Clear On Screen */ |
@@ -2359,11 +2291,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | |||
2359 | if (viafb_CRT_ON) { | 2291 | if (viafb_CRT_ON) { |
2360 | if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path == | 2292 | if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path == |
2361 | IGA2)) { | 2293 | IGA2)) { |
2362 | viafb_fill_crtc_timing(crt_timing1, vmode_index1, | 2294 | viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, |
2363 | video_bpp1 / 8, | 2295 | video_bpp1 / 8, |
2364 | viaparinfo->crt_setting_info->iga_path); | 2296 | viaparinfo->crt_setting_info->iga_path); |
2365 | } else { | 2297 | } else { |
2366 | viafb_fill_crtc_timing(crt_timing, vmode_index, | 2298 | viafb_fill_crtc_timing(crt_timing, vmode_tbl, |
2367 | video_bpp / 8, | 2299 | video_bpp / 8, |
2368 | viaparinfo->crt_setting_info->iga_path); | 2300 | viaparinfo->crt_setting_info->iga_path); |
2369 | } | 2301 | } |
@@ -2373,7 +2305,7 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | |||
2373 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode | 2305 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode |
2374 | to 8 alignment (1368),there is several pixels (2 pixels) | 2306 | to 8 alignment (1368),there is several pixels (2 pixels) |
2375 | on right side of screen. */ | 2307 | on right side of screen. */ |
2376 | if (hor_res % 8) { | 2308 | if (vmode_tbl->crtc[0].crtc.hor_addr % 8) { |
2377 | viafb_unlock_crt(); | 2309 | viafb_unlock_crt(); |
2378 | viafb_write_reg(CR02, VIACR, | 2310 | viafb_write_reg(CR02, VIACR, |
2379 | viafb_read_reg(VIACR, CR02) - 1); | 2311 | viafb_read_reg(VIACR, CR02) - 1); |
@@ -2384,14 +2316,14 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | |||
2384 | if (viafb_DVI_ON) { | 2316 | if (viafb_DVI_ON) { |
2385 | if (viafb_SAMM_ON && | 2317 | if (viafb_SAMM_ON && |
2386 | (viaparinfo->tmds_setting_info->iga_path == IGA2)) { | 2318 | (viaparinfo->tmds_setting_info->iga_path == IGA2)) { |
2387 | viafb_dvi_set_mode(viafb_get_mode_index | 2319 | viafb_dvi_set_mode(viafb_get_mode |
2388 | (viaparinfo->tmds_setting_info->h_active, | 2320 | (viaparinfo->tmds_setting_info->h_active, |
2389 | viaparinfo->tmds_setting_info-> | 2321 | viaparinfo->tmds_setting_info-> |
2390 | v_active), | 2322 | v_active), |
2391 | video_bpp1, viaparinfo-> | 2323 | video_bpp1, viaparinfo-> |
2392 | tmds_setting_info->iga_path); | 2324 | tmds_setting_info->iga_path); |
2393 | } else { | 2325 | } else { |
2394 | viafb_dvi_set_mode(viafb_get_mode_index | 2326 | viafb_dvi_set_mode(viafb_get_mode |
2395 | (viaparinfo->tmds_setting_info->h_active, | 2327 | (viaparinfo->tmds_setting_info->h_active, |
2396 | viaparinfo-> | 2328 | viaparinfo-> |
2397 | tmds_setting_info->v_active), | 2329 | tmds_setting_info->v_active), |
@@ -2445,8 +2377,8 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, | |||
2445 | 2377 | ||
2446 | /* If set mode normally, save resolution information for hot-plug . */ | 2378 | /* If set mode normally, save resolution information for hot-plug . */ |
2447 | if (!viafb_hotplug) { | 2379 | if (!viafb_hotplug) { |
2448 | viafb_hotplug_Xres = hor_res; | 2380 | viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr; |
2449 | viafb_hotplug_Yres = ver_res; | 2381 | viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr; |
2450 | viafb_hotplug_bpp = video_bpp; | 2382 | viafb_hotplug_bpp = video_bpp; |
2451 | viafb_hotplug_refresh = viafb_refresh; | 2383 | viafb_hotplug_refresh = viafb_refresh; |
2452 | 2384 | ||
@@ -2706,13 +2638,11 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | |||
2706 | 2638 | ||
2707 | /*According var's xres, yres fill var's other timing information*/ | 2639 | /*According var's xres, yres fill var's other timing information*/ |
2708 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 2640 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, |
2709 | int mode_index) | 2641 | struct VideoModeTable *vmode_tbl) |
2710 | { | 2642 | { |
2711 | struct VideoModeTable *vmode_tbl = NULL; | ||
2712 | struct crt_mode_table *crt_timing = NULL; | 2643 | struct crt_mode_table *crt_timing = NULL; |
2713 | struct display_timing crt_reg; | 2644 | struct display_timing crt_reg; |
2714 | int i = 0, index = 0; | 2645 | int i = 0, index = 0; |
2715 | vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)]; | ||
2716 | crt_timing = vmode_tbl->crtc; | 2646 | crt_timing = vmode_tbl->crtc; |
2717 | for (i = 0; i < vmode_tbl->mode_array; i++) { | 2647 | for (i = 0; i < vmode_tbl->mode_array; i++) { |
2718 | index = i; | 2648 | index = i; |
@@ -2721,36 +2651,6 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | |||
2721 | } | 2651 | } |
2722 | 2652 | ||
2723 | crt_reg = crt_timing[index].crtc; | 2653 | crt_reg = crt_timing[index].crtc; |
2724 | switch (var->bits_per_pixel) { | ||
2725 | case 8: | ||
2726 | var->red.offset = 0; | ||
2727 | var->green.offset = 0; | ||
2728 | var->blue.offset = 0; | ||
2729 | var->red.length = 6; | ||
2730 | var->green.length = 6; | ||
2731 | var->blue.length = 6; | ||
2732 | break; | ||
2733 | case 16: | ||
2734 | var->red.offset = 11; | ||
2735 | var->green.offset = 5; | ||
2736 | var->blue.offset = 0; | ||
2737 | var->red.length = 5; | ||
2738 | var->green.length = 6; | ||
2739 | var->blue.length = 5; | ||
2740 | break; | ||
2741 | case 32: | ||
2742 | var->red.offset = 16; | ||
2743 | var->green.offset = 8; | ||
2744 | var->blue.offset = 0; | ||
2745 | var->red.length = 8; | ||
2746 | var->green.length = 8; | ||
2747 | var->blue.length = 8; | ||
2748 | break; | ||
2749 | default: | ||
2750 | /* never happed, put here to keep consistent */ | ||
2751 | break; | ||
2752 | } | ||
2753 | |||
2754 | var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); | 2654 | var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); |
2755 | var->left_margin = | 2655 | var->left_margin = |
2756 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); | 2656 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); |
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index b874d952b446..12ef32d334cb 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #ifndef __HW_H__ | 22 | #ifndef __HW_H__ |
23 | #define __HW_H__ | 23 | #define __HW_H__ |
24 | 24 | ||
25 | #include "viamode.h" | ||
25 | #include "global.h" | 26 | #include "global.h" |
26 | 27 | ||
27 | /*************************************************** | 28 | /*************************************************** |
@@ -862,8 +863,6 @@ struct pci_device_id_info { | |||
862 | }; | 863 | }; |
863 | 864 | ||
864 | extern unsigned int viafb_second_virtual_xres; | 865 | extern unsigned int viafb_second_virtual_xres; |
865 | extern unsigned int viafb_second_offset; | ||
866 | extern int viafb_second_size; | ||
867 | extern int viafb_SAMM_ON; | 866 | extern int viafb_SAMM_ON; |
868 | extern int viafb_dual_fb; | 867 | extern int viafb_dual_fb; |
869 | extern int viafb_LCD2_ON; | 868 | extern int viafb_LCD2_ON; |
@@ -874,8 +873,9 @@ extern int viafb_hotplug; | |||
874 | void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); | 873 | void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); |
875 | void viafb_set_output_path(int device, int set_iga, | 874 | void viafb_set_output_path(int device, int set_iga, |
876 | int output_interface); | 875 | int output_interface); |
876 | |||
877 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | 877 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, |
878 | int mode_index, int bpp_byte, int set_iga); | 878 | struct VideoModeTable *video_mode, int bpp_byte, int set_iga); |
879 | 879 | ||
880 | void viafb_set_vclock(u32 CLK, int set_iga); | 880 | void viafb_set_vclock(u32 CLK, int set_iga); |
881 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, | 881 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, |
@@ -891,16 +891,15 @@ void viafb_lock_crt(void); | |||
891 | void viafb_unlock_crt(void); | 891 | void viafb_unlock_crt(void); |
892 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); | 892 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); |
893 | void viafb_write_regx(struct io_reg RegTable[], int ItemNum); | 893 | void viafb_write_regx(struct io_reg RegTable[], int ItemNum); |
894 | struct VideoModeTable *viafb_get_modetbl_pointer(int Index); | ||
895 | u32 viafb_get_clk_value(int clk); | 894 | u32 viafb_get_clk_value(int clk); |
896 | void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); | 895 | void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); |
897 | void viafb_set_color_depth(int bpp_byte, int set_iga); | ||
898 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | 896 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ |
899 | *p_gfx_dpa_setting); | 897 | *p_gfx_dpa_setting); |
900 | 898 | ||
901 | int viafb_setmode(int vmode_index, int hor_res, int ver_res, | 899 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, |
902 | int video_bpp, int vmode_index1, int hor_res1, | 900 | struct VideoModeTable *vmode_tbl1, int video_bpp1); |
903 | int ver_res1, int video_bpp1); | 901 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, |
902 | struct VideoModeTable *vmode_tbl); | ||
904 | void viafb_init_chip_info(struct pci_dev *pdev, | 903 | void viafb_init_chip_info(struct pci_dev *pdev, |
905 | const struct pci_device_id *pdi); | 904 | const struct pci_device_id *pdi); |
906 | void viafb_init_dac(int set_iga); | 905 | void viafb_init_dac(int set_iga); |
@@ -915,6 +914,8 @@ void viafb_set_primary_address(u32 addr); | |||
915 | void viafb_set_secondary_address(u32 addr); | 914 | void viafb_set_secondary_address(u32 addr); |
916 | void viafb_set_primary_pitch(u32 pitch); | 915 | void viafb_set_primary_pitch(u32 pitch); |
917 | void viafb_set_secondary_pitch(u32 pitch); | 916 | void viafb_set_secondary_pitch(u32 pitch); |
917 | void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); | ||
918 | void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); | ||
918 | void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); | 919 | void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); |
919 | 920 | ||
920 | #endif /* __HW_H__ */ | 921 | #endif /* __HW_H__ */ |
diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c deleted file mode 100644 index 1570636c8d51..000000000000 --- a/drivers/video/via/iface.c +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include "global.h" | ||
23 | |||
24 | /* Get frame buffer size from VGA BIOS */ | ||
25 | |||
26 | unsigned int viafb_get_memsize(void) | ||
27 | { | ||
28 | unsigned int m; | ||
29 | |||
30 | /* If memory size provided by user */ | ||
31 | if (viafb_memsize) | ||
32 | m = viafb_memsize * Mb; | ||
33 | else { | ||
34 | m = (unsigned int)viafb_read_reg(VIASR, SR39); | ||
35 | m = m * (4 * Mb); | ||
36 | |||
37 | if ((m < (16 * Mb)) || (m > (64 * Mb))) | ||
38 | m = 16 * Mb; | ||
39 | } | ||
40 | DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb); | ||
41 | return m; | ||
42 | } | ||
43 | |||
44 | /* Get Video Buffer Starting Physical Address(back door)*/ | ||
45 | |||
46 | unsigned long viafb_get_videobuf_addr(void) | ||
47 | { | ||
48 | struct pci_dev *pdev = NULL; | ||
49 | unsigned char sys_mem; | ||
50 | unsigned char video_mem; | ||
51 | unsigned long sys_mem_size; | ||
52 | unsigned long video_mem_size; | ||
53 | /*system memory = 256 MB, video memory 64 MB */ | ||
54 | unsigned long vmem_starting_adr = 0x0C000000; | ||
55 | |||
56 | pdev = | ||
57 | (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID, | ||
58 | VIA_K800_BRIDGE_DID, NULL); | ||
59 | if (pdev != NULL) { | ||
60 | pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG, | ||
61 | &sys_mem); | ||
62 | pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG, | ||
63 | &video_mem); | ||
64 | video_mem = (video_mem & 0x70) >> 4; | ||
65 | sys_mem_size = ((unsigned long)sys_mem) << 24; | ||
66 | if (video_mem != 0) | ||
67 | video_mem_size = (1 << (video_mem)) * 1024 * 1024; | ||
68 | else | ||
69 | video_mem_size = 0; | ||
70 | |||
71 | vmem_starting_adr = sys_mem_size - video_mem_size; | ||
72 | pci_dev_put(pdev); | ||
73 | } | ||
74 | |||
75 | DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n", | ||
76 | vmem_starting_adr); | ||
77 | return vmem_starting_adr; | ||
78 | } | ||
diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h deleted file mode 100644 index 790ec3e3aea2..000000000000 --- a/drivers/video/via/iface.h +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __IFACE_H__ | ||
23 | #define __IFACE_H__ | ||
24 | |||
25 | #define Kb (1024) | ||
26 | #define Mb (Kb*Kb) | ||
27 | |||
28 | #define VIA_K800_BRIDGE_VID 0x1106 | ||
29 | #define VIA_K800_BRIDGE_DID 0x3204 | ||
30 | |||
31 | #define VIA_K800_SYSTEM_MEMORY_REG 0x47 | ||
32 | #define VIA_K800_VIDEO_MEMORY_REG 0xA1 | ||
33 | |||
34 | extern int viafb_memsize; | ||
35 | unsigned int viafb_get_memsize(void); | ||
36 | unsigned long viafb_get_videobuf_addr(void); | ||
37 | |||
38 | #endif /* __IFACE_H__ */ | ||
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 09353e2b92f6..1b1ccdc2d83d 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c | |||
@@ -22,25 +22,7 @@ | |||
22 | #include "global.h" | 22 | #include "global.h" |
23 | #include "lcdtbl.h" | 23 | #include "lcdtbl.h" |
24 | 24 | ||
25 | static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = { | 25 | #define viafb_compact_res(x, y) (((x)<<16)|(y)) |
26 | /* IGA2 Shadow Horizontal Total */ | ||
27 | {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } }, | ||
28 | /* IGA2 Shadow Horizontal Blank End */ | ||
29 | {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } }, | ||
30 | /* IGA2 Shadow Vertical Total */ | ||
31 | {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } }, | ||
32 | /* IGA2 Shadow Vertical Addressable Video */ | ||
33 | {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } }, | ||
34 | /* IGA2 Shadow Vertical Blank Start */ | ||
35 | {IGA2_SHADOW_VER_BLANK_START_REG_NUM, | ||
36 | {{CR72, 0, 7}, {CR74, 4, 6} } }, | ||
37 | /* IGA2 Shadow Vertical Blank End */ | ||
38 | {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } }, | ||
39 | /* IGA2 Shadow Vertical Sync Start */ | ||
40 | {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } }, | ||
41 | /* IGA2 Shadow Vertical Sync End */ | ||
42 | {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } } | ||
43 | }; | ||
44 | 26 | ||
45 | static struct _lcd_scaling_factor lcd_scaling_factor = { | 27 | static struct _lcd_scaling_factor lcd_scaling_factor = { |
46 | /* LCD Horizontal Scaling Factor Register */ | 28 | /* LCD Horizontal Scaling Factor Register */ |
@@ -59,16 +41,10 @@ static struct _lcd_scaling_factor lcd_scaling_factor_CLE = { | |||
59 | 41 | ||
60 | static int check_lvds_chip(int device_id_subaddr, int device_id); | 42 | static int check_lvds_chip(int device_id_subaddr, int device_id); |
61 | static bool lvds_identify_integratedlvds(void); | 43 | static bool lvds_identify_integratedlvds(void); |
62 | static int fp_id_to_vindex(int panel_id); | 44 | static void fp_id_to_vindex(int panel_id); |
63 | static int lvds_register_read(int index); | 45 | static int lvds_register_read(int index); |
64 | static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | 46 | static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, |
65 | int panel_vres); | 47 | int panel_vres); |
66 | static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, | ||
67 | int panel_id); | ||
68 | static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, | ||
69 | int panel_id); | ||
70 | static void load_lcd_patch_regs(int set_hres, int set_vres, | ||
71 | int panel_id, int set_iga); | ||
72 | static void via_pitch_alignment_patch_lcd( | 48 | static void via_pitch_alignment_patch_lcd( |
73 | struct lvds_setting_information *plvds_setting_info, | 49 | struct lvds_setting_information *plvds_setting_info, |
74 | struct lvds_chip_information | 50 | struct lvds_chip_information |
@@ -98,8 +74,6 @@ static void check_diport_of_integrated_lvds( | |||
98 | static struct display_timing lcd_centering_timging(struct display_timing | 74 | static struct display_timing lcd_centering_timging(struct display_timing |
99 | mode_crt_reg, | 75 | mode_crt_reg, |
100 | struct display_timing panel_crt_reg); | 76 | struct display_timing panel_crt_reg); |
101 | static void load_crtc_shadow_timing(struct display_timing mode_timing, | ||
102 | struct display_timing panel_timing); | ||
103 | static void viafb_load_scaling_factor_for_p4m900(int set_hres, | 77 | static void viafb_load_scaling_factor_for_p4m900(int set_hres, |
104 | int set_vres, int panel_hres, int panel_vres); | 78 | int set_vres, int panel_hres, int panel_vres); |
105 | 79 | ||
@@ -125,33 +99,24 @@ void viafb_init_lcd_size(void) | |||
125 | break; | 99 | break; |
126 | case GET_LCD_SIZE_BY_VGA_BIOS: | 100 | case GET_LCD_SIZE_BY_VGA_BIOS: |
127 | DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n"); | 101 | DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n"); |
128 | viaparinfo->lvds_setting_info->lcd_panel_size = | 102 | fp_id_to_vindex(viafb_lcd_panel_id); |
129 | fp_id_to_vindex(viafb_lcd_panel_id); | ||
130 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", | 103 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", |
131 | viaparinfo->lvds_setting_info->lcd_panel_id); | 104 | viaparinfo->lvds_setting_info->lcd_panel_id); |
132 | DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", | ||
133 | viaparinfo->lvds_setting_info->lcd_panel_size); | ||
134 | break; | 105 | break; |
135 | case GET_LCD_SIZE_BY_USER_SETTING: | 106 | case GET_LCD_SIZE_BY_USER_SETTING: |
136 | DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n"); | 107 | DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n"); |
137 | viaparinfo->lvds_setting_info->lcd_panel_size = | 108 | fp_id_to_vindex(viafb_lcd_panel_id); |
138 | fp_id_to_vindex(viafb_lcd_panel_id); | ||
139 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", | 109 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", |
140 | viaparinfo->lvds_setting_info->lcd_panel_id); | 110 | viaparinfo->lvds_setting_info->lcd_panel_id); |
141 | DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", | ||
142 | viaparinfo->lvds_setting_info->lcd_panel_size); | ||
143 | break; | 111 | break; |
144 | default: | 112 | default: |
145 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n"); | 113 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n"); |
146 | viaparinfo->lvds_setting_info->lcd_panel_id = | 114 | viaparinfo->lvds_setting_info->lcd_panel_id = |
147 | LCD_PANEL_ID1_800X600; | 115 | LCD_PANEL_ID1_800X600; |
148 | viaparinfo->lvds_setting_info->lcd_panel_size = | 116 | fp_id_to_vindex(LCD_PANEL_ID1_800X600); |
149 | fp_id_to_vindex(LCD_PANEL_ID1_800X600); | ||
150 | } | 117 | } |
151 | viaparinfo->lvds_setting_info2->lcd_panel_id = | 118 | viaparinfo->lvds_setting_info2->lcd_panel_id = |
152 | viaparinfo->lvds_setting_info->lcd_panel_id; | 119 | viaparinfo->lvds_setting_info->lcd_panel_id; |
153 | viaparinfo->lvds_setting_info2->lcd_panel_size = | ||
154 | viaparinfo->lvds_setting_info->lcd_panel_size; | ||
155 | viaparinfo->lvds_setting_info2->lcd_panel_hres = | 120 | viaparinfo->lvds_setting_info2->lcd_panel_hres = |
156 | viaparinfo->lvds_setting_info->lcd_panel_hres; | 121 | viaparinfo->lvds_setting_info->lcd_panel_hres; |
157 | viaparinfo->lvds_setting_info2->lcd_panel_vres = | 122 | viaparinfo->lvds_setting_info2->lcd_panel_vres = |
@@ -171,13 +136,13 @@ static bool lvds_identify_integratedlvds(void) | |||
171 | if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | 136 | if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { |
172 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = | 137 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = |
173 | INTEGRATED_LVDS; | 138 | INTEGRATED_LVDS; |
174 | DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\ | 139 | DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! " |
175 | (Internal LVDS + External LVDS)\n"); | 140 | "(Internal LVDS + External LVDS)\n"); |
176 | } else { | 141 | } else { |
177 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | 142 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = |
178 | INTEGRATED_LVDS; | 143 | INTEGRATED_LVDS; |
179 | DEBUG_MSG(KERN_INFO "Not found external LVDS,\ | 144 | DEBUG_MSG(KERN_INFO "Not found external LVDS, " |
180 | so can't support two dual channel LVDS!\n"); | 145 | "so can't support two dual channel LVDS!\n"); |
181 | } | 146 | } |
182 | } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) { | 147 | } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) { |
183 | /* Two single channel LCD (Internal LVDS + Internal LVDS): */ | 148 | /* Two single channel LCD (Internal LVDS + Internal LVDS): */ |
@@ -185,8 +150,8 @@ static bool lvds_identify_integratedlvds(void) | |||
185 | INTEGRATED_LVDS; | 150 | INTEGRATED_LVDS; |
186 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = | 151 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = |
187 | INTEGRATED_LVDS; | 152 | INTEGRATED_LVDS; |
188 | DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\ | 153 | DEBUG_MSG(KERN_INFO "Support two single channel LVDS! " |
189 | (Internal LVDS + Internal LVDS)\n"); | 154 | "(Internal LVDS + Internal LVDS)\n"); |
190 | } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) { | 155 | } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) { |
191 | /* If we have found external LVDS, just use it, | 156 | /* If we have found external LVDS, just use it, |
192 | otherwise, we will use internal LVDS as default. */ | 157 | otherwise, we will use internal LVDS as default. */ |
@@ -248,7 +213,7 @@ int viafb_lvds_trasmitter_identify(void) | |||
248 | return FAIL; | 213 | return FAIL; |
249 | } | 214 | } |
250 | 215 | ||
251 | static int fp_id_to_vindex(int panel_id) | 216 | static void fp_id_to_vindex(int panel_id) |
252 | { | 217 | { |
253 | DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); | 218 | DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); |
254 | 219 | ||
@@ -264,7 +229,6 @@ static int fp_id_to_vindex(int panel_id) | |||
264 | LCD_PANEL_ID0_640X480; | 229 | LCD_PANEL_ID0_640X480; |
265 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 230 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
266 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 231 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
267 | return VIA_RES_640X480; | ||
268 | break; | 232 | break; |
269 | case 0x1: | 233 | case 0x1: |
270 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | 234 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; |
@@ -273,7 +237,6 @@ static int fp_id_to_vindex(int panel_id) | |||
273 | LCD_PANEL_ID1_800X600; | 237 | LCD_PANEL_ID1_800X600; |
274 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 238 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
275 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 239 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
276 | return VIA_RES_800X600; | ||
277 | break; | 240 | break; |
278 | case 0x2: | 241 | case 0x2: |
279 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | 242 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; |
@@ -282,7 +245,6 @@ static int fp_id_to_vindex(int panel_id) | |||
282 | LCD_PANEL_ID2_1024X768; | 245 | LCD_PANEL_ID2_1024X768; |
283 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 246 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
284 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 247 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
285 | return VIA_RES_1024X768; | ||
286 | break; | 248 | break; |
287 | case 0x3: | 249 | case 0x3: |
288 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | 250 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; |
@@ -291,7 +253,6 @@ static int fp_id_to_vindex(int panel_id) | |||
291 | LCD_PANEL_ID3_1280X768; | 253 | LCD_PANEL_ID3_1280X768; |
292 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 254 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
293 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 255 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
294 | return VIA_RES_1280X768; | ||
295 | break; | 256 | break; |
296 | case 0x4: | 257 | case 0x4: |
297 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | 258 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; |
@@ -300,7 +261,6 @@ static int fp_id_to_vindex(int panel_id) | |||
300 | LCD_PANEL_ID4_1280X1024; | 261 | LCD_PANEL_ID4_1280X1024; |
301 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 262 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
302 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 263 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
303 | return VIA_RES_1280X1024; | ||
304 | break; | 264 | break; |
305 | case 0x5: | 265 | case 0x5: |
306 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; | 266 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; |
@@ -309,7 +269,6 @@ static int fp_id_to_vindex(int panel_id) | |||
309 | LCD_PANEL_ID5_1400X1050; | 269 | LCD_PANEL_ID5_1400X1050; |
310 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 270 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
311 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 271 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
312 | return VIA_RES_1400X1050; | ||
313 | break; | 272 | break; |
314 | case 0x6: | 273 | case 0x6: |
315 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; | 274 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; |
@@ -318,7 +277,6 @@ static int fp_id_to_vindex(int panel_id) | |||
318 | LCD_PANEL_ID6_1600X1200; | 277 | LCD_PANEL_ID6_1600X1200; |
319 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 278 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
320 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 279 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
321 | return VIA_RES_1600X1200; | ||
322 | break; | 280 | break; |
323 | case 0x8: | 281 | case 0x8: |
324 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | 282 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; |
@@ -327,7 +285,6 @@ static int fp_id_to_vindex(int panel_id) | |||
327 | LCD_PANEL_IDA_800X480; | 285 | LCD_PANEL_IDA_800X480; |
328 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 286 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
329 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 287 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
330 | return VIA_RES_800X480; | ||
331 | break; | 288 | break; |
332 | case 0x9: | 289 | case 0x9: |
333 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | 290 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; |
@@ -336,7 +293,6 @@ static int fp_id_to_vindex(int panel_id) | |||
336 | LCD_PANEL_ID2_1024X768; | 293 | LCD_PANEL_ID2_1024X768; |
337 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 294 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
338 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 295 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
339 | return VIA_RES_1024X768; | ||
340 | break; | 296 | break; |
341 | case 0xA: | 297 | case 0xA: |
342 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | 298 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; |
@@ -345,7 +301,6 @@ static int fp_id_to_vindex(int panel_id) | |||
345 | LCD_PANEL_ID2_1024X768; | 301 | LCD_PANEL_ID2_1024X768; |
346 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 302 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
347 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 303 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
348 | return VIA_RES_1024X768; | ||
349 | break; | 304 | break; |
350 | case 0xB: | 305 | case 0xB: |
351 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | 306 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; |
@@ -354,7 +309,6 @@ static int fp_id_to_vindex(int panel_id) | |||
354 | LCD_PANEL_ID2_1024X768; | 309 | LCD_PANEL_ID2_1024X768; |
355 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 310 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
356 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 311 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
357 | return VIA_RES_1024X768; | ||
358 | break; | 312 | break; |
359 | case 0xC: | 313 | case 0xC: |
360 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | 314 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; |
@@ -363,7 +317,6 @@ static int fp_id_to_vindex(int panel_id) | |||
363 | LCD_PANEL_ID3_1280X768; | 317 | LCD_PANEL_ID3_1280X768; |
364 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 318 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
365 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 319 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
366 | return VIA_RES_1280X768; | ||
367 | break; | 320 | break; |
368 | case 0xD: | 321 | case 0xD: |
369 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | 322 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; |
@@ -372,7 +325,6 @@ static int fp_id_to_vindex(int panel_id) | |||
372 | LCD_PANEL_ID4_1280X1024; | 325 | LCD_PANEL_ID4_1280X1024; |
373 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 326 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
374 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 327 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
375 | return VIA_RES_1280X1024; | ||
376 | break; | 328 | break; |
377 | case 0xE: | 329 | case 0xE: |
378 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; | 330 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; |
@@ -381,7 +333,6 @@ static int fp_id_to_vindex(int panel_id) | |||
381 | LCD_PANEL_ID5_1400X1050; | 333 | LCD_PANEL_ID5_1400X1050; |
382 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 334 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
383 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 335 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
384 | return VIA_RES_1400X1050; | ||
385 | break; | 336 | break; |
386 | case 0xF: | 337 | case 0xF: |
387 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; | 338 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; |
@@ -390,7 +341,6 @@ static int fp_id_to_vindex(int panel_id) | |||
390 | LCD_PANEL_ID6_1600X1200; | 341 | LCD_PANEL_ID6_1600X1200; |
391 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 342 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
392 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 343 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
393 | return VIA_RES_1600X1200; | ||
394 | break; | 344 | break; |
395 | case 0x10: | 345 | case 0x10: |
396 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; | 346 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; |
@@ -399,7 +349,6 @@ static int fp_id_to_vindex(int panel_id) | |||
399 | LCD_PANEL_ID7_1366X768; | 349 | LCD_PANEL_ID7_1366X768; |
400 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 350 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
401 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 351 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
402 | return VIA_RES_1368X768; | ||
403 | break; | 352 | break; |
404 | case 0x11: | 353 | case 0x11: |
405 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | 354 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; |
@@ -408,7 +357,6 @@ static int fp_id_to_vindex(int panel_id) | |||
408 | LCD_PANEL_ID8_1024X600; | 357 | LCD_PANEL_ID8_1024X600; |
409 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 358 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
410 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 359 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
411 | return VIA_RES_1024X600; | ||
412 | break; | 360 | break; |
413 | case 0x12: | 361 | case 0x12: |
414 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | 362 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; |
@@ -417,7 +365,6 @@ static int fp_id_to_vindex(int panel_id) | |||
417 | LCD_PANEL_ID3_1280X768; | 365 | LCD_PANEL_ID3_1280X768; |
418 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 366 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
419 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 367 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
420 | return VIA_RES_1280X768; | ||
421 | break; | 368 | break; |
422 | case 0x13: | 369 | case 0x13: |
423 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | 370 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; |
@@ -426,7 +373,6 @@ static int fp_id_to_vindex(int panel_id) | |||
426 | LCD_PANEL_ID9_1280X800; | 373 | LCD_PANEL_ID9_1280X800; |
427 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 374 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
428 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 375 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
429 | return VIA_RES_1280X800; | ||
430 | break; | 376 | break; |
431 | case 0x14: | 377 | case 0x14: |
432 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; | 378 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; |
@@ -435,7 +381,6 @@ static int fp_id_to_vindex(int panel_id) | |||
435 | LCD_PANEL_IDB_1360X768; | 381 | LCD_PANEL_IDB_1360X768; |
436 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 382 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
437 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 383 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
438 | return VIA_RES_1360X768; | ||
439 | break; | 384 | break; |
440 | case 0x15: | 385 | case 0x15: |
441 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | 386 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; |
@@ -444,7 +389,6 @@ static int fp_id_to_vindex(int panel_id) | |||
444 | LCD_PANEL_ID3_1280X768; | 389 | LCD_PANEL_ID3_1280X768; |
445 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | 390 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; |
446 | viaparinfo->lvds_setting_info->LCDDithering = 0; | 391 | viaparinfo->lvds_setting_info->LCDDithering = 0; |
447 | return VIA_RES_1280X768; | ||
448 | break; | 392 | break; |
449 | case 0x16: | 393 | case 0x16: |
450 | viaparinfo->lvds_setting_info->lcd_panel_hres = 480; | 394 | viaparinfo->lvds_setting_info->lcd_panel_hres = 480; |
@@ -453,7 +397,6 @@ static int fp_id_to_vindex(int panel_id) | |||
453 | LCD_PANEL_IDC_480X640; | 397 | LCD_PANEL_IDC_480X640; |
454 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 398 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
455 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 399 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
456 | return VIA_RES_480X640; | ||
457 | break; | 400 | break; |
458 | default: | 401 | default: |
459 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | 402 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; |
@@ -462,7 +405,6 @@ static int fp_id_to_vindex(int panel_id) | |||
462 | LCD_PANEL_ID1_800X600; | 405 | LCD_PANEL_ID1_800X600; |
463 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 406 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
464 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 407 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
465 | return VIA_RES_800X600; | ||
466 | } | 408 | } |
467 | } | 409 | } |
468 | 410 | ||
@@ -573,284 +515,6 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | |||
573 | } | 515 | } |
574 | } | 516 | } |
575 | 517 | ||
576 | static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, | ||
577 | int panel_id) | ||
578 | { | ||
579 | int vmode_index; | ||
580 | int reg_num = 0; | ||
581 | struct io_reg *lcd_patch_reg = NULL; | ||
582 | |||
583 | vmode_index = viafb_get_mode_index(set_hres, set_vres); | ||
584 | switch (panel_id) { | ||
585 | /* LCD 800x600 */ | ||
586 | case LCD_PANEL_ID1_800X600: | ||
587 | switch (vmode_index) { | ||
588 | case VIA_RES_640X400: | ||
589 | case VIA_RES_640X480: | ||
590 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6; | ||
591 | lcd_patch_reg = K400_LCD_RES_6X4_8X6; | ||
592 | break; | ||
593 | case VIA_RES_720X480: | ||
594 | case VIA_RES_720X576: | ||
595 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6; | ||
596 | lcd_patch_reg = K400_LCD_RES_7X4_8X6; | ||
597 | break; | ||
598 | } | ||
599 | break; | ||
600 | |||
601 | /* LCD 1024x768 */ | ||
602 | case LCD_PANEL_ID2_1024X768: | ||
603 | switch (vmode_index) { | ||
604 | case VIA_RES_640X400: | ||
605 | case VIA_RES_640X480: | ||
606 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7; | ||
607 | lcd_patch_reg = K400_LCD_RES_6X4_10X7; | ||
608 | break; | ||
609 | case VIA_RES_720X480: | ||
610 | case VIA_RES_720X576: | ||
611 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7; | ||
612 | lcd_patch_reg = K400_LCD_RES_7X4_10X7; | ||
613 | break; | ||
614 | case VIA_RES_800X600: | ||
615 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7; | ||
616 | lcd_patch_reg = K400_LCD_RES_8X6_10X7; | ||
617 | break; | ||
618 | } | ||
619 | break; | ||
620 | |||
621 | /* LCD 1280x1024 */ | ||
622 | case LCD_PANEL_ID4_1280X1024: | ||
623 | switch (vmode_index) { | ||
624 | case VIA_RES_640X400: | ||
625 | case VIA_RES_640X480: | ||
626 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10; | ||
627 | lcd_patch_reg = K400_LCD_RES_6X4_12X10; | ||
628 | break; | ||
629 | case VIA_RES_720X480: | ||
630 | case VIA_RES_720X576: | ||
631 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10; | ||
632 | lcd_patch_reg = K400_LCD_RES_7X4_12X10; | ||
633 | break; | ||
634 | case VIA_RES_800X600: | ||
635 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10; | ||
636 | lcd_patch_reg = K400_LCD_RES_8X6_12X10; | ||
637 | break; | ||
638 | case VIA_RES_1024X768: | ||
639 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10; | ||
640 | lcd_patch_reg = K400_LCD_RES_10X7_12X10; | ||
641 | break; | ||
642 | |||
643 | } | ||
644 | break; | ||
645 | |||
646 | /* LCD 1400x1050 */ | ||
647 | case LCD_PANEL_ID5_1400X1050: | ||
648 | switch (vmode_index) { | ||
649 | case VIA_RES_640X480: | ||
650 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10; | ||
651 | lcd_patch_reg = K400_LCD_RES_6X4_14X10; | ||
652 | break; | ||
653 | case VIA_RES_800X600: | ||
654 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10; | ||
655 | lcd_patch_reg = K400_LCD_RES_8X6_14X10; | ||
656 | break; | ||
657 | case VIA_RES_1024X768: | ||
658 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10; | ||
659 | lcd_patch_reg = K400_LCD_RES_10X7_14X10; | ||
660 | break; | ||
661 | case VIA_RES_1280X768: | ||
662 | case VIA_RES_1280X800: | ||
663 | case VIA_RES_1280X960: | ||
664 | case VIA_RES_1280X1024: | ||
665 | reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10; | ||
666 | lcd_patch_reg = K400_LCD_RES_12X10_14X10; | ||
667 | break; | ||
668 | } | ||
669 | break; | ||
670 | |||
671 | /* LCD 1600x1200 */ | ||
672 | case LCD_PANEL_ID6_1600X1200: | ||
673 | switch (vmode_index) { | ||
674 | case VIA_RES_640X400: | ||
675 | case VIA_RES_640X480: | ||
676 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12; | ||
677 | lcd_patch_reg = K400_LCD_RES_6X4_16X12; | ||
678 | break; | ||
679 | case VIA_RES_720X480: | ||
680 | case VIA_RES_720X576: | ||
681 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12; | ||
682 | lcd_patch_reg = K400_LCD_RES_7X4_16X12; | ||
683 | break; | ||
684 | case VIA_RES_800X600: | ||
685 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12; | ||
686 | lcd_patch_reg = K400_LCD_RES_8X6_16X12; | ||
687 | break; | ||
688 | case VIA_RES_1024X768: | ||
689 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12; | ||
690 | lcd_patch_reg = K400_LCD_RES_10X7_16X12; | ||
691 | break; | ||
692 | case VIA_RES_1280X768: | ||
693 | case VIA_RES_1280X800: | ||
694 | case VIA_RES_1280X960: | ||
695 | case VIA_RES_1280X1024: | ||
696 | reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12; | ||
697 | lcd_patch_reg = K400_LCD_RES_12X10_16X12; | ||
698 | break; | ||
699 | } | ||
700 | break; | ||
701 | |||
702 | /* LCD 1366x768 */ | ||
703 | case LCD_PANEL_ID7_1366X768: | ||
704 | switch (vmode_index) { | ||
705 | case VIA_RES_640X480: | ||
706 | reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7; | ||
707 | lcd_patch_reg = K400_LCD_RES_6X4_1366X7; | ||
708 | break; | ||
709 | case VIA_RES_720X480: | ||
710 | case VIA_RES_720X576: | ||
711 | reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7; | ||
712 | lcd_patch_reg = K400_LCD_RES_7X4_1366X7; | ||
713 | break; | ||
714 | case VIA_RES_800X600: | ||
715 | reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7; | ||
716 | lcd_patch_reg = K400_LCD_RES_8X6_1366X7; | ||
717 | break; | ||
718 | case VIA_RES_1024X768: | ||
719 | reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7; | ||
720 | lcd_patch_reg = K400_LCD_RES_10X7_1366X7; | ||
721 | break; | ||
722 | case VIA_RES_1280X768: | ||
723 | case VIA_RES_1280X800: | ||
724 | case VIA_RES_1280X960: | ||
725 | case VIA_RES_1280X1024: | ||
726 | reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7; | ||
727 | lcd_patch_reg = K400_LCD_RES_12X10_1366X7; | ||
728 | break; | ||
729 | } | ||
730 | break; | ||
731 | |||
732 | /* LCD 1360x768 */ | ||
733 | case LCD_PANEL_IDB_1360X768: | ||
734 | break; | ||
735 | } | ||
736 | if (reg_num != 0) { | ||
737 | /* H.W. Reset : ON */ | ||
738 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
739 | |||
740 | viafb_write_regx(lcd_patch_reg, reg_num); | ||
741 | |||
742 | /* H.W. Reset : OFF */ | ||
743 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
744 | |||
745 | /* Reset PLL */ | ||
746 | viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); | ||
747 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); | ||
748 | |||
749 | /* Fire! */ | ||
750 | outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); | ||
751 | } | ||
752 | } | ||
753 | |||
754 | static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, | ||
755 | int panel_id) | ||
756 | { | ||
757 | int vmode_index; | ||
758 | int reg_num = 0; | ||
759 | struct io_reg *lcd_patch_reg = NULL; | ||
760 | |||
761 | vmode_index = viafb_get_mode_index(set_hres, set_vres); | ||
762 | |||
763 | switch (panel_id) { | ||
764 | case LCD_PANEL_ID5_1400X1050: | ||
765 | switch (vmode_index) { | ||
766 | case VIA_RES_640X480: | ||
767 | reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10; | ||
768 | lcd_patch_reg = P880_LCD_RES_6X4_14X10; | ||
769 | break; | ||
770 | case VIA_RES_800X600: | ||
771 | reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10; | ||
772 | lcd_patch_reg = P880_LCD_RES_8X6_14X10; | ||
773 | break; | ||
774 | } | ||
775 | break; | ||
776 | case LCD_PANEL_ID6_1600X1200: | ||
777 | switch (vmode_index) { | ||
778 | case VIA_RES_640X400: | ||
779 | case VIA_RES_640X480: | ||
780 | reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12; | ||
781 | lcd_patch_reg = P880_LCD_RES_6X4_16X12; | ||
782 | break; | ||
783 | case VIA_RES_720X480: | ||
784 | case VIA_RES_720X576: | ||
785 | reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12; | ||
786 | lcd_patch_reg = P880_LCD_RES_7X4_16X12; | ||
787 | break; | ||
788 | case VIA_RES_800X600: | ||
789 | reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12; | ||
790 | lcd_patch_reg = P880_LCD_RES_8X6_16X12; | ||
791 | break; | ||
792 | case VIA_RES_1024X768: | ||
793 | reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12; | ||
794 | lcd_patch_reg = P880_LCD_RES_10X7_16X12; | ||
795 | break; | ||
796 | case VIA_RES_1280X768: | ||
797 | case VIA_RES_1280X960: | ||
798 | case VIA_RES_1280X1024: | ||
799 | reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12; | ||
800 | lcd_patch_reg = P880_LCD_RES_12X10_16X12; | ||
801 | break; | ||
802 | } | ||
803 | break; | ||
804 | |||
805 | } | ||
806 | if (reg_num != 0) { | ||
807 | /* H.W. Reset : ON */ | ||
808 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
809 | |||
810 | viafb_write_regx(lcd_patch_reg, reg_num); | ||
811 | |||
812 | /* H.W. Reset : OFF */ | ||
813 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
814 | |||
815 | /* Reset PLL */ | ||
816 | viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); | ||
817 | viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); | ||
818 | |||
819 | /* Fire! */ | ||
820 | outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); | ||
821 | } | ||
822 | } | ||
823 | |||
824 | static void load_lcd_patch_regs(int set_hres, int set_vres, | ||
825 | int panel_id, int set_iga) | ||
826 | { | ||
827 | int vmode_index; | ||
828 | |||
829 | vmode_index = viafb_get_mode_index(set_hres, set_vres); | ||
830 | |||
831 | viafb_unlock_crt(); | ||
832 | |||
833 | /* Patch for simultaneous & Expansion */ | ||
834 | if ((set_iga == IGA1_IGA2) && | ||
835 | (viaparinfo->lvds_setting_info->display_method == | ||
836 | LCD_EXPANDSION)) { | ||
837 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
838 | case UNICHROME_CLE266: | ||
839 | case UNICHROME_K400: | ||
840 | load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id); | ||
841 | break; | ||
842 | case UNICHROME_K800: | ||
843 | break; | ||
844 | case UNICHROME_PM800: | ||
845 | case UNICHROME_CN700: | ||
846 | case UNICHROME_CX700: | ||
847 | load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id); | ||
848 | } | ||
849 | } | ||
850 | |||
851 | viafb_lock_crt(); | ||
852 | } | ||
853 | |||
854 | static void via_pitch_alignment_patch_lcd( | 518 | static void via_pitch_alignment_patch_lcd( |
855 | struct lvds_setting_information *plvds_setting_info, | 519 | struct lvds_setting_information *plvds_setting_info, |
856 | struct lvds_chip_information | 520 | struct lvds_chip_information |
@@ -949,29 +613,25 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
949 | struct lvds_setting_information *plvds_setting_info, | 613 | struct lvds_setting_information *plvds_setting_info, |
950 | struct lvds_chip_information *plvds_chip_info) | 614 | struct lvds_chip_information *plvds_chip_info) |
951 | { | 615 | { |
952 | int video_index = plvds_setting_info->lcd_panel_size; | ||
953 | int set_iga = plvds_setting_info->iga_path; | 616 | int set_iga = plvds_setting_info->iga_path; |
954 | int mode_bpp = plvds_setting_info->bpp; | 617 | int mode_bpp = plvds_setting_info->bpp; |
955 | int set_hres, set_vres; | 618 | int set_hres = plvds_setting_info->h_active; |
956 | int panel_hres, panel_vres; | 619 | int set_vres = plvds_setting_info->v_active; |
620 | int panel_hres = plvds_setting_info->lcd_panel_hres; | ||
621 | int panel_vres = plvds_setting_info->lcd_panel_vres; | ||
957 | u32 pll_D_N; | 622 | u32 pll_D_N; |
958 | int offset; | ||
959 | struct display_timing mode_crt_reg, panel_crt_reg; | 623 | struct display_timing mode_crt_reg, panel_crt_reg; |
960 | struct crt_mode_table *panel_crt_table = NULL; | 624 | struct crt_mode_table *panel_crt_table = NULL; |
961 | struct VideoModeTable *vmode_tbl = NULL; | 625 | struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres, |
626 | panel_vres); | ||
962 | 627 | ||
963 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); | 628 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); |
964 | /* Get mode table */ | 629 | /* Get mode table */ |
965 | mode_crt_reg = mode_crt_table->crtc; | 630 | mode_crt_reg = mode_crt_table->crtc; |
966 | /* Get panel table Pointer */ | 631 | /* Get panel table Pointer */ |
967 | vmode_tbl = viafb_get_modetbl_pointer(video_index); | ||
968 | panel_crt_table = vmode_tbl->crtc; | 632 | panel_crt_table = vmode_tbl->crtc; |
969 | panel_crt_reg = panel_crt_table->crtc; | 633 | panel_crt_reg = panel_crt_table->crtc; |
970 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); | 634 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); |
971 | set_hres = plvds_setting_info->h_active; | ||
972 | set_vres = plvds_setting_info->v_active; | ||
973 | panel_hres = plvds_setting_info->lcd_panel_hres; | ||
974 | panel_vres = plvds_setting_info->lcd_panel_vres; | ||
975 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) | 635 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) |
976 | viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); | 636 | viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); |
977 | plvds_setting_info->vclk = panel_crt_table->clk; | 637 | plvds_setting_info->vclk = panel_crt_table->clk; |
@@ -1001,54 +661,12 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
1001 | } | 661 | } |
1002 | } | 662 | } |
1003 | 663 | ||
1004 | if (set_iga == IGA1_IGA2) { | 664 | /* Fetch count for IGA2 only */ |
1005 | load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg); | 665 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); |
1006 | /* Fill shadow registers */ | ||
1007 | |||
1008 | switch (plvds_setting_info->lcd_panel_id) { | ||
1009 | case LCD_PANEL_ID0_640X480: | ||
1010 | offset = 80; | ||
1011 | break; | ||
1012 | case LCD_PANEL_ID1_800X600: | ||
1013 | case LCD_PANEL_IDA_800X480: | ||
1014 | offset = 110; | ||
1015 | break; | ||
1016 | case LCD_PANEL_ID2_1024X768: | ||
1017 | offset = 150; | ||
1018 | break; | ||
1019 | case LCD_PANEL_ID3_1280X768: | ||
1020 | case LCD_PANEL_ID4_1280X1024: | ||
1021 | case LCD_PANEL_ID5_1400X1050: | ||
1022 | case LCD_PANEL_ID9_1280X800: | ||
1023 | offset = 190; | ||
1024 | break; | ||
1025 | case LCD_PANEL_ID6_1600X1200: | ||
1026 | offset = 250; | ||
1027 | break; | ||
1028 | case LCD_PANEL_ID7_1366X768: | ||
1029 | case LCD_PANEL_IDB_1360X768: | ||
1030 | offset = 212; | ||
1031 | break; | ||
1032 | default: | ||
1033 | offset = 140; | ||
1034 | break; | ||
1035 | } | ||
1036 | |||
1037 | /* Offset for simultaneous */ | ||
1038 | viafb_set_secondary_pitch(offset << 3); | ||
1039 | DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n"); | ||
1040 | viafb_load_fetch_count_reg(set_hres, 4, IGA2); | ||
1041 | /* Fetch count for simultaneous */ | ||
1042 | } else { /* SAMM */ | ||
1043 | /* Fetch count for IGA2 only */ | ||
1044 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); | ||
1045 | |||
1046 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) | ||
1047 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | ||
1048 | viafb_load_FIFO_reg(set_iga, set_hres, set_vres); | ||
1049 | 666 | ||
1050 | viafb_set_color_depth(mode_bpp / 8, set_iga); | 667 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) |
1051 | } | 668 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) |
669 | viafb_load_FIFO_reg(set_iga, set_hres, set_vres); | ||
1052 | 670 | ||
1053 | fill_lcd_format(); | 671 | fill_lcd_format(); |
1054 | 672 | ||
@@ -1065,11 +683,6 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
1065 | || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)) | 683 | || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)) |
1066 | viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); | 684 | viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); |
1067 | 685 | ||
1068 | load_lcd_patch_regs(set_hres, set_vres, | ||
1069 | plvds_setting_info->lcd_panel_id, set_iga); | ||
1070 | |||
1071 | DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n"); | ||
1072 | |||
1073 | /* Patch for non 32bit alignment mode */ | 686 | /* Patch for non 32bit alignment mode */ |
1074 | via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); | 687 | via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); |
1075 | } | 688 | } |
@@ -1283,8 +896,7 @@ void viafb_lcd_enable(void) | |||
1283 | viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); | 896 | viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); |
1284 | } | 897 | } |
1285 | 898 | ||
1286 | if ((viaparinfo->lvds_setting_info->iga_path == IGA1) | 899 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { |
1287 | || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) { | ||
1288 | /* CRT path set to IGA2 */ | 900 | /* CRT path set to IGA2 */ |
1289 | viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40); | 901 | viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40); |
1290 | /* IGA2 path disabled */ | 902 | /* IGA2 path disabled */ |
@@ -1476,210 +1088,6 @@ static struct display_timing lcd_centering_timging(struct display_timing | |||
1476 | return crt_reg; | 1088 | return crt_reg; |
1477 | } | 1089 | } |
1478 | 1090 | ||
1479 | static void load_crtc_shadow_timing(struct display_timing mode_timing, | ||
1480 | struct display_timing panel_timing) | ||
1481 | { | ||
1482 | struct io_register *reg = NULL; | ||
1483 | int i; | ||
1484 | int viafb_load_reg_Num = 0; | ||
1485 | int reg_value = 0; | ||
1486 | |||
1487 | if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) { | ||
1488 | /* Expansion */ | ||
1489 | for (i = 12; i < 20; i++) { | ||
1490 | switch (i) { | ||
1491 | case H_TOTAL_SHADOW_INDEX: | ||
1492 | reg_value = | ||
1493 | IGA2_HOR_TOTAL_SHADOW_FORMULA | ||
1494 | (panel_timing.hor_total); | ||
1495 | viafb_load_reg_Num = | ||
1496 | iga2_shadow_crtc_reg.hor_total_shadow. | ||
1497 | reg_num; | ||
1498 | reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; | ||
1499 | break; | ||
1500 | case H_BLANK_END_SHADOW_INDEX: | ||
1501 | reg_value = | ||
1502 | IGA2_HOR_BLANK_END_SHADOW_FORMULA | ||
1503 | (panel_timing.hor_blank_start, | ||
1504 | panel_timing.hor_blank_end); | ||
1505 | viafb_load_reg_Num = | ||
1506 | iga2_shadow_crtc_reg. | ||
1507 | hor_blank_end_shadow.reg_num; | ||
1508 | reg = | ||
1509 | iga2_shadow_crtc_reg. | ||
1510 | hor_blank_end_shadow.reg; | ||
1511 | break; | ||
1512 | case V_TOTAL_SHADOW_INDEX: | ||
1513 | reg_value = | ||
1514 | IGA2_VER_TOTAL_SHADOW_FORMULA | ||
1515 | (panel_timing.ver_total); | ||
1516 | viafb_load_reg_Num = | ||
1517 | iga2_shadow_crtc_reg.ver_total_shadow. | ||
1518 | reg_num; | ||
1519 | reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; | ||
1520 | break; | ||
1521 | case V_ADDR_SHADOW_INDEX: | ||
1522 | reg_value = | ||
1523 | IGA2_VER_ADDR_SHADOW_FORMULA | ||
1524 | (panel_timing.ver_addr); | ||
1525 | viafb_load_reg_Num = | ||
1526 | iga2_shadow_crtc_reg.ver_addr_shadow. | ||
1527 | reg_num; | ||
1528 | reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; | ||
1529 | break; | ||
1530 | case V_BLANK_SATRT_SHADOW_INDEX: | ||
1531 | reg_value = | ||
1532 | IGA2_VER_BLANK_START_SHADOW_FORMULA | ||
1533 | (panel_timing.ver_blank_start); | ||
1534 | viafb_load_reg_Num = | ||
1535 | iga2_shadow_crtc_reg. | ||
1536 | ver_blank_start_shadow.reg_num; | ||
1537 | reg = | ||
1538 | iga2_shadow_crtc_reg. | ||
1539 | ver_blank_start_shadow.reg; | ||
1540 | break; | ||
1541 | case V_BLANK_END_SHADOW_INDEX: | ||
1542 | reg_value = | ||
1543 | IGA2_VER_BLANK_END_SHADOW_FORMULA | ||
1544 | (panel_timing.ver_blank_start, | ||
1545 | panel_timing.ver_blank_end); | ||
1546 | viafb_load_reg_Num = | ||
1547 | iga2_shadow_crtc_reg. | ||
1548 | ver_blank_end_shadow.reg_num; | ||
1549 | reg = | ||
1550 | iga2_shadow_crtc_reg. | ||
1551 | ver_blank_end_shadow.reg; | ||
1552 | break; | ||
1553 | case V_SYNC_SATRT_SHADOW_INDEX: | ||
1554 | reg_value = | ||
1555 | IGA2_VER_SYNC_START_SHADOW_FORMULA | ||
1556 | (panel_timing.ver_sync_start); | ||
1557 | viafb_load_reg_Num = | ||
1558 | iga2_shadow_crtc_reg. | ||
1559 | ver_sync_start_shadow.reg_num; | ||
1560 | reg = | ||
1561 | iga2_shadow_crtc_reg. | ||
1562 | ver_sync_start_shadow.reg; | ||
1563 | break; | ||
1564 | case V_SYNC_END_SHADOW_INDEX: | ||
1565 | reg_value = | ||
1566 | IGA2_VER_SYNC_END_SHADOW_FORMULA | ||
1567 | (panel_timing.ver_sync_start, | ||
1568 | panel_timing.ver_sync_end); | ||
1569 | viafb_load_reg_Num = | ||
1570 | iga2_shadow_crtc_reg. | ||
1571 | ver_sync_end_shadow.reg_num; | ||
1572 | reg = | ||
1573 | iga2_shadow_crtc_reg. | ||
1574 | ver_sync_end_shadow.reg; | ||
1575 | break; | ||
1576 | } | ||
1577 | viafb_load_reg(reg_value, | ||
1578 | viafb_load_reg_Num, reg, VIACR); | ||
1579 | } | ||
1580 | } else { /* Centering */ | ||
1581 | for (i = 12; i < 20; i++) { | ||
1582 | switch (i) { | ||
1583 | case H_TOTAL_SHADOW_INDEX: | ||
1584 | reg_value = | ||
1585 | IGA2_HOR_TOTAL_SHADOW_FORMULA | ||
1586 | (panel_timing.hor_total); | ||
1587 | viafb_load_reg_Num = | ||
1588 | iga2_shadow_crtc_reg.hor_total_shadow. | ||
1589 | reg_num; | ||
1590 | reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; | ||
1591 | break; | ||
1592 | case H_BLANK_END_SHADOW_INDEX: | ||
1593 | reg_value = | ||
1594 | IGA2_HOR_BLANK_END_SHADOW_FORMULA | ||
1595 | (panel_timing.hor_blank_start, | ||
1596 | panel_timing.hor_blank_end); | ||
1597 | viafb_load_reg_Num = | ||
1598 | iga2_shadow_crtc_reg. | ||
1599 | hor_blank_end_shadow.reg_num; | ||
1600 | reg = | ||
1601 | iga2_shadow_crtc_reg. | ||
1602 | hor_blank_end_shadow.reg; | ||
1603 | break; | ||
1604 | case V_TOTAL_SHADOW_INDEX: | ||
1605 | reg_value = | ||
1606 | IGA2_VER_TOTAL_SHADOW_FORMULA | ||
1607 | (panel_timing.ver_total); | ||
1608 | viafb_load_reg_Num = | ||
1609 | iga2_shadow_crtc_reg.ver_total_shadow. | ||
1610 | reg_num; | ||
1611 | reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; | ||
1612 | break; | ||
1613 | case V_ADDR_SHADOW_INDEX: | ||
1614 | reg_value = | ||
1615 | IGA2_VER_ADDR_SHADOW_FORMULA | ||
1616 | (mode_timing.ver_addr); | ||
1617 | viafb_load_reg_Num = | ||
1618 | iga2_shadow_crtc_reg.ver_addr_shadow. | ||
1619 | reg_num; | ||
1620 | reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; | ||
1621 | break; | ||
1622 | case V_BLANK_SATRT_SHADOW_INDEX: | ||
1623 | reg_value = | ||
1624 | IGA2_VER_BLANK_START_SHADOW_FORMULA | ||
1625 | (mode_timing.ver_blank_start); | ||
1626 | viafb_load_reg_Num = | ||
1627 | iga2_shadow_crtc_reg. | ||
1628 | ver_blank_start_shadow.reg_num; | ||
1629 | reg = | ||
1630 | iga2_shadow_crtc_reg. | ||
1631 | ver_blank_start_shadow.reg; | ||
1632 | break; | ||
1633 | case V_BLANK_END_SHADOW_INDEX: | ||
1634 | reg_value = | ||
1635 | IGA2_VER_BLANK_END_SHADOW_FORMULA | ||
1636 | (panel_timing.ver_blank_start, | ||
1637 | panel_timing.ver_blank_end); | ||
1638 | viafb_load_reg_Num = | ||
1639 | iga2_shadow_crtc_reg. | ||
1640 | ver_blank_end_shadow.reg_num; | ||
1641 | reg = | ||
1642 | iga2_shadow_crtc_reg. | ||
1643 | ver_blank_end_shadow.reg; | ||
1644 | break; | ||
1645 | case V_SYNC_SATRT_SHADOW_INDEX: | ||
1646 | reg_value = | ||
1647 | IGA2_VER_SYNC_START_SHADOW_FORMULA( | ||
1648 | (panel_timing.ver_sync_start - | ||
1649 | panel_timing.ver_blank_start) + | ||
1650 | (panel_timing.ver_addr - | ||
1651 | mode_timing.ver_addr) / 2 + | ||
1652 | mode_timing.ver_addr); | ||
1653 | viafb_load_reg_Num = | ||
1654 | iga2_shadow_crtc_reg.ver_sync_start_shadow. | ||
1655 | reg_num; | ||
1656 | reg = | ||
1657 | iga2_shadow_crtc_reg.ver_sync_start_shadow. | ||
1658 | reg; | ||
1659 | break; | ||
1660 | case V_SYNC_END_SHADOW_INDEX: | ||
1661 | reg_value = | ||
1662 | IGA2_VER_SYNC_END_SHADOW_FORMULA( | ||
1663 | (panel_timing.ver_sync_start - | ||
1664 | panel_timing.ver_blank_start) + | ||
1665 | (panel_timing.ver_addr - | ||
1666 | mode_timing.ver_addr) / 2 + | ||
1667 | mode_timing.ver_addr, | ||
1668 | panel_timing.ver_sync_end); | ||
1669 | viafb_load_reg_Num = | ||
1670 | iga2_shadow_crtc_reg.ver_sync_end_shadow. | ||
1671 | reg_num; | ||
1672 | reg = | ||
1673 | iga2_shadow_crtc_reg.ver_sync_end_shadow. | ||
1674 | reg; | ||
1675 | break; | ||
1676 | } | ||
1677 | viafb_load_reg(reg_value, | ||
1678 | viafb_load_reg_Num, reg, VIACR); | ||
1679 | } | ||
1680 | } | ||
1681 | } | ||
1682 | |||
1683 | bool viafb_lcd_get_mobile_state(bool *mobile) | 1091 | bool viafb_lcd_get_mobile_state(bool *mobile) |
1684 | { | 1092 | { |
1685 | unsigned char *romptr, *tableptr; | 1093 | unsigned char *romptr, *tableptr; |
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 7cd03e2a1275..d55aaa7b912c 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h | |||
@@ -43,61 +43,6 @@ | |||
43 | /* Video Memory Size */ | 43 | /* Video Memory Size */ |
44 | #define VIDEO_MEMORY_SIZE_16M 0x1000000 | 44 | #define VIDEO_MEMORY_SIZE_16M 0x1000000 |
45 | 45 | ||
46 | /* Definition Mode Index | ||
47 | */ | ||
48 | #define VIA_RES_640X480 0 | ||
49 | #define VIA_RES_800X600 1 | ||
50 | #define VIA_RES_1024X768 2 | ||
51 | #define VIA_RES_1152X864 3 | ||
52 | #define VIA_RES_1280X1024 4 | ||
53 | #define VIA_RES_1600X1200 5 | ||
54 | #define VIA_RES_1440X1050 6 | ||
55 | #define VIA_RES_1280X768 7 | ||
56 | #define VIA_RES_1280X960 8 | ||
57 | #define VIA_RES_1920X1440 9 | ||
58 | #define VIA_RES_848X480 10 | ||
59 | #define VIA_RES_1400X1050 11 | ||
60 | #define VIA_RES_720X480 12 | ||
61 | #define VIA_RES_720X576 13 | ||
62 | #define VIA_RES_1024X512 14 | ||
63 | #define VIA_RES_856X480 15 | ||
64 | #define VIA_RES_1024X576 16 | ||
65 | #define VIA_RES_640X400 17 | ||
66 | #define VIA_RES_1280X720 18 | ||
67 | #define VIA_RES_1920X1080 19 | ||
68 | #define VIA_RES_800X480 20 | ||
69 | #define VIA_RES_1368X768 21 | ||
70 | #define VIA_RES_1024X600 22 | ||
71 | #define VIA_RES_1280X800 23 | ||
72 | #define VIA_RES_1680X1050 24 | ||
73 | #define VIA_RES_960X600 25 | ||
74 | #define VIA_RES_1000X600 26 | ||
75 | #define VIA_RES_1088X612 27 | ||
76 | #define VIA_RES_1152X720 28 | ||
77 | #define VIA_RES_1200X720 29 | ||
78 | #define VIA_RES_1280X600 30 | ||
79 | #define VIA_RES_1360X768 31 | ||
80 | #define VIA_RES_1366X768 32 | ||
81 | #define VIA_RES_1440X900 33 | ||
82 | #define VIA_RES_1600X900 34 | ||
83 | #define VIA_RES_1600X1024 35 | ||
84 | #define VIA_RES_1792X1344 36 | ||
85 | #define VIA_RES_1856X1392 37 | ||
86 | #define VIA_RES_1920X1200 38 | ||
87 | #define VIA_RES_2048X1536 39 | ||
88 | #define VIA_RES_480X640 40 | ||
89 | |||
90 | /*Reduce Blanking*/ | ||
91 | #define VIA_RES_1360X768_RB 131 | ||
92 | #define VIA_RES_1440X900_RB 133 | ||
93 | #define VIA_RES_1400X1050_RB 111 | ||
94 | #define VIA_RES_1600X900_RB 134 | ||
95 | #define VIA_RES_1680X1050_RB 124 | ||
96 | #define VIA_RES_1920X1080_RB 119 | ||
97 | #define VIA_RES_1920X1200_RB 138 | ||
98 | |||
99 | #define VIA_RES_INVALID 255 | ||
100 | |||
101 | /* standard VGA IO port | 46 | /* standard VGA IO port |
102 | */ | 47 | */ |
103 | #define VIARMisc 0x3CC | 48 | #define VIARMisc 0x3CC |
@@ -118,7 +63,6 @@ | |||
118 | /* Display path */ | 63 | /* Display path */ |
119 | #define IGA1 1 | 64 | #define IGA1 1 |
120 | #define IGA2 2 | 65 | #define IGA2 2 |
121 | #define IGA1_IGA2 3 | ||
122 | 66 | ||
123 | /* Define Color Depth */ | 67 | /* Define Color Depth */ |
124 | #define MODE_8BPP 1 | 68 | #define MODE_8BPP 1 |
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c index d53c3d54ed8e..aefdeeec89b1 100644 --- a/drivers/video/via/via_utility.c +++ b/drivers/video/via/via_utility.c | |||
@@ -239,15 +239,3 @@ void viafb_get_gamma_support_state(int bpp, unsigned int *support_state) | |||
239 | else | 239 | else |
240 | *support_state = CRT_Device | DVI_Device | LCD_Device; | 240 | *support_state = CRT_Device | DVI_Device | LCD_Device; |
241 | } | 241 | } |
242 | |||
243 | int viafb_input_parameter_converter(int parameter_value) | ||
244 | { | ||
245 | int result; | ||
246 | |||
247 | if (parameter_value >= 1 && parameter_value <= 9) | ||
248 | result = 1 << (parameter_value - 1); | ||
249 | else | ||
250 | result = 1; | ||
251 | |||
252 | return result; | ||
253 | } | ||
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h index 2fd455202ebd..1670ba82143f 100644 --- a/drivers/video/via/via_utility.h +++ b/drivers/video/via/via_utility.h | |||
@@ -30,6 +30,5 @@ bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres); | |||
30 | void viafb_set_gamma_table(int bpp, unsigned int *gamma_table); | 30 | void viafb_set_gamma_table(int bpp, unsigned int *gamma_table); |
31 | void viafb_get_gamma_table(unsigned int *gamma_table); | 31 | void viafb_get_gamma_table(unsigned int *gamma_table); |
32 | void viafb_get_gamma_support_state(int bpp, unsigned int *support_state); | 32 | void viafb_get_gamma_support_state(int bpp, unsigned int *support_state); |
33 | int viafb_input_parameter_converter(int parameter_value); | ||
34 | 33 | ||
35 | #endif /* __VIAUTILITY_H__ */ | 34 | #endif /* __VIAUTILITY_H__ */ |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 3028e7ddc3b5..ce7783b63f6a 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -26,18 +26,22 @@ | |||
26 | 26 | ||
27 | #include "global.h" | 27 | #include "global.h" |
28 | 28 | ||
29 | static struct fb_var_screeninfo default_var; | ||
30 | static char *viafb_name = "Via"; | 29 | static char *viafb_name = "Via"; |
31 | static u32 pseudo_pal[17]; | 30 | static u32 pseudo_pal[17]; |
32 | 31 | ||
33 | /* video mode */ | 32 | /* video mode */ |
34 | static char *viafb_mode = "640x480"; | 33 | static char *viafb_mode; |
35 | static char *viafb_mode1 = "640x480"; | 34 | static char *viafb_mode1; |
35 | static int viafb_bpp = 32; | ||
36 | static int viafb_bpp1 = 32; | ||
37 | |||
38 | static unsigned int viafb_second_offset; | ||
39 | static int viafb_second_size; | ||
36 | 40 | ||
37 | static int viafb_accel = 1; | 41 | static int viafb_accel = 1; |
38 | 42 | ||
39 | /* Added for specifying active devices.*/ | 43 | /* Added for specifying active devices.*/ |
40 | char *viafb_active_dev = ""; | 44 | char *viafb_active_dev; |
41 | 45 | ||
42 | /*Added for specify lcd output port*/ | 46 | /*Added for specify lcd output port*/ |
43 | char *viafb_lcd_port = ""; | 47 | char *viafb_lcd_port = ""; |
@@ -50,18 +54,78 @@ static void apply_second_mode_setting(struct fb_var_screeninfo | |||
50 | *sec_var); | 54 | *sec_var); |
51 | static void retrieve_device_setting(struct viafb_ioctl_setting | 55 | static void retrieve_device_setting(struct viafb_ioctl_setting |
52 | *setting_info); | 56 | *setting_info); |
57 | static int viafb_pan_display(struct fb_var_screeninfo *var, | ||
58 | struct fb_info *info); | ||
53 | 59 | ||
54 | static struct fb_ops viafb_ops; | 60 | static struct fb_ops viafb_ops; |
55 | 61 | ||
56 | 62 | ||
63 | static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) | ||
64 | { | ||
65 | var->grayscale = 0; | ||
66 | var->red.msb_right = 0; | ||
67 | var->green.msb_right = 0; | ||
68 | var->blue.msb_right = 0; | ||
69 | var->transp.offset = 0; | ||
70 | var->transp.length = 0; | ||
71 | var->transp.msb_right = 0; | ||
72 | var->nonstd = 0; | ||
73 | switch (depth) { | ||
74 | case 8: | ||
75 | var->bits_per_pixel = 8; | ||
76 | var->red.offset = 0; | ||
77 | var->green.offset = 0; | ||
78 | var->blue.offset = 0; | ||
79 | var->red.length = 8; | ||
80 | var->green.length = 8; | ||
81 | var->blue.length = 8; | ||
82 | break; | ||
83 | case 15: | ||
84 | var->bits_per_pixel = 16; | ||
85 | var->red.offset = 10; | ||
86 | var->green.offset = 5; | ||
87 | var->blue.offset = 0; | ||
88 | var->red.length = 5; | ||
89 | var->green.length = 5; | ||
90 | var->blue.length = 5; | ||
91 | break; | ||
92 | case 16: | ||
93 | var->bits_per_pixel = 16; | ||
94 | var->red.offset = 11; | ||
95 | var->green.offset = 5; | ||
96 | var->blue.offset = 0; | ||
97 | var->red.length = 5; | ||
98 | var->green.length = 6; | ||
99 | var->blue.length = 5; | ||
100 | break; | ||
101 | case 24: | ||
102 | var->bits_per_pixel = 32; | ||
103 | var->red.offset = 16; | ||
104 | var->green.offset = 8; | ||
105 | var->blue.offset = 0; | ||
106 | var->red.length = 8; | ||
107 | var->green.length = 8; | ||
108 | var->blue.length = 8; | ||
109 | break; | ||
110 | case 30: | ||
111 | var->bits_per_pixel = 32; | ||
112 | var->red.offset = 20; | ||
113 | var->green.offset = 10; | ||
114 | var->blue.offset = 0; | ||
115 | var->red.length = 10; | ||
116 | var->green.length = 10; | ||
117 | var->blue.length = 10; | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | |||
57 | static void viafb_update_fix(struct fb_info *info) | 122 | static void viafb_update_fix(struct fb_info *info) |
58 | { | 123 | { |
59 | u32 bpp = info->var.bits_per_pixel; | 124 | u32 bpp = info->var.bits_per_pixel; |
60 | 125 | ||
61 | info->fix.visual = | 126 | info->fix.visual = |
62 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 127 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
63 | info->fix.line_length = | 128 | info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; |
64 | ((info->var.xres_virtual + 7) & ~7) * bpp / 8; | ||
65 | } | 129 | } |
66 | 130 | ||
67 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, | 131 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, |
@@ -75,6 +139,7 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, | |||
75 | 139 | ||
76 | fix->type = FB_TYPE_PACKED_PIXELS; | 140 | fix->type = FB_TYPE_PACKED_PIXELS; |
77 | fix->type_aux = 0; | 141 | fix->type_aux = 0; |
142 | fix->visual = FB_VISUAL_TRUECOLOR; | ||
78 | 143 | ||
79 | fix->xpanstep = fix->ywrapstep = 0; | 144 | fix->xpanstep = fix->ywrapstep = 0; |
80 | fix->ypanstep = 1; | 145 | fix->ypanstep = 1; |
@@ -97,9 +162,10 @@ static int viafb_release(struct fb_info *info, int user) | |||
97 | static int viafb_check_var(struct fb_var_screeninfo *var, | 162 | static int viafb_check_var(struct fb_var_screeninfo *var, |
98 | struct fb_info *info) | 163 | struct fb_info *info) |
99 | { | 164 | { |
100 | int vmode_index, htotal, vtotal; | 165 | int htotal, vtotal, depth; |
166 | struct VideoModeTable *vmode_entry; | ||
101 | struct viafb_par *ppar = info->par; | 167 | struct viafb_par *ppar = info->par; |
102 | u32 long_refresh; | 168 | u32 long_refresh, line; |
103 | 169 | ||
104 | DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); | 170 | DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); |
105 | /* Sanity check */ | 171 | /* Sanity check */ |
@@ -107,26 +173,36 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
107 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) | 173 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) |
108 | return -EINVAL; | 174 | return -EINVAL; |
109 | 175 | ||
110 | vmode_index = viafb_get_mode_index(var->xres, var->yres); | 176 | vmode_entry = viafb_get_mode(var->xres, var->yres); |
111 | if (vmode_index == VIA_RES_INVALID) { | 177 | if (!vmode_entry) { |
112 | DEBUG_MSG(KERN_INFO | 178 | DEBUG_MSG(KERN_INFO |
113 | "viafb: Mode %dx%dx%d not supported!!\n", | 179 | "viafb: Mode %dx%dx%d not supported!!\n", |
114 | var->xres, var->yres, var->bits_per_pixel); | 180 | var->xres, var->yres, var->bits_per_pixel); |
115 | return -EINVAL; | 181 | return -EINVAL; |
116 | } | 182 | } |
117 | 183 | ||
118 | if (24 == var->bits_per_pixel) | 184 | depth = fb_get_color_depth(var, &info->fix); |
119 | var->bits_per_pixel = 32; | 185 | if (!depth) |
186 | depth = var->bits_per_pixel; | ||
120 | 187 | ||
121 | if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && | 188 | if (depth < 0 || depth > 32) |
122 | var->bits_per_pixel != 32) | ||
123 | return -EINVAL; | 189 | return -EINVAL; |
190 | else if (!depth) | ||
191 | depth = 24; | ||
192 | else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1) | ||
193 | depth = 15; | ||
194 | else if (depth == 30) | ||
195 | depth = 30; | ||
196 | else if (depth <= 8) | ||
197 | depth = 8; | ||
198 | else if (depth <= 16) | ||
199 | depth = 16; | ||
200 | else | ||
201 | depth = 24; | ||
124 | 202 | ||
125 | if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F) | 203 | viafb_fill_var_color_info(var, depth); |
126 | /*32 pixel alignment */ | 204 | line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; |
127 | var->xres_virtual = (var->xres_virtual + 31) & ~31; | 205 | if (line * var->yres_virtual > ppar->memsize) |
128 | if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > | ||
129 | ppar->memsize) | ||
130 | return -EINVAL; | 206 | return -EINVAL; |
131 | 207 | ||
132 | /* Based on var passed in to calculate the refresh, | 208 | /* Based on var passed in to calculate the refresh, |
@@ -142,7 +218,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
142 | viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); | 218 | viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); |
143 | 219 | ||
144 | /* Adjust var according to our driver's own table */ | 220 | /* Adjust var according to our driver's own table */ |
145 | viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); | 221 | viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); |
146 | if (info->var.accel_flags & FB_ACCELF_TEXT && | 222 | if (info->var.accel_flags & FB_ACCELF_TEXT && |
147 | !ppar->shared->engine_mmio) | 223 | !ppar->shared->engine_mmio) |
148 | info->var.accel_flags = 0; | 224 | info->var.accel_flags = 0; |
@@ -153,39 +229,45 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
153 | static int viafb_set_par(struct fb_info *info) | 229 | static int viafb_set_par(struct fb_info *info) |
154 | { | 230 | { |
155 | struct viafb_par *viapar = info->par; | 231 | struct viafb_par *viapar = info->par; |
156 | int vmode_index; | 232 | struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; |
157 | int vmode_index1 = 0; | ||
158 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); | 233 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); |
159 | 234 | ||
160 | viapar->depth = fb_get_color_depth(&info->var, &info->fix); | 235 | viapar->depth = fb_get_color_depth(&info->var, &info->fix); |
161 | viafb_update_device_setting(info->var.xres, info->var.yres, | 236 | viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, |
162 | info->var.bits_per_pixel, viafb_refresh, 0); | 237 | viafbinfo->var.bits_per_pixel, viafb_refresh, 0); |
163 | 238 | ||
164 | vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres); | 239 | vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); |
165 | 240 | if (viafb_dual_fb) { | |
166 | if (viafb_SAMM_ON == 1) { | 241 | vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres, |
242 | viafbinfo1->var.yres); | ||
243 | viafb_update_device_setting(viafbinfo1->var.xres, | ||
244 | viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, | ||
245 | viafb_refresh1, 1); | ||
246 | } else if (viafb_SAMM_ON == 1) { | ||
167 | DEBUG_MSG(KERN_INFO | 247 | DEBUG_MSG(KERN_INFO |
168 | "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", | 248 | "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", |
169 | viafb_second_xres, viafb_second_yres, viafb_bpp1); | 249 | viafb_second_xres, viafb_second_yres, viafb_bpp1); |
170 | vmode_index1 = viafb_get_mode_index(viafb_second_xres, | 250 | vmode_entry1 = viafb_get_mode(viafb_second_xres, |
171 | viafb_second_yres); | 251 | viafb_second_yres); |
172 | DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n", | ||
173 | vmode_index1); | ||
174 | 252 | ||
175 | viafb_update_device_setting(viafb_second_xres, | 253 | viafb_update_device_setting(viafb_second_xres, |
176 | viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); | 254 | viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); |
177 | } | 255 | } |
178 | 256 | ||
179 | if (vmode_index != VIA_RES_INVALID) { | 257 | if (vmode_entry) { |
180 | viafb_update_fix(info); | 258 | viafb_update_fix(info); |
181 | viafb_bpp = info->var.bits_per_pixel; | 259 | if (viafb_dual_fb && viapar->iga_path == IGA2) |
260 | viafb_bpp1 = info->var.bits_per_pixel; | ||
261 | else | ||
262 | viafb_bpp = info->var.bits_per_pixel; | ||
263 | |||
182 | if (info->var.accel_flags & FB_ACCELF_TEXT) | 264 | if (info->var.accel_flags & FB_ACCELF_TEXT) |
183 | info->flags &= ~FBINFO_HWACCEL_DISABLED; | 265 | info->flags &= ~FBINFO_HWACCEL_DISABLED; |
184 | else | 266 | else |
185 | info->flags |= FBINFO_HWACCEL_DISABLED; | 267 | info->flags |= FBINFO_HWACCEL_DISABLED; |
186 | viafb_setmode(vmode_index, info->var.xres, info->var.yres, | 268 | viafb_setmode(vmode_entry, info->var.bits_per_pixel, |
187 | info->var.bits_per_pixel, vmode_index1, | 269 | vmode_entry1, viafb_bpp1); |
188 | viafb_second_xres, viafb_second_yres, viafb_bpp1); | 270 | viafb_pan_display(&info->var, info); |
189 | } | 271 | } |
190 | 272 | ||
191 | return 0; | 273 | return 0; |
@@ -195,234 +277,52 @@ static int viafb_set_par(struct fb_info *info) | |||
195 | static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, | 277 | static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, |
196 | unsigned blue, unsigned transp, struct fb_info *info) | 278 | unsigned blue, unsigned transp, struct fb_info *info) |
197 | { | 279 | { |
198 | u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; | 280 | struct viafb_par *viapar = info->par; |
199 | unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16; | 281 | u32 r, g, b; |
200 | DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n"); | ||
201 | if (regno >= cmap_entries) | ||
202 | return 1; | ||
203 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { | ||
204 | /* | ||
205 | * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev. | ||
206 | */ | ||
207 | outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); | ||
208 | rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; | ||
209 | } | ||
210 | switch (info->var.bits_per_pixel) { | ||
211 | case 8: | ||
212 | outb(0x1A, 0x3C4); | ||
213 | sr1a = inb(0x3C5); | ||
214 | outb(0x1B, 0x3C4); | ||
215 | sr1b = inb(0x3C5); | ||
216 | outb(0x67, 0x3D4); | ||
217 | cr67 = inb(0x3D5); | ||
218 | outb(0x6A, 0x3D4); | ||
219 | cr6a = inb(0x3D5); | ||
220 | |||
221 | /* Map the 3C6/7/8/9 to the IGA2 */ | ||
222 | outb(0x1A, 0x3C4); | ||
223 | outb(sr1a | 0x01, 0x3C5); | ||
224 | /* Second Display Engine colck always on */ | ||
225 | outb(0x1B, 0x3C4); | ||
226 | outb(sr1b | 0x80, 0x3C5); | ||
227 | /* Second Display Color Depth 8 */ | ||
228 | outb(0x67, 0x3D4); | ||
229 | outb(cr67 & 0x3F, 0x3D5); | ||
230 | outb(0x6A, 0x3D4); | ||
231 | /* Second Display Channel Reset CR6A[6]) */ | ||
232 | outb(cr6a & 0xBF, 0x3D5); | ||
233 | /* Second Display Channel Enable CR6A[7] */ | ||
234 | outb(cr6a | 0x80, 0x3D5); | ||
235 | /* Second Display Channel stop reset) */ | ||
236 | outb(cr6a | 0x40, 0x3D5); | ||
237 | |||
238 | /* Bit mask of palette */ | ||
239 | outb(0xFF, 0x3c6); | ||
240 | /* Write one register of IGA2 */ | ||
241 | outb(regno, 0x3C8); | ||
242 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && | ||
243 | rev >= 15) { | ||
244 | shift = 8; | ||
245 | viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); | ||
246 | viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); | ||
247 | } else { | ||
248 | shift = 10; | ||
249 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); | ||
250 | viafb_write_reg_mask(SR15, VIASR, 0, BIT7); | ||
251 | } | ||
252 | outb(red >> shift, 0x3C9); | ||
253 | outb(green >> shift, 0x3C9); | ||
254 | outb(blue >> shift, 0x3C9); | ||
255 | |||
256 | /* Map the 3C6/7/8/9 to the IGA1 */ | ||
257 | outb(0x1A, 0x3C4); | ||
258 | outb(sr1a & 0xFE, 0x3C5); | ||
259 | /* Bit mask of palette */ | ||
260 | outb(0xFF, 0x3c6); | ||
261 | /* Write one register of IGA1 */ | ||
262 | outb(regno, 0x3C8); | ||
263 | outb(red >> shift, 0x3C9); | ||
264 | outb(green >> shift, 0x3C9); | ||
265 | outb(blue >> shift, 0x3C9); | ||
266 | |||
267 | outb(0x1A, 0x3C4); | ||
268 | outb(sr1a, 0x3C5); | ||
269 | outb(0x1B, 0x3C4); | ||
270 | outb(sr1b, 0x3C5); | ||
271 | outb(0x67, 0x3D4); | ||
272 | outb(cr67, 0x3D5); | ||
273 | outb(0x6A, 0x3D4); | ||
274 | outb(cr6a, 0x3D5); | ||
275 | break; | ||
276 | case 16: | ||
277 | ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) | | ||
278 | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); | ||
279 | break; | ||
280 | case 32: | ||
281 | ((u32 *) info->pseudo_palette)[regno] = | ||
282 | ((transp & 0xFF00) << 16) | | ||
283 | ((red & 0xFF00) << 8) | | ||
284 | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | return 0; | ||
289 | 282 | ||
290 | } | 283 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { |
284 | if (regno > 255) | ||
285 | return -EINVAL; | ||
291 | 286 | ||
292 | /*CALLED BY: fb_set_cmap */ | 287 | if (!viafb_dual_fb || viapar->iga_path == IGA1) |
293 | /* fb_set_var, pass 256 colors */ | 288 | viafb_set_primary_color_register(regno, red >> 8, |
294 | /*CALLED BY: fb_set_cmap */ | 289 | green >> 8, blue >> 8); |
295 | /* fbcon_set_palette, pass 16 colors */ | ||
296 | static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) | ||
297 | { | ||
298 | u32 len = cmap->len; | ||
299 | u32 i; | ||
300 | u16 *pred = cmap->red; | ||
301 | u16 *pgreen = cmap->green; | ||
302 | u16 *pblue = cmap->blue; | ||
303 | u16 *ptransp = cmap->transp; | ||
304 | u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; | ||
305 | if (len > 256) | ||
306 | return 1; | ||
307 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { | ||
308 | /* | ||
309 | * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip | ||
310 | * rev. | ||
311 | */ | ||
312 | outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); | ||
313 | rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; | ||
314 | } | ||
315 | switch (info->var.bits_per_pixel) { | ||
316 | case 8: | ||
317 | outb(0x1A, 0x3C4); | ||
318 | sr1a = inb(0x3C5); | ||
319 | outb(0x1B, 0x3C4); | ||
320 | sr1b = inb(0x3C5); | ||
321 | outb(0x67, 0x3D4); | ||
322 | cr67 = inb(0x3D5); | ||
323 | outb(0x6A, 0x3D4); | ||
324 | cr6a = inb(0x3D5); | ||
325 | /* Map the 3C6/7/8/9 to the IGA2 */ | ||
326 | outb(0x1A, 0x3C4); | ||
327 | outb(sr1a | 0x01, 0x3C5); | ||
328 | outb(0x1B, 0x3C4); | ||
329 | /* Second Display Engine colck always on */ | ||
330 | outb(sr1b | 0x80, 0x3C5); | ||
331 | outb(0x67, 0x3D4); | ||
332 | /* Second Display Color Depth 8 */ | ||
333 | outb(cr67 & 0x3F, 0x3D5); | ||
334 | outb(0x6A, 0x3D4); | ||
335 | /* Second Display Channel Reset CR6A[6]) */ | ||
336 | outb(cr6a & 0xBF, 0x3D5); | ||
337 | /* Second Display Channel Enable CR6A[7] */ | ||
338 | outb(cr6a | 0x80, 0x3D5); | ||
339 | /* Second Display Channel stop reset) */ | ||
340 | outb(cr6a | 0xC0, 0x3D5); | ||
341 | |||
342 | /* Bit mask of palette */ | ||
343 | outb(0xFF, 0x3c6); | ||
344 | outb(0x00, 0x3C8); | ||
345 | if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && | ||
346 | rev >= 15) { | ||
347 | shift = 8; | ||
348 | viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); | ||
349 | viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); | ||
350 | } else { | ||
351 | shift = 10; | ||
352 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); | ||
353 | viafb_write_reg_mask(SR15, VIASR, 0, BIT7); | ||
354 | } | ||
355 | for (i = 0; i < len; i++) { | ||
356 | outb((*(pred + i)) >> shift, 0x3C9); | ||
357 | outb((*(pgreen + i)) >> shift, 0x3C9); | ||
358 | outb((*(pblue + i)) >> shift, 0x3C9); | ||
359 | } | ||
360 | 290 | ||
361 | outb(0x1A, 0x3C4); | 291 | if (!viafb_dual_fb || viapar->iga_path == IGA2) |
362 | /* Map the 3C6/7/8/9 to the IGA1 */ | 292 | viafb_set_secondary_color_register(regno, red >> 8, |
363 | outb(sr1a & 0xFE, 0x3C5); | 293 | green >> 8, blue >> 8); |
364 | /* Bit mask of palette */ | 294 | } else { |
365 | outb(0xFF, 0x3c6); | 295 | if (regno > 15) |
366 | outb(0x00, 0x3C8); | 296 | return -EINVAL; |
367 | for (i = 0; i < len; i++) { | ||
368 | outb((*(pred + i)) >> shift, 0x3C9); | ||
369 | outb((*(pgreen + i)) >> shift, 0x3C9); | ||
370 | outb((*(pblue + i)) >> shift, 0x3C9); | ||
371 | } | ||
372 | 297 | ||
373 | outb(0x1A, 0x3C4); | 298 | r = (red >> (16 - info->var.red.length)) |
374 | outb(sr1a, 0x3C5); | 299 | << info->var.red.offset; |
375 | outb(0x1B, 0x3C4); | 300 | b = (blue >> (16 - info->var.blue.length)) |
376 | outb(sr1b, 0x3C5); | 301 | << info->var.blue.offset; |
377 | outb(0x67, 0x3D4); | 302 | g = (green >> (16 - info->var.green.length)) |
378 | outb(cr67, 0x3D5); | 303 | << info->var.green.offset; |
379 | outb(0x6A, 0x3D4); | 304 | ((u32 *) info->pseudo_palette)[regno] = r | g | b; |
380 | outb(cr6a, 0x3D5); | ||
381 | break; | ||
382 | case 16: | ||
383 | if (len > 17) | ||
384 | return 0; /* Because static u32 pseudo_pal[17]; */ | ||
385 | for (i = 0; i < len; i++) | ||
386 | ((u32 *) info->pseudo_palette)[i] = | ||
387 | (*(pred + i) & 0xF800) | | ||
388 | ((*(pgreen + i) & 0xFC00) >> 5) | | ||
389 | ((*(pblue + i) & 0xF800) >> 11); | ||
390 | break; | ||
391 | case 32: | ||
392 | if (len > 17) | ||
393 | return 0; | ||
394 | if (ptransp) { | ||
395 | for (i = 0; i < len; i++) | ||
396 | ((u32 *) info->pseudo_palette)[i] = | ||
397 | ((*(ptransp + i) & 0xFF00) << 16) | | ||
398 | ((*(pred + i) & 0xFF00) << 8) | | ||
399 | ((*(pgreen + i) & 0xFF00)) | | ||
400 | ((*(pblue + i) & 0xFF00) >> 8); | ||
401 | } else { | ||
402 | for (i = 0; i < len; i++) | ||
403 | ((u32 *) info->pseudo_palette)[i] = | ||
404 | 0x00000000 | | ||
405 | ((*(pred + i) & 0xFF00) << 8) | | ||
406 | ((*(pgreen + i) & 0xFF00)) | | ||
407 | ((*(pblue + i) & 0xFF00) >> 8); | ||
408 | } | ||
409 | break; | ||
410 | } | 305 | } |
306 | |||
411 | return 0; | 307 | return 0; |
412 | } | 308 | } |
413 | 309 | ||
414 | static int viafb_pan_display(struct fb_var_screeninfo *var, | 310 | static int viafb_pan_display(struct fb_var_screeninfo *var, |
415 | struct fb_info *info) | 311 | struct fb_info *info) |
416 | { | 312 | { |
417 | unsigned int offset; | 313 | struct viafb_par *viapar = info->par; |
418 | 314 | u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) | |
419 | DEBUG_MSG(KERN_INFO "viafb_pan_display!\n"); | 315 | * (var->bits_per_pixel / 8) + viapar->vram_addr; |
420 | 316 | ||
421 | offset = (var->xoffset + (var->yoffset * var->xres_virtual)) * | 317 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); |
422 | var->bits_per_pixel / 16; | 318 | if (!viafb_dual_fb) { |
319 | viafb_set_primary_address(vram_addr); | ||
320 | viafb_set_secondary_address(vram_addr); | ||
321 | } else if (viapar->iga_path == IGA1) | ||
322 | viafb_set_primary_address(vram_addr); | ||
323 | else | ||
324 | viafb_set_secondary_address(vram_addr); | ||
423 | 325 | ||
424 | DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset); | ||
425 | viafb_set_primary_address(offset); | ||
426 | return 0; | 326 | return 0; |
427 | } | 327 | } |
428 | 328 | ||
@@ -476,6 +376,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
476 | u32 gpu32; | 376 | u32 gpu32; |
477 | 377 | ||
478 | DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); | 378 | DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); |
379 | printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n"); | ||
479 | memset(&u, 0, sizeof(u)); | 380 | memset(&u, 0, sizeof(u)); |
480 | 381 | ||
481 | switch (cmd) { | 382 | switch (cmd) { |
@@ -1015,23 +916,6 @@ static int viafb_sync(struct fb_info *info) | |||
1015 | return 0; | 916 | return 0; |
1016 | } | 917 | } |
1017 | 918 | ||
1018 | int viafb_get_mode_index(int hres, int vres) | ||
1019 | { | ||
1020 | u32 i; | ||
1021 | DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n"); | ||
1022 | |||
1023 | for (i = 0; i < NUM_TOTAL_MODETABLE; i++) | ||
1024 | if (CLE266Modes[i].mode_array && | ||
1025 | CLE266Modes[i].crtc[0].crtc.hor_addr == hres && | ||
1026 | CLE266Modes[i].crtc[0].crtc.ver_addr == vres) | ||
1027 | break; | ||
1028 | |||
1029 | if (i == NUM_TOTAL_MODETABLE) | ||
1030 | return VIA_RES_INVALID; | ||
1031 | |||
1032 | return CLE266Modes[i].ModeIndex; | ||
1033 | } | ||
1034 | |||
1035 | static void check_available_device_to_enable(int device_id) | 919 | static void check_available_device_to_enable(int device_id) |
1036 | { | 920 | { |
1037 | int device_num = 0; | 921 | int device_num = 0; |
@@ -1330,7 +1214,7 @@ static void retrieve_device_setting(struct viafb_ioctl_setting | |||
1330 | setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; | 1214 | setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; |
1331 | } | 1215 | } |
1332 | 1216 | ||
1333 | static void parse_active_dev(void) | 1217 | static int parse_active_dev(void) |
1334 | { | 1218 | { |
1335 | viafb_CRT_ON = STATE_OFF; | 1219 | viafb_CRT_ON = STATE_OFF; |
1336 | viafb_DVI_ON = STATE_OFF; | 1220 | viafb_DVI_ON = STATE_OFF; |
@@ -1341,60 +1225,63 @@ static void parse_active_dev(void) | |||
1341 | IGA path to devices in SAMM case. */ | 1225 | IGA path to devices in SAMM case. */ |
1342 | /* Note: The previous of active_dev is primary device, | 1226 | /* Note: The previous of active_dev is primary device, |
1343 | and the following is secondary device. */ | 1227 | and the following is secondary device. */ |
1344 | if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) { | 1228 | if (!viafb_active_dev) { |
1229 | viafb_CRT_ON = STATE_ON; | ||
1230 | viafb_SAMM_ON = STATE_OFF; | ||
1231 | } else if (!strcmp(viafb_active_dev, "CRT+DVI")) { | ||
1345 | /* CRT+DVI */ | 1232 | /* CRT+DVI */ |
1346 | viafb_CRT_ON = STATE_ON; | 1233 | viafb_CRT_ON = STATE_ON; |
1347 | viafb_DVI_ON = STATE_ON; | 1234 | viafb_DVI_ON = STATE_ON; |
1348 | viafb_primary_dev = CRT_Device; | 1235 | viafb_primary_dev = CRT_Device; |
1349 | } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) { | 1236 | } else if (!strcmp(viafb_active_dev, "DVI+CRT")) { |
1350 | /* DVI+CRT */ | 1237 | /* DVI+CRT */ |
1351 | viafb_CRT_ON = STATE_ON; | 1238 | viafb_CRT_ON = STATE_ON; |
1352 | viafb_DVI_ON = STATE_ON; | 1239 | viafb_DVI_ON = STATE_ON; |
1353 | viafb_primary_dev = DVI_Device; | 1240 | viafb_primary_dev = DVI_Device; |
1354 | } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) { | 1241 | } else if (!strcmp(viafb_active_dev, "CRT+LCD")) { |
1355 | /* CRT+LCD */ | 1242 | /* CRT+LCD */ |
1356 | viafb_CRT_ON = STATE_ON; | 1243 | viafb_CRT_ON = STATE_ON; |
1357 | viafb_LCD_ON = STATE_ON; | 1244 | viafb_LCD_ON = STATE_ON; |
1358 | viafb_primary_dev = CRT_Device; | 1245 | viafb_primary_dev = CRT_Device; |
1359 | } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) { | 1246 | } else if (!strcmp(viafb_active_dev, "LCD+CRT")) { |
1360 | /* LCD+CRT */ | 1247 | /* LCD+CRT */ |
1361 | viafb_CRT_ON = STATE_ON; | 1248 | viafb_CRT_ON = STATE_ON; |
1362 | viafb_LCD_ON = STATE_ON; | 1249 | viafb_LCD_ON = STATE_ON; |
1363 | viafb_primary_dev = LCD_Device; | 1250 | viafb_primary_dev = LCD_Device; |
1364 | } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) { | 1251 | } else if (!strcmp(viafb_active_dev, "DVI+LCD")) { |
1365 | /* DVI+LCD */ | 1252 | /* DVI+LCD */ |
1366 | viafb_DVI_ON = STATE_ON; | 1253 | viafb_DVI_ON = STATE_ON; |
1367 | viafb_LCD_ON = STATE_ON; | 1254 | viafb_LCD_ON = STATE_ON; |
1368 | viafb_primary_dev = DVI_Device; | 1255 | viafb_primary_dev = DVI_Device; |
1369 | } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) { | 1256 | } else if (!strcmp(viafb_active_dev, "LCD+DVI")) { |
1370 | /* LCD+DVI */ | 1257 | /* LCD+DVI */ |
1371 | viafb_DVI_ON = STATE_ON; | 1258 | viafb_DVI_ON = STATE_ON; |
1372 | viafb_LCD_ON = STATE_ON; | 1259 | viafb_LCD_ON = STATE_ON; |
1373 | viafb_primary_dev = LCD_Device; | 1260 | viafb_primary_dev = LCD_Device; |
1374 | } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) { | 1261 | } else if (!strcmp(viafb_active_dev, "LCD+LCD2")) { |
1375 | viafb_LCD_ON = STATE_ON; | 1262 | viafb_LCD_ON = STATE_ON; |
1376 | viafb_LCD2_ON = STATE_ON; | 1263 | viafb_LCD2_ON = STATE_ON; |
1377 | viafb_primary_dev = LCD_Device; | 1264 | viafb_primary_dev = LCD_Device; |
1378 | } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) { | 1265 | } else if (!strcmp(viafb_active_dev, "LCD2+LCD")) { |
1379 | viafb_LCD_ON = STATE_ON; | 1266 | viafb_LCD_ON = STATE_ON; |
1380 | viafb_LCD2_ON = STATE_ON; | 1267 | viafb_LCD2_ON = STATE_ON; |
1381 | viafb_primary_dev = LCD2_Device; | 1268 | viafb_primary_dev = LCD2_Device; |
1382 | } else if (!strncmp(viafb_active_dev, "CRT", 3)) { | 1269 | } else if (!strcmp(viafb_active_dev, "CRT")) { |
1383 | /* CRT only */ | 1270 | /* CRT only */ |
1384 | viafb_CRT_ON = STATE_ON; | 1271 | viafb_CRT_ON = STATE_ON; |
1385 | viafb_SAMM_ON = STATE_OFF; | 1272 | viafb_SAMM_ON = STATE_OFF; |
1386 | } else if (!strncmp(viafb_active_dev, "DVI", 3)) { | 1273 | } else if (!strcmp(viafb_active_dev, "DVI")) { |
1387 | /* DVI only */ | 1274 | /* DVI only */ |
1388 | viafb_DVI_ON = STATE_ON; | 1275 | viafb_DVI_ON = STATE_ON; |
1389 | viafb_SAMM_ON = STATE_OFF; | 1276 | viafb_SAMM_ON = STATE_OFF; |
1390 | } else if (!strncmp(viafb_active_dev, "LCD", 3)) { | 1277 | } else if (!strcmp(viafb_active_dev, "LCD")) { |
1391 | /* LCD only */ | 1278 | /* LCD only */ |
1392 | viafb_LCD_ON = STATE_ON; | 1279 | viafb_LCD_ON = STATE_ON; |
1393 | viafb_SAMM_ON = STATE_OFF; | 1280 | viafb_SAMM_ON = STATE_OFF; |
1394 | } else { | 1281 | } else |
1395 | viafb_CRT_ON = STATE_ON; | 1282 | return -EINVAL; |
1396 | viafb_SAMM_ON = STATE_OFF; | 1283 | |
1397 | } | 1284 | return 0; |
1398 | } | 1285 | } |
1399 | 1286 | ||
1400 | static int parse_port(char *opt_str, int *output_interface) | 1287 | static int parse_port(char *opt_str, int *output_interface) |
@@ -1823,35 +1710,37 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) | |||
1823 | remove_proc_entry("viafb", NULL); | 1710 | remove_proc_entry("viafb", NULL); |
1824 | } | 1711 | } |
1825 | 1712 | ||
1826 | static void parse_mode(const char *str, u32 *xres, u32 *yres) | 1713 | static int parse_mode(const char *str, u32 *xres, u32 *yres) |
1827 | { | 1714 | { |
1828 | char *ptr; | 1715 | char *ptr; |
1829 | 1716 | ||
1717 | if (!str) { | ||
1718 | *xres = 640; | ||
1719 | *yres = 480; | ||
1720 | return 0; | ||
1721 | } | ||
1722 | |||
1830 | *xres = simple_strtoul(str, &ptr, 10); | 1723 | *xres = simple_strtoul(str, &ptr, 10); |
1831 | if (ptr[0] != 'x') | 1724 | if (ptr[0] != 'x') |
1832 | goto out_default; | 1725 | return -EINVAL; |
1833 | 1726 | ||
1834 | *yres = simple_strtoul(&ptr[1], &ptr, 10); | 1727 | *yres = simple_strtoul(&ptr[1], &ptr, 10); |
1835 | if (ptr[0]) | 1728 | if (ptr[0]) |
1836 | goto out_default; | 1729 | return -EINVAL; |
1837 | |||
1838 | return; | ||
1839 | 1730 | ||
1840 | out_default: | 1731 | return 0; |
1841 | printk(KERN_WARNING "viafb received invalid mode string: %s\n", str); | ||
1842 | *xres = 640; | ||
1843 | *yres = 480; | ||
1844 | } | 1732 | } |
1845 | 1733 | ||
1846 | static int __devinit via_pci_probe(struct pci_dev *pdev, | 1734 | static int __devinit via_pci_probe(struct pci_dev *pdev, |
1847 | const struct pci_device_id *ent) | 1735 | const struct pci_device_id *ent) |
1848 | { | 1736 | { |
1849 | u32 default_xres, default_yres; | 1737 | u32 default_xres, default_yres; |
1850 | int vmode_index; | 1738 | struct VideoModeTable *vmode_entry; |
1739 | struct fb_var_screeninfo default_var; | ||
1851 | u32 viafb_par_length; | 1740 | u32 viafb_par_length; |
1852 | 1741 | ||
1853 | DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); | 1742 | DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); |
1854 | 1743 | memset(&default_var, 0, sizeof(default_var)); | |
1855 | viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); | 1744 | viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); |
1856 | 1745 | ||
1857 | /* Allocate fb_info and ***_par here, also including some other needed | 1746 | /* Allocate fb_info and ***_par here, also including some other needed |
@@ -1877,7 +1766,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1877 | 1766 | ||
1878 | if (viafb_dual_fb) | 1767 | if (viafb_dual_fb) |
1879 | viafb_SAMM_ON = 1; | 1768 | viafb_SAMM_ON = 1; |
1880 | parse_active_dev(); | ||
1881 | parse_lcd_port(); | 1769 | parse_lcd_port(); |
1882 | parse_dvi_port(); | 1770 | parse_dvi_port(); |
1883 | 1771 | ||
@@ -1926,9 +1814,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1926 | } | 1814 | } |
1927 | 1815 | ||
1928 | parse_mode(viafb_mode, &default_xres, &default_yres); | 1816 | parse_mode(viafb_mode, &default_xres, &default_yres); |
1929 | vmode_index = viafb_get_mode_index(default_xres, default_yres); | 1817 | vmode_entry = viafb_get_mode(default_xres, default_yres); |
1930 | DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); | ||
1931 | |||
1932 | if (viafb_SAMM_ON == 1) { | 1818 | if (viafb_SAMM_ON == 1) { |
1933 | parse_mode(viafb_mode1, &viafb_second_xres, | 1819 | parse_mode(viafb_mode1, &viafb_second_xres, |
1934 | &viafb_second_yres); | 1820 | &viafb_second_yres); |
@@ -1947,19 +1833,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1947 | viafb_second_virtual_yres = viafb_second_yres; | 1833 | viafb_second_virtual_yres = viafb_second_yres; |
1948 | } | 1834 | } |
1949 | 1835 | ||
1950 | switch (viafb_bpp) { | ||
1951 | case 0 ... 8: | ||
1952 | viafb_bpp = 8; | ||
1953 | break; | ||
1954 | case 9 ... 16: | ||
1955 | viafb_bpp = 16; | ||
1956 | break; | ||
1957 | case 17 ... 32: | ||
1958 | viafb_bpp = 32; | ||
1959 | break; | ||
1960 | default: | ||
1961 | viafb_bpp = 8; | ||
1962 | } | ||
1963 | default_var.xres = default_xres; | 1836 | default_var.xres = default_xres; |
1964 | default_var.yres = default_yres; | 1837 | default_var.yres = default_yres; |
1965 | switch (default_xres) { | 1838 | switch (default_xres) { |
@@ -1972,8 +1845,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1972 | } | 1845 | } |
1973 | default_var.yres_virtual = default_yres; | 1846 | default_var.yres_virtual = default_yres; |
1974 | default_var.bits_per_pixel = viafb_bpp; | 1847 | default_var.bits_per_pixel = viafb_bpp; |
1975 | if (default_var.bits_per_pixel == 15) | ||
1976 | default_var.bits_per_pixel = 16; | ||
1977 | default_var.pixclock = | 1848 | default_var.pixclock = |
1978 | viafb_get_pixclock(default_xres, default_yres, viafb_refresh); | 1849 | viafb_get_pixclock(default_xres, default_yres, viafb_refresh); |
1979 | default_var.left_margin = (default_xres >> 3) & 0xf8; | 1850 | default_var.left_margin = (default_xres >> 3) & 0xf8; |
@@ -1982,6 +1853,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1982 | default_var.lower_margin = 4; | 1853 | default_var.lower_margin = 4; |
1983 | default_var.hsync_len = default_var.left_margin; | 1854 | default_var.hsync_len = default_var.left_margin; |
1984 | default_var.vsync_len = 4; | 1855 | default_var.vsync_len = 4; |
1856 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); | ||
1857 | viafbinfo->var = default_var; | ||
1985 | 1858 | ||
1986 | if (viafb_dual_fb) { | 1859 | if (viafb_dual_fb) { |
1987 | viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); | 1860 | viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); |
@@ -2016,8 +1889,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
2016 | default_var.yres = viafb_second_yres; | 1889 | default_var.yres = viafb_second_yres; |
2017 | default_var.xres_virtual = viafb_second_virtual_xres; | 1890 | default_var.xres_virtual = viafb_second_virtual_xres; |
2018 | default_var.yres_virtual = viafb_second_virtual_yres; | 1891 | default_var.yres_virtual = viafb_second_virtual_yres; |
2019 | if (viafb_bpp1 != viafb_bpp) | ||
2020 | viafb_bpp1 = viafb_bpp; | ||
2021 | default_var.bits_per_pixel = viafb_bpp1; | 1892 | default_var.bits_per_pixel = viafb_bpp1; |
2022 | default_var.pixclock = | 1893 | default_var.pixclock = |
2023 | viafb_get_pixclock(viafb_second_xres, viafb_second_yres, | 1894 | viafb_get_pixclock(viafb_second_xres, viafb_second_yres, |
@@ -2037,9 +1908,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
2037 | &viafbinfo1->fix); | 1908 | &viafbinfo1->fix); |
2038 | } | 1909 | } |
2039 | 1910 | ||
2040 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); | 1911 | viafb_check_var(&viafbinfo->var, viafbinfo); |
2041 | viafb_check_var(&default_var, viafbinfo); | ||
2042 | viafbinfo->var = default_var; | ||
2043 | viafb_update_fix(viafbinfo); | 1912 | viafb_update_fix(viafbinfo); |
2044 | viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, | 1913 | viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, |
2045 | &viafbinfo->fix); | 1914 | &viafbinfo->fix); |
@@ -2197,12 +2066,20 @@ static struct pci_driver viafb_driver = { | |||
2197 | 2066 | ||
2198 | static int __init viafb_init(void) | 2067 | static int __init viafb_init(void) |
2199 | { | 2068 | { |
2069 | u32 dummy; | ||
2200 | #ifndef MODULE | 2070 | #ifndef MODULE |
2201 | char *option = NULL; | 2071 | char *option = NULL; |
2202 | if (fb_get_options("viafb", &option)) | 2072 | if (fb_get_options("viafb", &option)) |
2203 | return -ENODEV; | 2073 | return -ENODEV; |
2204 | viafb_setup(option); | 2074 | viafb_setup(option); |
2205 | #endif | 2075 | #endif |
2076 | if (parse_mode(viafb_mode, &dummy, &dummy) | ||
2077 | || parse_mode(viafb_mode1, &dummy, &dummy) | ||
2078 | || viafb_bpp < 0 || viafb_bpp > 32 | ||
2079 | || viafb_bpp1 < 0 || viafb_bpp1 > 32 | ||
2080 | || parse_active_dev()) | ||
2081 | return -EINVAL; | ||
2082 | |||
2206 | printk(KERN_INFO | 2083 | printk(KERN_INFO |
2207 | "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", | 2084 | "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", |
2208 | VERSION_MAJOR, VERSION_MINOR); | 2085 | VERSION_MAJOR, VERSION_MINOR); |
@@ -2230,15 +2107,12 @@ static struct fb_ops viafb_ops = { | |||
2230 | .fb_cursor = viafb_cursor, | 2107 | .fb_cursor = viafb_cursor, |
2231 | .fb_ioctl = viafb_ioctl, | 2108 | .fb_ioctl = viafb_ioctl, |
2232 | .fb_sync = viafb_sync, | 2109 | .fb_sync = viafb_sync, |
2233 | .fb_setcmap = viafb_setcmap, | ||
2234 | }; | 2110 | }; |
2235 | 2111 | ||
2236 | module_init(viafb_init); | 2112 | module_init(viafb_init); |
2237 | module_exit(viafb_exit); | 2113 | module_exit(viafb_exit); |
2238 | 2114 | ||
2239 | #ifdef MODULE | 2115 | #ifdef MODULE |
2240 | module_param(viafb_memsize, int, S_IRUSR); | ||
2241 | |||
2242 | module_param(viafb_mode, charp, S_IRUSR); | 2116 | module_param(viafb_mode, charp, S_IRUSR); |
2243 | MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); | 2117 | MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); |
2244 | 2118 | ||
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 0c94d2441922..61b5953cd159 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h | |||
@@ -83,22 +83,16 @@ struct viafb_par { | |||
83 | 83 | ||
84 | extern unsigned int viafb_second_virtual_yres; | 84 | extern unsigned int viafb_second_virtual_yres; |
85 | extern unsigned int viafb_second_virtual_xres; | 85 | extern unsigned int viafb_second_virtual_xres; |
86 | extern unsigned int viafb_second_offset; | ||
87 | extern int viafb_second_size; | ||
88 | extern int viafb_SAMM_ON; | 86 | extern int viafb_SAMM_ON; |
89 | extern int viafb_dual_fb; | 87 | extern int viafb_dual_fb; |
90 | extern int viafb_LCD2_ON; | 88 | extern int viafb_LCD2_ON; |
91 | extern int viafb_LCD_ON; | 89 | extern int viafb_LCD_ON; |
92 | extern int viafb_DVI_ON; | 90 | extern int viafb_DVI_ON; |
93 | extern int viafb_hotplug; | 91 | extern int viafb_hotplug; |
94 | extern int viafb_memsize; | ||
95 | 92 | ||
96 | extern int strict_strtoul(const char *cp, unsigned int base, | 93 | extern int strict_strtoul(const char *cp, unsigned int base, |
97 | unsigned long *res); | 94 | unsigned long *res); |
98 | 95 | ||
99 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | ||
100 | int mode_index); | ||
101 | int viafb_get_mode_index(int hres, int vres); | ||
102 | u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information | 96 | u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information |
103 | *plvds_setting_info, struct lvds_chip_information | 97 | *plvds_setting_info, struct lvds_chip_information |
104 | *plvds_chip_info, u8 index); | 98 | *plvds_chip_info, u8 index); |
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index b74f8a67923c..af50e244016c 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c | |||
@@ -412,7 +412,7 @@ struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C}, | |||
412 | }; | 412 | }; |
413 | 413 | ||
414 | struct patch_table res_patch_table[] = { | 414 | struct patch_table res_patch_table[] = { |
415 | {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768} | 415 | {ARRAY_SIZE(PM1024x768), PM1024x768} |
416 | }; | 416 | }; |
417 | 417 | ||
418 | /* struct VPITTable { | 418 | /* struct VPITTable { |
@@ -879,169 +879,151 @@ struct crt_mode_table CRTM2048x1536[] = { | |||
879 | {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} } | 879 | {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} } |
880 | }; | 880 | }; |
881 | 881 | ||
882 | /* Video Mode Table */ | 882 | struct VideoModeTable viafb_modes[] = { |
883 | /* struct VideoModeTable {*/ | ||
884 | /* int ModeIndex;*/ | ||
885 | /* struct crt_mode_table *crtc;*/ | ||
886 | /* int mode_array;*/ | ||
887 | /* };*/ | ||
888 | struct VideoModeTable CLE266Modes[] = { | ||
889 | /* Display : 480x640 (GTF) */ | 883 | /* Display : 480x640 (GTF) */ |
890 | {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)}, | 884 | {CRTM480x640, ARRAY_SIZE(CRTM480x640)}, |
891 | 885 | ||
892 | /* Display : 640x480 */ | 886 | /* Display : 640x480 */ |
893 | {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)}, | 887 | {CRTM640x480, ARRAY_SIZE(CRTM640x480)}, |
894 | 888 | ||
895 | /* Display : 720x480 (GTF) */ | 889 | /* Display : 720x480 (GTF) */ |
896 | {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)}, | 890 | {CRTM720x480, ARRAY_SIZE(CRTM720x480)}, |
897 | 891 | ||
898 | /* Display : 720x576 (GTF) */ | 892 | /* Display : 720x576 (GTF) */ |
899 | {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)}, | 893 | {CRTM720x576, ARRAY_SIZE(CRTM720x576)}, |
900 | 894 | ||
901 | /* Display : 800x600 */ | 895 | /* Display : 800x600 */ |
902 | {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)}, | 896 | {CRTM800x600, ARRAY_SIZE(CRTM800x600)}, |
903 | 897 | ||
904 | /* Display : 800x480 (CVT) */ | 898 | /* Display : 800x480 (CVT) */ |
905 | {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)}, | 899 | {CRTM800x480, ARRAY_SIZE(CRTM800x480)}, |
906 | 900 | ||
907 | /* Display : 848x480 (CVT) */ | 901 | /* Display : 848x480 (CVT) */ |
908 | {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)}, | 902 | {CRTM848x480, ARRAY_SIZE(CRTM848x480)}, |
909 | 903 | ||
910 | /* Display : 852x480 (GTF) */ | 904 | /* Display : 852x480 (GTF) */ |
911 | {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)}, | 905 | {CRTM852x480, ARRAY_SIZE(CRTM852x480)}, |
912 | 906 | ||
913 | /* Display : 1024x512 (GTF) */ | 907 | /* Display : 1024x512 (GTF) */ |
914 | {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, | 908 | {CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, |
915 | 909 | ||
916 | /* Display : 1024x600 */ | 910 | /* Display : 1024x600 */ |
917 | {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, | 911 | {CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, |
918 | |||
919 | /* Display : 1024x576 (GTF) */ | ||
920 | /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */ | ||
921 | 912 | ||
922 | /* Display : 1024x768 */ | 913 | /* Display : 1024x768 */ |
923 | {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, | 914 | {CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, |
924 | 915 | ||
925 | /* Display : 1152x864 */ | 916 | /* Display : 1152x864 */ |
926 | {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, | 917 | {CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, |
927 | 918 | ||
928 | /* Display : 1280x768 (GTF) */ | 919 | /* Display : 1280x768 (GTF) */ |
929 | {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, | 920 | {CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, |
930 | 921 | ||
931 | /* Display : 960x600 (CVT) */ | 922 | /* Display : 960x600 (CVT) */ |
932 | {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)}, | 923 | {CRTM960x600, ARRAY_SIZE(CRTM960x600)}, |
933 | 924 | ||
934 | /* Display : 1000x600 (GTF) */ | 925 | /* Display : 1000x600 (GTF) */ |
935 | {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, | 926 | {CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, |
936 | 927 | ||
937 | /* Display : 1024x576 (GTF) */ | 928 | /* Display : 1024x576 (GTF) */ |
938 | {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, | 929 | {CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, |
939 | 930 | ||
940 | /* Display : 1088x612 (GTF) */ | 931 | /* Display : 1088x612 (GTF) */ |
941 | {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, | 932 | {CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, |
942 | 933 | ||
943 | /* Display : 1152x720 (CVT) */ | 934 | /* Display : 1152x720 (CVT) */ |
944 | {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, | 935 | {CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, |
945 | 936 | ||
946 | /* Display : 1200x720 (GTF) */ | 937 | /* Display : 1200x720 (GTF) */ |
947 | {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, | 938 | {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, |
948 | 939 | ||
949 | /* Display : 1280x600 (GTF) */ | 940 | /* Display : 1280x600 (GTF) */ |
950 | {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, | 941 | {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, |
951 | 942 | ||
952 | /* Display : 1280x800 (CVT) */ | 943 | /* Display : 1280x800 (CVT) */ |
953 | {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, | 944 | {CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, |
954 | |||
955 | /* Display : 1280x800 (GTF) */ | ||
956 | /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */ | ||
957 | 945 | ||
958 | /* Display : 1280x960 */ | 946 | /* Display : 1280x960 */ |
959 | {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, | 947 | {CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, |
960 | 948 | ||
961 | /* Display : 1280x1024 */ | 949 | /* Display : 1280x1024 */ |
962 | {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, | 950 | {CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, |
963 | 951 | ||
964 | /* Display : 1360x768 (CVT) */ | 952 | /* Display : 1360x768 (CVT) */ |
965 | {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, | 953 | {CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, |
966 | |||
967 | /* Display : 1360x768 (CVT Reduce Blanking) */ | ||
968 | {VIA_RES_1360X768_RB, CRTM1360x768_RB, | ||
969 | ARRAY_SIZE(CRTM1360x768_RB)}, | ||
970 | 954 | ||
971 | /* Display : 1366x768 */ | 955 | /* Display : 1366x768 */ |
972 | {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, | 956 | {CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, |
973 | 957 | ||
974 | /* Display : 1368x768 (GTF) */ | 958 | /* Display : 1368x768 (GTF) */ |
975 | /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */ | 959 | {CRTM1368x768, ARRAY_SIZE(CRTM1368x768)}, |
976 | /* Display : 1368x768 (GTF) */ | ||
977 | {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)}, | ||
978 | 960 | ||
979 | /* Display : 1440x900 (CVT) */ | 961 | /* Display : 1440x900 (CVT) */ |
980 | {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, | 962 | {CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, |
981 | |||
982 | /* Display : 1440x900 (CVT Reduce Blanking) */ | ||
983 | {VIA_RES_1440X900_RB, CRTM1440x900_RB, | ||
984 | ARRAY_SIZE(CRTM1440x900_RB)}, | ||
985 | 963 | ||
986 | /* Display : 1440x1050 (GTF) */ | 964 | /* Display : 1440x1050 (GTF) */ |
987 | {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, | 965 | {CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, |
988 | |||
989 | /* Display : 1400x1050 (CVT Reduce Blanking) */ | ||
990 | {VIA_RES_1400X1050_RB, CRTM1400x1050_RB, | ||
991 | ARRAY_SIZE(CRTM1400x1050_RB)}, | ||
992 | 966 | ||
993 | /* Display : 1600x900 (CVT) */ | 967 | /* Display : 1600x900 (CVT) */ |
994 | {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, | 968 | {CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, |
995 | |||
996 | /* Display : 1600x900 (CVT Reduce Blanking) */ | ||
997 | {VIA_RES_1600X900_RB, CRTM1600x900_RB, | ||
998 | ARRAY_SIZE(CRTM1600x900_RB)}, | ||
999 | 969 | ||
1000 | /* Display : 1600x1024 (GTF) */ | 970 | /* Display : 1600x1024 (GTF) */ |
1001 | {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, | 971 | {CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, |
1002 | 972 | ||
1003 | /* Display : 1600x1200 */ | 973 | /* Display : 1600x1200 */ |
1004 | {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, | 974 | {CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, |
1005 | 975 | ||
1006 | /* Display : 1680x1050 (CVT) */ | 976 | /* Display : 1680x1050 (CVT) */ |
1007 | {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, | 977 | {CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, |
1008 | |||
1009 | /* Display : 1680x1050 (CVT Reduce Blanking) */ | ||
1010 | {VIA_RES_1680X1050_RB, CRTM1680x1050_RB, | ||
1011 | ARRAY_SIZE(CRTM1680x1050_RB)}, | ||
1012 | 978 | ||
1013 | /* Display : 1792x1344 (DMT) */ | 979 | /* Display : 1792x1344 (DMT) */ |
1014 | {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, | 980 | {CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, |
1015 | 981 | ||
1016 | /* Display : 1856x1392 (DMT) */ | 982 | /* Display : 1856x1392 (DMT) */ |
1017 | {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, | 983 | {CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, |
1018 | 984 | ||
1019 | /* Display : 1920x1440 */ | 985 | /* Display : 1920x1440 */ |
1020 | {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, | 986 | {CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, |
1021 | 987 | ||
1022 | /* Display : 2048x1536 */ | 988 | /* Display : 2048x1536 */ |
1023 | {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, | 989 | {CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, |
1024 | 990 | ||
1025 | /* Display : 1280x720 */ | 991 | /* Display : 1280x720 */ |
1026 | {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, | 992 | {CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, |
1027 | 993 | ||
1028 | /* Display : 1920x1080 (CVT) */ | 994 | /* Display : 1920x1080 (CVT) */ |
1029 | {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, | 995 | {CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, |
1030 | |||
1031 | /* Display : 1920x1080 (CVT Reduce Blanking) */ | ||
1032 | {VIA_RES_1920X1080_RB, CRTM1920x1080_RB, | ||
1033 | ARRAY_SIZE(CRTM1920x1080_RB)}, | ||
1034 | 996 | ||
1035 | /* Display : 1920x1200 (CVT) */ | 997 | /* Display : 1920x1200 (CVT) */ |
1036 | {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, | 998 | {CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, |
1037 | |||
1038 | /* Display : 1920x1200 (CVT Reduce Blanking) */ | ||
1039 | {VIA_RES_1920X1200_RB, CRTM1920x1200_RB, | ||
1040 | ARRAY_SIZE(CRTM1920x1200_RB)}, | ||
1041 | 999 | ||
1042 | /* Display : 1400x1050 (CVT) */ | 1000 | /* Display : 1400x1050 (CVT) */ |
1043 | {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} | 1001 | {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} |
1044 | }; | 1002 | }; |
1003 | |||
1004 | struct VideoModeTable viafb_rb_modes[] = { | ||
1005 | /* Display : 1360x768 (CVT Reduce Blanking) */ | ||
1006 | {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)}, | ||
1007 | |||
1008 | /* Display : 1440x900 (CVT Reduce Blanking) */ | ||
1009 | {CRTM1440x900_RB, ARRAY_SIZE(CRTM1440x900_RB)}, | ||
1010 | |||
1011 | /* Display : 1400x1050 (CVT Reduce Blanking) */ | ||
1012 | {CRTM1400x1050_RB, ARRAY_SIZE(CRTM1400x1050_RB)}, | ||
1013 | |||
1014 | /* Display : 1600x900 (CVT Reduce Blanking) */ | ||
1015 | {CRTM1600x900_RB, ARRAY_SIZE(CRTM1600x900_RB)}, | ||
1016 | |||
1017 | /* Display : 1680x1050 (CVT Reduce Blanking) */ | ||
1018 | {CRTM1680x1050_RB, ARRAY_SIZE(CRTM1680x1050_RB)}, | ||
1019 | |||
1020 | /* Display : 1920x1080 (CVT Reduce Blanking) */ | ||
1021 | {CRTM1920x1080_RB, ARRAY_SIZE(CRTM1920x1080_RB)}, | ||
1022 | |||
1023 | /* Display : 1920x1200 (CVT Reduce Blanking) */ | ||
1024 | {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)} | ||
1025 | }; | ||
1026 | |||
1045 | struct crt_mode_table CEAM1280x720[] = { | 1027 | struct crt_mode_table CEAM1280x720[] = { |
1046 | {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP, | 1028 | {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP, |
1047 | M1280X720_CEA_R60_VSP, | 1029 | M1280X720_CEA_R60_VSP, |
@@ -1056,8 +1038,8 @@ struct crt_mode_table CEAM1920x1080[] = { | |||
1056 | }; | 1038 | }; |
1057 | struct VideoModeTable CEA_HDMI_Modes[] = { | 1039 | struct VideoModeTable CEA_HDMI_Modes[] = { |
1058 | /* Display : 1280x720 */ | 1040 | /* Display : 1280x720 */ |
1059 | {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, | 1041 | {CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, |
1060 | {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} | 1042 | {CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} |
1061 | }; | 1043 | }; |
1062 | 1044 | ||
1063 | int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl); | 1045 | int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl); |
@@ -1069,4 +1051,28 @@ int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs); | |||
1069 | int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs); | 1051 | int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs); |
1070 | int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); | 1052 | int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); |
1071 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); | 1053 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); |
1072 | int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes); | 1054 | |
1055 | |||
1056 | struct VideoModeTable *viafb_get_mode(int hres, int vres) | ||
1057 | { | ||
1058 | u32 i; | ||
1059 | for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) | ||
1060 | if (viafb_modes[i].mode_array && | ||
1061 | viafb_modes[i].crtc[0].crtc.hor_addr == hres && | ||
1062 | viafb_modes[i].crtc[0].crtc.ver_addr == vres) | ||
1063 | return &viafb_modes[i]; | ||
1064 | |||
1065 | return NULL; | ||
1066 | } | ||
1067 | |||
1068 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) | ||
1069 | { | ||
1070 | u32 i; | ||
1071 | for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) | ||
1072 | if (viafb_rb_modes[i].mode_array && | ||
1073 | viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres && | ||
1074 | viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres) | ||
1075 | return &viafb_rb_modes[i]; | ||
1076 | |||
1077 | return NULL; | ||
1078 | } | ||
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index a9d6554fabdf..5b1ced86514b 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h | |||
@@ -32,13 +32,11 @@ struct VPITTable { | |||
32 | }; | 32 | }; |
33 | 33 | ||
34 | struct VideoModeTable { | 34 | struct VideoModeTable { |
35 | int ModeIndex; | ||
36 | struct crt_mode_table *crtc; | 35 | struct crt_mode_table *crtc; |
37 | int mode_array; | 36 | int mode_array; |
38 | }; | 37 | }; |
39 | 38 | ||
40 | struct patch_table { | 39 | struct patch_table { |
41 | int mode_index; | ||
42 | int table_length; | 40 | int table_length; |
43 | struct io_reg *io_reg_table; | 41 | struct io_reg *io_reg_table; |
44 | }; | 42 | }; |
@@ -59,13 +57,11 @@ extern int NUM_TOTAL_CX700_ModeXregs; | |||
59 | extern int NUM_TOTAL_VX855_ModeXregs; | 57 | extern int NUM_TOTAL_VX855_ModeXregs; |
60 | extern int NUM_TOTAL_CLE266_ModeXregs; | 58 | extern int NUM_TOTAL_CLE266_ModeXregs; |
61 | extern int NUM_TOTAL_PATCH_MODE; | 59 | extern int NUM_TOTAL_PATCH_MODE; |
62 | extern int NUM_TOTAL_MODETABLE; | ||
63 | 60 | ||
64 | /********************/ | 61 | /********************/ |
65 | /* Mode Table */ | 62 | /* Mode Table */ |
66 | /********************/ | 63 | /********************/ |
67 | 64 | ||
68 | extern struct VideoModeTable CLE266Modes[]; | ||
69 | extern struct crt_mode_table CEAM1280x720[]; | 65 | extern struct crt_mode_table CEAM1280x720[]; |
70 | extern struct crt_mode_table CEAM1920x1080[]; | 66 | extern struct crt_mode_table CEAM1920x1080[]; |
71 | extern struct VideoModeTable CEA_HDMI_Modes[]; | 67 | extern struct VideoModeTable CEA_HDMI_Modes[]; |
@@ -81,4 +77,8 @@ extern struct io_reg CLE266_ModeXregs[]; | |||
81 | extern struct io_reg PM1024x768[]; | 77 | extern struct io_reg PM1024x768[]; |
82 | extern struct patch_table res_patch_table[]; | 78 | extern struct patch_table res_patch_table[]; |
83 | extern struct VPITTable VPIT; | 79 | extern struct VPITTable VPIT; |
80 | |||
81 | struct VideoModeTable *viafb_get_mode(int hres, int vres); | ||
82 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); | ||
83 | |||
84 | #endif /* __VIAMODE_H__ */ | 84 | #endif /* __VIAMODE_H__ */ |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 2376f688ec8b..5d223959778a 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -628,7 +628,7 @@ static int w100fb_resume(struct platform_device *dev) | |||
628 | #endif | 628 | #endif |
629 | 629 | ||
630 | 630 | ||
631 | int __init w100fb_probe(struct platform_device *pdev) | 631 | int __devinit w100fb_probe(struct platform_device *pdev) |
632 | { | 632 | { |
633 | int err = -EIO; | 633 | int err = -EIO; |
634 | struct w100fb_mach_info *inf; | 634 | struct w100fb_mach_info *inf; |
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index 406caa6a71cb..e5f74416d4b7 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c | |||
@@ -214,7 +214,7 @@ static int ds2482_wait_1wire_idle(struct ds2482_data *pdev) | |||
214 | (++retries < DS2482_WAIT_IDLE_TIMEOUT)); | 214 | (++retries < DS2482_WAIT_IDLE_TIMEOUT)); |
215 | } | 215 | } |
216 | 216 | ||
217 | if (retries > DS2482_WAIT_IDLE_TIMEOUT) | 217 | if (retries >= DS2482_WAIT_IDLE_TIMEOUT) |
218 | printk(KERN_ERR "%s: timeout on channel %d\n", | 218 | printk(KERN_ERR "%s: timeout on channel %d\n", |
219 | __func__, pdev->channel); | 219 | __func__, pdev->channel); |
220 | 220 | ||
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 65244c02551b..492670358cbf 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c | |||
@@ -102,7 +102,7 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) | |||
102 | return ((__raw_readb(ctrl_addr)) >> 3) & 0x1; | 102 | return ((__raw_readb(ctrl_addr)) >> 3) & 0x1; |
103 | } | 103 | } |
104 | 104 | ||
105 | static int __init mxc_w1_probe(struct platform_device *pdev) | 105 | static int __devinit mxc_w1_probe(struct platform_device *pdev) |
106 | { | 106 | { |
107 | struct mxc_w1_device *mdev; | 107 | struct mxc_w1_device *mdev; |
108 | struct resource *res; | 108 | struct resource *res; |
@@ -166,7 +166,7 @@ failed_clk: | |||
166 | /* | 166 | /* |
167 | * disassociate the w1 device from the driver | 167 | * disassociate the w1 device from the driver |
168 | */ | 168 | */ |
169 | static int mxc_w1_remove(struct platform_device *pdev) | 169 | static int __devexit mxc_w1_remove(struct platform_device *pdev) |
170 | { | 170 | { |
171 | struct mxc_w1_device *mdev = platform_get_drvdata(pdev); | 171 | struct mxc_w1_device *mdev = platform_get_drvdata(pdev); |
172 | struct resource *res; | 172 | struct resource *res; |
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 0d92969404c3..22977d30f89e 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c | |||
@@ -72,7 +72,7 @@ struct hdq_data { | |||
72 | int init_trans; | 72 | int init_trans; |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static int __init omap_hdq_probe(struct platform_device *pdev); | 75 | static int __devinit omap_hdq_probe(struct platform_device *pdev); |
76 | static int omap_hdq_remove(struct platform_device *pdev); | 76 | static int omap_hdq_remove(struct platform_device *pdev); |
77 | 77 | ||
78 | static struct platform_driver omap_hdq_driver = { | 78 | static struct platform_driver omap_hdq_driver = { |
@@ -558,7 +558,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) | |||
558 | return; | 558 | return; |
559 | } | 559 | } |
560 | 560 | ||
561 | static int __init omap_hdq_probe(struct platform_device *pdev) | 561 | static int __devinit omap_hdq_probe(struct platform_device *pdev) |
562 | { | 562 | { |
563 | struct hdq_data *hdq_data; | 563 | struct hdq_data *hdq_data; |
564 | struct resource *res; | 564 | struct resource *res; |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 3da3f48720a7..bdcdbd53da89 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -55,6 +55,11 @@ config SOFT_WATCHDOG | |||
55 | To compile this driver as a module, choose M here: the | 55 | To compile this driver as a module, choose M here: the |
56 | module will be called softdog. | 56 | module will be called softdog. |
57 | 57 | ||
58 | config MAX63XX_WATCHDOG | ||
59 | tristate "Max63xx watchdog" | ||
60 | help | ||
61 | Support for memory mapped max63{69,70,71,72,73,74} watchdog timer. | ||
62 | |||
58 | config WM831X_WATCHDOG | 63 | config WM831X_WATCHDOG |
59 | tristate "WM831x watchdog" | 64 | tristate "WM831x watchdog" |
60 | depends on MFD_WM831X | 65 | depends on MFD_WM831X |
@@ -289,6 +294,17 @@ config ADX_WATCHDOG | |||
289 | Say Y here if you want support for the watchdog timer on Avionic | 294 | Say Y here if you want support for the watchdog timer on Avionic |
290 | Design Xanthos boards. | 295 | Design Xanthos boards. |
291 | 296 | ||
297 | config TS72XX_WATCHDOG | ||
298 | tristate "TS-72XX SBC Watchdog" | ||
299 | depends on MACH_TS72XX | ||
300 | help | ||
301 | Technologic Systems TS-7200, TS-7250 and TS-7260 boards have | ||
302 | watchdog timer implemented in a external CPLD chip. Say Y here | ||
303 | if you want to support for the watchdog timer on TS-72XX boards. | ||
304 | |||
305 | To compile this driver as a module, choose M here: the | ||
306 | module will be called ts72xx_wdt. | ||
307 | |||
292 | # AVR32 Architecture | 308 | # AVR32 Architecture |
293 | 309 | ||
294 | config AT32AP700X_WDT | 310 | config AT32AP700X_WDT |
@@ -845,10 +861,10 @@ config TXX9_WDT | |||
845 | # POWERPC Architecture | 861 | # POWERPC Architecture |
846 | 862 | ||
847 | config GEF_WDT | 863 | config GEF_WDT |
848 | tristate "GE Fanuc Watchdog Timer" | 864 | tristate "GE Watchdog Timer" |
849 | depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A | 865 | depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A |
850 | ---help--- | 866 | ---help--- |
851 | Watchdog timer found in a number of GE Fanuc single board computers. | 867 | Watchdog timer found in a number of GE single board computers. |
852 | 868 | ||
853 | config MPC5200_WDT | 869 | config MPC5200_WDT |
854 | bool "MPC52xx Watchdog Timer" | 870 | bool "MPC52xx Watchdog Timer" |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 475c61100069..5e3cb95bb0e9 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -46,6 +46,7 @@ obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o | |||
46 | obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o | 46 | obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o |
47 | obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o | 47 | obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o |
48 | obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o | 48 | obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o |
49 | obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o | ||
49 | 50 | ||
50 | # AVR32 Architecture | 51 | # AVR32 Architecture |
51 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o | 52 | obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o |
@@ -142,4 +143,5 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o | |||
142 | # Architecture Independant | 143 | # Architecture Independant |
143 | obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o | 144 | obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o |
144 | obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o | 145 | obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o |
146 | obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o | ||
145 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o | 147 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o |
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 4d18c874d963..2ffce4d75443 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c | |||
@@ -150,7 +150,7 @@ static long acq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
150 | int options, retval = -EINVAL; | 150 | int options, retval = -EINVAL; |
151 | void __user *argp = (void __user *)arg; | 151 | void __user *argp = (void __user *)arg; |
152 | int __user *p = argp; | 152 | int __user *p = argp; |
153 | static struct watchdog_info ident = { | 153 | static const struct watchdog_info ident = { |
154 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | 154 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, |
155 | .firmware_version = 1, | 155 | .firmware_version = 1, |
156 | .identity = WATCHDOG_NAME, | 156 | .identity = WATCHDOG_NAME, |
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index 824d076a5cd6..4d40965d2c9f 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c | |||
@@ -137,7 +137,7 @@ static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
137 | int new_timeout; | 137 | int new_timeout; |
138 | void __user *argp = (void __user *)arg; | 138 | void __user *argp = (void __user *)arg; |
139 | int __user *p = argp; | 139 | int __user *p = argp; |
140 | static struct watchdog_info ident = { | 140 | static const struct watchdog_info ident = { |
141 | .options = WDIOF_KEEPALIVEPING | | 141 | .options = WDIOF_KEEPALIVEPING | |
142 | WDIOF_SETTIMEOUT | | 142 | WDIOF_SETTIMEOUT | |
143 | WDIOF_MAGICCLOSE, | 143 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c index 9d7d155364f8..a5ca7a6ee133 100644 --- a/drivers/watchdog/adx_wdt.c +++ b/drivers/watchdog/adx_wdt.c | |||
@@ -37,7 +37,7 @@ struct adx_wdt { | |||
37 | spinlock_t lock; | 37 | spinlock_t lock; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static struct watchdog_info adx_wdt_info = { | 40 | static const struct watchdog_info adx_wdt_info = { |
41 | .identity = "Avionic Design Xanthos Watchdog", | 41 | .identity = "Avionic Design Xanthos Watchdog", |
42 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 42 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
43 | }; | 43 | }; |
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index 937a80fb61e1..1e9caea8ff8a 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c | |||
@@ -180,7 +180,7 @@ static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
180 | { | 180 | { |
181 | void __user *argp = (void __user *)arg; | 181 | void __user *argp = (void __user *)arg; |
182 | int __user *p = argp; | 182 | int __user *p = argp; |
183 | static struct watchdog_info ident = { | 183 | static const struct watchdog_info ident = { |
184 | .options = WDIOF_KEEPALIVEPING | | 184 | .options = WDIOF_KEEPALIVEPING | |
185 | WDIOF_SETTIMEOUT | | 185 | WDIOF_SETTIMEOUT | |
186 | WDIOF_MAGICCLOSE, | 186 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index f90afdb1b255..d8d4da9a483d 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c | |||
@@ -238,7 +238,7 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
238 | { | 238 | { |
239 | void __user *argp = (void __user *)arg; | 239 | void __user *argp = (void __user *)arg; |
240 | int __user *p = argp; | 240 | int __user *p = argp; |
241 | static struct watchdog_info ident = { | 241 | static const struct watchdog_info ident = { |
242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | 242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
243 | | WDIOF_MAGICCLOSE, | 243 | | WDIOF_MAGICCLOSE, |
244 | .firmware_version = 1, | 244 | .firmware_version = 1, |
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 2bb95cd308c1..c764c52412e4 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c | |||
@@ -219,7 +219,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data, | |||
219 | static long ar7_wdt_ioctl(struct file *file, | 219 | static long ar7_wdt_ioctl(struct file *file, |
220 | unsigned int cmd, unsigned long arg) | 220 | unsigned int cmd, unsigned long arg) |
221 | { | 221 | { |
222 | static struct watchdog_info ident = { | 222 | static const struct watchdog_info ident = { |
223 | .identity = LONGNAME, | 223 | .identity = LONGNAME, |
224 | .firmware_version = 1, | 224 | .firmware_version = 1, |
225 | .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | | 225 | .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | |
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 037847923dcb..6873376f986c 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c | |||
@@ -202,7 +202,7 @@ static int at32_wdt_get_status(void) | |||
202 | return status; | 202 | return status; |
203 | } | 203 | } |
204 | 204 | ||
205 | static struct watchdog_info at32_wdt_info = { | 205 | static const struct watchdog_info at32_wdt_info = { |
206 | .identity = "at32ap700x watchdog", | 206 | .identity = "at32ap700x watchdog", |
207 | .options = WDIOF_SETTIMEOUT | | 207 | .options = WDIOF_SETTIMEOUT | |
208 | WDIOF_KEEPALIVEPING | | 208 | WDIOF_KEEPALIVEPING | |
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index b185dafe1494..b3046dc4b56c 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c | |||
@@ -121,7 +121,7 @@ static int at91_wdt_settimeout(int new_time) | |||
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | 123 | ||
124 | static struct watchdog_info at91_wdt_info = { | 124 | static const struct watchdog_info at91_wdt_info = { |
125 | .identity = "at91 watchdog", | 125 | .identity = "at91 watchdog", |
126 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 126 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
127 | }; | 127 | }; |
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 751c003864ad..5f245522397b 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c | |||
@@ -149,7 +149,7 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data, | |||
149 | return len; | 149 | return len; |
150 | } | 150 | } |
151 | 151 | ||
152 | static struct watchdog_info bcm47xx_wdt_info = { | 152 | static const struct watchdog_info bcm47xx_wdt_info = { |
153 | .identity = DRV_NAME, | 153 | .identity = DRV_NAME, |
154 | .options = WDIOF_SETTIMEOUT | | 154 | .options = WDIOF_SETTIMEOUT | |
155 | WDIOF_KEEPALIVEPING | | 155 | WDIOF_KEEPALIVEPING | |
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 2159e668751c..9c7ccd1e9088 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c | |||
@@ -19,8 +19,6 @@ | |||
19 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
20 | #include <linux/watchdog.h> | 20 | #include <linux/watchdog.h> |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/notifier.h> | ||
23 | #include <linux/reboot.h> | ||
24 | #include <linux/init.h> | 22 | #include <linux/init.h> |
25 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
26 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
@@ -74,7 +72,7 @@ | |||
74 | 72 | ||
75 | static unsigned int timeout = WATCHDOG_TIMEOUT; | 73 | static unsigned int timeout = WATCHDOG_TIMEOUT; |
76 | static int nowayout = WATCHDOG_NOWAYOUT; | 74 | static int nowayout = WATCHDOG_NOWAYOUT; |
77 | static struct watchdog_info bfin_wdt_info; | 75 | static const struct watchdog_info bfin_wdt_info; |
78 | static unsigned long open_check; | 76 | static unsigned long open_check; |
79 | static char expect_close; | 77 | static char expect_close; |
80 | static DEFINE_SPINLOCK(bfin_wdt_spinlock); | 78 | static DEFINE_SPINLOCK(bfin_wdt_spinlock); |
@@ -309,26 +307,6 @@ static long bfin_wdt_ioctl(struct file *file, | |||
309 | } | 307 | } |
310 | } | 308 | } |
311 | 309 | ||
312 | /** | ||
313 | * bfin_wdt_notify_sys - Notifier Handler | ||
314 | * @this: notifier block | ||
315 | * @code: notifier event | ||
316 | * @unused: unused | ||
317 | * | ||
318 | * Handles specific events, such as turning off the watchdog during a | ||
319 | * shutdown event. | ||
320 | */ | ||
321 | static int bfin_wdt_notify_sys(struct notifier_block *this, | ||
322 | unsigned long code, void *unused) | ||
323 | { | ||
324 | stampit(); | ||
325 | |||
326 | if (code == SYS_DOWN || code == SYS_HALT) | ||
327 | bfin_wdt_stop(); | ||
328 | |||
329 | return NOTIFY_DONE; | ||
330 | } | ||
331 | |||
332 | #ifdef CONFIG_PM | 310 | #ifdef CONFIG_PM |
333 | static int state_before_suspend; | 311 | static int state_before_suspend; |
334 | 312 | ||
@@ -388,40 +366,28 @@ static struct miscdevice bfin_wdt_miscdev = { | |||
388 | .fops = &bfin_wdt_fops, | 366 | .fops = &bfin_wdt_fops, |
389 | }; | 367 | }; |
390 | 368 | ||
391 | static struct watchdog_info bfin_wdt_info = { | 369 | static const struct watchdog_info bfin_wdt_info = { |
392 | .identity = "Blackfin Watchdog", | 370 | .identity = "Blackfin Watchdog", |
393 | .options = WDIOF_SETTIMEOUT | | 371 | .options = WDIOF_SETTIMEOUT | |
394 | WDIOF_KEEPALIVEPING | | 372 | WDIOF_KEEPALIVEPING | |
395 | WDIOF_MAGICCLOSE, | 373 | WDIOF_MAGICCLOSE, |
396 | }; | 374 | }; |
397 | 375 | ||
398 | static struct notifier_block bfin_wdt_notifier = { | ||
399 | .notifier_call = bfin_wdt_notify_sys, | ||
400 | }; | ||
401 | |||
402 | /** | 376 | /** |
403 | * bfin_wdt_probe - Initialize module | 377 | * bfin_wdt_probe - Initialize module |
404 | * | 378 | * |
405 | * Registers the misc device and notifier handler. Actual device | 379 | * Registers the misc device. Actual device |
406 | * initialization is handled by bfin_wdt_open(). | 380 | * initialization is handled by bfin_wdt_open(). |
407 | */ | 381 | */ |
408 | static int __devinit bfin_wdt_probe(struct platform_device *pdev) | 382 | static int __devinit bfin_wdt_probe(struct platform_device *pdev) |
409 | { | 383 | { |
410 | int ret; | 384 | int ret; |
411 | 385 | ||
412 | ret = register_reboot_notifier(&bfin_wdt_notifier); | ||
413 | if (ret) { | ||
414 | pr_devinit(KERN_ERR PFX | ||
415 | "cannot register reboot notifier (err=%d)\n", ret); | ||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | ret = misc_register(&bfin_wdt_miscdev); | 386 | ret = misc_register(&bfin_wdt_miscdev); |
420 | if (ret) { | 387 | if (ret) { |
421 | pr_devinit(KERN_ERR PFX | 388 | pr_devinit(KERN_ERR PFX |
422 | "cannot register miscdev on minor=%d (err=%d)\n", | 389 | "cannot register miscdev on minor=%d (err=%d)\n", |
423 | WATCHDOG_MINOR, ret); | 390 | WATCHDOG_MINOR, ret); |
424 | unregister_reboot_notifier(&bfin_wdt_notifier); | ||
425 | return ret; | 391 | return ret; |
426 | } | 392 | } |
427 | 393 | ||
@@ -434,21 +400,33 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev) | |||
434 | /** | 400 | /** |
435 | * bfin_wdt_remove - Initialize module | 401 | * bfin_wdt_remove - Initialize module |
436 | * | 402 | * |
437 | * Unregisters the misc device and notifier handler. Actual device | 403 | * Unregisters the misc device. Actual device |
438 | * deinitialization is handled by bfin_wdt_close(). | 404 | * deinitialization is handled by bfin_wdt_close(). |
439 | */ | 405 | */ |
440 | static int __devexit bfin_wdt_remove(struct platform_device *pdev) | 406 | static int __devexit bfin_wdt_remove(struct platform_device *pdev) |
441 | { | 407 | { |
442 | misc_deregister(&bfin_wdt_miscdev); | 408 | misc_deregister(&bfin_wdt_miscdev); |
443 | unregister_reboot_notifier(&bfin_wdt_notifier); | ||
444 | return 0; | 409 | return 0; |
445 | } | 410 | } |
446 | 411 | ||
412 | /** | ||
413 | * bfin_wdt_shutdown - Soft Shutdown Handler | ||
414 | * | ||
415 | * Handles the soft shutdown event. | ||
416 | */ | ||
417 | static void bfin_wdt_shutdown(struct platform_device *pdev) | ||
418 | { | ||
419 | stampit(); | ||
420 | |||
421 | bfin_wdt_stop(); | ||
422 | } | ||
423 | |||
447 | static struct platform_device *bfin_wdt_device; | 424 | static struct platform_device *bfin_wdt_device; |
448 | 425 | ||
449 | static struct platform_driver bfin_wdt_driver = { | 426 | static struct platform_driver bfin_wdt_driver = { |
450 | .probe = bfin_wdt_probe, | 427 | .probe = bfin_wdt_probe, |
451 | .remove = __devexit_p(bfin_wdt_remove), | 428 | .remove = __devexit_p(bfin_wdt_remove), |
429 | .shutdown = bfin_wdt_shutdown, | ||
452 | .suspend = bfin_wdt_suspend, | 430 | .suspend = bfin_wdt_suspend, |
453 | .resume = bfin_wdt_resume, | 431 | .resume = bfin_wdt_resume, |
454 | .driver = { | 432 | .driver = { |
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index e8380ef65c1c..8b724aad6825 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c | |||
@@ -121,7 +121,7 @@ static ssize_t booke_wdt_write(struct file *file, const char __user *buf, | |||
121 | return count; | 121 | return count; |
122 | } | 122 | } |
123 | 123 | ||
124 | static struct watchdog_info ident = { | 124 | static const struct watchdog_info ident = { |
125 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 125 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
126 | .identity = "PowerPC Book-E Watchdog", | 126 | .identity = "PowerPC Book-E Watchdog", |
127 | }; | 127 | }; |
diff --git a/drivers/watchdog/coh901327_wdt.c b/drivers/watchdog/coh901327_wdt.c index 923cc68dba26..9291506b8b23 100644 --- a/drivers/watchdog/coh901327_wdt.c +++ b/drivers/watchdog/coh901327_wdt.c | |||
@@ -257,7 +257,7 @@ static long coh901327_ioctl(struct file *file, unsigned int cmd, | |||
257 | struct watchdog_info __user *ident; | 257 | struct watchdog_info __user *ident; |
258 | int __user *i; | 258 | int __user *i; |
259 | } uarg; | 259 | } uarg; |
260 | static struct watchdog_info ident = { | 260 | static const struct watchdog_info ident = { |
261 | .options = WDIOF_CARDRESET | | 261 | .options = WDIOF_CARDRESET | |
262 | WDIOF_SETTIMEOUT | | 262 | WDIOF_SETTIMEOUT | |
263 | WDIOF_KEEPALIVEPING, | 263 | WDIOF_KEEPALIVEPING, |
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c index 71f6d7eec9a8..edd3475f41db 100644 --- a/drivers/watchdog/cpu5wdt.c +++ b/drivers/watchdog/cpu5wdt.c | |||
@@ -154,7 +154,7 @@ static long cpu5wdt_ioctl(struct file *file, unsigned int cmd, | |||
154 | void __user *argp = (void __user *)arg; | 154 | void __user *argp = (void __user *)arg; |
155 | int __user *p = argp; | 155 | int __user *p = argp; |
156 | unsigned int value; | 156 | unsigned int value; |
157 | static struct watchdog_info ident = { | 157 | static const struct watchdog_info ident = { |
158 | .options = WDIOF_CARDRESET, | 158 | .options = WDIOF_CARDRESET, |
159 | .identity = "CPU5 WDT", | 159 | .identity = "CPU5 WDT", |
160 | }; | 160 | }; |
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 081f2955419e..37ea052d4dee 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c | |||
@@ -403,7 +403,7 @@ static int cpwd_release(struct inode *inode, struct file *file) | |||
403 | 403 | ||
404 | static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 404 | static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
405 | { | 405 | { |
406 | static struct watchdog_info info = { | 406 | static const struct watchdog_info info = { |
407 | .options = WDIOF_SETTIMEOUT, | 407 | .options = WDIOF_SETTIMEOUT, |
408 | .firmware_version = 1, | 408 | .firmware_version = 1, |
409 | .identity = DRIVER_NAME, | 409 | .identity = DRIVER_NAME, |
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 887136de1857..56162c87f5d8 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c | |||
@@ -142,7 +142,7 @@ davinci_wdt_write(struct file *file, const char *data, size_t len, | |||
142 | return len; | 142 | return len; |
143 | } | 143 | } |
144 | 144 | ||
145 | static struct watchdog_info ident = { | 145 | static const struct watchdog_info ident = { |
146 | .options = WDIOF_KEEPALIVEPING, | 146 | .options = WDIOF_KEEPALIVEPING, |
147 | .identity = "DaVinci Watchdog", | 147 | .identity = "DaVinci Watchdog", |
148 | }; | 148 | }; |
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index cdd55e0d09f8..88ed54e50f74 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c | |||
@@ -131,7 +131,7 @@ ep93xx_wdt_write(struct file *file, const char __user *data, size_t len, | |||
131 | return len; | 131 | return len; |
132 | } | 132 | } |
133 | 133 | ||
134 | static struct watchdog_info ident = { | 134 | static const struct watchdog_info ident = { |
135 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE, | 135 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE, |
136 | .identity = "EP93xx Watchdog", | 136 | .identity = "EP93xx Watchdog", |
137 | }; | 137 | }; |
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 9add3541fb42..d1c4e55b1db0 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c | |||
@@ -238,7 +238,7 @@ static long eurwdt_ioctl(struct file *file, | |||
238 | { | 238 | { |
239 | void __user *argp = (void __user *)arg; | 239 | void __user *argp = (void __user *)arg; |
240 | int __user *p = argp; | 240 | int __user *p = argp; |
241 | static struct watchdog_info ident = { | 241 | static const struct watchdog_info ident = { |
242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | 242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
243 | | WDIOF_MAGICCLOSE, | 243 | | WDIOF_MAGICCLOSE, |
244 | .firmware_version = 1, | 244 | .firmware_version = 1, |
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 734d9806a872..abdbad034a6c 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * GE Fanuc watchdog userspace interface | 2 | * GE watchdog userspace interface |
3 | * | 3 | * |
4 | * Author: Martyn Welch <martyn.welch@gefanuc.com> | 4 | * Author: Martyn Welch <martyn.welch@ge.com> |
5 | * | 5 | * |
6 | * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. | 6 | * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
@@ -161,11 +161,11 @@ static long gef_wdt_ioctl(struct file *file, unsigned int cmd, | |||
161 | int timeout; | 161 | int timeout; |
162 | int options; | 162 | int options; |
163 | void __user *argp = (void __user *)arg; | 163 | void __user *argp = (void __user *)arg; |
164 | static struct watchdog_info info = { | 164 | static const struct watchdog_info info = { |
165 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | | 165 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | |
166 | WDIOF_KEEPALIVEPING, | 166 | WDIOF_KEEPALIVEPING, |
167 | .firmware_version = 0, | 167 | .firmware_version = 0, |
168 | .identity = "GE Fanuc watchdog", | 168 | .identity = "GE watchdog", |
169 | }; | 169 | }; |
170 | 170 | ||
171 | switch (cmd) { | 171 | switch (cmd) { |
@@ -311,7 +311,7 @@ static struct of_platform_driver gef_wdt_driver = { | |||
311 | 311 | ||
312 | static int __init gef_wdt_init(void) | 312 | static int __init gef_wdt_init(void) |
313 | { | 313 | { |
314 | printk(KERN_INFO "GE Fanuc watchdog driver\n"); | 314 | printk(KERN_INFO "GE watchdog driver\n"); |
315 | return of_register_platform_driver(&gef_wdt_driver); | 315 | return of_register_platform_driver(&gef_wdt_driver); |
316 | } | 316 | } |
317 | 317 | ||
@@ -323,8 +323,8 @@ static void __exit gef_wdt_exit(void) | |||
323 | module_init(gef_wdt_init); | 323 | module_init(gef_wdt_init); |
324 | module_exit(gef_wdt_exit); | 324 | module_exit(gef_wdt_exit); |
325 | 325 | ||
326 | MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>"); | 326 | MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>"); |
327 | MODULE_DESCRIPTION("GE Fanuc watchdog driver"); | 327 | MODULE_DESCRIPTION("GE watchdog driver"); |
328 | MODULE_LICENSE("GPL"); | 328 | MODULE_LICENSE("GPL"); |
329 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 329 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
330 | MODULE_ALIAS("platform: gef_wdt"); | 330 | MODULE_ALIAS("platform: gef_wdt"); |
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 38252ff828ca..9b49b125ad5a 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c | |||
@@ -142,7 +142,7 @@ static long geodewdt_ioctl(struct file *file, unsigned int cmd, | |||
142 | int __user *p = argp; | 142 | int __user *p = argp; |
143 | int interval; | 143 | int interval; |
144 | 144 | ||
145 | static struct watchdog_info ident = { | 145 | static const struct watchdog_info ident = { |
146 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | 146 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
147 | | WDIOF_MAGICCLOSE, | 147 | | WDIOF_MAGICCLOSE, |
148 | .firmware_version = 1, | 148 | .firmware_version = 1, |
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index a6c5674c78e6..70c2c24660d0 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -554,7 +554,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data, | |||
554 | return len; | 554 | return len; |
555 | } | 555 | } |
556 | 556 | ||
557 | static struct watchdog_info ident = { | 557 | static const struct watchdog_info ident = { |
558 | .options = WDIOF_SETTIMEOUT | | 558 | .options = WDIOF_SETTIMEOUT | |
559 | WDIOF_KEEPALIVEPING | | 559 | WDIOF_KEEPALIVEPING | |
560 | WDIOF_MAGICCLOSE, | 560 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 7ba0b11ec525..bb9750a03942 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
35 | #include <linux/miscdevice.h> | 35 | #include <linux/miscdevice.h> |
36 | #include <linux/watchdog.h> | 36 | #include <linux/watchdog.h> |
37 | #include <linux/platform_device.h> | ||
38 | #include <linux/init.h> | 37 | #include <linux/init.h> |
39 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
40 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
@@ -42,7 +41,7 @@ | |||
42 | #include <linux/io.h> | 41 | #include <linux/io.h> |
43 | 42 | ||
44 | /* Module and version information */ | 43 | /* Module and version information */ |
45 | #define ESB_VERSION "0.04" | 44 | #define ESB_VERSION "0.05" |
46 | #define ESB_MODULE_NAME "i6300ESB timer" | 45 | #define ESB_MODULE_NAME "i6300ESB timer" |
47 | #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION | 46 | #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION |
48 | #define PFX ESB_MODULE_NAME ": " | 47 | #define PFX ESB_MODULE_NAME ": " |
@@ -65,7 +64,7 @@ | |||
65 | /* Config register bits */ | 64 | /* Config register bits */ |
66 | #define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ | 65 | #define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ |
67 | #define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */ | 66 | #define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */ |
68 | #define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ | 67 | #define ESB_WDT_INTTYPE (0x03 << 0) /* Interrupt type on timer1 timeout */ |
69 | 68 | ||
70 | /* Reload register bits */ | 69 | /* Reload register bits */ |
71 | #define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */ | 70 | #define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */ |
@@ -82,7 +81,9 @@ static unsigned long timer_alive; | |||
82 | static struct pci_dev *esb_pci; | 81 | static struct pci_dev *esb_pci; |
83 | static unsigned short triggered; /* The status of the watchdog upon boot */ | 82 | static unsigned short triggered; /* The status of the watchdog upon boot */ |
84 | static char esb_expect_close; | 83 | static char esb_expect_close; |
85 | static struct platform_device *esb_platform_device; | 84 | |
85 | /* We can only use 1 card due to the /dev/watchdog restriction */ | ||
86 | static int cards_found; | ||
86 | 87 | ||
87 | /* module parameters */ | 88 | /* module parameters */ |
88 | /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ | 89 | /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ |
@@ -111,8 +112,8 @@ MODULE_PARM_DESC(nowayout, | |||
111 | */ | 112 | */ |
112 | static inline void esb_unlock_registers(void) | 113 | static inline void esb_unlock_registers(void) |
113 | { | 114 | { |
114 | writeb(ESB_UNLOCK1, ESB_RELOAD_REG); | 115 | writew(ESB_UNLOCK1, ESB_RELOAD_REG); |
115 | writeb(ESB_UNLOCK2, ESB_RELOAD_REG); | 116 | writew(ESB_UNLOCK2, ESB_RELOAD_REG); |
116 | } | 117 | } |
117 | 118 | ||
118 | static int esb_timer_start(void) | 119 | static int esb_timer_start(void) |
@@ -256,7 +257,7 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
256 | int new_heartbeat; | 257 | int new_heartbeat; |
257 | void __user *argp = (void __user *)arg; | 258 | void __user *argp = (void __user *)arg; |
258 | int __user *p = argp; | 259 | int __user *p = argp; |
259 | static struct watchdog_info ident = { | 260 | static const struct watchdog_info ident = { |
260 | .options = WDIOF_SETTIMEOUT | | 261 | .options = WDIOF_SETTIMEOUT | |
261 | WDIOF_KEEPALIVEPING | | 262 | WDIOF_KEEPALIVEPING | |
262 | WDIOF_MAGICCLOSE, | 263 | WDIOF_MAGICCLOSE, |
@@ -332,11 +333,6 @@ static struct miscdevice esb_miscdev = { | |||
332 | 333 | ||
333 | /* | 334 | /* |
334 | * Data for PCI driver interface | 335 | * Data for PCI driver interface |
335 | * | ||
336 | * This data only exists for exporting the supported | ||
337 | * PCI ids via MODULE_DEVICE_TABLE. We do not actually | ||
338 | * register a pci_driver, because someone else might one day | ||
339 | * want to register another driver on the same PCI id. | ||
340 | */ | 336 | */ |
341 | static struct pci_device_id esb_pci_tbl[] = { | 337 | static struct pci_device_id esb_pci_tbl[] = { |
342 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, | 338 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, |
@@ -348,29 +344,19 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl); | |||
348 | * Init & exit routines | 344 | * Init & exit routines |
349 | */ | 345 | */ |
350 | 346 | ||
351 | static unsigned char __devinit esb_getdevice(void) | 347 | static unsigned char __devinit esb_getdevice(struct pci_dev *pdev) |
352 | { | 348 | { |
353 | /* | 349 | if (pci_enable_device(pdev)) { |
354 | * Find the PCI device | ||
355 | */ | ||
356 | |||
357 | esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
358 | PCI_DEVICE_ID_INTEL_ESB_9, NULL); | ||
359 | |||
360 | if (!esb_pci) | ||
361 | return 0; | ||
362 | |||
363 | if (pci_enable_device(esb_pci)) { | ||
364 | printk(KERN_ERR PFX "failed to enable device\n"); | 350 | printk(KERN_ERR PFX "failed to enable device\n"); |
365 | goto err_devput; | 351 | goto err_devput; |
366 | } | 352 | } |
367 | 353 | ||
368 | if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { | 354 | if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) { |
369 | printk(KERN_ERR PFX "failed to request region\n"); | 355 | printk(KERN_ERR PFX "failed to request region\n"); |
370 | goto err_disable; | 356 | goto err_disable; |
371 | } | 357 | } |
372 | 358 | ||
373 | BASEADDR = pci_ioremap_bar(esb_pci, 0); | 359 | BASEADDR = pci_ioremap_bar(pdev, 0); |
374 | if (BASEADDR == NULL) { | 360 | if (BASEADDR == NULL) { |
375 | /* Something's wrong here, BASEADDR has to be set */ | 361 | /* Something's wrong here, BASEADDR has to be set */ |
376 | printk(KERN_ERR PFX "failed to get BASEADDR\n"); | 362 | printk(KERN_ERR PFX "failed to get BASEADDR\n"); |
@@ -378,14 +364,14 @@ static unsigned char __devinit esb_getdevice(void) | |||
378 | } | 364 | } |
379 | 365 | ||
380 | /* Done */ | 366 | /* Done */ |
367 | esb_pci = pdev; | ||
381 | return 1; | 368 | return 1; |
382 | 369 | ||
383 | err_release: | 370 | err_release: |
384 | pci_release_region(esb_pci, 0); | 371 | pci_release_region(pdev, 0); |
385 | err_disable: | 372 | err_disable: |
386 | pci_disable_device(esb_pci); | 373 | pci_disable_device(pdev); |
387 | err_devput: | 374 | err_devput: |
388 | pci_dev_put(esb_pci); | ||
389 | return 0; | 375 | return 0; |
390 | } | 376 | } |
391 | 377 | ||
@@ -430,12 +416,23 @@ static void __devinit esb_initdevice(void) | |||
430 | esb_timer_set_heartbeat(heartbeat); | 416 | esb_timer_set_heartbeat(heartbeat); |
431 | } | 417 | } |
432 | 418 | ||
433 | static int __devinit esb_probe(struct platform_device *dev) | 419 | static int __devinit esb_probe(struct pci_dev *pdev, |
420 | const struct pci_device_id *ent) | ||
434 | { | 421 | { |
435 | int ret; | 422 | int ret; |
436 | 423 | ||
424 | cards_found++; | ||
425 | if (cards_found == 1) | ||
426 | printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n", | ||
427 | ESB_VERSION); | ||
428 | |||
429 | if (cards_found > 1) { | ||
430 | printk(KERN_ERR PFX "This driver only supports 1 device\n"); | ||
431 | return -ENODEV; | ||
432 | } | ||
433 | |||
437 | /* Check whether or not the hardware watchdog is there */ | 434 | /* Check whether or not the hardware watchdog is there */ |
438 | if (!esb_getdevice() || esb_pci == NULL) | 435 | if (!esb_getdevice(pdev) || esb_pci == NULL) |
439 | return -ENODEV; | 436 | return -ENODEV; |
440 | 437 | ||
441 | /* Check that the heartbeat value is within it's range; | 438 | /* Check that the heartbeat value is within it's range; |
@@ -467,11 +464,11 @@ err_unmap: | |||
467 | iounmap(BASEADDR); | 464 | iounmap(BASEADDR); |
468 | pci_release_region(esb_pci, 0); | 465 | pci_release_region(esb_pci, 0); |
469 | pci_disable_device(esb_pci); | 466 | pci_disable_device(esb_pci); |
470 | pci_dev_put(esb_pci); | 467 | esb_pci = NULL; |
471 | return ret; | 468 | return ret; |
472 | } | 469 | } |
473 | 470 | ||
474 | static int __devexit esb_remove(struct platform_device *dev) | 471 | static void __devexit esb_remove(struct pci_dev *pdev) |
475 | { | 472 | { |
476 | /* Stop the timer before we leave */ | 473 | /* Stop the timer before we leave */ |
477 | if (!nowayout) | 474 | if (!nowayout) |
@@ -482,54 +479,30 @@ static int __devexit esb_remove(struct platform_device *dev) | |||
482 | iounmap(BASEADDR); | 479 | iounmap(BASEADDR); |
483 | pci_release_region(esb_pci, 0); | 480 | pci_release_region(esb_pci, 0); |
484 | pci_disable_device(esb_pci); | 481 | pci_disable_device(esb_pci); |
485 | pci_dev_put(esb_pci); | 482 | esb_pci = NULL; |
486 | return 0; | ||
487 | } | 483 | } |
488 | 484 | ||
489 | static void esb_shutdown(struct platform_device *dev) | 485 | static void esb_shutdown(struct pci_dev *pdev) |
490 | { | 486 | { |
491 | esb_timer_stop(); | 487 | esb_timer_stop(); |
492 | } | 488 | } |
493 | 489 | ||
494 | static struct platform_driver esb_platform_driver = { | 490 | static struct pci_driver esb_driver = { |
491 | .name = ESB_MODULE_NAME, | ||
492 | .id_table = esb_pci_tbl, | ||
495 | .probe = esb_probe, | 493 | .probe = esb_probe, |
496 | .remove = __devexit_p(esb_remove), | 494 | .remove = __devexit_p(esb_remove), |
497 | .shutdown = esb_shutdown, | 495 | .shutdown = esb_shutdown, |
498 | .driver = { | ||
499 | .owner = THIS_MODULE, | ||
500 | .name = ESB_MODULE_NAME, | ||
501 | }, | ||
502 | }; | 496 | }; |
503 | 497 | ||
504 | static int __init watchdog_init(void) | 498 | static int __init watchdog_init(void) |
505 | { | 499 | { |
506 | int err; | 500 | return pci_register_driver(&esb_driver); |
507 | |||
508 | printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n", | ||
509 | ESB_VERSION); | ||
510 | |||
511 | err = platform_driver_register(&esb_platform_driver); | ||
512 | if (err) | ||
513 | return err; | ||
514 | |||
515 | esb_platform_device = platform_device_register_simple(ESB_MODULE_NAME, | ||
516 | -1, NULL, 0); | ||
517 | if (IS_ERR(esb_platform_device)) { | ||
518 | err = PTR_ERR(esb_platform_device); | ||
519 | goto unreg_platform_driver; | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | |||
524 | unreg_platform_driver: | ||
525 | platform_driver_unregister(&esb_platform_driver); | ||
526 | return err; | ||
527 | } | 501 | } |
528 | 502 | ||
529 | static void __exit watchdog_cleanup(void) | 503 | static void __exit watchdog_cleanup(void) |
530 | { | 504 | { |
531 | platform_device_unregister(esb_platform_device); | 505 | pci_unregister_driver(&esb_driver); |
532 | platform_driver_unregister(&esb_platform_driver); | ||
533 | printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); | 506 | printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); |
534 | } | 507 | } |
535 | 508 | ||
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 4bdb7f1a9077..44bc6aa46edf 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -584,7 +584,7 @@ static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd, | |||
584 | int new_heartbeat; | 584 | int new_heartbeat; |
585 | void __user *argp = (void __user *)arg; | 585 | void __user *argp = (void __user *)arg; |
586 | int __user *p = argp; | 586 | int __user *p = argp; |
587 | static struct watchdog_info ident = { | 587 | static const struct watchdog_info ident = { |
588 | .options = WDIOF_SETTIMEOUT | | 588 | .options = WDIOF_SETTIMEOUT | |
589 | WDIOF_KEEPALIVEPING | | 589 | WDIOF_KEEPALIVEPING | |
590 | WDIOF_MAGICCLOSE, | 590 | WDIOF_MAGICCLOSE, |
@@ -698,7 +698,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
698 | if (iTCO_wdt_private.iTCO_version == 2) { | 698 | if (iTCO_wdt_private.iTCO_version == 2) { |
699 | pci_read_config_dword(pdev, 0xf0, &base_address); | 699 | pci_read_config_dword(pdev, 0xf0, &base_address); |
700 | if ((base_address & 1) == 0) { | 700 | if ((base_address & 1) == 0) { |
701 | printk(KERN_ERR PFX "RCBA is disabled by harddware\n"); | 701 | printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); |
702 | ret = -ENODEV; | 702 | ret = -ENODEV; |
703 | goto out; | 703 | goto out; |
704 | } | 704 | } |
@@ -708,8 +708,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
708 | 708 | ||
709 | /* Check chipset's NO_REBOOT bit */ | 709 | /* Check chipset's NO_REBOOT bit */ |
710 | if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { | 710 | if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { |
711 | printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " | 711 | printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " |
712 | "reboot disabled by hardware\n"); | 712 | "platform may have disabled it\n"); |
713 | ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ | 713 | ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ |
714 | goto out_unmap; | 714 | goto out_unmap; |
715 | } | 715 | } |
@@ -805,6 +805,7 @@ static void __devexit iTCO_wdt_cleanup(void) | |||
805 | 805 | ||
806 | static int __devinit iTCO_wdt_probe(struct platform_device *dev) | 806 | static int __devinit iTCO_wdt_probe(struct platform_device *dev) |
807 | { | 807 | { |
808 | int ret = -ENODEV; | ||
808 | int found = 0; | 809 | int found = 0; |
809 | struct pci_dev *pdev = NULL; | 810 | struct pci_dev *pdev = NULL; |
810 | const struct pci_device_id *ent; | 811 | const struct pci_device_id *ent; |
@@ -814,19 +815,17 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev) | |||
814 | for_each_pci_dev(pdev) { | 815 | for_each_pci_dev(pdev) { |
815 | ent = pci_match_id(iTCO_wdt_pci_tbl, pdev); | 816 | ent = pci_match_id(iTCO_wdt_pci_tbl, pdev); |
816 | if (ent) { | 817 | if (ent) { |
817 | if (!(iTCO_wdt_init(pdev, ent, dev))) { | 818 | found++; |
818 | found++; | 819 | ret = iTCO_wdt_init(pdev, ent, dev); |
820 | if (!ret) | ||
819 | break; | 821 | break; |
820 | } | ||
821 | } | 822 | } |
822 | } | 823 | } |
823 | 824 | ||
824 | if (!found) { | 825 | if (!found) |
825 | printk(KERN_INFO PFX "No card detected\n"); | 826 | printk(KERN_INFO PFX "No card detected\n"); |
826 | return -ENODEV; | ||
827 | } | ||
828 | 827 | ||
829 | return 0; | 828 | return ret; |
830 | } | 829 | } |
831 | 830 | ||
832 | static int __devexit iTCO_wdt_remove(struct platform_device *dev) | 831 | static int __devexit iTCO_wdt_remove(struct platform_device *dev) |
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c index 4bef3ddff4a5..0149d8dfc81d 100644 --- a/drivers/watchdog/ib700wdt.c +++ b/drivers/watchdog/ib700wdt.c | |||
@@ -174,7 +174,7 @@ static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
174 | void __user *argp = (void __user *)arg; | 174 | void __user *argp = (void __user *)arg; |
175 | int __user *p = argp; | 175 | int __user *p = argp; |
176 | 176 | ||
177 | static struct watchdog_info ident = { | 177 | static const struct watchdog_info ident = { |
178 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | 178 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
179 | | WDIOF_MAGICCLOSE, | 179 | | WDIOF_MAGICCLOSE, |
180 | .firmware_version = 1, | 180 | .firmware_version = 1, |
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c index bea8a124a559..1cc5609666d1 100644 --- a/drivers/watchdog/indydog.c +++ b/drivers/watchdog/indydog.c | |||
@@ -111,7 +111,7 @@ static long indydog_ioctl(struct file *file, unsigned int cmd, | |||
111 | unsigned long arg) | 111 | unsigned long arg) |
112 | { | 112 | { |
113 | int options, retval = -EINVAL; | 113 | int options, retval = -EINVAL; |
114 | static struct watchdog_info ident = { | 114 | static const struct watchdog_info ident = { |
115 | .options = WDIOF_KEEPALIVEPING, | 115 | .options = WDIOF_KEEPALIVEPING, |
116 | .firmware_version = 0, | 116 | .firmware_version = 0, |
117 | .identity = "Hardware Watchdog for SGI IP22", | 117 | .identity = "Hardware Watchdog for SGI IP22", |
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index daed48ded7fe..f52c162b1bea 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c | |||
@@ -236,7 +236,7 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, | |||
236 | { | 236 | { |
237 | void __user *argp = (void __user *)arg; | 237 | void __user *argp = (void __user *)arg; |
238 | int __user *p = argp; | 238 | int __user *p = argp; |
239 | static struct watchdog_info ident = { | 239 | static const struct watchdog_info ident = { |
240 | .identity = "IT8712F Watchdog", | 240 | .identity = "IT8712F Watchdog", |
241 | .firmware_version = 1, | 241 | .firmware_version = 1, |
242 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | | 242 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | |
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index cc133c531d08..b709b3b2d1ef 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c | |||
@@ -421,7 +421,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, | |||
421 | return count; | 421 | return count; |
422 | } | 422 | } |
423 | 423 | ||
424 | static struct watchdog_info ident = { | 424 | static const struct watchdog_info ident = { |
425 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | 425 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, |
426 | .firmware_version = 1, | 426 | .firmware_version = 1, |
427 | .identity = WATCHDOG_NAME, | 427 | .identity = WATCHDOG_NAME, |
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c index 3c79dc587958..e86952a7168c 100644 --- a/drivers/watchdog/ixp2000_wdt.c +++ b/drivers/watchdog/ixp2000_wdt.c | |||
@@ -100,7 +100,7 @@ static ssize_t ixp2000_wdt_write(struct file *file, const char *data, | |||
100 | } | 100 | } |
101 | 101 | ||
102 | 102 | ||
103 | static struct watchdog_info ident = { | 103 | static const struct watchdog_info ident = { |
104 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | 104 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | |
105 | WDIOF_KEEPALIVEPING, | 105 | WDIOF_KEEPALIVEPING, |
106 | .identity = "IXP2000 Watchdog", | 106 | .identity = "IXP2000 Watchdog", |
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c index 147b4d5c63b3..e02c0ecda26b 100644 --- a/drivers/watchdog/ixp4xx_wdt.c +++ b/drivers/watchdog/ixp4xx_wdt.c | |||
@@ -89,7 +89,7 @@ ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | |||
89 | return len; | 89 | return len; |
90 | } | 90 | } |
91 | 91 | ||
92 | static struct watchdog_info ident = { | 92 | static const struct watchdog_info ident = { |
93 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | | 93 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | |
94 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 94 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
95 | .identity = "IXP4xx Watchdog", | 95 | .identity = "IXP4xx Watchdog", |
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index e1c82769b08e..2852bb2e3fd9 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c | |||
@@ -145,7 +145,7 @@ static int ks8695_wdt_close(struct inode *inode, struct file *file) | |||
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
147 | 147 | ||
148 | static struct watchdog_info ks8695_wdt_info = { | 148 | static const struct watchdog_info ks8695_wdt_info = { |
149 | .identity = "ks8695 watchdog", | 149 | .identity = "ks8695 watchdog", |
150 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 150 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
151 | }; | 151 | }; |
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 47d719717a3b..2d118cf022fc 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c | |||
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(nowayout, | |||
101 | 101 | ||
102 | #define PFX "machzwd" | 102 | #define PFX "machzwd" |
103 | 103 | ||
104 | static struct watchdog_info zf_info = { | 104 | static const struct watchdog_info zf_info = { |
105 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | 105 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, |
106 | .firmware_version = 1, | 106 | .firmware_version = 1, |
107 | .identity = "ZF-Logic watchdog", | 107 | .identity = "ZF-Logic watchdog", |
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c new file mode 100644 index 000000000000..6eb91d757604 --- /dev/null +++ b/drivers/watchdog/max63xx_wdt.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * drivers/char/watchdog/max63xx_wdt.c | ||
3 | * | ||
4 | * Driver for max63{69,70,71,72,73,74} watchdog timers | ||
5 | * | ||
6 | * Copyright (C) 2009 Marc Zyngier <maz@misterjones.org> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | * | ||
12 | * This driver assumes the watchdog pins are memory mapped (as it is | ||
13 | * the case for the Arcom Zeus). Should it be connected over GPIOs or | ||
14 | * another interface, some abstraction will have to be introduced. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/fs.h> | ||
22 | #include <linux/miscdevice.h> | ||
23 | #include <linux/watchdog.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/bitops.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/uaccess.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/device.h> | ||
31 | |||
32 | #define DEFAULT_HEARTBEAT 60 | ||
33 | #define MAX_HEARTBEAT 60 | ||
34 | |||
35 | static int heartbeat = DEFAULT_HEARTBEAT; | ||
36 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
37 | |||
38 | /* | ||
39 | * Memory mapping: a single byte, 3 first lower bits to select bit 3 | ||
40 | * to ping the watchdog. | ||
41 | */ | ||
42 | #define MAX6369_WDSET (7 << 0) | ||
43 | #define MAX6369_WDI (1 << 3) | ||
44 | |||
45 | static DEFINE_SPINLOCK(io_lock); | ||
46 | |||
47 | static unsigned long wdt_status; | ||
48 | #define WDT_IN_USE 0 | ||
49 | #define WDT_RUNNING 1 | ||
50 | #define WDT_OK_TO_CLOSE 2 | ||
51 | |||
52 | static int nodelay; | ||
53 | static struct resource *wdt_mem; | ||
54 | static void __iomem *wdt_base; | ||
55 | static struct platform_device *max63xx_pdev; | ||
56 | |||
57 | /* | ||
58 | * The timeout values used are actually the absolute minimum the chip | ||
59 | * offers. Typical values on my board are slightly over twice as long | ||
60 | * (10s setting ends up with a 25s timeout), and can be up to 3 times | ||
61 | * the nominal setting (according to the datasheet). So please take | ||
62 | * these values with a grain of salt. Same goes for the initial delay | ||
63 | * "feature". Only max6373/74 have a few settings without this initial | ||
64 | * delay (selected with the "nodelay" parameter). | ||
65 | * | ||
66 | * I also decided to remove from the tables any timeout smaller than a | ||
67 | * second, as it looked completly overkill... | ||
68 | */ | ||
69 | |||
70 | /* Timeouts in second */ | ||
71 | struct max63xx_timeout { | ||
72 | u8 wdset; | ||
73 | u8 tdelay; | ||
74 | u8 twd; | ||
75 | }; | ||
76 | |||
77 | static struct max63xx_timeout max6369_table[] = { | ||
78 | { 5, 1, 1 }, | ||
79 | { 6, 10, 10 }, | ||
80 | { 7, 60, 60 }, | ||
81 | { }, | ||
82 | }; | ||
83 | |||
84 | static struct max63xx_timeout max6371_table[] = { | ||
85 | { 6, 60, 3 }, | ||
86 | { 7, 60, 60 }, | ||
87 | { }, | ||
88 | }; | ||
89 | |||
90 | static struct max63xx_timeout max6373_table[] = { | ||
91 | { 2, 60, 1 }, | ||
92 | { 5, 0, 1 }, | ||
93 | { 1, 3, 3 }, | ||
94 | { 7, 60, 10 }, | ||
95 | { 6, 0, 10 }, | ||
96 | { }, | ||
97 | }; | ||
98 | |||
99 | static struct max63xx_timeout *current_timeout; | ||
100 | |||
101 | static struct max63xx_timeout * | ||
102 | max63xx_select_timeout(struct max63xx_timeout *table, int value) | ||
103 | { | ||
104 | while (table->twd) { | ||
105 | if (value <= table->twd) { | ||
106 | if (nodelay && table->tdelay == 0) | ||
107 | return table; | ||
108 | |||
109 | if (!nodelay) | ||
110 | return table; | ||
111 | } | ||
112 | |||
113 | table++; | ||
114 | } | ||
115 | |||
116 | return NULL; | ||
117 | } | ||
118 | |||
119 | static void max63xx_wdt_ping(void) | ||
120 | { | ||
121 | u8 val; | ||
122 | |||
123 | spin_lock(&io_lock); | ||
124 | |||
125 | val = __raw_readb(wdt_base); | ||
126 | |||
127 | __raw_writeb(val | MAX6369_WDI, wdt_base); | ||
128 | __raw_writeb(val & ~MAX6369_WDI, wdt_base); | ||
129 | |||
130 | spin_unlock(&io_lock); | ||
131 | } | ||
132 | |||
133 | static void max63xx_wdt_enable(struct max63xx_timeout *entry) | ||
134 | { | ||
135 | u8 val; | ||
136 | |||
137 | if (test_and_set_bit(WDT_RUNNING, &wdt_status)) | ||
138 | return; | ||
139 | |||
140 | spin_lock(&io_lock); | ||
141 | |||
142 | val = __raw_readb(wdt_base); | ||
143 | val &= ~MAX6369_WDSET; | ||
144 | val |= entry->wdset; | ||
145 | __raw_writeb(val, wdt_base); | ||
146 | |||
147 | spin_unlock(&io_lock); | ||
148 | |||
149 | /* check for a edge triggered startup */ | ||
150 | if (entry->tdelay == 0) | ||
151 | max63xx_wdt_ping(); | ||
152 | } | ||
153 | |||
154 | static void max63xx_wdt_disable(void) | ||
155 | { | ||
156 | spin_lock(&io_lock); | ||
157 | |||
158 | __raw_writeb(3, wdt_base); | ||
159 | |||
160 | spin_unlock(&io_lock); | ||
161 | |||
162 | clear_bit(WDT_RUNNING, &wdt_status); | ||
163 | } | ||
164 | |||
165 | static int max63xx_wdt_open(struct inode *inode, struct file *file) | ||
166 | { | ||
167 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
168 | return -EBUSY; | ||
169 | |||
170 | max63xx_wdt_enable(current_timeout); | ||
171 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
172 | |||
173 | return nonseekable_open(inode, file); | ||
174 | } | ||
175 | |||
176 | static ssize_t max63xx_wdt_write(struct file *file, const char *data, | ||
177 | size_t len, loff_t *ppos) | ||
178 | { | ||
179 | if (len) { | ||
180 | if (!nowayout) { | ||
181 | size_t i; | ||
182 | |||
183 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
184 | for (i = 0; i != len; i++) { | ||
185 | char c; | ||
186 | |||
187 | if (get_user(c, data + i)) | ||
188 | return -EFAULT; | ||
189 | |||
190 | if (c == 'V') | ||
191 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | max63xx_wdt_ping(); | ||
196 | } | ||
197 | |||
198 | return len; | ||
199 | } | ||
200 | |||
201 | static const struct watchdog_info ident = { | ||
202 | .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | ||
203 | .identity = "max63xx Watchdog", | ||
204 | }; | ||
205 | |||
206 | static long max63xx_wdt_ioctl(struct file *file, unsigned int cmd, | ||
207 | unsigned long arg) | ||
208 | { | ||
209 | int ret = -ENOTTY; | ||
210 | |||
211 | switch (cmd) { | ||
212 | case WDIOC_GETSUPPORT: | ||
213 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | ||
214 | sizeof(ident)) ? -EFAULT : 0; | ||
215 | break; | ||
216 | |||
217 | case WDIOC_GETSTATUS: | ||
218 | case WDIOC_GETBOOTSTATUS: | ||
219 | ret = put_user(0, (int *)arg); | ||
220 | break; | ||
221 | |||
222 | case WDIOC_KEEPALIVE: | ||
223 | max63xx_wdt_ping(); | ||
224 | ret = 0; | ||
225 | break; | ||
226 | |||
227 | case WDIOC_GETTIMEOUT: | ||
228 | ret = put_user(heartbeat, (int *)arg); | ||
229 | break; | ||
230 | } | ||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | static int max63xx_wdt_release(struct inode *inode, struct file *file) | ||
235 | { | ||
236 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
237 | max63xx_wdt_disable(); | ||
238 | else | ||
239 | dev_crit(&max63xx_pdev->dev, | ||
240 | "device closed unexpectedly - timer will not stop\n"); | ||
241 | |||
242 | clear_bit(WDT_IN_USE, &wdt_status); | ||
243 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static const struct file_operations max63xx_wdt_fops = { | ||
249 | .owner = THIS_MODULE, | ||
250 | .llseek = no_llseek, | ||
251 | .write = max63xx_wdt_write, | ||
252 | .unlocked_ioctl = max63xx_wdt_ioctl, | ||
253 | .open = max63xx_wdt_open, | ||
254 | .release = max63xx_wdt_release, | ||
255 | }; | ||
256 | |||
257 | static struct miscdevice max63xx_wdt_miscdev = { | ||
258 | .minor = WATCHDOG_MINOR, | ||
259 | .name = "watchdog", | ||
260 | .fops = &max63xx_wdt_fops, | ||
261 | }; | ||
262 | |||
263 | static int __devinit max63xx_wdt_probe(struct platform_device *pdev) | ||
264 | { | ||
265 | int ret = 0; | ||
266 | int size; | ||
267 | struct resource *res; | ||
268 | struct device *dev = &pdev->dev; | ||
269 | struct max63xx_timeout *table; | ||
270 | |||
271 | table = (struct max63xx_timeout *)pdev->id_entry->driver_data; | ||
272 | |||
273 | if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) | ||
274 | heartbeat = DEFAULT_HEARTBEAT; | ||
275 | |||
276 | dev_info(dev, "requesting %ds heartbeat\n", heartbeat); | ||
277 | current_timeout = max63xx_select_timeout(table, heartbeat); | ||
278 | |||
279 | if (!current_timeout) { | ||
280 | dev_err(dev, "unable to satisfy heartbeat request\n"); | ||
281 | return -EINVAL; | ||
282 | } | ||
283 | |||
284 | dev_info(dev, "using %ds heartbeat with %ds initial delay\n", | ||
285 | current_timeout->twd, current_timeout->tdelay); | ||
286 | |||
287 | heartbeat = current_timeout->twd; | ||
288 | |||
289 | max63xx_pdev = pdev; | ||
290 | |||
291 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
292 | if (res == NULL) { | ||
293 | dev_err(dev, "failed to get memory region resource\n"); | ||
294 | return -ENOENT; | ||
295 | } | ||
296 | |||
297 | size = resource_size(res); | ||
298 | wdt_mem = request_mem_region(res->start, size, pdev->name); | ||
299 | |||
300 | if (wdt_mem == NULL) { | ||
301 | dev_err(dev, "failed to get memory region\n"); | ||
302 | return -ENOENT; | ||
303 | } | ||
304 | |||
305 | wdt_base = ioremap(res->start, size); | ||
306 | if (!wdt_base) { | ||
307 | dev_err(dev, "failed to map memory region\n"); | ||
308 | ret = -ENOMEM; | ||
309 | goto out_request; | ||
310 | } | ||
311 | |||
312 | ret = misc_register(&max63xx_wdt_miscdev); | ||
313 | if (ret < 0) { | ||
314 | dev_err(dev, "cannot register misc device\n"); | ||
315 | goto out_unmap; | ||
316 | } | ||
317 | |||
318 | return 0; | ||
319 | |||
320 | out_unmap: | ||
321 | iounmap(wdt_base); | ||
322 | out_request: | ||
323 | release_resource(wdt_mem); | ||
324 | kfree(wdt_mem); | ||
325 | |||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | static int __devexit max63xx_wdt_remove(struct platform_device *pdev) | ||
330 | { | ||
331 | misc_deregister(&max63xx_wdt_miscdev); | ||
332 | if (wdt_mem) { | ||
333 | release_resource(wdt_mem); | ||
334 | kfree(wdt_mem); | ||
335 | wdt_mem = NULL; | ||
336 | } | ||
337 | |||
338 | if (wdt_base) | ||
339 | iounmap(wdt_base); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static struct platform_device_id max63xx_id_table[] = { | ||
345 | { "max6369_wdt", (kernel_ulong_t)max6369_table, }, | ||
346 | { "max6370_wdt", (kernel_ulong_t)max6369_table, }, | ||
347 | { "max6371_wdt", (kernel_ulong_t)max6371_table, }, | ||
348 | { "max6372_wdt", (kernel_ulong_t)max6371_table, }, | ||
349 | { "max6373_wdt", (kernel_ulong_t)max6373_table, }, | ||
350 | { "max6374_wdt", (kernel_ulong_t)max6373_table, }, | ||
351 | { }, | ||
352 | }; | ||
353 | MODULE_DEVICE_TABLE(platform, max63xx_id_table); | ||
354 | |||
355 | static struct platform_driver max63xx_wdt_driver = { | ||
356 | .probe = max63xx_wdt_probe, | ||
357 | .remove = __devexit_p(max63xx_wdt_remove), | ||
358 | .id_table = max63xx_id_table, | ||
359 | .driver = { | ||
360 | .name = "max63xx_wdt", | ||
361 | .owner = THIS_MODULE, | ||
362 | }, | ||
363 | }; | ||
364 | |||
365 | static int __init max63xx_wdt_init(void) | ||
366 | { | ||
367 | return platform_driver_register(&max63xx_wdt_driver); | ||
368 | } | ||
369 | |||
370 | static void __exit max63xx_wdt_exit(void) | ||
371 | { | ||
372 | platform_driver_unregister(&max63xx_wdt_driver); | ||
373 | } | ||
374 | |||
375 | module_init(max63xx_wdt_init); | ||
376 | module_exit(max63xx_wdt_exit); | ||
377 | |||
378 | MODULE_AUTHOR("Marc Zyngier <maz@misterjones.org>"); | ||
379 | MODULE_DESCRIPTION("max63xx Watchdog Driver"); | ||
380 | |||
381 | module_param(heartbeat, int, 0); | ||
382 | MODULE_PARM_DESC(heartbeat, | ||
383 | "Watchdog heartbeat period in seconds from 1 to " | ||
384 | __MODULE_STRING(MAX_HEARTBEAT) ", default " | ||
385 | __MODULE_STRING(DEFAULT_HEARTBEAT)); | ||
386 | |||
387 | module_param(nowayout, int, 0); | ||
388 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | ||
389 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
390 | |||
391 | module_param(nodelay, int, 0); | ||
392 | MODULE_PARM_DESC(nodelay, | ||
393 | "Force selection of a timeout setting without initial delay " | ||
394 | "(max6373/74 only, default=0)"); | ||
395 | |||
396 | MODULE_LICENSE("GPL"); | ||
397 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c index 407b025cb104..bc820d16699a 100644 --- a/drivers/watchdog/mixcomwd.c +++ b/drivers/watchdog/mixcomwd.c | |||
@@ -201,7 +201,7 @@ static long mixcomwd_ioctl(struct file *file, | |||
201 | void __user *argp = (void __user *)arg; | 201 | void __user *argp = (void __user *)arg; |
202 | int __user *p = argp; | 202 | int __user *p = argp; |
203 | int status; | 203 | int status; |
204 | static struct watchdog_info ident = { | 204 | static const struct watchdog_info ident = { |
205 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | 205 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, |
206 | .firmware_version = 1, | 206 | .firmware_version = 1, |
207 | .identity = "MixCOM watchdog", | 207 | .identity = "MixCOM watchdog", |
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 38c588ee694f..4e3941c5e293 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c | |||
@@ -148,7 +148,7 @@ static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd, | |||
148 | { | 148 | { |
149 | void __user *argp = (void __user *)arg; | 149 | void __user *argp = (void __user *)arg; |
150 | int __user *p = argp; | 150 | int __user *p = argp; |
151 | static struct watchdog_info ident = { | 151 | static const struct watchdog_info ident = { |
152 | .options = WDIOF_KEEPALIVEPING, | 152 | .options = WDIOF_KEEPALIVEPING, |
153 | .firmware_version = 1, | 153 | .firmware_version = 1, |
154 | .identity = "MPC8xxx", | 154 | .identity = "MPC8xxx", |
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index a2dc07c2ed49..b0646dac924e 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c | |||
@@ -213,7 +213,7 @@ static ssize_t mpcore_wdt_write(struct file *file, const char *data, | |||
213 | return len; | 213 | return len; |
214 | } | 214 | } |
215 | 215 | ||
216 | static struct watchdog_info ident = { | 216 | static const struct watchdog_info ident = { |
217 | .options = WDIOF_SETTIMEOUT | | 217 | .options = WDIOF_SETTIMEOUT | |
218 | WDIOF_KEEPALIVEPING | | 218 | WDIOF_KEEPALIVEPING | |
219 | WDIOF_MAGICCLOSE, | 219 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index a51dbe4c43da..97f8a48d8b78 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c | |||
@@ -179,7 +179,7 @@ static long mv64x60_wdt_ioctl(struct file *file, | |||
179 | int timeout; | 179 | int timeout; |
180 | int options; | 180 | int options; |
181 | void __user *argp = (void __user *)arg; | 181 | void __user *argp = (void __user *)arg; |
182 | static struct watchdog_info info = { | 182 | static const struct watchdog_info info = { |
183 | .options = WDIOF_SETTIMEOUT | | 183 | .options = WDIOF_SETTIMEOUT | |
184 | WDIOF_MAGICCLOSE | | 184 | WDIOF_MAGICCLOSE | |
185 | WDIOF_KEEPALIVEPING, | 185 | WDIOF_KEEPALIVEPING, |
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 1a2b916e3f8d..d3aa2f1fe61d 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c | |||
@@ -407,7 +407,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd, | |||
407 | int __user *i; | 407 | int __user *i; |
408 | } uarg; | 408 | } uarg; |
409 | 409 | ||
410 | static struct watchdog_info ident = { | 410 | static const struct watchdog_info ident = { |
411 | .options = WDIOF_KEEPALIVEPING | | 411 | .options = WDIOF_KEEPALIVEPING | |
412 | WDIOF_SETTIMEOUT | | 412 | WDIOF_SETTIMEOUT | |
413 | WDIOF_MAGICCLOSE, | 413 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index aa9512321f3a..06f7922606c0 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c | |||
@@ -606,7 +606,7 @@ static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
606 | int temperature; | 606 | int temperature; |
607 | int new_heartbeat; | 607 | int new_heartbeat; |
608 | int __user *argp = (int __user *)arg; | 608 | int __user *argp = (int __user *)arg; |
609 | static struct watchdog_info ident = { | 609 | static const struct watchdog_info ident = { |
610 | .options = WDIOF_OVERHEAT | | 610 | .options = WDIOF_OVERHEAT | |
611 | WDIOF_CARDRESET | | 611 | WDIOF_CARDRESET | |
612 | WDIOF_KEEPALIVEPING | | 612 | WDIOF_KEEPALIVEPING | |
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index 698f51bff1bc..64374d636f09 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c | |||
@@ -481,7 +481,7 @@ static long pcipcwd_ioctl(struct file *file, unsigned int cmd, | |||
481 | { | 481 | { |
482 | void __user *argp = (void __user *)arg; | 482 | void __user *argp = (void __user *)arg; |
483 | int __user *p = argp; | 483 | int __user *p = argp; |
484 | static struct watchdog_info ident = { | 484 | static const struct watchdog_info ident = { |
485 | .options = WDIOF_OVERHEAT | | 485 | .options = WDIOF_OVERHEAT | |
486 | WDIOF_CARDRESET | | 486 | WDIOF_CARDRESET | |
487 | WDIOF_KEEPALIVEPING | | 487 | WDIOF_KEEPALIVEPING | |
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 052fe451851f..8e4eacc5bb52 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c | |||
@@ -404,7 +404,7 @@ static long usb_pcwd_ioctl(struct file *file, unsigned int cmd, | |||
404 | { | 404 | { |
405 | void __user *argp = (void __user *)arg; | 405 | void __user *argp = (void __user *)arg; |
406 | int __user *p = argp; | 406 | int __user *p = argp; |
407 | static struct watchdog_info ident = { | 407 | static const struct watchdog_info ident = { |
408 | .options = WDIOF_KEEPALIVEPING | | 408 | .options = WDIOF_KEEPALIVEPING | |
409 | WDIOF_SETTIMEOUT | | 409 | WDIOF_SETTIMEOUT | |
410 | WDIOF_MAGICCLOSE, | 410 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c index 2d22e996e996..435ec2aed4fe 100644 --- a/drivers/watchdog/pika_wdt.c +++ b/drivers/watchdog/pika_wdt.c | |||
@@ -52,7 +52,7 @@ static struct { | |||
52 | struct timer_list timer; /* The timer that pings the watchdog */ | 52 | struct timer_list timer; /* The timer that pings the watchdog */ |
53 | } pikawdt_private; | 53 | } pikawdt_private; |
54 | 54 | ||
55 | static struct watchdog_info ident = { | 55 | static const struct watchdog_info ident = { |
56 | .identity = DRV_NAME, | 56 | .identity = DRV_NAME, |
57 | .options = WDIOF_CARDRESET | | 57 | .options = WDIOF_CARDRESET | |
58 | WDIOF_SETTIMEOUT | | 58 | WDIOF_SETTIMEOUT | |
diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c index 538ec2c05197..09102f09e681 100644 --- a/drivers/watchdog/pnx833x_wdt.c +++ b/drivers/watchdog/pnx833x_wdt.c | |||
@@ -141,7 +141,7 @@ static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
141 | int options, new_timeout = 0; | 141 | int options, new_timeout = 0; |
142 | uint32_t timeout, timeout_left = 0; | 142 | uint32_t timeout, timeout_left = 0; |
143 | 143 | ||
144 | static struct watchdog_info ident = { | 144 | static const struct watchdog_info ident = { |
145 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, | 145 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, |
146 | .firmware_version = 0, | 146 | .firmware_version = 0, |
147 | .identity = "Hardware Watchdog for PNX833x", | 147 | .identity = "Hardware Watchdog for PNX833x", |
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index bf12d06b5877..d4c29b5311a4 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c | |||
@@ -198,7 +198,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, | |||
198 | void __user *argp = (void __user *)arg; | 198 | void __user *argp = (void __user *)arg; |
199 | int new_timeout; | 199 | int new_timeout; |
200 | unsigned int value; | 200 | unsigned int value; |
201 | static struct watchdog_info ident = { | 201 | static const struct watchdog_info ident = { |
202 | .options = WDIOF_SETTIMEOUT | | 202 | .options = WDIOF_SETTIMEOUT | |
203 | WDIOF_KEEPALIVEPING | | 203 | WDIOF_KEEPALIVEPING | |
204 | WDIOF_MAGICCLOSE, | 204 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 4976bfd1fce6..69c6adbd8205 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c | |||
@@ -149,7 +149,7 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
149 | { | 149 | { |
150 | void __user *argp = (void __user *)arg; | 150 | void __user *argp = (void __user *)arg; |
151 | unsigned int value; | 151 | unsigned int value; |
152 | static struct watchdog_info ident = { | 152 | static const struct watchdog_info ident = { |
153 | .options = WDIOF_CARDRESET, | 153 | .options = WDIOF_CARDRESET, |
154 | .identity = "RDC321x WDT", | 154 | .identity = "RDC321x WDT", |
155 | }; | 155 | }; |
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index c14ae8676903..ae57bf9e1b03 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c | |||
@@ -85,7 +85,7 @@ static int riowd_release(struct inode *inode, struct file *filp) | |||
85 | 85 | ||
86 | static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 86 | static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
87 | { | 87 | { |
88 | static struct watchdog_info info = { | 88 | static const struct watchdog_info info = { |
89 | .options = WDIOF_SETTIMEOUT, | 89 | .options = WDIOF_SETTIMEOUT, |
90 | .firmware_version = 1, | 90 | .firmware_version = 1, |
91 | .identity = DRIVER_NAME, | 91 | .identity = DRIVER_NAME, |
diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index e6763d2a567b..8d44c9b6fb5b 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c | |||
@@ -111,7 +111,7 @@ out: | |||
111 | } | 111 | } |
112 | 112 | ||
113 | 113 | ||
114 | static struct watchdog_info ident = { | 114 | static const struct watchdog_info ident = { |
115 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | 115 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | |
116 | WDIOF_KEEPALIVEPING, | 116 | WDIOF_KEEPALIVEPING, |
117 | .identity = WATCHDOG_NAME, | 117 | .identity = WATCHDOG_NAME, |
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 569eb295a7a8..9c40f48804f5 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c | |||
@@ -250,7 +250,7 @@ static long sch311x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
250 | int new_timeout; | 250 | int new_timeout; |
251 | void __user *argp = (void __user *)arg; | 251 | void __user *argp = (void __user *)arg; |
252 | int __user *p = argp; | 252 | int __user *p = argp; |
253 | static struct watchdog_info ident = { | 253 | static const struct watchdog_info ident = { |
254 | .options = WDIOF_KEEPALIVEPING | | 254 | .options = WDIOF_KEEPALIVEPING | |
255 | WDIOF_SETTIMEOUT | | 255 | WDIOF_SETTIMEOUT | |
256 | WDIOF_MAGICCLOSE, | 256 | WDIOF_MAGICCLOSE, |
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c index 5dd952681f32..b3421fd2cda8 100644 --- a/drivers/watchdog/stmp3xxx_wdt.c +++ b/drivers/watchdog/stmp3xxx_wdt.c | |||
@@ -94,7 +94,7 @@ static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data, | |||
94 | return len; | 94 | return len; |
95 | } | 95 | } |
96 | 96 | ||
97 | static struct watchdog_info ident = { | 97 | static const struct watchdog_info ident = { |
98 | .options = WDIOF_CARDRESET | | 98 | .options = WDIOF_CARDRESET | |
99 | WDIOF_MAGICCLOSE | | 99 | WDIOF_MAGICCLOSE | |
100 | WDIOF_SETTIMEOUT | | 100 | WDIOF_SETTIMEOUT | |
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c new file mode 100644 index 000000000000..565a2c3321e5 --- /dev/null +++ b/drivers/watchdog/ts72xx_wdt.c | |||
@@ -0,0 +1,520 @@ | |||
1 | /* | ||
2 | * Watchdog driver for Technologic Systems TS-72xx based SBCs | ||
3 | * (TS-7200, TS-7250 and TS-7260). These boards have external | ||
4 | * glue logic CPLD chip, which includes programmable watchdog | ||
5 | * timer. | ||
6 | * | ||
7 | * Copyright (c) 2009 Mika Westerberg <mika.westerberg@iki.fi> | ||
8 | * | ||
9 | * This driver is based on ep93xx_wdt and wm831x_wdt drivers. | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | */ | ||
15 | |||
16 | #include <linux/fs.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/miscdevice.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/watchdog.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | |||
26 | #define TS72XX_WDT_FEED_VAL 0x05 | ||
27 | #define TS72XX_WDT_DEFAULT_TIMEOUT 8 | ||
28 | |||
29 | static int timeout = TS72XX_WDT_DEFAULT_TIMEOUT; | ||
30 | module_param(timeout, int, 0); | ||
31 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. " | ||
32 | "(1 <= timeout <= 8, default=" | ||
33 | __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT) | ||
34 | ")"); | ||
35 | |||
36 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
37 | module_param(nowayout, int, 0); | ||
38 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | ||
39 | |||
40 | /** | ||
41 | * struct ts72xx_wdt - watchdog control structure | ||
42 | * @lock: lock that protects this structure | ||
43 | * @regval: watchdog timeout value suitable for control register | ||
44 | * @flags: flags controlling watchdog device state | ||
45 | * @control_reg: watchdog control register | ||
46 | * @feed_reg: watchdog feed register | ||
47 | * @pdev: back pointer to platform dev | ||
48 | */ | ||
49 | struct ts72xx_wdt { | ||
50 | struct mutex lock; | ||
51 | int regval; | ||
52 | |||
53 | #define TS72XX_WDT_BUSY_FLAG 1 | ||
54 | #define TS72XX_WDT_EXPECT_CLOSE_FLAG 2 | ||
55 | int flags; | ||
56 | |||
57 | void __iomem *control_reg; | ||
58 | void __iomem *feed_reg; | ||
59 | |||
60 | struct platform_device *pdev; | ||
61 | }; | ||
62 | |||
63 | struct platform_device *ts72xx_wdt_pdev; | ||
64 | |||
65 | /* | ||
66 | * TS-72xx Watchdog supports following timeouts (value written | ||
67 | * to control register): | ||
68 | * value description | ||
69 | * ------------------------- | ||
70 | * 0x00 watchdog disabled | ||
71 | * 0x01 250ms | ||
72 | * 0x02 500ms | ||
73 | * 0x03 1s | ||
74 | * 0x04 reserved | ||
75 | * 0x05 2s | ||
76 | * 0x06 4s | ||
77 | * 0x07 8s | ||
78 | * | ||
79 | * Timeouts below 1s are not very usable so we don't | ||
80 | * allow them at all. | ||
81 | * | ||
82 | * We provide two functions that convert between these: | ||
83 | * timeout_to_regval() and regval_to_timeout(). | ||
84 | */ | ||
85 | static const struct { | ||
86 | int timeout; | ||
87 | int regval; | ||
88 | } ts72xx_wdt_map[] = { | ||
89 | { 1, 3 }, | ||
90 | { 2, 5 }, | ||
91 | { 4, 6 }, | ||
92 | { 8, 7 }, | ||
93 | }; | ||
94 | |||
95 | /** | ||
96 | * timeout_to_regval() - converts given timeout to control register value | ||
97 | * @new_timeout: timeout in seconds to be converted | ||
98 | * | ||
99 | * Function converts given @new_timeout into valid value that can | ||
100 | * be programmed into watchdog control register. When conversion is | ||
101 | * not possible, function returns %-EINVAL. | ||
102 | */ | ||
103 | static int timeout_to_regval(int new_timeout) | ||
104 | { | ||
105 | int i; | ||
106 | |||
107 | /* first limit it to 1 - 8 seconds */ | ||
108 | new_timeout = clamp_val(new_timeout, 1, 8); | ||
109 | |||
110 | for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { | ||
111 | if (ts72xx_wdt_map[i].timeout >= new_timeout) | ||
112 | return ts72xx_wdt_map[i].regval; | ||
113 | } | ||
114 | |||
115 | return -EINVAL; | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * regval_to_timeout() - converts control register value to timeout | ||
120 | * @regval: control register value to be converted | ||
121 | * | ||
122 | * Function converts given @regval to timeout in seconds (1, 2, 4 or 8). | ||
123 | * If @regval cannot be converted, function returns %-EINVAL. | ||
124 | */ | ||
125 | static int regval_to_timeout(int regval) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) { | ||
130 | if (ts72xx_wdt_map[i].regval == regval) | ||
131 | return ts72xx_wdt_map[i].timeout; | ||
132 | } | ||
133 | |||
134 | return -EINVAL; | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * ts72xx_wdt_kick() - kick the watchdog | ||
139 | * @wdt: watchdog to be kicked | ||
140 | * | ||
141 | * Called with @wdt->lock held. | ||
142 | */ | ||
143 | static inline void ts72xx_wdt_kick(struct ts72xx_wdt *wdt) | ||
144 | { | ||
145 | __raw_writeb(TS72XX_WDT_FEED_VAL, wdt->feed_reg); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * ts72xx_wdt_start() - starts the watchdog timer | ||
150 | * @wdt: watchdog to be started | ||
151 | * | ||
152 | * This function programs timeout to watchdog timer | ||
153 | * and starts it. | ||
154 | * | ||
155 | * Called with @wdt->lock held. | ||
156 | */ | ||
157 | static void ts72xx_wdt_start(struct ts72xx_wdt *wdt) | ||
158 | { | ||
159 | /* | ||
160 | * To program the wdt, it first must be "fed" and | ||
161 | * only after that (within 30 usecs) the configuration | ||
162 | * can be changed. | ||
163 | */ | ||
164 | ts72xx_wdt_kick(wdt); | ||
165 | __raw_writeb((u8)wdt->regval, wdt->control_reg); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * ts72xx_wdt_stop() - stops the watchdog timer | ||
170 | * @wdt: watchdog to be stopped | ||
171 | * | ||
172 | * Called with @wdt->lock held. | ||
173 | */ | ||
174 | static void ts72xx_wdt_stop(struct ts72xx_wdt *wdt) | ||
175 | { | ||
176 | ts72xx_wdt_kick(wdt); | ||
177 | __raw_writeb(0, wdt->control_reg); | ||
178 | } | ||
179 | |||
180 | static int ts72xx_wdt_open(struct inode *inode, struct file *file) | ||
181 | { | ||
182 | struct ts72xx_wdt *wdt = platform_get_drvdata(ts72xx_wdt_pdev); | ||
183 | int regval; | ||
184 | |||
185 | /* | ||
186 | * Try to convert default timeout to valid register | ||
187 | * value first. | ||
188 | */ | ||
189 | regval = timeout_to_regval(timeout); | ||
190 | if (regval < 0) { | ||
191 | dev_err(&wdt->pdev->dev, | ||
192 | "failed to convert timeout (%d) to register value\n", | ||
193 | timeout); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | if (mutex_lock_interruptible(&wdt->lock)) | ||
198 | return -ERESTARTSYS; | ||
199 | |||
200 | if ((wdt->flags & TS72XX_WDT_BUSY_FLAG) != 0) { | ||
201 | mutex_unlock(&wdt->lock); | ||
202 | return -EBUSY; | ||
203 | } | ||
204 | |||
205 | wdt->flags = TS72XX_WDT_BUSY_FLAG; | ||
206 | wdt->regval = regval; | ||
207 | file->private_data = wdt; | ||
208 | |||
209 | ts72xx_wdt_start(wdt); | ||
210 | |||
211 | mutex_unlock(&wdt->lock); | ||
212 | return nonseekable_open(inode, file); | ||
213 | } | ||
214 | |||
215 | static int ts72xx_wdt_release(struct inode *inode, struct file *file) | ||
216 | { | ||
217 | struct ts72xx_wdt *wdt = file->private_data; | ||
218 | |||
219 | if (mutex_lock_interruptible(&wdt->lock)) | ||
220 | return -ERESTARTSYS; | ||
221 | |||
222 | if ((wdt->flags & TS72XX_WDT_EXPECT_CLOSE_FLAG) != 0) { | ||
223 | ts72xx_wdt_stop(wdt); | ||
224 | } else { | ||
225 | dev_warn(&wdt->pdev->dev, | ||
226 | "TS-72XX WDT device closed unexpectly. " | ||
227 | "Watchdog timer will not stop!\n"); | ||
228 | /* | ||
229 | * Kick it one more time, to give userland some time | ||
230 | * to recover (for example, respawning the kicker | ||
231 | * daemon). | ||
232 | */ | ||
233 | ts72xx_wdt_kick(wdt); | ||
234 | } | ||
235 | |||
236 | wdt->flags = 0; | ||
237 | |||
238 | mutex_unlock(&wdt->lock); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static ssize_t ts72xx_wdt_write(struct file *file, | ||
243 | const char __user *data, | ||
244 | size_t len, | ||
245 | loff_t *ppos) | ||
246 | { | ||
247 | struct ts72xx_wdt *wdt = file->private_data; | ||
248 | |||
249 | if (!len) | ||
250 | return 0; | ||
251 | |||
252 | if (mutex_lock_interruptible(&wdt->lock)) | ||
253 | return -ERESTARTSYS; | ||
254 | |||
255 | ts72xx_wdt_kick(wdt); | ||
256 | |||
257 | /* | ||
258 | * Support for magic character closing. User process | ||
259 | * writes 'V' into the device, just before it is closed. | ||
260 | * This means that we know that the wdt timer can be | ||
261 | * stopped after user closes the device. | ||
262 | */ | ||
263 | if (!nowayout) { | ||
264 | int i; | ||
265 | |||
266 | for (i = 0; i < len; i++) { | ||
267 | char c; | ||
268 | |||
269 | /* In case it was set long ago */ | ||
270 | wdt->flags &= ~TS72XX_WDT_EXPECT_CLOSE_FLAG; | ||
271 | |||
272 | if (get_user(c, data + i)) { | ||
273 | mutex_unlock(&wdt->lock); | ||
274 | return -EFAULT; | ||
275 | } | ||
276 | if (c == 'V') { | ||
277 | wdt->flags |= TS72XX_WDT_EXPECT_CLOSE_FLAG; | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | mutex_unlock(&wdt->lock); | ||
284 | return len; | ||
285 | } | ||
286 | |||
287 | static const struct watchdog_info winfo = { | ||
288 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | | ||
289 | WDIOF_MAGICCLOSE, | ||
290 | .firmware_version = 1, | ||
291 | .identity = "TS-72XX WDT", | ||
292 | }; | ||
293 | |||
294 | static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd, | ||
295 | unsigned long arg) | ||
296 | { | ||
297 | struct ts72xx_wdt *wdt = file->private_data; | ||
298 | void __user *argp = (void __user *)arg; | ||
299 | int __user *p = (int __user *)argp; | ||
300 | int error = 0; | ||
301 | |||
302 | if (mutex_lock_interruptible(&wdt->lock)) | ||
303 | return -ERESTARTSYS; | ||
304 | |||
305 | switch (cmd) { | ||
306 | case WDIOC_GETSUPPORT: | ||
307 | error = copy_to_user(argp, &winfo, sizeof(winfo)); | ||
308 | break; | ||
309 | |||
310 | case WDIOC_GETSTATUS: | ||
311 | case WDIOC_GETBOOTSTATUS: | ||
312 | return put_user(0, p); | ||
313 | |||
314 | case WDIOC_KEEPALIVE: | ||
315 | ts72xx_wdt_kick(wdt); | ||
316 | break; | ||
317 | |||
318 | case WDIOC_SETOPTIONS: { | ||
319 | int options; | ||
320 | |||
321 | if (get_user(options, p)) { | ||
322 | error = -EFAULT; | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | error = -EINVAL; | ||
327 | |||
328 | if ((options & WDIOS_DISABLECARD) != 0) { | ||
329 | ts72xx_wdt_stop(wdt); | ||
330 | error = 0; | ||
331 | } | ||
332 | if ((options & WDIOS_ENABLECARD) != 0) { | ||
333 | ts72xx_wdt_start(wdt); | ||
334 | error = 0; | ||
335 | } | ||
336 | |||
337 | break; | ||
338 | } | ||
339 | |||
340 | case WDIOC_SETTIMEOUT: { | ||
341 | int new_timeout; | ||
342 | |||
343 | if (get_user(new_timeout, p)) { | ||
344 | error = -EFAULT; | ||
345 | } else { | ||
346 | int regval; | ||
347 | |||
348 | regval = timeout_to_regval(new_timeout); | ||
349 | if (regval < 0) { | ||
350 | error = -EINVAL; | ||
351 | } else { | ||
352 | ts72xx_wdt_stop(wdt); | ||
353 | wdt->regval = regval; | ||
354 | ts72xx_wdt_start(wdt); | ||
355 | } | ||
356 | } | ||
357 | if (error) | ||
358 | break; | ||
359 | |||
360 | /*FALLTHROUGH*/ | ||
361 | } | ||
362 | |||
363 | case WDIOC_GETTIMEOUT: | ||
364 | if (put_user(regval_to_timeout(wdt->regval), p)) | ||
365 | error = -EFAULT; | ||
366 | break; | ||
367 | |||
368 | default: | ||
369 | error = -ENOTTY; | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | mutex_unlock(&wdt->lock); | ||
374 | return error; | ||
375 | } | ||
376 | |||
377 | static const struct file_operations ts72xx_wdt_fops = { | ||
378 | .owner = THIS_MODULE, | ||
379 | .llseek = no_llseek, | ||
380 | .open = ts72xx_wdt_open, | ||
381 | .release = ts72xx_wdt_release, | ||
382 | .write = ts72xx_wdt_write, | ||
383 | .unlocked_ioctl = ts72xx_wdt_ioctl, | ||
384 | }; | ||
385 | |||
386 | static struct miscdevice ts72xx_wdt_miscdev = { | ||
387 | .minor = WATCHDOG_MINOR, | ||
388 | .name = "watchdog", | ||
389 | .fops = &ts72xx_wdt_fops, | ||
390 | }; | ||
391 | |||
392 | static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) | ||
393 | { | ||
394 | struct ts72xx_wdt *wdt; | ||
395 | struct resource *r1, *r2; | ||
396 | int error = 0; | ||
397 | |||
398 | wdt = kzalloc(sizeof(struct ts72xx_wdt), GFP_KERNEL); | ||
399 | if (!wdt) { | ||
400 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
401 | return -ENOMEM; | ||
402 | } | ||
403 | |||
404 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
405 | if (!r1) { | ||
406 | dev_err(&pdev->dev, "failed to get memory resource\n"); | ||
407 | error = -ENODEV; | ||
408 | goto fail; | ||
409 | } | ||
410 | |||
411 | r1 = request_mem_region(r1->start, resource_size(r1), pdev->name); | ||
412 | if (!r1) { | ||
413 | dev_err(&pdev->dev, "cannot request memory region\n"); | ||
414 | error = -EBUSY; | ||
415 | goto fail; | ||
416 | } | ||
417 | |||
418 | wdt->control_reg = ioremap(r1->start, resource_size(r1)); | ||
419 | if (!wdt->control_reg) { | ||
420 | dev_err(&pdev->dev, "failed to map memory\n"); | ||
421 | error = -ENODEV; | ||
422 | goto fail_free_control; | ||
423 | } | ||
424 | |||
425 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
426 | if (!r2) { | ||
427 | dev_err(&pdev->dev, "failed to get memory resource\n"); | ||
428 | error = -ENODEV; | ||
429 | goto fail_unmap_control; | ||
430 | } | ||
431 | |||
432 | r2 = request_mem_region(r2->start, resource_size(r2), pdev->name); | ||
433 | if (!r2) { | ||
434 | dev_err(&pdev->dev, "cannot request memory region\n"); | ||
435 | error = -EBUSY; | ||
436 | goto fail_unmap_control; | ||
437 | } | ||
438 | |||
439 | wdt->feed_reg = ioremap(r2->start, resource_size(r2)); | ||
440 | if (!wdt->feed_reg) { | ||
441 | dev_err(&pdev->dev, "failed to map memory\n"); | ||
442 | error = -ENODEV; | ||
443 | goto fail_free_feed; | ||
444 | } | ||
445 | |||
446 | platform_set_drvdata(pdev, wdt); | ||
447 | ts72xx_wdt_pdev = pdev; | ||
448 | wdt->pdev = pdev; | ||
449 | mutex_init(&wdt->lock); | ||
450 | |||
451 | error = misc_register(&ts72xx_wdt_miscdev); | ||
452 | if (error) { | ||
453 | dev_err(&pdev->dev, "failed to register miscdev\n"); | ||
454 | goto fail_unmap_feed; | ||
455 | } | ||
456 | |||
457 | dev_info(&pdev->dev, "TS-72xx Watchdog driver\n"); | ||
458 | |||
459 | return 0; | ||
460 | |||
461 | fail_unmap_feed: | ||
462 | platform_set_drvdata(pdev, NULL); | ||
463 | iounmap(wdt->feed_reg); | ||
464 | fail_free_feed: | ||
465 | release_mem_region(r2->start, resource_size(r2)); | ||
466 | fail_unmap_control: | ||
467 | iounmap(wdt->control_reg); | ||
468 | fail_free_control: | ||
469 | release_mem_region(r1->start, resource_size(r1)); | ||
470 | fail: | ||
471 | kfree(wdt); | ||
472 | return error; | ||
473 | } | ||
474 | |||
475 | static __devexit int ts72xx_wdt_remove(struct platform_device *pdev) | ||
476 | { | ||
477 | struct ts72xx_wdt *wdt = platform_get_drvdata(pdev); | ||
478 | struct resource *res; | ||
479 | int error; | ||
480 | |||
481 | error = misc_deregister(&ts72xx_wdt_miscdev); | ||
482 | platform_set_drvdata(pdev, NULL); | ||
483 | |||
484 | iounmap(wdt->feed_reg); | ||
485 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
486 | release_mem_region(res->start, resource_size(res)); | ||
487 | |||
488 | iounmap(wdt->control_reg); | ||
489 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
490 | release_mem_region(res->start, resource_size(res)); | ||
491 | |||
492 | kfree(wdt); | ||
493 | return error; | ||
494 | } | ||
495 | |||
496 | static struct platform_driver ts72xx_wdt_driver = { | ||
497 | .probe = ts72xx_wdt_probe, | ||
498 | .remove = __devexit_p(ts72xx_wdt_remove), | ||
499 | .driver = { | ||
500 | .name = "ts72xx-wdt", | ||
501 | .owner = THIS_MODULE, | ||
502 | }, | ||
503 | }; | ||
504 | |||
505 | static __init int ts72xx_wdt_init(void) | ||
506 | { | ||
507 | return platform_driver_register(&ts72xx_wdt_driver); | ||
508 | } | ||
509 | module_init(ts72xx_wdt_init); | ||
510 | |||
511 | static __exit void ts72xx_wdt_exit(void) | ||
512 | { | ||
513 | platform_driver_unregister(&ts72xx_wdt_driver); | ||
514 | } | ||
515 | module_exit(ts72xx_wdt_exit); | ||
516 | |||
517 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>"); | ||
518 | MODULE_DESCRIPTION("TS-72xx SBC Watchdog"); | ||
519 | MODULE_LICENSE("GPL"); | ||
520 | MODULE_ALIAS("platform:ts72xx-wdt"); | ||
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index d635566e9307..9e9ed7bfabcb 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/miscdevice.h> | 13 | #include <linux/miscdevice.h> |
14 | #include <linux/watchdog.h> | 14 | #include <linux/watchdog.h> |
15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
16 | #include <linux/reboot.h> | ||
17 | #include <linux/init.h> | 16 | #include <linux/init.h> |
18 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
19 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
@@ -166,14 +165,6 @@ static long txx9wdt_ioctl(struct file *file, unsigned int cmd, | |||
166 | } | 165 | } |
167 | } | 166 | } |
168 | 167 | ||
169 | static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
170 | void *unused) | ||
171 | { | ||
172 | if (code == SYS_DOWN || code == SYS_HALT) | ||
173 | txx9wdt_stop(); | ||
174 | return NOTIFY_DONE; | ||
175 | } | ||
176 | |||
177 | static const struct file_operations txx9wdt_fops = { | 168 | static const struct file_operations txx9wdt_fops = { |
178 | .owner = THIS_MODULE, | 169 | .owner = THIS_MODULE, |
179 | .llseek = no_llseek, | 170 | .llseek = no_llseek, |
@@ -189,10 +180,6 @@ static struct miscdevice txx9wdt_miscdev = { | |||
189 | .fops = &txx9wdt_fops, | 180 | .fops = &txx9wdt_fops, |
190 | }; | 181 | }; |
191 | 182 | ||
192 | static struct notifier_block txx9wdt_notifier = { | ||
193 | .notifier_call = txx9wdt_notify_sys, | ||
194 | }; | ||
195 | |||
196 | static int __init txx9wdt_probe(struct platform_device *dev) | 183 | static int __init txx9wdt_probe(struct platform_device *dev) |
197 | { | 184 | { |
198 | struct resource *res; | 185 | struct resource *res; |
@@ -221,13 +208,8 @@ static int __init txx9wdt_probe(struct platform_device *dev) | |||
221 | if (!txx9wdt_reg) | 208 | if (!txx9wdt_reg) |
222 | goto exit_busy; | 209 | goto exit_busy; |
223 | 210 | ||
224 | ret = register_reboot_notifier(&txx9wdt_notifier); | ||
225 | if (ret) | ||
226 | goto exit; | ||
227 | |||
228 | ret = misc_register(&txx9wdt_miscdev); | 211 | ret = misc_register(&txx9wdt_miscdev); |
229 | if (ret) { | 212 | if (ret) { |
230 | unregister_reboot_notifier(&txx9wdt_notifier); | ||
231 | goto exit; | 213 | goto exit; |
232 | } | 214 | } |
233 | 215 | ||
@@ -249,14 +231,19 @@ exit: | |||
249 | static int __exit txx9wdt_remove(struct platform_device *dev) | 231 | static int __exit txx9wdt_remove(struct platform_device *dev) |
250 | { | 232 | { |
251 | misc_deregister(&txx9wdt_miscdev); | 233 | misc_deregister(&txx9wdt_miscdev); |
252 | unregister_reboot_notifier(&txx9wdt_notifier); | ||
253 | clk_disable(txx9_imclk); | 234 | clk_disable(txx9_imclk); |
254 | clk_put(txx9_imclk); | 235 | clk_put(txx9_imclk); |
255 | return 0; | 236 | return 0; |
256 | } | 237 | } |
257 | 238 | ||
239 | static void txx9wdt_shutdown(struct platform_device *dev) | ||
240 | { | ||
241 | txx9wdt_stop(); | ||
242 | } | ||
243 | |||
258 | static struct platform_driver txx9wdt_driver = { | 244 | static struct platform_driver txx9wdt_driver = { |
259 | .remove = __exit_p(txx9wdt_remove), | 245 | .remove = __exit_p(txx9wdt_remove), |
246 | .shutdown = txx9wdt_shutdown, | ||
260 | .driver = { | 247 | .driver = { |
261 | .name = "txx9wdt", | 248 | .name = "txx9wdt", |
262 | .owner = THIS_MODULE, | 249 | .owner = THIS_MODULE, |
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index f201accc4e3d..0f5288df0091 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c | |||
@@ -201,7 +201,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
201 | void __user *argp = (void __user *)arg; | 201 | void __user *argp = (void __user *)arg; |
202 | int __user *p = argp; | 202 | int __user *p = argp; |
203 | int new_timeout; | 203 | int new_timeout; |
204 | static struct watchdog_info ident = { | 204 | static const struct watchdog_info ident = { |
205 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | | 205 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
206 | WDIOF_MAGICCLOSE, | 206 | WDIOF_MAGICCLOSE, |
207 | .firmware_version = 1, | 207 | .firmware_version = 1, |
diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c index 0560182a1d09..6e6743d1066f 100644 --- a/drivers/watchdog/w83977f_wdt.c +++ b/drivers/watchdog/w83977f_wdt.c | |||
@@ -371,7 +371,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, | |||
371 | * according to their available features. | 371 | * according to their available features. |
372 | */ | 372 | */ |
373 | 373 | ||
374 | static struct watchdog_info ident = { | 374 | static const struct watchdog_info ident = { |
375 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | 375 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, |
376 | .firmware_version = 1, | 376 | .firmware_version = 1, |
377 | .identity = WATCHDOG_NAME, | 377 | .identity = WATCHDOG_NAME, |
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index 5bfb1f2c5319..94ec22b9e66b 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c | |||
@@ -312,7 +312,7 @@ static long wdrtas_ioctl(struct file *file, unsigned int cmd, | |||
312 | { | 312 | { |
313 | int __user *argp = (void __user *)arg; | 313 | int __user *argp = (void __user *)arg; |
314 | int i; | 314 | int i; |
315 | static struct watchdog_info wdinfo = { | 315 | static const struct watchdog_info wdinfo = { |
316 | .options = WDRTAS_SUPPORTED_MASK, | 316 | .options = WDRTAS_SUPPORTED_MASK, |
317 | .firmware_version = 0, | 317 | .firmware_version = 0, |
318 | .identity = "wdrtas", | 318 | .identity = "wdrtas", |
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 3bbefe9a2634..bfda2e99dd89 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c | |||
@@ -358,7 +358,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
358 | int new_heartbeat; | 358 | int new_heartbeat; |
359 | int status; | 359 | int status; |
360 | 360 | ||
361 | static struct watchdog_info ident = { | 361 | struct watchdog_info ident = { |
362 | .options = WDIOF_SETTIMEOUT| | 362 | .options = WDIOF_SETTIMEOUT| |
363 | WDIOF_MAGICCLOSE| | 363 | WDIOF_MAGICCLOSE| |
364 | WDIOF_KEEPALIVEPING, | 364 | WDIOF_KEEPALIVEPING, |
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index f368dd87083a..7b22e3cdbc81 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c | |||
@@ -412,7 +412,7 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd, | |||
412 | int new_heartbeat; | 412 | int new_heartbeat; |
413 | int status; | 413 | int status; |
414 | 414 | ||
415 | static struct watchdog_info ident = { | 415 | struct watchdog_info ident = { |
416 | .options = WDIOF_SETTIMEOUT| | 416 | .options = WDIOF_SETTIMEOUT| |
417 | WDIOF_MAGICCLOSE| | 417 | WDIOF_MAGICCLOSE| |
418 | WDIOF_KEEPALIVEPING, | 418 | WDIOF_KEEPALIVEPING, |
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 775bcd807f31..8c4b2d5bb7da 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c | |||
@@ -213,7 +213,7 @@ static ssize_t wm831x_wdt_write(struct file *file, | |||
213 | return count; | 213 | return count; |
214 | } | 214 | } |
215 | 215 | ||
216 | static struct watchdog_info ident = { | 216 | static const struct watchdog_info ident = { |
217 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | 217 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, |
218 | .identity = "WM831x Watchdog", | 218 | .identity = "WM831x Watchdog", |
219 | }; | 219 | }; |
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c index a2d2e8eb2282..89dd7b035295 100644 --- a/drivers/watchdog/wm8350_wdt.c +++ b/drivers/watchdog/wm8350_wdt.c | |||
@@ -177,7 +177,7 @@ static ssize_t wm8350_wdt_write(struct file *file, | |||
177 | return count; | 177 | return count; |
178 | } | 178 | } |
179 | 179 | ||
180 | static struct watchdog_info ident = { | 180 | static const struct watchdog_info ident = { |
181 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | 181 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, |
182 | .identity = "WM8350 Watchdog", | 182 | .identity = "WM8350 Watchdog", |
183 | }; | 183 | }; |
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index ae5cb05a1a1c..bb71ab2336c8 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c | |||
@@ -426,7 +426,7 @@ static ssize_t hyp_sysfs_store(struct kobject *kobj, | |||
426 | return 0; | 426 | return 0; |
427 | } | 427 | } |
428 | 428 | ||
429 | static struct sysfs_ops hyp_sysfs_ops = { | 429 | static const struct sysfs_ops hyp_sysfs_ops = { |
430 | .show = hyp_sysfs_show, | 430 | .show = hyp_sysfs_show, |
431 | .store = hyp_sysfs_store, | 431 | .store = hyp_sysfs_store, |
432 | }; | 432 | }; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2b59201b955c..0427183e3e05 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -901,7 +901,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
901 | root->highest_objectid = 0; | 901 | root->highest_objectid = 0; |
902 | root->name = NULL; | 902 | root->name = NULL; |
903 | root->in_sysfs = 0; | 903 | root->in_sysfs = 0; |
904 | root->inode_tree.rb_node = NULL; | 904 | root->inode_tree = RB_ROOT; |
905 | 905 | ||
906 | INIT_LIST_HEAD(&root->dirty_list); | 906 | INIT_LIST_HEAD(&root->dirty_list); |
907 | INIT_LIST_HEAD(&root->orphan_list); | 907 | INIT_LIST_HEAD(&root->orphan_list); |
@@ -1673,7 +1673,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1673 | insert_inode_hash(fs_info->btree_inode); | 1673 | insert_inode_hash(fs_info->btree_inode); |
1674 | 1674 | ||
1675 | spin_lock_init(&fs_info->block_group_cache_lock); | 1675 | spin_lock_init(&fs_info->block_group_cache_lock); |
1676 | fs_info->block_group_cache_tree.rb_node = NULL; | 1676 | fs_info->block_group_cache_tree = RB_ROOT; |
1677 | 1677 | ||
1678 | extent_io_tree_init(&fs_info->freed_extents[0], | 1678 | extent_io_tree_init(&fs_info->freed_extents[0], |
1679 | fs_info->btree_inode->i_mapping, GFP_NOFS); | 1679 | fs_info->btree_inode->i_mapping, GFP_NOFS); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index b177ed319612..7073cbb1b2d4 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -104,8 +104,8 @@ void extent_io_exit(void) | |||
104 | void extent_io_tree_init(struct extent_io_tree *tree, | 104 | void extent_io_tree_init(struct extent_io_tree *tree, |
105 | struct address_space *mapping, gfp_t mask) | 105 | struct address_space *mapping, gfp_t mask) |
106 | { | 106 | { |
107 | tree->state.rb_node = NULL; | 107 | tree->state = RB_ROOT; |
108 | tree->buffer.rb_node = NULL; | 108 | tree->buffer = RB_ROOT; |
109 | tree->ops = NULL; | 109 | tree->ops = NULL; |
110 | tree->dirty_bytes = 0; | 110 | tree->dirty_bytes = 0; |
111 | spin_lock_init(&tree->lock); | 111 | spin_lock_init(&tree->lock); |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 428fcac45f90..28d87ba60ce8 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -35,7 +35,7 @@ void extent_map_exit(void) | |||
35 | */ | 35 | */ |
36 | void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask) | 36 | void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask) |
37 | { | 37 | { |
38 | tree->map.rb_node = NULL; | 38 | tree->map = RB_ROOT; |
39 | rwlock_init(&tree->lock); | 39 | rwlock_init(&tree->lock); |
40 | } | 40 | } |
41 | 41 | ||
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index cb2849f03251..dd831ed31eea 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -870,7 +870,7 @@ __btrfs_return_cluster_to_free_space( | |||
870 | tree_insert_offset(&block_group->free_space_offset, | 870 | tree_insert_offset(&block_group->free_space_offset, |
871 | entry->offset, &entry->offset_index, 0); | 871 | entry->offset, &entry->offset_index, 0); |
872 | } | 872 | } |
873 | cluster->root.rb_node = NULL; | 873 | cluster->root = RB_ROOT; |
874 | 874 | ||
875 | out: | 875 | out: |
876 | spin_unlock(&cluster->lock); | 876 | spin_unlock(&cluster->lock); |
@@ -1355,7 +1355,7 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster) | |||
1355 | { | 1355 | { |
1356 | spin_lock_init(&cluster->lock); | 1356 | spin_lock_init(&cluster->lock); |
1357 | spin_lock_init(&cluster->refill_lock); | 1357 | spin_lock_init(&cluster->refill_lock); |
1358 | cluster->root.rb_node = NULL; | 1358 | cluster->root = RB_ROOT; |
1359 | cluster->max_size = 0; | 1359 | cluster->max_size = 0; |
1360 | cluster->points_to_bitmap = false; | 1360 | cluster->points_to_bitmap = false; |
1361 | INIT_LIST_HEAD(&cluster->block_group_list); | 1361 | INIT_LIST_HEAD(&cluster->block_group_list); |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 1fe1282ef47c..9116c6d0c5a9 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
@@ -129,7 +129,7 @@ static inline void | |||
129 | btrfs_ordered_inode_tree_init(struct btrfs_ordered_inode_tree *t) | 129 | btrfs_ordered_inode_tree_init(struct btrfs_ordered_inode_tree *t) |
130 | { | 130 | { |
131 | mutex_init(&t->mutex); | 131 | mutex_init(&t->mutex); |
132 | t->tree.rb_node = NULL; | 132 | t->tree = RB_ROOT; |
133 | t->last = NULL; | 133 | t->last = NULL; |
134 | } | 134 | } |
135 | 135 | ||
diff --git a/fs/btrfs/ref-cache.h b/fs/btrfs/ref-cache.h index bc283ad2db73..e2a55cb2072b 100644 --- a/fs/btrfs/ref-cache.h +++ b/fs/btrfs/ref-cache.h | |||
@@ -52,7 +52,7 @@ static inline size_t btrfs_leaf_ref_size(int nr_extents) | |||
52 | 52 | ||
53 | static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree) | 53 | static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree) |
54 | { | 54 | { |
55 | tree->root.rb_node = NULL; | 55 | tree->root = RB_ROOT; |
56 | INIT_LIST_HEAD(&tree->list); | 56 | INIT_LIST_HEAD(&tree->list); |
57 | spin_lock_init(&tree->lock); | 57 | spin_lock_init(&tree->lock); |
58 | } | 58 | } |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index ab7ab5318745..0109e5606bad 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -170,14 +170,14 @@ struct async_merge { | |||
170 | 170 | ||
171 | static void mapping_tree_init(struct mapping_tree *tree) | 171 | static void mapping_tree_init(struct mapping_tree *tree) |
172 | { | 172 | { |
173 | tree->rb_root.rb_node = NULL; | 173 | tree->rb_root = RB_ROOT; |
174 | spin_lock_init(&tree->lock); | 174 | spin_lock_init(&tree->lock); |
175 | } | 175 | } |
176 | 176 | ||
177 | static void backref_cache_init(struct backref_cache *cache) | 177 | static void backref_cache_init(struct backref_cache *cache) |
178 | { | 178 | { |
179 | int i; | 179 | int i; |
180 | cache->rb_root.rb_node = NULL; | 180 | cache->rb_root = RB_ROOT; |
181 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) | 181 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) |
182 | INIT_LIST_HEAD(&cache->pending[i]); | 182 | INIT_LIST_HEAD(&cache->pending[i]); |
183 | spin_lock_init(&cache->lock); | 183 | spin_lock_init(&cache->lock); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8a1ea6e64575..f8b4521de907 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -128,7 +128,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
128 | { | 128 | { |
129 | struct btrfs_fs_info *info = root->fs_info; | 129 | struct btrfs_fs_info *info = root->fs_info; |
130 | substring_t args[MAX_OPT_ARGS]; | 130 | substring_t args[MAX_OPT_ARGS]; |
131 | char *p, *num; | 131 | char *p, *num, *orig; |
132 | int intarg; | 132 | int intarg; |
133 | int ret = 0; | 133 | int ret = 0; |
134 | 134 | ||
@@ -143,6 +143,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
143 | if (!options) | 143 | if (!options) |
144 | return -ENOMEM; | 144 | return -ENOMEM; |
145 | 145 | ||
146 | orig = options; | ||
146 | 147 | ||
147 | while ((p = strsep(&options, ",")) != NULL) { | 148 | while ((p = strsep(&options, ",")) != NULL) { |
148 | int token; | 149 | int token; |
@@ -280,7 +281,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
280 | } | 281 | } |
281 | } | 282 | } |
282 | out: | 283 | out: |
283 | kfree(options); | 284 | kfree(orig); |
284 | return ret; | 285 | return ret; |
285 | } | 286 | } |
286 | 287 | ||
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index a240b6fa81df..4ce16ef702a3 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c | |||
@@ -164,12 +164,12 @@ static void btrfs_root_release(struct kobject *kobj) | |||
164 | complete(&root->kobj_unregister); | 164 | complete(&root->kobj_unregister); |
165 | } | 165 | } |
166 | 166 | ||
167 | static struct sysfs_ops btrfs_super_attr_ops = { | 167 | static const struct sysfs_ops btrfs_super_attr_ops = { |
168 | .show = btrfs_super_attr_show, | 168 | .show = btrfs_super_attr_show, |
169 | .store = btrfs_super_attr_store, | 169 | .store = btrfs_super_attr_store, |
170 | }; | 170 | }; |
171 | 171 | ||
172 | static struct sysfs_ops btrfs_root_attr_ops = { | 172 | static const struct sysfs_ops btrfs_root_attr_ops = { |
173 | .show = btrfs_root_attr_show, | 173 | .show = btrfs_root_attr_show, |
174 | .store = btrfs_root_attr_store, | 174 | .store = btrfs_root_attr_store, |
175 | }; | 175 | }; |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index b2acc79f1b34..2a36e236a492 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -69,7 +69,7 @@ static noinline int join_transaction(struct btrfs_root *root) | |||
69 | cur_trans->commit_done = 0; | 69 | cur_trans->commit_done = 0; |
70 | cur_trans->start_time = get_seconds(); | 70 | cur_trans->start_time = get_seconds(); |
71 | 71 | ||
72 | cur_trans->delayed_refs.root.rb_node = NULL; | 72 | cur_trans->delayed_refs.root = RB_ROOT; |
73 | cur_trans->delayed_refs.num_entries = 0; | 73 | cur_trans->delayed_refs.num_entries = 0; |
74 | cur_trans->delayed_refs.num_heads_ready = 0; | 74 | cur_trans->delayed_refs.num_heads_ready = 0; |
75 | cur_trans->delayed_refs.num_heads = 0; | 75 | cur_trans->delayed_refs.num_heads = 0; |
diff --git a/fs/buffer.c b/fs/buffer.c index 6fa530256bfd..bc3212e0cef9 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -3265,7 +3265,7 @@ static void recalc_bh_state(void) | |||
3265 | 3265 | ||
3266 | struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) | 3266 | struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) |
3267 | { | 3267 | { |
3268 | struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); | 3268 | struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags); |
3269 | if (ret) { | 3269 | if (ret) { |
3270 | INIT_LIST_HEAD(&ret->b_assoc_buffers); | 3270 | INIT_LIST_HEAD(&ret->b_assoc_buffers); |
3271 | get_cpu_var(bh_accounting).nr++; | 3271 | get_cpu_var(bh_accounting).nr++; |
@@ -3352,15 +3352,6 @@ int bh_submit_read(struct buffer_head *bh) | |||
3352 | } | 3352 | } |
3353 | EXPORT_SYMBOL(bh_submit_read); | 3353 | EXPORT_SYMBOL(bh_submit_read); |
3354 | 3354 | ||
3355 | static void | ||
3356 | init_buffer_head(void *data) | ||
3357 | { | ||
3358 | struct buffer_head *bh = data; | ||
3359 | |||
3360 | memset(bh, 0, sizeof(*bh)); | ||
3361 | INIT_LIST_HEAD(&bh->b_assoc_buffers); | ||
3362 | } | ||
3363 | |||
3364 | void __init buffer_init(void) | 3355 | void __init buffer_init(void) |
3365 | { | 3356 | { |
3366 | int nrpages; | 3357 | int nrpages; |
@@ -3369,7 +3360,7 @@ void __init buffer_init(void) | |||
3369 | sizeof(struct buffer_head), 0, | 3360 | sizeof(struct buffer_head), 0, |
3370 | (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC| | 3361 | (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC| |
3371 | SLAB_MEM_SPREAD), | 3362 | SLAB_MEM_SPREAD), |
3372 | init_buffer_head); | 3363 | NULL); |
3373 | 3364 | ||
3374 | /* | 3365 | /* |
3375 | * Limit the bh occupancy to 10% of ZONE_NORMAL | 3366 | * Limit the bh occupancy to 10% of ZONE_NORMAL |
diff --git a/fs/compat.c b/fs/compat.c index 00d90c2e66f0..030602d453b7 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1795,6 +1795,24 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | |||
1795 | return ret; | 1795 | return ret; |
1796 | } | 1796 | } |
1797 | 1797 | ||
1798 | struct compat_sel_arg_struct { | ||
1799 | compat_ulong_t n; | ||
1800 | compat_uptr_t inp; | ||
1801 | compat_uptr_t outp; | ||
1802 | compat_uptr_t exp; | ||
1803 | compat_uptr_t tvp; | ||
1804 | }; | ||
1805 | |||
1806 | asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg) | ||
1807 | { | ||
1808 | struct compat_sel_arg_struct a; | ||
1809 | |||
1810 | if (copy_from_user(&a, arg, sizeof(a))) | ||
1811 | return -EFAULT; | ||
1812 | return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp), | ||
1813 | compat_ptr(a.exp), compat_ptr(a.tvp)); | ||
1814 | } | ||
1815 | |||
1798 | #ifdef HAVE_SET_RESTORE_SIGMASK | 1816 | #ifdef HAVE_SET_RESTORE_SIGMASK |
1799 | static long do_compat_pselect(int n, compat_ulong_t __user *inp, | 1817 | static long do_compat_pselect(int n, compat_ulong_t __user *inp, |
1800 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 1818 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 26a8bd40400a..f994a7dfda85 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -148,7 +148,7 @@ static void lockspace_kobj_release(struct kobject *k) | |||
148 | kfree(ls); | 148 | kfree(ls); |
149 | } | 149 | } |
150 | 150 | ||
151 | static struct sysfs_ops dlm_attr_ops = { | 151 | static const struct sysfs_ops dlm_attr_ops = { |
152 | .show = dlm_attr_show, | 152 | .show = dlm_attr_show, |
153 | .store = dlm_attr_store, | 153 | .store = dlm_attr_store, |
154 | }; | 154 | }; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 2b83b96cb2eb..ce84a6ed4a48 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -2358,7 +2358,7 @@ static void ext4_sb_release(struct kobject *kobj) | |||
2358 | } | 2358 | } |
2359 | 2359 | ||
2360 | 2360 | ||
2361 | static struct sysfs_ops ext4_attr_ops = { | 2361 | static const struct sysfs_ops ext4_attr_ops = { |
2362 | .show = ext4_attr_show, | 2362 | .show = ext4_attr_show, |
2363 | .store = ext4_attr_store, | 2363 | .store = ext4_attr_store, |
2364 | }; | 2364 | }; |
diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig index 864dac20a242..cc94bb9563f2 100644 --- a/fs/fscache/Kconfig +++ b/fs/fscache/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | 1 | ||
2 | config FSCACHE | 2 | config FSCACHE |
3 | tristate "General filesystem local caching manager" | 3 | tristate "General filesystem local caching manager" |
4 | depends on EXPERIMENTAL | ||
5 | select SLOW_WORK | 4 | select SLOW_WORK |
6 | help | 5 | help |
7 | This option enables a generic filesystem caching manager that can be | 6 | This option enables a generic filesystem caching manager that can be |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index b5f1a46133c8..419042f7f0b6 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -49,7 +49,7 @@ static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr, | |||
49 | return a->store ? a->store(sdp, buf, len) : len; | 49 | return a->store ? a->store(sdp, buf, len) : len; |
50 | } | 50 | } |
51 | 51 | ||
52 | static struct sysfs_ops gfs2_attr_ops = { | 52 | static const struct sysfs_ops gfs2_attr_ops = { |
53 | .show = gfs2_attr_show, | 53 | .show = gfs2_attr_show, |
54 | .store = gfs2_attr_store, | 54 | .store = gfs2_attr_store, |
55 | }; | 55 | }; |
@@ -574,7 +574,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, | |||
574 | return 0; | 574 | return 0; |
575 | } | 575 | } |
576 | 576 | ||
577 | static struct kset_uevent_ops gfs2_uevent_ops = { | 577 | static const struct kset_uevent_ops gfs2_uevent_ops = { |
578 | .uevent = gfs2_uevent, | 578 | .uevent = gfs2_uevent, |
579 | }; | 579 | }; |
580 | 580 | ||
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index b39da877b12f..3bb928a2bf7d 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c | |||
@@ -136,7 +136,7 @@ static ssize_t mlog_store(struct kobject *obj, struct attribute *attr, | |||
136 | return mlog_mask_store(mlog_attr->mask, buf, count); | 136 | return mlog_mask_store(mlog_attr->mask, buf, count); |
137 | } | 137 | } |
138 | 138 | ||
139 | static struct sysfs_ops mlog_attr_ops = { | 139 | static const struct sysfs_ops mlog_attr_ops = { |
140 | .show = mlog_show, | 140 | .show = mlog_show, |
141 | .store = mlog_store, | 141 | .store = mlog_store, |
142 | }; | 142 | }; |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index d8d0c65ac03c..73e743eea2c8 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -72,9 +72,9 @@ | |||
72 | 72 | ||
73 | #include "tcp_internal.h" | 73 | #include "tcp_internal.h" |
74 | 74 | ||
75 | #define SC_NODEF_FMT "node %s (num %u) at %u.%u.%u.%u:%u" | 75 | #define SC_NODEF_FMT "node %s (num %u) at %pI4:%u" |
76 | #define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ | 76 | #define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \ |
77 | NIPQUAD(sc->sc_node->nd_ipv4_address), \ | 77 | &sc->sc_node->nd_ipv4_address, \ |
78 | ntohs(sc->sc_node->nd_ipv4_port) | 78 | ntohs(sc->sc_node->nd_ipv4_port) |
79 | 79 | ||
80 | /* | 80 | /* |
diff --git a/fs/select.c b/fs/select.c index 73715e90030f..500a669f7790 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -691,6 +691,23 @@ SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp, | |||
691 | } | 691 | } |
692 | #endif /* HAVE_SET_RESTORE_SIGMASK */ | 692 | #endif /* HAVE_SET_RESTORE_SIGMASK */ |
693 | 693 | ||
694 | #ifdef __ARCH_WANT_SYS_OLD_SELECT | ||
695 | struct sel_arg_struct { | ||
696 | unsigned long n; | ||
697 | fd_set __user *inp, *outp, *exp; | ||
698 | struct timeval __user *tvp; | ||
699 | }; | ||
700 | |||
701 | SYSCALL_DEFINE1(old_select, struct sel_arg_struct __user *, arg) | ||
702 | { | ||
703 | struct sel_arg_struct a; | ||
704 | |||
705 | if (copy_from_user(&a, arg, sizeof(a))) | ||
706 | return -EFAULT; | ||
707 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
708 | } | ||
709 | #endif | ||
710 | |||
694 | struct poll_list { | 711 | struct poll_list { |
695 | struct poll_list *next; | 712 | struct poll_list *next; |
696 | int len; | 713 | int len; |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index a0a500af24a1..e9d293593e52 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -54,14 +54,14 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) | |||
54 | int rc; | 54 | int rc; |
55 | 55 | ||
56 | /* need attr_sd for attr, its parent for kobj */ | 56 | /* need attr_sd for attr, its parent for kobj */ |
57 | if (!sysfs_get_active_two(attr_sd)) | 57 | if (!sysfs_get_active(attr_sd)) |
58 | return -ENODEV; | 58 | return -ENODEV; |
59 | 59 | ||
60 | rc = -EIO; | 60 | rc = -EIO; |
61 | if (attr->read) | 61 | if (attr->read) |
62 | rc = attr->read(kobj, attr, buffer, off, count); | 62 | rc = attr->read(kobj, attr, buffer, off, count); |
63 | 63 | ||
64 | sysfs_put_active_two(attr_sd); | 64 | sysfs_put_active(attr_sd); |
65 | 65 | ||
66 | return rc; | 66 | return rc; |
67 | } | 67 | } |
@@ -125,14 +125,14 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) | |||
125 | int rc; | 125 | int rc; |
126 | 126 | ||
127 | /* need attr_sd for attr, its parent for kobj */ | 127 | /* need attr_sd for attr, its parent for kobj */ |
128 | if (!sysfs_get_active_two(attr_sd)) | 128 | if (!sysfs_get_active(attr_sd)) |
129 | return -ENODEV; | 129 | return -ENODEV; |
130 | 130 | ||
131 | rc = -EIO; | 131 | rc = -EIO; |
132 | if (attr->write) | 132 | if (attr->write) |
133 | rc = attr->write(kobj, attr, buffer, offset, count); | 133 | rc = attr->write(kobj, attr, buffer, offset, count); |
134 | 134 | ||
135 | sysfs_put_active_two(attr_sd); | 135 | sysfs_put_active(attr_sd); |
136 | 136 | ||
137 | return rc; | 137 | return rc; |
138 | } | 138 | } |
@@ -184,12 +184,12 @@ static void bin_vma_open(struct vm_area_struct *vma) | |||
184 | if (!bb->vm_ops || !bb->vm_ops->open) | 184 | if (!bb->vm_ops || !bb->vm_ops->open) |
185 | return; | 185 | return; |
186 | 186 | ||
187 | if (!sysfs_get_active_two(attr_sd)) | 187 | if (!sysfs_get_active(attr_sd)) |
188 | return; | 188 | return; |
189 | 189 | ||
190 | bb->vm_ops->open(vma); | 190 | bb->vm_ops->open(vma); |
191 | 191 | ||
192 | sysfs_put_active_two(attr_sd); | 192 | sysfs_put_active(attr_sd); |
193 | } | 193 | } |
194 | 194 | ||
195 | static void bin_vma_close(struct vm_area_struct *vma) | 195 | static void bin_vma_close(struct vm_area_struct *vma) |
@@ -201,12 +201,12 @@ static void bin_vma_close(struct vm_area_struct *vma) | |||
201 | if (!bb->vm_ops || !bb->vm_ops->close) | 201 | if (!bb->vm_ops || !bb->vm_ops->close) |
202 | return; | 202 | return; |
203 | 203 | ||
204 | if (!sysfs_get_active_two(attr_sd)) | 204 | if (!sysfs_get_active(attr_sd)) |
205 | return; | 205 | return; |
206 | 206 | ||
207 | bb->vm_ops->close(vma); | 207 | bb->vm_ops->close(vma); |
208 | 208 | ||
209 | sysfs_put_active_two(attr_sd); | 209 | sysfs_put_active(attr_sd); |
210 | } | 210 | } |
211 | 211 | ||
212 | static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 212 | static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
@@ -219,12 +219,12 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
219 | if (!bb->vm_ops || !bb->vm_ops->fault) | 219 | if (!bb->vm_ops || !bb->vm_ops->fault) |
220 | return VM_FAULT_SIGBUS; | 220 | return VM_FAULT_SIGBUS; |
221 | 221 | ||
222 | if (!sysfs_get_active_two(attr_sd)) | 222 | if (!sysfs_get_active(attr_sd)) |
223 | return VM_FAULT_SIGBUS; | 223 | return VM_FAULT_SIGBUS; |
224 | 224 | ||
225 | ret = bb->vm_ops->fault(vma, vmf); | 225 | ret = bb->vm_ops->fault(vma, vmf); |
226 | 226 | ||
227 | sysfs_put_active_two(attr_sd); | 227 | sysfs_put_active(attr_sd); |
228 | return ret; | 228 | return ret; |
229 | } | 229 | } |
230 | 230 | ||
@@ -241,12 +241,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
241 | if (!bb->vm_ops->page_mkwrite) | 241 | if (!bb->vm_ops->page_mkwrite) |
242 | return 0; | 242 | return 0; |
243 | 243 | ||
244 | if (!sysfs_get_active_two(attr_sd)) | 244 | if (!sysfs_get_active(attr_sd)) |
245 | return VM_FAULT_SIGBUS; | 245 | return VM_FAULT_SIGBUS; |
246 | 246 | ||
247 | ret = bb->vm_ops->page_mkwrite(vma, vmf); | 247 | ret = bb->vm_ops->page_mkwrite(vma, vmf); |
248 | 248 | ||
249 | sysfs_put_active_two(attr_sd); | 249 | sysfs_put_active(attr_sd); |
250 | return ret; | 250 | return ret; |
251 | } | 251 | } |
252 | 252 | ||
@@ -261,12 +261,12 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr, | |||
261 | if (!bb->vm_ops || !bb->vm_ops->access) | 261 | if (!bb->vm_ops || !bb->vm_ops->access) |
262 | return -EINVAL; | 262 | return -EINVAL; |
263 | 263 | ||
264 | if (!sysfs_get_active_two(attr_sd)) | 264 | if (!sysfs_get_active(attr_sd)) |
265 | return -EINVAL; | 265 | return -EINVAL; |
266 | 266 | ||
267 | ret = bb->vm_ops->access(vma, addr, buf, len, write); | 267 | ret = bb->vm_ops->access(vma, addr, buf, len, write); |
268 | 268 | ||
269 | sysfs_put_active_two(attr_sd); | 269 | sysfs_put_active(attr_sd); |
270 | return ret; | 270 | return ret; |
271 | } | 271 | } |
272 | 272 | ||
@@ -281,12 +281,12 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new) | |||
281 | if (!bb->vm_ops || !bb->vm_ops->set_policy) | 281 | if (!bb->vm_ops || !bb->vm_ops->set_policy) |
282 | return 0; | 282 | return 0; |
283 | 283 | ||
284 | if (!sysfs_get_active_two(attr_sd)) | 284 | if (!sysfs_get_active(attr_sd)) |
285 | return -EINVAL; | 285 | return -EINVAL; |
286 | 286 | ||
287 | ret = bb->vm_ops->set_policy(vma, new); | 287 | ret = bb->vm_ops->set_policy(vma, new); |
288 | 288 | ||
289 | sysfs_put_active_two(attr_sd); | 289 | sysfs_put_active(attr_sd); |
290 | return ret; | 290 | return ret; |
291 | } | 291 | } |
292 | 292 | ||
@@ -301,12 +301,12 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma, | |||
301 | if (!bb->vm_ops || !bb->vm_ops->get_policy) | 301 | if (!bb->vm_ops || !bb->vm_ops->get_policy) |
302 | return vma->vm_policy; | 302 | return vma->vm_policy; |
303 | 303 | ||
304 | if (!sysfs_get_active_two(attr_sd)) | 304 | if (!sysfs_get_active(attr_sd)) |
305 | return vma->vm_policy; | 305 | return vma->vm_policy; |
306 | 306 | ||
307 | pol = bb->vm_ops->get_policy(vma, addr); | 307 | pol = bb->vm_ops->get_policy(vma, addr); |
308 | 308 | ||
309 | sysfs_put_active_two(attr_sd); | 309 | sysfs_put_active(attr_sd); |
310 | return pol; | 310 | return pol; |
311 | } | 311 | } |
312 | 312 | ||
@@ -321,12 +321,12 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from, | |||
321 | if (!bb->vm_ops || !bb->vm_ops->migrate) | 321 | if (!bb->vm_ops || !bb->vm_ops->migrate) |
322 | return 0; | 322 | return 0; |
323 | 323 | ||
324 | if (!sysfs_get_active_two(attr_sd)) | 324 | if (!sysfs_get_active(attr_sd)) |
325 | return 0; | 325 | return 0; |
326 | 326 | ||
327 | ret = bb->vm_ops->migrate(vma, from, to, flags); | 327 | ret = bb->vm_ops->migrate(vma, from, to, flags); |
328 | 328 | ||
329 | sysfs_put_active_two(attr_sd); | 329 | sysfs_put_active(attr_sd); |
330 | return ret; | 330 | return ret; |
331 | } | 331 | } |
332 | #endif | 332 | #endif |
@@ -356,7 +356,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma) | |||
356 | 356 | ||
357 | /* need attr_sd for attr, its parent for kobj */ | 357 | /* need attr_sd for attr, its parent for kobj */ |
358 | rc = -ENODEV; | 358 | rc = -ENODEV; |
359 | if (!sysfs_get_active_two(attr_sd)) | 359 | if (!sysfs_get_active(attr_sd)) |
360 | goto out_unlock; | 360 | goto out_unlock; |
361 | 361 | ||
362 | rc = -EINVAL; | 362 | rc = -EINVAL; |
@@ -384,7 +384,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma) | |||
384 | bb->vm_ops = vma->vm_ops; | 384 | bb->vm_ops = vma->vm_ops; |
385 | vma->vm_ops = &bin_vm_ops; | 385 | vma->vm_ops = &bin_vm_ops; |
386 | out_put: | 386 | out_put: |
387 | sysfs_put_active_two(attr_sd); | 387 | sysfs_put_active(attr_sd); |
388 | out_unlock: | 388 | out_unlock: |
389 | mutex_unlock(&bb->mutex); | 389 | mutex_unlock(&bb->mutex); |
390 | 390 | ||
@@ -399,7 +399,7 @@ static int open(struct inode * inode, struct file * file) | |||
399 | int error; | 399 | int error; |
400 | 400 | ||
401 | /* binary file operations requires both @sd and its parent */ | 401 | /* binary file operations requires both @sd and its parent */ |
402 | if (!sysfs_get_active_two(attr_sd)) | 402 | if (!sysfs_get_active(attr_sd)) |
403 | return -ENODEV; | 403 | return -ENODEV; |
404 | 404 | ||
405 | error = -EACCES; | 405 | error = -EACCES; |
@@ -426,11 +426,11 @@ static int open(struct inode * inode, struct file * file) | |||
426 | mutex_unlock(&sysfs_bin_lock); | 426 | mutex_unlock(&sysfs_bin_lock); |
427 | 427 | ||
428 | /* open succeeded, put active references */ | 428 | /* open succeeded, put active references */ |
429 | sysfs_put_active_two(attr_sd); | 429 | sysfs_put_active(attr_sd); |
430 | return 0; | 430 | return 0; |
431 | 431 | ||
432 | err_out: | 432 | err_out: |
433 | sysfs_put_active_two(attr_sd); | 433 | sysfs_put_active(attr_sd); |
434 | kfree(bb); | 434 | kfree(bb); |
435 | return error; | 435 | return error; |
436 | } | 436 | } |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 699f371b9f12..590717861c7a 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -93,7 +93,7 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) | |||
93 | * RETURNS: | 93 | * RETURNS: |
94 | * Pointer to @sd on success, NULL on failure. | 94 | * Pointer to @sd on success, NULL on failure. |
95 | */ | 95 | */ |
96 | static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | 96 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) |
97 | { | 97 | { |
98 | if (unlikely(!sd)) | 98 | if (unlikely(!sd)) |
99 | return NULL; | 99 | return NULL; |
@@ -124,7 +124,7 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | |||
124 | * Put an active reference to @sd. This function is noop if @sd | 124 | * Put an active reference to @sd. This function is noop if @sd |
125 | * is NULL. | 125 | * is NULL. |
126 | */ | 126 | */ |
127 | static void sysfs_put_active(struct sysfs_dirent *sd) | 127 | void sysfs_put_active(struct sysfs_dirent *sd) |
128 | { | 128 | { |
129 | struct completion *cmpl; | 129 | struct completion *cmpl; |
130 | int v; | 130 | int v; |
@@ -145,45 +145,6 @@ static void sysfs_put_active(struct sysfs_dirent *sd) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | /** | 147 | /** |
148 | * sysfs_get_active_two - get active references to sysfs_dirent and parent | ||
149 | * @sd: sysfs_dirent of interest | ||
150 | * | ||
151 | * Get active reference to @sd and its parent. Parent's active | ||
152 | * reference is grabbed first. This function is noop if @sd is | ||
153 | * NULL. | ||
154 | * | ||
155 | * RETURNS: | ||
156 | * Pointer to @sd on success, NULL on failure. | ||
157 | */ | ||
158 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd) | ||
159 | { | ||
160 | if (sd) { | ||
161 | if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent))) | ||
162 | return NULL; | ||
163 | if (unlikely(!sysfs_get_active(sd))) { | ||
164 | sysfs_put_active(sd->s_parent); | ||
165 | return NULL; | ||
166 | } | ||
167 | } | ||
168 | return sd; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * sysfs_put_active_two - put active references to sysfs_dirent and parent | ||
173 | * @sd: sysfs_dirent of interest | ||
174 | * | ||
175 | * Put active references to @sd and its parent. This function is | ||
176 | * noop if @sd is NULL. | ||
177 | */ | ||
178 | void sysfs_put_active_two(struct sysfs_dirent *sd) | ||
179 | { | ||
180 | if (sd) { | ||
181 | sysfs_put_active(sd); | ||
182 | sysfs_put_active(sd->s_parent); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * sysfs_deactivate - deactivate sysfs_dirent | 148 | * sysfs_deactivate - deactivate sysfs_dirent |
188 | * @sd: sysfs_dirent to deactivate | 149 | * @sd: sysfs_dirent to deactivate |
189 | * | 150 | * |
@@ -195,6 +156,10 @@ static void sysfs_deactivate(struct sysfs_dirent *sd) | |||
195 | int v; | 156 | int v; |
196 | 157 | ||
197 | BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED)); | 158 | BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED)); |
159 | |||
160 | if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF)) | ||
161 | return; | ||
162 | |||
198 | sd->s_sibling = (void *)&wait; | 163 | sd->s_sibling = (void *)&wait; |
199 | 164 | ||
200 | rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); | 165 | rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); |
@@ -354,7 +319,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | |||
354 | 319 | ||
355 | atomic_set(&sd->s_count, 1); | 320 | atomic_set(&sd->s_count, 1); |
356 | atomic_set(&sd->s_active, 0); | 321 | atomic_set(&sd->s_active, 0); |
357 | sysfs_dirent_init_lockdep(sd); | ||
358 | 322 | ||
359 | sd->s_name = name; | 323 | sd->s_name = name; |
360 | sd->s_mode = mode; | 324 | sd->s_mode = mode; |
@@ -681,7 +645,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
681 | } | 645 | } |
682 | 646 | ||
683 | /* attach dentry and inode */ | 647 | /* attach dentry and inode */ |
684 | inode = sysfs_get_inode(sd); | 648 | inode = sysfs_get_inode(dir->i_sb, sd); |
685 | if (!inode) { | 649 | if (!inode) { |
686 | ret = ERR_PTR(-ENOMEM); | 650 | ret = ERR_PTR(-ENOMEM); |
687 | goto out_unlock; | 651 | goto out_unlock; |
@@ -837,11 +801,46 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd) | |||
837 | return (sd->s_mode >> 12) & 15; | 801 | return (sd->s_mode >> 12) & 15; |
838 | } | 802 | } |
839 | 803 | ||
804 | static int sysfs_dir_release(struct inode *inode, struct file *filp) | ||
805 | { | ||
806 | sysfs_put(filp->private_data); | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd, | ||
811 | ino_t ino, struct sysfs_dirent *pos) | ||
812 | { | ||
813 | if (pos) { | ||
814 | int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && | ||
815 | pos->s_parent == parent_sd && | ||
816 | ino == pos->s_ino; | ||
817 | sysfs_put(pos); | ||
818 | if (valid) | ||
819 | return pos; | ||
820 | } | ||
821 | pos = NULL; | ||
822 | if ((ino > 1) && (ino < INT_MAX)) { | ||
823 | pos = parent_sd->s_dir.children; | ||
824 | while (pos && (ino > pos->s_ino)) | ||
825 | pos = pos->s_sibling; | ||
826 | } | ||
827 | return pos; | ||
828 | } | ||
829 | |||
830 | static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd, | ||
831 | ino_t ino, struct sysfs_dirent *pos) | ||
832 | { | ||
833 | pos = sysfs_dir_pos(parent_sd, ino, pos); | ||
834 | if (pos) | ||
835 | pos = pos->s_sibling; | ||
836 | return pos; | ||
837 | } | ||
838 | |||
840 | static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | 839 | static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) |
841 | { | 840 | { |
842 | struct dentry *dentry = filp->f_path.dentry; | 841 | struct dentry *dentry = filp->f_path.dentry; |
843 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 842 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
844 | struct sysfs_dirent *pos; | 843 | struct sysfs_dirent *pos = filp->private_data; |
845 | ino_t ino; | 844 | ino_t ino; |
846 | 845 | ||
847 | if (filp->f_pos == 0) { | 846 | if (filp->f_pos == 0) { |
@@ -857,29 +856,31 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
857 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) | 856 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) |
858 | filp->f_pos++; | 857 | filp->f_pos++; |
859 | } | 858 | } |
860 | if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { | 859 | mutex_lock(&sysfs_mutex); |
861 | mutex_lock(&sysfs_mutex); | 860 | for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos); |
862 | 861 | pos; | |
863 | /* Skip the dentries we have already reported */ | 862 | pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) { |
864 | pos = parent_sd->s_dir.children; | 863 | const char * name; |
865 | while (pos && (filp->f_pos > pos->s_ino)) | 864 | unsigned int type; |
866 | pos = pos->s_sibling; | 865 | int len, ret; |
867 | 866 | ||
868 | for ( ; pos; pos = pos->s_sibling) { | 867 | name = pos->s_name; |
869 | const char * name; | 868 | len = strlen(name); |
870 | int len; | 869 | ino = pos->s_ino; |
871 | 870 | type = dt_type(pos); | |
872 | name = pos->s_name; | 871 | filp->f_pos = ino; |
873 | len = strlen(name); | 872 | filp->private_data = sysfs_get(pos); |
874 | filp->f_pos = ino = pos->s_ino; | ||
875 | 873 | ||
876 | if (filldir(dirent, name, len, filp->f_pos, ino, | ||
877 | dt_type(pos)) < 0) | ||
878 | break; | ||
879 | } | ||
880 | if (!pos) | ||
881 | filp->f_pos = INT_MAX; | ||
882 | mutex_unlock(&sysfs_mutex); | 874 | mutex_unlock(&sysfs_mutex); |
875 | ret = filldir(dirent, name, len, filp->f_pos, ino, type); | ||
876 | mutex_lock(&sysfs_mutex); | ||
877 | if (ret < 0) | ||
878 | break; | ||
879 | } | ||
880 | mutex_unlock(&sysfs_mutex); | ||
881 | if ((filp->f_pos > 1) && !pos) { /* EOF */ | ||
882 | filp->f_pos = INT_MAX; | ||
883 | filp->private_data = NULL; | ||
883 | } | 884 | } |
884 | return 0; | 885 | return 0; |
885 | } | 886 | } |
@@ -888,5 +889,6 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
888 | const struct file_operations sysfs_dir_operations = { | 889 | const struct file_operations sysfs_dir_operations = { |
889 | .read = generic_read_dir, | 890 | .read = generic_read_dir, |
890 | .readdir = sysfs_readdir, | 891 | .readdir = sysfs_readdir, |
892 | .release = sysfs_dir_release, | ||
891 | .llseek = generic_file_llseek, | 893 | .llseek = generic_file_llseek, |
892 | }; | 894 | }; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index dc30d9e31683..e222b2582746 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -53,7 +53,7 @@ struct sysfs_buffer { | |||
53 | size_t count; | 53 | size_t count; |
54 | loff_t pos; | 54 | loff_t pos; |
55 | char * page; | 55 | char * page; |
56 | struct sysfs_ops * ops; | 56 | const struct sysfs_ops * ops; |
57 | struct mutex mutex; | 57 | struct mutex mutex; |
58 | int needs_read_fill; | 58 | int needs_read_fill; |
59 | int event; | 59 | int event; |
@@ -75,7 +75,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
75 | { | 75 | { |
76 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 76 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
77 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 77 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
78 | struct sysfs_ops * ops = buffer->ops; | 78 | const struct sysfs_ops * ops = buffer->ops; |
79 | int ret = 0; | 79 | int ret = 0; |
80 | ssize_t count; | 80 | ssize_t count; |
81 | 81 | ||
@@ -85,13 +85,13 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
85 | return -ENOMEM; | 85 | return -ENOMEM; |
86 | 86 | ||
87 | /* need attr_sd for attr and ops, its parent for kobj */ | 87 | /* need attr_sd for attr and ops, its parent for kobj */ |
88 | if (!sysfs_get_active_two(attr_sd)) | 88 | if (!sysfs_get_active(attr_sd)) |
89 | return -ENODEV; | 89 | return -ENODEV; |
90 | 90 | ||
91 | buffer->event = atomic_read(&attr_sd->s_attr.open->event); | 91 | buffer->event = atomic_read(&attr_sd->s_attr.open->event); |
92 | count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); | 92 | count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); |
93 | 93 | ||
94 | sysfs_put_active_two(attr_sd); | 94 | sysfs_put_active(attr_sd); |
95 | 95 | ||
96 | /* | 96 | /* |
97 | * The code works fine with PAGE_SIZE return but it's likely to | 97 | * The code works fine with PAGE_SIZE return but it's likely to |
@@ -199,16 +199,16 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t | |||
199 | { | 199 | { |
200 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 200 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
201 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 201 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
202 | struct sysfs_ops * ops = buffer->ops; | 202 | const struct sysfs_ops * ops = buffer->ops; |
203 | int rc; | 203 | int rc; |
204 | 204 | ||
205 | /* need attr_sd for attr and ops, its parent for kobj */ | 205 | /* need attr_sd for attr and ops, its parent for kobj */ |
206 | if (!sysfs_get_active_two(attr_sd)) | 206 | if (!sysfs_get_active(attr_sd)) |
207 | return -ENODEV; | 207 | return -ENODEV; |
208 | 208 | ||
209 | rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count); | 209 | rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count); |
210 | 210 | ||
211 | sysfs_put_active_two(attr_sd); | 211 | sysfs_put_active(attr_sd); |
212 | 212 | ||
213 | return rc; | 213 | return rc; |
214 | } | 214 | } |
@@ -335,7 +335,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
335 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 335 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
336 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; | 336 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
337 | struct sysfs_buffer *buffer; | 337 | struct sysfs_buffer *buffer; |
338 | struct sysfs_ops *ops; | 338 | const struct sysfs_ops *ops; |
339 | int error = -EACCES; | 339 | int error = -EACCES; |
340 | char *p; | 340 | char *p; |
341 | 341 | ||
@@ -344,7 +344,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
344 | memmove(last_sysfs_file, p, strlen(p) + 1); | 344 | memmove(last_sysfs_file, p, strlen(p) + 1); |
345 | 345 | ||
346 | /* need attr_sd for attr and ops, its parent for kobj */ | 346 | /* need attr_sd for attr and ops, its parent for kobj */ |
347 | if (!sysfs_get_active_two(attr_sd)) | 347 | if (!sysfs_get_active(attr_sd)) |
348 | return -ENODEV; | 348 | return -ENODEV; |
349 | 349 | ||
350 | /* every kobject with an attribute needs a ktype assigned */ | 350 | /* every kobject with an attribute needs a ktype assigned */ |
@@ -393,13 +393,13 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
393 | goto err_free; | 393 | goto err_free; |
394 | 394 | ||
395 | /* open succeeded, put active references */ | 395 | /* open succeeded, put active references */ |
396 | sysfs_put_active_two(attr_sd); | 396 | sysfs_put_active(attr_sd); |
397 | return 0; | 397 | return 0; |
398 | 398 | ||
399 | err_free: | 399 | err_free: |
400 | kfree(buffer); | 400 | kfree(buffer); |
401 | err_out: | 401 | err_out: |
402 | sysfs_put_active_two(attr_sd); | 402 | sysfs_put_active(attr_sd); |
403 | return error; | 403 | return error; |
404 | } | 404 | } |
405 | 405 | ||
@@ -437,12 +437,12 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait) | |||
437 | struct sysfs_open_dirent *od = attr_sd->s_attr.open; | 437 | struct sysfs_open_dirent *od = attr_sd->s_attr.open; |
438 | 438 | ||
439 | /* need parent for the kobj, grab both */ | 439 | /* need parent for the kobj, grab both */ |
440 | if (!sysfs_get_active_two(attr_sd)) | 440 | if (!sysfs_get_active(attr_sd)) |
441 | goto trigger; | 441 | goto trigger; |
442 | 442 | ||
443 | poll_wait(filp, &od->poll, wait); | 443 | poll_wait(filp, &od->poll, wait); |
444 | 444 | ||
445 | sysfs_put_active_two(attr_sd); | 445 | sysfs_put_active(attr_sd); |
446 | 446 | ||
447 | if (buffer->event != atomic_read(&od->event)) | 447 | if (buffer->event != atomic_read(&od->event)) |
448 | goto trigger; | 448 | goto trigger; |
@@ -509,6 +509,7 @@ int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, | |||
509 | if (!sd) | 509 | if (!sd) |
510 | return -ENOMEM; | 510 | return -ENOMEM; |
511 | sd->s_attr.attr = (void *)attr; | 511 | sd->s_attr.attr = (void *)attr; |
512 | sysfs_dirent_init_lockdep(sd); | ||
512 | 513 | ||
513 | sysfs_addrm_start(&acxt, dir_sd); | 514 | sysfs_addrm_start(&acxt, dir_sd); |
514 | rc = sysfs_add_one(&acxt, sd); | 515 | rc = sysfs_add_one(&acxt, sd); |
@@ -542,6 +543,18 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) | |||
542 | 543 | ||
543 | } | 544 | } |
544 | 545 | ||
546 | int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr) | ||
547 | { | ||
548 | int err = 0; | ||
549 | int i; | ||
550 | |||
551 | for (i = 0; ptr[i] && !err; i++) | ||
552 | err = sysfs_create_file(kobj, ptr[i]); | ||
553 | if (err) | ||
554 | while (--i >= 0) | ||
555 | sysfs_remove_file(kobj, ptr[i]); | ||
556 | return err; | ||
557 | } | ||
545 | 558 | ||
546 | /** | 559 | /** |
547 | * sysfs_add_file_to_group - add an attribute file to a pre-existing group. | 560 | * sysfs_add_file_to_group - add an attribute file to a pre-existing group. |
@@ -614,6 +627,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | |||
614 | sysfs_hash_and_remove(kobj->sd, attr->name); | 627 | sysfs_hash_and_remove(kobj->sd, attr->name); |
615 | } | 628 | } |
616 | 629 | ||
630 | void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) | ||
631 | { | ||
632 | int i; | ||
633 | for (i = 0; ptr[i]; i++) | ||
634 | sysfs_remove_file(kobj, ptr[i]); | ||
635 | } | ||
617 | 636 | ||
618 | /** | 637 | /** |
619 | * sysfs_remove_file_from_group - remove an attribute file from a group. | 638 | * sysfs_remove_file_from_group - remove an attribute file from a group. |
@@ -732,3 +751,5 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback); | |||
732 | 751 | ||
733 | EXPORT_SYMBOL_GPL(sysfs_create_file); | 752 | EXPORT_SYMBOL_GPL(sysfs_create_file); |
734 | EXPORT_SYMBOL_GPL(sysfs_remove_file); | 753 | EXPORT_SYMBOL_GPL(sysfs_remove_file); |
754 | EXPORT_SYMBOL_GPL(sysfs_remove_files); | ||
755 | EXPORT_SYMBOL_GPL(sysfs_create_files); | ||
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 6a06a1d1ea7b..082daaecac1b 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -111,20 +111,20 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
111 | if (!sd) | 111 | if (!sd) |
112 | return -EINVAL; | 112 | return -EINVAL; |
113 | 113 | ||
114 | mutex_lock(&sysfs_mutex); | ||
114 | error = inode_change_ok(inode, iattr); | 115 | error = inode_change_ok(inode, iattr); |
115 | if (error) | 116 | if (error) |
116 | return error; | 117 | goto out; |
117 | 118 | ||
118 | iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ | 119 | iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ |
119 | 120 | ||
120 | error = inode_setattr(inode, iattr); | 121 | error = inode_setattr(inode, iattr); |
121 | if (error) | 122 | if (error) |
122 | return error; | 123 | goto out; |
123 | 124 | ||
124 | mutex_lock(&sysfs_mutex); | ||
125 | error = sysfs_sd_setattr(sd, iattr); | 125 | error = sysfs_sd_setattr(sd, iattr); |
126 | out: | ||
126 | mutex_unlock(&sysfs_mutex); | 127 | mutex_unlock(&sysfs_mutex); |
127 | |||
128 | return error; | 128 | return error; |
129 | } | 129 | } |
130 | 130 | ||
@@ -283,6 +283,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | |||
283 | 283 | ||
284 | /** | 284 | /** |
285 | * sysfs_get_inode - get inode for sysfs_dirent | 285 | * sysfs_get_inode - get inode for sysfs_dirent |
286 | * @sb: super block | ||
286 | * @sd: sysfs_dirent to allocate inode for | 287 | * @sd: sysfs_dirent to allocate inode for |
287 | * | 288 | * |
288 | * Get inode for @sd. If such inode doesn't exist, a new inode | 289 | * Get inode for @sd. If such inode doesn't exist, a new inode |
@@ -295,11 +296,11 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | |||
295 | * RETURNS: | 296 | * RETURNS: |
296 | * Pointer to allocated inode on success, NULL on failure. | 297 | * Pointer to allocated inode on success, NULL on failure. |
297 | */ | 298 | */ |
298 | struct inode * sysfs_get_inode(struct sysfs_dirent *sd) | 299 | struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd) |
299 | { | 300 | { |
300 | struct inode *inode; | 301 | struct inode *inode; |
301 | 302 | ||
302 | inode = iget_locked(sysfs_sb, sd->s_ino); | 303 | inode = iget_locked(sb, sd->s_ino); |
303 | if (inode && (inode->i_state & I_NEW)) | 304 | if (inode && (inode->i_state & I_NEW)) |
304 | sysfs_init_inode(sd, inode); | 305 | sysfs_init_inode(sd, inode); |
305 | 306 | ||
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 49749955ccaf..0cb10884a2fc 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | 24 | ||
25 | static struct vfsmount *sysfs_mount; | 25 | static struct vfsmount *sysfs_mount; |
26 | struct super_block * sysfs_sb = NULL; | ||
27 | struct kmem_cache *sysfs_dir_cachep; | 26 | struct kmem_cache *sysfs_dir_cachep; |
28 | 27 | ||
29 | static const struct super_operations sysfs_ops = { | 28 | static const struct super_operations sysfs_ops = { |
@@ -50,11 +49,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
50 | sb->s_magic = SYSFS_MAGIC; | 49 | sb->s_magic = SYSFS_MAGIC; |
51 | sb->s_op = &sysfs_ops; | 50 | sb->s_op = &sysfs_ops; |
52 | sb->s_time_gran = 1; | 51 | sb->s_time_gran = 1; |
53 | sysfs_sb = sb; | ||
54 | 52 | ||
55 | /* get root inode, initialize and unlock it */ | 53 | /* get root inode, initialize and unlock it */ |
56 | mutex_lock(&sysfs_mutex); | 54 | mutex_lock(&sysfs_mutex); |
57 | inode = sysfs_get_inode(&sysfs_root); | 55 | inode = sysfs_get_inode(sb, &sysfs_root); |
58 | mutex_unlock(&sysfs_mutex); | 56 | mutex_unlock(&sysfs_mutex); |
59 | if (!inode) { | 57 | if (!inode) { |
60 | pr_debug("sysfs: could not get root inode\n"); | 58 | pr_debug("sysfs: could not get root inode\n"); |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index c5eff49fa41b..1b9a3a1e8a17 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -123,6 +123,44 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) | |||
123 | sysfs_hash_and_remove(parent_sd, name); | 123 | sysfs_hash_and_remove(parent_sd, name); |
124 | } | 124 | } |
125 | 125 | ||
126 | /** | ||
127 | * sysfs_rename_link - rename symlink in object's directory. | ||
128 | * @kobj: object we're acting for. | ||
129 | * @targ: object we're pointing to. | ||
130 | * @old: previous name of the symlink. | ||
131 | * @new: new name of the symlink. | ||
132 | * | ||
133 | * A helper function for the common rename symlink idiom. | ||
134 | */ | ||
135 | int sysfs_rename_link(struct kobject *kobj, struct kobject *targ, | ||
136 | const char *old, const char *new) | ||
137 | { | ||
138 | struct sysfs_dirent *parent_sd, *sd = NULL; | ||
139 | int result; | ||
140 | |||
141 | if (!kobj) | ||
142 | parent_sd = &sysfs_root; | ||
143 | else | ||
144 | parent_sd = kobj->sd; | ||
145 | |||
146 | result = -ENOENT; | ||
147 | sd = sysfs_get_dirent(parent_sd, old); | ||
148 | if (!sd) | ||
149 | goto out; | ||
150 | |||
151 | result = -EINVAL; | ||
152 | if (sysfs_type(sd) != SYSFS_KOBJ_LINK) | ||
153 | goto out; | ||
154 | if (sd->s_symlink.target_sd->s_dir.kobj != targ) | ||
155 | goto out; | ||
156 | |||
157 | result = sysfs_rename(sd, parent_sd, new); | ||
158 | |||
159 | out: | ||
160 | sysfs_put(sd); | ||
161 | return result; | ||
162 | } | ||
163 | |||
126 | static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, | 164 | static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, |
127 | struct sysfs_dirent *target_sd, char *path) | 165 | struct sysfs_dirent *target_sd, char *path) |
128 | { | 166 | { |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index cdd9377a6e06..30f5a44fb5d3 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -66,8 +66,8 @@ struct sysfs_dirent { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | unsigned int s_flags; | 68 | unsigned int s_flags; |
69 | unsigned short s_mode; | ||
69 | ino_t s_ino; | 70 | ino_t s_ino; |
70 | umode_t s_mode; | ||
71 | struct sysfs_inode_attrs *s_iattr; | 71 | struct sysfs_inode_attrs *s_iattr; |
72 | }; | 72 | }; |
73 | 73 | ||
@@ -79,6 +79,7 @@ struct sysfs_dirent { | |||
79 | #define SYSFS_KOBJ_BIN_ATTR 0x0004 | 79 | #define SYSFS_KOBJ_BIN_ATTR 0x0004 |
80 | #define SYSFS_KOBJ_LINK 0x0008 | 80 | #define SYSFS_KOBJ_LINK 0x0008 |
81 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) | 81 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) |
82 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) | ||
82 | 83 | ||
83 | #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK | 84 | #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK |
84 | #define SYSFS_FLAG_REMOVED 0x0200 | 85 | #define SYSFS_FLAG_REMOVED 0x0200 |
@@ -91,9 +92,12 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | |||
91 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 92 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
92 | #define sysfs_dirent_init_lockdep(sd) \ | 93 | #define sysfs_dirent_init_lockdep(sd) \ |
93 | do { \ | 94 | do { \ |
94 | static struct lock_class_key __key; \ | 95 | struct attribute *attr = sd->s_attr.attr; \ |
96 | struct lock_class_key *key = attr->key; \ | ||
97 | if (!key) \ | ||
98 | key = &attr->skey; \ | ||
95 | \ | 99 | \ |
96 | lockdep_init_map(&sd->dep_map, "s_active", &__key, 0); \ | 100 | lockdep_init_map(&sd->dep_map, "s_active", key, 0); \ |
97 | } while(0) | 101 | } while(0) |
98 | #else | 102 | #else |
99 | #define sysfs_dirent_init_lockdep(sd) do {} while(0) | 103 | #define sysfs_dirent_init_lockdep(sd) do {} while(0) |
@@ -111,7 +115,6 @@ struct sysfs_addrm_cxt { | |||
111 | * mount.c | 115 | * mount.c |
112 | */ | 116 | */ |
113 | extern struct sysfs_dirent sysfs_root; | 117 | extern struct sysfs_dirent sysfs_root; |
114 | extern struct super_block *sysfs_sb; | ||
115 | extern struct kmem_cache *sysfs_dir_cachep; | 118 | extern struct kmem_cache *sysfs_dir_cachep; |
116 | 119 | ||
117 | /* | 120 | /* |
@@ -124,8 +127,8 @@ extern const struct file_operations sysfs_dir_operations; | |||
124 | extern const struct inode_operations sysfs_dir_inode_operations; | 127 | extern const struct inode_operations sysfs_dir_inode_operations; |
125 | 128 | ||
126 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); | 129 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); |
127 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | 130 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); |
128 | void sysfs_put_active_two(struct sysfs_dirent *sd); | 131 | void sysfs_put_active(struct sysfs_dirent *sd); |
129 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | 132 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, |
130 | struct sysfs_dirent *parent_sd); | 133 | struct sysfs_dirent *parent_sd); |
131 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | 134 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); |
@@ -168,7 +171,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) | |||
168 | /* | 171 | /* |
169 | * inode.c | 172 | * inode.c |
170 | */ | 173 | */ |
171 | struct inode *sysfs_get_inode(struct sysfs_dirent *sd); | 174 | struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); |
172 | void sysfs_delete_inode(struct inode *inode); | 175 | void sysfs_delete_inode(struct inode *inode); |
173 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); | 176 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); |
174 | int sysfs_permission(struct inode *inode, int mask); | 177 | int sysfs_permission(struct inode *inode, int mask); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 66b63a751615..14743d935a93 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -1016,6 +1016,9 @@ magic_found: | |||
1016 | case UFS_FSSTABLE: | 1016 | case UFS_FSSTABLE: |
1017 | UFSD("fs is stable\n"); | 1017 | UFSD("fs is stable\n"); |
1018 | break; | 1018 | break; |
1019 | case UFS_FSLOG: | ||
1020 | UFSD("fs is logging fs\n"); | ||
1021 | break; | ||
1019 | case UFS_FSOSF1: | 1022 | case UFS_FSOSF1: |
1020 | UFSD("fs is DEC OSF/1\n"); | 1023 | UFSD("fs is DEC OSF/1\n"); |
1021 | break; | 1024 | break; |
diff --git a/fs/ufs/ufs_fs.h b/fs/ufs/ufs_fs.h index 54bde1895a80..6943ec677c0b 100644 --- a/fs/ufs/ufs_fs.h +++ b/fs/ufs/ufs_fs.h | |||
@@ -138,6 +138,7 @@ typedef __u16 __bitwise __fs16; | |||
138 | 138 | ||
139 | #define UFS_USEEFT ((__u16)65535) | 139 | #define UFS_USEEFT ((__u16)65535) |
140 | 140 | ||
141 | /* fs_clean values */ | ||
141 | #define UFS_FSOK 0x7c269d38 | 142 | #define UFS_FSOK 0x7c269d38 |
142 | #define UFS_FSACTIVE ((__s8)0x00) | 143 | #define UFS_FSACTIVE ((__s8)0x00) |
143 | #define UFS_FSCLEAN ((__s8)0x01) | 144 | #define UFS_FSCLEAN ((__s8)0x01) |
@@ -145,6 +146,11 @@ typedef __u16 __bitwise __fs16; | |||
145 | #define UFS_FSOSF1 ((__s8)0x03) /* is this correct for DEC OSF/1? */ | 146 | #define UFS_FSOSF1 ((__s8)0x03) /* is this correct for DEC OSF/1? */ |
146 | #define UFS_FSBAD ((__s8)0xff) | 147 | #define UFS_FSBAD ((__s8)0xff) |
147 | 148 | ||
149 | /* Solaris-specific fs_clean values */ | ||
150 | #define UFS_FSSUSPEND ((__s8)0xfe) /* temporarily suspended */ | ||
151 | #define UFS_FSLOG ((__s8)0xfd) /* logging fs */ | ||
152 | #define UFS_FSFIX ((__s8)0xfc) /* being repaired while mounted */ | ||
153 | |||
148 | /* From here to next blank line, s_flags for ufs_sb_info */ | 154 | /* From here to next blank line, s_flags for ufs_sb_info */ |
149 | /* directory entry encoding */ | 155 | /* directory entry encoding */ |
150 | #define UFS_DE_MASK 0x00000010 /* mask for the following */ | 156 | #define UFS_DE_MASK 0x00000010 /* mask for the following */ |
@@ -227,11 +233,16 @@ typedef __u16 __bitwise __fs16; | |||
227 | */ | 233 | */ |
228 | #define ufs_cbtocylno(bno) \ | 234 | #define ufs_cbtocylno(bno) \ |
229 | ((bno) * uspi->s_nspf / uspi->s_spc) | 235 | ((bno) * uspi->s_nspf / uspi->s_spc) |
230 | #define ufs_cbtorpos(bno) \ | 236 | #define ufs_cbtorpos(bno) \ |
237 | ((UFS_SB(sb)->s_flags & UFS_CG_SUN) ? \ | ||
238 | (((((bno) * uspi->s_nspf % uspi->s_spc) % \ | ||
239 | uspi->s_nsect) * \ | ||
240 | uspi->s_nrpos) / uspi->s_nsect) \ | ||
241 | : \ | ||
231 | ((((bno) * uspi->s_nspf % uspi->s_spc / uspi->s_nsect \ | 242 | ((((bno) * uspi->s_nspf % uspi->s_spc / uspi->s_nsect \ |
232 | * uspi->s_trackskew + (bno) * uspi->s_nspf % uspi->s_spc \ | 243 | * uspi->s_trackskew + (bno) * uspi->s_nspf % uspi->s_spc \ |
233 | % uspi->s_nsect * uspi->s_interleave) % uspi->s_nsect \ | 244 | % uspi->s_nsect * uspi->s_interleave) % uspi->s_nsect \ |
234 | * uspi->s_nrpos) / uspi->s_npsect) | 245 | * uspi->s_nrpos) / uspi->s_npsect)) |
235 | 246 | ||
236 | /* | 247 | /* |
237 | * The following macros optimize certain frequently calculated | 248 | * The following macros optimize certain frequently calculated |
diff --git a/include/asm-generic/pci-dma-compat.h b/include/asm-generic/pci-dma-compat.h index 37b3706226e7..1437b7da09b2 100644 --- a/include/asm-generic/pci-dma-compat.h +++ b/include/asm-generic/pci-dma-compat.h | |||
@@ -6,9 +6,6 @@ | |||
6 | 6 | ||
7 | #include <linux/dma-mapping.h> | 7 | #include <linux/dma-mapping.h> |
8 | 8 | ||
9 | /* note pci_set_dma_mask isn't here, since it's a public function | ||
10 | * exported from drivers/pci, use dma_supported instead */ | ||
11 | |||
12 | static inline int | 9 | static inline int |
13 | pci_dma_supported(struct pci_dev *hwdev, u64 mask) | 10 | pci_dma_supported(struct pci_dev *hwdev, u64 mask) |
14 | { | 11 | { |
@@ -104,4 +101,16 @@ pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr) | |||
104 | return dma_mapping_error(&pdev->dev, dma_addr); | 101 | return dma_mapping_error(&pdev->dev, dma_addr); |
105 | } | 102 | } |
106 | 103 | ||
104 | #ifdef CONFIG_PCI | ||
105 | static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) | ||
106 | { | ||
107 | return dma_set_mask(&dev->dev, mask); | ||
108 | } | ||
109 | |||
110 | static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | ||
111 | { | ||
112 | return dma_set_coherent_mask(&dev->dev, mask); | ||
113 | } | ||
114 | #endif | ||
115 | |||
107 | #endif | 116 | #endif |
diff --git a/include/linux/acct.h b/include/linux/acct.h index 882dc7248766..3e4737fa6cce 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h | |||
@@ -121,16 +121,15 @@ struct vfsmount; | |||
121 | struct super_block; | 121 | struct super_block; |
122 | struct pacct_struct; | 122 | struct pacct_struct; |
123 | struct pid_namespace; | 123 | struct pid_namespace; |
124 | extern int acct_parm[]; /* for sysctl */ | ||
124 | extern void acct_auto_close_mnt(struct vfsmount *m); | 125 | extern void acct_auto_close_mnt(struct vfsmount *m); |
125 | extern void acct_auto_close(struct super_block *sb); | 126 | extern void acct_auto_close(struct super_block *sb); |
126 | extern void acct_init_pacct(struct pacct_struct *pacct); | ||
127 | extern void acct_collect(long exitcode, int group_dead); | 127 | extern void acct_collect(long exitcode, int group_dead); |
128 | extern void acct_process(void); | 128 | extern void acct_process(void); |
129 | extern void acct_exit_ns(struct pid_namespace *); | 129 | extern void acct_exit_ns(struct pid_namespace *); |
130 | #else | 130 | #else |
131 | #define acct_auto_close_mnt(x) do { } while (0) | 131 | #define acct_auto_close_mnt(x) do { } while (0) |
132 | #define acct_auto_close(x) do { } while (0) | 132 | #define acct_auto_close(x) do { } while (0) |
133 | #define acct_init_pacct(x) do { } while (0) | ||
134 | #define acct_collect(x,y) do { } while (0) | 133 | #define acct_collect(x,y) do { } while (0) |
135 | #define acct_process() do { } while (0) | 134 | #define acct_process() do { } while (0) |
136 | #define acct_exit_ns(ns) do { } while (0) | 135 | #define acct_exit_ns(ns) do { } while (0) |
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index c9bbcb2a75ae..b8ad1ea99586 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -37,16 +37,24 @@ extern void cgroup_post_fork(struct task_struct *p); | |||
37 | extern void cgroup_exit(struct task_struct *p, int run_callbacks); | 37 | extern void cgroup_exit(struct task_struct *p, int run_callbacks); |
38 | extern int cgroupstats_build(struct cgroupstats *stats, | 38 | extern int cgroupstats_build(struct cgroupstats *stats, |
39 | struct dentry *dentry); | 39 | struct dentry *dentry); |
40 | extern int cgroup_load_subsys(struct cgroup_subsys *ss); | ||
41 | extern void cgroup_unload_subsys(struct cgroup_subsys *ss); | ||
40 | 42 | ||
41 | extern const struct file_operations proc_cgroup_operations; | 43 | extern const struct file_operations proc_cgroup_operations; |
42 | 44 | ||
43 | /* Define the enumeration of all cgroup subsystems */ | 45 | /* Define the enumeration of all builtin cgroup subsystems */ |
44 | #define SUBSYS(_x) _x ## _subsys_id, | 46 | #define SUBSYS(_x) _x ## _subsys_id, |
45 | enum cgroup_subsys_id { | 47 | enum cgroup_subsys_id { |
46 | #include <linux/cgroup_subsys.h> | 48 | #include <linux/cgroup_subsys.h> |
47 | CGROUP_SUBSYS_COUNT | 49 | CGROUP_BUILTIN_SUBSYS_COUNT |
48 | }; | 50 | }; |
49 | #undef SUBSYS | 51 | #undef SUBSYS |
52 | /* | ||
53 | * This define indicates the maximum number of subsystems that can be loaded | ||
54 | * at once. We limit to this many since cgroupfs_root has subsys_bits to keep | ||
55 | * track of all of them. | ||
56 | */ | ||
57 | #define CGROUP_SUBSYS_COUNT (BITS_PER_BYTE*sizeof(unsigned long)) | ||
50 | 58 | ||
51 | /* Per-subsystem/per-cgroup state maintained by the system. */ | 59 | /* Per-subsystem/per-cgroup state maintained by the system. */ |
52 | struct cgroup_subsys_state { | 60 | struct cgroup_subsys_state { |
@@ -76,6 +84,12 @@ enum { | |||
76 | CSS_REMOVED, /* This CSS is dead */ | 84 | CSS_REMOVED, /* This CSS is dead */ |
77 | }; | 85 | }; |
78 | 86 | ||
87 | /* Caller must verify that the css is not for root cgroup */ | ||
88 | static inline void __css_get(struct cgroup_subsys_state *css, int count) | ||
89 | { | ||
90 | atomic_add(count, &css->refcnt); | ||
91 | } | ||
92 | |||
79 | /* | 93 | /* |
80 | * Call css_get() to hold a reference on the css; it can be used | 94 | * Call css_get() to hold a reference on the css; it can be used |
81 | * for a reference obtained via: | 95 | * for a reference obtained via: |
@@ -87,7 +101,7 @@ static inline void css_get(struct cgroup_subsys_state *css) | |||
87 | { | 101 | { |
88 | /* We don't need to reference count the root state */ | 102 | /* We don't need to reference count the root state */ |
89 | if (!test_bit(CSS_ROOT, &css->flags)) | 103 | if (!test_bit(CSS_ROOT, &css->flags)) |
90 | atomic_inc(&css->refcnt); | 104 | __css_get(css, 1); |
91 | } | 105 | } |
92 | 106 | ||
93 | static inline bool css_is_removed(struct cgroup_subsys_state *css) | 107 | static inline bool css_is_removed(struct cgroup_subsys_state *css) |
@@ -118,11 +132,11 @@ static inline bool css_tryget(struct cgroup_subsys_state *css) | |||
118 | * css_get() or css_tryget() | 132 | * css_get() or css_tryget() |
119 | */ | 133 | */ |
120 | 134 | ||
121 | extern void __css_put(struct cgroup_subsys_state *css); | 135 | extern void __css_put(struct cgroup_subsys_state *css, int count); |
122 | static inline void css_put(struct cgroup_subsys_state *css) | 136 | static inline void css_put(struct cgroup_subsys_state *css) |
123 | { | 137 | { |
124 | if (!test_bit(CSS_ROOT, &css->flags)) | 138 | if (!test_bit(CSS_ROOT, &css->flags)) |
125 | __css_put(css); | 139 | __css_put(css, 1); |
126 | } | 140 | } |
127 | 141 | ||
128 | /* bits in struct cgroup flags field */ | 142 | /* bits in struct cgroup flags field */ |
@@ -221,6 +235,10 @@ struct cgroup { | |||
221 | 235 | ||
222 | /* For RCU-protected deletion */ | 236 | /* For RCU-protected deletion */ |
223 | struct rcu_head rcu_head; | 237 | struct rcu_head rcu_head; |
238 | |||
239 | /* List of events which userspace want to recieve */ | ||
240 | struct list_head event_list; | ||
241 | spinlock_t event_list_lock; | ||
224 | }; | 242 | }; |
225 | 243 | ||
226 | /* | 244 | /* |
@@ -258,7 +276,8 @@ struct css_set { | |||
258 | /* | 276 | /* |
259 | * Set of subsystem states, one for each subsystem. This array | 277 | * Set of subsystem states, one for each subsystem. This array |
260 | * is immutable after creation apart from the init_css_set | 278 | * is immutable after creation apart from the init_css_set |
261 | * during subsystem registration (at boot time). | 279 | * during subsystem registration (at boot time) and modular subsystem |
280 | * loading/unloading. | ||
262 | */ | 281 | */ |
263 | struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; | 282 | struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; |
264 | 283 | ||
@@ -363,6 +382,23 @@ struct cftype { | |||
363 | int (*trigger)(struct cgroup *cgrp, unsigned int event); | 382 | int (*trigger)(struct cgroup *cgrp, unsigned int event); |
364 | 383 | ||
365 | int (*release)(struct inode *inode, struct file *file); | 384 | int (*release)(struct inode *inode, struct file *file); |
385 | |||
386 | /* | ||
387 | * register_event() callback will be used to add new userspace | ||
388 | * waiter for changes related to the cftype. Implement it if | ||
389 | * you want to provide this functionality. Use eventfd_signal() | ||
390 | * on eventfd to send notification to userspace. | ||
391 | */ | ||
392 | int (*register_event)(struct cgroup *cgrp, struct cftype *cft, | ||
393 | struct eventfd_ctx *eventfd, const char *args); | ||
394 | /* | ||
395 | * unregister_event() callback will be called when userspace | ||
396 | * closes the eventfd or on cgroup removing. | ||
397 | * This callback must be implemented, if you want provide | ||
398 | * notification functionality. | ||
399 | */ | ||
400 | int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft, | ||
401 | struct eventfd_ctx *eventfd); | ||
366 | }; | 402 | }; |
367 | 403 | ||
368 | struct cgroup_scanner { | 404 | struct cgroup_scanner { |
@@ -428,6 +464,8 @@ struct cgroup_subsys { | |||
428 | void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); | 464 | void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); |
429 | int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 465 | int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
430 | struct task_struct *tsk, bool threadgroup); | 466 | struct task_struct *tsk, bool threadgroup); |
467 | void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | ||
468 | struct task_struct *tsk, bool threadgroup); | ||
431 | void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 469 | void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
432 | struct cgroup *old_cgrp, struct task_struct *tsk, | 470 | struct cgroup *old_cgrp, struct task_struct *tsk, |
433 | bool threadgroup); | 471 | bool threadgroup); |
@@ -472,6 +510,9 @@ struct cgroup_subsys { | |||
472 | /* used when use_id == true */ | 510 | /* used when use_id == true */ |
473 | struct idr idr; | 511 | struct idr idr; |
474 | spinlock_t id_lock; | 512 | spinlock_t id_lock; |
513 | |||
514 | /* should be defined only by modular subsystems */ | ||
515 | struct module *module; | ||
475 | }; | 516 | }; |
476 | 517 | ||
477 | #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys; | 518 | #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys; |
diff --git a/include/linux/compat.h b/include/linux/compat.h index ef68119a4fd2..717c691ecd8e 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -23,6 +23,7 @@ | |||
23 | typedef __compat_uid32_t compat_uid_t; | 23 | typedef __compat_uid32_t compat_uid_t; |
24 | typedef __compat_gid32_t compat_gid_t; | 24 | typedef __compat_gid32_t compat_gid_t; |
25 | 25 | ||
26 | struct compat_sel_arg_struct; | ||
26 | struct rusage; | 27 | struct rusage; |
27 | 28 | ||
28 | struct compat_itimerspec { | 29 | struct compat_itimerspec { |
@@ -249,6 +250,8 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | |||
249 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 250 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
250 | struct compat_timeval __user *tvp); | 251 | struct compat_timeval __user *tvp); |
251 | 252 | ||
253 | asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg); | ||
254 | |||
252 | asmlinkage long compat_sys_wait4(compat_pid_t pid, | 255 | asmlinkage long compat_sys_wait4(compat_pid_t pid, |
253 | compat_uint_t __user *stat_addr, int options, | 256 | compat_uint_t __user *stat_addr, int options, |
254 | struct compat_rusage __user *ru); | 257 | struct compat_rusage __user *ru); |
diff --git a/include/linux/coredump.h b/include/linux/coredump.h index b3c91d7cede4..8ba66a9d9022 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h | |||
@@ -16,6 +16,8 @@ static inline int dump_write(struct file *file, const void *addr, int nr) | |||
16 | 16 | ||
17 | static inline int dump_seek(struct file *file, loff_t off) | 17 | static inline int dump_seek(struct file *file, loff_t off) |
18 | { | 18 | { |
19 | int ret = 1; | ||
20 | |||
19 | if (file->f_op->llseek && file->f_op->llseek != no_llseek) { | 21 | if (file->f_op->llseek && file->f_op->llseek != no_llseek) { |
20 | if (file->f_op->llseek(file, off, SEEK_CUR) < 0) | 22 | if (file->f_op->llseek(file, off, SEEK_CUR) < 0) |
21 | return 0; | 23 | return 0; |
@@ -29,13 +31,15 @@ static inline int dump_seek(struct file *file, loff_t off) | |||
29 | 31 | ||
30 | if (n > PAGE_SIZE) | 32 | if (n > PAGE_SIZE) |
31 | n = PAGE_SIZE; | 33 | n = PAGE_SIZE; |
32 | if (!dump_write(file, buf, n)) | 34 | if (!dump_write(file, buf, n)) { |
33 | return 0; | 35 | ret = 0; |
36 | break; | ||
37 | } | ||
34 | off -= n; | 38 | off -= n; |
35 | } | 39 | } |
36 | free_page((unsigned long)buf); | 40 | free_page((unsigned long)buf); |
37 | } | 41 | } |
38 | return 1; | 42 | return ret; |
39 | } | 43 | } |
40 | 44 | ||
41 | #endif /* _LINUX_COREDUMP_H */ | 45 | #endif /* _LINUX_COREDUMP_H */ |
diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h index 5032b9a31ae7..ad5ec1d0475e 100644 --- a/include/linux/decompress/mm.h +++ b/include/linux/decompress/mm.h | |||
@@ -14,11 +14,21 @@ | |||
14 | 14 | ||
15 | /* Code active when included from pre-boot environment: */ | 15 | /* Code active when included from pre-boot environment: */ |
16 | 16 | ||
17 | /* | ||
18 | * Some architectures want to ensure there is no local data in their | ||
19 | * pre-boot environment, so that data can arbitarily relocated (via | ||
20 | * GOT references). This is achieved by defining STATIC_RW_DATA to | ||
21 | * be null. | ||
22 | */ | ||
23 | #ifndef STATIC_RW_DATA | ||
24 | #define STATIC_RW_DATA static | ||
25 | #endif | ||
26 | |||
17 | /* A trivial malloc implementation, adapted from | 27 | /* A trivial malloc implementation, adapted from |
18 | * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 | 28 | * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 |
19 | */ | 29 | */ |
20 | static unsigned long malloc_ptr; | 30 | STATIC_RW_DATA unsigned long malloc_ptr; |
21 | static int malloc_count; | 31 | STATIC_RW_DATA int malloc_count; |
22 | 32 | ||
23 | static void *malloc(int size) | 33 | static void *malloc(int size) |
24 | { | 34 | { |
diff --git a/include/linux/device.h b/include/linux/device.h index b30527db3ac0..182192892d45 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -106,7 +106,7 @@ extern int bus_unregister_notifier(struct bus_type *bus, | |||
106 | 106 | ||
107 | /* All 4 notifers below get called with the target struct device * | 107 | /* All 4 notifers below get called with the target struct device * |
108 | * as an argument. Note that those functions are likely to be called | 108 | * as an argument. Note that those functions are likely to be called |
109 | * with the device semaphore held in the core, so be careful. | 109 | * with the device lock held in the core, so be careful. |
110 | */ | 110 | */ |
111 | #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ | 111 | #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ |
112 | #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ | 112 | #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ |
@@ -251,8 +251,10 @@ extern struct device *class_find_device(struct class *class, | |||
251 | 251 | ||
252 | struct class_attribute { | 252 | struct class_attribute { |
253 | struct attribute attr; | 253 | struct attribute attr; |
254 | ssize_t (*show)(struct class *class, char *buf); | 254 | ssize_t (*show)(struct class *class, struct class_attribute *attr, |
255 | ssize_t (*store)(struct class *class, const char *buf, size_t count); | 255 | char *buf); |
256 | ssize_t (*store)(struct class *class, struct class_attribute *attr, | ||
257 | const char *buf, size_t count); | ||
256 | }; | 258 | }; |
257 | 259 | ||
258 | #define CLASS_ATTR(_name, _mode, _show, _store) \ | 260 | #define CLASS_ATTR(_name, _mode, _show, _store) \ |
@@ -263,6 +265,23 @@ extern int __must_check class_create_file(struct class *class, | |||
263 | extern void class_remove_file(struct class *class, | 265 | extern void class_remove_file(struct class *class, |
264 | const struct class_attribute *attr); | 266 | const struct class_attribute *attr); |
265 | 267 | ||
268 | /* Simple class attribute that is just a static string */ | ||
269 | |||
270 | struct class_attribute_string { | ||
271 | struct class_attribute attr; | ||
272 | char *str; | ||
273 | }; | ||
274 | |||
275 | /* Currently read-only only */ | ||
276 | #define _CLASS_ATTR_STRING(_name, _mode, _str) \ | ||
277 | { __ATTR(_name, _mode, show_class_attr_string, NULL), _str } | ||
278 | #define CLASS_ATTR_STRING(_name, _mode, _str) \ | ||
279 | struct class_attribute_string class_attr_##_name = \ | ||
280 | _CLASS_ATTR_STRING(_name, _mode, _str) | ||
281 | |||
282 | extern ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr, | ||
283 | char *buf); | ||
284 | |||
266 | struct class_interface { | 285 | struct class_interface { |
267 | struct list_head node; | 286 | struct list_head node; |
268 | struct class *class; | 287 | struct class *class; |
@@ -489,6 +508,21 @@ static inline bool device_async_suspend_enabled(struct device *dev) | |||
489 | return !!dev->power.async_suspend; | 508 | return !!dev->power.async_suspend; |
490 | } | 509 | } |
491 | 510 | ||
511 | static inline void device_lock(struct device *dev) | ||
512 | { | ||
513 | down(&dev->sem); | ||
514 | } | ||
515 | |||
516 | static inline int device_trylock(struct device *dev) | ||
517 | { | ||
518 | return down_trylock(&dev->sem); | ||
519 | } | ||
520 | |||
521 | static inline void device_unlock(struct device *dev) | ||
522 | { | ||
523 | up(&dev->sem); | ||
524 | } | ||
525 | |||
492 | void driver_init(void); | 526 | void driver_init(void); |
493 | 527 | ||
494 | /* | 528 | /* |
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 91b761846061..ca32ed78b057 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h | |||
@@ -127,6 +127,14 @@ static inline u64 dma_get_mask(struct device *dev) | |||
127 | return DMA_BIT_MASK(32); | 127 | return DMA_BIT_MASK(32); |
128 | } | 128 | } |
129 | 129 | ||
130 | static inline int dma_set_coherent_mask(struct device *dev, u64 mask) | ||
131 | { | ||
132 | if (!dma_supported(dev, mask)) | ||
133 | return -EIO; | ||
134 | dev->coherent_dma_mask = mask; | ||
135 | return 0; | ||
136 | } | ||
137 | |||
130 | extern u64 dma_get_required_mask(struct device *dev); | 138 | extern u64 dma_get_required_mask(struct device *dev); |
131 | 139 | ||
132 | static inline unsigned int dma_get_max_seg_size(struct device *dev) | 140 | static inline unsigned int dma_get_max_seg_size(struct device *dev) |
@@ -232,4 +240,20 @@ struct dma_attrs; | |||
232 | 240 | ||
233 | #endif /* CONFIG_HAVE_DMA_ATTRS */ | 241 | #endif /* CONFIG_HAVE_DMA_ATTRS */ |
234 | 242 | ||
243 | #ifdef CONFIG_NEED_DMA_MAP_STATE | ||
244 | #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME | ||
245 | #define DEFINE_DMA_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME | ||
246 | #define dma_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) | ||
247 | #define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) | ||
248 | #define dma_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) | ||
249 | #define dma_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) | ||
250 | #else | ||
251 | #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) | ||
252 | #define DEFINE_DMA_UNMAP_LEN(LEN_NAME) | ||
253 | #define dma_unmap_addr(PTR, ADDR_NAME) (0) | ||
254 | #define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) | ||
255 | #define dma_unmap_len(PTR, LEN_NAME) (0) | ||
256 | #define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) | ||
257 | #endif | ||
258 | |||
235 | #endif | 259 | #endif |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index abec69b63d7e..b1ed1cd8e2a8 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -32,14 +32,6 @@ extern struct fs_struct init_fs; | |||
32 | } | 32 | } |
33 | 33 | ||
34 | extern struct nsproxy init_nsproxy; | 34 | extern struct nsproxy init_nsproxy; |
35 | #define INIT_NSPROXY(nsproxy) { \ | ||
36 | .pid_ns = &init_pid_ns, \ | ||
37 | .count = ATOMIC_INIT(1), \ | ||
38 | .uts_ns = &init_uts_ns, \ | ||
39 | .mnt_ns = NULL, \ | ||
40 | INIT_NET_NS(net_ns) \ | ||
41 | INIT_IPC_NS(ipc_ns) \ | ||
42 | } | ||
43 | 35 | ||
44 | #define INIT_SIGHAND(sighand) { \ | 36 | #define INIT_SIGHAND(sighand) { \ |
45 | .count = ATOMIC_INIT(1), \ | 37 | .count = ATOMIC_INIT(1), \ |
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h index 1195a806fe0c..a0bb301afac0 100644 --- a/include/linux/iocontext.h +++ b/include/linux/iocontext.h | |||
@@ -42,7 +42,7 @@ struct io_context { | |||
42 | unsigned short ioprio; | 42 | unsigned short ioprio; |
43 | unsigned short ioprio_changed; | 43 | unsigned short ioprio_changed; |
44 | 44 | ||
45 | #ifdef CONFIG_BLK_CGROUP | 45 | #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) |
46 | unsigned short cgroup_changed; | 46 | unsigned short cgroup_changed; |
47 | #endif | 47 | #endif |
48 | 48 | ||
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index 07baa38bce37..51952989ad42 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h | |||
@@ -62,11 +62,6 @@ extern struct ipc_namespace init_ipc_ns; | |||
62 | extern atomic_t nr_ipc_ns; | 62 | extern atomic_t nr_ipc_ns; |
63 | 63 | ||
64 | extern spinlock_t mq_lock; | 64 | extern spinlock_t mq_lock; |
65 | #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC) | ||
66 | #define INIT_IPC_NS(ns) .ns = &init_ipc_ns, | ||
67 | #else | ||
68 | #define INIT_IPC_NS(ns) | ||
69 | #endif | ||
70 | 65 | ||
71 | #ifdef CONFIG_SYSVIPC | 66 | #ifdef CONFIG_SYSVIPC |
72 | extern int register_ipcns_notifier(struct ipc_namespace *); | 67 | extern int register_ipcns_notifier(struct ipc_namespace *); |
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index f7c9c75a2775..4b48318ac542 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/device.h> | 40 | #include <linux/device.h> |
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/ipmi_smi.h> | ||
43 | 42 | ||
44 | /* This files describes the interface for IPMI system management interface | 43 | /* This files describes the interface for IPMI system management interface |
45 | drivers to bind into the IPMI message handler. */ | 44 | drivers to bind into the IPMI message handler. */ |
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 384ca8bbf1ac..facb27fe7de0 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define KMOD_PATH_LEN 256 | 27 | #define KMOD_PATH_LEN 256 |
28 | 28 | ||
29 | #ifdef CONFIG_MODULES | 29 | #ifdef CONFIG_MODULES |
30 | extern char modprobe_path[]; /* for sysctl */ | ||
30 | /* modprobe exit status on success, -ve on error. Return value | 31 | /* modprobe exit status on success, -ve on error. Return value |
31 | * usually useless though. */ | 32 | * usually useless though. */ |
32 | extern int __request_module(bool wait, const char *name, ...) \ | 33 | extern int __request_module(bool wait, const char *name, ...) \ |
diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 58ae8e00fcdd..3950d3c2850d 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h | |||
@@ -106,7 +106,7 @@ extern char *kobject_get_path(struct kobject *kobj, gfp_t flag); | |||
106 | 106 | ||
107 | struct kobj_type { | 107 | struct kobj_type { |
108 | void (*release)(struct kobject *kobj); | 108 | void (*release)(struct kobject *kobj); |
109 | struct sysfs_ops *sysfs_ops; | 109 | const struct sysfs_ops *sysfs_ops; |
110 | struct attribute **default_attrs; | 110 | struct attribute **default_attrs; |
111 | }; | 111 | }; |
112 | 112 | ||
@@ -118,9 +118,9 @@ struct kobj_uevent_env { | |||
118 | }; | 118 | }; |
119 | 119 | ||
120 | struct kset_uevent_ops { | 120 | struct kset_uevent_ops { |
121 | int (*filter)(struct kset *kset, struct kobject *kobj); | 121 | int (* const filter)(struct kset *kset, struct kobject *kobj); |
122 | const char *(*name)(struct kset *kset, struct kobject *kobj); | 122 | const char *(* const name)(struct kset *kset, struct kobject *kobj); |
123 | int (*uevent)(struct kset *kset, struct kobject *kobj, | 123 | int (* const uevent)(struct kset *kset, struct kobject *kobj, |
124 | struct kobj_uevent_env *env); | 124 | struct kobj_uevent_env *env); |
125 | }; | 125 | }; |
126 | 126 | ||
@@ -132,7 +132,7 @@ struct kobj_attribute { | |||
132 | const char *buf, size_t count); | 132 | const char *buf, size_t count); |
133 | }; | 133 | }; |
134 | 134 | ||
135 | extern struct sysfs_ops kobj_sysfs_ops; | 135 | extern const struct sysfs_ops kobj_sysfs_ops; |
136 | 136 | ||
137 | /** | 137 | /** |
138 | * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. | 138 | * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. |
@@ -155,14 +155,14 @@ struct kset { | |||
155 | struct list_head list; | 155 | struct list_head list; |
156 | spinlock_t list_lock; | 156 | spinlock_t list_lock; |
157 | struct kobject kobj; | 157 | struct kobject kobj; |
158 | struct kset_uevent_ops *uevent_ops; | 158 | const struct kset_uevent_ops *uevent_ops; |
159 | }; | 159 | }; |
160 | 160 | ||
161 | extern void kset_init(struct kset *kset); | 161 | extern void kset_init(struct kset *kset); |
162 | extern int __must_check kset_register(struct kset *kset); | 162 | extern int __must_check kset_register(struct kset *kset); |
163 | extern void kset_unregister(struct kset *kset); | 163 | extern void kset_unregister(struct kset *kset); |
164 | extern struct kset * __must_check kset_create_and_add(const char *name, | 164 | extern struct kset * __must_check kset_create_and_add(const char *name, |
165 | struct kset_uevent_ops *u, | 165 | const struct kset_uevent_ops *u, |
166 | struct kobject *parent_kobj); | 166 | struct kobject *parent_kobj); |
167 | 167 | ||
168 | static inline struct kset *to_kset(struct kobject *kobj) | 168 | static inline struct kset *to_kset(struct kobject *kobj) |
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 10206a87da19..a03977a96d7e 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h | |||
@@ -12,6 +12,10 @@ | |||
12 | struct task_struct; | 12 | struct task_struct; |
13 | struct lockdep_map; | 13 | struct lockdep_map; |
14 | 14 | ||
15 | /* for sysctl */ | ||
16 | extern int prove_locking; | ||
17 | extern int lock_stat; | ||
18 | |||
15 | #ifdef CONFIG_LOCKDEP | 19 | #ifdef CONFIG_LOCKDEP |
16 | 20 | ||
17 | #include <linux/linkage.h> | 21 | #include <linux/linkage.h> |
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 1f9b119f4ace..44301c6affa8 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h | |||
@@ -124,7 +124,6 @@ static inline bool mem_cgroup_disabled(void) | |||
124 | return false; | 124 | return false; |
125 | } | 125 | } |
126 | 126 | ||
127 | extern bool mem_cgroup_oom_called(struct task_struct *task); | ||
128 | void mem_cgroup_update_file_mapped(struct page *page, int val); | 127 | void mem_cgroup_update_file_mapped(struct page *page, int val); |
129 | unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, | 128 | unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, |
130 | gfp_t gfp_mask, int nid, | 129 | gfp_t gfp_mask, int nid, |
@@ -258,11 +257,6 @@ static inline bool mem_cgroup_disabled(void) | |||
258 | return true; | 257 | return true; |
259 | } | 258 | } |
260 | 259 | ||
261 | static inline bool mem_cgroup_oom_called(struct task_struct *task) | ||
262 | { | ||
263 | return false; | ||
264 | } | ||
265 | |||
266 | static inline int | 260 | static inline int |
267 | mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg) | 261 | mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg) |
268 | { | 262 | { |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 3899395a03de..e70f21beb4b4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -971,7 +971,13 @@ static inline void setmax_mm_hiwater_rss(unsigned long *maxrss, | |||
971 | *maxrss = hiwater_rss; | 971 | *maxrss = hiwater_rss; |
972 | } | 972 | } |
973 | 973 | ||
974 | #if defined(SPLIT_RSS_COUNTING) | ||
974 | void sync_mm_rss(struct task_struct *task, struct mm_struct *mm); | 975 | void sync_mm_rss(struct task_struct *task, struct mm_struct *mm); |
976 | #else | ||
977 | static inline void sync_mm_rss(struct task_struct *task, struct mm_struct *mm) | ||
978 | { | ||
979 | } | ||
980 | #endif | ||
975 | 981 | ||
976 | /* | 982 | /* |
977 | * A callback you can register to apply pressure to ageable caches. | 983 | * A callback you can register to apply pressure to ageable caches. |
@@ -1459,5 +1465,7 @@ extern void shake_page(struct page *p, int access); | |||
1459 | extern atomic_long_t mce_bad_pages; | 1465 | extern atomic_long_t mce_bad_pages; |
1460 | extern int soft_offline_page(struct page *page, int flags); | 1466 | extern int soft_offline_page(struct page *page, int flags); |
1461 | 1467 | ||
1468 | extern void dump_page(struct page *page); | ||
1469 | |||
1462 | #endif /* __KERNEL__ */ | 1470 | #endif /* __KERNEL__ */ |
1463 | #endif /* _LINUX_MM_H */ | 1471 | #endif /* _LINUX_MM_H */ |
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 048b46270aa5..b8bb9a6a1f37 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h | |||
@@ -203,7 +203,7 @@ enum { | |||
203 | NR_MM_COUNTERS | 203 | NR_MM_COUNTERS |
204 | }; | 204 | }; |
205 | 205 | ||
206 | #if USE_SPLIT_PTLOCKS | 206 | #if USE_SPLIT_PTLOCKS && defined(CONFIG_MMU) |
207 | #define SPLIT_RSS_COUNTING | 207 | #define SPLIT_RSS_COUNTING |
208 | struct mm_rss_stat { | 208 | struct mm_rss_stat { |
209 | atomic_long_t count[NR_MM_COUNTERS]; | 209 | atomic_long_t count[NR_MM_COUNTERS]; |
diff --git a/include/linux/module.h b/include/linux/module.h index dd618eb026aa..5e869ffd34aa 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -175,6 +175,7 @@ struct notifier_block; | |||
175 | 175 | ||
176 | #ifdef CONFIG_MODULES | 176 | #ifdef CONFIG_MODULES |
177 | 177 | ||
178 | extern int modules_disabled; /* for sysctl */ | ||
178 | /* Get/put a kernel symbol (calls must be symmetric) */ | 179 | /* Get/put a kernel symbol (calls must be symmetric) */ |
179 | void *__symbol_get(const char *symbol); | 180 | void *__symbol_get(const char *symbol); |
180 | void *__symbol_get_gpl(const char *symbol); | 181 | void *__symbol_get_gpl(const char *symbol); |
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index c4fa64b585ff..dba35e413371 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h | |||
@@ -483,7 +483,7 @@ static inline int num_node_state(enum node_states state) | |||
483 | type *name = kmalloc(sizeof(*name), gfp_flags) | 483 | type *name = kmalloc(sizeof(*name), gfp_flags) |
484 | #define NODEMASK_FREE(m) kfree(m) | 484 | #define NODEMASK_FREE(m) kfree(m) |
485 | #else | 485 | #else |
486 | #define NODEMASK_ALLOC(type, name, gfp_flags) type _name, *name = &_name | 486 | #define NODEMASK_ALLOC(type, name, gfp_flags) type _##name, *name = &_##name |
487 | #define NODEMASK_FREE(m) do {} while (0) | 487 | #define NODEMASK_FREE(m) do {} while (0) |
488 | #endif | 488 | #endif |
489 | 489 | ||
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h index b0e4eb126236..30b08136fdf3 100644 --- a/include/linux/page_cgroup.h +++ b/include/linux/page_cgroup.h | |||
@@ -118,6 +118,8 @@ static inline void __init page_cgroup_init_flatmem(void) | |||
118 | #include <linux/swap.h> | 118 | #include <linux/swap.h> |
119 | 119 | ||
120 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP | 120 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP |
121 | extern unsigned short swap_cgroup_cmpxchg(swp_entry_t ent, | ||
122 | unsigned short old, unsigned short new); | ||
121 | extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id); | 123 | extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id); |
122 | extern unsigned short lookup_swap_cgroup(swp_entry_t ent); | 124 | extern unsigned short lookup_swap_cgroup(swp_entry_t ent); |
123 | extern int swap_cgroup_swapon(int type, unsigned long max_pages); | 125 | extern int swap_cgroup_swapon(int type, unsigned long max_pages); |
diff --git a/include/linux/pci-dma.h b/include/linux/pci-dma.h new file mode 100644 index 000000000000..549a041f9c08 --- /dev/null +++ b/include/linux/pci-dma.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _LINUX_PCI_DMA_H | ||
2 | #define _LINUX_PCI_DMA_H | ||
3 | |||
4 | #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) DEFINE_DMA_UNMAP_ADDR(ADDR_NAME); | ||
5 | #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) DEFINE_DMA_UNMAP_LEN(LEN_NAME); | ||
6 | #define pci_unmap_addr dma_unmap_addr | ||
7 | #define pci_unmap_addr_set dma_unmap_addr_set | ||
8 | #define pci_unmap_len dma_unmap_len | ||
9 | #define pci_unmap_len_set dma_unmap_len_set | ||
10 | |||
11 | #endif | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index cd5809a5963e..a788fa12ff31 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -769,8 +769,6 @@ int pci_try_set_mwi(struct pci_dev *dev); | |||
769 | void pci_clear_mwi(struct pci_dev *dev); | 769 | void pci_clear_mwi(struct pci_dev *dev); |
770 | void pci_intx(struct pci_dev *dev, int enable); | 770 | void pci_intx(struct pci_dev *dev, int enable); |
771 | void pci_msi_off(struct pci_dev *dev); | 771 | void pci_msi_off(struct pci_dev *dev); |
772 | int pci_set_dma_mask(struct pci_dev *dev, u64 mask); | ||
773 | int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); | ||
774 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); | 772 | int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); |
775 | int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); | 773 | int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); |
776 | int pcix_get_max_mmrbc(struct pci_dev *dev); | 774 | int pcix_get_max_mmrbc(struct pci_dev *dev); |
@@ -904,6 +902,7 @@ int pci_set_vga_state(struct pci_dev *pdev, bool decode, | |||
904 | unsigned int command_bits, bool change_bridge); | 902 | unsigned int command_bits, bool change_bridge); |
905 | /* kmem_cache style wrapper around pci_alloc_consistent() */ | 903 | /* kmem_cache style wrapper around pci_alloc_consistent() */ |
906 | 904 | ||
905 | #include <linux/pci-dma.h> | ||
907 | #include <linux/dmapool.h> | 906 | #include <linux/dmapool.h> |
908 | 907 | ||
909 | #define pci_pool dma_pool | 908 | #define pci_pool dma_pool |
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 71ff887ca44e..212da17d06af 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
@@ -21,7 +21,7 @@ struct platform_device { | |||
21 | u32 num_resources; | 21 | u32 num_resources; |
22 | struct resource * resource; | 22 | struct resource * resource; |
23 | 23 | ||
24 | struct platform_device_id *id_entry; | 24 | const struct platform_device_id *id_entry; |
25 | 25 | ||
26 | /* arch specific additions */ | 26 | /* arch specific additions */ |
27 | struct pdev_archdata archdata; | 27 | struct pdev_archdata archdata; |
@@ -62,7 +62,7 @@ struct platform_driver { | |||
62 | int (*suspend)(struct platform_device *, pm_message_t state); | 62 | int (*suspend)(struct platform_device *, pm_message_t state); |
63 | int (*resume)(struct platform_device *); | 63 | int (*resume)(struct platform_device *); |
64 | struct device_driver driver; | 64 | struct device_driver driver; |
65 | struct platform_device_id *id_table; | 65 | const struct platform_device_id *id_table; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | extern int platform_driver_register(struct platform_driver *); | 68 | extern int platform_driver_register(struct platform_driver *); |
@@ -77,6 +77,11 @@ extern int platform_driver_probe(struct platform_driver *driver, | |||
77 | #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) | 77 | #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) |
78 | #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) | 78 | #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) |
79 | 79 | ||
80 | extern struct platform_device *platform_create_bundle(struct platform_driver *driver, | ||
81 | int (*probe)(struct platform_device *), | ||
82 | struct resource *res, unsigned int n_res, | ||
83 | const void *data, size_t size); | ||
84 | |||
80 | /* early platform driver interface */ | 85 | /* early platform driver interface */ |
81 | struct early_platform_driver { | 86 | struct early_platform_driver { |
82 | const char *class_str; | 87 | const char *class_str; |
diff --git a/include/linux/poll.h b/include/linux/poll.h index 6673743946f7..600cc1fde64d 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h | |||
@@ -10,8 +10,10 @@ | |||
10 | #include <linux/wait.h> | 10 | #include <linux/wait.h> |
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/sysctl.h> | ||
13 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
14 | 15 | ||
16 | extern struct ctl_table epoll_table[]; /* for sysctl */ | ||
15 | /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating | 17 | /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating |
16 | additional memory. */ | 18 | additional memory. */ |
17 | #define MAX_STACK_ALLOC 832 | 19 | #define MAX_STACK_ALLOC 832 |
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index c5eab89da51e..e1fb60729979 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
@@ -264,6 +264,9 @@ static inline void user_enable_single_step(struct task_struct *task) | |||
264 | static inline void user_disable_single_step(struct task_struct *task) | 264 | static inline void user_disable_single_step(struct task_struct *task) |
265 | { | 265 | { |
266 | } | 266 | } |
267 | #else | ||
268 | extern void user_enable_single_step(struct task_struct *); | ||
269 | extern void user_disable_single_step(struct task_struct *); | ||
267 | #endif /* arch_has_single_step */ | 270 | #endif /* arch_has_single_step */ |
268 | 271 | ||
269 | #ifndef arch_has_block_step | 272 | #ifndef arch_has_block_step |
@@ -291,6 +294,8 @@ static inline void user_enable_block_step(struct task_struct *task) | |||
291 | { | 294 | { |
292 | BUG(); /* This can never be called. */ | 295 | BUG(); /* This can never be called. */ |
293 | } | 296 | } |
297 | #else | ||
298 | extern void user_enable_block_step(struct task_struct *); | ||
294 | #endif /* arch_has_block_step */ | 299 | #endif /* arch_has_block_step */ |
295 | 300 | ||
296 | #ifdef ARCH_HAS_USER_SINGLE_STEP_INFO | 301 | #ifdef ARCH_HAS_USER_SINGLE_STEP_INFO |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index c84373626336..a005cac5e302 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -41,6 +41,10 @@ | |||
41 | #include <linux/lockdep.h> | 41 | #include <linux/lockdep.h> |
42 | #include <linux/completion.h> | 42 | #include <linux/completion.h> |
43 | 43 | ||
44 | #ifdef CONFIG_RCU_TORTURE_TEST | ||
45 | extern int rcutorture_runnable; /* for sysctl */ | ||
46 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ | ||
47 | |||
44 | /** | 48 | /** |
45 | * struct rcu_head - callback structure for use with RCU | 49 | * struct rcu_head - callback structure for use with RCU |
46 | * @next: next update requests in a list | 50 | * @next: next update requests in a list |
diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 988e55fe649b..3005d5a7fce5 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h | |||
@@ -64,6 +64,7 @@ extern void kernel_restart(char *cmd); | |||
64 | extern void kernel_halt(void); | 64 | extern void kernel_halt(void); |
65 | extern void kernel_power_off(void); | 65 | extern void kernel_power_off(void); |
66 | 66 | ||
67 | extern int C_A_D; /* for sysctl */ | ||
67 | void ctrl_alt_del(void); | 68 | void ctrl_alt_del(void); |
68 | 69 | ||
69 | #define POWEROFF_CMD_PATH_LEN 256 | 70 | #define POWEROFF_CMD_PATH_LEN 256 |
diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 60f88a7fb13d..14dbc83ded20 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h | |||
@@ -238,6 +238,12 @@ static inline bool is_leap_year(unsigned int year) | |||
238 | return (!(year % 4) && (year % 100)) || !(year % 400); | 238 | return (!(year % 4) && (year % 100)) || !(year % 400); |
239 | } | 239 | } |
240 | 240 | ||
241 | #ifdef CONFIG_RTC_HCTOSYS | ||
242 | extern int rtc_hctosys_ret; | ||
243 | #else | ||
244 | #define rtc_hctosys_ret -ENODEV | ||
245 | #endif | ||
246 | |||
241 | #endif /* __KERNEL__ */ | 247 | #endif /* __KERNEL__ */ |
242 | 248 | ||
243 | #endif /* _LINUX_RTC_H_ */ | 249 | #endif /* _LINUX_RTC_H_ */ |
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h index 281d8fd775e8..8d522ffeda33 100644 --- a/include/linux/rtmutex.h +++ b/include/linux/rtmutex.h | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/plist.h> | 16 | #include <linux/plist.h> |
17 | #include <linux/spinlock_types.h> | 17 | #include <linux/spinlock_types.h> |
18 | 18 | ||
19 | extern int max_lock_depth; /* for sysctl */ | ||
20 | |||
19 | /** | 21 | /** |
20 | * The rt_mutex structure | 22 | * The rt_mutex structure |
21 | * | 23 | * |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 46c6f8d5dc06..ca635c128482 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -2391,9 +2391,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times); | |||
2391 | 2391 | ||
2392 | static inline void thread_group_cputime_init(struct signal_struct *sig) | 2392 | static inline void thread_group_cputime_init(struct signal_struct *sig) |
2393 | { | 2393 | { |
2394 | sig->cputimer.cputime = INIT_CPUTIME; | ||
2395 | spin_lock_init(&sig->cputimer.lock); | 2394 | spin_lock_init(&sig->cputimer.lock); |
2396 | sig->cputimer.running = 0; | ||
2397 | } | 2395 | } |
2398 | 2396 | ||
2399 | static inline void thread_group_cputime_free(struct signal_struct *sig) | 2397 | static inline void thread_group_cputime_free(struct signal_struct *sig) |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 8c3dd36fe91a..78dd1e7120a9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -491,9 +491,13 @@ uart_handle_dcd_change(struct uart_port *uport, unsigned int status) | |||
491 | { | 491 | { |
492 | struct uart_state *state = uport->state; | 492 | struct uart_state *state = uport->state; |
493 | struct tty_port *port = &state->port; | 493 | struct tty_port *port = &state->port; |
494 | struct tty_ldisc *ld = tty_ldisc_ref(port->tty); | ||
495 | struct timespec ts; | ||
494 | 496 | ||
495 | uport->icount.dcd++; | 497 | if (ld && ld->ops->dcd_change) |
498 | getnstimeofday(&ts); | ||
496 | 499 | ||
500 | uport->icount.dcd++; | ||
497 | #ifdef CONFIG_HARD_PPS | 501 | #ifdef CONFIG_HARD_PPS |
498 | if ((uport->flags & UPF_HARDPPS_CD) && status) | 502 | if ((uport->flags & UPF_HARDPPS_CD) && status) |
499 | hardpps(); | 503 | hardpps(); |
@@ -505,6 +509,11 @@ uart_handle_dcd_change(struct uart_port *uport, unsigned int status) | |||
505 | else if (port->tty) | 509 | else if (port->tty) |
506 | tty_hangup(port->tty); | 510 | tty_hangup(port->tty); |
507 | } | 511 | } |
512 | |||
513 | if (ld && ld->ops->dcd_change) | ||
514 | ld->ops->dcd_change(port->tty, status, &ts); | ||
515 | if (ld) | ||
516 | tty_ldisc_deref(ld); | ||
508 | } | 517 | } |
509 | 518 | ||
510 | /** | 519 | /** |
diff --git a/include/linux/signal.h b/include/linux/signal.h index ab9272cc270c..fcd2b14b1932 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h | |||
@@ -7,6 +7,8 @@ | |||
7 | #ifdef __KERNEL__ | 7 | #ifdef __KERNEL__ |
8 | #include <linux/list.h> | 8 | #include <linux/list.h> |
9 | 9 | ||
10 | /* for sysctl */ | ||
11 | extern int print_fatal_signals; | ||
10 | /* | 12 | /* |
11 | * Real Time signals may be queued. | 13 | * Real Time signals may be queued. |
12 | */ | 14 | */ |
diff --git a/include/linux/swap.h b/include/linux/swap.h index a2602a8207a6..1f59d9340c4d 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -355,6 +355,7 @@ static inline void disable_swap_token(void) | |||
355 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | 355 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR |
356 | extern void | 356 | extern void |
357 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); | 357 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); |
358 | extern int mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep); | ||
358 | #else | 359 | #else |
359 | static inline void | 360 | static inline void |
360 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) | 361 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) |
@@ -485,6 +486,14 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent) | |||
485 | { | 486 | { |
486 | } | 487 | } |
487 | 488 | ||
489 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | ||
490 | static inline int | ||
491 | mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep) | ||
492 | { | ||
493 | return 0; | ||
494 | } | ||
495 | #endif | ||
496 | |||
488 | #endif /* CONFIG_SWAP */ | 497 | #endif /* CONFIG_SWAP */ |
489 | #endif /* __KERNEL__*/ | 498 | #endif /* __KERNEL__*/ |
490 | #endif /* _LINUX_SWAP_H */ | 499 | #endif /* _LINUX_SWAP_H */ |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 8126f239edf0..44f2ad0e8825 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -23,6 +23,7 @@ struct kexec_segment; | |||
23 | struct linux_dirent; | 23 | struct linux_dirent; |
24 | struct linux_dirent64; | 24 | struct linux_dirent64; |
25 | struct list_head; | 25 | struct list_head; |
26 | struct mmap_arg_struct; | ||
26 | struct msgbuf; | 27 | struct msgbuf; |
27 | struct msghdr; | 28 | struct msghdr; |
28 | struct mmsghdr; | 29 | struct mmsghdr; |
@@ -30,10 +31,13 @@ struct msqid_ds; | |||
30 | struct new_utsname; | 31 | struct new_utsname; |
31 | struct nfsctl_arg; | 32 | struct nfsctl_arg; |
32 | struct __old_kernel_stat; | 33 | struct __old_kernel_stat; |
34 | struct oldold_utsname; | ||
35 | struct old_utsname; | ||
33 | struct pollfd; | 36 | struct pollfd; |
34 | struct rlimit; | 37 | struct rlimit; |
35 | struct rusage; | 38 | struct rusage; |
36 | struct sched_param; | 39 | struct sched_param; |
40 | struct sel_arg_struct; | ||
37 | struct semaphore; | 41 | struct semaphore; |
38 | struct sembuf; | 42 | struct sembuf; |
39 | struct shmid_ds; | 43 | struct shmid_ds; |
@@ -638,6 +642,7 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, | |||
638 | long timeout); | 642 | long timeout); |
639 | asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, | 643 | asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, |
640 | fd_set __user *exp, struct timeval __user *tvp); | 644 | fd_set __user *exp, struct timeval __user *tvp); |
645 | asmlinkage long sys_old_select(struct sel_arg_struct __user *arg); | ||
641 | asmlinkage long sys_epoll_create(int size); | 646 | asmlinkage long sys_epoll_create(int size); |
642 | asmlinkage long sys_epoll_create1(int flags); | 647 | asmlinkage long sys_epoll_create1(int flags); |
643 | asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, | 648 | asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, |
@@ -652,6 +657,8 @@ asmlinkage long sys_gethostname(char __user *name, int len); | |||
652 | asmlinkage long sys_sethostname(char __user *name, int len); | 657 | asmlinkage long sys_sethostname(char __user *name, int len); |
653 | asmlinkage long sys_setdomainname(char __user *name, int len); | 658 | asmlinkage long sys_setdomainname(char __user *name, int len); |
654 | asmlinkage long sys_newuname(struct new_utsname __user *name); | 659 | asmlinkage long sys_newuname(struct new_utsname __user *name); |
660 | asmlinkage long sys_uname(struct old_utsname __user *); | ||
661 | asmlinkage long sys_olduname(struct oldold_utsname __user *); | ||
655 | 662 | ||
656 | asmlinkage long sys_getrlimit(unsigned int resource, | 663 | asmlinkage long sys_getrlimit(unsigned int resource, |
657 | struct rlimit __user *rlim); | 664 | struct rlimit __user *rlim); |
@@ -681,6 +688,8 @@ asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg); | |||
681 | asmlinkage long sys_shmget(key_t key, size_t size, int flag); | 688 | asmlinkage long sys_shmget(key_t key, size_t size, int flag); |
682 | asmlinkage long sys_shmdt(char __user *shmaddr); | 689 | asmlinkage long sys_shmdt(char __user *shmaddr); |
683 | asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); | 690 | asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); |
691 | asmlinkage long sys_ipc(unsigned int call, int first, int second, | ||
692 | unsigned long third, void __user *ptr, long fifth); | ||
684 | 693 | ||
685 | asmlinkage long sys_mq_open(const char __user *name, int oflag, mode_t mode, struct mq_attr __user *attr); | 694 | asmlinkage long sys_mq_open(const char __user *name, int oflag, mode_t mode, struct mq_attr __user *attr); |
686 | asmlinkage long sys_mq_unlink(const char __user *name); | 695 | asmlinkage long sys_mq_unlink(const char __user *name); |
@@ -836,4 +845,6 @@ asmlinkage long sys_perf_event_open( | |||
836 | asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, | 845 | asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, |
837 | unsigned long prot, unsigned long flags, | 846 | unsigned long prot, unsigned long flags, |
838 | unsigned long fd, unsigned long pgoff); | 847 | unsigned long fd, unsigned long pgoff); |
848 | asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg); | ||
849 | |||
839 | #endif | 850 | #endif |
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index f395bb3fa2f2..1154c29f4101 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h | |||
@@ -27,10 +27,12 @@ | |||
27 | 27 | ||
28 | 28 | ||
29 | struct sys_device; | 29 | struct sys_device; |
30 | struct sysdev_class_attribute; | ||
30 | 31 | ||
31 | struct sysdev_class { | 32 | struct sysdev_class { |
32 | const char *name; | 33 | const char *name; |
33 | struct list_head drivers; | 34 | struct list_head drivers; |
35 | struct sysdev_class_attribute **attrs; | ||
34 | 36 | ||
35 | /* Default operations for these types of devices */ | 37 | /* Default operations for these types of devices */ |
36 | int (*shutdown)(struct sys_device *); | 38 | int (*shutdown)(struct sys_device *); |
@@ -41,8 +43,10 @@ struct sysdev_class { | |||
41 | 43 | ||
42 | struct sysdev_class_attribute { | 44 | struct sysdev_class_attribute { |
43 | struct attribute attr; | 45 | struct attribute attr; |
44 | ssize_t (*show)(struct sysdev_class *, char *); | 46 | ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *, |
45 | ssize_t (*store)(struct sysdev_class *, const char *, size_t); | 47 | char *); |
48 | ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *, | ||
49 | const char *, size_t); | ||
46 | }; | 50 | }; |
47 | 51 | ||
48 | #define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ | 52 | #define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ |
@@ -119,6 +123,19 @@ struct sysdev_attribute { | |||
119 | extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); | 123 | extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); |
120 | extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); | 124 | extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); |
121 | 125 | ||
126 | /* Create/remove NULL terminated attribute list */ | ||
127 | static inline int | ||
128 | sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a) | ||
129 | { | ||
130 | return sysfs_create_files(&d->kobj, (const struct attribute **)a); | ||
131 | } | ||
132 | |||
133 | static inline void | ||
134 | sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a) | ||
135 | { | ||
136 | return sysfs_remove_files(&d->kobj, (const struct attribute **)a); | ||
137 | } | ||
138 | |||
122 | struct sysdev_ext_attribute { | 139 | struct sysdev_ext_attribute { |
123 | struct sysdev_attribute attr; | 140 | struct sysdev_attribute attr; |
124 | void *var; | 141 | void *var; |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index cfa83083a2d4..f0496b3d1811 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/compiler.h> | 15 | #include <linux/compiler.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/list.h> | 17 | #include <linux/list.h> |
18 | #include <linux/lockdep.h> | ||
18 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
19 | 20 | ||
20 | struct kobject; | 21 | struct kobject; |
@@ -29,8 +30,33 @@ struct attribute { | |||
29 | const char *name; | 30 | const char *name; |
30 | struct module *owner; | 31 | struct module *owner; |
31 | mode_t mode; | 32 | mode_t mode; |
33 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
34 | struct lock_class_key *key; | ||
35 | struct lock_class_key skey; | ||
36 | #endif | ||
32 | }; | 37 | }; |
33 | 38 | ||
39 | /** | ||
40 | * sysfs_attr_init - initialize a dynamically allocated sysfs attribute | ||
41 | * @attr: struct attribute to initialize | ||
42 | * | ||
43 | * Initialize a dynamically allocated struct attribute so we can | ||
44 | * make lockdep happy. This is a new requirement for attributes | ||
45 | * and initially this is only needed when lockdep is enabled. | ||
46 | * Lockdep gives a nice error when your attribute is added to | ||
47 | * sysfs if you don't have this. | ||
48 | */ | ||
49 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
50 | #define sysfs_attr_init(attr) \ | ||
51 | do { \ | ||
52 | static struct lock_class_key __key; \ | ||
53 | \ | ||
54 | (attr)->key = &__key; \ | ||
55 | } while(0) | ||
56 | #else | ||
57 | #define sysfs_attr_init(attr) do {} while(0) | ||
58 | #endif | ||
59 | |||
34 | struct attribute_group { | 60 | struct attribute_group { |
35 | const char *name; | 61 | const char *name; |
36 | mode_t (*is_visible)(struct kobject *, | 62 | mode_t (*is_visible)(struct kobject *, |
@@ -74,6 +100,18 @@ struct bin_attribute { | |||
74 | struct vm_area_struct *vma); | 100 | struct vm_area_struct *vma); |
75 | }; | 101 | }; |
76 | 102 | ||
103 | /** | ||
104 | * sysfs_bin_attr_init - initialize a dynamically allocated bin_attribute | ||
105 | * @attr: struct bin_attribute to initialize | ||
106 | * | ||
107 | * Initialize a dynamically allocated struct bin_attribute so we | ||
108 | * can make lockdep happy. This is a new requirement for | ||
109 | * attributes and initially this is only needed when lockdep is | ||
110 | * enabled. Lockdep gives a nice error when your attribute is | ||
111 | * added to sysfs if you don't have this. | ||
112 | */ | ||
113 | #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr) | ||
114 | |||
77 | struct sysfs_ops { | 115 | struct sysfs_ops { |
78 | ssize_t (*show)(struct kobject *, struct attribute *,char *); | 116 | ssize_t (*show)(struct kobject *, struct attribute *,char *); |
79 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); | 117 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); |
@@ -94,9 +132,12 @@ int __must_check sysfs_move_dir(struct kobject *kobj, | |||
94 | 132 | ||
95 | int __must_check sysfs_create_file(struct kobject *kobj, | 133 | int __must_check sysfs_create_file(struct kobject *kobj, |
96 | const struct attribute *attr); | 134 | const struct attribute *attr); |
135 | int __must_check sysfs_create_files(struct kobject *kobj, | ||
136 | const struct attribute **attr); | ||
97 | int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, | 137 | int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, |
98 | mode_t mode); | 138 | mode_t mode); |
99 | void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); | 139 | void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); |
140 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); | ||
100 | 141 | ||
101 | int __must_check sysfs_create_bin_file(struct kobject *kobj, | 142 | int __must_check sysfs_create_bin_file(struct kobject *kobj, |
102 | const struct bin_attribute *attr); | 143 | const struct bin_attribute *attr); |
@@ -110,6 +151,9 @@ int __must_check sysfs_create_link_nowarn(struct kobject *kobj, | |||
110 | const char *name); | 151 | const char *name); |
111 | void sysfs_remove_link(struct kobject *kobj, const char *name); | 152 | void sysfs_remove_link(struct kobject *kobj, const char *name); |
112 | 153 | ||
154 | int sysfs_rename_link(struct kobject *kobj, struct kobject *target, | ||
155 | const char *old_name, const char *new_name); | ||
156 | |||
113 | int __must_check sysfs_create_group(struct kobject *kobj, | 157 | int __must_check sysfs_create_group(struct kobject *kobj, |
114 | const struct attribute_group *grp); | 158 | const struct attribute_group *grp); |
115 | int sysfs_update_group(struct kobject *kobj, | 159 | int sysfs_update_group(struct kobject *kobj, |
@@ -164,6 +208,12 @@ static inline int sysfs_create_file(struct kobject *kobj, | |||
164 | return 0; | 208 | return 0; |
165 | } | 209 | } |
166 | 210 | ||
211 | static inline int sysfs_create_files(struct kobject *kobj, | ||
212 | const struct attribute **attr) | ||
213 | { | ||
214 | return 0; | ||
215 | } | ||
216 | |||
167 | static inline int sysfs_chmod_file(struct kobject *kobj, | 217 | static inline int sysfs_chmod_file(struct kobject *kobj, |
168 | struct attribute *attr, mode_t mode) | 218 | struct attribute *attr, mode_t mode) |
169 | { | 219 | { |
@@ -175,6 +225,11 @@ static inline void sysfs_remove_file(struct kobject *kobj, | |||
175 | { | 225 | { |
176 | } | 226 | } |
177 | 227 | ||
228 | static inline void sysfs_remove_files(struct kobject *kobj, | ||
229 | const struct attribute **attr) | ||
230 | { | ||
231 | } | ||
232 | |||
178 | static inline int sysfs_create_bin_file(struct kobject *kobj, | 233 | static inline int sysfs_create_bin_file(struct kobject *kobj, |
179 | const struct bin_attribute *attr) | 234 | const struct bin_attribute *attr) |
180 | { | 235 | { |
@@ -203,6 +258,12 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name) | |||
203 | { | 258 | { |
204 | } | 259 | } |
205 | 260 | ||
261 | static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, | ||
262 | const char *old_name, const char *new_name) | ||
263 | { | ||
264 | return 0; | ||
265 | } | ||
266 | |||
206 | static inline int sysfs_create_group(struct kobject *kobj, | 267 | static inline int sysfs_create_group(struct kobject *kobj, |
207 | const struct attribute_group *grp) | 268 | const struct attribute_group *grp) |
208 | { | 269 | { |
diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h index 3398f4553269..b6523c1427ce 100644 --- a/include/linux/taskstats_kern.h +++ b/include/linux/taskstats_kern.h | |||
@@ -14,11 +14,6 @@ | |||
14 | extern struct kmem_cache *taskstats_cache; | 14 | extern struct kmem_cache *taskstats_cache; |
15 | extern struct mutex taskstats_exit_mutex; | 15 | extern struct mutex taskstats_exit_mutex; |
16 | 16 | ||
17 | static inline void taskstats_tgid_init(struct signal_struct *sig) | ||
18 | { | ||
19 | sig->stats = NULL; | ||
20 | } | ||
21 | |||
22 | static inline void taskstats_tgid_free(struct signal_struct *sig) | 17 | static inline void taskstats_tgid_free(struct signal_struct *sig) |
23 | { | 18 | { |
24 | if (sig->stats) | 19 | if (sig->stats) |
@@ -30,8 +25,6 @@ extern void taskstats_init_early(void); | |||
30 | #else | 25 | #else |
31 | static inline void taskstats_exit(struct task_struct *tsk, int group_dead) | 26 | static inline void taskstats_exit(struct task_struct *tsk, int group_dead) |
32 | {} | 27 | {} |
33 | static inline void taskstats_tgid_init(struct signal_struct *sig) | ||
34 | {} | ||
35 | static inline void taskstats_tgid_free(struct signal_struct *sig) | 28 | static inline void taskstats_tgid_free(struct signal_struct *sig) |
36 | {} | 29 | {} |
37 | static inline void taskstats_init_early(void) | 30 | static inline void taskstats_init_early(void) |
diff --git a/include/linux/tty.h b/include/linux/tty.h index d96e5882f129..568369a86306 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -514,6 +514,7 @@ extern void tty_ldisc_enable(struct tty_struct *tty); | |||
514 | 514 | ||
515 | /* n_tty.c */ | 515 | /* n_tty.c */ |
516 | extern struct tty_ldisc_ops tty_ldisc_N_TTY; | 516 | extern struct tty_ldisc_ops tty_ldisc_N_TTY; |
517 | extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops); | ||
517 | 518 | ||
518 | /* tty_audit.c */ | 519 | /* tty_audit.c */ |
519 | #ifdef CONFIG_AUDIT | 520 | #ifdef CONFIG_AUDIT |
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 0c4ee9b88f85..526d66f066a3 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h | |||
@@ -99,6 +99,12 @@ | |||
99 | * cease I/O to the tty driver. Can sleep. The driver should | 99 | * cease I/O to the tty driver. Can sleep. The driver should |
100 | * seek to perform this action quickly but should wait until | 100 | * seek to perform this action quickly but should wait until |
101 | * any pending driver I/O is completed. | 101 | * any pending driver I/O is completed. |
102 | * | ||
103 | * void (*dcd_change)(struct tty_struct *tty, unsigned int status, | ||
104 | * struct timespec *ts) | ||
105 | * | ||
106 | * Tells the discipline that the DCD pin has changed its status and | ||
107 | * the relative timestamp. Pointer ts can be NULL. | ||
102 | */ | 108 | */ |
103 | 109 | ||
104 | #include <linux/fs.h> | 110 | #include <linux/fs.h> |
@@ -136,6 +142,8 @@ struct tty_ldisc_ops { | |||
136 | void (*receive_buf)(struct tty_struct *, const unsigned char *cp, | 142 | void (*receive_buf)(struct tty_struct *, const unsigned char *cp, |
137 | char *fp, int count); | 143 | char *fp, int count); |
138 | void (*write_wakeup)(struct tty_struct *); | 144 | void (*write_wakeup)(struct tty_struct *); |
145 | void (*dcd_change)(struct tty_struct *, unsigned int, | ||
146 | struct timespec *); | ||
139 | 147 | ||
140 | struct module *owner; | 148 | struct module *owner; |
141 | 149 | ||
diff --git a/include/linux/usb.h b/include/linux/usb.h index 3492abf82e75..8c9f053111bb 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -512,9 +512,9 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev); | |||
512 | extern void usb_put_dev(struct usb_device *dev); | 512 | extern void usb_put_dev(struct usb_device *dev); |
513 | 513 | ||
514 | /* USB device locking */ | 514 | /* USB device locking */ |
515 | #define usb_lock_device(udev) down(&(udev)->dev.sem) | 515 | #define usb_lock_device(udev) device_lock(&(udev)->dev) |
516 | #define usb_unlock_device(udev) up(&(udev)->dev.sem) | 516 | #define usb_unlock_device(udev) device_unlock(&(udev)->dev) |
517 | #define usb_trylock_device(udev) down_trylock(&(udev)->dev.sem) | 517 | #define usb_trylock_device(udev) device_trylock(&(udev)->dev) |
518 | extern int usb_lock_device_for_reset(struct usb_device *udev, | 518 | extern int usb_lock_device_for_reset(struct usb_device *udev, |
519 | const struct usb_interface *iface); | 519 | const struct usb_interface *iface); |
520 | 520 | ||
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h index 6bb293684eb8..4d3e450e2b03 100644 --- a/include/linux/usb/audio.h +++ b/include/linux/usb/audio.h | |||
@@ -269,8 +269,8 @@ struct uac_format_type_i_ext_descriptor { | |||
269 | __u8 bLength; | 269 | __u8 bLength; |
270 | __u8 bDescriptorType; | 270 | __u8 bDescriptorType; |
271 | __u8 bDescriptorSubtype; | 271 | __u8 bDescriptorSubtype; |
272 | __u8 bSubslotSize; | ||
273 | __u8 bFormatType; | 272 | __u8 bFormatType; |
273 | __u8 bSubslotSize; | ||
274 | __u8 bBitResolution; | 274 | __u8 bBitResolution; |
275 | __u8 bHeaderLength; | 275 | __u8 bHeaderLength; |
276 | __u8 bControlSize; | 276 | __u8 bControlSize; |
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 82b7be4db89a..bd10a7908993 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
@@ -100,14 +100,9 @@ struct net { | |||
100 | extern struct net init_net; | 100 | extern struct net init_net; |
101 | 101 | ||
102 | #ifdef CONFIG_NET | 102 | #ifdef CONFIG_NET |
103 | #define INIT_NET_NS(net_ns) .net_ns = &init_net, | ||
104 | |||
105 | extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns); | 103 | extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns); |
106 | 104 | ||
107 | #else /* CONFIG_NET */ | 105 | #else /* CONFIG_NET */ |
108 | |||
109 | #define INIT_NET_NS(net_ns) | ||
110 | |||
111 | static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns) | 106 | static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns) |
112 | { | 107 | { |
113 | /* There is nothing to copy so this is a noop */ | 108 | /* There is nothing to copy so this is a noop */ |
diff --git a/include/scsi/sg.h b/include/scsi/sg.h index 934ae389671d..a9f3c6fc3f57 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h | |||
@@ -70,6 +70,9 @@ Major new features in SG 3.x driver (cf SG 2.x drivers) | |||
70 | (for the lk 2.2 series). | 70 | (for the lk 2.2 series). |
71 | */ | 71 | */ |
72 | 72 | ||
73 | #ifdef __KERNEL__ | ||
74 | extern int sg_big_buff; /* for sysctl */ | ||
75 | #endif | ||
73 | 76 | ||
74 | /* New interface introduced in the 3.x SG drivers follows */ | 77 | /* New interface introduced in the 3.x SG drivers follows */ |
75 | 78 | ||
diff --git a/include/sound/asound.h b/include/sound/asound.h index 1f57bb92eb5a..098595500632 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h | |||
@@ -544,7 +544,7 @@ struct snd_rawmidi_status { | |||
544 | * Timer section - /dev/snd/timer | 544 | * Timer section - /dev/snd/timer |
545 | */ | 545 | */ |
546 | 546 | ||
547 | #define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5) | 547 | #define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6) |
548 | 548 | ||
549 | enum { | 549 | enum { |
550 | SNDRV_TIMER_CLASS_NONE = -1, | 550 | SNDRV_TIMER_CLASS_NONE = -1, |
diff --git a/include/video/broadsheetfb.h b/include/video/broadsheetfb.h index a758534c0272..548d28f4ec67 100644 --- a/include/video/broadsheetfb.h +++ b/include/video/broadsheetfb.h | |||
@@ -29,11 +29,19 @@ | |||
29 | #define BS_CMD_UPD_FULL 0x33 | 29 | #define BS_CMD_UPD_FULL 0x33 |
30 | #define BS_CMD_UPD_GDRV_CLR 0x37 | 30 | #define BS_CMD_UPD_GDRV_CLR 0x37 |
31 | 31 | ||
32 | /* Broadsheet register interface defines */ | ||
33 | #define BS_REG_REV 0x00 | ||
34 | #define BS_REG_PRC 0x02 | ||
35 | |||
32 | /* Broadsheet pin interface specific defines */ | 36 | /* Broadsheet pin interface specific defines */ |
33 | #define BS_CS 0x01 | 37 | #define BS_CS 0x01 |
34 | #define BS_DC 0x02 | 38 | #define BS_DC 0x02 |
35 | #define BS_WR 0x03 | 39 | #define BS_WR 0x03 |
36 | 40 | ||
41 | /* Broadsheet IO interface specific defines */ | ||
42 | #define BS_MMIO_CMD 0x01 | ||
43 | #define BS_MMIO_DATA 0x02 | ||
44 | |||
37 | /* struct used by broadsheet. board specific stuff comes from *board */ | 45 | /* struct used by broadsheet. board specific stuff comes from *board */ |
38 | struct broadsheetfb_par { | 46 | struct broadsheetfb_par { |
39 | struct fb_info *info; | 47 | struct fb_info *info; |
@@ -41,6 +49,8 @@ struct broadsheetfb_par { | |||
41 | void (*write_reg)(struct broadsheetfb_par *, u16 reg, u16 val); | 49 | void (*write_reg)(struct broadsheetfb_par *, u16 reg, u16 val); |
42 | u16 (*read_reg)(struct broadsheetfb_par *, u16 reg); | 50 | u16 (*read_reg)(struct broadsheetfb_par *, u16 reg); |
43 | wait_queue_head_t waitq; | 51 | wait_queue_head_t waitq; |
52 | int panel_index; | ||
53 | struct mutex io_lock; | ||
44 | }; | 54 | }; |
45 | 55 | ||
46 | /* board specific routines */ | 56 | /* board specific routines */ |
@@ -48,12 +58,17 @@ struct broadsheet_board { | |||
48 | struct module *owner; | 58 | struct module *owner; |
49 | int (*init)(struct broadsheetfb_par *); | 59 | int (*init)(struct broadsheetfb_par *); |
50 | int (*wait_for_rdy)(struct broadsheetfb_par *); | 60 | int (*wait_for_rdy)(struct broadsheetfb_par *); |
51 | void (*set_ctl)(struct broadsheetfb_par *, unsigned char, u8); | ||
52 | void (*set_hdb)(struct broadsheetfb_par *, u16); | ||
53 | u16 (*get_hdb)(struct broadsheetfb_par *); | ||
54 | void (*cleanup)(struct broadsheetfb_par *); | 61 | void (*cleanup)(struct broadsheetfb_par *); |
55 | int (*get_panel_type)(void); | 62 | int (*get_panel_type)(void); |
56 | int (*setup_irq)(struct fb_info *); | 63 | int (*setup_irq)(struct fb_info *); |
57 | }; | ||
58 | 64 | ||
65 | /* Functions for boards that use GPIO */ | ||
66 | void (*set_ctl)(struct broadsheetfb_par *, unsigned char, u8); | ||
67 | void (*set_hdb)(struct broadsheetfb_par *, u16); | ||
68 | u16 (*get_hdb)(struct broadsheetfb_par *); | ||
69 | |||
70 | /* Functions for boards that have specialized MMIO */ | ||
71 | void (*mmio_write)(struct broadsheetfb_par *, int type, u16); | ||
72 | u16 (*mmio_read)(struct broadsheetfb_par *); | ||
73 | }; | ||
59 | #endif | 74 | #endif |
diff --git a/init/Kconfig b/init/Kconfig index 089a230e5652..eb77e8ccde1c 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -463,6 +463,7 @@ config HAVE_UNSTABLE_SCHED_CLOCK | |||
463 | 463 | ||
464 | menuconfig CGROUPS | 464 | menuconfig CGROUPS |
465 | boolean "Control Group support" | 465 | boolean "Control Group support" |
466 | depends on EVENTFD | ||
466 | help | 467 | help |
467 | This option adds support for grouping sets of processes together, for | 468 | This option adds support for grouping sets of processes together, for |
468 | use with process control subsystems such as Cpusets, CFS, memory | 469 | use with process control subsystems such as Cpusets, CFS, memory |
diff --git a/ipc/Makefile b/ipc/Makefile index 4e1955ea815d..9075e172e52c 100644 --- a/ipc/Makefile +++ b/ipc/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o | 5 | obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o |
6 | obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o | 6 | obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o syscall.o |
7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o | 7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o |
8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o | 8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o |
9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) | 9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index b6cb06451f4b..e4e3f04803ca 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -155,7 +155,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, | |||
155 | spin_lock(&mq_lock); | 155 | spin_lock(&mq_lock); |
156 | if (u->mq_bytes + mq_bytes < u->mq_bytes || | 156 | if (u->mq_bytes + mq_bytes < u->mq_bytes || |
157 | u->mq_bytes + mq_bytes > | 157 | u->mq_bytes + mq_bytes > |
158 | p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur) { | 158 | task_rlimit(p, RLIMIT_MSGQUEUE)) { |
159 | spin_unlock(&mq_lock); | 159 | spin_unlock(&mq_lock); |
160 | kfree(info->messages); | 160 | kfree(info->messages); |
161 | goto out_inode; | 161 | goto out_inode; |
@@ -764,8 +764,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | |||
764 | if (euid != shp->shm_perm.uid && | 764 | if (euid != shp->shm_perm.uid && |
765 | euid != shp->shm_perm.cuid) | 765 | euid != shp->shm_perm.cuid) |
766 | goto out_unlock; | 766 | goto out_unlock; |
767 | if (cmd == SHM_LOCK && | 767 | if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) |
768 | !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) | ||
769 | goto out_unlock; | 768 | goto out_unlock; |
770 | } | 769 | } |
771 | 770 | ||
diff --git a/ipc/syscall.c b/ipc/syscall.c new file mode 100644 index 000000000000..355a3da9ec73 --- /dev/null +++ b/ipc/syscall.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * sys_ipc() is the old de-multiplexer for the SysV IPC calls. | ||
3 | * | ||
4 | * This is really horribly ugly, and new architectures should just wire up | ||
5 | * the individual syscalls instead. | ||
6 | */ | ||
7 | #include <linux/unistd.h> | ||
8 | |||
9 | #ifdef __ARCH_WANT_SYS_IPC | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/ipc.h> | ||
12 | #include <linux/shm.h> | ||
13 | #include <linux/syscalls.h> | ||
14 | #include <linux/uaccess.h> | ||
15 | |||
16 | SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second, | ||
17 | unsigned long, third, void __user *, ptr, long, fifth) | ||
18 | { | ||
19 | int version, ret; | ||
20 | |||
21 | version = call >> 16; /* hack for backward compatibility */ | ||
22 | call &= 0xffff; | ||
23 | |||
24 | switch (call) { | ||
25 | case SEMOP: | ||
26 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
27 | second, NULL); | ||
28 | case SEMTIMEDOP: | ||
29 | return sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
30 | second, | ||
31 | (const struct timespec __user *)fifth); | ||
32 | |||
33 | case SEMGET: | ||
34 | return sys_semget(first, second, third); | ||
35 | case SEMCTL: { | ||
36 | union semun fourth; | ||
37 | if (!ptr) | ||
38 | return -EINVAL; | ||
39 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
40 | return -EFAULT; | ||
41 | return sys_semctl(first, second, third, fourth); | ||
42 | } | ||
43 | |||
44 | case MSGSND: | ||
45 | return sys_msgsnd(first, (struct msgbuf __user *) ptr, | ||
46 | second, third); | ||
47 | case MSGRCV: | ||
48 | switch (version) { | ||
49 | case 0: { | ||
50 | struct ipc_kludge tmp; | ||
51 | if (!ptr) | ||
52 | return -EINVAL; | ||
53 | |||
54 | if (copy_from_user(&tmp, | ||
55 | (struct ipc_kludge __user *) ptr, | ||
56 | sizeof(tmp))) | ||
57 | return -EFAULT; | ||
58 | return sys_msgrcv(first, tmp.msgp, second, | ||
59 | tmp.msgtyp, third); | ||
60 | } | ||
61 | default: | ||
62 | return sys_msgrcv(first, | ||
63 | (struct msgbuf __user *) ptr, | ||
64 | second, fifth, third); | ||
65 | } | ||
66 | case MSGGET: | ||
67 | return sys_msgget((key_t) first, second); | ||
68 | case MSGCTL: | ||
69 | return sys_msgctl(first, second, (struct msqid_ds __user *)ptr); | ||
70 | |||
71 | case SHMAT: | ||
72 | switch (version) { | ||
73 | default: { | ||
74 | unsigned long raddr; | ||
75 | ret = do_shmat(first, (char __user *)ptr, | ||
76 | second, &raddr); | ||
77 | if (ret) | ||
78 | return ret; | ||
79 | return put_user(raddr, (unsigned long __user *) third); | ||
80 | } | ||
81 | case 1: | ||
82 | /* | ||
83 | * This was the entry point for kernel-originating calls | ||
84 | * from iBCS2 in 2.2 days. | ||
85 | */ | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | case SHMDT: | ||
89 | return sys_shmdt((char __user *)ptr); | ||
90 | case SHMGET: | ||
91 | return sys_shmget(first, second, third); | ||
92 | case SHMCTL: | ||
93 | return sys_shmctl(first, second, | ||
94 | (struct shmid_ds __user *) ptr); | ||
95 | default: | ||
96 | return -ENOSYS; | ||
97 | } | ||
98 | } | ||
99 | #endif | ||
diff --git a/kernel/acct.c b/kernel/acct.c index a6605ca921b6..24f8c81fc48d 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -588,16 +588,6 @@ out: | |||
588 | } | 588 | } |
589 | 589 | ||
590 | /** | 590 | /** |
591 | * acct_init_pacct - initialize a new pacct_struct | ||
592 | * @pacct: per-process accounting info struct to initialize | ||
593 | */ | ||
594 | void acct_init_pacct(struct pacct_struct *pacct) | ||
595 | { | ||
596 | memset(pacct, 0, sizeof(struct pacct_struct)); | ||
597 | pacct->ac_utime = pacct->ac_stime = cputime_zero; | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * acct_collect - collect accounting information into pacct_struct | 591 | * acct_collect - collect accounting information into pacct_struct |
602 | * @exitcode: task exit code | 592 | * @exitcode: task exit code |
603 | * @group_dead: not 0, if this thread is the last one in the process. | 593 | * @group_dead: not 0, if this thread is the last one in the process. |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 4fd90e129772..ef909a329750 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4,6 +4,10 @@ | |||
4 | * Based originally on the cpuset system, extracted by Paul Menage | 4 | * Based originally on the cpuset system, extracted by Paul Menage |
5 | * Copyright (C) 2006 Google, Inc | 5 | * Copyright (C) 2006 Google, Inc |
6 | * | 6 | * |
7 | * Notifications support | ||
8 | * Copyright (C) 2009 Nokia Corporation | ||
9 | * Author: Kirill A. Shutemov | ||
10 | * | ||
7 | * Copyright notices from the original cpuset code: | 11 | * Copyright notices from the original cpuset code: |
8 | * -------------------------------------------------- | 12 | * -------------------------------------------------- |
9 | * Copyright (C) 2003 BULL SA. | 13 | * Copyright (C) 2003 BULL SA. |
@@ -44,6 +48,7 @@ | |||
44 | #include <linux/string.h> | 48 | #include <linux/string.h> |
45 | #include <linux/sort.h> | 49 | #include <linux/sort.h> |
46 | #include <linux/kmod.h> | 50 | #include <linux/kmod.h> |
51 | #include <linux/module.h> | ||
47 | #include <linux/delayacct.h> | 52 | #include <linux/delayacct.h> |
48 | #include <linux/cgroupstats.h> | 53 | #include <linux/cgroupstats.h> |
49 | #include <linux/hash.h> | 54 | #include <linux/hash.h> |
@@ -52,15 +57,21 @@ | |||
52 | #include <linux/pid_namespace.h> | 57 | #include <linux/pid_namespace.h> |
53 | #include <linux/idr.h> | 58 | #include <linux/idr.h> |
54 | #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */ | 59 | #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */ |
60 | #include <linux/eventfd.h> | ||
61 | #include <linux/poll.h> | ||
55 | 62 | ||
56 | #include <asm/atomic.h> | 63 | #include <asm/atomic.h> |
57 | 64 | ||
58 | static DEFINE_MUTEX(cgroup_mutex); | 65 | static DEFINE_MUTEX(cgroup_mutex); |
59 | 66 | ||
60 | /* Generate an array of cgroup subsystem pointers */ | 67 | /* |
68 | * Generate an array of cgroup subsystem pointers. At boot time, this is | ||
69 | * populated up to CGROUP_BUILTIN_SUBSYS_COUNT, and modular subsystems are | ||
70 | * registered after that. The mutable section of this array is protected by | ||
71 | * cgroup_mutex. | ||
72 | */ | ||
61 | #define SUBSYS(_x) &_x ## _subsys, | 73 | #define SUBSYS(_x) &_x ## _subsys, |
62 | 74 | static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = { | |
63 | static struct cgroup_subsys *subsys[] = { | ||
64 | #include <linux/cgroup_subsys.h> | 75 | #include <linux/cgroup_subsys.h> |
65 | }; | 76 | }; |
66 | 77 | ||
@@ -147,6 +158,35 @@ struct css_id { | |||
147 | unsigned short stack[0]; /* Array of Length (depth+1) */ | 158 | unsigned short stack[0]; /* Array of Length (depth+1) */ |
148 | }; | 159 | }; |
149 | 160 | ||
161 | /* | ||
162 | * cgroup_event represents events which userspace want to recieve. | ||
163 | */ | ||
164 | struct cgroup_event { | ||
165 | /* | ||
166 | * Cgroup which the event belongs to. | ||
167 | */ | ||
168 | struct cgroup *cgrp; | ||
169 | /* | ||
170 | * Control file which the event associated. | ||
171 | */ | ||
172 | struct cftype *cft; | ||
173 | /* | ||
174 | * eventfd to signal userspace about the event. | ||
175 | */ | ||
176 | struct eventfd_ctx *eventfd; | ||
177 | /* | ||
178 | * Each of these stored in a list by the cgroup. | ||
179 | */ | ||
180 | struct list_head list; | ||
181 | /* | ||
182 | * All fields below needed to unregister event when | ||
183 | * userspace closes eventfd. | ||
184 | */ | ||
185 | poll_table pt; | ||
186 | wait_queue_head_t *wqh; | ||
187 | wait_queue_t wait; | ||
188 | struct work_struct remove; | ||
189 | }; | ||
150 | 190 | ||
151 | /* The list of hierarchy roots */ | 191 | /* The list of hierarchy roots */ |
152 | 192 | ||
@@ -250,7 +290,8 @@ struct cg_cgroup_link { | |||
250 | static struct css_set init_css_set; | 290 | static struct css_set init_css_set; |
251 | static struct cg_cgroup_link init_css_set_link; | 291 | static struct cg_cgroup_link init_css_set_link; |
252 | 292 | ||
253 | static int cgroup_subsys_init_idr(struct cgroup_subsys *ss); | 293 | static int cgroup_init_idr(struct cgroup_subsys *ss, |
294 | struct cgroup_subsys_state *css); | ||
254 | 295 | ||
255 | /* css_set_lock protects the list of css_set objects, and the | 296 | /* css_set_lock protects the list of css_set objects, and the |
256 | * chain of tasks off each css_set. Nests outside task->alloc_lock | 297 | * chain of tasks off each css_set. Nests outside task->alloc_lock |
@@ -448,8 +489,11 @@ static struct css_set *find_existing_css_set( | |||
448 | struct hlist_node *node; | 489 | struct hlist_node *node; |
449 | struct css_set *cg; | 490 | struct css_set *cg; |
450 | 491 | ||
451 | /* Built the set of subsystem state objects that we want to | 492 | /* |
452 | * see in the new css_set */ | 493 | * Build the set of subsystem state objects that we want to see in the |
494 | * new css_set. while subsystems can change globally, the entries here | ||
495 | * won't change, so no need for locking. | ||
496 | */ | ||
453 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 497 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
454 | if (root->subsys_bits & (1UL << i)) { | 498 | if (root->subsys_bits & (1UL << i)) { |
455 | /* Subsystem is in this hierarchy. So we want | 499 | /* Subsystem is in this hierarchy. So we want |
@@ -696,6 +740,7 @@ void cgroup_lock(void) | |||
696 | { | 740 | { |
697 | mutex_lock(&cgroup_mutex); | 741 | mutex_lock(&cgroup_mutex); |
698 | } | 742 | } |
743 | EXPORT_SYMBOL_GPL(cgroup_lock); | ||
699 | 744 | ||
700 | /** | 745 | /** |
701 | * cgroup_unlock - release lock on cgroup changes | 746 | * cgroup_unlock - release lock on cgroup changes |
@@ -706,6 +751,7 @@ void cgroup_unlock(void) | |||
706 | { | 751 | { |
707 | mutex_unlock(&cgroup_mutex); | 752 | mutex_unlock(&cgroup_mutex); |
708 | } | 753 | } |
754 | EXPORT_SYMBOL_GPL(cgroup_unlock); | ||
709 | 755 | ||
710 | /* | 756 | /* |
711 | * A couple of forward declarations required, due to cyclic reference loop: | 757 | * A couple of forward declarations required, due to cyclic reference loop: |
@@ -757,6 +803,7 @@ static int cgroup_call_pre_destroy(struct cgroup *cgrp) | |||
757 | if (ret) | 803 | if (ret) |
758 | break; | 804 | break; |
759 | } | 805 | } |
806 | |||
760 | return ret; | 807 | return ret; |
761 | } | 808 | } |
762 | 809 | ||
@@ -884,7 +931,11 @@ void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css) | |||
884 | css_put(css); | 931 | css_put(css); |
885 | } | 932 | } |
886 | 933 | ||
887 | 934 | /* | |
935 | * Call with cgroup_mutex held. Drops reference counts on modules, including | ||
936 | * any duplicate ones that parse_cgroupfs_options took. If this function | ||
937 | * returns an error, no reference counts are touched. | ||
938 | */ | ||
888 | static int rebind_subsystems(struct cgroupfs_root *root, | 939 | static int rebind_subsystems(struct cgroupfs_root *root, |
889 | unsigned long final_bits) | 940 | unsigned long final_bits) |
890 | { | 941 | { |
@@ -892,6 +943,8 @@ static int rebind_subsystems(struct cgroupfs_root *root, | |||
892 | struct cgroup *cgrp = &root->top_cgroup; | 943 | struct cgroup *cgrp = &root->top_cgroup; |
893 | int i; | 944 | int i; |
894 | 945 | ||
946 | BUG_ON(!mutex_is_locked(&cgroup_mutex)); | ||
947 | |||
895 | removed_bits = root->actual_subsys_bits & ~final_bits; | 948 | removed_bits = root->actual_subsys_bits & ~final_bits; |
896 | added_bits = final_bits & ~root->actual_subsys_bits; | 949 | added_bits = final_bits & ~root->actual_subsys_bits; |
897 | /* Check that any added subsystems are currently free */ | 950 | /* Check that any added subsystems are currently free */ |
@@ -900,6 +953,12 @@ static int rebind_subsystems(struct cgroupfs_root *root, | |||
900 | struct cgroup_subsys *ss = subsys[i]; | 953 | struct cgroup_subsys *ss = subsys[i]; |
901 | if (!(bit & added_bits)) | 954 | if (!(bit & added_bits)) |
902 | continue; | 955 | continue; |
956 | /* | ||
957 | * Nobody should tell us to do a subsys that doesn't exist: | ||
958 | * parse_cgroupfs_options should catch that case and refcounts | ||
959 | * ensure that subsystems won't disappear once selected. | ||
960 | */ | ||
961 | BUG_ON(ss == NULL); | ||
903 | if (ss->root != &rootnode) { | 962 | if (ss->root != &rootnode) { |
904 | /* Subsystem isn't free */ | 963 | /* Subsystem isn't free */ |
905 | return -EBUSY; | 964 | return -EBUSY; |
@@ -919,6 +978,7 @@ static int rebind_subsystems(struct cgroupfs_root *root, | |||
919 | unsigned long bit = 1UL << i; | 978 | unsigned long bit = 1UL << i; |
920 | if (bit & added_bits) { | 979 | if (bit & added_bits) { |
921 | /* We're binding this subsystem to this hierarchy */ | 980 | /* We're binding this subsystem to this hierarchy */ |
981 | BUG_ON(ss == NULL); | ||
922 | BUG_ON(cgrp->subsys[i]); | 982 | BUG_ON(cgrp->subsys[i]); |
923 | BUG_ON(!dummytop->subsys[i]); | 983 | BUG_ON(!dummytop->subsys[i]); |
924 | BUG_ON(dummytop->subsys[i]->cgroup != dummytop); | 984 | BUG_ON(dummytop->subsys[i]->cgroup != dummytop); |
@@ -930,8 +990,10 @@ static int rebind_subsystems(struct cgroupfs_root *root, | |||
930 | if (ss->bind) | 990 | if (ss->bind) |
931 | ss->bind(ss, cgrp); | 991 | ss->bind(ss, cgrp); |
932 | mutex_unlock(&ss->hierarchy_mutex); | 992 | mutex_unlock(&ss->hierarchy_mutex); |
993 | /* refcount was already taken, and we're keeping it */ | ||
933 | } else if (bit & removed_bits) { | 994 | } else if (bit & removed_bits) { |
934 | /* We're removing this subsystem */ | 995 | /* We're removing this subsystem */ |
996 | BUG_ON(ss == NULL); | ||
935 | BUG_ON(cgrp->subsys[i] != dummytop->subsys[i]); | 997 | BUG_ON(cgrp->subsys[i] != dummytop->subsys[i]); |
936 | BUG_ON(cgrp->subsys[i]->cgroup != cgrp); | 998 | BUG_ON(cgrp->subsys[i]->cgroup != cgrp); |
937 | mutex_lock(&ss->hierarchy_mutex); | 999 | mutex_lock(&ss->hierarchy_mutex); |
@@ -942,9 +1004,20 @@ static int rebind_subsystems(struct cgroupfs_root *root, | |||
942 | subsys[i]->root = &rootnode; | 1004 | subsys[i]->root = &rootnode; |
943 | list_move(&ss->sibling, &rootnode.subsys_list); | 1005 | list_move(&ss->sibling, &rootnode.subsys_list); |
944 | mutex_unlock(&ss->hierarchy_mutex); | 1006 | mutex_unlock(&ss->hierarchy_mutex); |
1007 | /* subsystem is now free - drop reference on module */ | ||
1008 | module_put(ss->module); | ||
945 | } else if (bit & final_bits) { | 1009 | } else if (bit & final_bits) { |
946 | /* Subsystem state should already exist */ | 1010 | /* Subsystem state should already exist */ |
1011 | BUG_ON(ss == NULL); | ||
947 | BUG_ON(!cgrp->subsys[i]); | 1012 | BUG_ON(!cgrp->subsys[i]); |
1013 | /* | ||
1014 | * a refcount was taken, but we already had one, so | ||
1015 | * drop the extra reference. | ||
1016 | */ | ||
1017 | module_put(ss->module); | ||
1018 | #ifdef CONFIG_MODULE_UNLOAD | ||
1019 | BUG_ON(ss->module && !module_refcount(ss->module)); | ||
1020 | #endif | ||
948 | } else { | 1021 | } else { |
949 | /* Subsystem state shouldn't exist */ | 1022 | /* Subsystem state shouldn't exist */ |
950 | BUG_ON(cgrp->subsys[i]); | 1023 | BUG_ON(cgrp->subsys[i]); |
@@ -986,13 +1059,20 @@ struct cgroup_sb_opts { | |||
986 | 1059 | ||
987 | }; | 1060 | }; |
988 | 1061 | ||
989 | /* Convert a hierarchy specifier into a bitmask of subsystems and | 1062 | /* |
990 | * flags. */ | 1063 | * Convert a hierarchy specifier into a bitmask of subsystems and flags. Call |
991 | static int parse_cgroupfs_options(char *data, | 1064 | * with cgroup_mutex held to protect the subsys[] array. This function takes |
992 | struct cgroup_sb_opts *opts) | 1065 | * refcounts on subsystems to be used, unless it returns error, in which case |
1066 | * no refcounts are taken. | ||
1067 | */ | ||
1068 | static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) | ||
993 | { | 1069 | { |
994 | char *token, *o = data ?: "all"; | 1070 | char *token, *o = data ?: "all"; |
995 | unsigned long mask = (unsigned long)-1; | 1071 | unsigned long mask = (unsigned long)-1; |
1072 | int i; | ||
1073 | bool module_pin_failed = false; | ||
1074 | |||
1075 | BUG_ON(!mutex_is_locked(&cgroup_mutex)); | ||
996 | 1076 | ||
997 | #ifdef CONFIG_CPUSETS | 1077 | #ifdef CONFIG_CPUSETS |
998 | mask = ~(1UL << cpuset_subsys_id); | 1078 | mask = ~(1UL << cpuset_subsys_id); |
@@ -1005,10 +1085,11 @@ static int parse_cgroupfs_options(char *data, | |||
1005 | return -EINVAL; | 1085 | return -EINVAL; |
1006 | if (!strcmp(token, "all")) { | 1086 | if (!strcmp(token, "all")) { |
1007 | /* Add all non-disabled subsystems */ | 1087 | /* Add all non-disabled subsystems */ |
1008 | int i; | ||
1009 | opts->subsys_bits = 0; | 1088 | opts->subsys_bits = 0; |
1010 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 1089 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
1011 | struct cgroup_subsys *ss = subsys[i]; | 1090 | struct cgroup_subsys *ss = subsys[i]; |
1091 | if (ss == NULL) | ||
1092 | continue; | ||
1012 | if (!ss->disabled) | 1093 | if (!ss->disabled) |
1013 | opts->subsys_bits |= 1ul << i; | 1094 | opts->subsys_bits |= 1ul << i; |
1014 | } | 1095 | } |
@@ -1026,7 +1107,6 @@ static int parse_cgroupfs_options(char *data, | |||
1026 | if (!opts->release_agent) | 1107 | if (!opts->release_agent) |
1027 | return -ENOMEM; | 1108 | return -ENOMEM; |
1028 | } else if (!strncmp(token, "name=", 5)) { | 1109 | } else if (!strncmp(token, "name=", 5)) { |
1029 | int i; | ||
1030 | const char *name = token + 5; | 1110 | const char *name = token + 5; |
1031 | /* Can't specify an empty name */ | 1111 | /* Can't specify an empty name */ |
1032 | if (!strlen(name)) | 1112 | if (!strlen(name)) |
@@ -1050,9 +1130,10 @@ static int parse_cgroupfs_options(char *data, | |||
1050 | return -ENOMEM; | 1130 | return -ENOMEM; |
1051 | } else { | 1131 | } else { |
1052 | struct cgroup_subsys *ss; | 1132 | struct cgroup_subsys *ss; |
1053 | int i; | ||
1054 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 1133 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
1055 | ss = subsys[i]; | 1134 | ss = subsys[i]; |
1135 | if (ss == NULL) | ||
1136 | continue; | ||
1056 | if (!strcmp(token, ss->name)) { | 1137 | if (!strcmp(token, ss->name)) { |
1057 | if (!ss->disabled) | 1138 | if (!ss->disabled) |
1058 | set_bit(i, &opts->subsys_bits); | 1139 | set_bit(i, &opts->subsys_bits); |
@@ -1087,9 +1168,54 @@ static int parse_cgroupfs_options(char *data, | |||
1087 | if (!opts->subsys_bits && !opts->name) | 1168 | if (!opts->subsys_bits && !opts->name) |
1088 | return -EINVAL; | 1169 | return -EINVAL; |
1089 | 1170 | ||
1171 | /* | ||
1172 | * Grab references on all the modules we'll need, so the subsystems | ||
1173 | * don't dance around before rebind_subsystems attaches them. This may | ||
1174 | * take duplicate reference counts on a subsystem that's already used, | ||
1175 | * but rebind_subsystems handles this case. | ||
1176 | */ | ||
1177 | for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) { | ||
1178 | unsigned long bit = 1UL << i; | ||
1179 | |||
1180 | if (!(bit & opts->subsys_bits)) | ||
1181 | continue; | ||
1182 | if (!try_module_get(subsys[i]->module)) { | ||
1183 | module_pin_failed = true; | ||
1184 | break; | ||
1185 | } | ||
1186 | } | ||
1187 | if (module_pin_failed) { | ||
1188 | /* | ||
1189 | * oops, one of the modules was going away. this means that we | ||
1190 | * raced with a module_delete call, and to the user this is | ||
1191 | * essentially a "subsystem doesn't exist" case. | ||
1192 | */ | ||
1193 | for (i--; i >= CGROUP_BUILTIN_SUBSYS_COUNT; i--) { | ||
1194 | /* drop refcounts only on the ones we took */ | ||
1195 | unsigned long bit = 1UL << i; | ||
1196 | |||
1197 | if (!(bit & opts->subsys_bits)) | ||
1198 | continue; | ||
1199 | module_put(subsys[i]->module); | ||
1200 | } | ||
1201 | return -ENOENT; | ||
1202 | } | ||
1203 | |||
1090 | return 0; | 1204 | return 0; |
1091 | } | 1205 | } |
1092 | 1206 | ||
1207 | static void drop_parsed_module_refcounts(unsigned long subsys_bits) | ||
1208 | { | ||
1209 | int i; | ||
1210 | for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) { | ||
1211 | unsigned long bit = 1UL << i; | ||
1212 | |||
1213 | if (!(bit & subsys_bits)) | ||
1214 | continue; | ||
1215 | module_put(subsys[i]->module); | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1093 | static int cgroup_remount(struct super_block *sb, int *flags, char *data) | 1219 | static int cgroup_remount(struct super_block *sb, int *flags, char *data) |
1094 | { | 1220 | { |
1095 | int ret = 0; | 1221 | int ret = 0; |
@@ -1106,21 +1232,19 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
1106 | if (ret) | 1232 | if (ret) |
1107 | goto out_unlock; | 1233 | goto out_unlock; |
1108 | 1234 | ||
1109 | /* Don't allow flags to change at remount */ | 1235 | /* Don't allow flags or name to change at remount */ |
1110 | if (opts.flags != root->flags) { | 1236 | if (opts.flags != root->flags || |
1111 | ret = -EINVAL; | 1237 | (opts.name && strcmp(opts.name, root->name))) { |
1112 | goto out_unlock; | ||
1113 | } | ||
1114 | |||
1115 | /* Don't allow name to change at remount */ | ||
1116 | if (opts.name && strcmp(opts.name, root->name)) { | ||
1117 | ret = -EINVAL; | 1238 | ret = -EINVAL; |
1239 | drop_parsed_module_refcounts(opts.subsys_bits); | ||
1118 | goto out_unlock; | 1240 | goto out_unlock; |
1119 | } | 1241 | } |
1120 | 1242 | ||
1121 | ret = rebind_subsystems(root, opts.subsys_bits); | 1243 | ret = rebind_subsystems(root, opts.subsys_bits); |
1122 | if (ret) | 1244 | if (ret) { |
1245 | drop_parsed_module_refcounts(opts.subsys_bits); | ||
1123 | goto out_unlock; | 1246 | goto out_unlock; |
1247 | } | ||
1124 | 1248 | ||
1125 | /* (re)populate subsystem files */ | 1249 | /* (re)populate subsystem files */ |
1126 | cgroup_populate_dir(cgrp); | 1250 | cgroup_populate_dir(cgrp); |
@@ -1151,6 +1275,8 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) | |||
1151 | INIT_LIST_HEAD(&cgrp->release_list); | 1275 | INIT_LIST_HEAD(&cgrp->release_list); |
1152 | INIT_LIST_HEAD(&cgrp->pidlists); | 1276 | INIT_LIST_HEAD(&cgrp->pidlists); |
1153 | mutex_init(&cgrp->pidlist_mutex); | 1277 | mutex_init(&cgrp->pidlist_mutex); |
1278 | INIT_LIST_HEAD(&cgrp->event_list); | ||
1279 | spin_lock_init(&cgrp->event_list_lock); | ||
1154 | } | 1280 | } |
1155 | 1281 | ||
1156 | static void init_cgroup_root(struct cgroupfs_root *root) | 1282 | static void init_cgroup_root(struct cgroupfs_root *root) |
@@ -1306,7 +1432,9 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1306 | struct cgroupfs_root *new_root; | 1432 | struct cgroupfs_root *new_root; |
1307 | 1433 | ||
1308 | /* First find the desired set of subsystems */ | 1434 | /* First find the desired set of subsystems */ |
1435 | mutex_lock(&cgroup_mutex); | ||
1309 | ret = parse_cgroupfs_options(data, &opts); | 1436 | ret = parse_cgroupfs_options(data, &opts); |
1437 | mutex_unlock(&cgroup_mutex); | ||
1310 | if (ret) | 1438 | if (ret) |
1311 | goto out_err; | 1439 | goto out_err; |
1312 | 1440 | ||
@@ -1317,7 +1445,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1317 | new_root = cgroup_root_from_opts(&opts); | 1445 | new_root = cgroup_root_from_opts(&opts); |
1318 | if (IS_ERR(new_root)) { | 1446 | if (IS_ERR(new_root)) { |
1319 | ret = PTR_ERR(new_root); | 1447 | ret = PTR_ERR(new_root); |
1320 | goto out_err; | 1448 | goto drop_modules; |
1321 | } | 1449 | } |
1322 | opts.new_root = new_root; | 1450 | opts.new_root = new_root; |
1323 | 1451 | ||
@@ -1326,7 +1454,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1326 | if (IS_ERR(sb)) { | 1454 | if (IS_ERR(sb)) { |
1327 | ret = PTR_ERR(sb); | 1455 | ret = PTR_ERR(sb); |
1328 | cgroup_drop_root(opts.new_root); | 1456 | cgroup_drop_root(opts.new_root); |
1329 | goto out_err; | 1457 | goto drop_modules; |
1330 | } | 1458 | } |
1331 | 1459 | ||
1332 | root = sb->s_fs_info; | 1460 | root = sb->s_fs_info; |
@@ -1382,6 +1510,11 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1382 | free_cg_links(&tmp_cg_links); | 1510 | free_cg_links(&tmp_cg_links); |
1383 | goto drop_new_super; | 1511 | goto drop_new_super; |
1384 | } | 1512 | } |
1513 | /* | ||
1514 | * There must be no failure case after here, since rebinding | ||
1515 | * takes care of subsystems' refcounts, which are explicitly | ||
1516 | * dropped in the failure exit path. | ||
1517 | */ | ||
1385 | 1518 | ||
1386 | /* EBUSY should be the only error here */ | 1519 | /* EBUSY should be the only error here */ |
1387 | BUG_ON(ret); | 1520 | BUG_ON(ret); |
@@ -1420,6 +1553,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1420 | * any) is not needed | 1553 | * any) is not needed |
1421 | */ | 1554 | */ |
1422 | cgroup_drop_root(opts.new_root); | 1555 | cgroup_drop_root(opts.new_root); |
1556 | /* no subsys rebinding, so refcounts don't change */ | ||
1557 | drop_parsed_module_refcounts(opts.subsys_bits); | ||
1423 | } | 1558 | } |
1424 | 1559 | ||
1425 | simple_set_mnt(mnt, sb); | 1560 | simple_set_mnt(mnt, sb); |
@@ -1429,6 +1564,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1429 | 1564 | ||
1430 | drop_new_super: | 1565 | drop_new_super: |
1431 | deactivate_locked_super(sb); | 1566 | deactivate_locked_super(sb); |
1567 | drop_modules: | ||
1568 | drop_parsed_module_refcounts(opts.subsys_bits); | ||
1432 | out_err: | 1569 | out_err: |
1433 | kfree(opts.release_agent); | 1570 | kfree(opts.release_agent); |
1434 | kfree(opts.name); | 1571 | kfree(opts.name); |
@@ -1542,6 +1679,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) | |||
1542 | memmove(buf, start, buf + buflen - start); | 1679 | memmove(buf, start, buf + buflen - start); |
1543 | return 0; | 1680 | return 0; |
1544 | } | 1681 | } |
1682 | EXPORT_SYMBOL_GPL(cgroup_path); | ||
1545 | 1683 | ||
1546 | /** | 1684 | /** |
1547 | * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp' | 1685 | * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp' |
@@ -1554,7 +1692,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) | |||
1554 | int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | 1692 | int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) |
1555 | { | 1693 | { |
1556 | int retval = 0; | 1694 | int retval = 0; |
1557 | struct cgroup_subsys *ss; | 1695 | struct cgroup_subsys *ss, *failed_ss = NULL; |
1558 | struct cgroup *oldcgrp; | 1696 | struct cgroup *oldcgrp; |
1559 | struct css_set *cg; | 1697 | struct css_set *cg; |
1560 | struct css_set *newcg; | 1698 | struct css_set *newcg; |
@@ -1568,8 +1706,16 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | |||
1568 | for_each_subsys(root, ss) { | 1706 | for_each_subsys(root, ss) { |
1569 | if (ss->can_attach) { | 1707 | if (ss->can_attach) { |
1570 | retval = ss->can_attach(ss, cgrp, tsk, false); | 1708 | retval = ss->can_attach(ss, cgrp, tsk, false); |
1571 | if (retval) | 1709 | if (retval) { |
1572 | return retval; | 1710 | /* |
1711 | * Remember on which subsystem the can_attach() | ||
1712 | * failed, so that we only call cancel_attach() | ||
1713 | * against the subsystems whose can_attach() | ||
1714 | * succeeded. (See below) | ||
1715 | */ | ||
1716 | failed_ss = ss; | ||
1717 | goto out; | ||
1718 | } | ||
1573 | } | 1719 | } |
1574 | } | 1720 | } |
1575 | 1721 | ||
@@ -1583,14 +1729,17 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | |||
1583 | */ | 1729 | */ |
1584 | newcg = find_css_set(cg, cgrp); | 1730 | newcg = find_css_set(cg, cgrp); |
1585 | put_css_set(cg); | 1731 | put_css_set(cg); |
1586 | if (!newcg) | 1732 | if (!newcg) { |
1587 | return -ENOMEM; | 1733 | retval = -ENOMEM; |
1734 | goto out; | ||
1735 | } | ||
1588 | 1736 | ||
1589 | task_lock(tsk); | 1737 | task_lock(tsk); |
1590 | if (tsk->flags & PF_EXITING) { | 1738 | if (tsk->flags & PF_EXITING) { |
1591 | task_unlock(tsk); | 1739 | task_unlock(tsk); |
1592 | put_css_set(newcg); | 1740 | put_css_set(newcg); |
1593 | return -ESRCH; | 1741 | retval = -ESRCH; |
1742 | goto out; | ||
1594 | } | 1743 | } |
1595 | rcu_assign_pointer(tsk->cgroups, newcg); | 1744 | rcu_assign_pointer(tsk->cgroups, newcg); |
1596 | task_unlock(tsk); | 1745 | task_unlock(tsk); |
@@ -1616,7 +1765,22 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | |||
1616 | * is no longer empty. | 1765 | * is no longer empty. |
1617 | */ | 1766 | */ |
1618 | cgroup_wakeup_rmdir_waiter(cgrp); | 1767 | cgroup_wakeup_rmdir_waiter(cgrp); |
1619 | return 0; | 1768 | out: |
1769 | if (retval) { | ||
1770 | for_each_subsys(root, ss) { | ||
1771 | if (ss == failed_ss) | ||
1772 | /* | ||
1773 | * This subsystem was the one that failed the | ||
1774 | * can_attach() check earlier, so we don't need | ||
1775 | * to call cancel_attach() against it or any | ||
1776 | * remaining subsystems. | ||
1777 | */ | ||
1778 | break; | ||
1779 | if (ss->cancel_attach) | ||
1780 | ss->cancel_attach(ss, cgrp, tsk, false); | ||
1781 | } | ||
1782 | } | ||
1783 | return retval; | ||
1620 | } | 1784 | } |
1621 | 1785 | ||
1622 | /* | 1786 | /* |
@@ -1682,6 +1846,7 @@ bool cgroup_lock_live_group(struct cgroup *cgrp) | |||
1682 | } | 1846 | } |
1683 | return true; | 1847 | return true; |
1684 | } | 1848 | } |
1849 | EXPORT_SYMBOL_GPL(cgroup_lock_live_group); | ||
1685 | 1850 | ||
1686 | static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft, | 1851 | static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft, |
1687 | const char *buffer) | 1852 | const char *buffer) |
@@ -1950,6 +2115,16 @@ static const struct inode_operations cgroup_dir_inode_operations = { | |||
1950 | .rename = cgroup_rename, | 2115 | .rename = cgroup_rename, |
1951 | }; | 2116 | }; |
1952 | 2117 | ||
2118 | /* | ||
2119 | * Check if a file is a control file | ||
2120 | */ | ||
2121 | static inline struct cftype *__file_cft(struct file *file) | ||
2122 | { | ||
2123 | if (file->f_dentry->d_inode->i_fop != &cgroup_file_operations) | ||
2124 | return ERR_PTR(-EINVAL); | ||
2125 | return __d_cft(file->f_dentry); | ||
2126 | } | ||
2127 | |||
1953 | static int cgroup_create_file(struct dentry *dentry, mode_t mode, | 2128 | static int cgroup_create_file(struct dentry *dentry, mode_t mode, |
1954 | struct super_block *sb) | 2129 | struct super_block *sb) |
1955 | { | 2130 | { |
@@ -2069,6 +2244,7 @@ int cgroup_add_file(struct cgroup *cgrp, | |||
2069 | error = PTR_ERR(dentry); | 2244 | error = PTR_ERR(dentry); |
2070 | return error; | 2245 | return error; |
2071 | } | 2246 | } |
2247 | EXPORT_SYMBOL_GPL(cgroup_add_file); | ||
2072 | 2248 | ||
2073 | int cgroup_add_files(struct cgroup *cgrp, | 2249 | int cgroup_add_files(struct cgroup *cgrp, |
2074 | struct cgroup_subsys *subsys, | 2250 | struct cgroup_subsys *subsys, |
@@ -2083,6 +2259,7 @@ int cgroup_add_files(struct cgroup *cgrp, | |||
2083 | } | 2259 | } |
2084 | return 0; | 2260 | return 0; |
2085 | } | 2261 | } |
2262 | EXPORT_SYMBOL_GPL(cgroup_add_files); | ||
2086 | 2263 | ||
2087 | /** | 2264 | /** |
2088 | * cgroup_task_count - count the number of tasks in a cgroup. | 2265 | * cgroup_task_count - count the number of tasks in a cgroup. |
@@ -2468,7 +2645,8 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, | |||
2468 | { | 2645 | { |
2469 | struct cgroup_pidlist *l; | 2646 | struct cgroup_pidlist *l; |
2470 | /* don't need task_nsproxy() if we're looking at ourself */ | 2647 | /* don't need task_nsproxy() if we're looking at ourself */ |
2471 | struct pid_namespace *ns = get_pid_ns(current->nsproxy->pid_ns); | 2648 | struct pid_namespace *ns = current->nsproxy->pid_ns; |
2649 | |||
2472 | /* | 2650 | /* |
2473 | * We can't drop the pidlist_mutex before taking the l->mutex in case | 2651 | * We can't drop the pidlist_mutex before taking the l->mutex in case |
2474 | * the last ref-holder is trying to remove l from the list at the same | 2652 | * the last ref-holder is trying to remove l from the list at the same |
@@ -2478,8 +2656,6 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, | |||
2478 | mutex_lock(&cgrp->pidlist_mutex); | 2656 | mutex_lock(&cgrp->pidlist_mutex); |
2479 | list_for_each_entry(l, &cgrp->pidlists, links) { | 2657 | list_for_each_entry(l, &cgrp->pidlists, links) { |
2480 | if (l->key.type == type && l->key.ns == ns) { | 2658 | if (l->key.type == type && l->key.ns == ns) { |
2481 | /* found a matching list - drop the extra refcount */ | ||
2482 | put_pid_ns(ns); | ||
2483 | /* make sure l doesn't vanish out from under us */ | 2659 | /* make sure l doesn't vanish out from under us */ |
2484 | down_write(&l->mutex); | 2660 | down_write(&l->mutex); |
2485 | mutex_unlock(&cgrp->pidlist_mutex); | 2661 | mutex_unlock(&cgrp->pidlist_mutex); |
@@ -2490,13 +2666,12 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, | |||
2490 | l = kmalloc(sizeof(struct cgroup_pidlist), GFP_KERNEL); | 2666 | l = kmalloc(sizeof(struct cgroup_pidlist), GFP_KERNEL); |
2491 | if (!l) { | 2667 | if (!l) { |
2492 | mutex_unlock(&cgrp->pidlist_mutex); | 2668 | mutex_unlock(&cgrp->pidlist_mutex); |
2493 | put_pid_ns(ns); | ||
2494 | return l; | 2669 | return l; |
2495 | } | 2670 | } |
2496 | init_rwsem(&l->mutex); | 2671 | init_rwsem(&l->mutex); |
2497 | down_write(&l->mutex); | 2672 | down_write(&l->mutex); |
2498 | l->key.type = type; | 2673 | l->key.type = type; |
2499 | l->key.ns = ns; | 2674 | l->key.ns = get_pid_ns(ns); |
2500 | l->use_count = 0; /* don't increment here */ | 2675 | l->use_count = 0; /* don't increment here */ |
2501 | l->list = NULL; | 2676 | l->list = NULL; |
2502 | l->owner = cgrp; | 2677 | l->owner = cgrp; |
@@ -2804,6 +2979,174 @@ static int cgroup_write_notify_on_release(struct cgroup *cgrp, | |||
2804 | } | 2979 | } |
2805 | 2980 | ||
2806 | /* | 2981 | /* |
2982 | * Unregister event and free resources. | ||
2983 | * | ||
2984 | * Gets called from workqueue. | ||
2985 | */ | ||
2986 | static void cgroup_event_remove(struct work_struct *work) | ||
2987 | { | ||
2988 | struct cgroup_event *event = container_of(work, struct cgroup_event, | ||
2989 | remove); | ||
2990 | struct cgroup *cgrp = event->cgrp; | ||
2991 | |||
2992 | /* TODO: check return code */ | ||
2993 | event->cft->unregister_event(cgrp, event->cft, event->eventfd); | ||
2994 | |||
2995 | eventfd_ctx_put(event->eventfd); | ||
2996 | kfree(event); | ||
2997 | dput(cgrp->dentry); | ||
2998 | } | ||
2999 | |||
3000 | /* | ||
3001 | * Gets called on POLLHUP on eventfd when user closes it. | ||
3002 | * | ||
3003 | * Called with wqh->lock held and interrupts disabled. | ||
3004 | */ | ||
3005 | static int cgroup_event_wake(wait_queue_t *wait, unsigned mode, | ||
3006 | int sync, void *key) | ||
3007 | { | ||
3008 | struct cgroup_event *event = container_of(wait, | ||
3009 | struct cgroup_event, wait); | ||
3010 | struct cgroup *cgrp = event->cgrp; | ||
3011 | unsigned long flags = (unsigned long)key; | ||
3012 | |||
3013 | if (flags & POLLHUP) { | ||
3014 | remove_wait_queue_locked(event->wqh, &event->wait); | ||
3015 | spin_lock(&cgrp->event_list_lock); | ||
3016 | list_del(&event->list); | ||
3017 | spin_unlock(&cgrp->event_list_lock); | ||
3018 | /* | ||
3019 | * We are in atomic context, but cgroup_event_remove() may | ||
3020 | * sleep, so we have to call it in workqueue. | ||
3021 | */ | ||
3022 | schedule_work(&event->remove); | ||
3023 | } | ||
3024 | |||
3025 | return 0; | ||
3026 | } | ||
3027 | |||
3028 | static void cgroup_event_ptable_queue_proc(struct file *file, | ||
3029 | wait_queue_head_t *wqh, poll_table *pt) | ||
3030 | { | ||
3031 | struct cgroup_event *event = container_of(pt, | ||
3032 | struct cgroup_event, pt); | ||
3033 | |||
3034 | event->wqh = wqh; | ||
3035 | add_wait_queue(wqh, &event->wait); | ||
3036 | } | ||
3037 | |||
3038 | /* | ||
3039 | * Parse input and register new cgroup event handler. | ||
3040 | * | ||
3041 | * Input must be in format '<event_fd> <control_fd> <args>'. | ||
3042 | * Interpretation of args is defined by control file implementation. | ||
3043 | */ | ||
3044 | static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, | ||
3045 | const char *buffer) | ||
3046 | { | ||
3047 | struct cgroup_event *event = NULL; | ||
3048 | unsigned int efd, cfd; | ||
3049 | struct file *efile = NULL; | ||
3050 | struct file *cfile = NULL; | ||
3051 | char *endp; | ||
3052 | int ret; | ||
3053 | |||
3054 | efd = simple_strtoul(buffer, &endp, 10); | ||
3055 | if (*endp != ' ') | ||
3056 | return -EINVAL; | ||
3057 | buffer = endp + 1; | ||
3058 | |||
3059 | cfd = simple_strtoul(buffer, &endp, 10); | ||
3060 | if ((*endp != ' ') && (*endp != '\0')) | ||
3061 | return -EINVAL; | ||
3062 | buffer = endp + 1; | ||
3063 | |||
3064 | event = kzalloc(sizeof(*event), GFP_KERNEL); | ||
3065 | if (!event) | ||
3066 | return -ENOMEM; | ||
3067 | event->cgrp = cgrp; | ||
3068 | INIT_LIST_HEAD(&event->list); | ||
3069 | init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc); | ||
3070 | init_waitqueue_func_entry(&event->wait, cgroup_event_wake); | ||
3071 | INIT_WORK(&event->remove, cgroup_event_remove); | ||
3072 | |||
3073 | efile = eventfd_fget(efd); | ||
3074 | if (IS_ERR(efile)) { | ||
3075 | ret = PTR_ERR(efile); | ||
3076 | goto fail; | ||
3077 | } | ||
3078 | |||
3079 | event->eventfd = eventfd_ctx_fileget(efile); | ||
3080 | if (IS_ERR(event->eventfd)) { | ||
3081 | ret = PTR_ERR(event->eventfd); | ||
3082 | goto fail; | ||
3083 | } | ||
3084 | |||
3085 | cfile = fget(cfd); | ||
3086 | if (!cfile) { | ||
3087 | ret = -EBADF; | ||
3088 | goto fail; | ||
3089 | } | ||
3090 | |||
3091 | /* the process need read permission on control file */ | ||
3092 | ret = file_permission(cfile, MAY_READ); | ||
3093 | if (ret < 0) | ||
3094 | goto fail; | ||
3095 | |||
3096 | event->cft = __file_cft(cfile); | ||
3097 | if (IS_ERR(event->cft)) { | ||
3098 | ret = PTR_ERR(event->cft); | ||
3099 | goto fail; | ||
3100 | } | ||
3101 | |||
3102 | if (!event->cft->register_event || !event->cft->unregister_event) { | ||
3103 | ret = -EINVAL; | ||
3104 | goto fail; | ||
3105 | } | ||
3106 | |||
3107 | ret = event->cft->register_event(cgrp, event->cft, | ||
3108 | event->eventfd, buffer); | ||
3109 | if (ret) | ||
3110 | goto fail; | ||
3111 | |||
3112 | if (efile->f_op->poll(efile, &event->pt) & POLLHUP) { | ||
3113 | event->cft->unregister_event(cgrp, event->cft, event->eventfd); | ||
3114 | ret = 0; | ||
3115 | goto fail; | ||
3116 | } | ||
3117 | |||
3118 | /* | ||
3119 | * Events should be removed after rmdir of cgroup directory, but before | ||
3120 | * destroying subsystem state objects. Let's take reference to cgroup | ||
3121 | * directory dentry to do that. | ||
3122 | */ | ||
3123 | dget(cgrp->dentry); | ||
3124 | |||
3125 | spin_lock(&cgrp->event_list_lock); | ||
3126 | list_add(&event->list, &cgrp->event_list); | ||
3127 | spin_unlock(&cgrp->event_list_lock); | ||
3128 | |||
3129 | fput(cfile); | ||
3130 | fput(efile); | ||
3131 | |||
3132 | return 0; | ||
3133 | |||
3134 | fail: | ||
3135 | if (cfile) | ||
3136 | fput(cfile); | ||
3137 | |||
3138 | if (event && event->eventfd && !IS_ERR(event->eventfd)) | ||
3139 | eventfd_ctx_put(event->eventfd); | ||
3140 | |||
3141 | if (!IS_ERR_OR_NULL(efile)) | ||
3142 | fput(efile); | ||
3143 | |||
3144 | kfree(event); | ||
3145 | |||
3146 | return ret; | ||
3147 | } | ||
3148 | |||
3149 | /* | ||
2807 | * for the common functions, 'private' gives the type of file | 3150 | * for the common functions, 'private' gives the type of file |
2808 | */ | 3151 | */ |
2809 | /* for hysterical raisins, we can't put this on the older files */ | 3152 | /* for hysterical raisins, we can't put this on the older files */ |
@@ -2828,6 +3171,11 @@ static struct cftype files[] = { | |||
2828 | .read_u64 = cgroup_read_notify_on_release, | 3171 | .read_u64 = cgroup_read_notify_on_release, |
2829 | .write_u64 = cgroup_write_notify_on_release, | 3172 | .write_u64 = cgroup_write_notify_on_release, |
2830 | }, | 3173 | }, |
3174 | { | ||
3175 | .name = CGROUP_FILE_GENERIC_PREFIX "event_control", | ||
3176 | .write_string = cgroup_write_event_control, | ||
3177 | .mode = S_IWUGO, | ||
3178 | }, | ||
2831 | }; | 3179 | }; |
2832 | 3180 | ||
2833 | static struct cftype cft_release_agent = { | 3181 | static struct cftype cft_release_agent = { |
@@ -2892,8 +3240,14 @@ static void cgroup_lock_hierarchy(struct cgroupfs_root *root) | |||
2892 | /* We need to take each hierarchy_mutex in a consistent order */ | 3240 | /* We need to take each hierarchy_mutex in a consistent order */ |
2893 | int i; | 3241 | int i; |
2894 | 3242 | ||
3243 | /* | ||
3244 | * No worry about a race with rebind_subsystems that might mess up the | ||
3245 | * locking order, since both parties are under cgroup_mutex. | ||
3246 | */ | ||
2895 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 3247 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
2896 | struct cgroup_subsys *ss = subsys[i]; | 3248 | struct cgroup_subsys *ss = subsys[i]; |
3249 | if (ss == NULL) | ||
3250 | continue; | ||
2897 | if (ss->root == root) | 3251 | if (ss->root == root) |
2898 | mutex_lock(&ss->hierarchy_mutex); | 3252 | mutex_lock(&ss->hierarchy_mutex); |
2899 | } | 3253 | } |
@@ -2905,6 +3259,8 @@ static void cgroup_unlock_hierarchy(struct cgroupfs_root *root) | |||
2905 | 3259 | ||
2906 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 3260 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
2907 | struct cgroup_subsys *ss = subsys[i]; | 3261 | struct cgroup_subsys *ss = subsys[i]; |
3262 | if (ss == NULL) | ||
3263 | continue; | ||
2908 | if (ss->root == root) | 3264 | if (ss->root == root) |
2909 | mutex_unlock(&ss->hierarchy_mutex); | 3265 | mutex_unlock(&ss->hierarchy_mutex); |
2910 | } | 3266 | } |
@@ -3028,11 +3384,16 @@ static int cgroup_has_css_refs(struct cgroup *cgrp) | |||
3028 | * synchronization other than RCU, and the subsystem linked | 3384 | * synchronization other than RCU, and the subsystem linked |
3029 | * list isn't RCU-safe */ | 3385 | * list isn't RCU-safe */ |
3030 | int i; | 3386 | int i; |
3387 | /* | ||
3388 | * We won't need to lock the subsys array, because the subsystems | ||
3389 | * we're concerned about aren't going anywhere since our cgroup root | ||
3390 | * has a reference on them. | ||
3391 | */ | ||
3031 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 3392 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
3032 | struct cgroup_subsys *ss = subsys[i]; | 3393 | struct cgroup_subsys *ss = subsys[i]; |
3033 | struct cgroup_subsys_state *css; | 3394 | struct cgroup_subsys_state *css; |
3034 | /* Skip subsystems not in this hierarchy */ | 3395 | /* Skip subsystems not present or not in this hierarchy */ |
3035 | if (ss->root != cgrp->root) | 3396 | if (ss == NULL || ss->root != cgrp->root) |
3036 | continue; | 3397 | continue; |
3037 | css = cgrp->subsys[ss->subsys_id]; | 3398 | css = cgrp->subsys[ss->subsys_id]; |
3038 | /* When called from check_for_release() it's possible | 3399 | /* When called from check_for_release() it's possible |
@@ -3106,6 +3467,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
3106 | struct dentry *d; | 3467 | struct dentry *d; |
3107 | struct cgroup *parent; | 3468 | struct cgroup *parent; |
3108 | DEFINE_WAIT(wait); | 3469 | DEFINE_WAIT(wait); |
3470 | struct cgroup_event *event, *tmp; | ||
3109 | int ret; | 3471 | int ret; |
3110 | 3472 | ||
3111 | /* the vfs holds both inode->i_mutex already */ | 3473 | /* the vfs holds both inode->i_mutex already */ |
@@ -3189,6 +3551,20 @@ again: | |||
3189 | set_bit(CGRP_RELEASABLE, &parent->flags); | 3551 | set_bit(CGRP_RELEASABLE, &parent->flags); |
3190 | check_for_release(parent); | 3552 | check_for_release(parent); |
3191 | 3553 | ||
3554 | /* | ||
3555 | * Unregister events and notify userspace. | ||
3556 | * Notify userspace about cgroup removing only after rmdir of cgroup | ||
3557 | * directory to avoid race between userspace and kernelspace | ||
3558 | */ | ||
3559 | spin_lock(&cgrp->event_list_lock); | ||
3560 | list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) { | ||
3561 | list_del(&event->list); | ||
3562 | remove_wait_queue(event->wqh, &event->wait); | ||
3563 | eventfd_signal(event->eventfd, 1); | ||
3564 | schedule_work(&event->remove); | ||
3565 | } | ||
3566 | spin_unlock(&cgrp->event_list_lock); | ||
3567 | |||
3192 | mutex_unlock(&cgroup_mutex); | 3568 | mutex_unlock(&cgroup_mutex); |
3193 | return 0; | 3569 | return 0; |
3194 | } | 3570 | } |
@@ -3223,7 +3599,196 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | |||
3223 | mutex_init(&ss->hierarchy_mutex); | 3599 | mutex_init(&ss->hierarchy_mutex); |
3224 | lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key); | 3600 | lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key); |
3225 | ss->active = 1; | 3601 | ss->active = 1; |
3602 | |||
3603 | /* this function shouldn't be used with modular subsystems, since they | ||
3604 | * need to register a subsys_id, among other things */ | ||
3605 | BUG_ON(ss->module); | ||
3606 | } | ||
3607 | |||
3608 | /** | ||
3609 | * cgroup_load_subsys: load and register a modular subsystem at runtime | ||
3610 | * @ss: the subsystem to load | ||
3611 | * | ||
3612 | * This function should be called in a modular subsystem's initcall. If the | ||
3613 | * subsytem is built as a module, it will be assigned a new subsys_id and set | ||
3614 | * up for use. If the subsystem is built-in anyway, work is delegated to the | ||
3615 | * simpler cgroup_init_subsys. | ||
3616 | */ | ||
3617 | int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | ||
3618 | { | ||
3619 | int i; | ||
3620 | struct cgroup_subsys_state *css; | ||
3621 | |||
3622 | /* check name and function validity */ | ||
3623 | if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN || | ||
3624 | ss->create == NULL || ss->destroy == NULL) | ||
3625 | return -EINVAL; | ||
3626 | |||
3627 | /* | ||
3628 | * we don't support callbacks in modular subsystems. this check is | ||
3629 | * before the ss->module check for consistency; a subsystem that could | ||
3630 | * be a module should still have no callbacks even if the user isn't | ||
3631 | * compiling it as one. | ||
3632 | */ | ||
3633 | if (ss->fork || ss->exit) | ||
3634 | return -EINVAL; | ||
3635 | |||
3636 | /* | ||
3637 | * an optionally modular subsystem is built-in: we want to do nothing, | ||
3638 | * since cgroup_init_subsys will have already taken care of it. | ||
3639 | */ | ||
3640 | if (ss->module == NULL) { | ||
3641 | /* a few sanity checks */ | ||
3642 | BUG_ON(ss->subsys_id >= CGROUP_BUILTIN_SUBSYS_COUNT); | ||
3643 | BUG_ON(subsys[ss->subsys_id] != ss); | ||
3644 | return 0; | ||
3645 | } | ||
3646 | |||
3647 | /* | ||
3648 | * need to register a subsys id before anything else - for example, | ||
3649 | * init_cgroup_css needs it. | ||
3650 | */ | ||
3651 | mutex_lock(&cgroup_mutex); | ||
3652 | /* find the first empty slot in the array */ | ||
3653 | for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) { | ||
3654 | if (subsys[i] == NULL) | ||
3655 | break; | ||
3656 | } | ||
3657 | if (i == CGROUP_SUBSYS_COUNT) { | ||
3658 | /* maximum number of subsystems already registered! */ | ||
3659 | mutex_unlock(&cgroup_mutex); | ||
3660 | return -EBUSY; | ||
3661 | } | ||
3662 | /* assign ourselves the subsys_id */ | ||
3663 | ss->subsys_id = i; | ||
3664 | subsys[i] = ss; | ||
3665 | |||
3666 | /* | ||
3667 | * no ss->create seems to need anything important in the ss struct, so | ||
3668 | * this can happen first (i.e. before the rootnode attachment). | ||
3669 | */ | ||
3670 | css = ss->create(ss, dummytop); | ||
3671 | if (IS_ERR(css)) { | ||
3672 | /* failure case - need to deassign the subsys[] slot. */ | ||
3673 | subsys[i] = NULL; | ||
3674 | mutex_unlock(&cgroup_mutex); | ||
3675 | return PTR_ERR(css); | ||
3676 | } | ||
3677 | |||
3678 | list_add(&ss->sibling, &rootnode.subsys_list); | ||
3679 | ss->root = &rootnode; | ||
3680 | |||
3681 | /* our new subsystem will be attached to the dummy hierarchy. */ | ||
3682 | init_cgroup_css(css, ss, dummytop); | ||
3683 | /* init_idr must be after init_cgroup_css because it sets css->id. */ | ||
3684 | if (ss->use_id) { | ||
3685 | int ret = cgroup_init_idr(ss, css); | ||
3686 | if (ret) { | ||
3687 | dummytop->subsys[ss->subsys_id] = NULL; | ||
3688 | ss->destroy(ss, dummytop); | ||
3689 | subsys[i] = NULL; | ||
3690 | mutex_unlock(&cgroup_mutex); | ||
3691 | return ret; | ||
3692 | } | ||
3693 | } | ||
3694 | |||
3695 | /* | ||
3696 | * Now we need to entangle the css into the existing css_sets. unlike | ||
3697 | * in cgroup_init_subsys, there are now multiple css_sets, so each one | ||
3698 | * will need a new pointer to it; done by iterating the css_set_table. | ||
3699 | * furthermore, modifying the existing css_sets will corrupt the hash | ||
3700 | * table state, so each changed css_set will need its hash recomputed. | ||
3701 | * this is all done under the css_set_lock. | ||
3702 | */ | ||
3703 | write_lock(&css_set_lock); | ||
3704 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) { | ||
3705 | struct css_set *cg; | ||
3706 | struct hlist_node *node, *tmp; | ||
3707 | struct hlist_head *bucket = &css_set_table[i], *new_bucket; | ||
3708 | |||
3709 | hlist_for_each_entry_safe(cg, node, tmp, bucket, hlist) { | ||
3710 | /* skip entries that we already rehashed */ | ||
3711 | if (cg->subsys[ss->subsys_id]) | ||
3712 | continue; | ||
3713 | /* remove existing entry */ | ||
3714 | hlist_del(&cg->hlist); | ||
3715 | /* set new value */ | ||
3716 | cg->subsys[ss->subsys_id] = css; | ||
3717 | /* recompute hash and restore entry */ | ||
3718 | new_bucket = css_set_hash(cg->subsys); | ||
3719 | hlist_add_head(&cg->hlist, new_bucket); | ||
3720 | } | ||
3721 | } | ||
3722 | write_unlock(&css_set_lock); | ||
3723 | |||
3724 | mutex_init(&ss->hierarchy_mutex); | ||
3725 | lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key); | ||
3726 | ss->active = 1; | ||
3727 | |||
3728 | /* success! */ | ||
3729 | mutex_unlock(&cgroup_mutex); | ||
3730 | return 0; | ||
3226 | } | 3731 | } |
3732 | EXPORT_SYMBOL_GPL(cgroup_load_subsys); | ||
3733 | |||
3734 | /** | ||
3735 | * cgroup_unload_subsys: unload a modular subsystem | ||
3736 | * @ss: the subsystem to unload | ||
3737 | * | ||
3738 | * This function should be called in a modular subsystem's exitcall. When this | ||
3739 | * function is invoked, the refcount on the subsystem's module will be 0, so | ||
3740 | * the subsystem will not be attached to any hierarchy. | ||
3741 | */ | ||
3742 | void cgroup_unload_subsys(struct cgroup_subsys *ss) | ||
3743 | { | ||
3744 | struct cg_cgroup_link *link; | ||
3745 | struct hlist_head *hhead; | ||
3746 | |||
3747 | BUG_ON(ss->module == NULL); | ||
3748 | |||
3749 | /* | ||
3750 | * we shouldn't be called if the subsystem is in use, and the use of | ||
3751 | * try_module_get in parse_cgroupfs_options should ensure that it | ||
3752 | * doesn't start being used while we're killing it off. | ||
3753 | */ | ||
3754 | BUG_ON(ss->root != &rootnode); | ||
3755 | |||
3756 | mutex_lock(&cgroup_mutex); | ||
3757 | /* deassign the subsys_id */ | ||
3758 | BUG_ON(ss->subsys_id < CGROUP_BUILTIN_SUBSYS_COUNT); | ||
3759 | subsys[ss->subsys_id] = NULL; | ||
3760 | |||
3761 | /* remove subsystem from rootnode's list of subsystems */ | ||
3762 | list_del(&ss->sibling); | ||
3763 | |||
3764 | /* | ||
3765 | * disentangle the css from all css_sets attached to the dummytop. as | ||
3766 | * in loading, we need to pay our respects to the hashtable gods. | ||
3767 | */ | ||
3768 | write_lock(&css_set_lock); | ||
3769 | list_for_each_entry(link, &dummytop->css_sets, cgrp_link_list) { | ||
3770 | struct css_set *cg = link->cg; | ||
3771 | |||
3772 | hlist_del(&cg->hlist); | ||
3773 | BUG_ON(!cg->subsys[ss->subsys_id]); | ||
3774 | cg->subsys[ss->subsys_id] = NULL; | ||
3775 | hhead = css_set_hash(cg->subsys); | ||
3776 | hlist_add_head(&cg->hlist, hhead); | ||
3777 | } | ||
3778 | write_unlock(&css_set_lock); | ||
3779 | |||
3780 | /* | ||
3781 | * remove subsystem's css from the dummytop and free it - need to free | ||
3782 | * before marking as null because ss->destroy needs the cgrp->subsys | ||
3783 | * pointer to find their state. note that this also takes care of | ||
3784 | * freeing the css_id. | ||
3785 | */ | ||
3786 | ss->destroy(ss, dummytop); | ||
3787 | dummytop->subsys[ss->subsys_id] = NULL; | ||
3788 | |||
3789 | mutex_unlock(&cgroup_mutex); | ||
3790 | } | ||
3791 | EXPORT_SYMBOL_GPL(cgroup_unload_subsys); | ||
3227 | 3792 | ||
3228 | /** | 3793 | /** |
3229 | * cgroup_init_early - cgroup initialization at system boot | 3794 | * cgroup_init_early - cgroup initialization at system boot |
@@ -3253,7 +3818,8 @@ int __init cgroup_init_early(void) | |||
3253 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) | 3818 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) |
3254 | INIT_HLIST_HEAD(&css_set_table[i]); | 3819 | INIT_HLIST_HEAD(&css_set_table[i]); |
3255 | 3820 | ||
3256 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 3821 | /* at bootup time, we don't worry about modular subsystems */ |
3822 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
3257 | struct cgroup_subsys *ss = subsys[i]; | 3823 | struct cgroup_subsys *ss = subsys[i]; |
3258 | 3824 | ||
3259 | BUG_ON(!ss->name); | 3825 | BUG_ON(!ss->name); |
@@ -3288,12 +3854,13 @@ int __init cgroup_init(void) | |||
3288 | if (err) | 3854 | if (err) |
3289 | return err; | 3855 | return err; |
3290 | 3856 | ||
3291 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 3857 | /* at bootup time, we don't worry about modular subsystems */ |
3858 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
3292 | struct cgroup_subsys *ss = subsys[i]; | 3859 | struct cgroup_subsys *ss = subsys[i]; |
3293 | if (!ss->early_init) | 3860 | if (!ss->early_init) |
3294 | cgroup_init_subsys(ss); | 3861 | cgroup_init_subsys(ss); |
3295 | if (ss->use_id) | 3862 | if (ss->use_id) |
3296 | cgroup_subsys_init_idr(ss); | 3863 | cgroup_init_idr(ss, init_css_set.subsys[ss->subsys_id]); |
3297 | } | 3864 | } |
3298 | 3865 | ||
3299 | /* Add init_css_set to the hash table */ | 3866 | /* Add init_css_set to the hash table */ |
@@ -3397,9 +3964,16 @@ static int proc_cgroupstats_show(struct seq_file *m, void *v) | |||
3397 | int i; | 3964 | int i; |
3398 | 3965 | ||
3399 | seq_puts(m, "#subsys_name\thierarchy\tnum_cgroups\tenabled\n"); | 3966 | seq_puts(m, "#subsys_name\thierarchy\tnum_cgroups\tenabled\n"); |
3967 | /* | ||
3968 | * ideally we don't want subsystems moving around while we do this. | ||
3969 | * cgroup_mutex is also necessary to guarantee an atomic snapshot of | ||
3970 | * subsys/hierarchy state. | ||
3971 | */ | ||
3400 | mutex_lock(&cgroup_mutex); | 3972 | mutex_lock(&cgroup_mutex); |
3401 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 3973 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
3402 | struct cgroup_subsys *ss = subsys[i]; | 3974 | struct cgroup_subsys *ss = subsys[i]; |
3975 | if (ss == NULL) | ||
3976 | continue; | ||
3403 | seq_printf(m, "%s\t%d\t%d\t%d\n", | 3977 | seq_printf(m, "%s\t%d\t%d\t%d\n", |
3404 | ss->name, ss->root->hierarchy_id, | 3978 | ss->name, ss->root->hierarchy_id, |
3405 | ss->root->number_of_cgroups, !ss->disabled); | 3979 | ss->root->number_of_cgroups, !ss->disabled); |
@@ -3457,7 +4031,12 @@ void cgroup_fork_callbacks(struct task_struct *child) | |||
3457 | { | 4031 | { |
3458 | if (need_forkexit_callback) { | 4032 | if (need_forkexit_callback) { |
3459 | int i; | 4033 | int i; |
3460 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 4034 | /* |
4035 | * forkexit callbacks are only supported for builtin | ||
4036 | * subsystems, and the builtin section of the subsys array is | ||
4037 | * immutable, so we don't need to lock the subsys array here. | ||
4038 | */ | ||
4039 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
3461 | struct cgroup_subsys *ss = subsys[i]; | 4040 | struct cgroup_subsys *ss = subsys[i]; |
3462 | if (ss->fork) | 4041 | if (ss->fork) |
3463 | ss->fork(ss, child); | 4042 | ss->fork(ss, child); |
@@ -3526,7 +4105,11 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks) | |||
3526 | struct css_set *cg; | 4105 | struct css_set *cg; |
3527 | 4106 | ||
3528 | if (run_callbacks && need_forkexit_callback) { | 4107 | if (run_callbacks && need_forkexit_callback) { |
3529 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 4108 | /* |
4109 | * modular subsystems can't use callbacks, so no need to lock | ||
4110 | * the subsys array | ||
4111 | */ | ||
4112 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
3530 | struct cgroup_subsys *ss = subsys[i]; | 4113 | struct cgroup_subsys *ss = subsys[i]; |
3531 | if (ss->exit) | 4114 | if (ss->exit) |
3532 | ss->exit(ss, tsk); | 4115 | ss->exit(ss, tsk); |
@@ -3720,12 +4303,13 @@ static void check_for_release(struct cgroup *cgrp) | |||
3720 | } | 4303 | } |
3721 | } | 4304 | } |
3722 | 4305 | ||
3723 | void __css_put(struct cgroup_subsys_state *css) | 4306 | /* Caller must verify that the css is not for root cgroup */ |
4307 | void __css_put(struct cgroup_subsys_state *css, int count) | ||
3724 | { | 4308 | { |
3725 | struct cgroup *cgrp = css->cgroup; | 4309 | struct cgroup *cgrp = css->cgroup; |
3726 | int val; | 4310 | int val; |
3727 | rcu_read_lock(); | 4311 | rcu_read_lock(); |
3728 | val = atomic_dec_return(&css->refcnt); | 4312 | val = atomic_sub_return(count, &css->refcnt); |
3729 | if (val == 1) { | 4313 | if (val == 1) { |
3730 | if (notify_on_release(cgrp)) { | 4314 | if (notify_on_release(cgrp)) { |
3731 | set_bit(CGRP_RELEASABLE, &cgrp->flags); | 4315 | set_bit(CGRP_RELEASABLE, &cgrp->flags); |
@@ -3736,6 +4320,7 @@ void __css_put(struct cgroup_subsys_state *css) | |||
3736 | rcu_read_unlock(); | 4320 | rcu_read_unlock(); |
3737 | WARN_ON_ONCE(val < 1); | 4321 | WARN_ON_ONCE(val < 1); |
3738 | } | 4322 | } |
4323 | EXPORT_SYMBOL_GPL(__css_put); | ||
3739 | 4324 | ||
3740 | /* | 4325 | /* |
3741 | * Notify userspace when a cgroup is released, by running the | 4326 | * Notify userspace when a cgroup is released, by running the |
@@ -3817,8 +4402,11 @@ static int __init cgroup_disable(char *str) | |||
3817 | while ((token = strsep(&str, ",")) != NULL) { | 4402 | while ((token = strsep(&str, ",")) != NULL) { |
3818 | if (!*token) | 4403 | if (!*token) |
3819 | continue; | 4404 | continue; |
3820 | 4405 | /* | |
3821 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 4406 | * cgroup_disable, being at boot time, can't know about module |
4407 | * subsystems, so we don't worry about them. | ||
4408 | */ | ||
4409 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
3822 | struct cgroup_subsys *ss = subsys[i]; | 4410 | struct cgroup_subsys *ss = subsys[i]; |
3823 | 4411 | ||
3824 | if (!strcmp(token, ss->name)) { | 4412 | if (!strcmp(token, ss->name)) { |
@@ -3848,6 +4436,7 @@ unsigned short css_id(struct cgroup_subsys_state *css) | |||
3848 | return cssid->id; | 4436 | return cssid->id; |
3849 | return 0; | 4437 | return 0; |
3850 | } | 4438 | } |
4439 | EXPORT_SYMBOL_GPL(css_id); | ||
3851 | 4440 | ||
3852 | unsigned short css_depth(struct cgroup_subsys_state *css) | 4441 | unsigned short css_depth(struct cgroup_subsys_state *css) |
3853 | { | 4442 | { |
@@ -3857,6 +4446,7 @@ unsigned short css_depth(struct cgroup_subsys_state *css) | |||
3857 | return cssid->depth; | 4446 | return cssid->depth; |
3858 | return 0; | 4447 | return 0; |
3859 | } | 4448 | } |
4449 | EXPORT_SYMBOL_GPL(css_depth); | ||
3860 | 4450 | ||
3861 | bool css_is_ancestor(struct cgroup_subsys_state *child, | 4451 | bool css_is_ancestor(struct cgroup_subsys_state *child, |
3862 | const struct cgroup_subsys_state *root) | 4452 | const struct cgroup_subsys_state *root) |
@@ -3893,6 +4483,7 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css) | |||
3893 | spin_unlock(&ss->id_lock); | 4483 | spin_unlock(&ss->id_lock); |
3894 | call_rcu(&id->rcu_head, __free_css_id_cb); | 4484 | call_rcu(&id->rcu_head, __free_css_id_cb); |
3895 | } | 4485 | } |
4486 | EXPORT_SYMBOL_GPL(free_css_id); | ||
3896 | 4487 | ||
3897 | /* | 4488 | /* |
3898 | * This is called by init or create(). Then, calls to this function are | 4489 | * This is called by init or create(). Then, calls to this function are |
@@ -3942,15 +4533,14 @@ err_out: | |||
3942 | 4533 | ||
3943 | } | 4534 | } |
3944 | 4535 | ||
3945 | static int __init cgroup_subsys_init_idr(struct cgroup_subsys *ss) | 4536 | static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss, |
4537 | struct cgroup_subsys_state *rootcss) | ||
3946 | { | 4538 | { |
3947 | struct css_id *newid; | 4539 | struct css_id *newid; |
3948 | struct cgroup_subsys_state *rootcss; | ||
3949 | 4540 | ||
3950 | spin_lock_init(&ss->id_lock); | 4541 | spin_lock_init(&ss->id_lock); |
3951 | idr_init(&ss->idr); | 4542 | idr_init(&ss->idr); |
3952 | 4543 | ||
3953 | rootcss = init_css_set.subsys[ss->subsys_id]; | ||
3954 | newid = get_new_cssid(ss, 0); | 4544 | newid = get_new_cssid(ss, 0); |
3955 | if (IS_ERR(newid)) | 4545 | if (IS_ERR(newid)) |
3956 | return PTR_ERR(newid); | 4546 | return PTR_ERR(newid); |
@@ -4010,6 +4600,7 @@ struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id) | |||
4010 | 4600 | ||
4011 | return rcu_dereference(cssid->css); | 4601 | return rcu_dereference(cssid->css); |
4012 | } | 4602 | } |
4603 | EXPORT_SYMBOL_GPL(css_lookup); | ||
4013 | 4604 | ||
4014 | /** | 4605 | /** |
4015 | * css_get_next - lookup next cgroup under specified hierarchy. | 4606 | * css_get_next - lookup next cgroup under specified hierarchy. |
diff --git a/kernel/fork.c b/kernel/fork.c index b0ec34abc0bb..1beb6c303c41 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -833,17 +833,6 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig) | |||
833 | /* Thread group counters. */ | 833 | /* Thread group counters. */ |
834 | thread_group_cputime_init(sig); | 834 | thread_group_cputime_init(sig); |
835 | 835 | ||
836 | /* Expiration times and increments. */ | ||
837 | sig->it[CPUCLOCK_PROF].expires = cputime_zero; | ||
838 | sig->it[CPUCLOCK_PROF].incr = cputime_zero; | ||
839 | sig->it[CPUCLOCK_VIRT].expires = cputime_zero; | ||
840 | sig->it[CPUCLOCK_VIRT].incr = cputime_zero; | ||
841 | |||
842 | /* Cached expiration times. */ | ||
843 | sig->cputime_expires.prof_exp = cputime_zero; | ||
844 | sig->cputime_expires.virt_exp = cputime_zero; | ||
845 | sig->cputime_expires.sched_exp = 0; | ||
846 | |||
847 | cpu_limit = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur); | 836 | cpu_limit = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur); |
848 | if (cpu_limit != RLIM_INFINITY) { | 837 | if (cpu_limit != RLIM_INFINITY) { |
849 | sig->cputime_expires.prof_exp = secs_to_cputime(cpu_limit); | 838 | sig->cputime_expires.prof_exp = secs_to_cputime(cpu_limit); |
@@ -863,7 +852,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
863 | if (clone_flags & CLONE_THREAD) | 852 | if (clone_flags & CLONE_THREAD) |
864 | return 0; | 853 | return 0; |
865 | 854 | ||
866 | sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL); | 855 | sig = kmem_cache_zalloc(signal_cachep, GFP_KERNEL); |
867 | tsk->signal = sig; | 856 | tsk->signal = sig; |
868 | if (!sig) | 857 | if (!sig) |
869 | return -ENOMEM; | 858 | return -ENOMEM; |
@@ -871,46 +860,21 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
871 | atomic_set(&sig->count, 1); | 860 | atomic_set(&sig->count, 1); |
872 | atomic_set(&sig->live, 1); | 861 | atomic_set(&sig->live, 1); |
873 | init_waitqueue_head(&sig->wait_chldexit); | 862 | init_waitqueue_head(&sig->wait_chldexit); |
874 | sig->flags = 0; | ||
875 | if (clone_flags & CLONE_NEWPID) | 863 | if (clone_flags & CLONE_NEWPID) |
876 | sig->flags |= SIGNAL_UNKILLABLE; | 864 | sig->flags |= SIGNAL_UNKILLABLE; |
877 | sig->group_exit_code = 0; | ||
878 | sig->group_exit_task = NULL; | ||
879 | sig->group_stop_count = 0; | ||
880 | sig->curr_target = tsk; | 865 | sig->curr_target = tsk; |
881 | init_sigpending(&sig->shared_pending); | 866 | init_sigpending(&sig->shared_pending); |
882 | INIT_LIST_HEAD(&sig->posix_timers); | 867 | INIT_LIST_HEAD(&sig->posix_timers); |
883 | 868 | ||
884 | hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 869 | hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
885 | sig->it_real_incr.tv64 = 0; | ||
886 | sig->real_timer.function = it_real_fn; | 870 | sig->real_timer.function = it_real_fn; |
887 | 871 | ||
888 | sig->leader = 0; /* session leadership doesn't inherit */ | ||
889 | sig->tty_old_pgrp = NULL; | ||
890 | sig->tty = NULL; | ||
891 | |||
892 | sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; | ||
893 | sig->gtime = cputime_zero; | ||
894 | sig->cgtime = cputime_zero; | ||
895 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | ||
896 | sig->prev_utime = sig->prev_stime = cputime_zero; | ||
897 | #endif | ||
898 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; | ||
899 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; | ||
900 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; | ||
901 | sig->maxrss = sig->cmaxrss = 0; | ||
902 | task_io_accounting_init(&sig->ioac); | ||
903 | sig->sum_sched_runtime = 0; | ||
904 | taskstats_tgid_init(sig); | ||
905 | |||
906 | task_lock(current->group_leader); | 872 | task_lock(current->group_leader); |
907 | memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim); | 873 | memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim); |
908 | task_unlock(current->group_leader); | 874 | task_unlock(current->group_leader); |
909 | 875 | ||
910 | posix_cpu_timers_init_group(sig); | 876 | posix_cpu_timers_init_group(sig); |
911 | 877 | ||
912 | acct_init_pacct(&sig->pacct); | ||
913 | |||
914 | tty_audit_fork(sig); | 878 | tty_audit_fork(sig); |
915 | 879 | ||
916 | sig->oom_adj = current->signal->oom_adj; | 880 | sig->oom_adj = current->signal->oom_adj; |
diff --git a/kernel/module.c b/kernel/module.c index e5538d5f00ad..c968d3606dca 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1085,6 +1085,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
1085 | if (sattr->name == NULL) | 1085 | if (sattr->name == NULL) |
1086 | goto out; | 1086 | goto out; |
1087 | sect_attrs->nsections++; | 1087 | sect_attrs->nsections++; |
1088 | sysfs_attr_init(&sattr->mattr.attr); | ||
1088 | sattr->mattr.show = module_sect_show; | 1089 | sattr->mattr.show = module_sect_show; |
1089 | sattr->mattr.store = NULL; | 1090 | sattr->mattr.store = NULL; |
1090 | sattr->mattr.attr.name = sattr->name; | 1091 | sattr->mattr.attr.name = sattr->name; |
@@ -1180,6 +1181,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, | |||
1180 | if (sect_empty(&sechdrs[i])) | 1181 | if (sect_empty(&sechdrs[i])) |
1181 | continue; | 1182 | continue; |
1182 | if (sechdrs[i].sh_type == SHT_NOTE) { | 1183 | if (sechdrs[i].sh_type == SHT_NOTE) { |
1184 | sysfs_bin_attr_init(nattr); | ||
1183 | nattr->attr.name = mod->sect_attrs->attrs[loaded].name; | 1185 | nattr->attr.name = mod->sect_attrs->attrs[loaded].name; |
1184 | nattr->attr.mode = S_IRUGO; | 1186 | nattr->attr.mode = S_IRUGO; |
1185 | nattr->size = sechdrs[i].sh_size; | 1187 | nattr->size = sechdrs[i].sh_size; |
@@ -1252,6 +1254,7 @@ int module_add_modinfo_attrs(struct module *mod) | |||
1252 | if (!attr->test || | 1254 | if (!attr->test || |
1253 | (attr->test && attr->test(mod))) { | 1255 | (attr->test && attr->test(mod))) { |
1254 | memcpy(temp_attr, attr, sizeof(*temp_attr)); | 1256 | memcpy(temp_attr, attr, sizeof(*temp_attr)); |
1257 | sysfs_attr_init(&temp_attr->attr); | ||
1255 | error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); | 1258 | error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); |
1256 | ++temp_attr; | 1259 | ++temp_attr; |
1257 | } | 1260 | } |
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 09b4ff9711b2..2ab67233ee8f 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
@@ -24,7 +24,18 @@ | |||
24 | 24 | ||
25 | static struct kmem_cache *nsproxy_cachep; | 25 | static struct kmem_cache *nsproxy_cachep; |
26 | 26 | ||
27 | struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); | 27 | struct nsproxy init_nsproxy = { |
28 | .count = ATOMIC_INIT(1), | ||
29 | .uts_ns = &init_uts_ns, | ||
30 | #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC) | ||
31 | .ipc_ns = &init_ipc_ns, | ||
32 | #endif | ||
33 | .mnt_ns = NULL, | ||
34 | .pid_ns = &init_pid_ns, | ||
35 | #ifdef CONFIG_NET | ||
36 | .net_ns = &init_net, | ||
37 | #endif | ||
38 | }; | ||
28 | 39 | ||
29 | static inline struct nsproxy *create_nsproxy(void) | 40 | static inline struct nsproxy *create_nsproxy(void) |
30 | { | 41 | { |
diff --git a/kernel/params.c b/kernel/params.c index 8d95f5451b22..d55a53ec9234 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -516,6 +516,7 @@ static __modinit int add_sysfs_param(struct module_kobject *mk, | |||
516 | new->grp.attrs = attrs; | 516 | new->grp.attrs = attrs; |
517 | 517 | ||
518 | /* Tack new one on the end. */ | 518 | /* Tack new one on the end. */ |
519 | sysfs_attr_init(&new->attrs[num].mattr.attr); | ||
519 | new->attrs[num].param = kp; | 520 | new->attrs[num].param = kp; |
520 | new->attrs[num].mattr.show = param_attr_show; | 521 | new->attrs[num].mattr.show = param_attr_show; |
521 | new->attrs[num].mattr.store = param_attr_store; | 522 | new->attrs[num].mattr.store = param_attr_store; |
@@ -722,7 +723,7 @@ static ssize_t module_attr_store(struct kobject *kobj, | |||
722 | return ret; | 723 | return ret; |
723 | } | 724 | } |
724 | 725 | ||
725 | static struct sysfs_ops module_sysfs_ops = { | 726 | static const struct sysfs_ops module_sysfs_ops = { |
726 | .show = module_attr_show, | 727 | .show = module_attr_show, |
727 | .store = module_attr_store, | 728 | .store = module_attr_store, |
728 | }; | 729 | }; |
@@ -736,7 +737,7 @@ static int uevent_filter(struct kset *kset, struct kobject *kobj) | |||
736 | return 0; | 737 | return 0; |
737 | } | 738 | } |
738 | 739 | ||
739 | static struct kset_uevent_ops module_uevent_ops = { | 740 | static const struct kset_uevent_ops module_uevent_ops = { |
740 | .filter = uevent_filter, | 741 | .filter = uevent_filter, |
741 | }; | 742 | }; |
742 | 743 | ||
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 8e352c756ba7..f40560b86544 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -5481,13 +5481,16 @@ void __init perf_event_init(void) | |||
5481 | register_cpu_notifier(&perf_cpu_nb); | 5481 | register_cpu_notifier(&perf_cpu_nb); |
5482 | } | 5482 | } |
5483 | 5483 | ||
5484 | static ssize_t perf_show_reserve_percpu(struct sysdev_class *class, char *buf) | 5484 | static ssize_t perf_show_reserve_percpu(struct sysdev_class *class, |
5485 | struct sysdev_class_attribute *attr, | ||
5486 | char *buf) | ||
5485 | { | 5487 | { |
5486 | return sprintf(buf, "%d\n", perf_reserved_percpu); | 5488 | return sprintf(buf, "%d\n", perf_reserved_percpu); |
5487 | } | 5489 | } |
5488 | 5490 | ||
5489 | static ssize_t | 5491 | static ssize_t |
5490 | perf_set_reserve_percpu(struct sysdev_class *class, | 5492 | perf_set_reserve_percpu(struct sysdev_class *class, |
5493 | struct sysdev_class_attribute *attr, | ||
5491 | const char *buf, | 5494 | const char *buf, |
5492 | size_t count) | 5495 | size_t count) |
5493 | { | 5496 | { |
@@ -5516,13 +5519,17 @@ perf_set_reserve_percpu(struct sysdev_class *class, | |||
5516 | return count; | 5519 | return count; |
5517 | } | 5520 | } |
5518 | 5521 | ||
5519 | static ssize_t perf_show_overcommit(struct sysdev_class *class, char *buf) | 5522 | static ssize_t perf_show_overcommit(struct sysdev_class *class, |
5523 | struct sysdev_class_attribute *attr, | ||
5524 | char *buf) | ||
5520 | { | 5525 | { |
5521 | return sprintf(buf, "%d\n", perf_overcommit); | 5526 | return sprintf(buf, "%d\n", perf_overcommit); |
5522 | } | 5527 | } |
5523 | 5528 | ||
5524 | static ssize_t | 5529 | static ssize_t |
5525 | perf_set_overcommit(struct sysdev_class *class, const char *buf, size_t count) | 5530 | perf_set_overcommit(struct sysdev_class *class, |
5531 | struct sysdev_class_attribute *attr, | ||
5532 | const char *buf, size_t count) | ||
5526 | { | 5533 | { |
5527 | unsigned long val; | 5534 | unsigned long val; |
5528 | int err; | 5535 | int err; |
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 86b3796b0436..79aac93acf99 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c | |||
@@ -161,13 +161,12 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
161 | rcu_read_lock(); | 161 | rcu_read_lock(); |
162 | 162 | ||
163 | /* | 163 | /* |
164 | * Use force_sig() since it clears SIGNAL_UNKILLABLE ensuring | 164 | * Any nested-container's init processes won't ignore the |
165 | * any nested-container's init processes don't ignore the | 165 | * SEND_SIG_NOINFO signal, see send_signal()->si_fromuser(). |
166 | * signal | ||
167 | */ | 166 | */ |
168 | task = pid_task(find_vpid(nr), PIDTYPE_PID); | 167 | task = pid_task(find_vpid(nr), PIDTYPE_PID); |
169 | if (task) | 168 | if (task) |
170 | force_sig(SIGKILL, task); | 169 | send_sig_info(SIGKILL, SEND_SIG_NOINFO, task); |
171 | 170 | ||
172 | rcu_read_unlock(); | 171 | rcu_read_unlock(); |
173 | 172 | ||
diff --git a/kernel/sched.c b/kernel/sched.c index b47ceeec1a91..150b6988de49 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -7406,11 +7406,13 @@ static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt) | |||
7406 | 7406 | ||
7407 | #ifdef CONFIG_SCHED_MC | 7407 | #ifdef CONFIG_SCHED_MC |
7408 | static ssize_t sched_mc_power_savings_show(struct sysdev_class *class, | 7408 | static ssize_t sched_mc_power_savings_show(struct sysdev_class *class, |
7409 | struct sysdev_class_attribute *attr, | ||
7409 | char *page) | 7410 | char *page) |
7410 | { | 7411 | { |
7411 | return sprintf(page, "%u\n", sched_mc_power_savings); | 7412 | return sprintf(page, "%u\n", sched_mc_power_savings); |
7412 | } | 7413 | } |
7413 | static ssize_t sched_mc_power_savings_store(struct sysdev_class *class, | 7414 | static ssize_t sched_mc_power_savings_store(struct sysdev_class *class, |
7415 | struct sysdev_class_attribute *attr, | ||
7414 | const char *buf, size_t count) | 7416 | const char *buf, size_t count) |
7415 | { | 7417 | { |
7416 | return sched_power_savings_store(buf, count, 0); | 7418 | return sched_power_savings_store(buf, count, 0); |
@@ -7422,11 +7424,13 @@ static SYSDEV_CLASS_ATTR(sched_mc_power_savings, 0644, | |||
7422 | 7424 | ||
7423 | #ifdef CONFIG_SCHED_SMT | 7425 | #ifdef CONFIG_SCHED_SMT |
7424 | static ssize_t sched_smt_power_savings_show(struct sysdev_class *dev, | 7426 | static ssize_t sched_smt_power_savings_show(struct sysdev_class *dev, |
7427 | struct sysdev_class_attribute *attr, | ||
7425 | char *page) | 7428 | char *page) |
7426 | { | 7429 | { |
7427 | return sprintf(page, "%u\n", sched_smt_power_savings); | 7430 | return sprintf(page, "%u\n", sched_smt_power_savings); |
7428 | } | 7431 | } |
7429 | static ssize_t sched_smt_power_savings_store(struct sysdev_class *dev, | 7432 | static ssize_t sched_smt_power_savings_store(struct sysdev_class *dev, |
7433 | struct sysdev_class_attribute *attr, | ||
7430 | const char *buf, size_t count) | 7434 | const char *buf, size_t count) |
7431 | { | 7435 | { |
7432 | return sched_power_savings_store(buf, count, 1); | 7436 | return sched_power_savings_store(buf, count, 1); |
diff --git a/kernel/sys.c b/kernel/sys.c index 9814e43fb23b..8298878f4f71 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/task_io_accounting_ops.h> | 33 | #include <linux/task_io_accounting_ops.h> |
34 | #include <linux/seccomp.h> | 34 | #include <linux/seccomp.h> |
35 | #include <linux/cpu.h> | 35 | #include <linux/cpu.h> |
36 | #include <linux/personality.h> | ||
36 | #include <linux/ptrace.h> | 37 | #include <linux/ptrace.h> |
37 | #include <linux/fs_struct.h> | 38 | #include <linux/fs_struct.h> |
38 | 39 | ||
@@ -1114,6 +1115,15 @@ out: | |||
1114 | 1115 | ||
1115 | DECLARE_RWSEM(uts_sem); | 1116 | DECLARE_RWSEM(uts_sem); |
1116 | 1117 | ||
1118 | #ifdef COMPAT_UTS_MACHINE | ||
1119 | #define override_architecture(name) \ | ||
1120 | (current->personality == PER_LINUX32 && \ | ||
1121 | copy_to_user(name->machine, COMPAT_UTS_MACHINE, \ | ||
1122 | sizeof(COMPAT_UTS_MACHINE))) | ||
1123 | #else | ||
1124 | #define override_architecture(name) 0 | ||
1125 | #endif | ||
1126 | |||
1117 | SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) | 1127 | SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) |
1118 | { | 1128 | { |
1119 | int errno = 0; | 1129 | int errno = 0; |
@@ -1122,9 +1132,66 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) | |||
1122 | if (copy_to_user(name, utsname(), sizeof *name)) | 1132 | if (copy_to_user(name, utsname(), sizeof *name)) |
1123 | errno = -EFAULT; | 1133 | errno = -EFAULT; |
1124 | up_read(&uts_sem); | 1134 | up_read(&uts_sem); |
1135 | |||
1136 | if (!errno && override_architecture(name)) | ||
1137 | errno = -EFAULT; | ||
1125 | return errno; | 1138 | return errno; |
1126 | } | 1139 | } |
1127 | 1140 | ||
1141 | #ifdef __ARCH_WANT_SYS_OLD_UNAME | ||
1142 | /* | ||
1143 | * Old cruft | ||
1144 | */ | ||
1145 | SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) | ||
1146 | { | ||
1147 | int error = 0; | ||
1148 | |||
1149 | if (!name) | ||
1150 | return -EFAULT; | ||
1151 | |||
1152 | down_read(&uts_sem); | ||
1153 | if (copy_to_user(name, utsname(), sizeof(*name))) | ||
1154 | error = -EFAULT; | ||
1155 | up_read(&uts_sem); | ||
1156 | |||
1157 | if (!error && override_architecture(name)) | ||
1158 | error = -EFAULT; | ||
1159 | return error; | ||
1160 | } | ||
1161 | |||
1162 | SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name) | ||
1163 | { | ||
1164 | int error; | ||
1165 | |||
1166 | if (!name) | ||
1167 | return -EFAULT; | ||
1168 | if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) | ||
1169 | return -EFAULT; | ||
1170 | |||
1171 | down_read(&uts_sem); | ||
1172 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
1173 | __OLD_UTS_LEN); | ||
1174 | error |= __put_user(0, name->sysname + __OLD_UTS_LEN); | ||
1175 | error |= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
1176 | __OLD_UTS_LEN); | ||
1177 | error |= __put_user(0, name->nodename + __OLD_UTS_LEN); | ||
1178 | error |= __copy_to_user(&name->release, &utsname()->release, | ||
1179 | __OLD_UTS_LEN); | ||
1180 | error |= __put_user(0, name->release + __OLD_UTS_LEN); | ||
1181 | error |= __copy_to_user(&name->version, &utsname()->version, | ||
1182 | __OLD_UTS_LEN); | ||
1183 | error |= __put_user(0, name->version + __OLD_UTS_LEN); | ||
1184 | error |= __copy_to_user(&name->machine, &utsname()->machine, | ||
1185 | __OLD_UTS_LEN); | ||
1186 | error |= __put_user(0, name->machine + __OLD_UTS_LEN); | ||
1187 | up_read(&uts_sem); | ||
1188 | |||
1189 | if (!error && override_architecture(name)) | ||
1190 | error = -EFAULT; | ||
1191 | return error ? -EFAULT : 0; | ||
1192 | } | ||
1193 | #endif | ||
1194 | |||
1128 | SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) | 1195 | SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) |
1129 | { | 1196 | { |
1130 | int errno; | 1197 | int errno; |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 695384f12a7d..70f2ea758ffe 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
@@ -126,6 +126,7 @@ cond_syscall(sys_setreuid16); | |||
126 | cond_syscall(sys_setuid16); | 126 | cond_syscall(sys_setuid16); |
127 | cond_syscall(sys_vm86old); | 127 | cond_syscall(sys_vm86old); |
128 | cond_syscall(sys_vm86); | 128 | cond_syscall(sys_vm86); |
129 | cond_syscall(sys_ipc); | ||
129 | cond_syscall(compat_sys_ipc); | 130 | cond_syscall(compat_sys_ipc); |
130 | cond_syscall(compat_sys_sysctl); | 131 | cond_syscall(compat_sys_sysctl); |
131 | cond_syscall(sys_flock); | 132 | cond_syscall(sys_flock); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0ef19c614f6d..8686b0f5fc12 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/sysctl.h> | 25 | #include <linux/sysctl.h> |
26 | #include <linux/signal.h> | ||
26 | #include <linux/proc_fs.h> | 27 | #include <linux/proc_fs.h> |
27 | #include <linux/security.h> | 28 | #include <linux/security.h> |
28 | #include <linux/ctype.h> | 29 | #include <linux/ctype.h> |
@@ -60,13 +61,23 @@ | |||
60 | #include <asm/stacktrace.h> | 61 | #include <asm/stacktrace.h> |
61 | #include <asm/io.h> | 62 | #include <asm/io.h> |
62 | #endif | 63 | #endif |
64 | #ifdef CONFIG_BSD_PROCESS_ACCT | ||
65 | #include <linux/acct.h> | ||
66 | #endif | ||
67 | #ifdef CONFIG_RT_MUTEXES | ||
68 | #include <linux/rtmutex.h> | ||
69 | #endif | ||
70 | #if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_LOCK_STAT) | ||
71 | #include <linux/lockdep.h> | ||
72 | #endif | ||
73 | #ifdef CONFIG_CHR_DEV_SG | ||
74 | #include <scsi/sg.h> | ||
75 | #endif | ||
63 | 76 | ||
64 | 77 | ||
65 | #if defined(CONFIG_SYSCTL) | 78 | #if defined(CONFIG_SYSCTL) |
66 | 79 | ||
67 | /* External variables not in a header file. */ | 80 | /* External variables not in a header file. */ |
68 | extern int C_A_D; | ||
69 | extern int print_fatal_signals; | ||
70 | extern int sysctl_overcommit_memory; | 81 | extern int sysctl_overcommit_memory; |
71 | extern int sysctl_overcommit_ratio; | 82 | extern int sysctl_overcommit_ratio; |
72 | extern int sysctl_panic_on_oom; | 83 | extern int sysctl_panic_on_oom; |
@@ -88,9 +99,6 @@ extern int sysctl_nr_open_min, sysctl_nr_open_max; | |||
88 | #ifndef CONFIG_MMU | 99 | #ifndef CONFIG_MMU |
89 | extern int sysctl_nr_trim_pages; | 100 | extern int sysctl_nr_trim_pages; |
90 | #endif | 101 | #endif |
91 | #ifdef CONFIG_RCU_TORTURE_TEST | ||
92 | extern int rcutorture_runnable; | ||
93 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ | ||
94 | #ifdef CONFIG_BLOCK | 102 | #ifdef CONFIG_BLOCK |
95 | extern int blk_iopoll_enabled; | 103 | extern int blk_iopoll_enabled; |
96 | #endif | 104 | #endif |
@@ -120,14 +128,6 @@ static int min_percpu_pagelist_fract = 8; | |||
120 | 128 | ||
121 | static int ngroups_max = NGROUPS_MAX; | 129 | static int ngroups_max = NGROUPS_MAX; |
122 | 130 | ||
123 | #ifdef CONFIG_MODULES | ||
124 | extern char modprobe_path[]; | ||
125 | extern int modules_disabled; | ||
126 | #endif | ||
127 | #ifdef CONFIG_CHR_DEV_SG | ||
128 | extern int sg_big_buff; | ||
129 | #endif | ||
130 | |||
131 | #ifdef CONFIG_SPARC | 131 | #ifdef CONFIG_SPARC |
132 | #include <asm/system.h> | 132 | #include <asm/system.h> |
133 | #endif | 133 | #endif |
@@ -149,10 +149,6 @@ extern int sysctl_userprocess_debug; | |||
149 | extern int spin_retry; | 149 | extern int spin_retry; |
150 | #endif | 150 | #endif |
151 | 151 | ||
152 | #ifdef CONFIG_BSD_PROCESS_ACCT | ||
153 | extern int acct_parm[]; | ||
154 | #endif | ||
155 | |||
156 | #ifdef CONFIG_IA64 | 152 | #ifdef CONFIG_IA64 |
157 | extern int no_unaligned_warning; | 153 | extern int no_unaligned_warning; |
158 | extern int unaligned_dump_stack; | 154 | extern int unaligned_dump_stack; |
@@ -160,10 +156,6 @@ extern int unaligned_dump_stack; | |||
160 | 156 | ||
161 | extern struct ratelimit_state printk_ratelimit_state; | 157 | extern struct ratelimit_state printk_ratelimit_state; |
162 | 158 | ||
163 | #ifdef CONFIG_RT_MUTEXES | ||
164 | extern int max_lock_depth; | ||
165 | #endif | ||
166 | |||
167 | #ifdef CONFIG_PROC_SYSCTL | 159 | #ifdef CONFIG_PROC_SYSCTL |
168 | static int proc_do_cad_pid(struct ctl_table *table, int write, | 160 | static int proc_do_cad_pid(struct ctl_table *table, int write, |
169 | void __user *buffer, size_t *lenp, loff_t *ppos); | 161 | void __user *buffer, size_t *lenp, loff_t *ppos); |
@@ -202,9 +194,6 @@ extern struct ctl_table epoll_table[]; | |||
202 | int sysctl_legacy_va_layout; | 194 | int sysctl_legacy_va_layout; |
203 | #endif | 195 | #endif |
204 | 196 | ||
205 | extern int prove_locking; | ||
206 | extern int lock_stat; | ||
207 | |||
208 | /* The default sysctl tables: */ | 197 | /* The default sysctl tables: */ |
209 | 198 | ||
210 | static struct ctl_table root_table[] = { | 199 | static struct ctl_table root_table[] = { |
diff --git a/lib/kobject.c b/lib/kobject.c index b512b746d2af..8115eb1bbf4d 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -700,7 +700,7 @@ static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr, | |||
700 | return ret; | 700 | return ret; |
701 | } | 701 | } |
702 | 702 | ||
703 | struct sysfs_ops kobj_sysfs_ops = { | 703 | const struct sysfs_ops kobj_sysfs_ops = { |
704 | .show = kobj_attr_show, | 704 | .show = kobj_attr_show, |
705 | .store = kobj_attr_store, | 705 | .store = kobj_attr_store, |
706 | }; | 706 | }; |
@@ -789,7 +789,7 @@ static struct kobj_type kset_ktype = { | |||
789 | * If the kset was not able to be created, NULL will be returned. | 789 | * If the kset was not able to be created, NULL will be returned. |
790 | */ | 790 | */ |
791 | static struct kset *kset_create(const char *name, | 791 | static struct kset *kset_create(const char *name, |
792 | struct kset_uevent_ops *uevent_ops, | 792 | const struct kset_uevent_ops *uevent_ops, |
793 | struct kobject *parent_kobj) | 793 | struct kobject *parent_kobj) |
794 | { | 794 | { |
795 | struct kset *kset; | 795 | struct kset *kset; |
@@ -832,7 +832,7 @@ static struct kset *kset_create(const char *name, | |||
832 | * If the kset was not able to be created, NULL will be returned. | 832 | * If the kset was not able to be created, NULL will be returned. |
833 | */ | 833 | */ |
834 | struct kset *kset_create_and_add(const char *name, | 834 | struct kset *kset_create_and_add(const char *name, |
835 | struct kset_uevent_ops *uevent_ops, | 835 | const struct kset_uevent_ops *uevent_ops, |
836 | struct kobject *parent_kobj) | 836 | struct kobject *parent_kobj) |
837 | { | 837 | { |
838 | struct kset *kset; | 838 | struct kset *kset; |
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 920a3ca6e259..c9d3a3e8405d 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c | |||
@@ -95,7 +95,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
95 | const char *subsystem; | 95 | const char *subsystem; |
96 | struct kobject *top_kobj; | 96 | struct kobject *top_kobj; |
97 | struct kset *kset; | 97 | struct kset *kset; |
98 | struct kset_uevent_ops *uevent_ops; | 98 | const struct kset_uevent_ops *uevent_ops; |
99 | u64 seq; | 99 | u64 seq; |
100 | int i = 0; | 100 | int i = 0; |
101 | int retval = 0; | 101 | int retval = 0; |
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c index 215447c55261..2c13ecc5bb2c 100644 --- a/lib/zlib_inflate/inffast.c +++ b/lib/zlib_inflate/inffast.c | |||
@@ -8,21 +8,6 @@ | |||
8 | #include "inflate.h" | 8 | #include "inflate.h" |
9 | #include "inffast.h" | 9 | #include "inffast.h" |
10 | 10 | ||
11 | /* Only do the unaligned "Faster" variant when | ||
12 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is set | ||
13 | * | ||
14 | * On powerpc, it won't be as we don't include autoconf.h | ||
15 | * automatically for the boot wrapper, which is intended as | ||
16 | * we run in an environment where we may not be able to deal | ||
17 | * with (even rare) alignment faults. In addition, we do not | ||
18 | * define __KERNEL__ for arch/powerpc/boot unlike x86 | ||
19 | */ | ||
20 | |||
21 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
22 | #include <asm/unaligned.h> | ||
23 | #include <asm/byteorder.h> | ||
24 | #endif | ||
25 | |||
26 | #ifndef ASMINF | 11 | #ifndef ASMINF |
27 | 12 | ||
28 | /* Allow machine dependent optimization for post-increment or pre-increment. | 13 | /* Allow machine dependent optimization for post-increment or pre-increment. |
@@ -36,14 +21,31 @@ | |||
36 | - Pentium III (Anderson) | 21 | - Pentium III (Anderson) |
37 | - M68060 (Nikl) | 22 | - M68060 (Nikl) |
38 | */ | 23 | */ |
24 | union uu { | ||
25 | unsigned short us; | ||
26 | unsigned char b[2]; | ||
27 | }; | ||
28 | |||
29 | /* Endian independed version */ | ||
30 | static inline unsigned short | ||
31 | get_unaligned16(const unsigned short *p) | ||
32 | { | ||
33 | union uu mm; | ||
34 | unsigned char *b = (unsigned char *)p; | ||
35 | |||
36 | mm.b[0] = b[0]; | ||
37 | mm.b[1] = b[1]; | ||
38 | return mm.us; | ||
39 | } | ||
40 | |||
39 | #ifdef POSTINC | 41 | #ifdef POSTINC |
40 | # define OFF 0 | 42 | # define OFF 0 |
41 | # define PUP(a) *(a)++ | 43 | # define PUP(a) *(a)++ |
42 | # define UP_UNALIGNED(a) get_unaligned((a)++) | 44 | # define UP_UNALIGNED(a) get_unaligned16((a)++) |
43 | #else | 45 | #else |
44 | # define OFF 1 | 46 | # define OFF 1 |
45 | # define PUP(a) *++(a) | 47 | # define PUP(a) *++(a) |
46 | # define UP_UNALIGNED(a) get_unaligned(++(a)) | 48 | # define UP_UNALIGNED(a) get_unaligned16(++(a)) |
47 | #endif | 49 | #endif |
48 | 50 | ||
49 | /* | 51 | /* |
@@ -256,7 +258,6 @@ void inflate_fast(z_streamp strm, unsigned start) | |||
256 | } | 258 | } |
257 | } | 259 | } |
258 | else { | 260 | else { |
259 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
260 | unsigned short *sout; | 261 | unsigned short *sout; |
261 | unsigned long loops; | 262 | unsigned long loops; |
262 | 263 | ||
@@ -274,22 +275,25 @@ void inflate_fast(z_streamp strm, unsigned start) | |||
274 | sfrom = (unsigned short *)(from - OFF); | 275 | sfrom = (unsigned short *)(from - OFF); |
275 | loops = len >> 1; | 276 | loops = len >> 1; |
276 | do | 277 | do |
278 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
279 | PUP(sout) = PUP(sfrom); | ||
280 | #else | ||
277 | PUP(sout) = UP_UNALIGNED(sfrom); | 281 | PUP(sout) = UP_UNALIGNED(sfrom); |
282 | #endif | ||
278 | while (--loops); | 283 | while (--loops); |
279 | out = (unsigned char *)sout + OFF; | 284 | out = (unsigned char *)sout + OFF; |
280 | from = (unsigned char *)sfrom + OFF; | 285 | from = (unsigned char *)sfrom + OFF; |
281 | } else { /* dist == 1 or dist == 2 */ | 286 | } else { /* dist == 1 or dist == 2 */ |
282 | unsigned short pat16; | 287 | unsigned short pat16; |
283 | 288 | ||
284 | pat16 = *(sout-2+2*OFF); | 289 | pat16 = *(sout-1+OFF); |
285 | if (dist == 1) | 290 | if (dist == 1) { |
286 | #if defined(__BIG_ENDIAN) | 291 | union uu mm; |
287 | pat16 = (pat16 & 0xff) | ((pat16 & 0xff) << 8); | 292 | /* copy one char pattern to both bytes */ |
288 | #elif defined(__LITTLE_ENDIAN) | 293 | mm.us = pat16; |
289 | pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00) >> 8); | 294 | mm.b[0] = mm.b[1]; |
290 | #else | 295 | pat16 = mm.us; |
291 | #error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined | 296 | } |
292 | #endif | ||
293 | loops = len >> 1; | 297 | loops = len >> 1; |
294 | do | 298 | do |
295 | PUP(sout) = pat16; | 299 | PUP(sout) = pat16; |
@@ -298,20 +302,6 @@ void inflate_fast(z_streamp strm, unsigned start) | |||
298 | } | 302 | } |
299 | if (len & 1) | 303 | if (len & 1) |
300 | PUP(out) = PUP(from); | 304 | PUP(out) = PUP(from); |
301 | #else /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ | ||
302 | from = out - dist; /* copy direct from output */ | ||
303 | do { /* minimum length is three */ | ||
304 | PUP(out) = PUP(from); | ||
305 | PUP(out) = PUP(from); | ||
306 | PUP(out) = PUP(from); | ||
307 | len -= 3; | ||
308 | } while (len > 2); | ||
309 | if (len) { | ||
310 | PUP(out) = PUP(from); | ||
311 | if (len > 1) | ||
312 | PUP(out) = PUP(from); | ||
313 | } | ||
314 | #endif /* !CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ | ||
315 | } | 305 | } |
316 | } | 306 | } |
317 | else if ((op & 64) == 0) { /* 2nd level distance code */ | 307 | else if ((op & 64) == 0) { /* 2nd level distance code */ |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d813823ab08f..7973b5221fb8 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -6,6 +6,10 @@ | |||
6 | * Copyright 2007 OpenVZ SWsoft Inc | 6 | * Copyright 2007 OpenVZ SWsoft Inc |
7 | * Author: Pavel Emelianov <xemul@openvz.org> | 7 | * Author: Pavel Emelianov <xemul@openvz.org> |
8 | * | 8 | * |
9 | * Memory thresholds | ||
10 | * Copyright (C) 2009 Nokia Corporation | ||
11 | * Author: Kirill A. Shutemov | ||
12 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or | 15 | * the Free Software Foundation; either version 2 of the License, or |
@@ -21,6 +25,7 @@ | |||
21 | #include <linux/memcontrol.h> | 25 | #include <linux/memcontrol.h> |
22 | #include <linux/cgroup.h> | 26 | #include <linux/cgroup.h> |
23 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/hugetlb.h> | ||
24 | #include <linux/pagemap.h> | 29 | #include <linux/pagemap.h> |
25 | #include <linux/smp.h> | 30 | #include <linux/smp.h> |
26 | #include <linux/page-flags.h> | 31 | #include <linux/page-flags.h> |
@@ -32,7 +37,10 @@ | |||
32 | #include <linux/rbtree.h> | 37 | #include <linux/rbtree.h> |
33 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
34 | #include <linux/swap.h> | 39 | #include <linux/swap.h> |
40 | #include <linux/swapops.h> | ||
35 | #include <linux/spinlock.h> | 41 | #include <linux/spinlock.h> |
42 | #include <linux/eventfd.h> | ||
43 | #include <linux/sort.h> | ||
36 | #include <linux/fs.h> | 44 | #include <linux/fs.h> |
37 | #include <linux/seq_file.h> | 45 | #include <linux/seq_file.h> |
38 | #include <linux/vmalloc.h> | 46 | #include <linux/vmalloc.h> |
@@ -55,7 +63,15 @@ static int really_do_swap_account __initdata = 1; /* for remember boot option*/ | |||
55 | #define do_swap_account (0) | 63 | #define do_swap_account (0) |
56 | #endif | 64 | #endif |
57 | 65 | ||
58 | #define SOFTLIMIT_EVENTS_THRESH (1000) | 66 | /* |
67 | * Per memcg event counter is incremented at every pagein/pageout. This counter | ||
68 | * is used for trigger some periodic events. This is straightforward and better | ||
69 | * than using jiffies etc. to handle periodic memcg event. | ||
70 | * | ||
71 | * These values will be used as !((event) & ((1 <<(thresh)) - 1)) | ||
72 | */ | ||
73 | #define THRESHOLDS_EVENTS_THRESH (7) /* once in 128 */ | ||
74 | #define SOFTLIMIT_EVENTS_THRESH (10) /* once in 1024 */ | ||
59 | 75 | ||
60 | /* | 76 | /* |
61 | * Statistics for memory cgroup. | 77 | * Statistics for memory cgroup. |
@@ -69,62 +85,16 @@ enum mem_cgroup_stat_index { | |||
69 | MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ | 85 | MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ |
70 | MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */ | 86 | MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */ |
71 | MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */ | 87 | MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */ |
72 | MEM_CGROUP_STAT_EVENTS, /* sum of pagein + pageout for internal use */ | ||
73 | MEM_CGROUP_STAT_SWAPOUT, /* # of pages, swapped out */ | 88 | MEM_CGROUP_STAT_SWAPOUT, /* # of pages, swapped out */ |
89 | MEM_CGROUP_EVENTS, /* incremented at every pagein/pageout */ | ||
74 | 90 | ||
75 | MEM_CGROUP_STAT_NSTATS, | 91 | MEM_CGROUP_STAT_NSTATS, |
76 | }; | 92 | }; |
77 | 93 | ||
78 | struct mem_cgroup_stat_cpu { | 94 | struct mem_cgroup_stat_cpu { |
79 | s64 count[MEM_CGROUP_STAT_NSTATS]; | 95 | s64 count[MEM_CGROUP_STAT_NSTATS]; |
80 | } ____cacheline_aligned_in_smp; | ||
81 | |||
82 | struct mem_cgroup_stat { | ||
83 | struct mem_cgroup_stat_cpu cpustat[0]; | ||
84 | }; | 96 | }; |
85 | 97 | ||
86 | static inline void | ||
87 | __mem_cgroup_stat_reset_safe(struct mem_cgroup_stat_cpu *stat, | ||
88 | enum mem_cgroup_stat_index idx) | ||
89 | { | ||
90 | stat->count[idx] = 0; | ||
91 | } | ||
92 | |||
93 | static inline s64 | ||
94 | __mem_cgroup_stat_read_local(struct mem_cgroup_stat_cpu *stat, | ||
95 | enum mem_cgroup_stat_index idx) | ||
96 | { | ||
97 | return stat->count[idx]; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * For accounting under irq disable, no need for increment preempt count. | ||
102 | */ | ||
103 | static inline void __mem_cgroup_stat_add_safe(struct mem_cgroup_stat_cpu *stat, | ||
104 | enum mem_cgroup_stat_index idx, int val) | ||
105 | { | ||
106 | stat->count[idx] += val; | ||
107 | } | ||
108 | |||
109 | static s64 mem_cgroup_read_stat(struct mem_cgroup_stat *stat, | ||
110 | enum mem_cgroup_stat_index idx) | ||
111 | { | ||
112 | int cpu; | ||
113 | s64 ret = 0; | ||
114 | for_each_possible_cpu(cpu) | ||
115 | ret += stat->cpustat[cpu].count[idx]; | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static s64 mem_cgroup_local_usage(struct mem_cgroup_stat *stat) | ||
120 | { | ||
121 | s64 ret; | ||
122 | |||
123 | ret = mem_cgroup_read_stat(stat, MEM_CGROUP_STAT_CACHE); | ||
124 | ret += mem_cgroup_read_stat(stat, MEM_CGROUP_STAT_RSS); | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | /* | 98 | /* |
129 | * per-zone information in memory controller. | 99 | * per-zone information in memory controller. |
130 | */ | 100 | */ |
@@ -174,6 +144,22 @@ struct mem_cgroup_tree { | |||
174 | 144 | ||
175 | static struct mem_cgroup_tree soft_limit_tree __read_mostly; | 145 | static struct mem_cgroup_tree soft_limit_tree __read_mostly; |
176 | 146 | ||
147 | struct mem_cgroup_threshold { | ||
148 | struct eventfd_ctx *eventfd; | ||
149 | u64 threshold; | ||
150 | }; | ||
151 | |||
152 | struct mem_cgroup_threshold_ary { | ||
153 | /* An array index points to threshold just below usage. */ | ||
154 | atomic_t current_threshold; | ||
155 | /* Size of entries[] */ | ||
156 | unsigned int size; | ||
157 | /* Array of thresholds */ | ||
158 | struct mem_cgroup_threshold entries[0]; | ||
159 | }; | ||
160 | |||
161 | static void mem_cgroup_threshold(struct mem_cgroup *mem); | ||
162 | |||
177 | /* | 163 | /* |
178 | * The memory controller data structure. The memory controller controls both | 164 | * The memory controller data structure. The memory controller controls both |
179 | * page cache and RSS per cgroup. We would eventually like to provide | 165 | * page cache and RSS per cgroup. We would eventually like to provide |
@@ -217,7 +203,7 @@ struct mem_cgroup { | |||
217 | * Should the accounting and control be hierarchical, per subtree? | 203 | * Should the accounting and control be hierarchical, per subtree? |
218 | */ | 204 | */ |
219 | bool use_hierarchy; | 205 | bool use_hierarchy; |
220 | unsigned long last_oom_jiffies; | 206 | atomic_t oom_lock; |
221 | atomic_t refcnt; | 207 | atomic_t refcnt; |
222 | 208 | ||
223 | unsigned int swappiness; | 209 | unsigned int swappiness; |
@@ -225,10 +211,48 @@ struct mem_cgroup { | |||
225 | /* set when res.limit == memsw.limit */ | 211 | /* set when res.limit == memsw.limit */ |
226 | bool memsw_is_minimum; | 212 | bool memsw_is_minimum; |
227 | 213 | ||
214 | /* protect arrays of thresholds */ | ||
215 | struct mutex thresholds_lock; | ||
216 | |||
217 | /* thresholds for memory usage. RCU-protected */ | ||
218 | struct mem_cgroup_threshold_ary *thresholds; | ||
219 | |||
220 | /* thresholds for mem+swap usage. RCU-protected */ | ||
221 | struct mem_cgroup_threshold_ary *memsw_thresholds; | ||
222 | |||
228 | /* | 223 | /* |
229 | * statistics. This must be placed at the end of memcg. | 224 | * Should we move charges of a task when a task is moved into this |
225 | * mem_cgroup ? And what type of charges should we move ? | ||
230 | */ | 226 | */ |
231 | struct mem_cgroup_stat stat; | 227 | unsigned long move_charge_at_immigrate; |
228 | |||
229 | /* | ||
230 | * percpu counter. | ||
231 | */ | ||
232 | struct mem_cgroup_stat_cpu *stat; | ||
233 | }; | ||
234 | |||
235 | /* Stuffs for move charges at task migration. */ | ||
236 | /* | ||
237 | * Types of charges to be moved. "move_charge_at_immitgrate" is treated as a | ||
238 | * left-shifted bitmap of these types. | ||
239 | */ | ||
240 | enum move_type { | ||
241 | MOVE_CHARGE_TYPE_ANON, /* private anonymous page and swap of it */ | ||
242 | NR_MOVE_TYPE, | ||
243 | }; | ||
244 | |||
245 | /* "mc" and its members are protected by cgroup_mutex */ | ||
246 | static struct move_charge_struct { | ||
247 | struct mem_cgroup *from; | ||
248 | struct mem_cgroup *to; | ||
249 | unsigned long precharge; | ||
250 | unsigned long moved_charge; | ||
251 | unsigned long moved_swap; | ||
252 | struct task_struct *moving_task; /* a task moving charges */ | ||
253 | wait_queue_head_t waitq; /* a waitq for other context */ | ||
254 | } mc = { | ||
255 | .waitq = __WAIT_QUEUE_HEAD_INITIALIZER(mc.waitq), | ||
232 | }; | 256 | }; |
233 | 257 | ||
234 | /* | 258 | /* |
@@ -371,23 +395,6 @@ mem_cgroup_remove_exceeded(struct mem_cgroup *mem, | |||
371 | spin_unlock(&mctz->lock); | 395 | spin_unlock(&mctz->lock); |
372 | } | 396 | } |
373 | 397 | ||
374 | static bool mem_cgroup_soft_limit_check(struct mem_cgroup *mem) | ||
375 | { | ||
376 | bool ret = false; | ||
377 | int cpu; | ||
378 | s64 val; | ||
379 | struct mem_cgroup_stat_cpu *cpustat; | ||
380 | |||
381 | cpu = get_cpu(); | ||
382 | cpustat = &mem->stat.cpustat[cpu]; | ||
383 | val = __mem_cgroup_stat_read_local(cpustat, MEM_CGROUP_STAT_EVENTS); | ||
384 | if (unlikely(val > SOFTLIMIT_EVENTS_THRESH)) { | ||
385 | __mem_cgroup_stat_reset_safe(cpustat, MEM_CGROUP_STAT_EVENTS); | ||
386 | ret = true; | ||
387 | } | ||
388 | put_cpu(); | ||
389 | return ret; | ||
390 | } | ||
391 | 398 | ||
392 | static void mem_cgroup_update_tree(struct mem_cgroup *mem, struct page *page) | 399 | static void mem_cgroup_update_tree(struct mem_cgroup *mem, struct page *page) |
393 | { | 400 | { |
@@ -481,17 +488,31 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz) | |||
481 | return mz; | 488 | return mz; |
482 | } | 489 | } |
483 | 490 | ||
491 | static s64 mem_cgroup_read_stat(struct mem_cgroup *mem, | ||
492 | enum mem_cgroup_stat_index idx) | ||
493 | { | ||
494 | int cpu; | ||
495 | s64 val = 0; | ||
496 | |||
497 | for_each_possible_cpu(cpu) | ||
498 | val += per_cpu(mem->stat->count[idx], cpu); | ||
499 | return val; | ||
500 | } | ||
501 | |||
502 | static s64 mem_cgroup_local_usage(struct mem_cgroup *mem) | ||
503 | { | ||
504 | s64 ret; | ||
505 | |||
506 | ret = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_RSS); | ||
507 | ret += mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_CACHE); | ||
508 | return ret; | ||
509 | } | ||
510 | |||
484 | static void mem_cgroup_swap_statistics(struct mem_cgroup *mem, | 511 | static void mem_cgroup_swap_statistics(struct mem_cgroup *mem, |
485 | bool charge) | 512 | bool charge) |
486 | { | 513 | { |
487 | int val = (charge) ? 1 : -1; | 514 | int val = (charge) ? 1 : -1; |
488 | struct mem_cgroup_stat *stat = &mem->stat; | 515 | this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_SWAPOUT], val); |
489 | struct mem_cgroup_stat_cpu *cpustat; | ||
490 | int cpu = get_cpu(); | ||
491 | |||
492 | cpustat = &stat->cpustat[cpu]; | ||
493 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_SWAPOUT, val); | ||
494 | put_cpu(); | ||
495 | } | 516 | } |
496 | 517 | ||
497 | static void mem_cgroup_charge_statistics(struct mem_cgroup *mem, | 518 | static void mem_cgroup_charge_statistics(struct mem_cgroup *mem, |
@@ -499,24 +520,21 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *mem, | |||
499 | bool charge) | 520 | bool charge) |
500 | { | 521 | { |
501 | int val = (charge) ? 1 : -1; | 522 | int val = (charge) ? 1 : -1; |
502 | struct mem_cgroup_stat *stat = &mem->stat; | ||
503 | struct mem_cgroup_stat_cpu *cpustat; | ||
504 | int cpu = get_cpu(); | ||
505 | 523 | ||
506 | cpustat = &stat->cpustat[cpu]; | 524 | preempt_disable(); |
525 | |||
507 | if (PageCgroupCache(pc)) | 526 | if (PageCgroupCache(pc)) |
508 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_CACHE, val); | 527 | __this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_CACHE], val); |
509 | else | 528 | else |
510 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_RSS, val); | 529 | __this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_RSS], val); |
511 | 530 | ||
512 | if (charge) | 531 | if (charge) |
513 | __mem_cgroup_stat_add_safe(cpustat, | 532 | __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGIN_COUNT]); |
514 | MEM_CGROUP_STAT_PGPGIN_COUNT, 1); | ||
515 | else | 533 | else |
516 | __mem_cgroup_stat_add_safe(cpustat, | 534 | __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGOUT_COUNT]); |
517 | MEM_CGROUP_STAT_PGPGOUT_COUNT, 1); | 535 | __this_cpu_inc(mem->stat->count[MEM_CGROUP_EVENTS]); |
518 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_EVENTS, 1); | 536 | |
519 | put_cpu(); | 537 | preempt_enable(); |
520 | } | 538 | } |
521 | 539 | ||
522 | static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem, | 540 | static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem, |
@@ -534,6 +552,29 @@ static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem, | |||
534 | return total; | 552 | return total; |
535 | } | 553 | } |
536 | 554 | ||
555 | static bool __memcg_event_check(struct mem_cgroup *mem, int event_mask_shift) | ||
556 | { | ||
557 | s64 val; | ||
558 | |||
559 | val = this_cpu_read(mem->stat->count[MEM_CGROUP_EVENTS]); | ||
560 | |||
561 | return !(val & ((1 << event_mask_shift) - 1)); | ||
562 | } | ||
563 | |||
564 | /* | ||
565 | * Check events in order. | ||
566 | * | ||
567 | */ | ||
568 | static void memcg_check_events(struct mem_cgroup *mem, struct page *page) | ||
569 | { | ||
570 | /* threshold event is triggered in finer grain than soft limit */ | ||
571 | if (unlikely(__memcg_event_check(mem, THRESHOLDS_EVENTS_THRESH))) { | ||
572 | mem_cgroup_threshold(mem); | ||
573 | if (unlikely(__memcg_event_check(mem, SOFTLIMIT_EVENTS_THRESH))) | ||
574 | mem_cgroup_update_tree(mem, page); | ||
575 | } | ||
576 | } | ||
577 | |||
537 | static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) | 578 | static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) |
538 | { | 579 | { |
539 | return container_of(cgroup_subsys_state(cont, | 580 | return container_of(cgroup_subsys_state(cont, |
@@ -1000,7 +1041,7 @@ static int mem_cgroup_count_children_cb(struct mem_cgroup *mem, void *data) | |||
1000 | } | 1041 | } |
1001 | 1042 | ||
1002 | /** | 1043 | /** |
1003 | * mem_cgroup_print_mem_info: Called from OOM with tasklist_lock held in read mode. | 1044 | * mem_cgroup_print_oom_info: Called from OOM with tasklist_lock held in read mode. |
1004 | * @memcg: The memory cgroup that went over limit | 1045 | * @memcg: The memory cgroup that went over limit |
1005 | * @p: Task that is going to be killed | 1046 | * @p: Task that is going to be killed |
1006 | * | 1047 | * |
@@ -1174,7 +1215,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, | |||
1174 | } | 1215 | } |
1175 | } | 1216 | } |
1176 | } | 1217 | } |
1177 | if (!mem_cgroup_local_usage(&victim->stat)) { | 1218 | if (!mem_cgroup_local_usage(victim)) { |
1178 | /* this cgroup's local usage == 0 */ | 1219 | /* this cgroup's local usage == 0 */ |
1179 | css_put(&victim->css); | 1220 | css_put(&victim->css); |
1180 | continue; | 1221 | continue; |
@@ -1205,32 +1246,102 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, | |||
1205 | return total; | 1246 | return total; |
1206 | } | 1247 | } |
1207 | 1248 | ||
1208 | bool mem_cgroup_oom_called(struct task_struct *task) | 1249 | static int mem_cgroup_oom_lock_cb(struct mem_cgroup *mem, void *data) |
1209 | { | 1250 | { |
1210 | bool ret = false; | 1251 | int *val = (int *)data; |
1211 | struct mem_cgroup *mem; | 1252 | int x; |
1212 | struct mm_struct *mm; | 1253 | /* |
1254 | * Logically, we can stop scanning immediately when we find | ||
1255 | * a memcg is already locked. But condidering unlock ops and | ||
1256 | * creation/removal of memcg, scan-all is simple operation. | ||
1257 | */ | ||
1258 | x = atomic_inc_return(&mem->oom_lock); | ||
1259 | *val = max(x, *val); | ||
1260 | return 0; | ||
1261 | } | ||
1262 | /* | ||
1263 | * Check OOM-Killer is already running under our hierarchy. | ||
1264 | * If someone is running, return false. | ||
1265 | */ | ||
1266 | static bool mem_cgroup_oom_lock(struct mem_cgroup *mem) | ||
1267 | { | ||
1268 | int lock_count = 0; | ||
1213 | 1269 | ||
1214 | rcu_read_lock(); | 1270 | mem_cgroup_walk_tree(mem, &lock_count, mem_cgroup_oom_lock_cb); |
1215 | mm = task->mm; | 1271 | |
1216 | if (!mm) | 1272 | if (lock_count == 1) |
1217 | mm = &init_mm; | 1273 | return true; |
1218 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); | 1274 | return false; |
1219 | if (mem && time_before(jiffies, mem->last_oom_jiffies + HZ/10)) | ||
1220 | ret = true; | ||
1221 | rcu_read_unlock(); | ||
1222 | return ret; | ||
1223 | } | 1275 | } |
1224 | 1276 | ||
1225 | static int record_last_oom_cb(struct mem_cgroup *mem, void *data) | 1277 | static int mem_cgroup_oom_unlock_cb(struct mem_cgroup *mem, void *data) |
1226 | { | 1278 | { |
1227 | mem->last_oom_jiffies = jiffies; | 1279 | /* |
1280 | * When a new child is created while the hierarchy is under oom, | ||
1281 | * mem_cgroup_oom_lock() may not be called. We have to use | ||
1282 | * atomic_add_unless() here. | ||
1283 | */ | ||
1284 | atomic_add_unless(&mem->oom_lock, -1, 0); | ||
1228 | return 0; | 1285 | return 0; |
1229 | } | 1286 | } |
1230 | 1287 | ||
1231 | static void record_last_oom(struct mem_cgroup *mem) | 1288 | static void mem_cgroup_oom_unlock(struct mem_cgroup *mem) |
1232 | { | 1289 | { |
1233 | mem_cgroup_walk_tree(mem, NULL, record_last_oom_cb); | 1290 | mem_cgroup_walk_tree(mem, NULL, mem_cgroup_oom_unlock_cb); |
1291 | } | ||
1292 | |||
1293 | static DEFINE_MUTEX(memcg_oom_mutex); | ||
1294 | static DECLARE_WAIT_QUEUE_HEAD(memcg_oom_waitq); | ||
1295 | |||
1296 | /* | ||
1297 | * try to call OOM killer. returns false if we should exit memory-reclaim loop. | ||
1298 | */ | ||
1299 | bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask) | ||
1300 | { | ||
1301 | DEFINE_WAIT(wait); | ||
1302 | bool locked; | ||
1303 | |||
1304 | /* At first, try to OOM lock hierarchy under mem.*/ | ||
1305 | mutex_lock(&memcg_oom_mutex); | ||
1306 | locked = mem_cgroup_oom_lock(mem); | ||
1307 | /* | ||
1308 | * Even if signal_pending(), we can't quit charge() loop without | ||
1309 | * accounting. So, UNINTERRUPTIBLE is appropriate. But SIGKILL | ||
1310 | * under OOM is always welcomed, use TASK_KILLABLE here. | ||
1311 | */ | ||
1312 | if (!locked) | ||
1313 | prepare_to_wait(&memcg_oom_waitq, &wait, TASK_KILLABLE); | ||
1314 | mutex_unlock(&memcg_oom_mutex); | ||
1315 | |||
1316 | if (locked) | ||
1317 | mem_cgroup_out_of_memory(mem, mask); | ||
1318 | else { | ||
1319 | schedule(); | ||
1320 | finish_wait(&memcg_oom_waitq, &wait); | ||
1321 | } | ||
1322 | mutex_lock(&memcg_oom_mutex); | ||
1323 | mem_cgroup_oom_unlock(mem); | ||
1324 | /* | ||
1325 | * Here, we use global waitq .....more fine grained waitq ? | ||
1326 | * Assume following hierarchy. | ||
1327 | * A/ | ||
1328 | * 01 | ||
1329 | * 02 | ||
1330 | * assume OOM happens both in A and 01 at the same time. Tthey are | ||
1331 | * mutually exclusive by lock. (kill in 01 helps A.) | ||
1332 | * When we use per memcg waitq, we have to wake up waiters on A and 02 | ||
1333 | * in addtion to waiters on 01. We use global waitq for avoiding mess. | ||
1334 | * It will not be a big problem. | ||
1335 | * (And a task may be moved to other groups while it's waiting for OOM.) | ||
1336 | */ | ||
1337 | wake_up_all(&memcg_oom_waitq); | ||
1338 | mutex_unlock(&memcg_oom_mutex); | ||
1339 | |||
1340 | if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current)) | ||
1341 | return false; | ||
1342 | /* Give chance to dying process */ | ||
1343 | schedule_timeout(1); | ||
1344 | return true; | ||
1234 | } | 1345 | } |
1235 | 1346 | ||
1236 | /* | 1347 | /* |
@@ -1240,9 +1351,6 @@ static void record_last_oom(struct mem_cgroup *mem) | |||
1240 | void mem_cgroup_update_file_mapped(struct page *page, int val) | 1351 | void mem_cgroup_update_file_mapped(struct page *page, int val) |
1241 | { | 1352 | { |
1242 | struct mem_cgroup *mem; | 1353 | struct mem_cgroup *mem; |
1243 | struct mem_cgroup_stat *stat; | ||
1244 | struct mem_cgroup_stat_cpu *cpustat; | ||
1245 | int cpu; | ||
1246 | struct page_cgroup *pc; | 1354 | struct page_cgroup *pc; |
1247 | 1355 | ||
1248 | pc = lookup_page_cgroup(page); | 1356 | pc = lookup_page_cgroup(page); |
@@ -1258,13 +1366,10 @@ void mem_cgroup_update_file_mapped(struct page *page, int val) | |||
1258 | goto done; | 1366 | goto done; |
1259 | 1367 | ||
1260 | /* | 1368 | /* |
1261 | * Preemption is already disabled, we don't need get_cpu() | 1369 | * Preemption is already disabled. We can use __this_cpu_xxx |
1262 | */ | 1370 | */ |
1263 | cpu = smp_processor_id(); | 1371 | __this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_FILE_MAPPED], val); |
1264 | stat = &mem->stat; | ||
1265 | cpustat = &stat->cpustat[cpu]; | ||
1266 | 1372 | ||
1267 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED, val); | ||
1268 | done: | 1373 | done: |
1269 | unlock_page_cgroup(pc); | 1374 | unlock_page_cgroup(pc); |
1270 | } | 1375 | } |
@@ -1401,19 +1506,21 @@ static int __cpuinit memcg_stock_cpu_callback(struct notifier_block *nb, | |||
1401 | * oom-killer can be invoked. | 1506 | * oom-killer can be invoked. |
1402 | */ | 1507 | */ |
1403 | static int __mem_cgroup_try_charge(struct mm_struct *mm, | 1508 | static int __mem_cgroup_try_charge(struct mm_struct *mm, |
1404 | gfp_t gfp_mask, struct mem_cgroup **memcg, | 1509 | gfp_t gfp_mask, struct mem_cgroup **memcg, bool oom) |
1405 | bool oom, struct page *page) | ||
1406 | { | 1510 | { |
1407 | struct mem_cgroup *mem, *mem_over_limit; | 1511 | struct mem_cgroup *mem, *mem_over_limit; |
1408 | int nr_retries = MEM_CGROUP_RECLAIM_RETRIES; | 1512 | int nr_retries = MEM_CGROUP_RECLAIM_RETRIES; |
1409 | struct res_counter *fail_res; | 1513 | struct res_counter *fail_res; |
1410 | int csize = CHARGE_SIZE; | 1514 | int csize = CHARGE_SIZE; |
1411 | 1515 | ||
1412 | if (unlikely(test_thread_flag(TIF_MEMDIE))) { | 1516 | /* |
1413 | /* Don't account this! */ | 1517 | * Unlike gloval-vm's OOM-kill, we're not in memory shortage |
1414 | *memcg = NULL; | 1518 | * in system level. So, allow to go ahead dying process in addition to |
1415 | return 0; | 1519 | * MEMDIE process. |
1416 | } | 1520 | */ |
1521 | if (unlikely(test_thread_flag(TIF_MEMDIE) | ||
1522 | || fatal_signal_pending(current))) | ||
1523 | goto bypass; | ||
1417 | 1524 | ||
1418 | /* | 1525 | /* |
1419 | * We always charge the cgroup the mm_struct belongs to. | 1526 | * We always charge the cgroup the mm_struct belongs to. |
@@ -1440,7 +1547,7 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, | |||
1440 | unsigned long flags = 0; | 1547 | unsigned long flags = 0; |
1441 | 1548 | ||
1442 | if (consume_stock(mem)) | 1549 | if (consume_stock(mem)) |
1443 | goto charged; | 1550 | goto done; |
1444 | 1551 | ||
1445 | ret = res_counter_charge(&mem->res, csize, &fail_res); | 1552 | ret = res_counter_charge(&mem->res, csize, &fail_res); |
1446 | if (likely(!ret)) { | 1553 | if (likely(!ret)) { |
@@ -1483,28 +1590,70 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, | |||
1483 | if (mem_cgroup_check_under_limit(mem_over_limit)) | 1590 | if (mem_cgroup_check_under_limit(mem_over_limit)) |
1484 | continue; | 1591 | continue; |
1485 | 1592 | ||
1593 | /* try to avoid oom while someone is moving charge */ | ||
1594 | if (mc.moving_task && current != mc.moving_task) { | ||
1595 | struct mem_cgroup *from, *to; | ||
1596 | bool do_continue = false; | ||
1597 | /* | ||
1598 | * There is a small race that "from" or "to" can be | ||
1599 | * freed by rmdir, so we use css_tryget(). | ||
1600 | */ | ||
1601 | rcu_read_lock(); | ||
1602 | from = mc.from; | ||
1603 | to = mc.to; | ||
1604 | if (from && css_tryget(&from->css)) { | ||
1605 | if (mem_over_limit->use_hierarchy) | ||
1606 | do_continue = css_is_ancestor( | ||
1607 | &from->css, | ||
1608 | &mem_over_limit->css); | ||
1609 | else | ||
1610 | do_continue = (from == mem_over_limit); | ||
1611 | css_put(&from->css); | ||
1612 | } | ||
1613 | if (!do_continue && to && css_tryget(&to->css)) { | ||
1614 | if (mem_over_limit->use_hierarchy) | ||
1615 | do_continue = css_is_ancestor( | ||
1616 | &to->css, | ||
1617 | &mem_over_limit->css); | ||
1618 | else | ||
1619 | do_continue = (to == mem_over_limit); | ||
1620 | css_put(&to->css); | ||
1621 | } | ||
1622 | rcu_read_unlock(); | ||
1623 | if (do_continue) { | ||
1624 | DEFINE_WAIT(wait); | ||
1625 | prepare_to_wait(&mc.waitq, &wait, | ||
1626 | TASK_INTERRUPTIBLE); | ||
1627 | /* moving charge context might have finished. */ | ||
1628 | if (mc.moving_task) | ||
1629 | schedule(); | ||
1630 | finish_wait(&mc.waitq, &wait); | ||
1631 | continue; | ||
1632 | } | ||
1633 | } | ||
1634 | |||
1486 | if (!nr_retries--) { | 1635 | if (!nr_retries--) { |
1487 | if (oom) { | 1636 | if (!oom) |
1488 | mem_cgroup_out_of_memory(mem_over_limit, gfp_mask); | 1637 | goto nomem; |
1489 | record_last_oom(mem_over_limit); | 1638 | if (mem_cgroup_handle_oom(mem_over_limit, gfp_mask)) { |
1639 | nr_retries = MEM_CGROUP_RECLAIM_RETRIES; | ||
1640 | continue; | ||
1490 | } | 1641 | } |
1491 | goto nomem; | 1642 | /* When we reach here, current task is dying .*/ |
1643 | css_put(&mem->css); | ||
1644 | goto bypass; | ||
1492 | } | 1645 | } |
1493 | } | 1646 | } |
1494 | if (csize > PAGE_SIZE) | 1647 | if (csize > PAGE_SIZE) |
1495 | refill_stock(mem, csize - PAGE_SIZE); | 1648 | refill_stock(mem, csize - PAGE_SIZE); |
1496 | charged: | ||
1497 | /* | ||
1498 | * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree. | ||
1499 | * if they exceeds softlimit. | ||
1500 | */ | ||
1501 | if (mem_cgroup_soft_limit_check(mem)) | ||
1502 | mem_cgroup_update_tree(mem, page); | ||
1503 | done: | 1649 | done: |
1504 | return 0; | 1650 | return 0; |
1505 | nomem: | 1651 | nomem: |
1506 | css_put(&mem->css); | 1652 | css_put(&mem->css); |
1507 | return -ENOMEM; | 1653 | return -ENOMEM; |
1654 | bypass: | ||
1655 | *memcg = NULL; | ||
1656 | return 0; | ||
1508 | } | 1657 | } |
1509 | 1658 | ||
1510 | /* | 1659 | /* |
@@ -1512,14 +1661,23 @@ nomem: | |||
1512 | * This function is for that and do uncharge, put css's refcnt. | 1661 | * This function is for that and do uncharge, put css's refcnt. |
1513 | * gotten by try_charge(). | 1662 | * gotten by try_charge(). |
1514 | */ | 1663 | */ |
1515 | static void mem_cgroup_cancel_charge(struct mem_cgroup *mem) | 1664 | static void __mem_cgroup_cancel_charge(struct mem_cgroup *mem, |
1665 | unsigned long count) | ||
1516 | { | 1666 | { |
1517 | if (!mem_cgroup_is_root(mem)) { | 1667 | if (!mem_cgroup_is_root(mem)) { |
1518 | res_counter_uncharge(&mem->res, PAGE_SIZE); | 1668 | res_counter_uncharge(&mem->res, PAGE_SIZE * count); |
1519 | if (do_swap_account) | 1669 | if (do_swap_account) |
1520 | res_counter_uncharge(&mem->memsw, PAGE_SIZE); | 1670 | res_counter_uncharge(&mem->memsw, PAGE_SIZE * count); |
1671 | VM_BUG_ON(test_bit(CSS_ROOT, &mem->css.flags)); | ||
1672 | WARN_ON_ONCE(count > INT_MAX); | ||
1673 | __css_put(&mem->css, (int)count); | ||
1521 | } | 1674 | } |
1522 | css_put(&mem->css); | 1675 | /* we don't need css_put for root */ |
1676 | } | ||
1677 | |||
1678 | static void mem_cgroup_cancel_charge(struct mem_cgroup *mem) | ||
1679 | { | ||
1680 | __mem_cgroup_cancel_charge(mem, 1); | ||
1523 | } | 1681 | } |
1524 | 1682 | ||
1525 | /* | 1683 | /* |
@@ -1615,6 +1773,12 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem, | |||
1615 | mem_cgroup_charge_statistics(mem, pc, true); | 1773 | mem_cgroup_charge_statistics(mem, pc, true); |
1616 | 1774 | ||
1617 | unlock_page_cgroup(pc); | 1775 | unlock_page_cgroup(pc); |
1776 | /* | ||
1777 | * "charge_statistics" updated event counter. Then, check it. | ||
1778 | * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree. | ||
1779 | * if they exceeds softlimit. | ||
1780 | */ | ||
1781 | memcg_check_events(mem, pc->page); | ||
1618 | } | 1782 | } |
1619 | 1783 | ||
1620 | /** | 1784 | /** |
@@ -1622,22 +1786,22 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem, | |||
1622 | * @pc: page_cgroup of the page. | 1786 | * @pc: page_cgroup of the page. |
1623 | * @from: mem_cgroup which the page is moved from. | 1787 | * @from: mem_cgroup which the page is moved from. |
1624 | * @to: mem_cgroup which the page is moved to. @from != @to. | 1788 | * @to: mem_cgroup which the page is moved to. @from != @to. |
1789 | * @uncharge: whether we should call uncharge and css_put against @from. | ||
1625 | * | 1790 | * |
1626 | * The caller must confirm following. | 1791 | * The caller must confirm following. |
1627 | * - page is not on LRU (isolate_page() is useful.) | 1792 | * - page is not on LRU (isolate_page() is useful.) |
1628 | * - the pc is locked, used, and ->mem_cgroup points to @from. | 1793 | * - the pc is locked, used, and ->mem_cgroup points to @from. |
1629 | * | 1794 | * |
1630 | * This function does "uncharge" from old cgroup but doesn't do "charge" to | 1795 | * This function doesn't do "charge" nor css_get to new cgroup. It should be |
1631 | * new cgroup. It should be done by a caller. | 1796 | * done by a caller(__mem_cgroup_try_charge would be usefull). If @uncharge is |
1797 | * true, this function does "uncharge" from old cgroup, but it doesn't if | ||
1798 | * @uncharge is false, so a caller should do "uncharge". | ||
1632 | */ | 1799 | */ |
1633 | 1800 | ||
1634 | static void __mem_cgroup_move_account(struct page_cgroup *pc, | 1801 | static void __mem_cgroup_move_account(struct page_cgroup *pc, |
1635 | struct mem_cgroup *from, struct mem_cgroup *to) | 1802 | struct mem_cgroup *from, struct mem_cgroup *to, bool uncharge) |
1636 | { | 1803 | { |
1637 | struct page *page; | 1804 | struct page *page; |
1638 | int cpu; | ||
1639 | struct mem_cgroup_stat *stat; | ||
1640 | struct mem_cgroup_stat_cpu *cpustat; | ||
1641 | 1805 | ||
1642 | VM_BUG_ON(from == to); | 1806 | VM_BUG_ON(from == to); |
1643 | VM_BUG_ON(PageLRU(pc->page)); | 1807 | VM_BUG_ON(PageLRU(pc->page)); |
@@ -1645,38 +1809,28 @@ static void __mem_cgroup_move_account(struct page_cgroup *pc, | |||
1645 | VM_BUG_ON(!PageCgroupUsed(pc)); | 1809 | VM_BUG_ON(!PageCgroupUsed(pc)); |
1646 | VM_BUG_ON(pc->mem_cgroup != from); | 1810 | VM_BUG_ON(pc->mem_cgroup != from); |
1647 | 1811 | ||
1648 | if (!mem_cgroup_is_root(from)) | ||
1649 | res_counter_uncharge(&from->res, PAGE_SIZE); | ||
1650 | mem_cgroup_charge_statistics(from, pc, false); | ||
1651 | |||
1652 | page = pc->page; | 1812 | page = pc->page; |
1653 | if (page_mapped(page) && !PageAnon(page)) { | 1813 | if (page_mapped(page) && !PageAnon(page)) { |
1654 | cpu = smp_processor_id(); | 1814 | /* Update mapped_file data for mem_cgroup */ |
1655 | /* Update mapped_file data for mem_cgroup "from" */ | 1815 | preempt_disable(); |
1656 | stat = &from->stat; | 1816 | __this_cpu_dec(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]); |
1657 | cpustat = &stat->cpustat[cpu]; | 1817 | __this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]); |
1658 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED, | 1818 | preempt_enable(); |
1659 | -1); | ||
1660 | |||
1661 | /* Update mapped_file data for mem_cgroup "to" */ | ||
1662 | stat = &to->stat; | ||
1663 | cpustat = &stat->cpustat[cpu]; | ||
1664 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED, | ||
1665 | 1); | ||
1666 | } | 1819 | } |
1820 | mem_cgroup_charge_statistics(from, pc, false); | ||
1821 | if (uncharge) | ||
1822 | /* This is not "cancel", but cancel_charge does all we need. */ | ||
1823 | mem_cgroup_cancel_charge(from); | ||
1667 | 1824 | ||
1668 | if (do_swap_account && !mem_cgroup_is_root(from)) | 1825 | /* caller should have done css_get */ |
1669 | res_counter_uncharge(&from->memsw, PAGE_SIZE); | ||
1670 | css_put(&from->css); | ||
1671 | |||
1672 | css_get(&to->css); | ||
1673 | pc->mem_cgroup = to; | 1826 | pc->mem_cgroup = to; |
1674 | mem_cgroup_charge_statistics(to, pc, true); | 1827 | mem_cgroup_charge_statistics(to, pc, true); |
1675 | /* | 1828 | /* |
1676 | * We charges against "to" which may not have any tasks. Then, "to" | 1829 | * We charges against "to" which may not have any tasks. Then, "to" |
1677 | * can be under rmdir(). But in current implementation, caller of | 1830 | * can be under rmdir(). But in current implementation, caller of |
1678 | * this function is just force_empty() and it's garanteed that | 1831 | * this function is just force_empty() and move charge, so it's |
1679 | * "to" is never removed. So, we don't check rmdir status here. | 1832 | * garanteed that "to" is never removed. So, we don't check rmdir |
1833 | * status here. | ||
1680 | */ | 1834 | */ |
1681 | } | 1835 | } |
1682 | 1836 | ||
@@ -1685,15 +1839,20 @@ static void __mem_cgroup_move_account(struct page_cgroup *pc, | |||
1685 | * __mem_cgroup_move_account() | 1839 | * __mem_cgroup_move_account() |
1686 | */ | 1840 | */ |
1687 | static int mem_cgroup_move_account(struct page_cgroup *pc, | 1841 | static int mem_cgroup_move_account(struct page_cgroup *pc, |
1688 | struct mem_cgroup *from, struct mem_cgroup *to) | 1842 | struct mem_cgroup *from, struct mem_cgroup *to, bool uncharge) |
1689 | { | 1843 | { |
1690 | int ret = -EINVAL; | 1844 | int ret = -EINVAL; |
1691 | lock_page_cgroup(pc); | 1845 | lock_page_cgroup(pc); |
1692 | if (PageCgroupUsed(pc) && pc->mem_cgroup == from) { | 1846 | if (PageCgroupUsed(pc) && pc->mem_cgroup == from) { |
1693 | __mem_cgroup_move_account(pc, from, to); | 1847 | __mem_cgroup_move_account(pc, from, to, uncharge); |
1694 | ret = 0; | 1848 | ret = 0; |
1695 | } | 1849 | } |
1696 | unlock_page_cgroup(pc); | 1850 | unlock_page_cgroup(pc); |
1851 | /* | ||
1852 | * check events | ||
1853 | */ | ||
1854 | memcg_check_events(to, pc->page); | ||
1855 | memcg_check_events(from, pc->page); | ||
1697 | return ret; | 1856 | return ret; |
1698 | } | 1857 | } |
1699 | 1858 | ||
@@ -1722,15 +1881,13 @@ static int mem_cgroup_move_parent(struct page_cgroup *pc, | |||
1722 | goto put; | 1881 | goto put; |
1723 | 1882 | ||
1724 | parent = mem_cgroup_from_cont(pcg); | 1883 | parent = mem_cgroup_from_cont(pcg); |
1725 | ret = __mem_cgroup_try_charge(NULL, gfp_mask, &parent, false, page); | 1884 | ret = __mem_cgroup_try_charge(NULL, gfp_mask, &parent, false); |
1726 | if (ret || !parent) | 1885 | if (ret || !parent) |
1727 | goto put_back; | 1886 | goto put_back; |
1728 | 1887 | ||
1729 | ret = mem_cgroup_move_account(pc, child, parent); | 1888 | ret = mem_cgroup_move_account(pc, child, parent, true); |
1730 | if (!ret) | 1889 | if (ret) |
1731 | css_put(&parent->css); /* drop extra refcnt by try_charge() */ | 1890 | mem_cgroup_cancel_charge(parent); |
1732 | else | ||
1733 | mem_cgroup_cancel_charge(parent); /* does css_put */ | ||
1734 | put_back: | 1891 | put_back: |
1735 | putback_lru_page(page); | 1892 | putback_lru_page(page); |
1736 | put: | 1893 | put: |
@@ -1760,7 +1917,7 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, | |||
1760 | prefetchw(pc); | 1917 | prefetchw(pc); |
1761 | 1918 | ||
1762 | mem = memcg; | 1919 | mem = memcg; |
1763 | ret = __mem_cgroup_try_charge(mm, gfp_mask, &mem, true, page); | 1920 | ret = __mem_cgroup_try_charge(mm, gfp_mask, &mem, true); |
1764 | if (ret || !mem) | 1921 | if (ret || !mem) |
1765 | return ret; | 1922 | return ret; |
1766 | 1923 | ||
@@ -1880,14 +2037,14 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, | |||
1880 | if (!mem) | 2037 | if (!mem) |
1881 | goto charge_cur_mm; | 2038 | goto charge_cur_mm; |
1882 | *ptr = mem; | 2039 | *ptr = mem; |
1883 | ret = __mem_cgroup_try_charge(NULL, mask, ptr, true, page); | 2040 | ret = __mem_cgroup_try_charge(NULL, mask, ptr, true); |
1884 | /* drop extra refcnt from tryget */ | 2041 | /* drop extra refcnt from tryget */ |
1885 | css_put(&mem->css); | 2042 | css_put(&mem->css); |
1886 | return ret; | 2043 | return ret; |
1887 | charge_cur_mm: | 2044 | charge_cur_mm: |
1888 | if (unlikely(!mm)) | 2045 | if (unlikely(!mm)) |
1889 | mm = &init_mm; | 2046 | mm = &init_mm; |
1890 | return __mem_cgroup_try_charge(mm, mask, ptr, true, page); | 2047 | return __mem_cgroup_try_charge(mm, mask, ptr, true); |
1891 | } | 2048 | } |
1892 | 2049 | ||
1893 | static void | 2050 | static void |
@@ -2064,8 +2221,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) | |||
2064 | mz = page_cgroup_zoneinfo(pc); | 2221 | mz = page_cgroup_zoneinfo(pc); |
2065 | unlock_page_cgroup(pc); | 2222 | unlock_page_cgroup(pc); |
2066 | 2223 | ||
2067 | if (mem_cgroup_soft_limit_check(mem)) | 2224 | memcg_check_events(mem, page); |
2068 | mem_cgroup_update_tree(mem, page); | ||
2069 | /* at swapout, this memcg will be accessed to record to swap */ | 2225 | /* at swapout, this memcg will be accessed to record to swap */ |
2070 | if (ctype != MEM_CGROUP_CHARGE_TYPE_SWAPOUT) | 2226 | if (ctype != MEM_CGROUP_CHARGE_TYPE_SWAPOUT) |
2071 | css_put(&mem->css); | 2227 | css_put(&mem->css); |
@@ -2192,6 +2348,64 @@ void mem_cgroup_uncharge_swap(swp_entry_t ent) | |||
2192 | } | 2348 | } |
2193 | rcu_read_unlock(); | 2349 | rcu_read_unlock(); |
2194 | } | 2350 | } |
2351 | |||
2352 | /** | ||
2353 | * mem_cgroup_move_swap_account - move swap charge and swap_cgroup's record. | ||
2354 | * @entry: swap entry to be moved | ||
2355 | * @from: mem_cgroup which the entry is moved from | ||
2356 | * @to: mem_cgroup which the entry is moved to | ||
2357 | * @need_fixup: whether we should fixup res_counters and refcounts. | ||
2358 | * | ||
2359 | * It succeeds only when the swap_cgroup's record for this entry is the same | ||
2360 | * as the mem_cgroup's id of @from. | ||
2361 | * | ||
2362 | * Returns 0 on success, -EINVAL on failure. | ||
2363 | * | ||
2364 | * The caller must have charged to @to, IOW, called res_counter_charge() about | ||
2365 | * both res and memsw, and called css_get(). | ||
2366 | */ | ||
2367 | static int mem_cgroup_move_swap_account(swp_entry_t entry, | ||
2368 | struct mem_cgroup *from, struct mem_cgroup *to, bool need_fixup) | ||
2369 | { | ||
2370 | unsigned short old_id, new_id; | ||
2371 | |||
2372 | old_id = css_id(&from->css); | ||
2373 | new_id = css_id(&to->css); | ||
2374 | |||
2375 | if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) { | ||
2376 | mem_cgroup_swap_statistics(from, false); | ||
2377 | mem_cgroup_swap_statistics(to, true); | ||
2378 | /* | ||
2379 | * This function is only called from task migration context now. | ||
2380 | * It postpones res_counter and refcount handling till the end | ||
2381 | * of task migration(mem_cgroup_clear_mc()) for performance | ||
2382 | * improvement. But we cannot postpone mem_cgroup_get(to) | ||
2383 | * because if the process that has been moved to @to does | ||
2384 | * swap-in, the refcount of @to might be decreased to 0. | ||
2385 | */ | ||
2386 | mem_cgroup_get(to); | ||
2387 | if (need_fixup) { | ||
2388 | if (!mem_cgroup_is_root(from)) | ||
2389 | res_counter_uncharge(&from->memsw, PAGE_SIZE); | ||
2390 | mem_cgroup_put(from); | ||
2391 | /* | ||
2392 | * we charged both to->res and to->memsw, so we should | ||
2393 | * uncharge to->res. | ||
2394 | */ | ||
2395 | if (!mem_cgroup_is_root(to)) | ||
2396 | res_counter_uncharge(&to->res, PAGE_SIZE); | ||
2397 | css_put(&to->css); | ||
2398 | } | ||
2399 | return 0; | ||
2400 | } | ||
2401 | return -EINVAL; | ||
2402 | } | ||
2403 | #else | ||
2404 | static inline int mem_cgroup_move_swap_account(swp_entry_t entry, | ||
2405 | struct mem_cgroup *from, struct mem_cgroup *to, bool need_fixup) | ||
2406 | { | ||
2407 | return -EINVAL; | ||
2408 | } | ||
2195 | #endif | 2409 | #endif |
2196 | 2410 | ||
2197 | /* | 2411 | /* |
@@ -2216,8 +2430,7 @@ int mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr) | |||
2216 | unlock_page_cgroup(pc); | 2430 | unlock_page_cgroup(pc); |
2217 | 2431 | ||
2218 | if (mem) { | 2432 | if (mem) { |
2219 | ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, &mem, false, | 2433 | ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, &mem, false); |
2220 | page); | ||
2221 | css_put(&mem->css); | 2434 | css_put(&mem->css); |
2222 | } | 2435 | } |
2223 | *ptr = mem; | 2436 | *ptr = mem; |
@@ -2704,7 +2917,7 @@ static int | |||
2704 | mem_cgroup_get_idx_stat(struct mem_cgroup *mem, void *data) | 2917 | mem_cgroup_get_idx_stat(struct mem_cgroup *mem, void *data) |
2705 | { | 2918 | { |
2706 | struct mem_cgroup_idx_data *d = data; | 2919 | struct mem_cgroup_idx_data *d = data; |
2707 | d->val += mem_cgroup_read_stat(&mem->stat, d->idx); | 2920 | d->val += mem_cgroup_read_stat(mem, d->idx); |
2708 | return 0; | 2921 | return 0; |
2709 | } | 2922 | } |
2710 | 2923 | ||
@@ -2719,40 +2932,50 @@ mem_cgroup_get_recursive_idx_stat(struct mem_cgroup *mem, | |||
2719 | *val = d.val; | 2932 | *val = d.val; |
2720 | } | 2933 | } |
2721 | 2934 | ||
2935 | static inline u64 mem_cgroup_usage(struct mem_cgroup *mem, bool swap) | ||
2936 | { | ||
2937 | u64 idx_val, val; | ||
2938 | |||
2939 | if (!mem_cgroup_is_root(mem)) { | ||
2940 | if (!swap) | ||
2941 | return res_counter_read_u64(&mem->res, RES_USAGE); | ||
2942 | else | ||
2943 | return res_counter_read_u64(&mem->memsw, RES_USAGE); | ||
2944 | } | ||
2945 | |||
2946 | mem_cgroup_get_recursive_idx_stat(mem, MEM_CGROUP_STAT_CACHE, &idx_val); | ||
2947 | val = idx_val; | ||
2948 | mem_cgroup_get_recursive_idx_stat(mem, MEM_CGROUP_STAT_RSS, &idx_val); | ||
2949 | val += idx_val; | ||
2950 | |||
2951 | if (swap) { | ||
2952 | mem_cgroup_get_recursive_idx_stat(mem, | ||
2953 | MEM_CGROUP_STAT_SWAPOUT, &idx_val); | ||
2954 | val += idx_val; | ||
2955 | } | ||
2956 | |||
2957 | return val << PAGE_SHIFT; | ||
2958 | } | ||
2959 | |||
2722 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) | 2960 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) |
2723 | { | 2961 | { |
2724 | struct mem_cgroup *mem = mem_cgroup_from_cont(cont); | 2962 | struct mem_cgroup *mem = mem_cgroup_from_cont(cont); |
2725 | u64 idx_val, val; | 2963 | u64 val; |
2726 | int type, name; | 2964 | int type, name; |
2727 | 2965 | ||
2728 | type = MEMFILE_TYPE(cft->private); | 2966 | type = MEMFILE_TYPE(cft->private); |
2729 | name = MEMFILE_ATTR(cft->private); | 2967 | name = MEMFILE_ATTR(cft->private); |
2730 | switch (type) { | 2968 | switch (type) { |
2731 | case _MEM: | 2969 | case _MEM: |
2732 | if (name == RES_USAGE && mem_cgroup_is_root(mem)) { | 2970 | if (name == RES_USAGE) |
2733 | mem_cgroup_get_recursive_idx_stat(mem, | 2971 | val = mem_cgroup_usage(mem, false); |
2734 | MEM_CGROUP_STAT_CACHE, &idx_val); | 2972 | else |
2735 | val = idx_val; | ||
2736 | mem_cgroup_get_recursive_idx_stat(mem, | ||
2737 | MEM_CGROUP_STAT_RSS, &idx_val); | ||
2738 | val += idx_val; | ||
2739 | val <<= PAGE_SHIFT; | ||
2740 | } else | ||
2741 | val = res_counter_read_u64(&mem->res, name); | 2973 | val = res_counter_read_u64(&mem->res, name); |
2742 | break; | 2974 | break; |
2743 | case _MEMSWAP: | 2975 | case _MEMSWAP: |
2744 | if (name == RES_USAGE && mem_cgroup_is_root(mem)) { | 2976 | if (name == RES_USAGE) |
2745 | mem_cgroup_get_recursive_idx_stat(mem, | 2977 | val = mem_cgroup_usage(mem, true); |
2746 | MEM_CGROUP_STAT_CACHE, &idx_val); | 2978 | else |
2747 | val = idx_val; | ||
2748 | mem_cgroup_get_recursive_idx_stat(mem, | ||
2749 | MEM_CGROUP_STAT_RSS, &idx_val); | ||
2750 | val += idx_val; | ||
2751 | mem_cgroup_get_recursive_idx_stat(mem, | ||
2752 | MEM_CGROUP_STAT_SWAPOUT, &idx_val); | ||
2753 | val += idx_val; | ||
2754 | val <<= PAGE_SHIFT; | ||
2755 | } else | ||
2756 | val = res_counter_read_u64(&mem->memsw, name); | 2979 | val = res_counter_read_u64(&mem->memsw, name); |
2757 | break; | 2980 | break; |
2758 | default: | 2981 | default: |
@@ -2865,6 +3088,39 @@ static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) | |||
2865 | return 0; | 3088 | return 0; |
2866 | } | 3089 | } |
2867 | 3090 | ||
3091 | static u64 mem_cgroup_move_charge_read(struct cgroup *cgrp, | ||
3092 | struct cftype *cft) | ||
3093 | { | ||
3094 | return mem_cgroup_from_cont(cgrp)->move_charge_at_immigrate; | ||
3095 | } | ||
3096 | |||
3097 | #ifdef CONFIG_MMU | ||
3098 | static int mem_cgroup_move_charge_write(struct cgroup *cgrp, | ||
3099 | struct cftype *cft, u64 val) | ||
3100 | { | ||
3101 | struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp); | ||
3102 | |||
3103 | if (val >= (1 << NR_MOVE_TYPE)) | ||
3104 | return -EINVAL; | ||
3105 | /* | ||
3106 | * We check this value several times in both in can_attach() and | ||
3107 | * attach(), so we need cgroup lock to prevent this value from being | ||
3108 | * inconsistent. | ||
3109 | */ | ||
3110 | cgroup_lock(); | ||
3111 | mem->move_charge_at_immigrate = val; | ||
3112 | cgroup_unlock(); | ||
3113 | |||
3114 | return 0; | ||
3115 | } | ||
3116 | #else | ||
3117 | static int mem_cgroup_move_charge_write(struct cgroup *cgrp, | ||
3118 | struct cftype *cft, u64 val) | ||
3119 | { | ||
3120 | return -ENOSYS; | ||
3121 | } | ||
3122 | #endif | ||
3123 | |||
2868 | 3124 | ||
2869 | /* For read statistics */ | 3125 | /* For read statistics */ |
2870 | enum { | 3126 | enum { |
@@ -2910,18 +3166,18 @@ static int mem_cgroup_get_local_stat(struct mem_cgroup *mem, void *data) | |||
2910 | s64 val; | 3166 | s64 val; |
2911 | 3167 | ||
2912 | /* per cpu stat */ | 3168 | /* per cpu stat */ |
2913 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_CACHE); | 3169 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_CACHE); |
2914 | s->stat[MCS_CACHE] += val * PAGE_SIZE; | 3170 | s->stat[MCS_CACHE] += val * PAGE_SIZE; |
2915 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_RSS); | 3171 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_RSS); |
2916 | s->stat[MCS_RSS] += val * PAGE_SIZE; | 3172 | s->stat[MCS_RSS] += val * PAGE_SIZE; |
2917 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_FILE_MAPPED); | 3173 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_FILE_MAPPED); |
2918 | s->stat[MCS_FILE_MAPPED] += val * PAGE_SIZE; | 3174 | s->stat[MCS_FILE_MAPPED] += val * PAGE_SIZE; |
2919 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGIN_COUNT); | 3175 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_PGPGIN_COUNT); |
2920 | s->stat[MCS_PGPGIN] += val; | 3176 | s->stat[MCS_PGPGIN] += val; |
2921 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGOUT_COUNT); | 3177 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_PGPGOUT_COUNT); |
2922 | s->stat[MCS_PGPGOUT] += val; | 3178 | s->stat[MCS_PGPGOUT] += val; |
2923 | if (do_swap_account) { | 3179 | if (do_swap_account) { |
2924 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_SWAPOUT); | 3180 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_SWAPOUT); |
2925 | s->stat[MCS_SWAP] += val * PAGE_SIZE; | 3181 | s->stat[MCS_SWAP] += val * PAGE_SIZE; |
2926 | } | 3182 | } |
2927 | 3183 | ||
@@ -3049,12 +3305,249 @@ static int mem_cgroup_swappiness_write(struct cgroup *cgrp, struct cftype *cft, | |||
3049 | return 0; | 3305 | return 0; |
3050 | } | 3306 | } |
3051 | 3307 | ||
3308 | static void __mem_cgroup_threshold(struct mem_cgroup *memcg, bool swap) | ||
3309 | { | ||
3310 | struct mem_cgroup_threshold_ary *t; | ||
3311 | u64 usage; | ||
3312 | int i; | ||
3313 | |||
3314 | rcu_read_lock(); | ||
3315 | if (!swap) | ||
3316 | t = rcu_dereference(memcg->thresholds); | ||
3317 | else | ||
3318 | t = rcu_dereference(memcg->memsw_thresholds); | ||
3319 | |||
3320 | if (!t) | ||
3321 | goto unlock; | ||
3322 | |||
3323 | usage = mem_cgroup_usage(memcg, swap); | ||
3324 | |||
3325 | /* | ||
3326 | * current_threshold points to threshold just below usage. | ||
3327 | * If it's not true, a threshold was crossed after last | ||
3328 | * call of __mem_cgroup_threshold(). | ||
3329 | */ | ||
3330 | i = atomic_read(&t->current_threshold); | ||
3331 | |||
3332 | /* | ||
3333 | * Iterate backward over array of thresholds starting from | ||
3334 | * current_threshold and check if a threshold is crossed. | ||
3335 | * If none of thresholds below usage is crossed, we read | ||
3336 | * only one element of the array here. | ||
3337 | */ | ||
3338 | for (; i >= 0 && unlikely(t->entries[i].threshold > usage); i--) | ||
3339 | eventfd_signal(t->entries[i].eventfd, 1); | ||
3340 | |||
3341 | /* i = current_threshold + 1 */ | ||
3342 | i++; | ||
3343 | |||
3344 | /* | ||
3345 | * Iterate forward over array of thresholds starting from | ||
3346 | * current_threshold+1 and check if a threshold is crossed. | ||
3347 | * If none of thresholds above usage is crossed, we read | ||
3348 | * only one element of the array here. | ||
3349 | */ | ||
3350 | for (; i < t->size && unlikely(t->entries[i].threshold <= usage); i++) | ||
3351 | eventfd_signal(t->entries[i].eventfd, 1); | ||
3352 | |||
3353 | /* Update current_threshold */ | ||
3354 | atomic_set(&t->current_threshold, i - 1); | ||
3355 | unlock: | ||
3356 | rcu_read_unlock(); | ||
3357 | } | ||
3358 | |||
3359 | static void mem_cgroup_threshold(struct mem_cgroup *memcg) | ||
3360 | { | ||
3361 | __mem_cgroup_threshold(memcg, false); | ||
3362 | if (do_swap_account) | ||
3363 | __mem_cgroup_threshold(memcg, true); | ||
3364 | } | ||
3365 | |||
3366 | static int compare_thresholds(const void *a, const void *b) | ||
3367 | { | ||
3368 | const struct mem_cgroup_threshold *_a = a; | ||
3369 | const struct mem_cgroup_threshold *_b = b; | ||
3370 | |||
3371 | return _a->threshold - _b->threshold; | ||
3372 | } | ||
3373 | |||
3374 | static int mem_cgroup_register_event(struct cgroup *cgrp, struct cftype *cft, | ||
3375 | struct eventfd_ctx *eventfd, const char *args) | ||
3376 | { | ||
3377 | struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); | ||
3378 | struct mem_cgroup_threshold_ary *thresholds, *thresholds_new; | ||
3379 | int type = MEMFILE_TYPE(cft->private); | ||
3380 | u64 threshold, usage; | ||
3381 | int size; | ||
3382 | int i, ret; | ||
3383 | |||
3384 | ret = res_counter_memparse_write_strategy(args, &threshold); | ||
3385 | if (ret) | ||
3386 | return ret; | ||
3387 | |||
3388 | mutex_lock(&memcg->thresholds_lock); | ||
3389 | if (type == _MEM) | ||
3390 | thresholds = memcg->thresholds; | ||
3391 | else if (type == _MEMSWAP) | ||
3392 | thresholds = memcg->memsw_thresholds; | ||
3393 | else | ||
3394 | BUG(); | ||
3395 | |||
3396 | usage = mem_cgroup_usage(memcg, type == _MEMSWAP); | ||
3397 | |||
3398 | /* Check if a threshold crossed before adding a new one */ | ||
3399 | if (thresholds) | ||
3400 | __mem_cgroup_threshold(memcg, type == _MEMSWAP); | ||
3401 | |||
3402 | if (thresholds) | ||
3403 | size = thresholds->size + 1; | ||
3404 | else | ||
3405 | size = 1; | ||
3406 | |||
3407 | /* Allocate memory for new array of thresholds */ | ||
3408 | thresholds_new = kmalloc(sizeof(*thresholds_new) + | ||
3409 | size * sizeof(struct mem_cgroup_threshold), | ||
3410 | GFP_KERNEL); | ||
3411 | if (!thresholds_new) { | ||
3412 | ret = -ENOMEM; | ||
3413 | goto unlock; | ||
3414 | } | ||
3415 | thresholds_new->size = size; | ||
3416 | |||
3417 | /* Copy thresholds (if any) to new array */ | ||
3418 | if (thresholds) | ||
3419 | memcpy(thresholds_new->entries, thresholds->entries, | ||
3420 | thresholds->size * | ||
3421 | sizeof(struct mem_cgroup_threshold)); | ||
3422 | /* Add new threshold */ | ||
3423 | thresholds_new->entries[size - 1].eventfd = eventfd; | ||
3424 | thresholds_new->entries[size - 1].threshold = threshold; | ||
3425 | |||
3426 | /* Sort thresholds. Registering of new threshold isn't time-critical */ | ||
3427 | sort(thresholds_new->entries, size, | ||
3428 | sizeof(struct mem_cgroup_threshold), | ||
3429 | compare_thresholds, NULL); | ||
3430 | |||
3431 | /* Find current threshold */ | ||
3432 | atomic_set(&thresholds_new->current_threshold, -1); | ||
3433 | for (i = 0; i < size; i++) { | ||
3434 | if (thresholds_new->entries[i].threshold < usage) { | ||
3435 | /* | ||
3436 | * thresholds_new->current_threshold will not be used | ||
3437 | * until rcu_assign_pointer(), so it's safe to increment | ||
3438 | * it here. | ||
3439 | */ | ||
3440 | atomic_inc(&thresholds_new->current_threshold); | ||
3441 | } | ||
3442 | } | ||
3443 | |||
3444 | if (type == _MEM) | ||
3445 | rcu_assign_pointer(memcg->thresholds, thresholds_new); | ||
3446 | else | ||
3447 | rcu_assign_pointer(memcg->memsw_thresholds, thresholds_new); | ||
3448 | |||
3449 | /* To be sure that nobody uses thresholds before freeing it */ | ||
3450 | synchronize_rcu(); | ||
3451 | |||
3452 | kfree(thresholds); | ||
3453 | unlock: | ||
3454 | mutex_unlock(&memcg->thresholds_lock); | ||
3455 | |||
3456 | return ret; | ||
3457 | } | ||
3458 | |||
3459 | static int mem_cgroup_unregister_event(struct cgroup *cgrp, struct cftype *cft, | ||
3460 | struct eventfd_ctx *eventfd) | ||
3461 | { | ||
3462 | struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); | ||
3463 | struct mem_cgroup_threshold_ary *thresholds, *thresholds_new; | ||
3464 | int type = MEMFILE_TYPE(cft->private); | ||
3465 | u64 usage; | ||
3466 | int size = 0; | ||
3467 | int i, j, ret; | ||
3468 | |||
3469 | mutex_lock(&memcg->thresholds_lock); | ||
3470 | if (type == _MEM) | ||
3471 | thresholds = memcg->thresholds; | ||
3472 | else if (type == _MEMSWAP) | ||
3473 | thresholds = memcg->memsw_thresholds; | ||
3474 | else | ||
3475 | BUG(); | ||
3476 | |||
3477 | /* | ||
3478 | * Something went wrong if we trying to unregister a threshold | ||
3479 | * if we don't have thresholds | ||
3480 | */ | ||
3481 | BUG_ON(!thresholds); | ||
3482 | |||
3483 | usage = mem_cgroup_usage(memcg, type == _MEMSWAP); | ||
3484 | |||
3485 | /* Check if a threshold crossed before removing */ | ||
3486 | __mem_cgroup_threshold(memcg, type == _MEMSWAP); | ||
3487 | |||
3488 | /* Calculate new number of threshold */ | ||
3489 | for (i = 0; i < thresholds->size; i++) { | ||
3490 | if (thresholds->entries[i].eventfd != eventfd) | ||
3491 | size++; | ||
3492 | } | ||
3493 | |||
3494 | /* Set thresholds array to NULL if we don't have thresholds */ | ||
3495 | if (!size) { | ||
3496 | thresholds_new = NULL; | ||
3497 | goto assign; | ||
3498 | } | ||
3499 | |||
3500 | /* Allocate memory for new array of thresholds */ | ||
3501 | thresholds_new = kmalloc(sizeof(*thresholds_new) + | ||
3502 | size * sizeof(struct mem_cgroup_threshold), | ||
3503 | GFP_KERNEL); | ||
3504 | if (!thresholds_new) { | ||
3505 | ret = -ENOMEM; | ||
3506 | goto unlock; | ||
3507 | } | ||
3508 | thresholds_new->size = size; | ||
3509 | |||
3510 | /* Copy thresholds and find current threshold */ | ||
3511 | atomic_set(&thresholds_new->current_threshold, -1); | ||
3512 | for (i = 0, j = 0; i < thresholds->size; i++) { | ||
3513 | if (thresholds->entries[i].eventfd == eventfd) | ||
3514 | continue; | ||
3515 | |||
3516 | thresholds_new->entries[j] = thresholds->entries[i]; | ||
3517 | if (thresholds_new->entries[j].threshold < usage) { | ||
3518 | /* | ||
3519 | * thresholds_new->current_threshold will not be used | ||
3520 | * until rcu_assign_pointer(), so it's safe to increment | ||
3521 | * it here. | ||
3522 | */ | ||
3523 | atomic_inc(&thresholds_new->current_threshold); | ||
3524 | } | ||
3525 | j++; | ||
3526 | } | ||
3527 | |||
3528 | assign: | ||
3529 | if (type == _MEM) | ||
3530 | rcu_assign_pointer(memcg->thresholds, thresholds_new); | ||
3531 | else | ||
3532 | rcu_assign_pointer(memcg->memsw_thresholds, thresholds_new); | ||
3533 | |||
3534 | /* To be sure that nobody uses thresholds before freeing it */ | ||
3535 | synchronize_rcu(); | ||
3536 | |||
3537 | kfree(thresholds); | ||
3538 | unlock: | ||
3539 | mutex_unlock(&memcg->thresholds_lock); | ||
3540 | |||
3541 | return ret; | ||
3542 | } | ||
3052 | 3543 | ||
3053 | static struct cftype mem_cgroup_files[] = { | 3544 | static struct cftype mem_cgroup_files[] = { |
3054 | { | 3545 | { |
3055 | .name = "usage_in_bytes", | 3546 | .name = "usage_in_bytes", |
3056 | .private = MEMFILE_PRIVATE(_MEM, RES_USAGE), | 3547 | .private = MEMFILE_PRIVATE(_MEM, RES_USAGE), |
3057 | .read_u64 = mem_cgroup_read, | 3548 | .read_u64 = mem_cgroup_read, |
3549 | .register_event = mem_cgroup_register_event, | ||
3550 | .unregister_event = mem_cgroup_unregister_event, | ||
3058 | }, | 3551 | }, |
3059 | { | 3552 | { |
3060 | .name = "max_usage_in_bytes", | 3553 | .name = "max_usage_in_bytes", |
@@ -3098,6 +3591,11 @@ static struct cftype mem_cgroup_files[] = { | |||
3098 | .read_u64 = mem_cgroup_swappiness_read, | 3591 | .read_u64 = mem_cgroup_swappiness_read, |
3099 | .write_u64 = mem_cgroup_swappiness_write, | 3592 | .write_u64 = mem_cgroup_swappiness_write, |
3100 | }, | 3593 | }, |
3594 | { | ||
3595 | .name = "move_charge_at_immigrate", | ||
3596 | .read_u64 = mem_cgroup_move_charge_read, | ||
3597 | .write_u64 = mem_cgroup_move_charge_write, | ||
3598 | }, | ||
3101 | }; | 3599 | }; |
3102 | 3600 | ||
3103 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP | 3601 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP |
@@ -3106,6 +3604,8 @@ static struct cftype memsw_cgroup_files[] = { | |||
3106 | .name = "memsw.usage_in_bytes", | 3604 | .name = "memsw.usage_in_bytes", |
3107 | .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE), | 3605 | .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE), |
3108 | .read_u64 = mem_cgroup_read, | 3606 | .read_u64 = mem_cgroup_read, |
3607 | .register_event = mem_cgroup_register_event, | ||
3608 | .unregister_event = mem_cgroup_unregister_event, | ||
3109 | }, | 3609 | }, |
3110 | { | 3610 | { |
3111 | .name = "memsw.max_usage_in_bytes", | 3611 | .name = "memsw.max_usage_in_bytes", |
@@ -3180,17 +3680,12 @@ static void free_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node) | |||
3180 | kfree(mem->info.nodeinfo[node]); | 3680 | kfree(mem->info.nodeinfo[node]); |
3181 | } | 3681 | } |
3182 | 3682 | ||
3183 | static int mem_cgroup_size(void) | ||
3184 | { | ||
3185 | int cpustat_size = nr_cpu_ids * sizeof(struct mem_cgroup_stat_cpu); | ||
3186 | return sizeof(struct mem_cgroup) + cpustat_size; | ||
3187 | } | ||
3188 | |||
3189 | static struct mem_cgroup *mem_cgroup_alloc(void) | 3683 | static struct mem_cgroup *mem_cgroup_alloc(void) |
3190 | { | 3684 | { |
3191 | struct mem_cgroup *mem; | 3685 | struct mem_cgroup *mem; |
3192 | int size = mem_cgroup_size(); | 3686 | int size = sizeof(struct mem_cgroup); |
3193 | 3687 | ||
3688 | /* Can be very big if MAX_NUMNODES is very big */ | ||
3194 | if (size < PAGE_SIZE) | 3689 | if (size < PAGE_SIZE) |
3195 | mem = kmalloc(size, GFP_KERNEL); | 3690 | mem = kmalloc(size, GFP_KERNEL); |
3196 | else | 3691 | else |
@@ -3198,6 +3693,14 @@ static struct mem_cgroup *mem_cgroup_alloc(void) | |||
3198 | 3693 | ||
3199 | if (mem) | 3694 | if (mem) |
3200 | memset(mem, 0, size); | 3695 | memset(mem, 0, size); |
3696 | mem->stat = alloc_percpu(struct mem_cgroup_stat_cpu); | ||
3697 | if (!mem->stat) { | ||
3698 | if (size < PAGE_SIZE) | ||
3699 | kfree(mem); | ||
3700 | else | ||
3701 | vfree(mem); | ||
3702 | mem = NULL; | ||
3703 | } | ||
3201 | return mem; | 3704 | return mem; |
3202 | } | 3705 | } |
3203 | 3706 | ||
@@ -3222,7 +3725,8 @@ static void __mem_cgroup_free(struct mem_cgroup *mem) | |||
3222 | for_each_node_state(node, N_POSSIBLE) | 3725 | for_each_node_state(node, N_POSSIBLE) |
3223 | free_mem_cgroup_per_zone_info(mem, node); | 3726 | free_mem_cgroup_per_zone_info(mem, node); |
3224 | 3727 | ||
3225 | if (mem_cgroup_size() < PAGE_SIZE) | 3728 | free_percpu(mem->stat); |
3729 | if (sizeof(struct mem_cgroup) < PAGE_SIZE) | ||
3226 | kfree(mem); | 3730 | kfree(mem); |
3227 | else | 3731 | else |
3228 | vfree(mem); | 3732 | vfree(mem); |
@@ -3233,9 +3737,9 @@ static void mem_cgroup_get(struct mem_cgroup *mem) | |||
3233 | atomic_inc(&mem->refcnt); | 3737 | atomic_inc(&mem->refcnt); |
3234 | } | 3738 | } |
3235 | 3739 | ||
3236 | static void mem_cgroup_put(struct mem_cgroup *mem) | 3740 | static void __mem_cgroup_put(struct mem_cgroup *mem, int count) |
3237 | { | 3741 | { |
3238 | if (atomic_dec_and_test(&mem->refcnt)) { | 3742 | if (atomic_sub_and_test(count, &mem->refcnt)) { |
3239 | struct mem_cgroup *parent = parent_mem_cgroup(mem); | 3743 | struct mem_cgroup *parent = parent_mem_cgroup(mem); |
3240 | __mem_cgroup_free(mem); | 3744 | __mem_cgroup_free(mem); |
3241 | if (parent) | 3745 | if (parent) |
@@ -3243,6 +3747,11 @@ static void mem_cgroup_put(struct mem_cgroup *mem) | |||
3243 | } | 3747 | } |
3244 | } | 3748 | } |
3245 | 3749 | ||
3750 | static void mem_cgroup_put(struct mem_cgroup *mem) | ||
3751 | { | ||
3752 | __mem_cgroup_put(mem, 1); | ||
3753 | } | ||
3754 | |||
3246 | /* | 3755 | /* |
3247 | * Returns the parent mem_cgroup in memcgroup hierarchy with hierarchy enabled. | 3756 | * Returns the parent mem_cgroup in memcgroup hierarchy with hierarchy enabled. |
3248 | */ | 3757 | */ |
@@ -3319,7 +3828,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) | |||
3319 | INIT_WORK(&stock->work, drain_local_stock); | 3828 | INIT_WORK(&stock->work, drain_local_stock); |
3320 | } | 3829 | } |
3321 | hotcpu_notifier(memcg_stock_cpu_callback, 0); | 3830 | hotcpu_notifier(memcg_stock_cpu_callback, 0); |
3322 | |||
3323 | } else { | 3831 | } else { |
3324 | parent = mem_cgroup_from_cont(cont->parent); | 3832 | parent = mem_cgroup_from_cont(cont->parent); |
3325 | mem->use_hierarchy = parent->use_hierarchy; | 3833 | mem->use_hierarchy = parent->use_hierarchy; |
@@ -3345,6 +3853,8 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) | |||
3345 | if (parent) | 3853 | if (parent) |
3346 | mem->swappiness = get_swappiness(parent); | 3854 | mem->swappiness = get_swappiness(parent); |
3347 | atomic_set(&mem->refcnt, 1); | 3855 | atomic_set(&mem->refcnt, 1); |
3856 | mem->move_charge_at_immigrate = 0; | ||
3857 | mutex_init(&mem->thresholds_lock); | ||
3348 | return &mem->css; | 3858 | return &mem->css; |
3349 | free_out: | 3859 | free_out: |
3350 | __mem_cgroup_free(mem); | 3860 | __mem_cgroup_free(mem); |
@@ -3381,16 +3891,444 @@ static int mem_cgroup_populate(struct cgroup_subsys *ss, | |||
3381 | return ret; | 3891 | return ret; |
3382 | } | 3892 | } |
3383 | 3893 | ||
3894 | #ifdef CONFIG_MMU | ||
3895 | /* Handlers for move charge at task migration. */ | ||
3896 | #define PRECHARGE_COUNT_AT_ONCE 256 | ||
3897 | static int mem_cgroup_do_precharge(unsigned long count) | ||
3898 | { | ||
3899 | int ret = 0; | ||
3900 | int batch_count = PRECHARGE_COUNT_AT_ONCE; | ||
3901 | struct mem_cgroup *mem = mc.to; | ||
3902 | |||
3903 | if (mem_cgroup_is_root(mem)) { | ||
3904 | mc.precharge += count; | ||
3905 | /* we don't need css_get for root */ | ||
3906 | return ret; | ||
3907 | } | ||
3908 | /* try to charge at once */ | ||
3909 | if (count > 1) { | ||
3910 | struct res_counter *dummy; | ||
3911 | /* | ||
3912 | * "mem" cannot be under rmdir() because we've already checked | ||
3913 | * by cgroup_lock_live_cgroup() that it is not removed and we | ||
3914 | * are still under the same cgroup_mutex. So we can postpone | ||
3915 | * css_get(). | ||
3916 | */ | ||
3917 | if (res_counter_charge(&mem->res, PAGE_SIZE * count, &dummy)) | ||
3918 | goto one_by_one; | ||
3919 | if (do_swap_account && res_counter_charge(&mem->memsw, | ||
3920 | PAGE_SIZE * count, &dummy)) { | ||
3921 | res_counter_uncharge(&mem->res, PAGE_SIZE * count); | ||
3922 | goto one_by_one; | ||
3923 | } | ||
3924 | mc.precharge += count; | ||
3925 | VM_BUG_ON(test_bit(CSS_ROOT, &mem->css.flags)); | ||
3926 | WARN_ON_ONCE(count > INT_MAX); | ||
3927 | __css_get(&mem->css, (int)count); | ||
3928 | return ret; | ||
3929 | } | ||
3930 | one_by_one: | ||
3931 | /* fall back to one by one charge */ | ||
3932 | while (count--) { | ||
3933 | if (signal_pending(current)) { | ||
3934 | ret = -EINTR; | ||
3935 | break; | ||
3936 | } | ||
3937 | if (!batch_count--) { | ||
3938 | batch_count = PRECHARGE_COUNT_AT_ONCE; | ||
3939 | cond_resched(); | ||
3940 | } | ||
3941 | ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, &mem, false); | ||
3942 | if (ret || !mem) | ||
3943 | /* mem_cgroup_clear_mc() will do uncharge later */ | ||
3944 | return -ENOMEM; | ||
3945 | mc.precharge++; | ||
3946 | } | ||
3947 | return ret; | ||
3948 | } | ||
3949 | #else /* !CONFIG_MMU */ | ||
3950 | static int mem_cgroup_can_attach(struct cgroup_subsys *ss, | ||
3951 | struct cgroup *cgroup, | ||
3952 | struct task_struct *p, | ||
3953 | bool threadgroup) | ||
3954 | { | ||
3955 | return 0; | ||
3956 | } | ||
3957 | static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss, | ||
3958 | struct cgroup *cgroup, | ||
3959 | struct task_struct *p, | ||
3960 | bool threadgroup) | ||
3961 | { | ||
3962 | } | ||
3384 | static void mem_cgroup_move_task(struct cgroup_subsys *ss, | 3963 | static void mem_cgroup_move_task(struct cgroup_subsys *ss, |
3385 | struct cgroup *cont, | 3964 | struct cgroup *cont, |
3386 | struct cgroup *old_cont, | 3965 | struct cgroup *old_cont, |
3387 | struct task_struct *p, | 3966 | struct task_struct *p, |
3388 | bool threadgroup) | 3967 | bool threadgroup) |
3389 | { | 3968 | { |
3969 | } | ||
3970 | #endif | ||
3971 | |||
3972 | /** | ||
3973 | * is_target_pte_for_mc - check a pte whether it is valid for move charge | ||
3974 | * @vma: the vma the pte to be checked belongs | ||
3975 | * @addr: the address corresponding to the pte to be checked | ||
3976 | * @ptent: the pte to be checked | ||
3977 | * @target: the pointer the target page or swap ent will be stored(can be NULL) | ||
3978 | * | ||
3979 | * Returns | ||
3980 | * 0(MC_TARGET_NONE): if the pte is not a target for move charge. | ||
3981 | * 1(MC_TARGET_PAGE): if the page corresponding to this pte is a target for | ||
3982 | * move charge. if @target is not NULL, the page is stored in target->page | ||
3983 | * with extra refcnt got(Callers should handle it). | ||
3984 | * 2(MC_TARGET_SWAP): if the swap entry corresponding to this pte is a | ||
3985 | * target for charge migration. if @target is not NULL, the entry is stored | ||
3986 | * in target->ent. | ||
3987 | * | ||
3988 | * Called with pte lock held. | ||
3989 | */ | ||
3990 | union mc_target { | ||
3991 | struct page *page; | ||
3992 | swp_entry_t ent; | ||
3993 | }; | ||
3994 | |||
3995 | enum mc_target_type { | ||
3996 | MC_TARGET_NONE, /* not used */ | ||
3997 | MC_TARGET_PAGE, | ||
3998 | MC_TARGET_SWAP, | ||
3999 | }; | ||
4000 | |||
4001 | static int is_target_pte_for_mc(struct vm_area_struct *vma, | ||
4002 | unsigned long addr, pte_t ptent, union mc_target *target) | ||
4003 | { | ||
4004 | struct page *page = NULL; | ||
4005 | struct page_cgroup *pc; | ||
4006 | int ret = 0; | ||
4007 | swp_entry_t ent = { .val = 0 }; | ||
4008 | int usage_count = 0; | ||
4009 | bool move_anon = test_bit(MOVE_CHARGE_TYPE_ANON, | ||
4010 | &mc.to->move_charge_at_immigrate); | ||
4011 | |||
4012 | if (!pte_present(ptent)) { | ||
4013 | /* TODO: handle swap of shmes/tmpfs */ | ||
4014 | if (pte_none(ptent) || pte_file(ptent)) | ||
4015 | return 0; | ||
4016 | else if (is_swap_pte(ptent)) { | ||
4017 | ent = pte_to_swp_entry(ptent); | ||
4018 | if (!move_anon || non_swap_entry(ent)) | ||
4019 | return 0; | ||
4020 | usage_count = mem_cgroup_count_swap_user(ent, &page); | ||
4021 | } | ||
4022 | } else { | ||
4023 | page = vm_normal_page(vma, addr, ptent); | ||
4024 | if (!page || !page_mapped(page)) | ||
4025 | return 0; | ||
4026 | /* | ||
4027 | * TODO: We don't move charges of file(including shmem/tmpfs) | ||
4028 | * pages for now. | ||
4029 | */ | ||
4030 | if (!move_anon || !PageAnon(page)) | ||
4031 | return 0; | ||
4032 | if (!get_page_unless_zero(page)) | ||
4033 | return 0; | ||
4034 | usage_count = page_mapcount(page); | ||
4035 | } | ||
4036 | if (usage_count > 1) { | ||
4037 | /* | ||
4038 | * TODO: We don't move charges of shared(used by multiple | ||
4039 | * processes) pages for now. | ||
4040 | */ | ||
4041 | if (page) | ||
4042 | put_page(page); | ||
4043 | return 0; | ||
4044 | } | ||
4045 | if (page) { | ||
4046 | pc = lookup_page_cgroup(page); | ||
4047 | /* | ||
4048 | * Do only loose check w/o page_cgroup lock. | ||
4049 | * mem_cgroup_move_account() checks the pc is valid or not under | ||
4050 | * the lock. | ||
4051 | */ | ||
4052 | if (PageCgroupUsed(pc) && pc->mem_cgroup == mc.from) { | ||
4053 | ret = MC_TARGET_PAGE; | ||
4054 | if (target) | ||
4055 | target->page = page; | ||
4056 | } | ||
4057 | if (!ret || !target) | ||
4058 | put_page(page); | ||
4059 | } | ||
4060 | /* throught */ | ||
4061 | if (ent.val && do_swap_account && !ret && | ||
4062 | css_id(&mc.from->css) == lookup_swap_cgroup(ent)) { | ||
4063 | ret = MC_TARGET_SWAP; | ||
4064 | if (target) | ||
4065 | target->ent = ent; | ||
4066 | } | ||
4067 | return ret; | ||
4068 | } | ||
4069 | |||
4070 | static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd, | ||
4071 | unsigned long addr, unsigned long end, | ||
4072 | struct mm_walk *walk) | ||
4073 | { | ||
4074 | struct vm_area_struct *vma = walk->private; | ||
4075 | pte_t *pte; | ||
4076 | spinlock_t *ptl; | ||
4077 | |||
4078 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | ||
4079 | for (; addr != end; pte++, addr += PAGE_SIZE) | ||
4080 | if (is_target_pte_for_mc(vma, addr, *pte, NULL)) | ||
4081 | mc.precharge++; /* increment precharge temporarily */ | ||
4082 | pte_unmap_unlock(pte - 1, ptl); | ||
4083 | cond_resched(); | ||
4084 | |||
4085 | return 0; | ||
4086 | } | ||
4087 | |||
4088 | static unsigned long mem_cgroup_count_precharge(struct mm_struct *mm) | ||
4089 | { | ||
4090 | unsigned long precharge; | ||
4091 | struct vm_area_struct *vma; | ||
4092 | |||
4093 | down_read(&mm->mmap_sem); | ||
4094 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | ||
4095 | struct mm_walk mem_cgroup_count_precharge_walk = { | ||
4096 | .pmd_entry = mem_cgroup_count_precharge_pte_range, | ||
4097 | .mm = mm, | ||
4098 | .private = vma, | ||
4099 | }; | ||
4100 | if (is_vm_hugetlb_page(vma)) | ||
4101 | continue; | ||
4102 | /* TODO: We don't move charges of shmem/tmpfs pages for now. */ | ||
4103 | if (vma->vm_flags & VM_SHARED) | ||
4104 | continue; | ||
4105 | walk_page_range(vma->vm_start, vma->vm_end, | ||
4106 | &mem_cgroup_count_precharge_walk); | ||
4107 | } | ||
4108 | up_read(&mm->mmap_sem); | ||
4109 | |||
4110 | precharge = mc.precharge; | ||
4111 | mc.precharge = 0; | ||
4112 | |||
4113 | return precharge; | ||
4114 | } | ||
4115 | |||
4116 | static int mem_cgroup_precharge_mc(struct mm_struct *mm) | ||
4117 | { | ||
4118 | return mem_cgroup_do_precharge(mem_cgroup_count_precharge(mm)); | ||
4119 | } | ||
4120 | |||
4121 | static void mem_cgroup_clear_mc(void) | ||
4122 | { | ||
4123 | /* we must uncharge all the leftover precharges from mc.to */ | ||
4124 | if (mc.precharge) { | ||
4125 | __mem_cgroup_cancel_charge(mc.to, mc.precharge); | ||
4126 | mc.precharge = 0; | ||
4127 | } | ||
3390 | /* | 4128 | /* |
3391 | * FIXME: It's better to move charges of this process from old | 4129 | * we didn't uncharge from mc.from at mem_cgroup_move_account(), so |
3392 | * memcg to new memcg. But it's just on TODO-List now. | 4130 | * we must uncharge here. |
3393 | */ | 4131 | */ |
4132 | if (mc.moved_charge) { | ||
4133 | __mem_cgroup_cancel_charge(mc.from, mc.moved_charge); | ||
4134 | mc.moved_charge = 0; | ||
4135 | } | ||
4136 | /* we must fixup refcnts and charges */ | ||
4137 | if (mc.moved_swap) { | ||
4138 | WARN_ON_ONCE(mc.moved_swap > INT_MAX); | ||
4139 | /* uncharge swap account from the old cgroup */ | ||
4140 | if (!mem_cgroup_is_root(mc.from)) | ||
4141 | res_counter_uncharge(&mc.from->memsw, | ||
4142 | PAGE_SIZE * mc.moved_swap); | ||
4143 | __mem_cgroup_put(mc.from, mc.moved_swap); | ||
4144 | |||
4145 | if (!mem_cgroup_is_root(mc.to)) { | ||
4146 | /* | ||
4147 | * we charged both to->res and to->memsw, so we should | ||
4148 | * uncharge to->res. | ||
4149 | */ | ||
4150 | res_counter_uncharge(&mc.to->res, | ||
4151 | PAGE_SIZE * mc.moved_swap); | ||
4152 | VM_BUG_ON(test_bit(CSS_ROOT, &mc.to->css.flags)); | ||
4153 | __css_put(&mc.to->css, mc.moved_swap); | ||
4154 | } | ||
4155 | /* we've already done mem_cgroup_get(mc.to) */ | ||
4156 | |||
4157 | mc.moved_swap = 0; | ||
4158 | } | ||
4159 | mc.from = NULL; | ||
4160 | mc.to = NULL; | ||
4161 | mc.moving_task = NULL; | ||
4162 | wake_up_all(&mc.waitq); | ||
4163 | } | ||
4164 | |||
4165 | static int mem_cgroup_can_attach(struct cgroup_subsys *ss, | ||
4166 | struct cgroup *cgroup, | ||
4167 | struct task_struct *p, | ||
4168 | bool threadgroup) | ||
4169 | { | ||
4170 | int ret = 0; | ||
4171 | struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup); | ||
4172 | |||
4173 | if (mem->move_charge_at_immigrate) { | ||
4174 | struct mm_struct *mm; | ||
4175 | struct mem_cgroup *from = mem_cgroup_from_task(p); | ||
4176 | |||
4177 | VM_BUG_ON(from == mem); | ||
4178 | |||
4179 | mm = get_task_mm(p); | ||
4180 | if (!mm) | ||
4181 | return 0; | ||
4182 | /* We move charges only when we move a owner of the mm */ | ||
4183 | if (mm->owner == p) { | ||
4184 | VM_BUG_ON(mc.from); | ||
4185 | VM_BUG_ON(mc.to); | ||
4186 | VM_BUG_ON(mc.precharge); | ||
4187 | VM_BUG_ON(mc.moved_charge); | ||
4188 | VM_BUG_ON(mc.moved_swap); | ||
4189 | VM_BUG_ON(mc.moving_task); | ||
4190 | mc.from = from; | ||
4191 | mc.to = mem; | ||
4192 | mc.precharge = 0; | ||
4193 | mc.moved_charge = 0; | ||
4194 | mc.moved_swap = 0; | ||
4195 | mc.moving_task = current; | ||
4196 | |||
4197 | ret = mem_cgroup_precharge_mc(mm); | ||
4198 | if (ret) | ||
4199 | mem_cgroup_clear_mc(); | ||
4200 | } | ||
4201 | mmput(mm); | ||
4202 | } | ||
4203 | return ret; | ||
4204 | } | ||
4205 | |||
4206 | static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss, | ||
4207 | struct cgroup *cgroup, | ||
4208 | struct task_struct *p, | ||
4209 | bool threadgroup) | ||
4210 | { | ||
4211 | mem_cgroup_clear_mc(); | ||
4212 | } | ||
4213 | |||
4214 | static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, | ||
4215 | unsigned long addr, unsigned long end, | ||
4216 | struct mm_walk *walk) | ||
4217 | { | ||
4218 | int ret = 0; | ||
4219 | struct vm_area_struct *vma = walk->private; | ||
4220 | pte_t *pte; | ||
4221 | spinlock_t *ptl; | ||
4222 | |||
4223 | retry: | ||
4224 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | ||
4225 | for (; addr != end; addr += PAGE_SIZE) { | ||
4226 | pte_t ptent = *(pte++); | ||
4227 | union mc_target target; | ||
4228 | int type; | ||
4229 | struct page *page; | ||
4230 | struct page_cgroup *pc; | ||
4231 | swp_entry_t ent; | ||
4232 | |||
4233 | if (!mc.precharge) | ||
4234 | break; | ||
4235 | |||
4236 | type = is_target_pte_for_mc(vma, addr, ptent, &target); | ||
4237 | switch (type) { | ||
4238 | case MC_TARGET_PAGE: | ||
4239 | page = target.page; | ||
4240 | if (isolate_lru_page(page)) | ||
4241 | goto put; | ||
4242 | pc = lookup_page_cgroup(page); | ||
4243 | if (!mem_cgroup_move_account(pc, | ||
4244 | mc.from, mc.to, false)) { | ||
4245 | mc.precharge--; | ||
4246 | /* we uncharge from mc.from later. */ | ||
4247 | mc.moved_charge++; | ||
4248 | } | ||
4249 | putback_lru_page(page); | ||
4250 | put: /* is_target_pte_for_mc() gets the page */ | ||
4251 | put_page(page); | ||
4252 | break; | ||
4253 | case MC_TARGET_SWAP: | ||
4254 | ent = target.ent; | ||
4255 | if (!mem_cgroup_move_swap_account(ent, | ||
4256 | mc.from, mc.to, false)) { | ||
4257 | mc.precharge--; | ||
4258 | /* we fixup refcnts and charges later. */ | ||
4259 | mc.moved_swap++; | ||
4260 | } | ||
4261 | break; | ||
4262 | default: | ||
4263 | break; | ||
4264 | } | ||
4265 | } | ||
4266 | pte_unmap_unlock(pte - 1, ptl); | ||
4267 | cond_resched(); | ||
4268 | |||
4269 | if (addr != end) { | ||
4270 | /* | ||
4271 | * We have consumed all precharges we got in can_attach(). | ||
4272 | * We try charge one by one, but don't do any additional | ||
4273 | * charges to mc.to if we have failed in charge once in attach() | ||
4274 | * phase. | ||
4275 | */ | ||
4276 | ret = mem_cgroup_do_precharge(1); | ||
4277 | if (!ret) | ||
4278 | goto retry; | ||
4279 | } | ||
4280 | |||
4281 | return ret; | ||
4282 | } | ||
4283 | |||
4284 | static void mem_cgroup_move_charge(struct mm_struct *mm) | ||
4285 | { | ||
4286 | struct vm_area_struct *vma; | ||
4287 | |||
4288 | lru_add_drain_all(); | ||
4289 | down_read(&mm->mmap_sem); | ||
4290 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | ||
4291 | int ret; | ||
4292 | struct mm_walk mem_cgroup_move_charge_walk = { | ||
4293 | .pmd_entry = mem_cgroup_move_charge_pte_range, | ||
4294 | .mm = mm, | ||
4295 | .private = vma, | ||
4296 | }; | ||
4297 | if (is_vm_hugetlb_page(vma)) | ||
4298 | continue; | ||
4299 | /* TODO: We don't move charges of shmem/tmpfs pages for now. */ | ||
4300 | if (vma->vm_flags & VM_SHARED) | ||
4301 | continue; | ||
4302 | ret = walk_page_range(vma->vm_start, vma->vm_end, | ||
4303 | &mem_cgroup_move_charge_walk); | ||
4304 | if (ret) | ||
4305 | /* | ||
4306 | * means we have consumed all precharges and failed in | ||
4307 | * doing additional charge. Just abandon here. | ||
4308 | */ | ||
4309 | break; | ||
4310 | } | ||
4311 | up_read(&mm->mmap_sem); | ||
4312 | } | ||
4313 | |||
4314 | static void mem_cgroup_move_task(struct cgroup_subsys *ss, | ||
4315 | struct cgroup *cont, | ||
4316 | struct cgroup *old_cont, | ||
4317 | struct task_struct *p, | ||
4318 | bool threadgroup) | ||
4319 | { | ||
4320 | struct mm_struct *mm; | ||
4321 | |||
4322 | if (!mc.to) | ||
4323 | /* no need to move charge */ | ||
4324 | return; | ||
4325 | |||
4326 | mm = get_task_mm(p); | ||
4327 | if (mm) { | ||
4328 | mem_cgroup_move_charge(mm); | ||
4329 | mmput(mm); | ||
4330 | } | ||
4331 | mem_cgroup_clear_mc(); | ||
3394 | } | 4332 | } |
3395 | 4333 | ||
3396 | struct cgroup_subsys mem_cgroup_subsys = { | 4334 | struct cgroup_subsys mem_cgroup_subsys = { |
@@ -3400,6 +4338,8 @@ struct cgroup_subsys mem_cgroup_subsys = { | |||
3400 | .pre_destroy = mem_cgroup_pre_destroy, | 4338 | .pre_destroy = mem_cgroup_pre_destroy, |
3401 | .destroy = mem_cgroup_destroy, | 4339 | .destroy = mem_cgroup_destroy, |
3402 | .populate = mem_cgroup_populate, | 4340 | .populate = mem_cgroup_populate, |
4341 | .can_attach = mem_cgroup_can_attach, | ||
4342 | .cancel_attach = mem_cgroup_cancel_attach, | ||
3403 | .attach = mem_cgroup_move_task, | 4343 | .attach = mem_cgroup_move_task, |
3404 | .early_init = 0, | 4344 | .early_init = 0, |
3405 | .use_id = 1, | 4345 | .use_id = 1, |
diff --git a/mm/memory.c b/mm/memory.c index d1153e37e9ba..5b7f2002e54b 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -190,9 +190,6 @@ static void check_sync_rss_stat(struct task_struct *task) | |||
190 | { | 190 | { |
191 | } | 191 | } |
192 | 192 | ||
193 | void sync_mm_rss(struct task_struct *task, struct mm_struct *mm) | ||
194 | { | ||
195 | } | ||
196 | #endif | 193 | #endif |
197 | 194 | ||
198 | /* | 195 | /* |
@@ -512,12 +509,8 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, | |||
512 | "BUG: Bad page map in process %s pte:%08llx pmd:%08llx\n", | 509 | "BUG: Bad page map in process %s pte:%08llx pmd:%08llx\n", |
513 | current->comm, | 510 | current->comm, |
514 | (long long)pte_val(pte), (long long)pmd_val(*pmd)); | 511 | (long long)pte_val(pte), (long long)pmd_val(*pmd)); |
515 | if (page) { | 512 | if (page) |
516 | printk(KERN_ALERT | 513 | dump_page(page); |
517 | "page:%p flags:%p count:%d mapcount:%d mapping:%p index:%lx\n", | ||
518 | page, (void *)page->flags, page_count(page), | ||
519 | page_mapcount(page), page->mapping, page->index); | ||
520 | } | ||
521 | printk(KERN_ALERT | 514 | printk(KERN_ALERT |
522 | "addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n", | 515 | "addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n", |
523 | (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index); | 516 | (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 78e34e63c7b8..be211a582930 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -688,9 +688,9 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) | |||
688 | if (page_count(page)) | 688 | if (page_count(page)) |
689 | not_managed++; | 689 | not_managed++; |
690 | #ifdef CONFIG_DEBUG_VM | 690 | #ifdef CONFIG_DEBUG_VM |
691 | printk(KERN_INFO "removing from LRU failed" | 691 | printk(KERN_ALERT "removing pfn %lx from LRU failed\n", |
692 | " %lx/%d/%lx\n", | 692 | pfn); |
693 | pfn, page_count(page), page->flags); | 693 | dump_page(page); |
694 | #endif | 694 | #endif |
695 | } | 695 | } |
696 | } | 696 | } |
@@ -1088,6 +1088,30 @@ out: | |||
1088 | return retval; | 1088 | return retval; |
1089 | } | 1089 | } |
1090 | 1090 | ||
1091 | #ifdef __ARCH_WANT_SYS_OLD_MMAP | ||
1092 | struct mmap_arg_struct { | ||
1093 | unsigned long addr; | ||
1094 | unsigned long len; | ||
1095 | unsigned long prot; | ||
1096 | unsigned long flags; | ||
1097 | unsigned long fd; | ||
1098 | unsigned long offset; | ||
1099 | }; | ||
1100 | |||
1101 | SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg) | ||
1102 | { | ||
1103 | struct mmap_arg_struct a; | ||
1104 | |||
1105 | if (copy_from_user(&a, arg, sizeof(a))) | ||
1106 | return -EFAULT; | ||
1107 | if (a.offset & ~PAGE_MASK) | ||
1108 | return -EINVAL; | ||
1109 | |||
1110 | return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, | ||
1111 | a.offset >> PAGE_SHIFT); | ||
1112 | } | ||
1113 | #endif /* __ARCH_WANT_SYS_OLD_MMAP */ | ||
1114 | |||
1091 | /* | 1115 | /* |
1092 | * Some shared mappigns will want the pages marked read-only | 1116 | * Some shared mappigns will want the pages marked read-only |
1093 | * to track write events. If so, we'll downgrade vm_page_prot | 1117 | * to track write events. If so, we'll downgrade vm_page_prot |
diff --git a/mm/nommu.c b/mm/nommu.c index b9b5cceb1b68..605ace8982a8 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1428,6 +1428,30 @@ out: | |||
1428 | return retval; | 1428 | return retval; |
1429 | } | 1429 | } |
1430 | 1430 | ||
1431 | #ifdef __ARCH_WANT_SYS_OLD_MMAP | ||
1432 | struct mmap_arg_struct { | ||
1433 | unsigned long addr; | ||
1434 | unsigned long len; | ||
1435 | unsigned long prot; | ||
1436 | unsigned long flags; | ||
1437 | unsigned long fd; | ||
1438 | unsigned long offset; | ||
1439 | }; | ||
1440 | |||
1441 | SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg) | ||
1442 | { | ||
1443 | struct mmap_arg_struct a; | ||
1444 | |||
1445 | if (copy_from_user(&a, arg, sizeof(a))) | ||
1446 | return -EFAULT; | ||
1447 | if (a.offset & ~PAGE_MASK) | ||
1448 | return -EINVAL; | ||
1449 | |||
1450 | return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, | ||
1451 | a.offset >> PAGE_SHIFT); | ||
1452 | } | ||
1453 | #endif /* __ARCH_WANT_SYS_OLD_MMAP */ | ||
1454 | |||
1431 | /* | 1455 | /* |
1432 | * split a vma into two pieces at address 'addr', a new vma is allocated either | 1456 | * split a vma into two pieces at address 'addr', a new vma is allocated either |
1433 | * for the first part or the tail. | 1457 | * for the first part or the tail. |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 35755a4156d6..9b223af6a147 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -473,6 +473,8 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask) | |||
473 | unsigned long points = 0; | 473 | unsigned long points = 0; |
474 | struct task_struct *p; | 474 | struct task_struct *p; |
475 | 475 | ||
476 | if (sysctl_panic_on_oom == 2) | ||
477 | panic("out of memory(memcg). panic_on_oom is selected.\n"); | ||
476 | read_lock(&tasklist_lock); | 478 | read_lock(&tasklist_lock); |
477 | retry: | 479 | retry: |
478 | p = select_bad_process(&points, mem); | 480 | p = select_bad_process(&points, mem); |
@@ -601,13 +603,6 @@ void pagefault_out_of_memory(void) | |||
601 | /* Got some memory back in the last second. */ | 603 | /* Got some memory back in the last second. */ |
602 | return; | 604 | return; |
603 | 605 | ||
604 | /* | ||
605 | * If this is from memcg, oom-killer is already invoked. | ||
606 | * and not worth to go system-wide-oom. | ||
607 | */ | ||
608 | if (mem_cgroup_oom_called(current)) | ||
609 | goto rest_and_return; | ||
610 | |||
611 | if (sysctl_panic_on_oom) | 606 | if (sysctl_panic_on_oom) |
612 | panic("out of memory from page fault. panic_on_oom is selected.\n"); | 607 | panic("out of memory from page fault. panic_on_oom is selected.\n"); |
613 | 608 | ||
@@ -619,7 +614,6 @@ void pagefault_out_of_memory(void) | |||
619 | * Give "p" a good chance of killing itself before we | 614 | * Give "p" a good chance of killing itself before we |
620 | * retry to allocate memory. | 615 | * retry to allocate memory. |
621 | */ | 616 | */ |
622 | rest_and_return: | ||
623 | if (!test_thread_flag(TIF_MEMDIE)) | 617 | if (!test_thread_flag(TIF_MEMDIE)) |
624 | schedule_timeout_uninterruptible(1); | 618 | schedule_timeout_uninterruptible(1); |
625 | } | 619 | } |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a8182c89de59..d03c946d5566 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/kmemleak.h> | 50 | #include <linux/kmemleak.h> |
51 | #include <linux/memory.h> | 51 | #include <linux/memory.h> |
52 | #include <trace/events/kmem.h> | 52 | #include <trace/events/kmem.h> |
53 | #include <linux/ftrace_event.h> | ||
53 | 54 | ||
54 | #include <asm/tlbflush.h> | 55 | #include <asm/tlbflush.h> |
55 | #include <asm/div64.h> | 56 | #include <asm/div64.h> |
@@ -288,10 +289,7 @@ static void bad_page(struct page *page) | |||
288 | 289 | ||
289 | printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n", | 290 | printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n", |
290 | current->comm, page_to_pfn(page)); | 291 | current->comm, page_to_pfn(page)); |
291 | printk(KERN_ALERT | 292 | dump_page(page); |
292 | "page:%p flags:%p count:%d mapcount:%d mapping:%p index:%lx\n", | ||
293 | page, (void *)page->flags, page_count(page), | ||
294 | page_mapcount(page), page->mapping, page->index); | ||
295 | 293 | ||
296 | dump_stack(); | 294 | dump_stack(); |
297 | out: | 295 | out: |
@@ -3224,7 +3222,7 @@ static int __zone_pcp_update(void *data) | |||
3224 | int cpu; | 3222 | int cpu; |
3225 | unsigned long batch = zone_batchsize(zone), flags; | 3223 | unsigned long batch = zone_batchsize(zone), flags; |
3226 | 3224 | ||
3227 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 3225 | for_each_possible_cpu(cpu) { |
3228 | struct per_cpu_pageset *pset; | 3226 | struct per_cpu_pageset *pset; |
3229 | struct per_cpu_pages *pcp; | 3227 | struct per_cpu_pages *pcp; |
3230 | 3228 | ||
@@ -5183,3 +5181,80 @@ bool is_free_buddy_page(struct page *page) | |||
5183 | return order < MAX_ORDER; | 5181 | return order < MAX_ORDER; |
5184 | } | 5182 | } |
5185 | #endif | 5183 | #endif |
5184 | |||
5185 | static struct trace_print_flags pageflag_names[] = { | ||
5186 | {1UL << PG_locked, "locked" }, | ||
5187 | {1UL << PG_error, "error" }, | ||
5188 | {1UL << PG_referenced, "referenced" }, | ||
5189 | {1UL << PG_uptodate, "uptodate" }, | ||
5190 | {1UL << PG_dirty, "dirty" }, | ||
5191 | {1UL << PG_lru, "lru" }, | ||
5192 | {1UL << PG_active, "active" }, | ||
5193 | {1UL << PG_slab, "slab" }, | ||
5194 | {1UL << PG_owner_priv_1, "owner_priv_1" }, | ||
5195 | {1UL << PG_arch_1, "arch_1" }, | ||
5196 | {1UL << PG_reserved, "reserved" }, | ||
5197 | {1UL << PG_private, "private" }, | ||
5198 | {1UL << PG_private_2, "private_2" }, | ||
5199 | {1UL << PG_writeback, "writeback" }, | ||
5200 | #ifdef CONFIG_PAGEFLAGS_EXTENDED | ||
5201 | {1UL << PG_head, "head" }, | ||
5202 | {1UL << PG_tail, "tail" }, | ||
5203 | #else | ||
5204 | {1UL << PG_compound, "compound" }, | ||
5205 | #endif | ||
5206 | {1UL << PG_swapcache, "swapcache" }, | ||
5207 | {1UL << PG_mappedtodisk, "mappedtodisk" }, | ||
5208 | {1UL << PG_reclaim, "reclaim" }, | ||
5209 | {1UL << PG_buddy, "buddy" }, | ||
5210 | {1UL << PG_swapbacked, "swapbacked" }, | ||
5211 | {1UL << PG_unevictable, "unevictable" }, | ||
5212 | #ifdef CONFIG_MMU | ||
5213 | {1UL << PG_mlocked, "mlocked" }, | ||
5214 | #endif | ||
5215 | #ifdef CONFIG_ARCH_USES_PG_UNCACHED | ||
5216 | {1UL << PG_uncached, "uncached" }, | ||
5217 | #endif | ||
5218 | #ifdef CONFIG_MEMORY_FAILURE | ||
5219 | {1UL << PG_hwpoison, "hwpoison" }, | ||
5220 | #endif | ||
5221 | {-1UL, NULL }, | ||
5222 | }; | ||
5223 | |||
5224 | static void dump_page_flags(unsigned long flags) | ||
5225 | { | ||
5226 | const char *delim = ""; | ||
5227 | unsigned long mask; | ||
5228 | int i; | ||
5229 | |||
5230 | printk(KERN_ALERT "page flags: %#lx(", flags); | ||
5231 | |||
5232 | /* remove zone id */ | ||
5233 | flags &= (1UL << NR_PAGEFLAGS) - 1; | ||
5234 | |||
5235 | for (i = 0; pageflag_names[i].name && flags; i++) { | ||
5236 | |||
5237 | mask = pageflag_names[i].mask; | ||
5238 | if ((flags & mask) != mask) | ||
5239 | continue; | ||
5240 | |||
5241 | flags &= ~mask; | ||
5242 | printk("%s%s", delim, pageflag_names[i].name); | ||
5243 | delim = "|"; | ||
5244 | } | ||
5245 | |||
5246 | /* check for left over flags */ | ||
5247 | if (flags) | ||
5248 | printk("%s%#lx", delim, flags); | ||
5249 | |||
5250 | printk(")\n"); | ||
5251 | } | ||
5252 | |||
5253 | void dump_page(struct page *page) | ||
5254 | { | ||
5255 | printk(KERN_ALERT | ||
5256 | "page:%p count:%d mapcount:%d mapping:%p index:%#lx\n", | ||
5257 | page, page_count(page), page_mapcount(page), | ||
5258 | page->mapping, page->index); | ||
5259 | dump_page_flags(page->flags); | ||
5260 | } | ||
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 3d535d594826..3dd88539a0e6 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -335,6 +335,37 @@ not_enough_page: | |||
335 | } | 335 | } |
336 | 336 | ||
337 | /** | 337 | /** |
338 | * swap_cgroup_cmpxchg - cmpxchg mem_cgroup's id for this swp_entry. | ||
339 | * @end: swap entry to be cmpxchged | ||
340 | * @old: old id | ||
341 | * @new: new id | ||
342 | * | ||
343 | * Returns old id at success, 0 at failure. | ||
344 | * (There is no mem_cgroup useing 0 as its id) | ||
345 | */ | ||
346 | unsigned short swap_cgroup_cmpxchg(swp_entry_t ent, | ||
347 | unsigned short old, unsigned short new) | ||
348 | { | ||
349 | int type = swp_type(ent); | ||
350 | unsigned long offset = swp_offset(ent); | ||
351 | unsigned long idx = offset / SC_PER_PAGE; | ||
352 | unsigned long pos = offset & SC_POS_MASK; | ||
353 | struct swap_cgroup_ctrl *ctrl; | ||
354 | struct page *mappage; | ||
355 | struct swap_cgroup *sc; | ||
356 | |||
357 | ctrl = &swap_cgroup_ctrl[type]; | ||
358 | |||
359 | mappage = ctrl->map[idx]; | ||
360 | sc = page_address(mappage); | ||
361 | sc += pos; | ||
362 | if (cmpxchg(&sc->id, old, new) == old) | ||
363 | return old; | ||
364 | else | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | /** | ||
338 | * swap_cgroup_record - record mem_cgroup for this swp_entry. | 369 | * swap_cgroup_record - record mem_cgroup for this swp_entry. |
339 | * @ent: swap entry to be recorded into | 370 | * @ent: swap entry to be recorded into |
340 | * @mem: mem_cgroup to be recorded | 371 | * @mem: mem_cgroup to be recorded |
@@ -358,8 +389,7 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id) | |||
358 | mappage = ctrl->map[idx]; | 389 | mappage = ctrl->map[idx]; |
359 | sc = page_address(mappage); | 390 | sc = page_address(mappage); |
360 | sc += pos; | 391 | sc += pos; |
361 | old = sc->id; | 392 | old = xchg(&sc->id, id); |
362 | sc->id = id; | ||
363 | 393 | ||
364 | return old; | 394 | return old; |
365 | } | 395 | } |
@@ -4390,7 +4390,7 @@ static void kmem_cache_release(struct kobject *kobj) | |||
4390 | kfree(s); | 4390 | kfree(s); |
4391 | } | 4391 | } |
4392 | 4392 | ||
4393 | static struct sysfs_ops slab_sysfs_ops = { | 4393 | static const struct sysfs_ops slab_sysfs_ops = { |
4394 | .show = slab_attr_show, | 4394 | .show = slab_attr_show, |
4395 | .store = slab_attr_store, | 4395 | .store = slab_attr_store, |
4396 | }; | 4396 | }; |
@@ -4409,7 +4409,7 @@ static int uevent_filter(struct kset *kset, struct kobject *kobj) | |||
4409 | return 0; | 4409 | return 0; |
4410 | } | 4410 | } |
4411 | 4411 | ||
4412 | static struct kset_uevent_ops slab_uevent_ops = { | 4412 | static const struct kset_uevent_ops slab_uevent_ops = { |
4413 | .filter = uevent_filter, | 4413 | .filter = uevent_filter, |
4414 | }; | 4414 | }; |
4415 | 4415 | ||
diff --git a/mm/swapfile.c b/mm/swapfile.c index 84374d8cf814..6cd0a8f90dc7 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -723,6 +723,37 @@ int free_swap_and_cache(swp_entry_t entry) | |||
723 | return p != NULL; | 723 | return p != NULL; |
724 | } | 724 | } |
725 | 725 | ||
726 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | ||
727 | /** | ||
728 | * mem_cgroup_count_swap_user - count the user of a swap entry | ||
729 | * @ent: the swap entry to be checked | ||
730 | * @pagep: the pointer for the swap cache page of the entry to be stored | ||
731 | * | ||
732 | * Returns the number of the user of the swap entry. The number is valid only | ||
733 | * for swaps of anonymous pages. | ||
734 | * If the entry is found on swap cache, the page is stored to pagep with | ||
735 | * refcount of it being incremented. | ||
736 | */ | ||
737 | int mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep) | ||
738 | { | ||
739 | struct page *page; | ||
740 | struct swap_info_struct *p; | ||
741 | int count = 0; | ||
742 | |||
743 | page = find_get_page(&swapper_space, ent.val); | ||
744 | if (page) | ||
745 | count += page_mapcount(page); | ||
746 | p = swap_info_get(ent); | ||
747 | if (p) { | ||
748 | count += swap_count(p->swap_map[swp_offset(ent)]); | ||
749 | spin_unlock(&swap_lock); | ||
750 | } | ||
751 | |||
752 | *pagep = page; | ||
753 | return count; | ||
754 | } | ||
755 | #endif | ||
756 | |||
726 | #ifdef CONFIG_HIBERNATION | 757 | #ifdef CONFIG_HIBERNATION |
727 | /* | 758 | /* |
728 | * Find the swap type that corresponds to given device (if any). | 759 | * Find the swap type that corresponds to given device (if any). |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 400efa26ddba..4db7ae2fe07d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -3937,7 +3937,9 @@ drop: | |||
3937 | return 0; | 3937 | return 0; |
3938 | } | 3938 | } |
3939 | 3939 | ||
3940 | static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) | 3940 | static ssize_t l2cap_sysfs_show(struct class *dev, |
3941 | struct class_attribute *attr, | ||
3942 | char *buf) | ||
3941 | { | 3943 | { |
3942 | struct sock *sk; | 3944 | struct sock *sk; |
3943 | struct hlist_node *node; | 3945 | struct hlist_node *node; |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 89f4a59eb82b..db8a68e1a5ba 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -2098,7 +2098,9 @@ static struct hci_cb rfcomm_cb = { | |||
2098 | .security_cfm = rfcomm_security_cfm | 2098 | .security_cfm = rfcomm_security_cfm |
2099 | }; | 2099 | }; |
2100 | 2100 | ||
2101 | static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf) | 2101 | static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, |
2102 | struct class_attribute *attr, | ||
2103 | char *buf) | ||
2102 | { | 2104 | { |
2103 | struct rfcomm_session *s; | 2105 | struct rfcomm_session *s; |
2104 | struct list_head *pp, *p; | 2106 | struct list_head *pp, *p; |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 4b5968dda673..ca87d6ac6a20 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -1061,7 +1061,9 @@ done: | |||
1061 | return result; | 1061 | return result; |
1062 | } | 1062 | } |
1063 | 1063 | ||
1064 | static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf) | 1064 | static ssize_t rfcomm_sock_sysfs_show(struct class *dev, |
1065 | struct class_attribute *attr, | ||
1066 | char *buf) | ||
1065 | { | 1067 | { |
1066 | struct sock *sk; | 1068 | struct sock *sk; |
1067 | struct hlist_node *node; | 1069 | struct hlist_node *node; |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index dd8f6ec57dce..f93b939539bc 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -953,7 +953,9 @@ drop: | |||
953 | return 0; | 953 | return 0; |
954 | } | 954 | } |
955 | 955 | ||
956 | static ssize_t sco_sysfs_show(struct class *dev, char *buf) | 956 | static ssize_t sco_sysfs_show(struct class *dev, |
957 | struct class_attribute *attr, | ||
958 | char *buf) | ||
957 | { | 959 | { |
958 | struct sock *sk; | 960 | struct sock *sk; |
959 | struct hlist_node *node; | 961 | struct hlist_node *node; |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1cf2cef78584..fef0384e3c0b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -423,7 +423,7 @@ extern void br_ifinfo_notify(int event, struct net_bridge_port *port); | |||
423 | 423 | ||
424 | #ifdef CONFIG_SYSFS | 424 | #ifdef CONFIG_SYSFS |
425 | /* br_sysfs_if.c */ | 425 | /* br_sysfs_if.c */ |
426 | extern struct sysfs_ops brport_sysfs_ops; | 426 | extern const struct sysfs_ops brport_sysfs_ops; |
427 | extern int br_sysfs_addif(struct net_bridge_port *p); | 427 | extern int br_sysfs_addif(struct net_bridge_port *p); |
428 | 428 | ||
429 | /* br_sysfs_br.c */ | 429 | /* br_sysfs_br.c */ |
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 696596cd3384..0b9916489d6b 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -238,7 +238,7 @@ static ssize_t brport_store(struct kobject * kobj, | |||
238 | return ret; | 238 | return ret; |
239 | } | 239 | } |
240 | 240 | ||
241 | struct sysfs_ops brport_sysfs_ops = { | 241 | const struct sysfs_ops brport_sysfs_ops = { |
242 | .show = brport_show, | 242 | .show = brport_show, |
243 | .store = brport_store, | 243 | .store = brport_store, |
244 | }; | 244 | }; |
diff --git a/samples/kobject/kobject-example.c b/samples/kobject/kobject-example.c index 8d9b55a12023..86ea0c3ad975 100644 --- a/samples/kobject/kobject-example.c +++ b/samples/kobject/kobject-example.c | |||
@@ -44,7 +44,7 @@ static struct kobj_attribute foo_attribute = | |||
44 | __ATTR(foo, 0666, foo_show, foo_store); | 44 | __ATTR(foo, 0666, foo_show, foo_store); |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * More complex function where we determine which varible is being accessed by | 47 | * More complex function where we determine which variable is being accessed by |
48 | * looking at the attribute for the "baz" and "bar" files. | 48 | * looking at the attribute for the "baz" and "bar" files. |
49 | */ | 49 | */ |
50 | static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr, | 50 | static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr, |
@@ -79,7 +79,7 @@ static struct kobj_attribute bar_attribute = | |||
79 | 79 | ||
80 | 80 | ||
81 | /* | 81 | /* |
82 | * Create a group of attributes so that we can create and destory them all | 82 | * Create a group of attributes so that we can create and destroy them all |
83 | * at once. | 83 | * at once. |
84 | */ | 84 | */ |
85 | static struct attribute *attrs[] = { | 85 | static struct attribute *attrs[] = { |
diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c index 45b7d56fb541..3b126d1f8599 100644 --- a/samples/kobject/kset-example.c +++ b/samples/kobject/kset-example.c | |||
@@ -87,7 +87,7 @@ static ssize_t foo_attr_store(struct kobject *kobj, | |||
87 | } | 87 | } |
88 | 88 | ||
89 | /* Our custom sysfs_ops that we will associate with our ktype later on */ | 89 | /* Our custom sysfs_ops that we will associate with our ktype later on */ |
90 | static struct sysfs_ops foo_sysfs_ops = { | 90 | static const struct sysfs_ops foo_sysfs_ops = { |
91 | .show = foo_attr_show, | 91 | .show = foo_attr_show, |
92 | .store = foo_attr_store, | 92 | .store = foo_attr_store, |
93 | }; | 93 | }; |
@@ -127,7 +127,7 @@ static struct foo_attribute foo_attribute = | |||
127 | __ATTR(foo, 0666, foo_show, foo_store); | 127 | __ATTR(foo, 0666, foo_show, foo_store); |
128 | 128 | ||
129 | /* | 129 | /* |
130 | * More complex function where we determine which varible is being accessed by | 130 | * More complex function where we determine which variable is being accessed by |
131 | * looking at the attribute for the "baz" and "bar" files. | 131 | * looking at the attribute for the "baz" and "bar" files. |
132 | */ | 132 | */ |
133 | static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr, | 133 | static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr, |
@@ -161,7 +161,7 @@ static struct foo_attribute bar_attribute = | |||
161 | __ATTR(bar, 0666, b_show, b_store); | 161 | __ATTR(bar, 0666, b_show, b_store); |
162 | 162 | ||
163 | /* | 163 | /* |
164 | * Create a group of attributes so that we can create and destory them all | 164 | * Create a group of attributes so that we can create and destroy them all |
165 | * at once. | 165 | * at once. |
166 | */ | 166 | */ |
167 | static struct attribute *foo_default_attrs[] = { | 167 | static struct attribute *foo_default_attrs[] = { |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 208ad3b0ca51..c7865c362d28 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
@@ -2103,7 +2103,7 @@ sub process_file($) { | |||
2103 | $section = $newsection; | 2103 | $section = $newsection; |
2104 | } elsif (/$doc_end/) { | 2104 | } elsif (/$doc_end/) { |
2105 | 2105 | ||
2106 | if ($contents ne "") { | 2106 | if (($contents ne "") && ($contents ne "\n")) { |
2107 | dump_section($file, $section, xml_escape($contents)); | 2107 | dump_section($file, $section, xml_escape($contents)); |
2108 | $section = $section_default; | 2108 | $section = $section_default; |
2109 | $contents = ""; | 2109 | $contents = ""; |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 8f8b17ac074d..73943651caed 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -393,7 +393,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | |||
393 | event == SNDRV_TIMER_EVENT_CONTINUE) | 393 | event == SNDRV_TIMER_EVENT_CONTINUE) |
394 | resolution = snd_timer_resolution(ti); | 394 | resolution = snd_timer_resolution(ti); |
395 | if (ti->ccallback) | 395 | if (ti->ccallback) |
396 | ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); | 396 | ti->ccallback(ti, event, &tstamp, resolution); |
397 | if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) | 397 | if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) |
398 | return; | 398 | return; |
399 | timer = ti->timer; | 399 | timer = ti->timer; |
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index b865e45a8f9b..5913717c1be6 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -1558,7 +1558,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip, | |||
1558 | 1558 | ||
1559 | err = pnp_activate_dev(devmc); | 1559 | err = pnp_activate_dev(devmc); |
1560 | if (err < 0) { | 1560 | if (err < 0) { |
1561 | snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n", | 1561 | snd_printk(KERN_ERR "MC pnp configure failure: %d\n", |
1562 | err); | 1562 | err); |
1563 | return err; | 1563 | return err; |
1564 | } | 1564 | } |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index a4af53b5c1cf..becd90d7536d 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -144,12 +144,8 @@ struct snd_opti9xx { | |||
144 | 144 | ||
145 | spinlock_t lock; | 145 | spinlock_t lock; |
146 | 146 | ||
147 | long wss_base; | ||
147 | int irq; | 148 | int irq; |
148 | |||
149 | #ifdef CONFIG_PNP | ||
150 | struct pnp_dev *dev; | ||
151 | struct pnp_dev *devmpu; | ||
152 | #endif /* CONFIG_PNP */ | ||
153 | }; | 149 | }; |
154 | 150 | ||
155 | static int snd_opti9xx_pnp_is_probed; | 151 | static int snd_opti9xx_pnp_is_probed; |
@@ -159,12 +155,17 @@ static int snd_opti9xx_pnp_is_probed; | |||
159 | static struct pnp_card_device_id snd_opti9xx_pnpids[] = { | 155 | static struct pnp_card_device_id snd_opti9xx_pnpids[] = { |
160 | #ifndef OPTi93X | 156 | #ifndef OPTi93X |
161 | /* OPTi 82C924 */ | 157 | /* OPTi 82C924 */ |
162 | { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 }, | 158 | { .id = "OPT0924", |
159 | .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } }, | ||
160 | .driver_data = 0x0924 }, | ||
163 | /* OPTi 82C925 */ | 161 | /* OPTi 82C925 */ |
164 | { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 }, | 162 | { .id = "OPT0925", |
163 | .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } }, | ||
164 | .driver_data = 0x0925 }, | ||
165 | #else | 165 | #else |
166 | /* OPTi 82C931/3 */ | 166 | /* OPTi 82C931/3 */ |
167 | { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 }, | 167 | { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, |
168 | .driver_data = 0x0931 }, | ||
168 | #endif /* OPTi93X */ | 169 | #endif /* OPTi93X */ |
169 | { .id = "" } | 170 | { .id = "" } |
170 | }; | 171 | }; |
@@ -207,24 +208,34 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, | |||
207 | chip->hardware = hardware; | 208 | chip->hardware = hardware; |
208 | strcpy(chip->name, snd_opti9xx_names[hardware]); | 209 | strcpy(chip->name, snd_opti9xx_names[hardware]); |
209 | 210 | ||
210 | chip->mc_base_size = opti9xx_mc_size[hardware]; | ||
211 | |||
212 | spin_lock_init(&chip->lock); | 211 | spin_lock_init(&chip->lock); |
213 | 212 | ||
214 | chip->irq = -1; | 213 | chip->irq = -1; |
215 | 214 | ||
215 | #ifndef OPTi93X | ||
216 | #ifdef CONFIG_PNP | ||
217 | if (isapnp && chip->mc_base) | ||
218 | /* PnP resource gives the least 10 bits */ | ||
219 | chip->mc_base |= 0xc00; | ||
220 | #endif /* CONFIG_PNP */ | ||
221 | else { | ||
222 | chip->mc_base = 0xf8c; | ||
223 | chip->mc_base_size = opti9xx_mc_size[hardware]; | ||
224 | } | ||
225 | #else | ||
226 | chip->mc_base_size = opti9xx_mc_size[hardware]; | ||
227 | #endif | ||
228 | |||
216 | switch (hardware) { | 229 | switch (hardware) { |
217 | #ifndef OPTi93X | 230 | #ifndef OPTi93X |
218 | case OPTi9XX_HW_82C928: | 231 | case OPTi9XX_HW_82C928: |
219 | case OPTi9XX_HW_82C929: | 232 | case OPTi9XX_HW_82C929: |
220 | chip->mc_base = 0xf8c; | ||
221 | chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; | 233 | chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; |
222 | chip->pwd_reg = 3; | 234 | chip->pwd_reg = 3; |
223 | break; | 235 | break; |
224 | 236 | ||
225 | case OPTi9XX_HW_82C924: | 237 | case OPTi9XX_HW_82C924: |
226 | case OPTi9XX_HW_82C925: | 238 | case OPTi9XX_HW_82C925: |
227 | chip->mc_base = 0xf8c; | ||
228 | chip->password = 0xe5; | 239 | chip->password = 0xe5; |
229 | chip->pwd_reg = 3; | 240 | chip->pwd_reg = 3; |
230 | break; | 241 | break; |
@@ -292,7 +303,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, | |||
292 | spin_unlock_irqrestore(&chip->lock, flags); | 303 | spin_unlock_irqrestore(&chip->lock, flags); |
293 | return retval; | 304 | return retval; |
294 | } | 305 | } |
295 | 306 | ||
296 | static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, | 307 | static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, |
297 | unsigned char value) | 308 | unsigned char value) |
298 | { | 309 | { |
@@ -341,7 +352,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, | |||
341 | 352 | ||
342 | 353 | ||
343 | static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, | 354 | static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, |
344 | long wss_base, | 355 | long port, |
345 | int irq, int dma1, int dma2, | 356 | int irq, int dma1, int dma2, |
346 | long mpu_port, int mpu_irq) | 357 | long mpu_port, int mpu_irq) |
347 | { | 358 | { |
@@ -354,16 +365,23 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, | |||
354 | switch (chip->hardware) { | 365 | switch (chip->hardware) { |
355 | #ifndef OPTi93X | 366 | #ifndef OPTi93X |
356 | case OPTi9XX_HW_82C924: | 367 | case OPTi9XX_HW_82C924: |
368 | /* opti 929 mode (?), OPL3 clock output, audio enable */ | ||
357 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); | 369 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); |
370 | /* enable wave audio */ | ||
358 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); | 371 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); |
359 | 372 | ||
360 | case OPTi9XX_HW_82C925: | 373 | case OPTi9XX_HW_82C925: |
374 | /* enable WSS mode */ | ||
361 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); | 375 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); |
376 | /* OPL3 FM synthesis */ | ||
362 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); | 377 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); |
378 | /* disable Sound Blaster IRQ and DMA */ | ||
363 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); | 379 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); |
364 | #ifdef CS4231 | 380 | #ifdef CS4231 |
381 | /* cs4231/4248 fix enabled */ | ||
365 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); | 382 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); |
366 | #else | 383 | #else |
384 | /* cs4231/4248 fix disabled */ | ||
367 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); | 385 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); |
368 | #endif /* CS4231 */ | 386 | #endif /* CS4231 */ |
369 | break; | 387 | break; |
@@ -411,21 +429,26 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, | |||
411 | return -EINVAL; | 429 | return -EINVAL; |
412 | } | 430 | } |
413 | 431 | ||
414 | switch (wss_base) { | 432 | /* PnP resource says it decodes only 10 bits of address */ |
415 | case 0x530: | 433 | switch (port & 0x3ff) { |
434 | case 0x130: | ||
435 | chip->wss_base = 0x530; | ||
416 | wss_base_bits = 0x00; | 436 | wss_base_bits = 0x00; |
417 | break; | 437 | break; |
418 | case 0x604: | 438 | case 0x204: |
439 | chip->wss_base = 0x604; | ||
419 | wss_base_bits = 0x03; | 440 | wss_base_bits = 0x03; |
420 | break; | 441 | break; |
421 | case 0xe80: | 442 | case 0x280: |
443 | chip->wss_base = 0xe80; | ||
422 | wss_base_bits = 0x01; | 444 | wss_base_bits = 0x01; |
423 | break; | 445 | break; |
424 | case 0xf40: | 446 | case 0x340: |
447 | chip->wss_base = 0xf40; | ||
425 | wss_base_bits = 0x02; | 448 | wss_base_bits = 0x02; |
426 | break; | 449 | break; |
427 | default: | 450 | default: |
428 | snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base); | 451 | snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); |
429 | goto __skip_base; | 452 | goto __skip_base; |
430 | } | 453 | } |
431 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); | 454 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); |
@@ -487,7 +510,7 @@ __skip_base: | |||
487 | #endif /* CS4231 || OPTi93X */ | 510 | #endif /* CS4231 || OPTi93X */ |
488 | 511 | ||
489 | #ifndef OPTi93X | 512 | #ifndef OPTi93X |
490 | outb(irq_bits << 3 | dma_bits, wss_base); | 513 | outb(irq_bits << 3 | dma_bits, chip->wss_base); |
491 | #else /* OPTi93X */ | 514 | #else /* OPTi93X */ |
492 | snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); | 515 | snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); |
493 | #endif /* OPTi93X */ | 516 | #endif /* OPTi93X */ |
@@ -729,15 +752,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
729 | { | 752 | { |
730 | struct pnp_dev *pdev; | 753 | struct pnp_dev *pdev; |
731 | int err; | 754 | int err; |
755 | struct pnp_dev *devmpu; | ||
756 | #ifndef OPTi93X | ||
757 | struct pnp_dev *devmc; | ||
758 | #endif | ||
732 | 759 | ||
733 | chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL); | 760 | pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); |
734 | if (chip->dev == NULL) | 761 | if (pdev == NULL) |
735 | return -EBUSY; | 762 | return -EBUSY; |
736 | 763 | ||
737 | chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); | ||
738 | |||
739 | pdev = chip->dev; | ||
740 | |||
741 | err = pnp_activate_dev(pdev); | 764 | err = pnp_activate_dev(pdev); |
742 | if (err < 0) { | 765 | if (err < 0) { |
743 | snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); | 766 | snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); |
@@ -750,9 +773,24 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
750 | chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; | 773 | chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; |
751 | chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; | 774 | chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; |
752 | #else | 775 | #else |
753 | if (pid->driver_data != 0x0924) | 776 | devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); |
754 | port = pnp_port_start(pdev, 1); | 777 | if (devmc == NULL) |
778 | return -EBUSY; | ||
779 | |||
780 | err = pnp_activate_dev(devmc); | ||
781 | if (err < 0) { | ||
782 | snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); | ||
783 | return err; | ||
784 | } | ||
785 | |||
786 | port = pnp_port_start(pdev, 1); | ||
755 | fm_port = pnp_port_start(pdev, 2) + 8; | 787 | fm_port = pnp_port_start(pdev, 2) + 8; |
788 | /* | ||
789 | * The MC(0) is never accessed and card does not | ||
790 | * include it in the PnP resource range. OPTI93x include it. | ||
791 | */ | ||
792 | chip->mc_base = pnp_port_start(devmc, 0) - 1; | ||
793 | chip->mc_base_size = pnp_port_len(devmc, 0) + 1; | ||
756 | #endif /* OPTi93X */ | 794 | #endif /* OPTi93X */ |
757 | irq = pnp_irq(pdev, 0); | 795 | irq = pnp_irq(pdev, 0); |
758 | dma1 = pnp_dma(pdev, 0); | 796 | dma1 = pnp_dma(pdev, 0); |
@@ -760,16 +798,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
760 | dma2 = pnp_dma(pdev, 1); | 798 | dma2 = pnp_dma(pdev, 1); |
761 | #endif /* CS4231 || OPTi93X */ | 799 | #endif /* CS4231 || OPTi93X */ |
762 | 800 | ||
763 | pdev = chip->devmpu; | 801 | devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); |
764 | if (pdev && mpu_port > 0) { | 802 | |
765 | err = pnp_activate_dev(pdev); | 803 | if (devmpu && mpu_port > 0) { |
804 | err = pnp_activate_dev(devmpu); | ||
766 | if (err < 0) { | 805 | if (err < 0) { |
767 | snd_printk(KERN_ERR "AUDIO pnp configure failure\n"); | 806 | snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); |
768 | mpu_port = -1; | 807 | mpu_port = -1; |
769 | chip->devmpu = NULL; | ||
770 | } else { | 808 | } else { |
771 | mpu_port = pnp_port_start(pdev, 0); | 809 | mpu_port = pnp_port_start(devmpu, 0); |
772 | mpu_irq = pnp_irq(pdev, 0); | 810 | mpu_irq = pnp_irq(devmpu, 0); |
773 | } | 811 | } |
774 | } | 812 | } |
775 | return pid->driver_data; | 813 | return pid->driver_data; |
@@ -824,7 +862,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
824 | if (error) | 862 | if (error) |
825 | return error; | 863 | return error; |
826 | 864 | ||
827 | error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2, | 865 | error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2, |
828 | #ifdef OPTi93X | 866 | #ifdef OPTi93X |
829 | WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, | 867 | WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, |
830 | #else | 868 | #else |
@@ -865,10 +903,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
865 | sprintf(card->shortname, "OPTi %s", card->driver); | 903 | sprintf(card->shortname, "OPTi %s", card->driver); |
866 | #if defined(CS4231) || defined(OPTi93X) | 904 | #if defined(CS4231) || defined(OPTi93X) |
867 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", | 905 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", |
868 | card->shortname, pcm->name, port + 4, irq, dma1, xdma2); | 906 | card->shortname, pcm->name, |
907 | chip->wss_base + 4, irq, dma1, xdma2); | ||
869 | #else | 908 | #else |
870 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", | 909 | sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", |
871 | card->shortname, pcm->name, port + 4, irq, dma1); | 910 | card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); |
872 | #endif /* CS4231 || OPTi93X */ | 911 | #endif /* CS4231 || OPTi93X */ |
873 | 912 | ||
874 | if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) | 913 | if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) |
@@ -1062,9 +1101,6 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, | |||
1062 | snd_card_free(card); | 1101 | snd_card_free(card); |
1063 | return error; | 1102 | return error; |
1064 | } | 1103 | } |
1065 | if (hw <= OPTi9XX_HW_82C930) | ||
1066 | chip->mc_base -= 0x80; | ||
1067 | |||
1068 | error = snd_opti9xx_read_check(chip); | 1104 | error = snd_opti9xx_read_check(chip); |
1069 | if (error) { | 1105 | if (error) { |
1070 | snd_printk(KERN_ERR "OPTI chip not found\n"); | 1106 | snd_printk(KERN_ERR "OPTI chip not found\n"); |
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 8d21a3feda3a..8ccbcddf08e1 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/delay.h> | ||
17 | #include <asm/dma.h> | 18 | #include <asm/dma.h> |
18 | #include <linux/isa.h> | 19 | #include <linux/isa.h> |
19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
diff --git a/sound/oss/coproc.h b/sound/oss/coproc.h index 7306346e9ac4..7bec21bbdd88 100644 --- a/sound/oss/coproc.h +++ b/sound/oss/coproc.h | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | /* | 6 | /* |
7 | * Coprocessor access types | 7 | * Coprocessor access types |
8 | */ | 8 | */ |
9 | #define COPR_CUSTOM 0x0001 /* Custom applications */ | 9 | #define COPR_CUSTOM 0x0001 /* Custom applications */ |
10 | #define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */ | 10 | #define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */ |
diff --git a/sound/oss/v_midi.h b/sound/oss/v_midi.h index 1b86cb45c607..08e2185ee816 100644 --- a/sound/oss/v_midi.h +++ b/sound/oss/v_midi.h | |||
@@ -2,9 +2,9 @@ typedef struct vmidi_devc { | |||
2 | int dev; | 2 | int dev; |
3 | 3 | ||
4 | /* State variables */ | 4 | /* State variables */ |
5 | int opened; | 5 | int opened; |
6 | spinlock_t lock; | 6 | spinlock_t lock; |
7 | 7 | ||
8 | /* MIDI fields */ | 8 | /* MIDI fields */ |
9 | int my_mididev; | 9 | int my_mididev; |
10 | int pair_mididev; | 10 | int pair_mididev; |
@@ -12,4 +12,3 @@ typedef struct vmidi_devc { | |||
12 | int intr_active; | 12 | int intr_active; |
13 | void (*midi_input_intr) (int dev, unsigned char data); | 13 | void (*midi_input_intr) (int dev, unsigned char data); |
14 | } vmidi_devc; | 14 | } vmidi_devc; |
15 | |||
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 556cff937be7..567348b05b5a 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI | |||
157 | 157 | ||
158 | config SND_HDA_ELD | 158 | config SND_HDA_ELD |
159 | def_bool y | 159 | def_bool y |
160 | depends on SND_HDA_CODEC_INTELHDMI | 160 | depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI |
161 | 161 | ||
162 | config SND_HDA_CODEC_CIRRUS | 162 | config SND_HDA_CODEC_CIRRUS |
163 | bool "Build Cirrus Logic codec support" | 163 | bool "Build Cirrus Logic codec support" |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 315a1c4f8998..24bc195b02da 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o | |||
3 | snd-hda-codec-y := hda_codec.o | 3 | snd-hda-codec-y := hda_codec.o |
4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
6 | # snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o | 6 | snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o |
7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
9 | 9 | ||
@@ -18,7 +18,7 @@ snd-hda-codec-ca0110-objs := patch_ca0110.o | |||
18 | snd-hda-codec-conexant-objs := patch_conexant.o | 18 | snd-hda-codec-conexant-objs := patch_conexant.o |
19 | snd-hda-codec-via-objs := patch_via.o | 19 | snd-hda-codec-via-objs := patch_via.o |
20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o | 20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o |
21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o | 21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o |
22 | 22 | ||
23 | # common driver | 23 | # common driver |
24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o | 24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 76d3c4c049db..5bd7cf45f3a5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -978,8 +978,9 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
978 | * | 978 | * |
979 | * Returns 0 if successful, or a negative error code. | 979 | * Returns 0 if successful, or a negative error code. |
980 | */ | 980 | */ |
981 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | 981 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, |
982 | struct hda_codec **codecp) | 982 | unsigned int codec_addr, |
983 | struct hda_codec **codecp) | ||
983 | { | 984 | { |
984 | struct hda_codec *codec; | 985 | struct hda_codec *codec; |
985 | char component[31]; | 986 | char component[31]; |
@@ -1186,7 +1187,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | |||
1186 | */ | 1187 | */ |
1187 | 1188 | ||
1188 | /* FIXME: more better hash key? */ | 1189 | /* FIXME: more better hash key? */ |
1189 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | 1190 | #define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) |
1190 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) | 1191 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) |
1191 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) | 1192 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) |
1192 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) | 1193 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) |
@@ -1356,7 +1357,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) | |||
1356 | if (!codec->no_trigger_sense) { | 1357 | if (!codec->no_trigger_sense) { |
1357 | pincap = snd_hda_query_pin_caps(codec, nid); | 1358 | pincap = snd_hda_query_pin_caps(codec, nid); |
1358 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ | 1359 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ |
1359 | snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); | 1360 | snd_hda_codec_read(codec, nid, 0, |
1361 | AC_VERB_SET_PIN_SENSE, 0); | ||
1360 | } | 1362 | } |
1361 | return snd_hda_codec_read(codec, nid, 0, | 1363 | return snd_hda_codec_read(codec, nid, 0, |
1362 | AC_VERB_GET_PIN_SENSE, 0); | 1364 | AC_VERB_GET_PIN_SENSE, 0); |
@@ -1372,8 +1374,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense); | |||
1372 | */ | 1374 | */ |
1373 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) | 1375 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) |
1374 | { | 1376 | { |
1375 | u32 sense = snd_hda_pin_sense(codec, nid); | 1377 | u32 sense = snd_hda_pin_sense(codec, nid); |
1376 | return !!(sense & AC_PINSENSE_PRESENCE); | 1378 | return !!(sense & AC_PINSENSE_PRESENCE); |
1377 | } | 1379 | } |
1378 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); | 1380 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); |
1379 | 1381 | ||
@@ -1952,7 +1954,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1952 | err = snd_hda_ctl_add(codec, 0, kctl); | 1954 | err = snd_hda_ctl_add(codec, 0, kctl); |
1953 | if (err < 0) | 1955 | if (err < 0) |
1954 | return err; | 1956 | return err; |
1955 | 1957 | ||
1956 | for (s = slaves; *s; s++) { | 1958 | for (s = slaves; *s; s++) { |
1957 | struct snd_kcontrol *sctl; | 1959 | struct snd_kcontrol *sctl; |
1958 | int i = 0; | 1960 | int i = 0; |
@@ -2439,27 +2441,27 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
2439 | { | 2441 | { |
2440 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2442 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2441 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2443 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2442 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), | 2444 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), |
2443 | .info = snd_hda_spdif_mask_info, | 2445 | .info = snd_hda_spdif_mask_info, |
2444 | .get = snd_hda_spdif_cmask_get, | 2446 | .get = snd_hda_spdif_cmask_get, |
2445 | }, | 2447 | }, |
2446 | { | 2448 | { |
2447 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2449 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2448 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2450 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2449 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), | 2451 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), |
2450 | .info = snd_hda_spdif_mask_info, | 2452 | .info = snd_hda_spdif_mask_info, |
2451 | .get = snd_hda_spdif_pmask_get, | 2453 | .get = snd_hda_spdif_pmask_get, |
2452 | }, | 2454 | }, |
2453 | { | 2455 | { |
2454 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2456 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2455 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 2457 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), |
2456 | .info = snd_hda_spdif_mask_info, | 2458 | .info = snd_hda_spdif_mask_info, |
2457 | .get = snd_hda_spdif_default_get, | 2459 | .get = snd_hda_spdif_default_get, |
2458 | .put = snd_hda_spdif_default_put, | 2460 | .put = snd_hda_spdif_default_put, |
2459 | }, | 2461 | }, |
2460 | { | 2462 | { |
2461 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2463 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2462 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), | 2464 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), |
2463 | .info = snd_hda_spdif_out_switch_info, | 2465 | .info = snd_hda_spdif_out_switch_info, |
2464 | .get = snd_hda_spdif_out_switch_get, | 2466 | .get = snd_hda_spdif_out_switch_get, |
2465 | .put = snd_hda_spdif_out_switch_put, | 2467 | .put = snd_hda_spdif_out_switch_put, |
@@ -2610,7 +2612,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, | |||
2610 | static struct snd_kcontrol_new dig_in_ctls[] = { | 2612 | static struct snd_kcontrol_new dig_in_ctls[] = { |
2611 | { | 2613 | { |
2612 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2614 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2613 | .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), | 2615 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), |
2614 | .info = snd_hda_spdif_in_switch_info, | 2616 | .info = snd_hda_spdif_in_switch_info, |
2615 | .get = snd_hda_spdif_in_switch_get, | 2617 | .get = snd_hda_spdif_in_switch_get, |
2616 | .put = snd_hda_spdif_in_switch_put, | 2618 | .put = snd_hda_spdif_in_switch_put, |
@@ -2618,7 +2620,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { | |||
2618 | { | 2620 | { |
2619 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2621 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2620 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2622 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2621 | .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), | 2623 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), |
2622 | .info = snd_hda_spdif_mask_info, | 2624 | .info = snd_hda_spdif_mask_info, |
2623 | .get = snd_hda_spdif_in_status_get, | 2625 | .get = snd_hda_spdif_in_status_get, |
2624 | }, | 2626 | }, |
@@ -2883,7 +2885,7 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) | |||
2883 | int err = snd_hda_codec_build_controls(codec); | 2885 | int err = snd_hda_codec_build_controls(codec); |
2884 | if (err < 0) { | 2886 | if (err < 0) { |
2885 | printk(KERN_ERR "hda_codec: cannot build controls" | 2887 | printk(KERN_ERR "hda_codec: cannot build controls" |
2886 | "for #%d (error %d)\n", codec->addr, err); | 2888 | "for #%d (error %d)\n", codec->addr, err); |
2887 | err = snd_hda_codec_reset(codec); | 2889 | err = snd_hda_codec_reset(codec); |
2888 | if (err < 0) { | 2890 | if (err < 0) { |
2889 | printk(KERN_ERR | 2891 | printk(KERN_ERR |
@@ -2979,8 +2981,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
2979 | val |= channels - 1; | 2981 | val |= channels - 1; |
2980 | 2982 | ||
2981 | switch (snd_pcm_format_width(format)) { | 2983 | switch (snd_pcm_format_width(format)) { |
2982 | case 8: val |= 0x00; break; | 2984 | case 8: |
2983 | case 16: val |= 0x10; break; | 2985 | val |= 0x00; |
2986 | break; | ||
2987 | case 16: | ||
2988 | val |= 0x10; | ||
2989 | break; | ||
2984 | case 20: | 2990 | case 20: |
2985 | case 24: | 2991 | case 24: |
2986 | case 32: | 2992 | case 32: |
@@ -3298,7 +3304,8 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
3298 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) | 3304 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) |
3299 | return audio_idx[type][i]; | 3305 | return audio_idx[type][i]; |
3300 | 3306 | ||
3301 | snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]); | 3307 | snd_printk(KERN_WARNING "Too many %s devices\n", |
3308 | snd_hda_pcm_type_name[type]); | ||
3302 | return -EAGAIN; | 3309 | return -EAGAIN; |
3303 | } | 3310 | } |
3304 | 3311 | ||
@@ -3336,7 +3343,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
3336 | err = codec->patch_ops.build_pcms(codec); | 3343 | err = codec->patch_ops.build_pcms(codec); |
3337 | if (err < 0) { | 3344 | if (err < 0) { |
3338 | printk(KERN_ERR "hda_codec: cannot build PCMs" | 3345 | printk(KERN_ERR "hda_codec: cannot build PCMs" |
3339 | "for #%d (error %d)\n", codec->addr, err); | 3346 | "for #%d (error %d)\n", codec->addr, err); |
3340 | err = snd_hda_codec_reset(codec); | 3347 | err = snd_hda_codec_reset(codec); |
3341 | if (err < 0) { | 3348 | if (err < 0) { |
3342 | printk(KERN_ERR | 3349 | printk(KERN_ERR |
@@ -3466,8 +3473,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config); | |||
3466 | 3473 | ||
3467 | /** | 3474 | /** |
3468 | * snd_hda_check_board_codec_sid_config - compare the current codec | 3475 | * snd_hda_check_board_codec_sid_config - compare the current codec |
3469 | subsystem ID with the | 3476 | subsystem ID with the |
3470 | config table | 3477 | config table |
3471 | 3478 | ||
3472 | This is important for Gateway notebooks with SB450 HDA Audio | 3479 | This is important for Gateway notebooks with SB450 HDA Audio |
3473 | where the vendor ID of the PCI device is: | 3480 | where the vendor ID of the PCI device is: |
@@ -3607,7 +3614,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec) | |||
3607 | * | 3614 | * |
3608 | * Increment the power-up counter and power up the hardware really when | 3615 | * Increment the power-up counter and power up the hardware really when |
3609 | * not turned on yet. | 3616 | * not turned on yet. |
3610 | */ | 3617 | */ |
3611 | void snd_hda_power_up(struct hda_codec *codec) | 3618 | void snd_hda_power_up(struct hda_codec *codec) |
3612 | { | 3619 | { |
3613 | struct hda_bus *bus = codec->bus; | 3620 | struct hda_bus *bus = codec->bus; |
@@ -3636,7 +3643,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up); | |||
3636 | * | 3643 | * |
3637 | * Decrement the power-up counter and schedules the power-off work if | 3644 | * Decrement the power-up counter and schedules the power-off work if |
3638 | * the counter rearches to zero. | 3645 | * the counter rearches to zero. |
3639 | */ | 3646 | */ |
3640 | void snd_hda_power_down(struct hda_codec *codec) | 3647 | void snd_hda_power_down(struct hda_codec *codec) |
3641 | { | 3648 | { |
3642 | --codec->power_count; | 3649 | --codec->power_count; |
@@ -3662,7 +3669,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down); | |||
3662 | * | 3669 | * |
3663 | * This function is supposed to be set or called from the check_power_status | 3670 | * This function is supposed to be set or called from the check_power_status |
3664 | * patch ops. | 3671 | * patch ops. |
3665 | */ | 3672 | */ |
3666 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | 3673 | int snd_hda_check_amp_list_power(struct hda_codec *codec, |
3667 | struct hda_loopback_check *check, | 3674 | struct hda_loopback_check *check, |
3668 | hda_nid_t nid) | 3675 | hda_nid_t nid) |
@@ -3830,7 +3837,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, | |||
3830 | { | 3837 | { |
3831 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 3838 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
3832 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 3839 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) |
3833 | set_dig_out_convert(codec, nid, | 3840 | set_dig_out_convert(codec, nid, |
3834 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, | 3841 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, |
3835 | -1); | 3842 | -1); |
3836 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | 3843 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); |
@@ -4089,13 +4096,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
4089 | /* | 4096 | /* |
4090 | * Sort an associated group of pins according to their sequence numbers. | 4097 | * Sort an associated group of pins according to their sequence numbers. |
4091 | */ | 4098 | */ |
4092 | static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | 4099 | static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, |
4093 | int num_pins) | 4100 | int num_pins) |
4094 | { | 4101 | { |
4095 | int i, j; | 4102 | int i, j; |
4096 | short seq; | 4103 | short seq; |
4097 | hda_nid_t nid; | 4104 | hda_nid_t nid; |
4098 | 4105 | ||
4099 | for (i = 0; i < num_pins; i++) { | 4106 | for (i = 0; i < num_pins; i++) { |
4100 | for (j = i + 1; j < num_pins; j++) { | 4107 | for (j = i + 1; j < num_pins; j++) { |
4101 | if (sequences[i] > sequences[j]) { | 4108 | if (sequences[i] > sequences[j]) { |
@@ -4123,7 +4130,7 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | |||
4123 | * is detected, one of speaker of HP pins is assigned as the primary | 4130 | * is detected, one of speaker of HP pins is assigned as the primary |
4124 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 4131 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
4125 | * if any analog output exists. | 4132 | * if any analog output exists. |
4126 | * | 4133 | * |
4127 | * The analog input pins are assigned to input_pins array. | 4134 | * The analog input pins are assigned to input_pins array. |
4128 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 4135 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
4129 | * respectively. | 4136 | * respectively. |
@@ -4186,9 +4193,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4186 | case AC_JACK_SPEAKER: | 4193 | case AC_JACK_SPEAKER: |
4187 | seq = get_defcfg_sequence(def_conf); | 4194 | seq = get_defcfg_sequence(def_conf); |
4188 | assoc = get_defcfg_association(def_conf); | 4195 | assoc = get_defcfg_association(def_conf); |
4189 | if (! assoc) | 4196 | if (!assoc) |
4190 | continue; | 4197 | continue; |
4191 | if (! assoc_speaker) | 4198 | if (!assoc_speaker) |
4192 | assoc_speaker = assoc; | 4199 | assoc_speaker = assoc; |
4193 | else if (assoc_speaker != assoc) | 4200 | else if (assoc_speaker != assoc) |
4194 | continue; | 4201 | continue; |
@@ -4286,7 +4293,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4286 | cfg->speaker_outs); | 4293 | cfg->speaker_outs); |
4287 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | 4294 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, |
4288 | cfg->hp_outs); | 4295 | cfg->hp_outs); |
4289 | 4296 | ||
4290 | /* if we have only one mic, make it AUTO_PIN_MIC */ | 4297 | /* if we have only one mic, make it AUTO_PIN_MIC */ |
4291 | if (!cfg->input_pins[AUTO_PIN_MIC] && | 4298 | if (!cfg->input_pins[AUTO_PIN_MIC] && |
4292 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { | 4299 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { |
@@ -4436,7 +4443,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); | |||
4436 | /** | 4443 | /** |
4437 | * snd_array_new - get a new element from the given array | 4444 | * snd_array_new - get a new element from the given array |
4438 | * @array: the array object | 4445 | * @array: the array object |
4439 | * | 4446 | * |
4440 | * Get a new element from the given array. If it exceeds the | 4447 | * Get a new element from the given array. If it exceeds the |
4441 | * pre-allocated array size, re-allocate the array. | 4448 | * pre-allocated array size, re-allocate the array. |
4442 | * | 4449 | * |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 4228f2fe5956..dcd22446cfc7 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -331,6 +331,7 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) | |||
331 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | 331 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, |
332 | AC_DIPSIZE_ELD_BUF); | 332 | AC_DIPSIZE_ELD_BUF); |
333 | } | 333 | } |
334 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); | ||
334 | 335 | ||
335 | int snd_hdmi_get_eld(struct hdmi_eld *eld, | 336 | int snd_hdmi_get_eld(struct hdmi_eld *eld, |
336 | struct hda_codec *codec, hda_nid_t nid) | 337 | struct hda_codec *codec, hda_nid_t nid) |
@@ -366,6 +367,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, | |||
366 | kfree(buf); | 367 | kfree(buf); |
367 | return ret; | 368 | return ret; |
368 | } | 369 | } |
370 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); | ||
369 | 371 | ||
370 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 372 | static void hdmi_show_short_audio_desc(struct cea_sad *a) |
371 | { | 373 | { |
@@ -404,6 +406,7 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
404 | } | 406 | } |
405 | buf[j] = '\0'; /* necessary when j == 0 */ | 407 | buf[j] = '\0'; /* necessary when j == 0 */ |
406 | } | 408 | } |
409 | EXPORT_SYMBOL_HDA(snd_print_channel_allocation); | ||
407 | 410 | ||
408 | void snd_hdmi_show_eld(struct hdmi_eld *e) | 411 | void snd_hdmi_show_eld(struct hdmi_eld *e) |
409 | { | 412 | { |
@@ -422,6 +425,7 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) | |||
422 | for (i = 0; i < e->sad_count; i++) | 425 | for (i = 0; i < e->sad_count; i++) |
423 | hdmi_show_short_audio_desc(e->sad + i); | 426 | hdmi_show_short_audio_desc(e->sad + i); |
424 | } | 427 | } |
428 | EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); | ||
425 | 429 | ||
426 | #ifdef CONFIG_PROC_FS | 430 | #ifdef CONFIG_PROC_FS |
427 | 431 | ||
@@ -580,6 +584,7 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, | |||
580 | 584 | ||
581 | return 0; | 585 | return 0; |
582 | } | 586 | } |
587 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); | ||
583 | 588 | ||
584 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | 589 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) |
585 | { | 590 | { |
@@ -588,5 +593,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | |||
588 | eld->proc_entry = NULL; | 593 | eld->proc_entry = NULL; |
589 | } | 594 | } |
590 | } | 595 | } |
596 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); | ||
591 | 597 | ||
592 | #endif /* CONFIG_PROC_FS */ | 598 | #endif /* CONFIG_PROC_FS */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d5c93ad852ee..43b7cfb7cffd 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
267 | #define RIRB_INT_MASK 0x05 | 267 | #define RIRB_INT_MASK 0x05 |
268 | 268 | ||
269 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ | 269 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ |
270 | #define AZX_MAX_CODECS 4 | 270 | #define AZX_MAX_CODECS 8 |
271 | #define AZX_DEFAULT_CODECS 4 | ||
271 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) | 272 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) |
272 | 273 | ||
273 | /* SD_CTL bits */ | 274 | /* SD_CTL bits */ |
@@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1367 | 1368 | ||
1368 | /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ | 1369 | /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ |
1369 | static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | 1370 | static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { |
1371 | [AZX_DRIVER_NVIDIA] = 8, | ||
1370 | [AZX_DRIVER_TERA] = 1, | 1372 | [AZX_DRIVER_TERA] = 1, |
1371 | }; | 1373 | }; |
1372 | 1374 | ||
@@ -1399,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1399 | codecs = 0; | 1401 | codecs = 0; |
1400 | max_slots = azx_max_codecs[chip->driver_type]; | 1402 | max_slots = azx_max_codecs[chip->driver_type]; |
1401 | if (!max_slots) | 1403 | if (!max_slots) |
1402 | max_slots = AZX_MAX_CODECS; | 1404 | max_slots = AZX_DEFAULT_CODECS; |
1403 | 1405 | ||
1404 | /* First try to probe all given codec slots */ | 1406 | /* First try to probe all given codec slots */ |
1405 | for (c = 0; c < max_slots; c++) { | 1407 | for (c = 0; c < max_slots; c++) { |
@@ -2263,10 +2265,12 @@ static int azx_dev_free(struct snd_device *device) | |||
2263 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { | 2265 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { |
2264 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), | 2266 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), |
2265 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), | 2267 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), |
2268 | SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), | ||
2266 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), | 2269 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), |
2267 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), | 2270 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), |
2268 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), | 2271 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), |
2269 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), | 2272 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), |
2273 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), | ||
2270 | {} | 2274 | {} |
2271 | }; | 2275 | }; |
2272 | 2276 | ||
@@ -2354,6 +2358,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) | |||
2354 | static struct snd_pci_quirk msi_black_list[] __devinitdata = { | 2358 | static struct snd_pci_quirk msi_black_list[] __devinitdata = { |
2355 | SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ | 2359 | SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ |
2356 | SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ | 2360 | SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ |
2361 | SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ | ||
2357 | {} | 2362 | {} |
2358 | }; | 2363 | }; |
2359 | 2364 | ||
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c new file mode 100644 index 000000000000..2c2bafbf0258 --- /dev/null +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -0,0 +1,849 @@ | |||
1 | /* | ||
2 | * | ||
3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs | ||
4 | * | ||
5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * Authors: | ||
8 | * Wu Fengguang <wfg@linux.intel.com> | ||
9 | * | ||
10 | * Maintained by: | ||
11 | * Wu Fengguang <wfg@linux.intel.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the Free | ||
15 | * Software Foundation; either version 2 of the License, or (at your option) | ||
16 | * any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, but | ||
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
20 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
21 | * for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software Foundation, | ||
25 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
26 | */ | ||
27 | |||
28 | |||
29 | struct hdmi_spec { | ||
30 | int num_cvts; | ||
31 | int num_pins; | ||
32 | hda_nid_t cvt[MAX_HDMI_CVTS+1]; /* audio sources */ | ||
33 | hda_nid_t pin[MAX_HDMI_PINS+1]; /* audio sinks */ | ||
34 | |||
35 | /* | ||
36 | * source connection for each pin | ||
37 | */ | ||
38 | hda_nid_t pin_cvt[MAX_HDMI_PINS+1]; | ||
39 | |||
40 | /* | ||
41 | * HDMI sink attached to each pin | ||
42 | */ | ||
43 | struct hdmi_eld sink_eld[MAX_HDMI_PINS]; | ||
44 | |||
45 | /* | ||
46 | * export one pcm per pipe | ||
47 | */ | ||
48 | struct hda_pcm pcm_rec[MAX_HDMI_CVTS]; | ||
49 | |||
50 | /* | ||
51 | * nvhdmi specific | ||
52 | */ | ||
53 | struct hda_multi_out multiout; | ||
54 | unsigned int codec_type; | ||
55 | }; | ||
56 | |||
57 | |||
58 | struct hdmi_audio_infoframe { | ||
59 | u8 type; /* 0x84 */ | ||
60 | u8 ver; /* 0x01 */ | ||
61 | u8 len; /* 0x0a */ | ||
62 | |||
63 | u8 checksum; /* PB0 */ | ||
64 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | ||
65 | u8 SS01_SF24; | ||
66 | u8 CXT04; | ||
67 | u8 CA; | ||
68 | u8 LFEPBL01_LSV36_DM_INH7; | ||
69 | u8 reserved[5]; /* PB6 - PB10 */ | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * CEA speaker placement: | ||
74 | * | ||
75 | * FLH FCH FRH | ||
76 | * FLW FL FLC FC FRC FR FRW | ||
77 | * | ||
78 | * LFE | ||
79 | * TC | ||
80 | * | ||
81 | * RL RLC RC RRC RR | ||
82 | * | ||
83 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | ||
84 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | ||
85 | */ | ||
86 | enum cea_speaker_placement { | ||
87 | FL = (1 << 0), /* Front Left */ | ||
88 | FC = (1 << 1), /* Front Center */ | ||
89 | FR = (1 << 2), /* Front Right */ | ||
90 | FLC = (1 << 3), /* Front Left Center */ | ||
91 | FRC = (1 << 4), /* Front Right Center */ | ||
92 | RL = (1 << 5), /* Rear Left */ | ||
93 | RC = (1 << 6), /* Rear Center */ | ||
94 | RR = (1 << 7), /* Rear Right */ | ||
95 | RLC = (1 << 8), /* Rear Left Center */ | ||
96 | RRC = (1 << 9), /* Rear Right Center */ | ||
97 | LFE = (1 << 10), /* Low Frequency Effect */ | ||
98 | FLW = (1 << 11), /* Front Left Wide */ | ||
99 | FRW = (1 << 12), /* Front Right Wide */ | ||
100 | FLH = (1 << 13), /* Front Left High */ | ||
101 | FCH = (1 << 14), /* Front Center High */ | ||
102 | FRH = (1 << 15), /* Front Right High */ | ||
103 | TC = (1 << 16), /* Top Center */ | ||
104 | }; | ||
105 | |||
106 | /* | ||
107 | * ELD SA bits in the CEA Speaker Allocation data block | ||
108 | */ | ||
109 | static int eld_speaker_allocation_bits[] = { | ||
110 | [0] = FL | FR, | ||
111 | [1] = LFE, | ||
112 | [2] = FC, | ||
113 | [3] = RL | RR, | ||
114 | [4] = RC, | ||
115 | [5] = FLC | FRC, | ||
116 | [6] = RLC | RRC, | ||
117 | /* the following are not defined in ELD yet */ | ||
118 | [7] = FLW | FRW, | ||
119 | [8] = FLH | FRH, | ||
120 | [9] = TC, | ||
121 | [10] = FCH, | ||
122 | }; | ||
123 | |||
124 | struct cea_channel_speaker_allocation { | ||
125 | int ca_index; | ||
126 | int speakers[8]; | ||
127 | |||
128 | /* derived values, just for convenience */ | ||
129 | int channels; | ||
130 | int spk_mask; | ||
131 | }; | ||
132 | |||
133 | /* | ||
134 | * ALSA sequence is: | ||
135 | * | ||
136 | * surround40 surround41 surround50 surround51 surround71 | ||
137 | * ch0 front left = = = = | ||
138 | * ch1 front right = = = = | ||
139 | * ch2 rear left = = = = | ||
140 | * ch3 rear right = = = = | ||
141 | * ch4 LFE center center center | ||
142 | * ch5 LFE LFE | ||
143 | * ch6 side left | ||
144 | * ch7 side right | ||
145 | * | ||
146 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | ||
147 | */ | ||
148 | static int hdmi_channel_mapping[0x32][8] = { | ||
149 | /* stereo */ | ||
150 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
151 | /* 2.1 */ | ||
152 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
153 | /* Dolby Surround */ | ||
154 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
155 | /* surround40 */ | ||
156 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | ||
157 | /* 4ch */ | ||
158 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | ||
159 | /* surround41 */ | ||
160 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
161 | /* surround50 */ | ||
162 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
163 | /* surround51 */ | ||
164 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | ||
165 | /* 7.1 */ | ||
166 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | ||
167 | }; | ||
168 | |||
169 | /* | ||
170 | * This is an ordered list! | ||
171 | * | ||
172 | * The preceding ones have better chances to be selected by | ||
173 | * hdmi_setup_channel_allocation(). | ||
174 | */ | ||
175 | static struct cea_channel_speaker_allocation channel_allocations[] = { | ||
176 | /* channel: 7 6 5 4 3 2 1 0 */ | ||
177 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | ||
178 | /* 2.1 */ | ||
179 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | ||
180 | /* Dolby Surround */ | ||
181 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | ||
182 | /* surround40 */ | ||
183 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
184 | /* surround41 */ | ||
185 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
186 | /* surround50 */ | ||
187 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
188 | /* surround51 */ | ||
189 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
190 | /* 6.1 */ | ||
191 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
192 | /* surround71 */ | ||
193 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
194 | |||
195 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | ||
196 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | ||
197 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | ||
198 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | ||
199 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | ||
200 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | ||
201 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | ||
202 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | ||
203 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | ||
204 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | ||
205 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | ||
206 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | ||
207 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | ||
208 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | ||
209 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | ||
210 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | ||
211 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | ||
212 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | ||
213 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | ||
214 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | ||
215 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | ||
216 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | ||
217 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | ||
218 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | ||
219 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
220 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | ||
221 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | ||
222 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | ||
223 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | ||
224 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | ||
225 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | ||
226 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | ||
227 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | ||
228 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | ||
229 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | ||
230 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | ||
231 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
232 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | ||
233 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | ||
234 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | ||
235 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | ||
236 | }; | ||
237 | |||
238 | |||
239 | /* | ||
240 | * HDMI routines | ||
241 | */ | ||
242 | |||
243 | static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) | ||
244 | { | ||
245 | int i; | ||
246 | |||
247 | for (i = 0; nids[i]; i++) | ||
248 | if (nids[i] == nid) | ||
249 | return i; | ||
250 | |||
251 | snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, | ||
256 | struct hdmi_eld *eld) | ||
257 | { | ||
258 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | ||
259 | snd_hdmi_show_eld(eld); | ||
260 | } | ||
261 | |||
262 | #ifdef BE_PARANOID | ||
263 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
264 | int *packet_index, int *byte_index) | ||
265 | { | ||
266 | int val; | ||
267 | |||
268 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
269 | AC_VERB_GET_HDMI_DIP_INDEX, 0); | ||
270 | |||
271 | *packet_index = val >> 5; | ||
272 | *byte_index = val & 0x1f; | ||
273 | } | ||
274 | #endif | ||
275 | |||
276 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
277 | int packet_index, int byte_index) | ||
278 | { | ||
279 | int val; | ||
280 | |||
281 | val = (packet_index << 5) | (byte_index & 0x1f); | ||
282 | |||
283 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | ||
284 | } | ||
285 | |||
286 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, | ||
287 | unsigned char val) | ||
288 | { | ||
289 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | ||
290 | } | ||
291 | |||
292 | static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) | ||
293 | { | ||
294 | /* Unmute */ | ||
295 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) | ||
296 | snd_hda_codec_write(codec, pin_nid, 0, | ||
297 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
298 | /* Enable pin out */ | ||
299 | snd_hda_codec_write(codec, pin_nid, 0, | ||
300 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
301 | } | ||
302 | |||
303 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) | ||
304 | { | ||
305 | return 1 + snd_hda_codec_read(codec, nid, 0, | ||
306 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | ||
307 | } | ||
308 | |||
309 | static void hdmi_set_channel_count(struct hda_codec *codec, | ||
310 | hda_nid_t nid, int chs) | ||
311 | { | ||
312 | if (chs != hdmi_get_channel_count(codec, nid)) | ||
313 | snd_hda_codec_write(codec, nid, 0, | ||
314 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | ||
315 | } | ||
316 | |||
317 | |||
318 | /* | ||
319 | * Channel mapping routines | ||
320 | */ | ||
321 | |||
322 | /* | ||
323 | * Compute derived values in channel_allocations[]. | ||
324 | */ | ||
325 | static void init_channel_allocations(void) | ||
326 | { | ||
327 | int i, j; | ||
328 | struct cea_channel_speaker_allocation *p; | ||
329 | |||
330 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
331 | p = channel_allocations + i; | ||
332 | p->channels = 0; | ||
333 | p->spk_mask = 0; | ||
334 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | ||
335 | if (p->speakers[j]) { | ||
336 | p->channels++; | ||
337 | p->spk_mask |= p->speakers[j]; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * The transformation takes two steps: | ||
344 | * | ||
345 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | ||
346 | * spk_mask => (channel_allocations[]) => ai->CA | ||
347 | * | ||
348 | * TODO: it could select the wrong CA from multiple candidates. | ||
349 | */ | ||
350 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | ||
351 | struct hdmi_audio_infoframe *ai) | ||
352 | { | ||
353 | struct hdmi_spec *spec = codec->spec; | ||
354 | struct hdmi_eld *eld; | ||
355 | int i; | ||
356 | int spk_mask = 0; | ||
357 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
358 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
359 | |||
360 | /* | ||
361 | * CA defaults to 0 for basic stereo audio | ||
362 | */ | ||
363 | if (channels <= 2) | ||
364 | return 0; | ||
365 | |||
366 | i = hda_node_index(spec->pin_cvt, nid); | ||
367 | if (i < 0) | ||
368 | return 0; | ||
369 | eld = &spec->sink_eld[i]; | ||
370 | |||
371 | /* | ||
372 | * HDMI sink's ELD info cannot always be retrieved for now, e.g. | ||
373 | * in console or for audio devices. Assume the highest speakers | ||
374 | * configuration, to _not_ prohibit multi-channel audio playback. | ||
375 | */ | ||
376 | if (!eld->spk_alloc) | ||
377 | eld->spk_alloc = 0xffff; | ||
378 | |||
379 | /* | ||
380 | * expand ELD's speaker allocation mask | ||
381 | * | ||
382 | * ELD tells the speaker mask in a compact(paired) form, | ||
383 | * expand ELD's notions to match the ones used by Audio InfoFrame. | ||
384 | */ | ||
385 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | ||
386 | if (eld->spk_alloc & (1 << i)) | ||
387 | spk_mask |= eld_speaker_allocation_bits[i]; | ||
388 | } | ||
389 | |||
390 | /* search for the first working match in the CA table */ | ||
391 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
392 | if (channels == channel_allocations[i].channels && | ||
393 | (spk_mask & channel_allocations[i].spk_mask) == | ||
394 | channel_allocations[i].spk_mask) { | ||
395 | ai->CA = channel_allocations[i].ca_index; | ||
396 | break; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | ||
401 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | ||
402 | ai->CA, channels, buf); | ||
403 | |||
404 | return ai->CA; | ||
405 | } | ||
406 | |||
407 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | ||
408 | hda_nid_t pin_nid) | ||
409 | { | ||
410 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
411 | int i; | ||
412 | int slot; | ||
413 | |||
414 | for (i = 0; i < 8; i++) { | ||
415 | slot = snd_hda_codec_read(codec, pin_nid, 0, | ||
416 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | ||
417 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | ||
418 | slot >> 4, slot & 0xf); | ||
419 | } | ||
420 | #endif | ||
421 | } | ||
422 | |||
423 | |||
424 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
425 | hda_nid_t pin_nid, | ||
426 | struct hdmi_audio_infoframe *ai) | ||
427 | { | ||
428 | int i; | ||
429 | int ca = ai->CA; | ||
430 | int err; | ||
431 | |||
432 | if (hdmi_channel_mapping[ca][1] == 0) { | ||
433 | for (i = 0; i < channel_allocations[ca].channels; i++) | ||
434 | hdmi_channel_mapping[ca][i] = i | (i << 4); | ||
435 | for (; i < 8; i++) | ||
436 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); | ||
437 | } | ||
438 | |||
439 | for (i = 0; i < 8; i++) { | ||
440 | err = snd_hda_codec_write(codec, pin_nid, 0, | ||
441 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
442 | hdmi_channel_mapping[ca][i]); | ||
443 | if (err) { | ||
444 | snd_printdd(KERN_NOTICE | ||
445 | "HDMI: channel mapping failed\n"); | ||
446 | break; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | hdmi_debug_channel_mapping(codec, pin_nid); | ||
451 | } | ||
452 | |||
453 | |||
454 | /* | ||
455 | * Audio InfoFrame routines | ||
456 | */ | ||
457 | |||
458 | /* | ||
459 | * Enable Audio InfoFrame Transmission | ||
460 | */ | ||
461 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, | ||
462 | hda_nid_t pin_nid) | ||
463 | { | ||
464 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
465 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
466 | AC_DIPXMIT_BEST); | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * Disable Audio InfoFrame Transmission | ||
471 | */ | ||
472 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, | ||
473 | hda_nid_t pin_nid) | ||
474 | { | ||
475 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
476 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
477 | AC_DIPXMIT_DISABLE); | ||
478 | } | ||
479 | |||
480 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) | ||
481 | { | ||
482 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
483 | int i; | ||
484 | int size; | ||
485 | |||
486 | size = snd_hdmi_get_eld_size(codec, pin_nid); | ||
487 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); | ||
488 | |||
489 | for (i = 0; i < 8; i++) { | ||
490 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
491 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
492 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); | ||
493 | } | ||
494 | #endif | ||
495 | } | ||
496 | |||
497 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | ||
498 | { | ||
499 | #ifdef BE_PARANOID | ||
500 | int i, j; | ||
501 | int size; | ||
502 | int pi, bi; | ||
503 | for (i = 0; i < 8; i++) { | ||
504 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
505 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
506 | if (size == 0) | ||
507 | continue; | ||
508 | |||
509 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); | ||
510 | for (j = 1; j < 1000; j++) { | ||
511 | hdmi_write_dip_byte(codec, pin_nid, 0x0); | ||
512 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); | ||
513 | if (pi != i) | ||
514 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | ||
515 | bi, pi, i); | ||
516 | if (bi == 0) /* byte index wrapped around */ | ||
517 | break; | ||
518 | } | ||
519 | snd_printd(KERN_INFO | ||
520 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | ||
521 | i, size, j); | ||
522 | } | ||
523 | #endif | ||
524 | } | ||
525 | |||
526 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | ||
527 | { | ||
528 | u8 *bytes = (u8 *)ai; | ||
529 | u8 sum = 0; | ||
530 | int i; | ||
531 | |||
532 | ai->checksum = 0; | ||
533 | |||
534 | for (i = 0; i < sizeof(*ai); i++) | ||
535 | sum += bytes[i]; | ||
536 | |||
537 | ai->checksum = -sum; | ||
538 | } | ||
539 | |||
540 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | ||
541 | hda_nid_t pin_nid, | ||
542 | struct hdmi_audio_infoframe *ai) | ||
543 | { | ||
544 | u8 *bytes = (u8 *)ai; | ||
545 | int i; | ||
546 | |||
547 | hdmi_debug_dip_size(codec, pin_nid); | ||
548 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | ||
549 | |||
550 | hdmi_checksum_audio_infoframe(ai); | ||
551 | |||
552 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
553 | for (i = 0; i < sizeof(*ai); i++) | ||
554 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | ||
555 | } | ||
556 | |||
557 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | ||
558 | struct hdmi_audio_infoframe *ai) | ||
559 | { | ||
560 | u8 *bytes = (u8 *)ai; | ||
561 | u8 val; | ||
562 | int i; | ||
563 | |||
564 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) | ||
565 | != AC_DIPXMIT_BEST) | ||
566 | return false; | ||
567 | |||
568 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
569 | for (i = 0; i < sizeof(*ai); i++) { | ||
570 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
571 | AC_VERB_GET_HDMI_DIP_DATA, 0); | ||
572 | if (val != bytes[i]) | ||
573 | return false; | ||
574 | } | ||
575 | |||
576 | return true; | ||
577 | } | ||
578 | |||
579 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | ||
580 | struct snd_pcm_substream *substream) | ||
581 | { | ||
582 | struct hdmi_spec *spec = codec->spec; | ||
583 | hda_nid_t pin_nid; | ||
584 | int i; | ||
585 | struct hdmi_audio_infoframe ai = { | ||
586 | .type = 0x84, | ||
587 | .ver = 0x01, | ||
588 | .len = 0x0a, | ||
589 | .CC02_CT47 = substream->runtime->channels - 1, | ||
590 | }; | ||
591 | |||
592 | hdmi_setup_channel_allocation(codec, nid, &ai); | ||
593 | |||
594 | for (i = 0; i < spec->num_pins; i++) { | ||
595 | if (spec->pin_cvt[i] != nid) | ||
596 | continue; | ||
597 | if (!spec->sink_eld[i].monitor_present) | ||
598 | continue; | ||
599 | |||
600 | pin_nid = spec->pin[i]; | ||
601 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | ||
602 | snd_printdd("hdmi_setup_audio_infoframe: " | ||
603 | "cvt=%d pin=%d channels=%d\n", | ||
604 | nid, pin_nid, | ||
605 | substream->runtime->channels); | ||
606 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | ||
607 | hdmi_stop_infoframe_trans(codec, pin_nid); | ||
608 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | ||
609 | hdmi_start_infoframe_trans(codec, pin_nid); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | |||
615 | /* | ||
616 | * Unsolicited events | ||
617 | */ | ||
618 | |||
619 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
620 | { | ||
621 | struct hdmi_spec *spec = codec->spec; | ||
622 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
623 | int pind = !!(res & AC_UNSOL_RES_PD); | ||
624 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | ||
625 | int index; | ||
626 | |||
627 | printk(KERN_INFO | ||
628 | "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | ||
629 | tag, pind, eldv); | ||
630 | |||
631 | index = hda_node_index(spec->pin, tag); | ||
632 | if (index < 0) | ||
633 | return; | ||
634 | |||
635 | spec->sink_eld[index].monitor_present = pind; | ||
636 | spec->sink_eld[index].eld_valid = eldv; | ||
637 | |||
638 | if (pind && eldv) { | ||
639 | hdmi_get_show_eld(codec, spec->pin[index], | ||
640 | &spec->sink_eld[index]); | ||
641 | /* TODO: do real things about ELD */ | ||
642 | } | ||
643 | } | ||
644 | |||
645 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
646 | { | ||
647 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
648 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
649 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | ||
650 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | ||
651 | |||
652 | printk(KERN_INFO | ||
653 | "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | ||
654 | tag, | ||
655 | subtag, | ||
656 | cp_state, | ||
657 | cp_ready); | ||
658 | |||
659 | /* TODO */ | ||
660 | if (cp_state) | ||
661 | ; | ||
662 | if (cp_ready) | ||
663 | ; | ||
664 | } | ||
665 | |||
666 | |||
667 | static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | ||
668 | { | ||
669 | struct hdmi_spec *spec = codec->spec; | ||
670 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
671 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
672 | |||
673 | if (hda_node_index(spec->pin, tag) < 0) { | ||
674 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); | ||
675 | return; | ||
676 | } | ||
677 | |||
678 | if (subtag == 0) | ||
679 | hdmi_intrinsic_event(codec, res); | ||
680 | else | ||
681 | hdmi_non_intrinsic_event(codec, res); | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * Callbacks | ||
686 | */ | ||
687 | |||
688 | static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
689 | u32 stream_tag, int format) | ||
690 | { | ||
691 | int tag; | ||
692 | int fmt; | ||
693 | |||
694 | tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; | ||
695 | fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); | ||
696 | |||
697 | snd_printdd("hdmi_setup_stream: " | ||
698 | "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", | ||
699 | nid, | ||
700 | tag == stream_tag ? "" : "new-", | ||
701 | stream_tag, | ||
702 | fmt == format ? "" : "new-", | ||
703 | format); | ||
704 | |||
705 | if (tag != stream_tag) | ||
706 | snd_hda_codec_write(codec, nid, 0, | ||
707 | AC_VERB_SET_CHANNEL_STREAMID, | ||
708 | stream_tag << 4); | ||
709 | if (fmt != format) | ||
710 | snd_hda_codec_write(codec, nid, 0, | ||
711 | AC_VERB_SET_STREAM_FORMAT, format); | ||
712 | } | ||
713 | |||
714 | /* | ||
715 | * HDA/HDMI auto parsing | ||
716 | */ | ||
717 | |||
718 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | ||
719 | { | ||
720 | struct hdmi_spec *spec = codec->spec; | ||
721 | hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; | ||
722 | int conn_len, curr; | ||
723 | int index; | ||
724 | |||
725 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | ||
726 | snd_printk(KERN_WARNING | ||
727 | "HDMI: pin %d wcaps %#x " | ||
728 | "does not support connection list\n", | ||
729 | pin_nid, get_wcaps(codec, pin_nid)); | ||
730 | return -EINVAL; | ||
731 | } | ||
732 | |||
733 | conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, | ||
734 | HDA_MAX_CONNECTIONS); | ||
735 | if (conn_len > 1) | ||
736 | curr = snd_hda_codec_read(codec, pin_nid, 0, | ||
737 | AC_VERB_GET_CONNECT_SEL, 0); | ||
738 | else | ||
739 | curr = 0; | ||
740 | |||
741 | index = hda_node_index(spec->pin, pin_nid); | ||
742 | if (index < 0) | ||
743 | return -EINVAL; | ||
744 | |||
745 | spec->pin_cvt[index] = conn_list[curr]; | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | ||
751 | struct hdmi_eld *eld) | ||
752 | { | ||
753 | int present = snd_hda_pin_sense(codec, pin_nid); | ||
754 | |||
755 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | ||
756 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | ||
757 | |||
758 | if (present & AC_PINSENSE_ELDV) | ||
759 | hdmi_get_show_eld(codec, pin_nid, eld); | ||
760 | } | ||
761 | |||
762 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | ||
763 | { | ||
764 | struct hdmi_spec *spec = codec->spec; | ||
765 | |||
766 | if (spec->num_pins >= MAX_HDMI_PINS) { | ||
767 | snd_printk(KERN_WARNING | ||
768 | "HDMI: no space for pin %d\n", pin_nid); | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | |||
772 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); | ||
773 | |||
774 | spec->pin[spec->num_pins] = pin_nid; | ||
775 | spec->num_pins++; | ||
776 | |||
777 | /* | ||
778 | * It is assumed that converter nodes come first in the node list and | ||
779 | * hence have been registered and usable now. | ||
780 | */ | ||
781 | return hdmi_read_pin_conn(codec, pin_nid); | ||
782 | } | ||
783 | |||
784 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | ||
785 | { | ||
786 | struct hdmi_spec *spec = codec->spec; | ||
787 | |||
788 | if (spec->num_cvts >= MAX_HDMI_CVTS) { | ||
789 | snd_printk(KERN_WARNING | ||
790 | "HDMI: no space for converter %d\n", nid); | ||
791 | return -EINVAL; | ||
792 | } | ||
793 | |||
794 | spec->cvt[spec->num_cvts] = nid; | ||
795 | spec->num_cvts++; | ||
796 | |||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static int hdmi_parse_codec(struct hda_codec *codec) | ||
801 | { | ||
802 | hda_nid_t nid; | ||
803 | int i, nodes; | ||
804 | |||
805 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | ||
806 | if (!nid || nodes < 0) { | ||
807 | snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); | ||
808 | return -EINVAL; | ||
809 | } | ||
810 | |||
811 | for (i = 0; i < nodes; i++, nid++) { | ||
812 | unsigned int caps; | ||
813 | unsigned int type; | ||
814 | |||
815 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | ||
816 | type = get_wcaps_type(caps); | ||
817 | |||
818 | if (!(caps & AC_WCAP_DIGITAL)) | ||
819 | continue; | ||
820 | |||
821 | switch (type) { | ||
822 | case AC_WID_AUD_OUT: | ||
823 | if (hdmi_add_cvt(codec, nid) < 0) | ||
824 | return -EINVAL; | ||
825 | break; | ||
826 | case AC_WID_PIN: | ||
827 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
828 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | ||
829 | continue; | ||
830 | if (hdmi_add_pin(codec, nid) < 0) | ||
831 | return -EINVAL; | ||
832 | break; | ||
833 | } | ||
834 | } | ||
835 | |||
836 | /* | ||
837 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | ||
838 | * can be lost and presence sense verb will become inaccurate if the | ||
839 | * HDA link is powered off at hot plug or hw initialization time. | ||
840 | */ | ||
841 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
842 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | ||
843 | AC_PWRST_EPSS)) | ||
844 | codec->bus->power_keep_link_on = 1; | ||
845 | #endif | ||
846 | |||
847 | return 0; | ||
848 | } | ||
849 | |||
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 918f40378d52..88d035104cc5 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c | |||
@@ -40,815 +40,20 @@ | |||
40 | * | 40 | * |
41 | * The HDA correspondence of pipes/ports are converter/pin nodes. | 41 | * The HDA correspondence of pipes/ports are converter/pin nodes. |
42 | */ | 42 | */ |
43 | #define INTEL_HDMI_CVTS 2 | 43 | #define MAX_HDMI_CVTS 2 |
44 | #define INTEL_HDMI_PINS 3 | 44 | #define MAX_HDMI_PINS 3 |
45 | 45 | ||
46 | static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = { | 46 | #include "patch_hdmi.c" |
47 | |||
48 | static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
47 | "INTEL HDMI 0", | 49 | "INTEL HDMI 0", |
48 | "INTEL HDMI 1", | 50 | "INTEL HDMI 1", |
49 | }; | 51 | }; |
50 | 52 | ||
51 | struct intel_hdmi_spec { | ||
52 | int num_cvts; | ||
53 | int num_pins; | ||
54 | hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */ | ||
55 | hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */ | ||
56 | |||
57 | /* | ||
58 | * source connection for each pin | ||
59 | */ | ||
60 | hda_nid_t pin_cvt[INTEL_HDMI_PINS+1]; | ||
61 | |||
62 | /* | ||
63 | * HDMI sink attached to each pin | ||
64 | */ | ||
65 | struct hdmi_eld sink_eld[INTEL_HDMI_PINS]; | ||
66 | |||
67 | /* | ||
68 | * export one pcm per pipe | ||
69 | */ | ||
70 | struct hda_pcm pcm_rec[INTEL_HDMI_CVTS]; | ||
71 | }; | ||
72 | |||
73 | struct hdmi_audio_infoframe { | ||
74 | u8 type; /* 0x84 */ | ||
75 | u8 ver; /* 0x01 */ | ||
76 | u8 len; /* 0x0a */ | ||
77 | |||
78 | u8 checksum; /* PB0 */ | ||
79 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | ||
80 | u8 SS01_SF24; | ||
81 | u8 CXT04; | ||
82 | u8 CA; | ||
83 | u8 LFEPBL01_LSV36_DM_INH7; | ||
84 | u8 reserved[5]; /* PB6 - PB10 */ | ||
85 | }; | ||
86 | |||
87 | /* | ||
88 | * CEA speaker placement: | ||
89 | * | ||
90 | * FLH FCH FRH | ||
91 | * FLW FL FLC FC FRC FR FRW | ||
92 | * | ||
93 | * LFE | ||
94 | * TC | ||
95 | * | ||
96 | * RL RLC RC RRC RR | ||
97 | * | ||
98 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | ||
99 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | ||
100 | */ | ||
101 | enum cea_speaker_placement { | ||
102 | FL = (1 << 0), /* Front Left */ | ||
103 | FC = (1 << 1), /* Front Center */ | ||
104 | FR = (1 << 2), /* Front Right */ | ||
105 | FLC = (1 << 3), /* Front Left Center */ | ||
106 | FRC = (1 << 4), /* Front Right Center */ | ||
107 | RL = (1 << 5), /* Rear Left */ | ||
108 | RC = (1 << 6), /* Rear Center */ | ||
109 | RR = (1 << 7), /* Rear Right */ | ||
110 | RLC = (1 << 8), /* Rear Left Center */ | ||
111 | RRC = (1 << 9), /* Rear Right Center */ | ||
112 | LFE = (1 << 10), /* Low Frequency Effect */ | ||
113 | FLW = (1 << 11), /* Front Left Wide */ | ||
114 | FRW = (1 << 12), /* Front Right Wide */ | ||
115 | FLH = (1 << 13), /* Front Left High */ | ||
116 | FCH = (1 << 14), /* Front Center High */ | ||
117 | FRH = (1 << 15), /* Front Right High */ | ||
118 | TC = (1 << 16), /* Top Center */ | ||
119 | }; | ||
120 | |||
121 | /* | ||
122 | * ELD SA bits in the CEA Speaker Allocation data block | ||
123 | */ | ||
124 | static int eld_speaker_allocation_bits[] = { | ||
125 | [0] = FL | FR, | ||
126 | [1] = LFE, | ||
127 | [2] = FC, | ||
128 | [3] = RL | RR, | ||
129 | [4] = RC, | ||
130 | [5] = FLC | FRC, | ||
131 | [6] = RLC | RRC, | ||
132 | /* the following are not defined in ELD yet */ | ||
133 | [7] = FLW | FRW, | ||
134 | [8] = FLH | FRH, | ||
135 | [9] = TC, | ||
136 | [10] = FCH, | ||
137 | }; | ||
138 | |||
139 | struct cea_channel_speaker_allocation { | ||
140 | int ca_index; | ||
141 | int speakers[8]; | ||
142 | |||
143 | /* derived values, just for convenience */ | ||
144 | int channels; | ||
145 | int spk_mask; | ||
146 | }; | ||
147 | |||
148 | /* | ||
149 | * ALSA sequence is: | ||
150 | * | ||
151 | * surround40 surround41 surround50 surround51 surround71 | ||
152 | * ch0 front left = = = = | ||
153 | * ch1 front right = = = = | ||
154 | * ch2 rear left = = = = | ||
155 | * ch3 rear right = = = = | ||
156 | * ch4 LFE center center center | ||
157 | * ch5 LFE LFE | ||
158 | * ch6 side left | ||
159 | * ch7 side right | ||
160 | * | ||
161 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | ||
162 | */ | ||
163 | static int hdmi_channel_mapping[0x32][8] = { | ||
164 | /* stereo */ | ||
165 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
166 | /* 2.1 */ | ||
167 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
168 | /* Dolby Surround */ | ||
169 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
170 | /* surround40 */ | ||
171 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | ||
172 | /* 4ch */ | ||
173 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | ||
174 | /* surround41 */ | ||
175 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
176 | /* surround50 */ | ||
177 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
178 | /* surround51 */ | ||
179 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | ||
180 | /* 7.1 */ | ||
181 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * This is an ordered list! | ||
186 | * | ||
187 | * The preceding ones have better chances to be selected by | ||
188 | * hdmi_setup_channel_allocation(). | ||
189 | */ | ||
190 | static struct cea_channel_speaker_allocation channel_allocations[] = { | ||
191 | /* channel: 7 6 5 4 3 2 1 0 */ | ||
192 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | ||
193 | /* 2.1 */ | ||
194 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | ||
195 | /* Dolby Surround */ | ||
196 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | ||
197 | /* surround40 */ | ||
198 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
199 | /* surround41 */ | ||
200 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
201 | /* surround50 */ | ||
202 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
203 | /* surround51 */ | ||
204 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
205 | /* 6.1 */ | ||
206 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
207 | /* surround71 */ | ||
208 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
209 | |||
210 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | ||
211 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | ||
212 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | ||
213 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | ||
214 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | ||
215 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | ||
216 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | ||
217 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | ||
218 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | ||
219 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | ||
220 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | ||
221 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | ||
222 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | ||
223 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | ||
224 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | ||
225 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | ||
226 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | ||
227 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | ||
228 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | ||
229 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | ||
230 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | ||
231 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | ||
232 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | ||
233 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | ||
234 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
235 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | ||
236 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | ||
237 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | ||
238 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | ||
239 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | ||
240 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | ||
241 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | ||
242 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | ||
243 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | ||
244 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | ||
245 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | ||
246 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
247 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | ||
248 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | ||
249 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | ||
250 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | ||
251 | }; | ||
252 | |||
253 | /* | ||
254 | * HDA/HDMI auto parsing | ||
255 | */ | ||
256 | |||
257 | static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) | ||
258 | { | ||
259 | int i; | ||
260 | |||
261 | for (i = 0; nids[i]; i++) | ||
262 | if (nids[i] == nid) | ||
263 | return i; | ||
264 | |||
265 | snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | ||
270 | { | ||
271 | struct intel_hdmi_spec *spec = codec->spec; | ||
272 | hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; | ||
273 | int conn_len, curr; | ||
274 | int index; | ||
275 | |||
276 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | ||
277 | snd_printk(KERN_WARNING | ||
278 | "HDMI: pin %d wcaps %#x " | ||
279 | "does not support connection list\n", | ||
280 | pin_nid, get_wcaps(codec, pin_nid)); | ||
281 | return -EINVAL; | ||
282 | } | ||
283 | |||
284 | conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, | ||
285 | HDA_MAX_CONNECTIONS); | ||
286 | if (conn_len > 1) | ||
287 | curr = snd_hda_codec_read(codec, pin_nid, 0, | ||
288 | AC_VERB_GET_CONNECT_SEL, 0); | ||
289 | else | ||
290 | curr = 0; | ||
291 | |||
292 | index = hda_node_index(spec->pin, pin_nid); | ||
293 | if (index < 0) | ||
294 | return -EINVAL; | ||
295 | |||
296 | spec->pin_cvt[index] = conn_list[curr]; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, | ||
302 | struct hdmi_eld *eld) | ||
303 | { | ||
304 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | ||
305 | snd_hdmi_show_eld(eld); | ||
306 | } | ||
307 | |||
308 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | ||
309 | struct hdmi_eld *eld) | ||
310 | { | ||
311 | int present = snd_hda_pin_sense(codec, pin_nid); | ||
312 | |||
313 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | ||
314 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | ||
315 | |||
316 | if (present & AC_PINSENSE_ELDV) | ||
317 | hdmi_get_show_eld(codec, pin_nid, eld); | ||
318 | } | ||
319 | |||
320 | static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | ||
321 | { | ||
322 | struct intel_hdmi_spec *spec = codec->spec; | ||
323 | |||
324 | if (spec->num_pins >= INTEL_HDMI_PINS) { | ||
325 | snd_printk(KERN_WARNING | ||
326 | "HDMI: no space for pin %d \n", pin_nid); | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | |||
330 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); | ||
331 | |||
332 | spec->pin[spec->num_pins] = pin_nid; | ||
333 | spec->num_pins++; | ||
334 | |||
335 | /* | ||
336 | * It is assumed that converter nodes come first in the node list and | ||
337 | * hence have been registered and usable now. | ||
338 | */ | ||
339 | return intel_hdmi_read_pin_conn(codec, pin_nid); | ||
340 | } | ||
341 | |||
342 | static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | ||
343 | { | ||
344 | struct intel_hdmi_spec *spec = codec->spec; | ||
345 | |||
346 | if (spec->num_cvts >= INTEL_HDMI_CVTS) { | ||
347 | snd_printk(KERN_WARNING | ||
348 | "HDMI: no space for converter %d \n", nid); | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | |||
352 | spec->cvt[spec->num_cvts] = nid; | ||
353 | spec->num_cvts++; | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int intel_hdmi_parse_codec(struct hda_codec *codec) | ||
359 | { | ||
360 | hda_nid_t nid; | ||
361 | int i, nodes; | ||
362 | |||
363 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | ||
364 | if (!nid || nodes < 0) { | ||
365 | snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); | ||
366 | return -EINVAL; | ||
367 | } | ||
368 | |||
369 | for (i = 0; i < nodes; i++, nid++) { | ||
370 | unsigned int caps; | ||
371 | unsigned int type; | ||
372 | |||
373 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | ||
374 | type = get_wcaps_type(caps); | ||
375 | |||
376 | if (!(caps & AC_WCAP_DIGITAL)) | ||
377 | continue; | ||
378 | |||
379 | switch (type) { | ||
380 | case AC_WID_AUD_OUT: | ||
381 | if (intel_hdmi_add_cvt(codec, nid) < 0) | ||
382 | return -EINVAL; | ||
383 | break; | ||
384 | case AC_WID_PIN: | ||
385 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
386 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | ||
387 | continue; | ||
388 | if (intel_hdmi_add_pin(codec, nid) < 0) | ||
389 | return -EINVAL; | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | /* | ||
395 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | ||
396 | * can be lost and presence sense verb will become inaccurate if the | ||
397 | * HDA link is powered off at hot plug or hw initialization time. | ||
398 | */ | ||
399 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
400 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | ||
401 | AC_PWRST_EPSS)) | ||
402 | codec->bus->power_keep_link_on = 1; | ||
403 | #endif | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | /* | ||
409 | * HDMI routines | ||
410 | */ | ||
411 | |||
412 | #ifdef BE_PARANOID | ||
413 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
414 | int *packet_index, int *byte_index) | ||
415 | { | ||
416 | int val; | ||
417 | |||
418 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
419 | AC_VERB_GET_HDMI_DIP_INDEX, 0); | ||
420 | |||
421 | *packet_index = val >> 5; | ||
422 | *byte_index = val & 0x1f; | ||
423 | } | ||
424 | #endif | ||
425 | |||
426 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
427 | int packet_index, int byte_index) | ||
428 | { | ||
429 | int val; | ||
430 | |||
431 | val = (packet_index << 5) | (byte_index & 0x1f); | ||
432 | |||
433 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | ||
434 | } | ||
435 | |||
436 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, | ||
437 | unsigned char val) | ||
438 | { | ||
439 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | ||
440 | } | ||
441 | |||
442 | static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) | ||
443 | { | ||
444 | /* Unmute */ | ||
445 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) | ||
446 | snd_hda_codec_write(codec, pin_nid, 0, | ||
447 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
448 | /* Enable pin out */ | ||
449 | snd_hda_codec_write(codec, pin_nid, 0, | ||
450 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
451 | } | ||
452 | |||
453 | /* | ||
454 | * Enable Audio InfoFrame Transmission | ||
455 | */ | ||
456 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, | ||
457 | hda_nid_t pin_nid) | ||
458 | { | ||
459 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
460 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
461 | AC_DIPXMIT_BEST); | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * Disable Audio InfoFrame Transmission | ||
466 | */ | ||
467 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, | ||
468 | hda_nid_t pin_nid) | ||
469 | { | ||
470 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
471 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
472 | AC_DIPXMIT_DISABLE); | ||
473 | } | ||
474 | |||
475 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) | ||
476 | { | ||
477 | return 1 + snd_hda_codec_read(codec, nid, 0, | ||
478 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | ||
479 | } | ||
480 | |||
481 | static void hdmi_set_channel_count(struct hda_codec *codec, | ||
482 | hda_nid_t nid, int chs) | ||
483 | { | ||
484 | if (chs != hdmi_get_channel_count(codec, nid)) | ||
485 | snd_hda_codec_write(codec, nid, 0, | ||
486 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | ||
487 | } | ||
488 | |||
489 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | ||
490 | hda_nid_t pin_nid) | ||
491 | { | ||
492 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
493 | int i; | ||
494 | int slot; | ||
495 | |||
496 | for (i = 0; i < 8; i++) { | ||
497 | slot = snd_hda_codec_read(codec, pin_nid, 0, | ||
498 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | ||
499 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | ||
500 | slot >> 4, slot & 0xf); | ||
501 | } | ||
502 | #endif | ||
503 | } | ||
504 | |||
505 | |||
506 | /* | ||
507 | * Audio InfoFrame routines | ||
508 | */ | ||
509 | |||
510 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) | ||
511 | { | ||
512 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
513 | int i; | ||
514 | int size; | ||
515 | |||
516 | size = snd_hdmi_get_eld_size(codec, pin_nid); | ||
517 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); | ||
518 | |||
519 | for (i = 0; i < 8; i++) { | ||
520 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
521 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
522 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); | ||
523 | } | ||
524 | #endif | ||
525 | } | ||
526 | |||
527 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | ||
528 | { | ||
529 | #ifdef BE_PARANOID | ||
530 | int i, j; | ||
531 | int size; | ||
532 | int pi, bi; | ||
533 | for (i = 0; i < 8; i++) { | ||
534 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
535 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
536 | if (size == 0) | ||
537 | continue; | ||
538 | |||
539 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); | ||
540 | for (j = 1; j < 1000; j++) { | ||
541 | hdmi_write_dip_byte(codec, pin_nid, 0x0); | ||
542 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); | ||
543 | if (pi != i) | ||
544 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | ||
545 | bi, pi, i); | ||
546 | if (bi == 0) /* byte index wrapped around */ | ||
547 | break; | ||
548 | } | ||
549 | snd_printd(KERN_INFO | ||
550 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | ||
551 | i, size, j); | ||
552 | } | ||
553 | #endif | ||
554 | } | ||
555 | |||
556 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | ||
557 | { | ||
558 | u8 *bytes = (u8 *)ai; | ||
559 | u8 sum = 0; | ||
560 | int i; | ||
561 | |||
562 | ai->checksum = 0; | ||
563 | |||
564 | for (i = 0; i < sizeof(*ai); i++) | ||
565 | sum += bytes[i]; | ||
566 | |||
567 | ai->checksum = - sum; | ||
568 | } | ||
569 | |||
570 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | ||
571 | hda_nid_t pin_nid, | ||
572 | struct hdmi_audio_infoframe *ai) | ||
573 | { | ||
574 | u8 *bytes = (u8 *)ai; | ||
575 | int i; | ||
576 | |||
577 | hdmi_debug_dip_size(codec, pin_nid); | ||
578 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | ||
579 | |||
580 | hdmi_checksum_audio_infoframe(ai); | ||
581 | |||
582 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
583 | for (i = 0; i < sizeof(*ai); i++) | ||
584 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * Compute derived values in channel_allocations[]. | ||
589 | */ | ||
590 | static void init_channel_allocations(void) | ||
591 | { | ||
592 | int i, j; | ||
593 | struct cea_channel_speaker_allocation *p; | ||
594 | |||
595 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
596 | p = channel_allocations + i; | ||
597 | p->channels = 0; | ||
598 | p->spk_mask = 0; | ||
599 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | ||
600 | if (p->speakers[j]) { | ||
601 | p->channels++; | ||
602 | p->spk_mask |= p->speakers[j]; | ||
603 | } | ||
604 | } | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * The transformation takes two steps: | ||
609 | * | ||
610 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | ||
611 | * spk_mask => (channel_allocations[]) => ai->CA | ||
612 | * | ||
613 | * TODO: it could select the wrong CA from multiple candidates. | ||
614 | */ | ||
615 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | ||
616 | struct hdmi_audio_infoframe *ai) | ||
617 | { | ||
618 | struct intel_hdmi_spec *spec = codec->spec; | ||
619 | struct hdmi_eld *eld; | ||
620 | int i; | ||
621 | int spk_mask = 0; | ||
622 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
623 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
624 | |||
625 | /* | ||
626 | * CA defaults to 0 for basic stereo audio | ||
627 | */ | ||
628 | if (channels <= 2) | ||
629 | return 0; | ||
630 | |||
631 | i = hda_node_index(spec->pin_cvt, nid); | ||
632 | if (i < 0) | ||
633 | return 0; | ||
634 | eld = &spec->sink_eld[i]; | ||
635 | |||
636 | /* | ||
637 | * HDMI sink's ELD info cannot always be retrieved for now, e.g. | ||
638 | * in console or for audio devices. Assume the highest speakers | ||
639 | * configuration, to _not_ prohibit multi-channel audio playback. | ||
640 | */ | ||
641 | if (!eld->spk_alloc) | ||
642 | eld->spk_alloc = 0xffff; | ||
643 | |||
644 | /* | ||
645 | * expand ELD's speaker allocation mask | ||
646 | * | ||
647 | * ELD tells the speaker mask in a compact(paired) form, | ||
648 | * expand ELD's notions to match the ones used by Audio InfoFrame. | ||
649 | */ | ||
650 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | ||
651 | if (eld->spk_alloc & (1 << i)) | ||
652 | spk_mask |= eld_speaker_allocation_bits[i]; | ||
653 | } | ||
654 | |||
655 | /* search for the first working match in the CA table */ | ||
656 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
657 | if (channels == channel_allocations[i].channels && | ||
658 | (spk_mask & channel_allocations[i].spk_mask) == | ||
659 | channel_allocations[i].spk_mask) { | ||
660 | ai->CA = channel_allocations[i].ca_index; | ||
661 | break; | ||
662 | } | ||
663 | } | ||
664 | |||
665 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | ||
666 | snd_printdd(KERN_INFO | ||
667 | "HDMI: select CA 0x%x for %d-channel allocation: %s\n", | ||
668 | ai->CA, channels, buf); | ||
669 | |||
670 | return ai->CA; | ||
671 | } | ||
672 | |||
673 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
674 | hda_nid_t pin_nid, | ||
675 | struct hdmi_audio_infoframe *ai) | ||
676 | { | ||
677 | int i; | ||
678 | int ca = ai->CA; | ||
679 | int err; | ||
680 | |||
681 | if (hdmi_channel_mapping[ca][1] == 0) { | ||
682 | for (i = 0; i < channel_allocations[ca].channels; i++) | ||
683 | hdmi_channel_mapping[ca][i] = i | (i << 4); | ||
684 | for (; i < 8; i++) | ||
685 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); | ||
686 | } | ||
687 | |||
688 | for (i = 0; i < 8; i++) { | ||
689 | err = snd_hda_codec_write(codec, pin_nid, 0, | ||
690 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
691 | hdmi_channel_mapping[ca][i]); | ||
692 | if (err) { | ||
693 | snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); | ||
694 | break; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | hdmi_debug_channel_mapping(codec, pin_nid); | ||
699 | } | ||
700 | |||
701 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | ||
702 | struct hdmi_audio_infoframe *ai) | ||
703 | { | ||
704 | u8 *bytes = (u8 *)ai; | ||
705 | u8 val; | ||
706 | int i; | ||
707 | |||
708 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) | ||
709 | != AC_DIPXMIT_BEST) | ||
710 | return false; | ||
711 | |||
712 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
713 | for (i = 0; i < sizeof(*ai); i++) { | ||
714 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
715 | AC_VERB_GET_HDMI_DIP_DATA, 0); | ||
716 | if (val != bytes[i]) | ||
717 | return false; | ||
718 | } | ||
719 | |||
720 | return true; | ||
721 | } | ||
722 | |||
723 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | ||
724 | struct snd_pcm_substream *substream) | ||
725 | { | ||
726 | struct intel_hdmi_spec *spec = codec->spec; | ||
727 | hda_nid_t pin_nid; | ||
728 | int i; | ||
729 | struct hdmi_audio_infoframe ai = { | ||
730 | .type = 0x84, | ||
731 | .ver = 0x01, | ||
732 | .len = 0x0a, | ||
733 | .CC02_CT47 = substream->runtime->channels - 1, | ||
734 | }; | ||
735 | |||
736 | hdmi_setup_channel_allocation(codec, nid, &ai); | ||
737 | |||
738 | for (i = 0; i < spec->num_pins; i++) { | ||
739 | if (spec->pin_cvt[i] != nid) | ||
740 | continue; | ||
741 | if (!spec->sink_eld[i].monitor_present) | ||
742 | continue; | ||
743 | |||
744 | pin_nid = spec->pin[i]; | ||
745 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | ||
746 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | ||
747 | hdmi_stop_infoframe_trans(codec, pin_nid); | ||
748 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | ||
749 | hdmi_start_infoframe_trans(codec, pin_nid); | ||
750 | } | ||
751 | } | ||
752 | } | ||
753 | |||
754 | |||
755 | /* | 53 | /* |
756 | * Unsolicited events | 54 | * HDMI callbacks |
757 | */ | 55 | */ |
758 | 56 | ||
759 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
760 | { | ||
761 | struct intel_hdmi_spec *spec = codec->spec; | ||
762 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
763 | int pind = !!(res & AC_UNSOL_RES_PD); | ||
764 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | ||
765 | int index; | ||
766 | |||
767 | printk(KERN_INFO | ||
768 | "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | ||
769 | tag, pind, eldv); | ||
770 | |||
771 | index = hda_node_index(spec->pin, tag); | ||
772 | if (index < 0) | ||
773 | return; | ||
774 | |||
775 | spec->sink_eld[index].monitor_present = pind; | ||
776 | spec->sink_eld[index].eld_valid = eldv; | ||
777 | |||
778 | if (pind && eldv) { | ||
779 | hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]); | ||
780 | /* TODO: do real things about ELD */ | ||
781 | } | ||
782 | } | ||
783 | |||
784 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
785 | { | ||
786 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
787 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
788 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | ||
789 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | ||
790 | |||
791 | printk(KERN_INFO | ||
792 | "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | ||
793 | tag, | ||
794 | subtag, | ||
795 | cp_state, | ||
796 | cp_ready); | ||
797 | |||
798 | /* TODO */ | ||
799 | if (cp_state) | ||
800 | ; | ||
801 | if (cp_ready) | ||
802 | ; | ||
803 | } | ||
804 | |||
805 | |||
806 | static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | ||
807 | { | ||
808 | struct intel_hdmi_spec *spec = codec->spec; | ||
809 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
810 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
811 | |||
812 | if (hda_node_index(spec->pin, tag) < 0) { | ||
813 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); | ||
814 | return; | ||
815 | } | ||
816 | |||
817 | if (subtag == 0) | ||
818 | hdmi_intrinsic_event(codec, res); | ||
819 | else | ||
820 | hdmi_non_intrinsic_event(codec, res); | ||
821 | } | ||
822 | |||
823 | /* | ||
824 | * Callbacks | ||
825 | */ | ||
826 | |||
827 | static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
828 | u32 stream_tag, int format) | ||
829 | { | ||
830 | int tag; | ||
831 | int fmt; | ||
832 | |||
833 | tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; | ||
834 | fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); | ||
835 | |||
836 | snd_printdd("hdmi_setup_stream: " | ||
837 | "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", | ||
838 | nid, | ||
839 | tag == stream_tag ? "" : "new-", | ||
840 | stream_tag, | ||
841 | fmt == format ? "" : "new-", | ||
842 | format); | ||
843 | |||
844 | if (tag != stream_tag) | ||
845 | snd_hda_codec_write(codec, nid, 0, | ||
846 | AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4); | ||
847 | if (fmt != format) | ||
848 | snd_hda_codec_write(codec, nid, 0, | ||
849 | AC_VERB_SET_STREAM_FORMAT, format); | ||
850 | } | ||
851 | |||
852 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 57 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
853 | struct hda_codec *codec, | 58 | struct hda_codec *codec, |
854 | unsigned int stream_tag, | 59 | unsigned int stream_tag, |
@@ -882,7 +87,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = { | |||
882 | 87 | ||
883 | static int intel_hdmi_build_pcms(struct hda_codec *codec) | 88 | static int intel_hdmi_build_pcms(struct hda_codec *codec) |
884 | { | 89 | { |
885 | struct intel_hdmi_spec *spec = codec->spec; | 90 | struct hdmi_spec *spec = codec->spec; |
886 | struct hda_pcm *info = spec->pcm_rec; | 91 | struct hda_pcm *info = spec->pcm_rec; |
887 | int i; | 92 | int i; |
888 | 93 | ||
@@ -908,7 +113,7 @@ static int intel_hdmi_build_pcms(struct hda_codec *codec) | |||
908 | 113 | ||
909 | static int intel_hdmi_build_controls(struct hda_codec *codec) | 114 | static int intel_hdmi_build_controls(struct hda_codec *codec) |
910 | { | 115 | { |
911 | struct intel_hdmi_spec *spec = codec->spec; | 116 | struct hdmi_spec *spec = codec->spec; |
912 | int err; | 117 | int err; |
913 | int i; | 118 | int i; |
914 | 119 | ||
@@ -923,7 +128,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec) | |||
923 | 128 | ||
924 | static int intel_hdmi_init(struct hda_codec *codec) | 129 | static int intel_hdmi_init(struct hda_codec *codec) |
925 | { | 130 | { |
926 | struct intel_hdmi_spec *spec = codec->spec; | 131 | struct hdmi_spec *spec = codec->spec; |
927 | int i; | 132 | int i; |
928 | 133 | ||
929 | for (i = 0; spec->pin[i]; i++) { | 134 | for (i = 0; spec->pin[i]; i++) { |
@@ -937,7 +142,7 @@ static int intel_hdmi_init(struct hda_codec *codec) | |||
937 | 142 | ||
938 | static void intel_hdmi_free(struct hda_codec *codec) | 143 | static void intel_hdmi_free(struct hda_codec *codec) |
939 | { | 144 | { |
940 | struct intel_hdmi_spec *spec = codec->spec; | 145 | struct hdmi_spec *spec = codec->spec; |
941 | int i; | 146 | int i; |
942 | 147 | ||
943 | for (i = 0; i < spec->num_pins; i++) | 148 | for (i = 0; i < spec->num_pins; i++) |
@@ -951,12 +156,12 @@ static struct hda_codec_ops intel_hdmi_patch_ops = { | |||
951 | .free = intel_hdmi_free, | 156 | .free = intel_hdmi_free, |
952 | .build_pcms = intel_hdmi_build_pcms, | 157 | .build_pcms = intel_hdmi_build_pcms, |
953 | .build_controls = intel_hdmi_build_controls, | 158 | .build_controls = intel_hdmi_build_controls, |
954 | .unsol_event = intel_hdmi_unsol_event, | 159 | .unsol_event = hdmi_unsol_event, |
955 | }; | 160 | }; |
956 | 161 | ||
957 | static int patch_intel_hdmi(struct hda_codec *codec) | 162 | static int patch_intel_hdmi(struct hda_codec *codec) |
958 | { | 163 | { |
959 | struct intel_hdmi_spec *spec; | 164 | struct hdmi_spec *spec; |
960 | int i; | 165 | int i; |
961 | 166 | ||
962 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 167 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
@@ -964,7 +169,7 @@ static int patch_intel_hdmi(struct hda_codec *codec) | |||
964 | return -ENOMEM; | 169 | return -ENOMEM; |
965 | 170 | ||
966 | codec->spec = spec; | 171 | codec->spec = spec; |
967 | if (intel_hdmi_parse_codec(codec) < 0) { | 172 | if (hdmi_parse_codec(codec) < 0) { |
968 | codec->spec = NULL; | 173 | codec->spec = NULL; |
969 | kfree(spec); | 174 | kfree(spec); |
970 | return -EINVAL; | 175 | return -EINVAL; |
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 6afdab09bab7..70669a246902 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c | |||
@@ -29,13 +29,23 @@ | |||
29 | #include "hda_codec.h" | 29 | #include "hda_codec.h" |
30 | #include "hda_local.h" | 30 | #include "hda_local.h" |
31 | 31 | ||
32 | #define MAX_HDMI_CVTS 1 | ||
33 | #define MAX_HDMI_PINS 1 | ||
34 | |||
35 | #include "patch_hdmi.c" | ||
36 | |||
37 | static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
38 | "NVIDIA HDMI", | ||
39 | }; | ||
40 | |||
32 | /* define below to restrict the supported rates and formats */ | 41 | /* define below to restrict the supported rates and formats */ |
33 | /* #define LIMITED_RATE_FMT_SUPPORT */ | 42 | /* #define LIMITED_RATE_FMT_SUPPORT */ |
34 | 43 | ||
35 | struct nvhdmi_spec { | 44 | enum HDACodec { |
36 | struct hda_multi_out multiout; | 45 | HDA_CODEC_NVIDIA_MCP7X, |
37 | 46 | HDA_CODEC_NVIDIA_MCP89, | |
38 | struct hda_pcm pcm_rec; | 47 | HDA_CODEC_NVIDIA_GT21X, |
48 | HDA_CODEC_INVALID | ||
39 | }; | 49 | }; |
40 | 50 | ||
41 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | 51 | #define Nv_VERB_SET_Channel_Allocation 0xF79 |
@@ -43,15 +53,18 @@ struct nvhdmi_spec { | |||
43 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | 53 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 |
44 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | 54 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 |
45 | 55 | ||
46 | #define Nv_Master_Convert_nid 0x04 | 56 | #define nvhdmi_master_con_nid_7x 0x04 |
47 | #define Nv_Master_Pin_nid 0x05 | 57 | #define nvhdmi_master_pin_nid_7x 0x05 |
48 | 58 | ||
49 | static hda_nid_t nvhdmi_convert_nids[4] = { | 59 | #define nvhdmi_master_con_nid_89 0x04 |
60 | #define nvhdmi_master_pin_nid_89 0x05 | ||
61 | |||
62 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
50 | /*front, rear, clfe, rear_surr */ | 63 | /*front, rear, clfe, rear_surr */ |
51 | 0x6, 0x8, 0xa, 0xc, | 64 | 0x6, 0x8, 0xa, 0xc, |
52 | }; | 65 | }; |
53 | 66 | ||
54 | static struct hda_verb nvhdmi_basic_init[] = { | 67 | static struct hda_verb nvhdmi_basic_init_7x[] = { |
55 | /* set audio protect on */ | 68 | /* set audio protect on */ |
56 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 69 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
57 | /* enable digital output on pin widget */ | 70 | /* enable digital output on pin widget */ |
@@ -84,22 +97,60 @@ static struct hda_verb nvhdmi_basic_init[] = { | |||
84 | */ | 97 | */ |
85 | static int nvhdmi_build_controls(struct hda_codec *codec) | 98 | static int nvhdmi_build_controls(struct hda_codec *codec) |
86 | { | 99 | { |
87 | struct nvhdmi_spec *spec = codec->spec; | 100 | struct hdmi_spec *spec = codec->spec; |
88 | int err; | 101 | int err; |
102 | int i; | ||
89 | 103 | ||
90 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 104 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) |
91 | if (err < 0) | 105 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { |
92 | return err; | 106 | for (i = 0; i < codec->num_pcms; i++) { |
107 | err = snd_hda_create_spdif_out_ctls(codec, | ||
108 | spec->cvt[i]); | ||
109 | if (err < 0) | ||
110 | return err; | ||
111 | } | ||
112 | } else { | ||
113 | err = snd_hda_create_spdif_out_ctls(codec, | ||
114 | spec->multiout.dig_out_nid); | ||
115 | if (err < 0) | ||
116 | return err; | ||
117 | } | ||
93 | 118 | ||
94 | return 0; | 119 | return 0; |
95 | } | 120 | } |
96 | 121 | ||
97 | static int nvhdmi_init(struct hda_codec *codec) | 122 | static int nvhdmi_init(struct hda_codec *codec) |
98 | { | 123 | { |
99 | snd_hda_sequence_write(codec, nvhdmi_basic_init); | 124 | struct hdmi_spec *spec = codec->spec; |
125 | int i; | ||
126 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
127 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
128 | for (i = 0; spec->pin[i]; i++) { | ||
129 | hdmi_enable_output(codec, spec->pin[i]); | ||
130 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
131 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
132 | AC_USRSP_EN | spec->pin[i]); | ||
133 | } | ||
134 | } else { | ||
135 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
136 | } | ||
100 | return 0; | 137 | return 0; |
101 | } | 138 | } |
102 | 139 | ||
140 | static void nvhdmi_free(struct hda_codec *codec) | ||
141 | { | ||
142 | struct hdmi_spec *spec = codec->spec; | ||
143 | int i; | ||
144 | |||
145 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
146 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
147 | for (i = 0; i < spec->num_pins; i++) | ||
148 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
149 | } | ||
150 | |||
151 | kfree(spec); | ||
152 | } | ||
153 | |||
103 | /* | 154 | /* |
104 | * Digital out | 155 | * Digital out |
105 | */ | 156 | */ |
@@ -107,25 +158,25 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
107 | struct hda_codec *codec, | 158 | struct hda_codec *codec, |
108 | struct snd_pcm_substream *substream) | 159 | struct snd_pcm_substream *substream) |
109 | { | 160 | { |
110 | struct nvhdmi_spec *spec = codec->spec; | 161 | struct hdmi_spec *spec = codec->spec; |
111 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 162 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
112 | } | 163 | } |
113 | 164 | ||
114 | static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, | 165 | static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, |
115 | struct hda_codec *codec, | 166 | struct hda_codec *codec, |
116 | struct snd_pcm_substream *substream) | 167 | struct snd_pcm_substream *substream) |
117 | { | 168 | { |
118 | struct nvhdmi_spec *spec = codec->spec; | 169 | struct hdmi_spec *spec = codec->spec; |
119 | int i; | 170 | int i; |
120 | 171 | ||
121 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, | 172 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, |
122 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 173 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
123 | for (i = 0; i < 4; i++) { | 174 | for (i = 0; i < 4; i++) { |
124 | /* set the stream id */ | 175 | /* set the stream id */ |
125 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 176 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
126 | AC_VERB_SET_CHANNEL_STREAMID, 0); | 177 | AC_VERB_SET_CHANNEL_STREAMID, 0); |
127 | /* set the stream format */ | 178 | /* set the stream format */ |
128 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 179 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
129 | AC_VERB_SET_STREAM_FORMAT, 0); | 180 | AC_VERB_SET_STREAM_FORMAT, 0); |
130 | } | 181 | } |
131 | 182 | ||
@@ -136,10 +187,25 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, | |||
136 | struct hda_codec *codec, | 187 | struct hda_codec *codec, |
137 | struct snd_pcm_substream *substream) | 188 | struct snd_pcm_substream *substream) |
138 | { | 189 | { |
139 | struct nvhdmi_spec *spec = codec->spec; | 190 | struct hdmi_spec *spec = codec->spec; |
140 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 191 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
141 | } | 192 | } |
142 | 193 | ||
194 | static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, | ||
195 | struct hda_codec *codec, | ||
196 | unsigned int stream_tag, | ||
197 | unsigned int format, | ||
198 | struct snd_pcm_substream *substream) | ||
199 | { | ||
200 | hdmi_set_channel_count(codec, hinfo->nid, | ||
201 | substream->runtime->channels); | ||
202 | |||
203 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
204 | |||
205 | hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
143 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | 209 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, |
144 | struct hda_codec *codec, | 210 | struct hda_codec *codec, |
145 | unsigned int stream_tag, | 211 | unsigned int stream_tag, |
@@ -181,29 +247,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
181 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 247 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
182 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 248 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) |
183 | snd_hda_codec_write(codec, | 249 | snd_hda_codec_write(codec, |
184 | Nv_Master_Convert_nid, | 250 | nvhdmi_master_con_nid_7x, |
185 | 0, | 251 | 0, |
186 | AC_VERB_SET_DIGI_CONVERT_1, | 252 | AC_VERB_SET_DIGI_CONVERT_1, |
187 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 253 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
188 | 254 | ||
189 | /* set the stream id */ | 255 | /* set the stream id */ |
190 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 256 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
191 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | 257 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); |
192 | 258 | ||
193 | /* set the stream format */ | 259 | /* set the stream format */ |
194 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 260 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
195 | AC_VERB_SET_STREAM_FORMAT, format); | 261 | AC_VERB_SET_STREAM_FORMAT, format); |
196 | 262 | ||
197 | /* turn on again (if needed) */ | 263 | /* turn on again (if needed) */ |
198 | /* enable and set the channel status audio/data flag */ | 264 | /* enable and set the channel status audio/data flag */ |
199 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 265 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
200 | snd_hda_codec_write(codec, | 266 | snd_hda_codec_write(codec, |
201 | Nv_Master_Convert_nid, | 267 | nvhdmi_master_con_nid_7x, |
202 | 0, | 268 | 0, |
203 | AC_VERB_SET_DIGI_CONVERT_1, | 269 | AC_VERB_SET_DIGI_CONVERT_1, |
204 | codec->spdif_ctls & 0xff); | 270 | codec->spdif_ctls & 0xff); |
205 | snd_hda_codec_write(codec, | 271 | snd_hda_codec_write(codec, |
206 | Nv_Master_Convert_nid, | 272 | nvhdmi_master_con_nid_7x, |
207 | 0, | 273 | 0, |
208 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 274 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
209 | } | 275 | } |
@@ -220,19 +286,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
220 | if (codec->spdif_status_reset && | 286 | if (codec->spdif_status_reset && |
221 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | 287 | (codec->spdif_ctls & AC_DIG1_ENABLE)) |
222 | snd_hda_codec_write(codec, | 288 | snd_hda_codec_write(codec, |
223 | nvhdmi_convert_nids[i], | 289 | nvhdmi_con_nids_7x[i], |
224 | 0, | 290 | 0, |
225 | AC_VERB_SET_DIGI_CONVERT_1, | 291 | AC_VERB_SET_DIGI_CONVERT_1, |
226 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 292 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
227 | /* set the stream id */ | 293 | /* set the stream id */ |
228 | snd_hda_codec_write(codec, | 294 | snd_hda_codec_write(codec, |
229 | nvhdmi_convert_nids[i], | 295 | nvhdmi_con_nids_7x[i], |
230 | 0, | 296 | 0, |
231 | AC_VERB_SET_CHANNEL_STREAMID, | 297 | AC_VERB_SET_CHANNEL_STREAMID, |
232 | (stream_tag << 4) | channel_id); | 298 | (stream_tag << 4) | channel_id); |
233 | /* set the stream format */ | 299 | /* set the stream format */ |
234 | snd_hda_codec_write(codec, | 300 | snd_hda_codec_write(codec, |
235 | nvhdmi_convert_nids[i], | 301 | nvhdmi_con_nids_7x[i], |
236 | 0, | 302 | 0, |
237 | AC_VERB_SET_STREAM_FORMAT, | 303 | AC_VERB_SET_STREAM_FORMAT, |
238 | format); | 304 | format); |
@@ -241,12 +307,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
241 | if (codec->spdif_status_reset && | 307 | if (codec->spdif_status_reset && |
242 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 308 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
243 | snd_hda_codec_write(codec, | 309 | snd_hda_codec_write(codec, |
244 | nvhdmi_convert_nids[i], | 310 | nvhdmi_con_nids_7x[i], |
245 | 0, | 311 | 0, |
246 | AC_VERB_SET_DIGI_CONVERT_1, | 312 | AC_VERB_SET_DIGI_CONVERT_1, |
247 | codec->spdif_ctls & 0xff); | 313 | codec->spdif_ctls & 0xff); |
248 | snd_hda_codec_write(codec, | 314 | snd_hda_codec_write(codec, |
249 | nvhdmi_convert_nids[i], | 315 | nvhdmi_con_nids_7x[i], |
250 | 0, | 316 | 0, |
251 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 317 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
252 | } | 318 | } |
@@ -261,28 +327,47 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
261 | return 0; | 327 | return 0; |
262 | } | 328 | } |
263 | 329 | ||
330 | static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
331 | struct hda_codec *codec, | ||
332 | struct snd_pcm_substream *substream) | ||
333 | { | ||
334 | return 0; | ||
335 | } | ||
336 | |||
264 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, | 337 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, |
265 | struct hda_codec *codec, | 338 | struct hda_codec *codec, |
266 | unsigned int stream_tag, | 339 | unsigned int stream_tag, |
267 | unsigned int format, | 340 | unsigned int format, |
268 | struct snd_pcm_substream *substream) | 341 | struct snd_pcm_substream *substream) |
269 | { | 342 | { |
270 | struct nvhdmi_spec *spec = codec->spec; | 343 | struct hdmi_spec *spec = codec->spec; |
271 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | 344 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, |
272 | format, substream); | 345 | format, substream); |
273 | } | 346 | } |
274 | 347 | ||
275 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { | 348 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { |
349 | .substreams = 1, | ||
350 | .channels_min = 2, | ||
351 | .rates = SUPPORTED_RATES, | ||
352 | .maxbps = SUPPORTED_MAXBPS, | ||
353 | .formats = SUPPORTED_FORMATS, | ||
354 | .ops = { | ||
355 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, | ||
356 | .cleanup = nvhdmi_playback_pcm_cleanup, | ||
357 | }, | ||
358 | }; | ||
359 | |||
360 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { | ||
276 | .substreams = 1, | 361 | .substreams = 1, |
277 | .channels_min = 2, | 362 | .channels_min = 2, |
278 | .channels_max = 8, | 363 | .channels_max = 8, |
279 | .nid = Nv_Master_Convert_nid, | 364 | .nid = nvhdmi_master_con_nid_7x, |
280 | .rates = SUPPORTED_RATES, | 365 | .rates = SUPPORTED_RATES, |
281 | .maxbps = SUPPORTED_MAXBPS, | 366 | .maxbps = SUPPORTED_MAXBPS, |
282 | .formats = SUPPORTED_FORMATS, | 367 | .formats = SUPPORTED_FORMATS, |
283 | .ops = { | 368 | .ops = { |
284 | .open = nvhdmi_dig_playback_pcm_open, | 369 | .open = nvhdmi_dig_playback_pcm_open, |
285 | .close = nvhdmi_dig_playback_pcm_close_8ch, | 370 | .close = nvhdmi_dig_playback_pcm_close_8ch_7x, |
286 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch | 371 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch |
287 | }, | 372 | }, |
288 | }; | 373 | }; |
@@ -291,7 +376,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
291 | .substreams = 1, | 376 | .substreams = 1, |
292 | .channels_min = 2, | 377 | .channels_min = 2, |
293 | .channels_max = 2, | 378 | .channels_max = 2, |
294 | .nid = Nv_Master_Convert_nid, | 379 | .nid = nvhdmi_master_con_nid_7x, |
295 | .rates = SUPPORTED_RATES, | 380 | .rates = SUPPORTED_RATES, |
296 | .maxbps = SUPPORTED_MAXBPS, | 381 | .maxbps = SUPPORTED_MAXBPS, |
297 | .formats = SUPPORTED_FORMATS, | 382 | .formats = SUPPORTED_FORMATS, |
@@ -302,10 +387,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
302 | }, | 387 | }, |
303 | }; | 388 | }; |
304 | 389 | ||
305 | static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | 390 | static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) |
391 | { | ||
392 | struct hdmi_spec *spec = codec->spec; | ||
393 | struct hda_pcm *info = spec->pcm_rec; | ||
394 | int i; | ||
395 | |||
396 | codec->num_pcms = spec->num_cvts; | ||
397 | codec->pcm_info = info; | ||
398 | |||
399 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
400 | unsigned int chans; | ||
401 | |||
402 | chans = get_wcaps(codec, spec->cvt[i]); | ||
403 | chans = get_wcaps_channels(chans); | ||
404 | |||
405 | info->name = nvhdmi_pcm_names[i]; | ||
406 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
407 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
408 | = nvhdmi_pcm_digital_playback_8ch_89; | ||
409 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
410 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
411 | } | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) | ||
306 | { | 417 | { |
307 | struct nvhdmi_spec *spec = codec->spec; | 418 | struct hdmi_spec *spec = codec->spec; |
308 | struct hda_pcm *info = &spec->pcm_rec; | 419 | struct hda_pcm *info = spec->pcm_rec; |
309 | 420 | ||
310 | codec->num_pcms = 1; | 421 | codec->num_pcms = 1; |
311 | codec->pcm_info = info; | 422 | codec->pcm_info = info; |
@@ -313,15 +424,15 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | |||
313 | info->name = "NVIDIA HDMI"; | 424 | info->name = "NVIDIA HDMI"; |
314 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 425 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
315 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | 426 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] |
316 | = nvhdmi_pcm_digital_playback_8ch; | 427 | = nvhdmi_pcm_digital_playback_8ch_7x; |
317 | 428 | ||
318 | return 0; | 429 | return 0; |
319 | } | 430 | } |
320 | 431 | ||
321 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | 432 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) |
322 | { | 433 | { |
323 | struct nvhdmi_spec *spec = codec->spec; | 434 | struct hdmi_spec *spec = codec->spec; |
324 | struct hda_pcm *info = &spec->pcm_rec; | 435 | struct hda_pcm *info = spec->pcm_rec; |
325 | 436 | ||
326 | codec->num_pcms = 1; | 437 | codec->num_pcms = 1; |
327 | codec->pcm_info = info; | 438 | codec->pcm_info = info; |
@@ -334,14 +445,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | |||
334 | return 0; | 445 | return 0; |
335 | } | 446 | } |
336 | 447 | ||
337 | static void nvhdmi_free(struct hda_codec *codec) | 448 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { |
338 | { | 449 | .build_controls = nvhdmi_build_controls, |
339 | kfree(codec->spec); | 450 | .build_pcms = nvhdmi_build_pcms_8ch_89, |
340 | } | 451 | .init = nvhdmi_init, |
452 | .free = nvhdmi_free, | ||
453 | .unsol_event = hdmi_unsol_event, | ||
454 | }; | ||
341 | 455 | ||
342 | static struct hda_codec_ops nvhdmi_patch_ops_8ch = { | 456 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { |
343 | .build_controls = nvhdmi_build_controls, | 457 | .build_controls = nvhdmi_build_controls, |
344 | .build_pcms = nvhdmi_build_pcms_8ch, | 458 | .build_pcms = nvhdmi_build_pcms_8ch_7x, |
345 | .init = nvhdmi_init, | 459 | .init = nvhdmi_init, |
346 | .free = nvhdmi_free, | 460 | .free = nvhdmi_free, |
347 | }; | 461 | }; |
@@ -353,9 +467,36 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | |||
353 | .free = nvhdmi_free, | 467 | .free = nvhdmi_free, |
354 | }; | 468 | }; |
355 | 469 | ||
356 | static int patch_nvhdmi_8ch(struct hda_codec *codec) | 470 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) |
471 | { | ||
472 | struct hdmi_spec *spec; | ||
473 | int i; | ||
474 | |||
475 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
476 | if (spec == NULL) | ||
477 | return -ENOMEM; | ||
478 | |||
479 | codec->spec = spec; | ||
480 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; | ||
481 | |||
482 | if (hdmi_parse_codec(codec) < 0) { | ||
483 | codec->spec = NULL; | ||
484 | kfree(spec); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | codec->patch_ops = nvhdmi_patch_ops_8ch_89; | ||
488 | |||
489 | for (i = 0; i < spec->num_pins; i++) | ||
490 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
491 | |||
492 | init_channel_allocations(); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
357 | { | 498 | { |
358 | struct nvhdmi_spec *spec; | 499 | struct hdmi_spec *spec; |
359 | 500 | ||
360 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 501 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
361 | if (spec == NULL) | 502 | if (spec == NULL) |
@@ -365,16 +506,17 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec) | |||
365 | 506 | ||
366 | spec->multiout.num_dacs = 0; /* no analog */ | 507 | spec->multiout.num_dacs = 0; /* no analog */ |
367 | spec->multiout.max_channels = 8; | 508 | spec->multiout.max_channels = 8; |
368 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 509 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
510 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
369 | 511 | ||
370 | codec->patch_ops = nvhdmi_patch_ops_8ch; | 512 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; |
371 | 513 | ||
372 | return 0; | 514 | return 0; |
373 | } | 515 | } |
374 | 516 | ||
375 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | 517 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
376 | { | 518 | { |
377 | struct nvhdmi_spec *spec; | 519 | struct hdmi_spec *spec; |
378 | 520 | ||
379 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 521 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
380 | if (spec == NULL) | 522 | if (spec == NULL) |
@@ -384,7 +526,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
384 | 526 | ||
385 | spec->multiout.num_dacs = 0; /* no analog */ | 527 | spec->multiout.num_dacs = 0; /* no analog */ |
386 | spec->multiout.max_channels = 2; | 528 | spec->multiout.max_channels = 2; |
387 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 529 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
530 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
388 | 531 | ||
389 | codec->patch_ops = nvhdmi_patch_ops_2ch; | 532 | codec->patch_ops = nvhdmi_patch_ops_2ch; |
390 | 533 | ||
@@ -395,13 +538,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
395 | * patch entries | 538 | * patch entries |
396 | */ | 539 | */ |
397 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | 540 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { |
398 | { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
399 | { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
400 | { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
401 | { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
402 | { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch }, | ||
403 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 541 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
404 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 542 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
543 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", | ||
544 | .patch = patch_nvhdmi_8ch_7x }, | ||
545 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", | ||
546 | .patch = patch_nvhdmi_8ch_7x }, | ||
547 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", | ||
548 | .patch = patch_nvhdmi_8ch_7x }, | ||
549 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", | ||
550 | .patch = patch_nvhdmi_8ch_7x }, | ||
551 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", | ||
552 | .patch = patch_nvhdmi_8ch_7x }, | ||
553 | { .id = 0x10de000c, .name = "MCP89 HDMI", | ||
554 | .patch = patch_nvhdmi_8ch_89 }, | ||
555 | { .id = 0x10de000b, .name = "GT21x HDMI", | ||
556 | .patch = patch_nvhdmi_8ch_89 }, | ||
557 | { .id = 0x10de000d, .name = "GT240 HDMI", | ||
558 | .patch = patch_nvhdmi_8ch_89 }, | ||
405 | {} /* terminator */ | 559 | {} /* terminator */ |
406 | }; | 560 | }; |
407 | 561 | ||
@@ -412,9 +566,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"); | |||
412 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | 566 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); |
413 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 567 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
414 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 568 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
569 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
570 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
571 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
415 | 572 | ||
416 | MODULE_LICENSE("GPL"); | 573 | MODULE_LICENSE("GPL"); |
417 | MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); | 574 | MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); |
418 | 575 | ||
419 | static struct hda_codec_preset_list nvhdmi_list = { | 576 | static struct hda_codec_preset_list nvhdmi_list = { |
420 | .preset = snd_hda_preset_nvhdmi, | 577 | .preset = snd_hda_preset_nvhdmi, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e8cbe216e912..5d2fbb87b871 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -4915,7 +4915,7 @@ static void fixup_automic_adc(struct hda_codec *codec) | |||
4915 | static void fixup_single_adc(struct hda_codec *codec) | 4915 | static void fixup_single_adc(struct hda_codec *codec) |
4916 | { | 4916 | { |
4917 | struct alc_spec *spec = codec->spec; | 4917 | struct alc_spec *spec = codec->spec; |
4918 | hda_nid_t pin; | 4918 | hda_nid_t pin = 0; |
4919 | int i; | 4919 | int i; |
4920 | 4920 | ||
4921 | /* search for the input pin; there must be only one */ | 4921 | /* search for the input pin; there must be only one */ |
@@ -13561,6 +13561,8 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec, | |||
13561 | static void alc269_quanta_fl1_setup(struct hda_codec *codec) | 13561 | static void alc269_quanta_fl1_setup(struct hda_codec *codec) |
13562 | { | 13562 | { |
13563 | struct alc_spec *spec = codec->spec; | 13563 | struct alc_spec *spec = codec->spec; |
13564 | spec->autocfg.hp_pins[0] = 0x15; | ||
13565 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13564 | spec->ext_mic.pin = 0x18; | 13566 | spec->ext_mic.pin = 0x18; |
13565 | spec->ext_mic.mux_idx = 0; | 13567 | spec->ext_mic.mux_idx = 0; |
13566 | spec->int_mic.pin = 0x19; | 13568 | spec->int_mic.pin = 0x19; |
@@ -13656,6 +13658,8 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec, | |||
13656 | static void alc269_laptop_dmic_setup(struct hda_codec *codec) | 13658 | static void alc269_laptop_dmic_setup(struct hda_codec *codec) |
13657 | { | 13659 | { |
13658 | struct alc_spec *spec = codec->spec; | 13660 | struct alc_spec *spec = codec->spec; |
13661 | spec->autocfg.hp_pins[0] = 0x15; | ||
13662 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13659 | spec->ext_mic.pin = 0x18; | 13663 | spec->ext_mic.pin = 0x18; |
13660 | spec->ext_mic.mux_idx = 0; | 13664 | spec->ext_mic.mux_idx = 0; |
13661 | spec->int_mic.pin = 0x12; | 13665 | spec->int_mic.pin = 0x12; |
@@ -13666,6 +13670,8 @@ static void alc269_laptop_dmic_setup(struct hda_codec *codec) | |||
13666 | static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) | 13670 | static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) |
13667 | { | 13671 | { |
13668 | struct alc_spec *spec = codec->spec; | 13672 | struct alc_spec *spec = codec->spec; |
13673 | spec->autocfg.hp_pins[0] = 0x15; | ||
13674 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13669 | spec->ext_mic.pin = 0x18; | 13675 | spec->ext_mic.pin = 0x18; |
13670 | spec->ext_mic.mux_idx = 0; | 13676 | spec->ext_mic.mux_idx = 0; |
13671 | spec->int_mic.pin = 0x12; | 13677 | spec->int_mic.pin = 0x12; |
@@ -13676,6 +13682,8 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) | |||
13676 | static void alc269_laptop_amic_setup(struct hda_codec *codec) | 13682 | static void alc269_laptop_amic_setup(struct hda_codec *codec) |
13677 | { | 13683 | { |
13678 | struct alc_spec *spec = codec->spec; | 13684 | struct alc_spec *spec = codec->spec; |
13685 | spec->autocfg.hp_pins[0] = 0x15; | ||
13686 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13679 | spec->ext_mic.pin = 0x18; | 13687 | spec->ext_mic.pin = 0x18; |
13680 | spec->ext_mic.mux_idx = 0; | 13688 | spec->ext_mic.mux_idx = 0; |
13681 | spec->int_mic.pin = 0x19; | 13689 | spec->int_mic.pin = 0x19; |
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 7754db166d9e..dbc4b89d74e4 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
@@ -68,7 +68,7 @@ static void wm8776_write(struct oxygen *chip, | |||
68 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, | 68 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, |
69 | (reg << 9) | value); | 69 | (reg << 9) | value); |
70 | if (reg < ARRAY_SIZE(data->wm8776_regs)) { | 70 | if (reg < ARRAY_SIZE(data->wm8776_regs)) { |
71 | if (reg >= WM8776_HPLVOL || reg <= WM8776_DACMASTER) | 71 | if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) |
72 | value &= ~WM8776_UPDATE; | 72 | value &= ~WM8776_UPDATE; |
73 | data->wm8776_regs[reg] = value; | 73 | data->wm8776_regs[reg] = value; |
74 | } | 74 | } |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 960a227eb653..ad4462677615 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -1974,9 +1974,9 @@ snd_riptide_proc_read(struct snd_info_entry *entry, | |||
1974 | } | 1974 | } |
1975 | snd_iprintf(buffer, "Paths:\n"); | 1975 | snd_iprintf(buffer, "Paths:\n"); |
1976 | i = getpaths(cif, p); | 1976 | i = getpaths(cif, p); |
1977 | while (i--) { | 1977 | while (i >= 2) { |
1978 | snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]); | 1978 | i -= 2; |
1979 | i--; | 1979 | snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]); |
1980 | } | 1980 | } |
1981 | snd_iprintf(buffer, "\n"); | 1981 | snd_iprintf(buffer, "\n"); |
1982 | } | 1982 | } |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index b9ef7e45891d..b68d99fb6af0 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -90,12 +90,10 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, | |||
90 | if (reg >= codec->reg_cache_size) | 90 | if (reg >= codec->reg_cache_size) |
91 | return -EINVAL; | 91 | return -EINVAL; |
92 | 92 | ||
93 | reg &= AK4104_REG_MASK; | ||
94 | reg |= AK4104_WRITE; | ||
95 | |||
96 | /* only write to the hardware if value has changed */ | 93 | /* only write to the hardware if value has changed */ |
97 | if (cache[reg] != value) { | 94 | if (cache[reg] != value) { |
98 | u8 tmp[2] = { reg, value }; | 95 | u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value }; |
96 | |||
99 | if (spi_write(spi, tmp, sizeof(tmp))) { | 97 | if (spi_write(spi, tmp, sizeof(tmp))) { |
100 | dev_err(&spi->dev, "SPI write failed\n"); | 98 | dev_err(&spi->dev, "SPI write failed\n"); |
101 | return -EIO; | 99 | return -EIO; |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a03bac943aaf..c8b0556ef431 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -427,24 +427,24 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
427 | if (!runtime->hw.rates) { | 427 | if (!runtime->hw.rates) { |
428 | printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", | 428 | printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", |
429 | codec_dai->name, cpu_dai->name); | 429 | codec_dai->name, cpu_dai->name); |
430 | goto machine_err; | 430 | goto config_err; |
431 | } | 431 | } |
432 | if (!runtime->hw.formats) { | 432 | if (!runtime->hw.formats) { |
433 | printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", | 433 | printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", |
434 | codec_dai->name, cpu_dai->name); | 434 | codec_dai->name, cpu_dai->name); |
435 | goto machine_err; | 435 | goto config_err; |
436 | } | 436 | } |
437 | if (!runtime->hw.channels_min || !runtime->hw.channels_max) { | 437 | if (!runtime->hw.channels_min || !runtime->hw.channels_max) { |
438 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", | 438 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", |
439 | codec_dai->name, cpu_dai->name); | 439 | codec_dai->name, cpu_dai->name); |
440 | goto machine_err; | 440 | goto config_err; |
441 | } | 441 | } |
442 | 442 | ||
443 | /* Symmetry only applies if we've already got an active stream. */ | 443 | /* Symmetry only applies if we've already got an active stream. */ |
444 | if (cpu_dai->active || codec_dai->active) { | 444 | if (cpu_dai->active || codec_dai->active) { |
445 | ret = soc_pcm_apply_symmetry(substream); | 445 | ret = soc_pcm_apply_symmetry(substream); |
446 | if (ret != 0) | 446 | if (ret != 0) |
447 | goto machine_err; | 447 | goto config_err; |
448 | } | 448 | } |
449 | 449 | ||
450 | pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); | 450 | pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); |
@@ -464,10 +464,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
464 | mutex_unlock(&pcm_mutex); | 464 | mutex_unlock(&pcm_mutex); |
465 | return 0; | 465 | return 0; |
466 | 466 | ||
467 | machine_err: | 467 | config_err: |
468 | if (machine->ops && machine->ops->shutdown) | 468 | if (machine->ops && machine->ops->shutdown) |
469 | machine->ops->shutdown(substream); | 469 | machine->ops->shutdown(substream); |
470 | 470 | ||
471 | machine_err: | ||
472 | if (codec_dai->ops->shutdown) | ||
473 | codec_dai->ops->shutdown(substream, codec_dai); | ||
474 | |||
471 | codec_dai_err: | 475 | codec_dai_err: |
472 | if (platform->pcm_ops->close) | 476 | if (platform->pcm_ops->close) |
473 | platform->pcm_ops->close(substream); | 477 | platform->pcm_ops->close(substream); |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 8c2925814ce4..c570ae3e6d55 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -22,13 +22,13 @@ config SND_USB_AUDIO | |||
22 | will be called snd-usb-audio. | 22 | will be called snd-usb-audio. |
23 | 23 | ||
24 | config SND_USB_UA101 | 24 | config SND_USB_UA101 |
25 | tristate "Edirol UA-101 driver (EXPERIMENTAL)" | 25 | tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)" |
26 | depends on EXPERIMENTAL | 26 | depends on EXPERIMENTAL |
27 | select SND_PCM | 27 | select SND_PCM |
28 | select SND_RAWMIDI | 28 | select SND_RAWMIDI |
29 | help | 29 | help |
30 | Say Y here to include support for the Edirol UA-101 audio/MIDI | 30 | Say Y here to include support for the Edirol UA-101 and UA-1000 |
31 | interface. | 31 | audio/MIDI interfaces. |
32 | 32 | ||
33 | To compile this driver as a module, choose M here: the module | 33 | To compile this driver as a module, choose M here: the module |
34 | will be called snd-ua101. | 34 | will be called snd-ua101. |
diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h index 9d16db027fc3..380f984babc9 100644 --- a/sound/usb/caiaq/midi.h +++ b/sound/usb/caiaq/midi.h | |||
@@ -3,6 +3,6 @@ | |||
3 | 3 | ||
4 | int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); | 4 | int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); |
5 | void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); | 5 | void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); |
6 | void snd_usb_caiaq_midi_output_done(struct urb* urb); | 6 | void snd_usb_caiaq_midi_output_done(struct urb *urb); |
7 | 7 | ||
8 | #endif /* CAIAQ_MIDI_H */ | 8 | #endif /* CAIAQ_MIDI_H */ |
diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c index 4f4ccdf70dd0..3d458d3b9962 100644 --- a/sound/usb/ua101.c +++ b/sound/usb/ua101.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Edirol UA-101 driver | 2 | * Edirol UA-101/UA-1000 driver |
3 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | 3 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
4 | * | 4 | * |
5 | * This driver is free software: you can redistribute it and/or modify | 5 | * This driver is free software: you can redistribute it and/or modify |
@@ -25,13 +25,10 @@ | |||
25 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
26 | #include "usbaudio.h" | 26 | #include "usbaudio.h" |
27 | 27 | ||
28 | MODULE_DESCRIPTION("Edirol UA-101 driver"); | 28 | MODULE_DESCRIPTION("Edirol UA-101/1000 driver"); |
29 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 29 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
30 | MODULE_LICENSE("GPL v2"); | 30 | MODULE_LICENSE("GPL v2"); |
31 | MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}"); | 31 | MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); |
32 | |||
33 | /* I use my UA-1A for testing because I don't have a UA-101 ... */ | ||
34 | #define UA1A_HACK | ||
35 | 32 | ||
36 | /* | 33 | /* |
37 | * Should not be lower than the minimum scheduling delay of the host | 34 | * Should not be lower than the minimum scheduling delay of the host |
@@ -132,9 +129,6 @@ struct ua101 { | |||
132 | dma_addr_t dma; | 129 | dma_addr_t dma; |
133 | } buffers[MAX_MEMORY_BUFFERS]; | 130 | } buffers[MAX_MEMORY_BUFFERS]; |
134 | } capture, playback; | 131 | } capture, playback; |
135 | |||
136 | unsigned int fps[10]; | ||
137 | unsigned int frame_counter; | ||
138 | }; | 132 | }; |
139 | 133 | ||
140 | static DEFINE_MUTEX(devices_mutex); | 134 | static DEFINE_MUTEX(devices_mutex); |
@@ -424,16 +418,6 @@ static void capture_urb_complete(struct urb *urb) | |||
424 | if (do_period_elapsed) | 418 | if (do_period_elapsed) |
425 | snd_pcm_period_elapsed(stream->substream); | 419 | snd_pcm_period_elapsed(stream->substream); |
426 | 420 | ||
427 | /* for debugging: measure the sample rate relative to the USB clock */ | ||
428 | ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames; | ||
429 | if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) { | ||
430 | printk(KERN_DEBUG "capture rate:"); | ||
431 | for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames) | ||
432 | printk(KERN_CONT " %u", ua->fps[frames]); | ||
433 | printk(KERN_CONT "\n"); | ||
434 | memset(ua->fps, 0, sizeof(ua->fps)); | ||
435 | ua->frame_counter = 0; | ||
436 | } | ||
437 | return; | 421 | return; |
438 | 422 | ||
439 | stream_stopped: | 423 | stream_stopped: |
@@ -1200,13 +1184,30 @@ static int ua101_probe(struct usb_interface *interface, | |||
1200 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 1184 | .type = QUIRK_MIDI_FIXED_ENDPOINT, |
1201 | .data = &midi_ep | 1185 | .data = &midi_ep |
1202 | }; | 1186 | }; |
1187 | static const int intf_numbers[2][3] = { | ||
1188 | { /* UA-101 */ | ||
1189 | [INTF_PLAYBACK] = 0, | ||
1190 | [INTF_CAPTURE] = 1, | ||
1191 | [INTF_MIDI] = 2, | ||
1192 | }, | ||
1193 | { /* UA-1000 */ | ||
1194 | [INTF_CAPTURE] = 1, | ||
1195 | [INTF_PLAYBACK] = 2, | ||
1196 | [INTF_MIDI] = 3, | ||
1197 | }, | ||
1198 | }; | ||
1203 | struct snd_card *card; | 1199 | struct snd_card *card; |
1204 | struct ua101 *ua; | 1200 | struct ua101 *ua; |
1205 | unsigned int card_index, i; | 1201 | unsigned int card_index, i; |
1202 | int is_ua1000; | ||
1203 | const char *name; | ||
1206 | char usb_path[32]; | 1204 | char usb_path[32]; |
1207 | int err; | 1205 | int err; |
1208 | 1206 | ||
1209 | if (interface->altsetting->desc.bInterfaceNumber != 0) | 1207 | is_ua1000 = usb_id->idProduct == 0x0044; |
1208 | |||
1209 | if (interface->altsetting->desc.bInterfaceNumber != | ||
1210 | intf_numbers[is_ua1000][0]) | ||
1210 | return -ENODEV; | 1211 | return -ENODEV; |
1211 | 1212 | ||
1212 | mutex_lock(&devices_mutex); | 1213 | mutex_lock(&devices_mutex); |
@@ -1239,20 +1240,13 @@ static int ua101_probe(struct usb_interface *interface, | |||
1239 | init_waitqueue_head(&ua->rate_feedback_wait); | 1240 | init_waitqueue_head(&ua->rate_feedback_wait); |
1240 | init_waitqueue_head(&ua->alsa_playback_wait); | 1241 | init_waitqueue_head(&ua->alsa_playback_wait); |
1241 | 1242 | ||
1242 | #ifdef UA1A_HACK | ||
1243 | if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { | ||
1244 | ua->intf[2] = interface; | ||
1245 | ua->intf[0] = usb_ifnum_to_if(ua->dev, 1); | ||
1246 | ua->intf[1] = usb_ifnum_to_if(ua->dev, 2); | ||
1247 | usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua); | ||
1248 | usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua); | ||
1249 | } else { | ||
1250 | #endif | ||
1251 | ua->intf[0] = interface; | 1243 | ua->intf[0] = interface; |
1252 | for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { | 1244 | for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { |
1253 | ua->intf[i] = usb_ifnum_to_if(ua->dev, i); | 1245 | ua->intf[i] = usb_ifnum_to_if(ua->dev, |
1246 | intf_numbers[is_ua1000][i]); | ||
1254 | if (!ua->intf[i]) { | 1247 | if (!ua->intf[i]) { |
1255 | dev_err(&ua->dev->dev, "interface %u not found\n", i); | 1248 | dev_err(&ua->dev->dev, "interface %u not found\n", |
1249 | intf_numbers[is_ua1000][i]); | ||
1256 | err = -ENXIO; | 1250 | err = -ENXIO; |
1257 | goto probe_error; | 1251 | goto probe_error; |
1258 | } | 1252 | } |
@@ -1264,39 +1258,19 @@ static int ua101_probe(struct usb_interface *interface, | |||
1264 | goto probe_error; | 1258 | goto probe_error; |
1265 | } | 1259 | } |
1266 | } | 1260 | } |
1267 | #ifdef UA1A_HACK | ||
1268 | } | ||
1269 | #endif | ||
1270 | 1261 | ||
1271 | snd_card_set_dev(card, &interface->dev); | 1262 | snd_card_set_dev(card, &interface->dev); |
1272 | 1263 | ||
1273 | #ifdef UA1A_HACK | ||
1274 | if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { | ||
1275 | ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE; | ||
1276 | ua->rate = 44100; | ||
1277 | ua->packets_per_second = 1000; | ||
1278 | ua->capture.channels = 2; | ||
1279 | ua->playback.channels = 2; | ||
1280 | ua->capture.frame_bytes = 4; | ||
1281 | ua->playback.frame_bytes = 4; | ||
1282 | ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2); | ||
1283 | ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1); | ||
1284 | ua->capture.max_packet_bytes = 192; | ||
1285 | ua->playback.max_packet_bytes = 192; | ||
1286 | } else { | ||
1287 | #endif | ||
1288 | err = detect_usb_format(ua); | 1264 | err = detect_usb_format(ua); |
1289 | if (err < 0) | 1265 | if (err < 0) |
1290 | goto probe_error; | 1266 | goto probe_error; |
1291 | #ifdef UA1A_HACK | ||
1292 | } | ||
1293 | #endif | ||
1294 | 1267 | ||
1268 | name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101"; | ||
1295 | strcpy(card->driver, "UA-101"); | 1269 | strcpy(card->driver, "UA-101"); |
1296 | strcpy(card->shortname, "UA-101"); | 1270 | strcpy(card->shortname, name); |
1297 | usb_make_path(ua->dev, usb_path, sizeof(usb_path)); | 1271 | usb_make_path(ua->dev, usb_path, sizeof(usb_path)); |
1298 | snprintf(ua->card->longname, sizeof(ua->card->longname), | 1272 | snprintf(ua->card->longname, sizeof(ua->card->longname), |
1299 | "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed", | 1273 | "EDIROL %s (serial %s), %u Hz at %s, %s speed", name, |
1300 | ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, | 1274 | ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, |
1301 | ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); | 1275 | ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); |
1302 | 1276 | ||
@@ -1314,24 +1288,18 @@ static int ua101_probe(struct usb_interface *interface, | |||
1314 | if (err < 0) | 1288 | if (err < 0) |
1315 | goto probe_error; | 1289 | goto probe_error; |
1316 | 1290 | ||
1317 | err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm); | 1291 | err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm); |
1318 | if (err < 0) | 1292 | if (err < 0) |
1319 | goto probe_error; | 1293 | goto probe_error; |
1320 | ua->pcm->private_data = ua; | 1294 | ua->pcm->private_data = ua; |
1321 | strcpy(ua->pcm->name, "UA-101"); | 1295 | strcpy(ua->pcm->name, name); |
1322 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); | 1296 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); |
1323 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); | 1297 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); |
1324 | 1298 | ||
1325 | #ifdef UA1A_HACK | ||
1326 | if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) { | ||
1327 | #endif | ||
1328 | err = snd_usbmidi_create(card, ua->intf[INTF_MIDI], | 1299 | err = snd_usbmidi_create(card, ua->intf[INTF_MIDI], |
1329 | &ua->midi_list, &midi_quirk); | 1300 | &ua->midi_list, &midi_quirk); |
1330 | if (err < 0) | 1301 | if (err < 0) |
1331 | goto probe_error; | 1302 | goto probe_error; |
1332 | #ifdef UA1A_HACK | ||
1333 | } | ||
1334 | #endif | ||
1335 | 1303 | ||
1336 | err = snd_card_register(card); | 1304 | err = snd_card_register(card); |
1337 | if (err < 0) | 1305 | if (err < 0) |
@@ -1386,11 +1354,9 @@ static void ua101_disconnect(struct usb_interface *interface) | |||
1386 | } | 1354 | } |
1387 | 1355 | ||
1388 | static struct usb_device_id ua101_ids[] = { | 1356 | static struct usb_device_id ua101_ids[] = { |
1389 | #ifdef UA1A_HACK | 1357 | { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */ |
1390 | { USB_DEVICE(0x0582, 0x0018) }, | 1358 | { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */ |
1391 | #endif | 1359 | { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */ |
1392 | { USB_DEVICE(0x0582, 0x007d) }, | ||
1393 | { USB_DEVICE(0x0582, 0x008d) }, | ||
1394 | { } | 1360 | { } |
1395 | }; | 1361 | }; |
1396 | MODULE_DEVICE_TABLE(usb, ua101_ids); | 1362 | MODULE_DEVICE_TABLE(usb, ua101_ids); |
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c539f7fe292f..11b0826b8fe6 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -2483,7 +2483,6 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, | |||
2483 | sample_width, sample_bytes); | 2483 | sample_width, sample_bytes); |
2484 | } | 2484 | } |
2485 | /* check the format byte size */ | 2485 | /* check the format byte size */ |
2486 | printk(" XXXXX SAMPLE BYTES %d\n", sample_bytes); | ||
2487 | switch (sample_bytes) { | 2486 | switch (sample_bytes) { |
2488 | case 1: | 2487 | case 1: |
2489 | pcm_format = SNDRV_PCM_FORMAT_S8; | 2488 | pcm_format = SNDRV_PCM_FORMAT_S8; |
@@ -2581,6 +2580,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof | |||
2581 | chip->usb_id == USB_ID(0x0d8c, 0x0102)) && | 2580 | chip->usb_id == USB_ID(0x0d8c, 0x0102)) && |
2582 | fp->altsetting == 5 && fp->maxpacksize == 392) | 2581 | fp->altsetting == 5 && fp->maxpacksize == 392) |
2583 | rate = 96000; | 2582 | rate = 96000; |
2583 | /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */ | ||
2584 | if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068)) | ||
2585 | rate = 8000; | ||
2584 | fp->rate_table[fp->nr_rates] = rate; | 2586 | fp->rate_table[fp->nr_rates] = rate; |
2585 | if (!fp->rate_min || rate < fp->rate_min) | 2587 | if (!fp->rate_min || rate < fp->rate_min) |
2586 | fp->rate_min = rate; | 2588 | fp->rate_min = rate; |
@@ -3386,58 +3388,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, | |||
3386 | return 0; | 3388 | return 0; |
3387 | } | 3389 | } |
3388 | 3390 | ||
3389 | /* | ||
3390 | * Create a stream for an Edirol UA-1000 interface. | ||
3391 | */ | ||
3392 | static int create_ua1000_quirk(struct snd_usb_audio *chip, | ||
3393 | struct usb_interface *iface, | ||
3394 | const struct snd_usb_audio_quirk *quirk) | ||
3395 | { | ||
3396 | static const struct audioformat ua1000_format = { | ||
3397 | .format = SNDRV_PCM_FORMAT_S32_LE, | ||
3398 | .fmt_type = UAC_FORMAT_TYPE_I, | ||
3399 | .altsetting = 1, | ||
3400 | .altset_idx = 1, | ||
3401 | .attributes = 0, | ||
3402 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
3403 | }; | ||
3404 | struct usb_host_interface *alts; | ||
3405 | struct usb_interface_descriptor *altsd; | ||
3406 | struct audioformat *fp; | ||
3407 | int stream, err; | ||
3408 | |||
3409 | if (iface->num_altsetting != 2) | ||
3410 | return -ENXIO; | ||
3411 | alts = &iface->altsetting[1]; | ||
3412 | altsd = get_iface_desc(alts); | ||
3413 | if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE || | ||
3414 | altsd->bNumEndpoints != 1) | ||
3415 | return -ENXIO; | ||
3416 | |||
3417 | fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL); | ||
3418 | if (!fp) | ||
3419 | return -ENOMEM; | ||
3420 | |||
3421 | fp->channels = alts->extra[4]; | ||
3422 | fp->iface = altsd->bInterfaceNumber; | ||
3423 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | ||
3424 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | ||
3425 | fp->datainterval = parse_datainterval(chip, alts); | ||
3426 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | ||
3427 | fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); | ||
3428 | |||
3429 | stream = (fp->endpoint & USB_DIR_IN) | ||
3430 | ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | ||
3431 | err = add_audio_endpoint(chip, stream, fp); | ||
3432 | if (err < 0) { | ||
3433 | kfree(fp); | ||
3434 | return err; | ||
3435 | } | ||
3436 | /* FIXME: playback must be synchronized to capture */ | ||
3437 | usb_set_interface(chip->dev, fp->iface, 0); | ||
3438 | return 0; | ||
3439 | } | ||
3440 | |||
3441 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, | 3391 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, |
3442 | struct usb_interface *iface, | 3392 | struct usb_interface *iface, |
3443 | const struct snd_usb_audio_quirk *quirk); | 3393 | const struct snd_usb_audio_quirk *quirk); |
@@ -3686,7 +3636,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
3686 | [QUIRK_MIDI_CME] = create_any_midi_quirk, | 3636 | [QUIRK_MIDI_CME] = create_any_midi_quirk, |
3687 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, | 3637 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, |
3688 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, | 3638 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
3689 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, | ||
3690 | [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, | 3639 | [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, |
3691 | [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk | 3640 | [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk |
3692 | }; | 3641 | }; |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 6b016d4aac6b..42c299cbf63a 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -75,7 +75,6 @@ enum quirk_type { | |||
75 | QUIRK_MIDI_US122L, | 75 | QUIRK_MIDI_US122L, |
76 | QUIRK_AUDIO_STANDARD_INTERFACE, | 76 | QUIRK_AUDIO_STANDARD_INTERFACE, |
77 | QUIRK_AUDIO_FIXED_ENDPOINT, | 77 | QUIRK_AUDIO_FIXED_ENDPOINT, |
78 | QUIRK_AUDIO_EDIROL_UA1000, | ||
79 | QUIRK_AUDIO_EDIROL_UAXX, | 78 | QUIRK_AUDIO_EDIROL_UAXX, |
80 | QUIRK_AUDIO_ALIGN_TRANSFER, | 79 | QUIRK_AUDIO_ALIGN_TRANSFER, |
81 | 80 | ||
@@ -112,7 +111,7 @@ struct snd_usb_midi_endpoint_info { | |||
112 | 111 | ||
113 | /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ | 112 | /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ |
114 | 113 | ||
115 | /* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ | 114 | /* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */ |
116 | 115 | ||
117 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ | 116 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ |
118 | 117 | ||
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index f06faf7917b9..2b426c1fd0e8 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -1016,36 +1016,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1016 | } | 1016 | } |
1017 | }, | 1017 | }, |
1018 | { | 1018 | { |
1019 | USB_DEVICE(0x0582, 0x0044), | ||
1020 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1021 | .vendor_name = "Roland", | ||
1022 | .product_name = "UA-1000", | ||
1023 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1024 | .type = QUIRK_COMPOSITE, | ||
1025 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1026 | { | ||
1027 | .ifnum = 1, | ||
1028 | .type = QUIRK_AUDIO_EDIROL_UA1000 | ||
1029 | }, | ||
1030 | { | ||
1031 | .ifnum = 2, | ||
1032 | .type = QUIRK_AUDIO_EDIROL_UA1000 | ||
1033 | }, | ||
1034 | { | ||
1035 | .ifnum = 3, | ||
1036 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1037 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1038 | .out_cables = 0x0003, | ||
1039 | .in_cables = 0x0003 | ||
1040 | } | ||
1041 | }, | ||
1042 | { | ||
1043 | .ifnum = -1 | ||
1044 | } | ||
1045 | } | ||
1046 | } | ||
1047 | }, | ||
1048 | { | ||
1049 | /* has ID 0x0049 when not in "Advanced Driver" mode */ | 1019 | /* has ID 0x0049 when not in "Advanced Driver" mode */ |
1050 | USB_DEVICE(0x0582, 0x0047), | 1020 | USB_DEVICE(0x0582, 0x0047), |
1051 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1021 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |