diff options
500 files changed, 12886 insertions, 5602 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 1977fab38656..6de71308a906 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
| @@ -361,8 +361,6 @@ telephony/ | |||
| 361 | - directory with info on telephony (e.g. voice over IP) support. | 361 | - directory with info on telephony (e.g. voice over IP) support. |
| 362 | time_interpolators.txt | 362 | time_interpolators.txt |
| 363 | - info on time interpolators. | 363 | - info on time interpolators. |
| 364 | tipar.txt | ||
| 365 | - information about Parallel link cable for Texas Instruments handhelds. | ||
| 366 | tty.txt | 364 | tty.txt |
| 367 | - guide to the locking policies of the tty layer. | 365 | - guide to the locking policies of the tty layer. |
| 368 | uml/ | 366 | uml/ |
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 6caa14615578..1875e502f872 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle | |||
| @@ -474,25 +474,29 @@ make a good program). | |||
| 474 | So, you can either get rid of GNU emacs, or change it to use saner | 474 | So, you can either get rid of GNU emacs, or change it to use saner |
| 475 | values. To do the latter, you can stick the following in your .emacs file: | 475 | values. To do the latter, you can stick the following in your .emacs file: |
| 476 | 476 | ||
| 477 | (defun linux-c-mode () | 477 | (defun c-lineup-arglist-tabs-only (ignored) |
| 478 | "C mode with adjusted defaults for use with the Linux kernel." | 478 | "Line up argument lists by tabs, not spaces" |
| 479 | (interactive) | 479 | (let* ((anchor (c-langelem-pos c-syntactic-element)) |
| 480 | (c-mode) | 480 | (column (c-langelem-2nd-pos c-syntactic-element)) |
| 481 | (c-set-style "K&R") | 481 | (offset (- (1+ column) anchor)) |
| 482 | (setq tab-width 8) | 482 | (steps (floor offset c-basic-offset))) |
| 483 | (setq indent-tabs-mode t) | 483 | (* (max steps 1) |
| 484 | (setq c-basic-offset 8)) | 484 | c-basic-offset))) |
| 485 | 485 | ||
| 486 | This will define the M-x linux-c-mode command. When hacking on a | 486 | (add-hook 'c-mode-hook |
| 487 | module, if you put the string -*- linux-c -*- somewhere on the first | 487 | (lambda () |
| 488 | two lines, this mode will be automatically invoked. Also, you may want | 488 | (let ((filename (buffer-file-name))) |
| 489 | to add | 489 | ;; Enable kernel mode for the appropriate files |
| 490 | 490 | (when (and filename | |
| 491 | (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) | 491 | (string-match "~/src/linux-trees" filename)) |
| 492 | auto-mode-alist)) | 492 | (setq indent-tabs-mode t) |
| 493 | 493 | (c-set-style "linux") | |
| 494 | to your .emacs file if you want to have linux-c-mode switched on | 494 | (c-set-offset 'arglist-cont-nonempty |
| 495 | automagically when you edit source files under /usr/src/linux. | 495 | '(c-lineup-gcc-asm-reg |
| 496 | c-lineup-arglist-tabs-only)))))) | ||
| 497 | |||
| 498 | This will make emacs go better with the kernel coding style for C | ||
| 499 | files below ~/src/linux-trees. | ||
| 496 | 500 | ||
| 497 | But even if you fail in getting emacs to do sane formatting, not | 501 | But even if you fail in getting emacs to do sane formatting, not |
| 498 | everything is lost: use "indent". | 502 | everything is lost: use "indent". |
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl index 1fd6a1ec7591..8a5dc6e021ff 100644 --- a/Documentation/DocBook/procfs-guide.tmpl +++ b/Documentation/DocBook/procfs-guide.tmpl | |||
| @@ -29,12 +29,12 @@ | |||
| 29 | 29 | ||
| 30 | <revhistory> | 30 | <revhistory> |
| 31 | <revision> | 31 | <revision> |
| 32 | <revnumber>1.0 </revnumber> | 32 | <revnumber>1.0</revnumber> |
| 33 | <date>May 30, 2001</date> | 33 | <date>May 30, 2001</date> |
| 34 | <revremark>Initial revision posted to linux-kernel</revremark> | 34 | <revremark>Initial revision posted to linux-kernel</revremark> |
| 35 | </revision> | 35 | </revision> |
| 36 | <revision> | 36 | <revision> |
| 37 | <revnumber>1.1 </revnumber> | 37 | <revnumber>1.1</revnumber> |
| 38 | <date>June 3, 2001</date> | 38 | <date>June 3, 2001</date> |
| 39 | <revremark>Revised after comments from linux-kernel</revremark> | 39 | <revremark>Revised after comments from linux-kernel</revremark> |
| 40 | </revision> | 40 | </revision> |
diff --git a/Documentation/accounting/delay-accounting.txt b/Documentation/accounting/delay-accounting.txt index 1443cd71d263..8a12f0730c94 100644 --- a/Documentation/accounting/delay-accounting.txt +++ b/Documentation/accounting/delay-accounting.txt | |||
| @@ -11,6 +11,7 @@ the delays experienced by a task while | |||
| 11 | a) waiting for a CPU (while being runnable) | 11 | a) waiting for a CPU (while being runnable) |
| 12 | b) completion of synchronous block I/O initiated by the task | 12 | b) completion of synchronous block I/O initiated by the task |
| 13 | c) swapping in pages | 13 | c) swapping in pages |
| 14 | d) memory reclaim | ||
| 14 | 15 | ||
| 15 | and makes these statistics available to userspace through | 16 | and makes these statistics available to userspace through |
| 16 | the taskstats interface. | 17 | the taskstats interface. |
| @@ -41,7 +42,7 @@ this structure. See | |||
| 41 | include/linux/taskstats.h | 42 | include/linux/taskstats.h |
| 42 | for a description of the fields pertaining to delay accounting. | 43 | for a description of the fields pertaining to delay accounting. |
| 43 | It will generally be in the form of counters returning the cumulative | 44 | It will generally be in the form of counters returning the cumulative |
| 44 | delay seen for cpu, sync block I/O, swapin etc. | 45 | delay seen for cpu, sync block I/O, swapin, memory reclaim etc. |
| 45 | 46 | ||
| 46 | Taking the difference of two successive readings of a given | 47 | Taking the difference of two successive readings of a given |
| 47 | counter (say cpu_delay_total) for a task will give the delay | 48 | counter (say cpu_delay_total) for a task will give the delay |
| @@ -94,7 +95,9 @@ CPU count real total virtual total delay total | |||
| 94 | 7876 92005750 100000000 24001500 | 95 | 7876 92005750 100000000 24001500 |
| 95 | IO count delay total | 96 | IO count delay total |
| 96 | 0 0 | 97 | 0 0 |
| 97 | MEM count delay total | 98 | SWAP count delay total |
| 99 | 0 0 | ||
| 100 | RECLAIM count delay total | ||
| 98 | 0 0 | 101 | 0 0 |
| 99 | 102 | ||
| 100 | Get delays seen in executing a given simple command | 103 | Get delays seen in executing a given simple command |
| @@ -108,5 +111,7 @@ CPU count real total virtual total delay total | |||
| 108 | 6 4000250 4000000 0 | 111 | 6 4000250 4000000 0 |
| 109 | IO count delay total | 112 | IO count delay total |
| 110 | 0 0 | 113 | 0 0 |
| 111 | MEM count delay total | 114 | SWAP count delay total |
| 115 | 0 0 | ||
| 116 | RECLAIM count delay total | ||
| 112 | 0 0 | 117 | 0 0 |
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c index 40121b5cca14..3f7755f3963f 100644 --- a/Documentation/accounting/getdelays.c +++ b/Documentation/accounting/getdelays.c | |||
| @@ -196,14 +196,18 @@ void print_delayacct(struct taskstats *t) | |||
| 196 | " %15llu%15llu%15llu%15llu\n" | 196 | " %15llu%15llu%15llu%15llu\n" |
| 197 | "IO %15s%15s\n" | 197 | "IO %15s%15s\n" |
| 198 | " %15llu%15llu\n" | 198 | " %15llu%15llu\n" |
| 199 | "MEM %15s%15s\n" | 199 | "SWAP %15s%15s\n" |
| 200 | " %15llu%15llu\n" | ||
| 201 | "RECLAIM %12s%15s\n" | ||
| 200 | " %15llu%15llu\n", | 202 | " %15llu%15llu\n", |
| 201 | "count", "real total", "virtual total", "delay total", | 203 | "count", "real total", "virtual total", "delay total", |
| 202 | t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total, | 204 | t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total, |
| 203 | t->cpu_delay_total, | 205 | t->cpu_delay_total, |
| 204 | "count", "delay total", | 206 | "count", "delay total", |
| 205 | t->blkio_count, t->blkio_delay_total, | 207 | t->blkio_count, t->blkio_delay_total, |
| 206 | "count", "delay total", t->swapin_count, t->swapin_delay_total); | 208 | "count", "delay total", t->swapin_count, t->swapin_delay_total, |
| 209 | "count", "delay total", | ||
| 210 | t->freepages_count, t->freepages_delay_total); | ||
| 207 | } | 211 | } |
| 208 | 212 | ||
| 209 | void task_context_switch_counts(struct taskstats *t) | 213 | void task_context_switch_counts(struct taskstats *t) |
diff --git a/Documentation/accounting/taskstats-struct.txt b/Documentation/accounting/taskstats-struct.txt index cd784f46bf8a..b988d110db59 100644 --- a/Documentation/accounting/taskstats-struct.txt +++ b/Documentation/accounting/taskstats-struct.txt | |||
| @@ -26,6 +26,8 @@ There are three different groups of fields in the struct taskstats: | |||
| 26 | 26 | ||
| 27 | 5) Time accounting for SMT machines | 27 | 5) Time accounting for SMT machines |
| 28 | 28 | ||
| 29 | 6) Extended delay accounting fields for memory reclaim | ||
| 30 | |||
| 29 | Future extension should add fields to the end of the taskstats struct, and | 31 | Future extension should add fields to the end of the taskstats struct, and |
| 30 | should not change the relative position of each field within the struct. | 32 | should not change the relative position of each field within the struct. |
| 31 | 33 | ||
| @@ -170,4 +172,9 @@ struct taskstats { | |||
| 170 | __u64 ac_utimescaled; /* utime scaled on frequency etc */ | 172 | __u64 ac_utimescaled; /* utime scaled on frequency etc */ |
| 171 | __u64 ac_stimescaled; /* stime scaled on frequency etc */ | 173 | __u64 ac_stimescaled; /* stime scaled on frequency etc */ |
| 172 | __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */ | 174 | __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */ |
| 175 | |||
| 176 | 6) Extended delay accounting fields for memory reclaim | ||
| 177 | /* Delay waiting for memory reclaim */ | ||
| 178 | __u64 freepages_count; | ||
| 179 | __u64 freepages_delay_total; | ||
| 173 | } | 180 | } |
diff --git a/Documentation/bt8xxgpio.txt b/Documentation/bt8xxgpio.txt new file mode 100644 index 000000000000..d8297e4ebd26 --- /dev/null +++ b/Documentation/bt8xxgpio.txt | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | =============================================================== | ||
| 2 | == BT8XXGPIO driver == | ||
| 3 | == == | ||
| 4 | == A driver for a selfmade cheap BT8xx based PCI GPIO-card == | ||
| 5 | == == | ||
| 6 | == For advanced documentation, see == | ||
| 7 | == http://www.bu3sch.de/btgpio.php == | ||
| 8 | =============================================================== | ||
| 9 | |||
| 10 | |||
| 11 | A generic digital 24-port PCI GPIO card can be built out of an ordinary | ||
| 12 | Brooktree bt848, bt849, bt878 or bt879 based analog TV tuner card. The | ||
| 13 | Brooktree chip is used in old analog Hauppauge WinTV PCI cards. You can easily | ||
| 14 | find them used for low prices on the net. | ||
| 15 | |||
| 16 | The bt8xx chip does have 24 digital GPIO ports. | ||
| 17 | These ports are accessible via 24 pins on the SMD chip package. | ||
| 18 | |||
| 19 | |||
| 20 | ============================================== | ||
| 21 | == How to physically access the GPIO pins == | ||
| 22 | ============================================== | ||
| 23 | |||
| 24 | The are several ways to access these pins. One might unsolder the whole chip | ||
| 25 | and put it on a custom PCI board, or one might only unsolder each individual | ||
| 26 | GPIO pin and solder that to some tiny wire. As the chip package really is tiny | ||
| 27 | there are some advanced soldering skills needed in any case. | ||
| 28 | |||
| 29 | The physical pinouts are drawn in the following ASCII art. | ||
| 30 | The GPIO pins are marked with G00-G23 | ||
| 31 | |||
| 32 | G G G G G G G G G G G G G G G G G G | ||
| 33 | 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 | ||
| 34 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 | ||
| 35 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ||
| 36 | --------------------------------------------------------------------------- | ||
| 37 | --| ^ ^ |-- | ||
| 38 | --| pin 86 pin 67 |-- | ||
| 39 | --| |-- | ||
| 40 | --| pin 61 > |-- G18 | ||
| 41 | --| |-- G19 | ||
| 42 | --| |-- G20 | ||
| 43 | --| |-- G21 | ||
| 44 | --| |-- G22 | ||
| 45 | --| pin 56 > |-- G23 | ||
| 46 | --| |-- | ||
| 47 | --| Brooktree 878/879 |-- | ||
| 48 | --| |-- | ||
| 49 | --| |-- | ||
| 50 | --| |-- | ||
| 51 | --| |-- | ||
| 52 | --| |-- | ||
| 53 | --| |-- | ||
| 54 | --| |-- | ||
| 55 | --| |-- | ||
| 56 | --| |-- | ||
| 57 | --| |-- | ||
| 58 | --| |-- | ||
| 59 | --| |-- | ||
| 60 | --| |-- | ||
| 61 | --| O |-- | ||
| 62 | --| |-- | ||
| 63 | --------------------------------------------------------------------------- | ||
| 64 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ||
| 65 | ^ | ||
| 66 | This is pin 1 | ||
| 67 | |||
diff --git a/Documentation/controllers/memory.txt b/Documentation/controllers/memory.txt index 866b9cd9a959..9b53d5827361 100644 --- a/Documentation/controllers/memory.txt +++ b/Documentation/controllers/memory.txt | |||
| @@ -242,8 +242,7 @@ rmdir() if there are no tasks. | |||
| 242 | 1. Add support for accounting huge pages (as a separate controller) | 242 | 1. Add support for accounting huge pages (as a separate controller) |
| 243 | 2. Make per-cgroup scanner reclaim not-shared pages first | 243 | 2. Make per-cgroup scanner reclaim not-shared pages first |
| 244 | 3. Teach controller to account for shared-pages | 244 | 3. Teach controller to account for shared-pages |
| 245 | 4. Start reclamation when the limit is lowered | 245 | 4. Start reclamation in the background when the limit is |
| 246 | 5. Start reclamation in the background when the limit is | ||
| 247 | not yet hit but the usage is getting closer | 246 | not yet hit but the usage is getting closer |
| 248 | 247 | ||
| 249 | Summary | 248 | Summary |
diff --git a/Documentation/edac.txt b/Documentation/edac.txt index a5c36842ecef..ced527388001 100644 --- a/Documentation/edac.txt +++ b/Documentation/edac.txt | |||
| @@ -222,74 +222,9 @@ both csrow2 and csrow3 are populated, this indicates a dual ranked | |||
| 222 | set of DIMMs for channels 0 and 1. | 222 | set of DIMMs for channels 0 and 1. |
| 223 | 223 | ||
| 224 | 224 | ||
| 225 | Within each of the 'mc','mcX' and 'csrowX' directories are several | 225 | Within each of the 'mcX' and 'csrowX' directories are several |
| 226 | EDAC control and attribute files. | 226 | EDAC control and attribute files. |
| 227 | 227 | ||
| 228 | |||
| 229 | ============================================================================ | ||
| 230 | DIRECTORY 'mc' | ||
| 231 | |||
| 232 | In directory 'mc' are EDAC system overall control and attribute files: | ||
| 233 | |||
| 234 | |||
| 235 | Panic on UE control file: | ||
| 236 | |||
| 237 | 'edac_mc_panic_on_ue' | ||
| 238 | |||
| 239 | An uncorrectable error will cause a machine panic. This is usually | ||
| 240 | desirable. It is a bad idea to continue when an uncorrectable error | ||
| 241 | occurs - it is indeterminate what was uncorrected and the operating | ||
| 242 | system context might be so mangled that continuing will lead to further | ||
| 243 | corruption. If the kernel has MCE configured, then EDAC will never | ||
| 244 | notice the UE. | ||
| 245 | |||
| 246 | LOAD TIME: module/kernel parameter: panic_on_ue=[0|1] | ||
| 247 | |||
| 248 | RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_panic_on_ue | ||
| 249 | |||
| 250 | |||
| 251 | Log UE control file: | ||
| 252 | |||
| 253 | 'edac_mc_log_ue' | ||
| 254 | |||
| 255 | Generate kernel messages describing uncorrectable errors. These errors | ||
| 256 | are reported through the system message log system. UE statistics | ||
| 257 | will be accumulated even when UE logging is disabled. | ||
| 258 | |||
| 259 | LOAD TIME: module/kernel parameter: log_ue=[0|1] | ||
| 260 | |||
| 261 | RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ue | ||
| 262 | |||
| 263 | |||
| 264 | Log CE control file: | ||
| 265 | |||
| 266 | 'edac_mc_log_ce' | ||
| 267 | |||
| 268 | Generate kernel messages describing correctable errors. These | ||
| 269 | errors are reported through the system message log system. | ||
| 270 | CE statistics will be accumulated even when CE logging is disabled. | ||
| 271 | |||
| 272 | LOAD TIME: module/kernel parameter: log_ce=[0|1] | ||
| 273 | |||
| 274 | RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ce | ||
| 275 | |||
| 276 | |||
| 277 | Polling period control file: | ||
| 278 | |||
| 279 | 'edac_mc_poll_msec' | ||
| 280 | |||
| 281 | The time period, in milliseconds, for polling for error information. | ||
| 282 | Too small a value wastes resources. Too large a value might delay | ||
| 283 | necessary handling of errors and might loose valuable information for | ||
| 284 | locating the error. 1000 milliseconds (once each second) is the current | ||
| 285 | default. Systems which require all the bandwidth they can get, may | ||
| 286 | increase this. | ||
| 287 | |||
| 288 | LOAD TIME: module/kernel parameter: poll_msec=[0|1] | ||
| 289 | |||
| 290 | RUN TIME: echo "1000" >/sys/devices/system/edac/mc/edac_mc_poll_msec | ||
| 291 | |||
| 292 | |||
| 293 | ============================================================================ | 228 | ============================================================================ |
| 294 | 'mcX' DIRECTORIES | 229 | 'mcX' DIRECTORIES |
| 295 | 230 | ||
| @@ -537,7 +472,6 @@ Channel 1 DIMM Label control file: | |||
| 537 | motherboard specific and determination of this information | 472 | motherboard specific and determination of this information |
| 538 | must occur in userland at this time. | 473 | must occur in userland at this time. |
| 539 | 474 | ||
| 540 | |||
| 541 | ============================================================================ | 475 | ============================================================================ |
| 542 | SYSTEM LOGGING | 476 | SYSTEM LOGGING |
| 543 | 477 | ||
| @@ -570,7 +504,6 @@ error type, a notice of "no info" and then an optional, | |||
| 570 | driver-specific error message. | 504 | driver-specific error message. |
| 571 | 505 | ||
| 572 | 506 | ||
| 573 | |||
| 574 | ============================================================================ | 507 | ============================================================================ |
| 575 | PCI Bus Parity Detection | 508 | PCI Bus Parity Detection |
| 576 | 509 | ||
| @@ -604,6 +537,74 @@ Enable/Disable PCI Parity checking control file: | |||
| 604 | echo "0" >/sys/devices/system/edac/pci/check_pci_parity | 537 | echo "0" >/sys/devices/system/edac/pci/check_pci_parity |
| 605 | 538 | ||
| 606 | 539 | ||
| 540 | Parity Count: | ||
| 541 | |||
| 542 | 'pci_parity_count' | ||
| 543 | |||
| 544 | This attribute file will display the number of parity errors that | ||
| 545 | have been detected. | ||
| 546 | |||
| 547 | |||
| 548 | ============================================================================ | ||
| 549 | MODULE PARAMETERS | ||
| 550 | |||
| 551 | Panic on UE control file: | ||
| 552 | |||
| 553 | 'edac_mc_panic_on_ue' | ||
| 554 | |||
| 555 | An uncorrectable error will cause a machine panic. This is usually | ||
| 556 | desirable. It is a bad idea to continue when an uncorrectable error | ||
| 557 | occurs - it is indeterminate what was uncorrected and the operating | ||
| 558 | system context might be so mangled that continuing will lead to further | ||
| 559 | corruption. If the kernel has MCE configured, then EDAC will never | ||
| 560 | notice the UE. | ||
| 561 | |||
| 562 | LOAD TIME: module/kernel parameter: edac_mc_panic_on_ue=[0|1] | ||
| 563 | |||
| 564 | RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue | ||
| 565 | |||
| 566 | |||
| 567 | Log UE control file: | ||
| 568 | |||
| 569 | 'edac_mc_log_ue' | ||
| 570 | |||
| 571 | Generate kernel messages describing uncorrectable errors. These errors | ||
| 572 | are reported through the system message log system. UE statistics | ||
| 573 | will be accumulated even when UE logging is disabled. | ||
| 574 | |||
| 575 | LOAD TIME: module/kernel parameter: edac_mc_log_ue=[0|1] | ||
| 576 | |||
| 577 | RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue | ||
| 578 | |||
| 579 | |||
| 580 | Log CE control file: | ||
| 581 | |||
| 582 | 'edac_mc_log_ce' | ||
| 583 | |||
| 584 | Generate kernel messages describing correctable errors. These | ||
| 585 | errors are reported through the system message log system. | ||
| 586 | CE statistics will be accumulated even when CE logging is disabled. | ||
| 587 | |||
| 588 | LOAD TIME: module/kernel parameter: edac_mc_log_ce=[0|1] | ||
| 589 | |||
| 590 | RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce | ||
| 591 | |||
| 592 | |||
| 593 | Polling period control file: | ||
| 594 | |||
| 595 | 'edac_mc_poll_msec' | ||
| 596 | |||
| 597 | The time period, in milliseconds, for polling for error information. | ||
| 598 | Too small a value wastes resources. Too large a value might delay | ||
| 599 | necessary handling of errors and might loose valuable information for | ||
| 600 | locating the error. 1000 milliseconds (once each second) is the current | ||
| 601 | default. Systems which require all the bandwidth they can get, may | ||
| 602 | increase this. | ||
| 603 | |||
| 604 | LOAD TIME: module/kernel parameter: edac_mc_poll_msec=[0|1] | ||
| 605 | |||
| 606 | RUN TIME: echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec | ||
| 607 | |||
| 607 | 608 | ||
| 608 | Panic on PCI PARITY Error: | 609 | Panic on PCI PARITY Error: |
| 609 | 610 | ||
| @@ -614,21 +615,13 @@ Panic on PCI PARITY Error: | |||
| 614 | error has been detected. | 615 | error has been detected. |
| 615 | 616 | ||
| 616 | 617 | ||
| 617 | module/kernel parameter: panic_on_pci_parity=[0|1] | 618 | module/kernel parameter: edac_panic_on_pci_pe=[0|1] |
| 618 | 619 | ||
| 619 | Enable: | 620 | Enable: |
| 620 | echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity | 621 | echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe |
| 621 | 622 | ||
| 622 | Disable: | 623 | Disable: |
| 623 | echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity | 624 | echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe |
| 624 | |||
| 625 | |||
| 626 | Parity Count: | ||
| 627 | |||
| 628 | 'pci_parity_count' | ||
| 629 | |||
| 630 | This attribute file will display the number of parity errors that | ||
| 631 | have been detected. | ||
| 632 | 625 | ||
| 633 | 626 | ||
| 634 | 627 | ||
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 09c4a1efb8e3..721c71b86e06 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
| @@ -138,24 +138,6 @@ Who: Kay Sievers <kay.sievers@suse.de> | |||
| 138 | 138 | ||
| 139 | --------------------------- | 139 | --------------------------- |
| 140 | 140 | ||
| 141 | What: find_task_by_pid | ||
| 142 | When: 2.6.26 | ||
| 143 | Why: With pid namespaces, calling this funciton will return the | ||
| 144 | wrong task when called from inside a namespace. | ||
| 145 | |||
| 146 | The best way to save a task pid and find a task by this | ||
| 147 | pid later, is to find this task's struct pid pointer (or get | ||
| 148 | it directly from the task) and call pid_task() later. | ||
| 149 | |||
| 150 | If someone really needs to get a task by its pid_t, then | ||
| 151 | he most likely needs the find_task_by_vpid() to get the | ||
| 152 | task from the same namespace as the current task is in, but | ||
| 153 | this may be not so in general. | ||
| 154 | |||
| 155 | Who: Pavel Emelyanov <xemul@openvz.org> | ||
| 156 | |||
| 157 | --------------------------- | ||
| 158 | |||
| 159 | What: ACPI procfs interface | 141 | What: ACPI procfs interface |
| 160 | When: July 2008 | 142 | When: July 2008 |
| 161 | Why: ACPI sysfs conversion should be finished by January 2008. | 143 | Why: ACPI sysfs conversion should be finished by January 2008. |
diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index 2d5e1e582e13..bbac4f1d9056 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt | |||
| @@ -96,6 +96,14 @@ shortname=lower|win95|winnt|mixed | |||
| 96 | emulate the Windows 95 rule for create. | 96 | emulate the Windows 95 rule for create. |
| 97 | Default setting is `lower'. | 97 | Default setting is `lower'. |
| 98 | 98 | ||
| 99 | tz=UTC -- Interpret timestamps as UTC rather than local time. | ||
| 100 | This option disables the conversion of timestamps | ||
| 101 | between local time (as used by Windows on FAT) and UTC | ||
| 102 | (which Linux uses internally). This is particuluarly | ||
| 103 | useful when mounting devices (like digital cameras) | ||
| 104 | that are set to UTC in order to avoid the pitfalls of | ||
| 105 | local time. | ||
| 106 | |||
| 99 | <bool>: 0,1,yes,no,true,false | 107 | <bool>: 0,1,yes,no,true,false |
| 100 | 108 | ||
| 101 | TODO | 109 | TODO |
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index c35ca9e40d4c..18022e249c53 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt | |||
| @@ -347,15 +347,12 @@ necessarily be nonportable. | |||
| 347 | Dynamic definition of GPIOs is not currently standard; for example, as | 347 | Dynamic definition of GPIOs is not currently standard; for example, as |
| 348 | a side effect of configuring an add-on board with some GPIO expanders. | 348 | a side effect of configuring an add-on board with some GPIO expanders. |
| 349 | 349 | ||
| 350 | These calls are purely for kernel space, but a userspace API could be built | ||
| 351 | on top of them. | ||
| 352 | |||
| 353 | 350 | ||
| 354 | GPIO implementor's framework (OPTIONAL) | 351 | GPIO implementor's framework (OPTIONAL) |
| 355 | ======================================= | 352 | ======================================= |
| 356 | As noted earlier, there is an optional implementation framework making it | 353 | As noted earlier, there is an optional implementation framework making it |
| 357 | easier for platforms to support different kinds of GPIO controller using | 354 | easier for platforms to support different kinds of GPIO controller using |
| 358 | the same programming interface. | 355 | the same programming interface. This framework is called "gpiolib". |
| 359 | 356 | ||
| 360 | As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file | 357 | As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file |
| 361 | will be found there. That will list all the controllers registered through | 358 | will be found there. That will list all the controllers registered through |
| @@ -392,11 +389,21 @@ either NULL or the label associated with that GPIO when it was requested. | |||
| 392 | 389 | ||
| 393 | Platform Support | 390 | Platform Support |
| 394 | ---------------- | 391 | ---------------- |
| 395 | To support this framework, a platform's Kconfig will "select HAVE_GPIO_LIB" | 392 | To support this framework, a platform's Kconfig will "select" either |
| 393 | ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 396 | and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines | 394 | and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines |
| 397 | three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep(). | 395 | three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep(). |
| 398 | They may also want to provide a custom value for ARCH_NR_GPIOS. | 396 | They may also want to provide a custom value for ARCH_NR_GPIOS. |
| 399 | 397 | ||
| 398 | ARCH_REQUIRE_GPIOLIB means that the gpio-lib code will always get compiled | ||
| 399 | into the kernel on that architecture. | ||
| 400 | |||
| 401 | ARCH_WANT_OPTIONAL_GPIOLIB means the gpio-lib code defaults to off and the user | ||
| 402 | can enable it and build it into the kernel optionally. | ||
| 403 | |||
| 404 | If neither of these options are selected, the platform does not support | ||
| 405 | GPIOs through GPIO-lib and the code cannot be enabled by the user. | ||
| 406 | |||
| 400 | Trivial implementations of those functions can directly use framework | 407 | Trivial implementations of those functions can directly use framework |
| 401 | code, which always dispatches through the gpio_chip: | 408 | code, which always dispatches through the gpio_chip: |
| 402 | 409 | ||
| @@ -439,4 +446,120 @@ becomes available. That may mean the device should not be registered until | |||
| 439 | calls for that GPIO can work. One way to address such dependencies is for | 446 | calls for that GPIO can work. One way to address such dependencies is for |
| 440 | such gpio_chip controllers to provide setup() and teardown() callbacks to | 447 | such gpio_chip controllers to provide setup() and teardown() callbacks to |
| 441 | board specific code; those board specific callbacks would register devices | 448 | board specific code; those board specific callbacks would register devices |
| 442 | once all the necessary resources are available. | 449 | once all the necessary resources are available, and remove them later when |
| 450 | the GPIO controller device becomes unavailable. | ||
| 451 | |||
| 452 | |||
| 453 | Sysfs Interface for Userspace (OPTIONAL) | ||
| 454 | ======================================== | ||
| 455 | Platforms which use the "gpiolib" implementors framework may choose to | ||
| 456 | configure a sysfs user interface to GPIOs. This is different from the | ||
| 457 | debugfs interface, since it provides control over GPIO direction and | ||
| 458 | value instead of just showing a gpio state summary. Plus, it could be | ||
| 459 | present on production systems without debugging support. | ||
| 460 | |||
| 461 | Given approprate hardware documentation for the system, userspace could | ||
| 462 | know for example that GPIO #23 controls the write protect line used to | ||
| 463 | protect boot loader segments in flash memory. System upgrade procedures | ||
| 464 | may need to temporarily remove that protection, first importing a GPIO, | ||
| 465 | then changing its output state, then updating the code before re-enabling | ||
| 466 | the write protection. In normal use, GPIO #23 would never be touched, | ||
| 467 | and the kernel would have no need to know about it. | ||
| 468 | |||
| 469 | Again depending on appropriate hardware documentation, on some systems | ||
| 470 | userspace GPIO can be used to determine system configuration data that | ||
| 471 | standard kernels won't know about. And for some tasks, simple userspace | ||
| 472 | GPIO drivers could be all that the system really needs. | ||
| 473 | |||
| 474 | Note that standard kernel drivers exist for common "LEDs and Buttons" | ||
| 475 | GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those | ||
| 476 | instead of talking directly to the GPIOs; they integrate with kernel | ||
| 477 | frameworks better than your userspace code could. | ||
| 478 | |||
| 479 | |||
| 480 | Paths in Sysfs | ||
| 481 | -------------- | ||
| 482 | There are three kinds of entry in /sys/class/gpio: | ||
| 483 | |||
| 484 | - Control interfaces used to get userspace control over GPIOs; | ||
| 485 | |||
| 486 | - GPIOs themselves; and | ||
| 487 | |||
| 488 | - GPIO controllers ("gpio_chip" instances). | ||
| 489 | |||
| 490 | That's in addition to standard files including the "device" symlink. | ||
| 491 | |||
| 492 | The control interfaces are write-only: | ||
| 493 | |||
| 494 | /sys/class/gpio/ | ||
| 495 | |||
| 496 | "export" ... Userspace may ask the kernel to export control of | ||
| 497 | a GPIO to userspace by writing its number to this file. | ||
| 498 | |||
| 499 | Example: "echo 19 > export" will create a "gpio19" node | ||
| 500 | for GPIO #19, if that's not requested by kernel code. | ||
| 501 | |||
| 502 | "unexport" ... Reverses the effect of exporting to userspace. | ||
| 503 | |||
| 504 | Example: "echo 19 > unexport" will remove a "gpio19" | ||
| 505 | node exported using the "export" file. | ||
| 506 | |||
| 507 | GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42) | ||
| 508 | and have the following read/write attributes: | ||
| 509 | |||
| 510 | /sys/class/gpio/gpioN/ | ||
| 511 | |||
| 512 | "direction" ... reads as either "in" or "out". This value may | ||
| 513 | normally be written. Writing as "out" defaults to | ||
| 514 | initializing the value as low. To ensure glitch free | ||
| 515 | operation, values "low" and "high" may be written to | ||
| 516 | configure the GPIO as an output with that initial value. | ||
| 517 | |||
| 518 | Note that this attribute *will not exist* if the kernel | ||
| 519 | doesn't support changing the direction of a GPIO, or | ||
| 520 | it was exported by kernel code that didn't explicitly | ||
| 521 | allow userspace to reconfigure this GPIO's direction. | ||
| 522 | |||
| 523 | "value" ... reads as either 0 (low) or 1 (high). If the GPIO | ||
| 524 | is configured as an output, this value may be written; | ||
| 525 | any nonzero value is treated as high. | ||
| 526 | |||
| 527 | GPIO controllers have paths like /sys/class/gpio/chipchip42/ (for the | ||
| 528 | controller implementing GPIOs starting at #42) and have the following | ||
| 529 | read-only attributes: | ||
| 530 | |||
| 531 | /sys/class/gpio/gpiochipN/ | ||
| 532 | |||
| 533 | "base" ... same as N, the first GPIO managed by this chip | ||
| 534 | |||
| 535 | "label" ... provided for diagnostics (not always unique) | ||
| 536 | |||
| 537 | "ngpio" ... how many GPIOs this manges (N to N + ngpio - 1) | ||
| 538 | |||
| 539 | Board documentation should in most cases cover what GPIOs are used for | ||
| 540 | what purposes. However, those numbers are not always stable; GPIOs on | ||
| 541 | a daughtercard might be different depending on the base board being used, | ||
| 542 | or other cards in the stack. In such cases, you may need to use the | ||
| 543 | gpiochip nodes (possibly in conjunction with schematics) to determine | ||
| 544 | the correct GPIO number to use for a given signal. | ||
| 545 | |||
| 546 | |||
| 547 | Exporting from Kernel code | ||
| 548 | -------------------------- | ||
| 549 | Kernel code can explicitly manage exports of GPIOs which have already been | ||
| 550 | requested using gpio_request(): | ||
| 551 | |||
| 552 | /* export the GPIO to userspace */ | ||
| 553 | int gpio_export(unsigned gpio, bool direction_may_change); | ||
| 554 | |||
| 555 | /* reverse gpio_export() */ | ||
| 556 | void gpio_unexport(); | ||
| 557 | |||
| 558 | After a kernel driver requests a GPIO, it may only be made available in | ||
| 559 | the sysfs interface by gpio_export(). The driver can control whether the | ||
| 560 | signal direction may change. This helps drivers prevent userspace code | ||
| 561 | from accidentally clobbering important system state. | ||
| 562 | |||
| 563 | This explicit exporting can help with debugging (by making some kinds | ||
| 564 | of experiments easier), or can provide an always-there interface that's | ||
| 565 | suitable for documenting as part of a board support package. | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 497a98dafdaa..e7bea3e85304 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -2159,13 +2159,6 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 2159 | <deci-seconds>: poll all this frequency | 2159 | <deci-seconds>: poll all this frequency |
| 2160 | 0: no polling (default) | 2160 | 0: no polling (default) |
| 2161 | 2161 | ||
| 2162 | tipar.timeout= [HW,PPT] | ||
| 2163 | Set communications timeout in tenths of a second | ||
| 2164 | (default 15). | ||
| 2165 | |||
| 2166 | tipar.delay= [HW,PPT] | ||
| 2167 | Set inter-bit delay in microseconds (default 10). | ||
| 2168 | |||
| 2169 | tmscsim= [HW,SCSI] | 2162 | tmscsim= [HW,SCSI] |
| 2170 | See comment before function dc390_setup() in | 2163 | See comment before function dc390_setup() in |
| 2171 | drivers/scsi/tmscsim.c. | 2164 | drivers/scsi/tmscsim.c. |
diff --git a/Documentation/moxa-smartio b/Documentation/moxa-smartio index fe24ecc6372e..5337e80a5b96 100644 --- a/Documentation/moxa-smartio +++ b/Documentation/moxa-smartio | |||
| @@ -1,14 +1,22 @@ | |||
| 1 | ============================================================================= | 1 | ============================================================================= |
| 2 | 2 | MOXA Smartio/Industio Family Device Driver Installation Guide | |
| 3 | MOXA Smartio Family Device Driver Ver 1.1 Installation Guide | 3 | for Linux Kernel 2.4.x, 2.6.x |
| 4 | for Linux Kernel 2.2.x and 2.0.3x | 4 | Copyright (C) 2008, Moxa Inc. |
| 5 | Copyright (C) 1999, Moxa Technologies Co, Ltd. | ||
| 6 | ============================================================================= | 5 | ============================================================================= |
| 6 | Date: 01/21/2008 | ||
| 7 | |||
| 7 | Content | 8 | Content |
| 8 | 9 | ||
| 9 | 1. Introduction | 10 | 1. Introduction |
| 10 | 2. System Requirement | 11 | 2. System Requirement |
| 11 | 3. Installation | 12 | 3. Installation |
| 13 | 3.1 Hardware installation | ||
| 14 | 3.2 Driver files | ||
| 15 | 3.3 Device naming convention | ||
| 16 | 3.4 Module driver configuration | ||
| 17 | 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x. | ||
| 18 | 3.6 Custom configuration | ||
| 19 | 3.7 Verify driver installation | ||
| 12 | 4. Utilities | 20 | 4. Utilities |
| 13 | 5. Setserial | 21 | 5. Setserial |
| 14 | 6. Troubleshooting | 22 | 6. Troubleshooting |
| @@ -16,27 +24,48 @@ Content | |||
| 16 | ----------------------------------------------------------------------------- | 24 | ----------------------------------------------------------------------------- |
| 17 | 1. Introduction | 25 | 1. Introduction |
| 18 | 26 | ||
| 19 | The Smartio family Linux driver, Ver. 1.1, supports following multiport | 27 | The Smartio/Industio/UPCI family Linux driver supports following multiport |
| 20 | boards. | 28 | boards. |
| 21 | 29 | ||
| 22 | -C104P/H/HS, C104H/PCI, C104HS/PCI, CI-104J 4 port multiport board. | 30 | - 2 ports multiport board |
| 23 | -C168P/H/HS, C168H/PCI 8 port multiport board. | 31 | CP-102U, CP-102UL, CP-102UF |
| 24 | 32 | CP-132U-I, CP-132UL, | |
| 25 | This driver has been modified a little and cleaned up from the Moxa | 33 | CP-132, CP-132I, CP132S, CP-132IS, |
| 26 | contributed driver code and merged into Linux 2.2.14pre. In particular | 34 | CI-132, CI-132I, CI-132IS, |
| 27 | official major/minor numbers have been assigned which are different to | 35 | (C102H, C102HI, C102HIS, C102P, CP-102, CP-102S) |
| 28 | those the original Moxa supplied driver used. | 36 | |
| 37 | - 4 ports multiport board | ||
| 38 | CP-104EL, | ||
| 39 | CP-104UL, CP-104JU, | ||
| 40 | CP-134U, CP-134U-I, | ||
| 41 | C104H/PCI, C104HS/PCI, | ||
| 42 | CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL, | ||
| 43 | C104H, C104HS, | ||
| 44 | CI-104J, CI-104JS, | ||
| 45 | CI-134, CI-134I, CI-134IS, | ||
| 46 | (C114HI, CT-114I, C104P) | ||
| 47 | POS-104UL, | ||
| 48 | CB-114, | ||
| 49 | CB-134I | ||
| 50 | |||
| 51 | - 8 ports multiport board | ||
| 52 | CP-118EL, CP-168EL, | ||
| 53 | CP-118U, CP-168U, | ||
| 54 | C168H/PCI, | ||
| 55 | C168H, C168HS, | ||
| 56 | (C168P), | ||
| 57 | CB-108 | ||
| 29 | 58 | ||
| 30 | This driver and installation procedure have been developed upon Linux Kernel | 59 | This driver and installation procedure have been developed upon Linux Kernel |
| 31 | 2.2.5 and backward compatible to 2.0.3x. This driver supports Intel x86 and | 60 | 2.4.x and 2.6.x. This driver supports Intel x86 hardware platform. In order |
| 32 | Alpha hardware platform. In order to maintain compatibility, this version | 61 | to maintain compatibility, this version has also been properly tested with |
| 33 | has also been properly tested with RedHat, OpenLinux, TurboLinux and | 62 | RedHat, Mandrake, Fedora and S.u.S.E Linux. However, if compatibility problem |
| 34 | S.u.S.E Linux. However, if compatibility problem occurs, please contact | 63 | occurs, please contact Moxa at support@moxa.com.tw. |
| 35 | Moxa at support@moxa.com.tw. | ||
| 36 | 64 | ||
| 37 | In addition to device driver, useful utilities are also provided in this | 65 | In addition to device driver, useful utilities are also provided in this |
| 38 | version. They are | 66 | version. They are |
| 39 | - msdiag Diagnostic program for detecting installed Moxa Smartio boards. | 67 | - msdiag Diagnostic program for displaying installed Moxa |
| 68 | Smartio/Industio boards. | ||
| 40 | - msmon Monitor program to observe data count and line status signals. | 69 | - msmon Monitor program to observe data count and line status signals. |
| 41 | - msterm A simple terminal program which is useful in testing serial | 70 | - msterm A simple terminal program which is useful in testing serial |
| 42 | ports. | 71 | ports. |
| @@ -47,8 +76,7 @@ Content | |||
| 47 | GNU General Public License in this version. Please refer to GNU General | 76 | GNU General Public License in this version. Please refer to GNU General |
| 48 | Public License announcement in each source code file for more detail. | 77 | Public License announcement in each source code file for more detail. |
| 49 | 78 | ||
| 50 | In Moxa's ftp sites, you may always find latest driver at | 79 | In Moxa's Web sites, you may always find latest driver at http://web.moxa.com. |
| 51 | ftp://ftp.moxa.com or ftp://ftp.moxa.com.tw. | ||
| 52 | 80 | ||
| 53 | This version of driver can be installed as Loadable Module (Module driver) | 81 | This version of driver can be installed as Loadable Module (Module driver) |
| 54 | or built-in into kernel (Static driver). You may refer to following | 82 | or built-in into kernel (Static driver). You may refer to following |
| @@ -61,8 +89,8 @@ Content | |||
| 61 | 89 | ||
| 62 | ----------------------------------------------------------------------------- | 90 | ----------------------------------------------------------------------------- |
| 63 | 2. System Requirement | 91 | 2. System Requirement |
| 64 | - Hardware platform: Intel x86 or Alpha machine | 92 | - Hardware platform: Intel x86 machine |
| 65 | - Kernel version: 2.0.3x or 2.2.x | 93 | - Kernel version: 2.4.x or 2.6.x |
| 66 | - gcc version 2.72 or later | 94 | - gcc version 2.72 or later |
| 67 | - Maximum 4 boards can be installed in combination | 95 | - Maximum 4 boards can be installed in combination |
| 68 | 96 | ||
| @@ -70,9 +98,18 @@ Content | |||
| 70 | 3. Installation | 98 | 3. Installation |
| 71 | 99 | ||
| 72 | 3.1 Hardware installation | 100 | 3.1 Hardware installation |
| 101 | 3.2 Driver files | ||
| 102 | 3.3 Device naming convention | ||
| 103 | 3.4 Module driver configuration | ||
| 104 | 3.5 Static driver configuration for Linux kernel 2.4.x, 2.6.x. | ||
| 105 | 3.6 Custom configuration | ||
| 106 | 3.7 Verify driver installation | ||
| 107 | |||
| 108 | |||
| 109 | 3.1 Hardware installation | ||
| 73 | 110 | ||
| 74 | There are two types of buses, ISA and PCI, for Smartio family multiport | 111 | There are two types of buses, ISA and PCI, for Smartio/Industio |
| 75 | board. | 112 | family multiport board. |
| 76 | 113 | ||
| 77 | ISA board | 114 | ISA board |
| 78 | --------- | 115 | --------- |
| @@ -81,47 +118,57 @@ Content | |||
| 81 | installation procedure in User's Manual before proceed any further. | 118 | installation procedure in User's Manual before proceed any further. |
| 82 | Please make sure the JP1 is open after the ISA board is set properly. | 119 | Please make sure the JP1 is open after the ISA board is set properly. |
| 83 | 120 | ||
| 84 | PCI board | 121 | PCI/UPCI board |
| 85 | --------- | 122 | -------------- |
| 86 | You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict | 123 | You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict |
| 87 | with other ISA devices. Please refer to hardware installation | 124 | with other ISA devices. Please refer to hardware installation |
| 88 | procedure in User's Manual in advance. | 125 | procedure in User's Manual in advance. |
| 89 | 126 | ||
| 90 | IRQ Sharing | 127 | PCI IRQ Sharing |
| 91 | ----------- | 128 | ----------- |
| 92 | Each port within the same multiport board shares the same IRQ. Up to | 129 | Each port within the same multiport board shares the same IRQ. Up to |
| 93 | 4 Moxa Smartio Family multiport boards can be installed together on | 130 | 4 Moxa Smartio/Industio PCI Family multiport boards can be installed |
| 94 | one system and they can share the same IRQ. | 131 | together on one system and they can share the same IRQ. |
| 132 | |||
| 95 | 133 | ||
| 96 | 3.2 Driver files and device naming convention | 134 | 3.2 Driver files |
| 97 | 135 | ||
| 98 | The driver file may be obtained from ftp, CD-ROM or floppy disk. The | 136 | The driver file may be obtained from ftp, CD-ROM or floppy disk. The |
| 99 | first step, anyway, is to copy driver file "mxser.tgz" into specified | 137 | first step, anyway, is to copy driver file "mxser.tgz" into specified |
| 100 | directory. e.g. /moxa. The execute commands as below. | 138 | directory. e.g. /moxa. The execute commands as below. |
| 101 | 139 | ||
| 140 | # cd / | ||
| 141 | # mkdir moxa | ||
| 102 | # cd /moxa | 142 | # cd /moxa |
| 103 | # tar xvf /dev/fd0 | 143 | # tar xvf /dev/fd0 |
| 144 | |||
| 104 | or | 145 | or |
| 146 | |||
| 147 | # cd / | ||
| 148 | # mkdir moxa | ||
| 105 | # cd /moxa | 149 | # cd /moxa |
| 106 | # cp /mnt/cdrom/<driver directory>/mxser.tgz . | 150 | # cp /mnt/cdrom/<driver directory>/mxser.tgz . |
| 107 | # tar xvfz mxser.tgz | 151 | # tar xvfz mxser.tgz |
| 108 | 152 | ||
| 153 | |||
| 154 | 3.3 Device naming convention | ||
| 155 | |||
| 109 | You may find all the driver and utilities files in /moxa/mxser. | 156 | You may find all the driver and utilities files in /moxa/mxser. |
| 110 | Following installation procedure depends on the model you'd like to | 157 | Following installation procedure depends on the model you'd like to |
| 111 | run the driver. If you prefer module driver, please refer to 3.3. | 158 | run the driver. If you prefer module driver, please refer to 3.4. |
| 112 | If static driver is required, please refer to 3.4. | 159 | If static driver is required, please refer to 3.5. |
| 113 | 160 | ||
| 114 | Dialin and callout port | 161 | Dialin and callout port |
| 115 | ----------------------- | 162 | ----------------------- |
| 116 | This driver remains traditional serial device properties. There're | 163 | This driver remains traditional serial device properties. There are |
| 117 | two special file name for each serial port. One is dial-in port | 164 | two special file name for each serial port. One is dial-in port |
| 118 | which is named "ttyMxx". For callout port, the naming convention | 165 | which is named "ttyMxx". For callout port, the naming convention |
| 119 | is "cumxx". | 166 | is "cumxx". |
| 120 | 167 | ||
| 121 | Device naming when more than 2 boards installed | 168 | Device naming when more than 2 boards installed |
| 122 | ----------------------------------------------- | 169 | ----------------------------------------------- |
| 123 | Naming convention for each Smartio multiport board is pre-defined | 170 | Naming convention for each Smartio/Industio multiport board is |
| 124 | as below. | 171 | pre-defined as below. |
| 125 | 172 | ||
| 126 | Board Num. Dial-in Port Callout port | 173 | Board Num. Dial-in Port Callout port |
| 127 | 1st board ttyM0 - ttyM7 cum0 - cum7 | 174 | 1st board ttyM0 - ttyM7 cum0 - cum7 |
| @@ -129,6 +176,12 @@ Content | |||
| 129 | 3rd board ttyM16 - ttyM23 cum16 - cum23 | 176 | 3rd board ttyM16 - ttyM23 cum16 - cum23 |
| 130 | 4th board ttyM24 - ttym31 cum24 - cum31 | 177 | 4th board ttyM24 - ttym31 cum24 - cum31 |
| 131 | 178 | ||
| 179 | |||
| 180 | !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| 181 | Under Kernel 2.6 the cum Device is Obsolete. So use ttyM* | ||
| 182 | device instead. | ||
| 183 | !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| 184 | |||
| 132 | Board sequence | 185 | Board sequence |
| 133 | -------------- | 186 | -------------- |
| 134 | This driver will activate ISA boards according to the parameter set | 187 | This driver will activate ISA boards according to the parameter set |
| @@ -138,69 +191,131 @@ Content | |||
| 138 | For PCI boards, their sequence will be after ISA boards and C168H/PCI | 191 | For PCI boards, their sequence will be after ISA boards and C168H/PCI |
| 139 | has higher priority than C104H/PCI boards. | 192 | has higher priority than C104H/PCI boards. |
| 140 | 193 | ||
| 141 | 3.3 Module driver configuration | 194 | 3.4 Module driver configuration |
| 142 | Module driver is easiest way to install. If you prefer static driver | 195 | Module driver is easiest way to install. If you prefer static driver |
| 143 | installation, please skip this paragraph. | 196 | installation, please skip this paragraph. |
| 144 | 1. Find "Makefile" in /moxa/mxser, then run | ||
| 145 | 197 | ||
| 146 | # make install | 198 | |
| 199 | ------------- Prepare to use the MOXA driver-------------------- | ||
| 200 | 3.4.1 Create tty device with correct major number | ||
| 201 | Before using MOXA driver, your system must have the tty devices | ||
| 202 | which are created with driver's major number. We offer one shell | ||
| 203 | script "msmknod" to simplify the procedure. | ||
| 204 | This step is only needed to be executed once. But you still | ||
| 205 | need to do this procedure when: | ||
| 206 | a. You change the driver's major number. Please refer the "3.7" | ||
| 207 | section. | ||
| 208 | b. Your total installed MOXA boards number is changed. Maybe you | ||
| 209 | add/delete one MOXA board. | ||
| 210 | c. You want to change the tty name. This needs to modify the | ||
| 211 | shell script "msmknod" | ||
| 212 | |||
| 213 | The procedure is: | ||
| 214 | # cd /moxa/mxser/driver | ||
| 215 | # ./msmknod | ||
| 216 | |||
| 217 | This shell script will require the major number for dial-in | ||
| 218 | device and callout device to create tty device. You also need | ||
| 219 | to specify the total installed MOXA board number. Default major | ||
| 220 | numbers for dial-in device and callout device are 30, 35. If | ||
| 221 | you need to change to other number, please refer section "3.7" | ||
| 222 | for more detailed procedure. | ||
| 223 | Msmknod will delete any special files occupying the same device | ||
| 224 | naming. | ||
| 225 | |||
| 226 | 3.4.2 Build the MOXA driver and utilities | ||
| 227 | Before using the MOXA driver and utilities, you need compile the | ||
| 228 | all the source code. This step is only need to be executed once. | ||
| 229 | But you still re-compile the source code if you modify the source | ||
| 230 | code. For example, if you change the driver's major number (see | ||
| 231 | "3.7" section), then you need to do this step again. | ||
| 232 | |||
| 233 | Find "Makefile" in /moxa/mxser, then run | ||
| 234 | |||
| 235 | # make clean; make install | ||
| 236 | |||
| 237 | !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!! | ||
| 238 | For Red Hat 9, Red Hat Enterprise Linux AS3/ES3/WS3 & Fedora Core1: | ||
| 239 | # make clean; make installsp1 | ||
| 240 | |||
| 241 | For Red Hat Enterprise Linux AS4/ES4/WS4: | ||
| 242 | # make clean; make installsp2 | ||
| 243 | !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!! | ||
| 147 | 244 | ||
| 148 | The driver files "mxser.o" and utilities will be properly compiled | 245 | The driver files "mxser.o" and utilities will be properly compiled |
| 149 | and copied to system directories respectively.Then run | 246 | and copied to system directories respectively. |
| 150 | 247 | ||
| 151 | # insmod mxser | 248 | ------------- Load MOXA driver-------------------- |
| 249 | 3.4.3 Load the MOXA driver | ||
| 152 | 250 | ||
| 153 | to activate the modular driver. You may run "lsmod" to check | 251 | # modprobe mxser <argument> |
| 154 | if "mxser.o" is activated. | ||
| 155 | 252 | ||
| 156 | 2. Create special files by executing "msmknod". | 253 | will activate the module driver. You may run "lsmod" to check |
| 157 | # cd /moxa/mxser/driver | 254 | if "mxser" is activated. If the MOXA board is ISA board, the |
| 158 | # ./msmknod | 255 | <argument> is needed. Please refer to section "3.4.5" for more |
| 256 | information. | ||
| 257 | |||
| 258 | |||
| 259 | ------------- Load MOXA driver on boot -------------------- | ||
| 260 | 3.4.4 For the above description, you may manually execute | ||
| 261 | "modprobe mxser" to activate this driver and run | ||
| 262 | "rmmod mxser" to remove it. | ||
| 263 | However, it's better to have a boot time configuration to | ||
| 264 | eliminate manual operation. Boot time configuration can be | ||
| 265 | achieved by rc file. We offer one "rc.mxser" file to simplify | ||
| 266 | the procedure under "moxa/mxser/driver". | ||
| 159 | 267 | ||
| 160 | Default major numbers for dial-in device and callout device are | 268 | But if you use ISA board, please modify the "modprobe ..." command |
| 161 | 174, 175. Msmknod will delete any special files occupying the same | 269 | to add the argument (see "3.4.5" section). After modifying the |
| 162 | device naming. | 270 | rc.mxser, please try to execute "/moxa/mxser/driver/rc.mxser" |
| 271 | manually to make sure the modification is ok. If any error | ||
| 272 | encountered, please try to modify again. If the modification is | ||
| 273 | completed, follow the below step. | ||
| 163 | 274 | ||
| 164 | 3. Up to now, you may manually execute "insmod mxser" to activate | 275 | Run following command for setting rc files. |
| 165 | this driver and run "rmmod mxser" to remove it. However, it's | ||
| 166 | better to have a boot time configuration to eliminate manual | ||
| 167 | operation. | ||
| 168 | Boot time configuration can be achieved by rc file. Run following | ||
| 169 | command for setting rc files. | ||
| 170 | 276 | ||
| 171 | # cd /moxa/mxser/driver | 277 | # cd /moxa/mxser/driver |
| 172 | # cp ./rc.mxser /etc/rc.d | 278 | # cp ./rc.mxser /etc/rc.d |
| 173 | # cd /etc/rc.d | 279 | # cd /etc/rc.d |
| 174 | 280 | ||
| 175 | You may have to modify part of the content in rc.mxser to specify | 281 | Check "rc.serial" is existed or not. If "rc.serial" doesn't exist, |
| 176 | parameters for ISA board. Please refer to rc.mxser for more detail. | 282 | create it by vi, run "chmod 755 rc.serial" to change the permission. |
| 177 | Find "rc.serial". If "rc.serial" doesn't exist, create it by vi. | 283 | Add "/etc/rc.d/rc.mxser" in last line, |
| 178 | Add "rc.mxser" in last line. Next, open rc.local by vi | ||
| 179 | and append following content. | ||
| 180 | 284 | ||
| 181 | if [ -f /etc/rc.d/rc.serial ]; then | 285 | Reboot and check if moxa.o activated by "lsmod" command. |
| 182 | sh /etc/rc.d/rc.serial | ||
| 183 | fi | ||
| 184 | 286 | ||
| 185 | 4. Reboot and check if mxser.o activated by "lsmod" command. | 287 | 3.4.5. If you'd like to drive Smartio/Industio ISA boards in the system, |
| 186 | 5. If you'd like to drive Smartio ISA boards in the system, you'll | 288 | you'll have to add parameter to specify CAP address of given |
| 187 | have to add parameter to specify CAP address of given board while | 289 | board while activating "mxser.o". The format for parameters are |
| 188 | activating "mxser.o". The format for parameters are as follows. | 290 | as follows. |
| 189 | 291 | ||
| 190 | insmod mxser ioaddr=0x???,0x???,0x???,0x??? | 292 | modprobe mxser ioaddr=0x???,0x???,0x???,0x??? |
| 191 | | | | | | 293 | | | | | |
| 192 | | | | +- 4th ISA board | 294 | | | | +- 4th ISA board |
| 193 | | | +------ 3rd ISA board | 295 | | | +------ 3rd ISA board |
| 194 | | +------------ 2nd ISA board | 296 | | +------------ 2nd ISA board |
| 195 | +------------------- 1st ISA board | 297 | +------------------- 1st ISA board |
| 196 | 298 | ||
| 197 | 3.4 Static driver configuration | 299 | 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x |
| 300 | |||
| 301 | Note: To use static driver, you must install the linux kernel | ||
| 302 | source package. | ||
| 303 | |||
| 304 | 3.5.1 Backup the built-in driver in the kernel. | ||
| 305 | # cd /usr/src/linux/drivers/char | ||
| 306 | # mv mxser.c mxser.c.old | ||
| 307 | |||
| 308 | For Red Hat 7.x user, you need to create link: | ||
| 309 | # cd /usr/src | ||
| 310 | # ln -s linux-2.4 linux | ||
| 198 | 311 | ||
| 199 | 1. Create link | 312 | 3.5.2 Create link |
| 200 | # cd /usr/src/linux/drivers/char | 313 | # cd /usr/src/linux/drivers/char |
| 201 | # ln -s /moxa/mxser/driver/mxser.c mxser.c | 314 | # ln -s /moxa/mxser/driver/mxser.c mxser.c |
| 202 | 315 | ||
| 203 | 2. Add CAP address list for ISA boards | 316 | 3.5.3 Add CAP address list for ISA boards. For PCI boards user, |
| 317 | please skip this step. | ||
| 318 | |||
| 204 | In module mode, the CAP address for ISA board is given by | 319 | In module mode, the CAP address for ISA board is given by |
| 205 | parameter. In static driver configuration, you'll have to | 320 | parameter. In static driver configuration, you'll have to |
| 206 | assign it within driver's source code. If you will not | 321 | assign it within driver's source code. If you will not |
| @@ -222,73 +337,55 @@ Content | |||
| 222 | static int mxserBoardCAP[] | 337 | static int mxserBoardCAP[] |
| 223 | = {0x280, 0x180, 0x00, 0x00}; | 338 | = {0x280, 0x180, 0x00, 0x00}; |
| 224 | 339 | ||
| 225 | 3. Modify tty_io.c | 340 | 3.5.4 Setup kernel configuration |
| 226 | # cd /usr/src/linux/drivers/char/ | ||
| 227 | # vi tty_io.c | ||
| 228 | Find pty_init(), insert "mxser_init()" as | ||
| 229 | 341 | ||
| 230 | pty_init(); | 342 | Configure the kernel: |
| 231 | mxser_init(); | ||
| 232 | 343 | ||
| 233 | 4. Modify tty.h | 344 | # cd /usr/src/linux |
| 234 | # cd /usr/src/linux/include/linux | 345 | # make menuconfig |
| 235 | # vi tty.h | ||
| 236 | Find extern int tty_init(void), insert "mxser_init()" as | ||
| 237 | 346 | ||
| 238 | extern int tty_init(void); | 347 | You will go into a menu-driven system. Please select [Character |
| 239 | extern int mxser_init(void); | 348 | devices][Non-standard serial port support], enable the [Moxa |
| 240 | 349 | SmartIO support] driver with "[*]" for built-in (not "[M]"), then | |
| 241 | 5. Modify Makefile | 350 | select [Exit] to exit this program. |
| 242 | # cd /usr/src/linux/drivers/char | ||
| 243 | # vi Makefile | ||
| 244 | Find L_OBJS := tty_io.o ...... random.o, add | ||
| 245 | "mxser.o" at last of this line as | ||
| 246 | L_OBJS := tty_io.o ....... mxser.o | ||
| 247 | 351 | ||
| 248 | 6. Rebuild kernel | 352 | 3.5.5 Rebuild kernel |
| 249 | The following are for Linux kernel rebuilding,for your reference only. | 353 | The following are for Linux kernel rebuilding, for your |
| 354 | reference only. | ||
| 250 | For appropriate details, please refer to the Linux document. | 355 | For appropriate details, please refer to the Linux document. |
| 251 | 356 | ||
| 252 | If 'lilo' utility is installed, please use 'make zlilo' to rebuild | ||
| 253 | kernel. If 'lilo' is not installed, please follow the following steps. | ||
| 254 | |||
| 255 | a. cd /usr/src/linux | 357 | a. cd /usr/src/linux |
| 256 | b. make clean /* take a few minutes */ | 358 | b. make clean /* take a few minutes */ |
| 257 | c. make bzImage /* take probably 10-20 minutes */ | 359 | c. make dep /* take a few minutes */ |
| 258 | d. Backup original boot kernel. /* optional step */ | 360 | d. make bzImage /* take probably 10-20 minutes */ |
| 259 | e. cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz | 361 | e. make install /* copy boot image to correct position */ |
| 260 | f. Please make sure the boot kernel (vmlinuz) is in the | 362 | f. Please make sure the boot kernel (vmlinuz) is in the |
| 261 | correct position. If you use 'lilo' utility, you should | 363 | correct position. |
| 262 | check /etc/lilo.conf 'image' item specified the path | 364 | g. If you use 'lilo' utility, you should check /etc/lilo.conf |
| 263 | which is the 'vmlinuz' path, or you will load wrong | 365 | 'image' item specified the path which is the 'vmlinuz' path, |
| 264 | (or old) boot kernel image (vmlinuz). | 366 | or you will load wrong (or old) boot kernel image (vmlinuz). |
| 265 | g. chmod 400 /vmlinuz | 367 | After checking /etc/lilo.conf, please run "lilo". |
| 266 | h. lilo | 368 | |
| 267 | i. rdev -R /vmlinuz 1 | 369 | Note that if the result of "make bzImage" is ERROR, then you have to |
| 268 | j. sync | 370 | go back to Linux configuration Setup. Type "make menuconfig" in |
| 269 | 371 | directory /usr/src/linux. | |
| 270 | Note that if the result of "make zImage" is ERROR, then you have to | 372 | |
| 271 | go back to Linux configuration Setup. Type "make config" in directory | 373 | |
| 272 | /usr/src/linux or "setup". | 374 | 3.5.6 Make tty device and special file |
| 273 | |||
| 274 | Since system include file, /usr/src/linux/include/linux/interrupt.h, | ||
| 275 | is modified each time the MOXA driver is installed, kernel rebuilding | ||
| 276 | is inevitable. And it takes about 10 to 20 minutes depends on the | ||
| 277 | machine. | ||
| 278 | |||
| 279 | 7. Make utility | ||
| 280 | # cd /moxa/mxser/utility | ||
| 281 | # make install | ||
| 282 | |||
| 283 | 8. Make special file | ||
| 284 | # cd /moxa/mxser/driver | 375 | # cd /moxa/mxser/driver |
| 285 | # ./msmknod | 376 | # ./msmknod |
| 286 | 377 | ||
| 287 | 9. Reboot | 378 | 3.5.7 Make utility |
| 379 | # cd /moxa/mxser/utility | ||
| 380 | # make clean; make install | ||
| 381 | |||
| 382 | 3.5.8 Reboot | ||
| 288 | 383 | ||
| 289 | 3.5 Custom configuration | 384 | |
| 385 | |||
| 386 | 3.6 Custom configuration | ||
| 290 | Although this driver already provides you default configuration, you | 387 | Although this driver already provides you default configuration, you |
| 291 | still can change the device name and major number.The instruction to | 388 | still can change the device name and major number. The instruction to |
| 292 | change these parameters are shown as below. | 389 | change these parameters are shown as below. |
| 293 | 390 | ||
| 294 | Change Device name | 391 | Change Device name |
| @@ -306,33 +403,37 @@ Content | |||
| 306 | 2 free major numbers for this driver. There are 3 steps to change | 403 | 2 free major numbers for this driver. There are 3 steps to change |
| 307 | major numbers. | 404 | major numbers. |
| 308 | 405 | ||
| 309 | 1. Find free major numbers | 406 | 3.6.1 Find free major numbers |
| 310 | In /proc/devices, you may find all the major numbers occupied | 407 | In /proc/devices, you may find all the major numbers occupied |
| 311 | in the system. Please select 2 major numbers that are available. | 408 | in the system. Please select 2 major numbers that are available. |
| 312 | e.g. 40, 45. | 409 | e.g. 40, 45. |
| 313 | 2. Create special files | 410 | 3.6.2 Create special files |
| 314 | Run /moxa/mxser/driver/msmknod to create special files with | 411 | Run /moxa/mxser/driver/msmknod to create special files with |
| 315 | specified major numbers. | 412 | specified major numbers. |
| 316 | 3. Modify driver with new major number | 413 | 3.6.3 Modify driver with new major number |
| 317 | Run vi to open /moxa/mxser/driver/mxser.c. Locate the line | 414 | Run vi to open /moxa/mxser/driver/mxser.c. Locate the line |
| 318 | contains "MXSERMAJOR". Change the content as below. | 415 | contains "MXSERMAJOR". Change the content as below. |
| 319 | #define MXSERMAJOR 40 | 416 | #define MXSERMAJOR 40 |
| 320 | #define MXSERCUMAJOR 45 | 417 | #define MXSERCUMAJOR 45 |
| 321 | 4. Run # make install in /moxa/mxser/driver. | 418 | 3.6.4 Run "make clean; make install" in /moxa/mxser/driver. |
| 322 | 419 | ||
| 323 | 3.6 Verify driver installation | 420 | 3.7 Verify driver installation |
| 324 | You may refer to /var/log/messages to check the latest status | 421 | You may refer to /var/log/messages to check the latest status |
| 325 | log reported by this driver whenever it's activated. | 422 | log reported by this driver whenever it's activated. |
| 423 | |||
| 326 | ----------------------------------------------------------------------------- | 424 | ----------------------------------------------------------------------------- |
| 327 | 4. Utilities | 425 | 4. Utilities |
| 328 | There are 3 utilities contained in this driver. They are msdiag, msmon and | 426 | There are 3 utilities contained in this driver. They are msdiag, msmon and |
| 329 | msterm. These 3 utilities are released in form of source code. They should | 427 | msterm. These 3 utilities are released in form of source code. They should |
| 330 | be compiled into executable file and copied into /usr/bin. | 428 | be compiled into executable file and copied into /usr/bin. |
| 331 | 429 | ||
| 430 | Before using these utilities, please load driver (refer 3.4 & 3.5) and | ||
| 431 | make sure you had run the "msmknod" utility. | ||
| 432 | |||
| 332 | msdiag - Diagnostic | 433 | msdiag - Diagnostic |
| 333 | -------------------- | 434 | -------------------- |
| 334 | This utility provides the function to detect what Moxa Smartio multiport | 435 | This utility provides the function to display what Moxa Smartio/Industio |
| 335 | board exists in the system. | 436 | board found by driver in the system. |
| 336 | 437 | ||
| 337 | msmon - Port Monitoring | 438 | msmon - Port Monitoring |
| 338 | ----------------------- | 439 | ----------------------- |
| @@ -353,12 +454,13 @@ Content | |||
| 353 | application, for example, sending AT command to a modem connected to the | 454 | application, for example, sending AT command to a modem connected to the |
| 354 | port or used as a terminal for login purpose. Note that this is only a | 455 | port or used as a terminal for login purpose. Note that this is only a |
| 355 | dumb terminal emulation without handling full screen operation. | 456 | dumb terminal emulation without handling full screen operation. |
| 457 | |||
| 356 | ----------------------------------------------------------------------------- | 458 | ----------------------------------------------------------------------------- |
| 357 | 5. Setserial | 459 | 5. Setserial |
| 358 | 460 | ||
| 359 | Supported Setserial parameters are listed as below. | 461 | Supported Setserial parameters are listed as below. |
| 360 | 462 | ||
| 361 | uart set UART type(16450-->disable FIFO, 16550A-->enable FIFO) | 463 | uart set UART type(16450-->disable FIFO, 16550A-->enable FIFO) |
| 362 | close_delay set the amount of time(in 1/100 of a second) that DTR | 464 | close_delay set the amount of time(in 1/100 of a second) that DTR |
| 363 | should be kept low while being closed. | 465 | should be kept low while being closed. |
| 364 | closing_wait set the amount of time(in 1/100 of a second) that the | 466 | closing_wait set the amount of time(in 1/100 of a second) that the |
| @@ -366,7 +468,13 @@ Content | |||
| 366 | being closed, before the receiver is disable. | 468 | being closed, before the receiver is disable. |
| 367 | spd_hi Use 57.6kb when the application requests 38.4kb. | 469 | spd_hi Use 57.6kb when the application requests 38.4kb. |
| 368 | spd_vhi Use 115.2kb when the application requests 38.4kb. | 470 | spd_vhi Use 115.2kb when the application requests 38.4kb. |
| 471 | spd_shi Use 230.4kb when the application requests 38.4kb. | ||
| 472 | spd_warp Use 460.8kb when the application requests 38.4kb. | ||
| 369 | spd_normal Use 38.4kb when the application requests 38.4kb. | 473 | spd_normal Use 38.4kb when the application requests 38.4kb. |
| 474 | spd_cust Use the custom divisor to set the speed when the | ||
| 475 | application requests 38.4kb. | ||
| 476 | divisor This option set the custom divison. | ||
| 477 | baud_base This option set the base baud rate. | ||
| 370 | 478 | ||
| 371 | ----------------------------------------------------------------------------- | 479 | ----------------------------------------------------------------------------- |
| 372 | 6. Troubleshooting | 480 | 6. Troubleshooting |
| @@ -375,8 +483,9 @@ Content | |||
| 375 | possible. If all the possible solutions fail, please contact our technical | 483 | possible. If all the possible solutions fail, please contact our technical |
| 376 | support team to get more help. | 484 | support team to get more help. |
| 377 | 485 | ||
| 378 | Error msg: More than 4 Moxa Smartio family boards found. Fifth board and | 486 | |
| 379 | after are ignored. | 487 | Error msg: More than 4 Moxa Smartio/Industio family boards found. Fifth board |
| 488 | and after are ignored. | ||
| 380 | Solution: | 489 | Solution: |
| 381 | To avoid this problem, please unplug fifth and after board, because Moxa | 490 | To avoid this problem, please unplug fifth and after board, because Moxa |
| 382 | driver supports up to 4 boards. | 491 | driver supports up to 4 boards. |
| @@ -384,7 +493,7 @@ Content | |||
| 384 | Error msg: Request_irq fail, IRQ(?) may be conflict with another device. | 493 | Error msg: Request_irq fail, IRQ(?) may be conflict with another device. |
| 385 | Solution: | 494 | Solution: |
| 386 | Other PCI or ISA devices occupy the assigned IRQ. If you are not sure | 495 | Other PCI or ISA devices occupy the assigned IRQ. If you are not sure |
| 387 | which device causes the situation,please check /proc/interrupts to find | 496 | which device causes the situation, please check /proc/interrupts to find |
| 388 | free IRQ and simply change another free IRQ for Moxa board. | 497 | free IRQ and simply change another free IRQ for Moxa board. |
| 389 | 498 | ||
| 390 | Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid. | 499 | Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid. |
| @@ -397,15 +506,18 @@ Content | |||
| 397 | Moxa ISA board needs an interrupt vector.Please refer to user's manual | 506 | Moxa ISA board needs an interrupt vector.Please refer to user's manual |
| 398 | "Hardware Installation" chapter to set interrupt vector. | 507 | "Hardware Installation" chapter to set interrupt vector. |
| 399 | 508 | ||
| 400 | Error msg: Couldn't install MOXA Smartio family driver! | 509 | Error msg: Couldn't install MOXA Smartio/Industio family driver! |
| 401 | Solution: | 510 | Solution: |
| 402 | Load Moxa driver fail, the major number may conflict with other devices. | 511 | Load Moxa driver fail, the major number may conflict with other devices. |
| 403 | Please refer to previous section 3.5 to change a free major number for | 512 | Please refer to previous section 3.7 to change a free major number for |
| 404 | Moxa driver. | 513 | Moxa driver. |
| 405 | 514 | ||
| 406 | Error msg: Couldn't install MOXA Smartio family callout driver! | 515 | Error msg: Couldn't install MOXA Smartio/Industio family callout driver! |
| 407 | Solution: | 516 | Solution: |
| 408 | Load Moxa callout driver fail, the callout device major number may | 517 | Load Moxa callout driver fail, the callout device major number may |
| 409 | conflict with other devices. Please refer to previous section 3.5 to | 518 | conflict with other devices. Please refer to previous section 3.7 to |
| 410 | change a free callout device major number for Moxa driver. | 519 | change a free callout device major number for Moxa driver. |
| 520 | |||
| 521 | |||
| 411 | ----------------------------------------------------------------------------- | 522 | ----------------------------------------------------------------------------- |
| 523 | |||
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index ea1b70b35793..99514ced82c5 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
| @@ -59,6 +59,7 @@ Table of Contents | |||
| 59 | p) Freescale Synchronous Serial Interface | 59 | p) Freescale Synchronous Serial Interface |
| 60 | q) USB EHCI controllers | 60 | q) USB EHCI controllers |
| 61 | r) MDIO on GPIOs | 61 | r) MDIO on GPIOs |
| 62 | s) SPI busses | ||
| 62 | 63 | ||
| 63 | VII - Marvell Discovery mv64[345]6x System Controller chips | 64 | VII - Marvell Discovery mv64[345]6x System Controller chips |
| 64 | 1) The /system-controller node | 65 | 1) The /system-controller node |
| @@ -1883,6 +1884,62 @@ platforms are moved over to use the flattened-device-tree model. | |||
| 1883 | &qe_pio_c 6>; | 1884 | &qe_pio_c 6>; |
| 1884 | }; | 1885 | }; |
| 1885 | 1886 | ||
| 1887 | s) SPI (Serial Peripheral Interface) busses | ||
| 1888 | |||
| 1889 | SPI busses can be described with a node for the SPI master device | ||
| 1890 | and a set of child nodes for each SPI slave on the bus. For this | ||
| 1891 | discussion, it is assumed that the system's SPI controller is in | ||
| 1892 | SPI master mode. This binding does not describe SPI controllers | ||
| 1893 | in slave mode. | ||
| 1894 | |||
| 1895 | The SPI master node requires the following properties: | ||
| 1896 | - #address-cells - number of cells required to define a chip select | ||
| 1897 | address on the SPI bus. | ||
| 1898 | - #size-cells - should be zero. | ||
| 1899 | - compatible - name of SPI bus controller following generic names | ||
| 1900 | recommended practice. | ||
| 1901 | No other properties are required in the SPI bus node. It is assumed | ||
| 1902 | that a driver for an SPI bus device will understand that it is an SPI bus. | ||
| 1903 | However, the binding does not attempt to define the specific method for | ||
| 1904 | assigning chip select numbers. Since SPI chip select configuration is | ||
| 1905 | flexible and non-standardized, it is left out of this binding with the | ||
| 1906 | assumption that board specific platform code will be used to manage | ||
| 1907 | chip selects. Individual drivers can define additional properties to | ||
| 1908 | support describing the chip select layout. | ||
| 1909 | |||
| 1910 | SPI slave nodes must be children of the SPI master node and can | ||
| 1911 | contain the following properties. | ||
| 1912 | - reg - (required) chip select address of device. | ||
| 1913 | - compatible - (required) name of SPI device following generic names | ||
| 1914 | recommended practice | ||
| 1915 | - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz | ||
| 1916 | - spi-cpol - (optional) Empty property indicating device requires | ||
| 1917 | inverse clock polarity (CPOL) mode | ||
| 1918 | - spi-cpha - (optional) Empty property indicating device requires | ||
| 1919 | shifted clock phase (CPHA) mode | ||
| 1920 | |||
| 1921 | SPI example for an MPC5200 SPI bus: | ||
| 1922 | spi@f00 { | ||
| 1923 | #address-cells = <1>; | ||
| 1924 | #size-cells = <0>; | ||
| 1925 | compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi"; | ||
| 1926 | reg = <0xf00 0x20>; | ||
| 1927 | interrupts = <2 13 0 2 14 0>; | ||
| 1928 | interrupt-parent = <&mpc5200_pic>; | ||
| 1929 | |||
| 1930 | ethernet-switch@0 { | ||
| 1931 | compatible = "micrel,ks8995m"; | ||
| 1932 | spi-max-frequency = <1000000>; | ||
| 1933 | reg = <0>; | ||
| 1934 | }; | ||
| 1935 | |||
| 1936 | codec@1 { | ||
| 1937 | compatible = "ti,tlv320aic26"; | ||
| 1938 | spi-max-frequency = <100000>; | ||
| 1939 | reg = <1>; | ||
| 1940 | }; | ||
| 1941 | }; | ||
| 1942 | |||
| 1886 | VII - Marvell Discovery mv64[345]6x System Controller chips | 1943 | VII - Marvell Discovery mv64[345]6x System Controller chips |
| 1887 | =========================================================== | 1944 | =========================================================== |
| 1888 | 1945 | ||
diff --git a/Documentation/unaligned-memory-access.txt b/Documentation/unaligned-memory-access.txt index b0472ac5226a..f866c72291bf 100644 --- a/Documentation/unaligned-memory-access.txt +++ b/Documentation/unaligned-memory-access.txt | |||
| @@ -218,9 +218,35 @@ If use of such macros is not convenient, another option is to use memcpy(), | |||
| 218 | where the source or destination (or both) are of type u8* or unsigned char*. | 218 | where the source or destination (or both) are of type u8* or unsigned char*. |
| 219 | Due to the byte-wise nature of this operation, unaligned accesses are avoided. | 219 | Due to the byte-wise nature of this operation, unaligned accesses are avoided. |
| 220 | 220 | ||
| 221 | |||
| 222 | Alignment vs. Networking | ||
| 223 | ======================== | ||
| 224 | |||
| 225 | On architectures that require aligned loads, networking requires that the IP | ||
| 226 | header is aligned on a four-byte boundary to optimise the IP stack. For | ||
| 227 | regular ethernet hardware, the constant NET_IP_ALIGN is used. On most | ||
| 228 | architectures this constant has the value 2 because the normal ethernet | ||
| 229 | header is 14 bytes long, so in order to get proper alignment one needs to | ||
| 230 | DMA to an address which can be expressed as 4*n + 2. One notable exception | ||
| 231 | here is powerpc which defines NET_IP_ALIGN to 0 because DMA to unaligned | ||
| 232 | addresses can be very expensive and dwarf the cost of unaligned loads. | ||
| 233 | |||
| 234 | For some ethernet hardware that cannot DMA to unaligned addresses like | ||
| 235 | 4*n+2 or non-ethernet hardware, this can be a problem, and it is then | ||
| 236 | required to copy the incoming frame into an aligned buffer. Because this is | ||
| 237 | unnecessary on architectures that can do unaligned accesses, the code can be | ||
| 238 | made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so: | ||
| 239 | |||
| 240 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
| 241 | skb = original skb | ||
| 242 | #else | ||
| 243 | skb = copy skb | ||
| 244 | #endif | ||
| 245 | |||
| 221 | -- | 246 | -- |
| 222 | Author: Daniel Drake <dsd@gentoo.org> | 247 | Authors: Daniel Drake <dsd@gentoo.org>, |
| 248 | Johannes Berg <johannes@sipsolutions.net> | ||
| 223 | With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, | 249 | With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt, |
| 224 | Johannes Berg, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, | 250 | Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz, |
| 225 | Uli Kunitz, Vadim Lobanov | 251 | Vadim Lobanov |
| 226 | 252 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index be05ef9b7b42..4cbf6016a9b9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -1043,6 +1043,12 @@ M: fujita.tomonori@lab.ntt.co.jp | |||
| 1043 | L: linux-scsi@vger.kernel.org | 1043 | L: linux-scsi@vger.kernel.org |
| 1044 | S: Supported | 1044 | S: Supported |
| 1045 | 1045 | ||
| 1046 | BT8XXGPIO DRIVER | ||
| 1047 | P: Michael Buesch | ||
| 1048 | M: mb@bu3sch.de | ||
| 1049 | W: http://bu3sch.de/btgpio.php | ||
| 1050 | S: Maintained | ||
| 1051 | |||
| 1046 | BTTV VIDEO4LINUX DRIVER | 1052 | BTTV VIDEO4LINUX DRIVER |
| 1047 | P: Mauro Carvalho Chehab | 1053 | P: Mauro Carvalho Chehab |
| 1048 | M: mchehab@infradead.org | 1054 | M: mchehab@infradead.org |
| @@ -1061,6 +1061,7 @@ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) | |||
| 1061 | $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order | 1061 | $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order |
| 1062 | @echo ' Building modules, stage 2.'; | 1062 | @echo ' Building modules, stage 2.'; |
| 1063 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost | 1063 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost |
| 1064 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild | ||
| 1064 | 1065 | ||
| 1065 | 1066 | ||
| 1066 | # Target to prepare building external modules | 1067 | # Target to prepare building external modules |
diff --git a/arch/Kconfig b/arch/Kconfig index 6093c0be58b0..b0fabfa864ff 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
| @@ -27,6 +27,25 @@ config KPROBES | |||
| 27 | for kernel debugging, non-intrusive instrumentation and testing. | 27 | for kernel debugging, non-intrusive instrumentation and testing. |
| 28 | If in doubt, say "N". | 28 | If in doubt, say "N". |
| 29 | 29 | ||
| 30 | config HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
| 31 | def_bool n | ||
| 32 | help | ||
| 33 | Some architectures are unable to perform unaligned accesses | ||
| 34 | without the use of get_unaligned/put_unaligned. Others are | ||
| 35 | unable to perform such accesses efficiently (e.g. trap on | ||
| 36 | unaligned access and require fixing it up in the exception | ||
| 37 | handler.) | ||
| 38 | |||
| 39 | This symbol should be selected by an architecture if it can | ||
| 40 | perform unaligned accesses efficiently to allow different | ||
| 41 | code paths to be selected for these cases. Some network | ||
| 42 | drivers, for example, could opt to not fix up alignment | ||
| 43 | problems with received packets if doing so would not help | ||
| 44 | much. | ||
| 45 | |||
| 46 | See Documentation/unaligned-memory-access.txt for more | ||
| 47 | information on the topic of unaligned memory accesses. | ||
| 48 | |||
| 30 | config KRETPROBES | 49 | config KRETPROBES |
| 31 | def_bool y | 50 | def_bool y |
| 32 | depends on KPROBES && HAVE_KRETPROBES | 51 | depends on KPROBES && HAVE_KRETPROBES |
diff --git a/arch/alpha/boot/misc.c b/arch/alpha/boot/misc.c index c00646b25f6e..3047a1b3a517 100644 --- a/arch/alpha/boot/misc.c +++ b/arch/alpha/boot/misc.c | |||
| @@ -78,8 +78,6 @@ static unsigned outcnt; /* bytes in output buffer */ | |||
| 78 | static int fill_inbuf(void); | 78 | static int fill_inbuf(void); |
| 79 | static void flush_window(void); | 79 | static void flush_window(void); |
| 80 | static void error(char *m); | 80 | static void error(char *m); |
| 81 | static void gzip_mark(void **); | ||
| 82 | static void gzip_release(void **); | ||
| 83 | 81 | ||
| 84 | static char *input_data; | 82 | static char *input_data; |
| 85 | static int input_data_size; | 83 | static int input_data_size; |
| @@ -88,51 +86,18 @@ static uch *output_data; | |||
| 88 | static ulg output_ptr; | 86 | static ulg output_ptr; |
| 89 | static ulg bytes_out; | 87 | static ulg bytes_out; |
| 90 | 88 | ||
| 91 | static void *malloc(int size); | ||
| 92 | static void free(void *where); | ||
| 93 | static void error(char *m); | 89 | static void error(char *m); |
| 94 | static void gzip_mark(void **); | 90 | static void gzip_mark(void **); |
| 95 | static void gzip_release(void **); | 91 | static void gzip_release(void **); |
| 96 | 92 | ||
| 97 | extern int end; | 93 | extern int end; |
| 98 | static ulg free_mem_ptr; | 94 | static ulg free_mem_ptr; |
| 99 | static ulg free_mem_ptr_end; | 95 | static ulg free_mem_end_ptr; |
| 100 | 96 | ||
| 101 | #define HEAP_SIZE 0x3000 | 97 | #define HEAP_SIZE 0x3000 |
| 102 | 98 | ||
| 103 | #include "../../../lib/inflate.c" | 99 | #include "../../../lib/inflate.c" |
| 104 | 100 | ||
| 105 | static void *malloc(int size) | ||
| 106 | { | ||
| 107 | void *p; | ||
| 108 | |||
| 109 | if (size <0) error("Malloc error"); | ||
| 110 | if (free_mem_ptr <= 0) error("Memory error"); | ||
| 111 | |||
| 112 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 113 | |||
| 114 | p = (void *)free_mem_ptr; | ||
| 115 | free_mem_ptr += size; | ||
| 116 | |||
| 117 | if (free_mem_ptr >= free_mem_ptr_end) | ||
| 118 | error("Out of memory"); | ||
| 119 | return p; | ||
| 120 | } | ||
| 121 | |||
| 122 | static void free(void *where) | ||
| 123 | { /* gzip_mark & gzip_release do the free */ | ||
| 124 | } | ||
| 125 | |||
| 126 | static void gzip_mark(void **ptr) | ||
| 127 | { | ||
| 128 | *ptr = (void *) free_mem_ptr; | ||
| 129 | } | ||
| 130 | |||
| 131 | static void gzip_release(void **ptr) | ||
| 132 | { | ||
| 133 | free_mem_ptr = (long) *ptr; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* =========================================================================== | 101 | /* =========================================================================== |
| 137 | * Fill the input buffer. This is called only when the buffer is empty | 102 | * Fill the input buffer. This is called only when the buffer is empty |
| 138 | * and at least one byte is really needed. | 103 | * and at least one byte is really needed. |
| @@ -193,7 +158,7 @@ decompress_kernel(void *output_start, | |||
| 193 | 158 | ||
| 194 | /* FIXME FIXME FIXME */ | 159 | /* FIXME FIXME FIXME */ |
| 195 | free_mem_ptr = (ulg)output_start + ksize; | 160 | free_mem_ptr = (ulg)output_start + ksize; |
| 196 | free_mem_ptr_end = (ulg)output_start + ksize + 0x200000; | 161 | free_mem_end_ptr = (ulg)output_start + ksize + 0x200000; |
| 197 | /* FIXME FIXME FIXME */ | 162 | /* FIXME FIXME FIXME */ |
| 198 | 163 | ||
| 199 | /* put in temp area to reduce initial footprint */ | 164 | /* put in temp area to reduce initial footprint */ |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6fb4f03369f2..dabb015aa40b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -268,7 +268,7 @@ config ARCH_EP93XX | |||
| 268 | select GENERIC_GPIO | 268 | select GENERIC_GPIO |
| 269 | select HAVE_CLK | 269 | select HAVE_CLK |
| 270 | select HAVE_CLK | 270 | select HAVE_CLK |
| 271 | select HAVE_GPIO_LIB | 271 | select ARCH_REQUIRE_GPIOLIB |
| 272 | help | 272 | help |
| 273 | This enables support for the Cirrus EP93xx series of CPUs. | 273 | This enables support for the Cirrus EP93xx series of CPUs. |
| 274 | 274 | ||
| @@ -447,7 +447,7 @@ config ARCH_PXA | |||
| 447 | select ARCH_MTD_XIP | 447 | select ARCH_MTD_XIP |
| 448 | select GENERIC_GPIO | 448 | select GENERIC_GPIO |
| 449 | select HAVE_CLK | 449 | select HAVE_CLK |
| 450 | select HAVE_GPIO_LIB | 450 | select ARCH_REQUIRE_GPIOLIB |
| 451 | select GENERIC_TIME | 451 | select GENERIC_TIME |
| 452 | select GENERIC_CLOCKEVENTS | 452 | select GENERIC_CLOCKEVENTS |
| 453 | select TICK_ONESHOT | 453 | select TICK_ONESHOT |
| @@ -479,7 +479,7 @@ config ARCH_SA1100 | |||
| 479 | select GENERIC_CLOCKEVENTS | 479 | select GENERIC_CLOCKEVENTS |
| 480 | select HAVE_CLK | 480 | select HAVE_CLK |
| 481 | select TICK_ONESHOT | 481 | select TICK_ONESHOT |
| 482 | select HAVE_GPIO_LIB | 482 | select ARCH_REQUIRE_GPIOLIB |
| 483 | help | 483 | help |
| 484 | Support for StrongARM 11x0 based boards. | 484 | Support for StrongARM 11x0 based boards. |
| 485 | 485 | ||
| @@ -522,7 +522,7 @@ config ARCH_OMAP | |||
| 522 | bool "TI OMAP" | 522 | bool "TI OMAP" |
| 523 | select GENERIC_GPIO | 523 | select GENERIC_GPIO |
| 524 | select HAVE_CLK | 524 | select HAVE_CLK |
| 525 | select HAVE_GPIO_LIB | 525 | select ARCH_REQUIRE_GPIOLIB |
| 526 | select GENERIC_TIME | 526 | select GENERIC_TIME |
| 527 | select GENERIC_CLOCKEVENTS | 527 | select GENERIC_CLOCKEVENTS |
| 528 | help | 528 | help |
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 9b444022cb9b..7145cc7c04f0 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c | |||
| @@ -217,8 +217,6 @@ static unsigned outcnt; /* bytes in output buffer */ | |||
| 217 | static int fill_inbuf(void); | 217 | static int fill_inbuf(void); |
| 218 | static void flush_window(void); | 218 | static void flush_window(void); |
| 219 | static void error(char *m); | 219 | static void error(char *m); |
| 220 | static void gzip_mark(void **); | ||
| 221 | static void gzip_release(void **); | ||
| 222 | 220 | ||
| 223 | extern char input_data[]; | 221 | extern char input_data[]; |
| 224 | extern char input_data_end[]; | 222 | extern char input_data_end[]; |
| @@ -227,64 +225,21 @@ static uch *output_data; | |||
| 227 | static ulg output_ptr; | 225 | static ulg output_ptr; |
| 228 | static ulg bytes_out; | 226 | static ulg bytes_out; |
| 229 | 227 | ||
| 230 | static void *malloc(int size); | ||
| 231 | static void free(void *where); | ||
| 232 | static void error(char *m); | 228 | static void error(char *m); |
| 233 | static void gzip_mark(void **); | ||
| 234 | static void gzip_release(void **); | ||
| 235 | 229 | ||
| 236 | static void putstr(const char *); | 230 | static void putstr(const char *); |
| 237 | 231 | ||
| 238 | extern int end; | 232 | extern int end; |
| 239 | static ulg free_mem_ptr; | 233 | static ulg free_mem_ptr; |
| 240 | static ulg free_mem_ptr_end; | 234 | static ulg free_mem_end_ptr; |
| 241 | 235 | ||
| 242 | #define HEAP_SIZE 0x3000 | 236 | #ifdef STANDALONE_DEBUG |
| 243 | 237 | #define NO_INFLATE_MALLOC | |
| 244 | #include "../../../../lib/inflate.c" | 238 | #endif |
| 245 | |||
| 246 | #ifndef STANDALONE_DEBUG | ||
| 247 | static void *malloc(int size) | ||
| 248 | { | ||
| 249 | void *p; | ||
| 250 | |||
| 251 | if (size <0) error("Malloc error"); | ||
| 252 | if (free_mem_ptr <= 0) error("Memory error"); | ||
| 253 | |||
| 254 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 255 | |||
| 256 | p = (void *)free_mem_ptr; | ||
| 257 | free_mem_ptr += size; | ||
| 258 | |||
| 259 | if (free_mem_ptr >= free_mem_ptr_end) | ||
| 260 | error("Out of memory"); | ||
| 261 | return p; | ||
| 262 | } | ||
| 263 | |||
| 264 | static void free(void *where) | ||
| 265 | { /* gzip_mark & gzip_release do the free */ | ||
| 266 | } | ||
| 267 | |||
| 268 | static void gzip_mark(void **ptr) | ||
| 269 | { | ||
| 270 | arch_decomp_wdog(); | ||
| 271 | *ptr = (void *) free_mem_ptr; | ||
| 272 | } | ||
| 273 | 239 | ||
| 274 | static void gzip_release(void **ptr) | 240 | #define ARCH_HAS_DECOMP_WDOG |
| 275 | { | ||
| 276 | arch_decomp_wdog(); | ||
| 277 | free_mem_ptr = (long) *ptr; | ||
| 278 | } | ||
| 279 | #else | ||
| 280 | static void gzip_mark(void **ptr) | ||
| 281 | { | ||
| 282 | } | ||
| 283 | 241 | ||
| 284 | static void gzip_release(void **ptr) | 242 | #include "../../../../lib/inflate.c" |
| 285 | { | ||
| 286 | } | ||
| 287 | #endif | ||
| 288 | 243 | ||
| 289 | /* =========================================================================== | 244 | /* =========================================================================== |
| 290 | * Fill the input buffer. This is called only when the buffer is empty | 245 | * Fill the input buffer. This is called only when the buffer is empty |
| @@ -348,7 +303,7 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, | |||
| 348 | { | 303 | { |
| 349 | output_data = (uch *)output_start; /* Points to kernel start */ | 304 | output_data = (uch *)output_start; /* Points to kernel start */ |
| 350 | free_mem_ptr = free_mem_ptr_p; | 305 | free_mem_ptr = free_mem_ptr_p; |
| 351 | free_mem_ptr_end = free_mem_ptr_end_p; | 306 | free_mem_end_ptr = free_mem_ptr_end_p; |
| 352 | __machine_arch_type = arch_id; | 307 | __machine_arch_type = arch_id; |
| 353 | 308 | ||
| 354 | arch_decomp_setup(); | 309 | arch_decomp_setup(); |
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 5ee39e10c8d1..d28513f14d05 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
| @@ -296,8 +296,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
| 296 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 296 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; |
| 297 | 297 | ||
| 298 | INIT_HLIST_HEAD(&empty_rp); | 298 | INIT_HLIST_HEAD(&empty_rp); |
| 299 | spin_lock_irqsave(&kretprobe_lock, flags); | 299 | kretprobe_hash_lock(current, &head, &flags); |
| 300 | head = kretprobe_inst_table_head(current); | ||
| 301 | 300 | ||
| 302 | /* | 301 | /* |
| 303 | * It is possible to have multiple instances associated with a given | 302 | * It is possible to have multiple instances associated with a given |
| @@ -337,7 +336,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
| 337 | } | 336 | } |
| 338 | 337 | ||
| 339 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 338 | kretprobe_assert(ri, orig_ret_address, trampoline_address); |
| 340 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 339 | kretprobe_hash_unlock(current, &flags); |
| 341 | 340 | ||
| 342 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 341 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
| 343 | hlist_del(&ri->hlist); | 342 | hlist_del(&ri->hlist); |
| @@ -347,7 +346,6 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
| 347 | return (void *)orig_ret_address; | 346 | return (void *)orig_ret_address; |
| 348 | } | 347 | } |
| 349 | 348 | ||
| 350 | /* Called with kretprobe_lock held. */ | ||
| 351 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 349 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
| 352 | struct pt_regs *regs) | 350 | struct pt_regs *regs) |
| 353 | { | 351 | { |
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 1903a3491ee9..d8e9c2c3f0f6 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
| @@ -1488,6 +1488,9 @@ static int __init _omap_gpio_init(void) | |||
| 1488 | bank->chip.set = gpio_set; | 1488 | bank->chip.set = gpio_set; |
| 1489 | if (bank_is_mpuio(bank)) { | 1489 | if (bank_is_mpuio(bank)) { |
| 1490 | bank->chip.label = "mpuio"; | 1490 | bank->chip.label = "mpuio"; |
| 1491 | #ifdef CONFIG_ARCH_OMAP1 | ||
| 1492 | bank->chip.dev = &omap_mpuio_device.dev; | ||
| 1493 | #endif | ||
| 1491 | bank->chip.base = OMAP_MPUIO(0); | 1494 | bank->chip.base = OMAP_MPUIO(0); |
| 1492 | } else { | 1495 | } else { |
| 1493 | bank->chip.label = "gpio"; | 1496 | bank->chip.label = "gpio"; |
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index df4adefedb42..7c239a916275 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
| @@ -88,7 +88,7 @@ config PLATFORM_AT32AP | |||
| 88 | select SUBARCH_AVR32B | 88 | select SUBARCH_AVR32B |
| 89 | select MMU | 89 | select MMU |
| 90 | select PERFORMANCE_COUNTERS | 90 | select PERFORMANCE_COUNTERS |
| 91 | select HAVE_GPIO_LIB | 91 | select ARCH_REQUIRE_GPIOLIB |
| 92 | select GENERIC_ALLOCATOR | 92 | select GENERIC_ALLOCATOR |
| 93 | 93 | ||
| 94 | # | 94 | # |
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 60da03ba7117..296294f8ed81 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c | |||
| @@ -360,6 +360,8 @@ static int __init pio_probe(struct platform_device *pdev) | |||
| 360 | pio->chip.label = pio->name; | 360 | pio->chip.label = pio->name; |
| 361 | pio->chip.base = pdev->id * 32; | 361 | pio->chip.base = pdev->id * 32; |
| 362 | pio->chip.ngpio = 32; | 362 | pio->chip.ngpio = 32; |
| 363 | pio->chip.dev = &pdev->dev; | ||
| 364 | pio->chip.owner = THIS_MODULE; | ||
| 363 | 365 | ||
| 364 | pio->chip.direction_input = direction_input; | 366 | pio->chip.direction_input = direction_input; |
| 365 | pio->chip.get = gpio_get; | 367 | pio->chip.get = gpio_get; |
diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c index 18e13bce1400..d933c89889db 100644 --- a/arch/cris/arch-v10/boot/compressed/misc.c +++ b/arch/cris/arch-v10/boot/compressed/misc.c | |||
| @@ -102,50 +102,16 @@ extern char *input_data; /* lives in head.S */ | |||
| 102 | static long bytes_out = 0; | 102 | static long bytes_out = 0; |
| 103 | static uch *output_data; | 103 | static uch *output_data; |
| 104 | static unsigned long output_ptr = 0; | 104 | static unsigned long output_ptr = 0; |
| 105 | |||
| 106 | static void *malloc(int size); | ||
| 107 | static void free(void *where); | ||
| 108 | static void gzip_mark(void **); | ||
| 109 | static void gzip_release(void **); | ||
| 110 | |||
| 111 | static void puts(const char *); | 105 | static void puts(const char *); |
| 112 | 106 | ||
| 113 | /* the "heap" is put directly after the BSS ends, at end */ | 107 | /* the "heap" is put directly after the BSS ends, at end */ |
| 114 | 108 | ||
| 115 | extern int _end; | 109 | extern int _end; |
| 116 | static long free_mem_ptr = (long)&_end; | 110 | static long free_mem_ptr = (long)&_end; |
| 111 | static long free_mem_end_ptr; | ||
| 117 | 112 | ||
| 118 | #include "../../../../../lib/inflate.c" | 113 | #include "../../../../../lib/inflate.c" |
| 119 | 114 | ||
| 120 | static void *malloc(int size) | ||
| 121 | { | ||
| 122 | void *p; | ||
| 123 | |||
| 124 | if (size < 0) | ||
| 125 | error("Malloc error"); | ||
| 126 | |||
| 127 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 128 | |||
| 129 | p = (void *)free_mem_ptr; | ||
| 130 | free_mem_ptr += size; | ||
| 131 | |||
| 132 | return p; | ||
| 133 | } | ||
| 134 | |||
| 135 | static void free(void *where) | ||
| 136 | { /* Don't care */ | ||
| 137 | } | ||
| 138 | |||
| 139 | static void gzip_mark(void **ptr) | ||
| 140 | { | ||
| 141 | *ptr = (void *) free_mem_ptr; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void gzip_release(void **ptr) | ||
| 145 | { | ||
| 146 | free_mem_ptr = (long) *ptr; | ||
| 147 | } | ||
| 148 | |||
| 149 | /* decompressor info and error messages to serial console */ | 115 | /* decompressor info and error messages to serial console */ |
| 150 | 116 | ||
| 151 | static void | 117 | static void |
diff --git a/arch/cris/arch-v32/boot/compressed/misc.c b/arch/cris/arch-v32/boot/compressed/misc.c index 55b2695c5d70..3595e16e82bc 100644 --- a/arch/cris/arch-v32/boot/compressed/misc.c +++ b/arch/cris/arch-v32/boot/compressed/misc.c | |||
| @@ -89,20 +89,14 @@ static unsigned outcnt = 0; /* bytes in output buffer */ | |||
| 89 | 89 | ||
| 90 | static void flush_window(void); | 90 | static void flush_window(void); |
| 91 | static void error(char *m); | 91 | static void error(char *m); |
| 92 | static void gzip_mark(void **); | ||
| 93 | static void gzip_release(void **); | ||
| 94 | 92 | ||
| 95 | extern char *input_data; /* lives in head.S */ | 93 | extern char *input_data; /* lives in head.S */ |
| 96 | 94 | ||
| 97 | static long bytes_out = 0; | 95 | static long bytes_out; |
| 98 | static uch *output_data; | 96 | static uch *output_data; |
| 99 | static unsigned long output_ptr = 0; | 97 | static unsigned long output_ptr; |
| 100 | 98 | ||
| 101 | static void *malloc(int size); | ||
| 102 | static void free(void *where); | ||
| 103 | static void error(char *m); | 99 | static void error(char *m); |
| 104 | static void gzip_mark(void **); | ||
| 105 | static void gzip_release(void **); | ||
| 106 | 100 | ||
| 107 | static void puts(const char *); | 101 | static void puts(const char *); |
| 108 | 102 | ||
| @@ -110,37 +104,10 @@ static void puts(const char *); | |||
| 110 | 104 | ||
| 111 | extern int _end; | 105 | extern int _end; |
| 112 | static long free_mem_ptr = (long)&_end; | 106 | static long free_mem_ptr = (long)&_end; |
| 107 | static long free_mem_end_ptr; | ||
| 113 | 108 | ||
| 114 | #include "../../../../../lib/inflate.c" | 109 | #include "../../../../../lib/inflate.c" |
| 115 | 110 | ||
| 116 | static void *malloc(int size) | ||
| 117 | { | ||
| 118 | void *p; | ||
| 119 | |||
| 120 | if (size <0) error("Malloc error"); | ||
| 121 | |||
| 122 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 123 | |||
| 124 | p = (void *)free_mem_ptr; | ||
| 125 | free_mem_ptr += size; | ||
| 126 | |||
| 127 | return p; | ||
| 128 | } | ||
| 129 | |||
| 130 | static void free(void *where) | ||
| 131 | { /* Don't care */ | ||
| 132 | } | ||
| 133 | |||
| 134 | static void gzip_mark(void **ptr) | ||
| 135 | { | ||
| 136 | *ptr = (void *) free_mem_ptr; | ||
| 137 | } | ||
| 138 | |||
| 139 | static void gzip_release(void **ptr) | ||
| 140 | { | ||
| 141 | free_mem_ptr = (long) *ptr; | ||
| 142 | } | ||
| 143 | |||
| 144 | /* decompressor info and error messages to serial console */ | 111 | /* decompressor info and error messages to serial console */ |
| 145 | 112 | ||
| 146 | static inline void | 113 | static inline void |
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 085dc6ec152b..396ab059efa3 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig | |||
| @@ -203,20 +203,6 @@ config UNIX98_PTYS | |||
| 203 | Read the instructions in <file:Documentation/Changes> pertaining to | 203 | Read the instructions in <file:Documentation/Changes> pertaining to |
| 204 | pseudo terminals. It's safe to say N. | 204 | pseudo terminals. It's safe to say N. |
| 205 | 205 | ||
| 206 | config UNIX98_PTY_COUNT | ||
| 207 | int "Maximum number of Unix98 PTYs in use (0-2048)" | ||
| 208 | depends on UNIX98_PTYS | ||
| 209 | default "256" | ||
| 210 | help | ||
| 211 | The maximum number of Unix98 PTYs that can be used at any one time. | ||
| 212 | The default is 256, and should be enough for desktop systems. Server | ||
| 213 | machines which support incoming telnet/rlogin/ssh connections and/or | ||
| 214 | serve several X terminals may want to increase this: every incoming | ||
| 215 | connection and every xterm uses up one PTY. | ||
| 216 | |||
| 217 | When not in use, each additional set of 256 PTYs occupy | ||
| 218 | approximately 8 KB of kernel memory on 32-bit architectures. | ||
| 219 | |||
| 220 | source "drivers/char/pcmcia/Kconfig" | 206 | source "drivers/char/pcmcia/Kconfig" |
| 221 | 207 | ||
| 222 | source "drivers/serial/Kconfig" | 208 | source "drivers/serial/Kconfig" |
diff --git a/arch/h8300/boot/compressed/misc.c b/arch/h8300/boot/compressed/misc.c index 845074588af0..51ab6cbd030f 100644 --- a/arch/h8300/boot/compressed/misc.c +++ b/arch/h8300/boot/compressed/misc.c | |||
| @@ -67,8 +67,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */ | |||
| 67 | static int fill_inbuf(void); | 67 | static int fill_inbuf(void); |
| 68 | static void flush_window(void); | 68 | static void flush_window(void); |
| 69 | static void error(char *m); | 69 | static void error(char *m); |
| 70 | static void gzip_mark(void **); | ||
| 71 | static void gzip_release(void **); | ||
| 72 | 70 | ||
| 73 | extern char input_data[]; | 71 | extern char input_data[]; |
| 74 | extern int input_len; | 72 | extern int input_len; |
| @@ -77,11 +75,7 @@ static long bytes_out = 0; | |||
| 77 | static uch *output_data; | 75 | static uch *output_data; |
| 78 | static unsigned long output_ptr = 0; | 76 | static unsigned long output_ptr = 0; |
| 79 | 77 | ||
| 80 | static void *malloc(int size); | ||
| 81 | static void free(void *where); | ||
| 82 | static void error(char *m); | 78 | static void error(char *m); |
| 83 | static void gzip_mark(void **); | ||
| 84 | static void gzip_release(void **); | ||
| 85 | 79 | ||
| 86 | int puts(const char *); | 80 | int puts(const char *); |
| 87 | 81 | ||
| @@ -98,38 +92,6 @@ static unsigned long free_mem_end_ptr; | |||
| 98 | #define TDR *((volatile unsigned char *)0xffff8b) | 92 | #define TDR *((volatile unsigned char *)0xffff8b) |
| 99 | #define SSR *((volatile unsigned char *)0xffff8c) | 93 | #define SSR *((volatile unsigned char *)0xffff8c) |
| 100 | 94 | ||
| 101 | static void *malloc(int size) | ||
| 102 | { | ||
| 103 | void *p; | ||
| 104 | |||
| 105 | if (size <0) error("Malloc error"); | ||
| 106 | if (free_mem_ptr == 0) error("Memory error"); | ||
| 107 | |||
| 108 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 109 | |||
| 110 | p = (void *)free_mem_ptr; | ||
| 111 | free_mem_ptr += size; | ||
| 112 | |||
| 113 | if (free_mem_ptr >= free_mem_end_ptr) | ||
| 114 | error("Out of memory"); | ||
| 115 | |||
| 116 | return p; | ||
| 117 | } | ||
| 118 | |||
| 119 | static void free(void *where) | ||
| 120 | { /* Don't care */ | ||
| 121 | } | ||
| 122 | |||
| 123 | static void gzip_mark(void **ptr) | ||
| 124 | { | ||
| 125 | *ptr = (void *) free_mem_ptr; | ||
| 126 | } | ||
| 127 | |||
| 128 | static void gzip_release(void **ptr) | ||
| 129 | { | ||
| 130 | free_mem_ptr = (long) *ptr; | ||
| 131 | } | ||
| 132 | |||
| 133 | int puts(const char *s) | 95 | int puts(const char *s) |
| 134 | { | 96 | { |
| 135 | return 0; | 97 | return 0; |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 56ab156c48ae..0dd6c1419d8d 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
| @@ -1691,6 +1691,12 @@ sys_call_table: | |||
| 1691 | data8 sys_timerfd_create // 1310 | 1691 | data8 sys_timerfd_create // 1310 |
| 1692 | data8 sys_timerfd_settime | 1692 | data8 sys_timerfd_settime |
| 1693 | data8 sys_timerfd_gettime | 1693 | data8 sys_timerfd_gettime |
| 1694 | data8 sys_signalfd4 | ||
| 1695 | data8 sys_eventfd2 | ||
| 1696 | data8 sys_epoll_create1 // 1315 | ||
| 1697 | data8 sys_dup3 | ||
| 1698 | data8 sys_pipe2 | ||
| 1699 | data8 sys_inotify_init1 | ||
| 1694 | 1700 | ||
| 1695 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 1701 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
| 1696 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ | 1702 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 233434f4f88f..f07688da947c 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
| @@ -429,8 +429,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 429 | ((struct fnptr *)kretprobe_trampoline)->ip; | 429 | ((struct fnptr *)kretprobe_trampoline)->ip; |
| 430 | 430 | ||
| 431 | INIT_HLIST_HEAD(&empty_rp); | 431 | INIT_HLIST_HEAD(&empty_rp); |
| 432 | spin_lock_irqsave(&kretprobe_lock, flags); | 432 | kretprobe_hash_lock(current, &head, &flags); |
| 433 | head = kretprobe_inst_table_head(current); | ||
| 434 | 433 | ||
| 435 | /* | 434 | /* |
| 436 | * It is possible to have multiple instances associated with a given | 435 | * It is possible to have multiple instances associated with a given |
| @@ -485,7 +484,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 485 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 484 | kretprobe_assert(ri, orig_ret_address, trampoline_address); |
| 486 | 485 | ||
| 487 | reset_current_kprobe(); | 486 | reset_current_kprobe(); |
| 488 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 487 | kretprobe_hash_unlock(current, &flags); |
| 489 | preempt_enable_no_resched(); | 488 | preempt_enable_no_resched(); |
| 490 | 489 | ||
| 491 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 490 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
| @@ -500,7 +499,6 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 500 | return 1; | 499 | return 1; |
| 501 | } | 500 | } |
| 502 | 501 | ||
| 503 | /* Called with kretprobe_lock held */ | ||
| 504 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 502 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
| 505 | struct pt_regs *regs) | 503 | struct pt_regs *regs) |
| 506 | { | 504 | { |
diff --git a/arch/m32r/boot/compressed/misc.c b/arch/m32r/boot/compressed/misc.c index 600d40e33495..d394292498c0 100644 --- a/arch/m32r/boot/compressed/misc.c +++ b/arch/m32r/boot/compressed/misc.c | |||
| @@ -70,8 +70,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */ | |||
| 70 | static int fill_inbuf(void); | 70 | static int fill_inbuf(void); |
| 71 | static void flush_window(void); | 71 | static void flush_window(void); |
| 72 | static void error(char *m); | 72 | static void error(char *m); |
| 73 | static void gzip_mark(void **); | ||
| 74 | static void gzip_release(void **); | ||
| 75 | 73 | ||
| 76 | static unsigned char *input_data; | 74 | static unsigned char *input_data; |
| 77 | static int input_len; | 75 | static int input_len; |
| @@ -82,9 +80,6 @@ static unsigned long output_ptr = 0; | |||
| 82 | 80 | ||
| 83 | #include "m32r_sio.c" | 81 | #include "m32r_sio.c" |
| 84 | 82 | ||
| 85 | static void *malloc(int size); | ||
| 86 | static void free(void *where); | ||
| 87 | |||
| 88 | static unsigned long free_mem_ptr; | 83 | static unsigned long free_mem_ptr; |
| 89 | static unsigned long free_mem_end_ptr; | 84 | static unsigned long free_mem_end_ptr; |
| 90 | 85 | ||
| @@ -92,38 +87,6 @@ static unsigned long free_mem_end_ptr; | |||
| 92 | 87 | ||
| 93 | #include "../../../../lib/inflate.c" | 88 | #include "../../../../lib/inflate.c" |
| 94 | 89 | ||
| 95 | static void *malloc(int size) | ||
| 96 | { | ||
| 97 | void *p; | ||
| 98 | |||
| 99 | if (size <0) error("Malloc error"); | ||
| 100 | if (free_mem_ptr == 0) error("Memory error"); | ||
| 101 | |||
| 102 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 103 | |||
| 104 | p = (void *)free_mem_ptr; | ||
| 105 | free_mem_ptr += size; | ||
| 106 | |||
| 107 | if (free_mem_ptr >= free_mem_end_ptr) | ||
| 108 | error("Out of memory"); | ||
| 109 | |||
| 110 | return p; | ||
| 111 | } | ||
| 112 | |||
| 113 | static void free(void *where) | ||
| 114 | { /* Don't care */ | ||
| 115 | } | ||
| 116 | |||
| 117 | static void gzip_mark(void **ptr) | ||
| 118 | { | ||
| 119 | *ptr = (void *) free_mem_ptr; | ||
| 120 | } | ||
| 121 | |||
| 122 | static void gzip_release(void **ptr) | ||
| 123 | { | ||
| 124 | free_mem_ptr = (long) *ptr; | ||
| 125 | } | ||
| 126 | |||
| 127 | void* memset(void* s, int c, size_t n) | 90 | void* memset(void* s, int c, size_t n) |
| 128 | { | 91 | { |
| 129 | int i; | 92 | int i; |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b9c754f4070c..b4c4eaa5dd26 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -713,7 +713,7 @@ config CSRC_SB1250 | |||
| 713 | 713 | ||
| 714 | config GPIO_TXX9 | 714 | config GPIO_TXX9 |
| 715 | select GENERIC_GPIO | 715 | select GENERIC_GPIO |
| 716 | select HAVE_GPIO_LIB | 716 | select ARCH_REQUIRE_GPIOLIB |
| 717 | bool | 717 | bool |
| 718 | 718 | ||
| 719 | config CFE | 719 | config CFE |
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index c266211ed653..2fefb14414b7 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include <linux/file.h> | 11 | #include <linux/file.h> |
| 12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
| 13 | #include <linux/highuid.h> | 13 | #include <linux/highuid.h> |
| 14 | #include <linux/dirent.h> | ||
| 15 | #include <linux/resource.h> | 14 | #include <linux/resource.h> |
| 16 | #include <linux/highmem.h> | 15 | #include <linux/highmem.h> |
| 17 | #include <linux/time.h> | 16 | #include <linux/time.h> |
diff --git a/arch/mn10300/boot/compressed/misc.c b/arch/mn10300/boot/compressed/misc.c index ded207efc97a..f673383518e4 100644 --- a/arch/mn10300/boot/compressed/misc.c +++ b/arch/mn10300/boot/compressed/misc.c | |||
| @@ -153,26 +153,9 @@ static uch *output_data; | |||
| 153 | static unsigned long output_ptr; | 153 | static unsigned long output_ptr; |
| 154 | 154 | ||
| 155 | 155 | ||
| 156 | static void *malloc(int size); | ||
| 157 | |||
| 158 | static inline void free(void *where) | ||
| 159 | { /* Don't care */ | ||
| 160 | } | ||
| 161 | |||
| 162 | static unsigned long free_mem_ptr = (unsigned long) &end; | 156 | static unsigned long free_mem_ptr = (unsigned long) &end; |
| 163 | static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000; | 157 | static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000; |
| 164 | 158 | ||
| 165 | static inline void gzip_mark(void **ptr) | ||
| 166 | { | ||
| 167 | kputs("."); | ||
| 168 | *ptr = (void *) free_mem_ptr; | ||
| 169 | } | ||
| 170 | |||
| 171 | static inline void gzip_release(void **ptr) | ||
| 172 | { | ||
| 173 | free_mem_ptr = (unsigned long) *ptr; | ||
| 174 | } | ||
| 175 | |||
| 176 | #define INPLACE_MOVE_ROUTINE 0x1000 | 159 | #define INPLACE_MOVE_ROUTINE 0x1000 |
| 177 | #define LOW_BUFFER_START 0x2000 | 160 | #define LOW_BUFFER_START 0x2000 |
| 178 | #define LOW_BUFFER_END 0x90000 | 161 | #define LOW_BUFFER_END 0x90000 |
| @@ -186,26 +169,6 @@ static int lines, cols; | |||
| 186 | 169 | ||
| 187 | #include "../../../../lib/inflate.c" | 170 | #include "../../../../lib/inflate.c" |
| 188 | 171 | ||
| 189 | static void *malloc(int size) | ||
| 190 | { | ||
| 191 | void *p; | ||
| 192 | |||
| 193 | if (size < 0) | ||
| 194 | error("Malloc error\n"); | ||
| 195 | if (!free_mem_ptr) | ||
| 196 | error("Memory error\n"); | ||
| 197 | |||
| 198 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 199 | |||
| 200 | p = (void *) free_mem_ptr; | ||
| 201 | free_mem_ptr += size; | ||
| 202 | |||
| 203 | if (free_mem_ptr >= free_mem_end_ptr) | ||
| 204 | error("\nOut of memory\n"); | ||
| 205 | |||
| 206 | return p; | ||
| 207 | } | ||
| 208 | |||
| 209 | static inline void scroll(void) | 172 | static inline void scroll(void) |
| 210 | { | 173 | { |
| 211 | int i; | 174 | int i; |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a487671c282f..fe88418167c5 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -110,8 +110,10 @@ config PPC | |||
| 110 | default y | 110 | default y |
| 111 | select HAVE_DYNAMIC_FTRACE | 111 | select HAVE_DYNAMIC_FTRACE |
| 112 | select HAVE_FTRACE | 112 | select HAVE_FTRACE |
| 113 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 113 | select HAVE_IDE | 114 | select HAVE_IDE |
| 114 | select HAVE_IOREMAP_PROT | 115 | select HAVE_IOREMAP_PROT |
| 116 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
| 115 | select HAVE_KPROBES | 117 | select HAVE_KPROBES |
| 116 | select HAVE_ARCH_KGDB | 118 | select HAVE_ARCH_KGDB |
| 117 | select HAVE_KRETPROBES | 119 | select HAVE_KRETPROBES |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index b936a1dd0a50..25a052c16754 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -23,6 +23,9 @@ | |||
| 23 | struct cpu_spec* cur_cpu_spec = NULL; | 23 | struct cpu_spec* cur_cpu_spec = NULL; |
| 24 | EXPORT_SYMBOL(cur_cpu_spec); | 24 | EXPORT_SYMBOL(cur_cpu_spec); |
| 25 | 25 | ||
| 26 | /* The platform string corresponding to the real PVR */ | ||
| 27 | const char *powerpc_base_platform; | ||
| 28 | |||
| 26 | /* NOTE: | 29 | /* NOTE: |
| 27 | * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's | 30 | * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's |
| 28 | * the responsibility of the appropriate CPU save/restore functions to | 31 | * the responsibility of the appropriate CPU save/restore functions to |
| @@ -1652,6 +1655,14 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) | |||
| 1652 | } else | 1655 | } else |
| 1653 | *t = *s; | 1656 | *t = *s; |
| 1654 | *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; | 1657 | *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; |
| 1658 | |||
| 1659 | /* | ||
| 1660 | * Set the base platform string once; assumes | ||
| 1661 | * we're called with real pvr first. | ||
| 1662 | */ | ||
| 1663 | if (powerpc_base_platform == NULL) | ||
| 1664 | powerpc_base_platform = t->platform; | ||
| 1665 | |||
| 1655 | #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) | 1666 | #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) |
| 1656 | /* ppc64 and booke expect identify_cpu to also call | 1667 | /* ppc64 and booke expect identify_cpu to also call |
| 1657 | * setup_cpu for that processor. I will consolidate | 1668 | * setup_cpu for that processor. I will consolidate |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index da52269aec1e..81c8324a4a3c 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
| @@ -148,7 +148,7 @@ transfer_to_handler: | |||
| 148 | /* Check to see if the dbcr0 register is set up to debug. Use the | 148 | /* Check to see if the dbcr0 register is set up to debug. Use the |
| 149 | internal debug mode bit to do this. */ | 149 | internal debug mode bit to do this. */ |
| 150 | lwz r12,THREAD_DBCR0(r12) | 150 | lwz r12,THREAD_DBCR0(r12) |
| 151 | andis. r12,r12,DBCR0_IDM@h | 151 | andis. r12,r12,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h |
| 152 | beq+ 3f | 152 | beq+ 3f |
| 153 | /* From user and task is ptraced - load up global dbcr0 */ | 153 | /* From user and task is ptraced - load up global dbcr0 */ |
| 154 | li r12,-1 /* clear all pending debug events */ | 154 | li r12,-1 /* clear all pending debug events */ |
| @@ -292,7 +292,7 @@ syscall_exit_cont: | |||
| 292 | /* If the process has its own DBCR0 value, load it up. The internal | 292 | /* If the process has its own DBCR0 value, load it up. The internal |
| 293 | debug mode bit tells us that dbcr0 should be loaded. */ | 293 | debug mode bit tells us that dbcr0 should be loaded. */ |
| 294 | lwz r0,THREAD+THREAD_DBCR0(r2) | 294 | lwz r0,THREAD+THREAD_DBCR0(r2) |
| 295 | andis. r10,r0,DBCR0_IDM@h | 295 | andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h |
| 296 | bnel- load_dbcr0 | 296 | bnel- load_dbcr0 |
| 297 | #endif | 297 | #endif |
| 298 | #ifdef CONFIG_44x | 298 | #ifdef CONFIG_44x |
| @@ -720,7 +720,7 @@ restore_user: | |||
| 720 | /* Check whether this process has its own DBCR0 value. The internal | 720 | /* Check whether this process has its own DBCR0 value. The internal |
| 721 | debug mode bit tells us that dbcr0 should be loaded. */ | 721 | debug mode bit tells us that dbcr0 should be loaded. */ |
| 722 | lwz r0,THREAD+THREAD_DBCR0(r2) | 722 | lwz r0,THREAD+THREAD_DBCR0(r2) |
| 723 | andis. r10,r0,DBCR0_IDM@h | 723 | andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h |
| 724 | bnel- load_dbcr0 | 724 | bnel- load_dbcr0 |
| 725 | #endif | 725 | #endif |
| 726 | 726 | ||
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 2385f68c1751..550a19399bfa 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
| @@ -49,6 +49,8 @@ static int novmerge = 1; | |||
| 49 | 49 | ||
| 50 | static int protect4gb = 1; | 50 | static int protect4gb = 1; |
| 51 | 51 | ||
| 52 | static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int); | ||
| 53 | |||
| 52 | static inline unsigned long iommu_num_pages(unsigned long vaddr, | 54 | static inline unsigned long iommu_num_pages(unsigned long vaddr, |
| 53 | unsigned long slen) | 55 | unsigned long slen) |
| 54 | { | 56 | { |
| @@ -191,6 +193,7 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl, | |||
| 191 | { | 193 | { |
| 192 | unsigned long entry, flags; | 194 | unsigned long entry, flags; |
| 193 | dma_addr_t ret = DMA_ERROR_CODE; | 195 | dma_addr_t ret = DMA_ERROR_CODE; |
| 196 | int build_fail; | ||
| 194 | 197 | ||
| 195 | spin_lock_irqsave(&(tbl->it_lock), flags); | 198 | spin_lock_irqsave(&(tbl->it_lock), flags); |
| 196 | 199 | ||
| @@ -205,9 +208,21 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl, | |||
| 205 | ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */ | 208 | ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */ |
| 206 | 209 | ||
| 207 | /* Put the TCEs in the HW table */ | 210 | /* Put the TCEs in the HW table */ |
| 208 | ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK, | 211 | build_fail = ppc_md.tce_build(tbl, entry, npages, |
| 209 | direction, attrs); | 212 | (unsigned long)page & IOMMU_PAGE_MASK, |
| 213 | direction, attrs); | ||
| 214 | |||
| 215 | /* ppc_md.tce_build() only returns non-zero for transient errors. | ||
| 216 | * Clean up the table bitmap in this case and return | ||
| 217 | * DMA_ERROR_CODE. For all other errors the functionality is | ||
| 218 | * not altered. | ||
| 219 | */ | ||
| 220 | if (unlikely(build_fail)) { | ||
| 221 | __iommu_free(tbl, ret, npages); | ||
| 210 | 222 | ||
| 223 | spin_unlock_irqrestore(&(tbl->it_lock), flags); | ||
| 224 | return DMA_ERROR_CODE; | ||
| 225 | } | ||
| 211 | 226 | ||
| 212 | /* Flush/invalidate TLB caches if necessary */ | 227 | /* Flush/invalidate TLB caches if necessary */ |
| 213 | if (ppc_md.tce_flush) | 228 | if (ppc_md.tce_flush) |
| @@ -276,7 +291,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
| 276 | dma_addr_t dma_next = 0, dma_addr; | 291 | dma_addr_t dma_next = 0, dma_addr; |
| 277 | unsigned long flags; | 292 | unsigned long flags; |
| 278 | struct scatterlist *s, *outs, *segstart; | 293 | struct scatterlist *s, *outs, *segstart; |
| 279 | int outcount, incount, i; | 294 | int outcount, incount, i, build_fail = 0; |
| 280 | unsigned int align; | 295 | unsigned int align; |
| 281 | unsigned long handle; | 296 | unsigned long handle; |
| 282 | unsigned int max_seg_size; | 297 | unsigned int max_seg_size; |
| @@ -337,8 +352,11 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
| 337 | npages, entry, dma_addr); | 352 | npages, entry, dma_addr); |
| 338 | 353 | ||
| 339 | /* Insert into HW table */ | 354 | /* Insert into HW table */ |
| 340 | ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, | 355 | build_fail = ppc_md.tce_build(tbl, entry, npages, |
| 341 | direction, attrs); | 356 | vaddr & IOMMU_PAGE_MASK, |
| 357 | direction, attrs); | ||
| 358 | if(unlikely(build_fail)) | ||
| 359 | goto failure; | ||
| 342 | 360 | ||
| 343 | /* If we are in an open segment, try merging */ | 361 | /* If we are in an open segment, try merging */ |
| 344 | if (segstart != s) { | 362 | if (segstart != s) { |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 4ba2af125450..de79915452c8 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
| @@ -144,7 +144,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, | |||
| 144 | kcb->kprobe_saved_msr = regs->msr; | 144 | kcb->kprobe_saved_msr = regs->msr; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | /* Called with kretprobe_lock held */ | ||
| 148 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 147 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
| 149 | struct pt_regs *regs) | 148 | struct pt_regs *regs) |
| 150 | { | 149 | { |
| @@ -312,8 +311,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
| 312 | unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; | 311 | unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; |
| 313 | 312 | ||
| 314 | INIT_HLIST_HEAD(&empty_rp); | 313 | INIT_HLIST_HEAD(&empty_rp); |
| 315 | spin_lock_irqsave(&kretprobe_lock, flags); | 314 | kretprobe_hash_lock(current, &head, &flags); |
| 316 | head = kretprobe_inst_table_head(current); | ||
| 317 | 315 | ||
| 318 | /* | 316 | /* |
| 319 | * It is possible to have multiple instances associated with a given | 317 | * It is possible to have multiple instances associated with a given |
| @@ -352,7 +350,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
| 352 | regs->nip = orig_ret_address; | 350 | regs->nip = orig_ret_address; |
| 353 | 351 | ||
| 354 | reset_current_kprobe(); | 352 | reset_current_kprobe(); |
| 355 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 353 | kretprobe_hash_unlock(current, &flags); |
| 356 | preempt_enable_no_resched(); | 354 | preempt_enable_no_resched(); |
| 357 | 355 | ||
| 358 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 356 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 827a5726a035..9f856a0c3e38 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
| @@ -34,8 +34,9 @@ | |||
| 34 | #include <asm/time.h> | 34 | #include <asm/time.h> |
| 35 | #include <asm/prom.h> | 35 | #include <asm/prom.h> |
| 36 | #include <asm/vdso_datapage.h> | 36 | #include <asm/vdso_datapage.h> |
| 37 | #include <asm/vio.h> | ||
| 37 | 38 | ||
| 38 | #define MODULE_VERS "1.7" | 39 | #define MODULE_VERS "1.8" |
| 39 | #define MODULE_NAME "lparcfg" | 40 | #define MODULE_NAME "lparcfg" |
| 40 | 41 | ||
| 41 | /* #define LPARCFG_DEBUG */ | 42 | /* #define LPARCFG_DEBUG */ |
| @@ -129,32 +130,46 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v) | |||
| 129 | /* | 130 | /* |
| 130 | * Methods used to fetch LPAR data when running on a pSeries platform. | 131 | * Methods used to fetch LPAR data when running on a pSeries platform. |
| 131 | */ | 132 | */ |
| 132 | static void log_plpar_hcall_return(unsigned long rc, char *tag) | 133 | /** |
| 134 | * h_get_mpp | ||
| 135 | * H_GET_MPP hcall returns info in 7 parms | ||
| 136 | */ | ||
| 137 | int h_get_mpp(struct hvcall_mpp_data *mpp_data) | ||
| 133 | { | 138 | { |
| 134 | switch(rc) { | 139 | int rc; |
| 135 | case 0: | 140 | unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; |
| 136 | return; | 141 | |
| 137 | case H_HARDWARE: | 142 | rc = plpar_hcall9(H_GET_MPP, retbuf); |
| 138 | printk(KERN_INFO "plpar-hcall (%s) " | 143 | |
| 139 | "Hardware fault\n", tag); | 144 | mpp_data->entitled_mem = retbuf[0]; |
| 140 | return; | 145 | mpp_data->mapped_mem = retbuf[1]; |
| 141 | case H_FUNCTION: | 146 | |
| 142 | printk(KERN_INFO "plpar-hcall (%s) " | 147 | mpp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff; |
| 143 | "Function not allowed\n", tag); | 148 | mpp_data->pool_num = retbuf[2] & 0xffff; |
| 144 | return; | 149 | |
| 145 | case H_AUTHORITY: | 150 | mpp_data->mem_weight = (retbuf[3] >> 7 * 8) & 0xff; |
| 146 | printk(KERN_INFO "plpar-hcall (%s) " | 151 | mpp_data->unallocated_mem_weight = (retbuf[3] >> 6 * 8) & 0xff; |
| 147 | "Not authorized to this function\n", tag); | 152 | mpp_data->unallocated_entitlement = retbuf[3] & 0xffffffffffff; |
| 148 | return; | 153 | |
| 149 | case H_PARAMETER: | 154 | mpp_data->pool_size = retbuf[4]; |
| 150 | printk(KERN_INFO "plpar-hcall (%s) " | 155 | mpp_data->loan_request = retbuf[5]; |
| 151 | "Bad parameter(s)\n",tag); | 156 | mpp_data->backing_mem = retbuf[6]; |
| 152 | return; | 157 | |
| 153 | default: | 158 | return rc; |
| 154 | printk(KERN_INFO "plpar-hcall (%s) " | ||
| 155 | "Unexpected rc(0x%lx)\n", tag, rc); | ||
| 156 | } | ||
| 157 | } | 159 | } |
| 160 | EXPORT_SYMBOL(h_get_mpp); | ||
| 161 | |||
| 162 | struct hvcall_ppp_data { | ||
| 163 | u64 entitlement; | ||
| 164 | u64 unallocated_entitlement; | ||
| 165 | u16 group_num; | ||
| 166 | u16 pool_num; | ||
| 167 | u8 capped; | ||
| 168 | u8 weight; | ||
| 169 | u8 unallocated_weight; | ||
| 170 | u16 active_procs_in_pool; | ||
| 171 | u16 active_system_procs; | ||
| 172 | }; | ||
| 158 | 173 | ||
| 159 | /* | 174 | /* |
| 160 | * H_GET_PPP hcall returns info in 4 parms. | 175 | * H_GET_PPP hcall returns info in 4 parms. |
| @@ -176,27 +191,30 @@ static void log_plpar_hcall_return(unsigned long rc, char *tag) | |||
| 176 | * XXXX - Active processors in Physical Processor Pool. | 191 | * XXXX - Active processors in Physical Processor Pool. |
| 177 | * XXXX - Processors active on platform. | 192 | * XXXX - Processors active on platform. |
| 178 | */ | 193 | */ |
| 179 | static unsigned int h_get_ppp(unsigned long *entitled, | 194 | static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data) |
| 180 | unsigned long *unallocated, | ||
| 181 | unsigned long *aggregation, | ||
| 182 | unsigned long *resource) | ||
| 183 | { | 195 | { |
| 184 | unsigned long rc; | 196 | unsigned long rc; |
| 185 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 197 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
| 186 | 198 | ||
| 187 | rc = plpar_hcall(H_GET_PPP, retbuf); | 199 | rc = plpar_hcall(H_GET_PPP, retbuf); |
| 188 | 200 | ||
| 189 | *entitled = retbuf[0]; | 201 | ppp_data->entitlement = retbuf[0]; |
| 190 | *unallocated = retbuf[1]; | 202 | ppp_data->unallocated_entitlement = retbuf[1]; |
| 191 | *aggregation = retbuf[2]; | 203 | |
| 192 | *resource = retbuf[3]; | 204 | ppp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff; |
| 205 | ppp_data->pool_num = retbuf[2] & 0xffff; | ||
| 193 | 206 | ||
| 194 | log_plpar_hcall_return(rc, "H_GET_PPP"); | 207 | ppp_data->capped = (retbuf[3] >> 6 * 8) & 0x01; |
| 208 | ppp_data->weight = (retbuf[3] >> 5 * 8) & 0xff; | ||
| 209 | ppp_data->unallocated_weight = (retbuf[3] >> 4 * 8) & 0xff; | ||
| 210 | ppp_data->active_procs_in_pool = (retbuf[3] >> 2 * 8) & 0xffff; | ||
| 211 | ppp_data->active_system_procs = retbuf[3] & 0xffff; | ||
| 195 | 212 | ||
| 196 | return rc; | 213 | return rc; |
| 197 | } | 214 | } |
| 198 | 215 | ||
| 199 | static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs) | 216 | static unsigned h_pic(unsigned long *pool_idle_time, |
| 217 | unsigned long *num_procs) | ||
| 200 | { | 218 | { |
| 201 | unsigned long rc; | 219 | unsigned long rc; |
| 202 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 220 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
| @@ -206,8 +224,87 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs) | |||
| 206 | *pool_idle_time = retbuf[0]; | 224 | *pool_idle_time = retbuf[0]; |
| 207 | *num_procs = retbuf[1]; | 225 | *num_procs = retbuf[1]; |
| 208 | 226 | ||
| 209 | if (rc != H_AUTHORITY) | 227 | return rc; |
| 210 | log_plpar_hcall_return(rc, "H_PIC"); | 228 | } |
| 229 | |||
| 230 | /* | ||
| 231 | * parse_ppp_data | ||
| 232 | * Parse out the data returned from h_get_ppp and h_pic | ||
| 233 | */ | ||
| 234 | static void parse_ppp_data(struct seq_file *m) | ||
| 235 | { | ||
| 236 | struct hvcall_ppp_data ppp_data; | ||
| 237 | int rc; | ||
| 238 | |||
| 239 | rc = h_get_ppp(&ppp_data); | ||
| 240 | if (rc) | ||
| 241 | return; | ||
| 242 | |||
| 243 | seq_printf(m, "partition_entitled_capacity=%ld\n", | ||
| 244 | ppp_data.entitlement); | ||
| 245 | seq_printf(m, "group=%d\n", ppp_data.group_num); | ||
| 246 | seq_printf(m, "system_active_processors=%d\n", | ||
| 247 | ppp_data.active_system_procs); | ||
| 248 | |||
| 249 | /* pool related entries are apropriate for shared configs */ | ||
| 250 | if (lppaca[0].shared_proc) { | ||
| 251 | unsigned long pool_idle_time, pool_procs; | ||
| 252 | |||
| 253 | seq_printf(m, "pool=%d\n", ppp_data.pool_num); | ||
| 254 | |||
| 255 | /* report pool_capacity in percentage */ | ||
| 256 | seq_printf(m, "pool_capacity=%d\n", | ||
| 257 | ppp_data.active_procs_in_pool * 100); | ||
| 258 | |||
| 259 | h_pic(&pool_idle_time, &pool_procs); | ||
| 260 | seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time); | ||
| 261 | seq_printf(m, "pool_num_procs=%ld\n", pool_procs); | ||
| 262 | } | ||
| 263 | |||
| 264 | seq_printf(m, "unallocated_capacity_weight=%d\n", | ||
| 265 | ppp_data.unallocated_weight); | ||
| 266 | seq_printf(m, "capacity_weight=%d\n", ppp_data.weight); | ||
| 267 | seq_printf(m, "capped=%d\n", ppp_data.capped); | ||
| 268 | seq_printf(m, "unallocated_capacity=%ld\n", | ||
| 269 | ppp_data.unallocated_entitlement); | ||
| 270 | } | ||
| 271 | |||
| 272 | /** | ||
| 273 | * parse_mpp_data | ||
| 274 | * Parse out data returned from h_get_mpp | ||
| 275 | */ | ||
| 276 | static void parse_mpp_data(struct seq_file *m) | ||
| 277 | { | ||
| 278 | struct hvcall_mpp_data mpp_data; | ||
| 279 | int rc; | ||
| 280 | |||
| 281 | rc = h_get_mpp(&mpp_data); | ||
| 282 | if (rc) | ||
| 283 | return; | ||
| 284 | |||
| 285 | seq_printf(m, "entitled_memory=%ld\n", mpp_data.entitled_mem); | ||
| 286 | |||
| 287 | if (mpp_data.mapped_mem != -1) | ||
| 288 | seq_printf(m, "mapped_entitled_memory=%ld\n", | ||
| 289 | mpp_data.mapped_mem); | ||
| 290 | |||
| 291 | seq_printf(m, "entitled_memory_group_number=%d\n", mpp_data.group_num); | ||
| 292 | seq_printf(m, "entitled_memory_pool_number=%d\n", mpp_data.pool_num); | ||
| 293 | |||
| 294 | seq_printf(m, "entitled_memory_weight=%d\n", mpp_data.mem_weight); | ||
| 295 | seq_printf(m, "unallocated_entitled_memory_weight=%d\n", | ||
| 296 | mpp_data.unallocated_mem_weight); | ||
| 297 | seq_printf(m, "unallocated_io_mapping_entitlement=%ld\n", | ||
| 298 | mpp_data.unallocated_entitlement); | ||
| 299 | |||
| 300 | if (mpp_data.pool_size != -1) | ||
| 301 | seq_printf(m, "entitled_memory_pool_size=%ld bytes\n", | ||
| 302 | mpp_data.pool_size); | ||
| 303 | |||
| 304 | seq_printf(m, "entitled_memory_loan_request=%ld\n", | ||
| 305 | mpp_data.loan_request); | ||
| 306 | |||
| 307 | seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem); | ||
| 211 | } | 308 | } |
| 212 | 309 | ||
| 213 | #define SPLPAR_CHARACTERISTICS_TOKEN 20 | 310 | #define SPLPAR_CHARACTERISTICS_TOKEN 20 |
| @@ -313,6 +410,25 @@ static int lparcfg_count_active_processors(void) | |||
| 313 | return count; | 410 | return count; |
| 314 | } | 411 | } |
| 315 | 412 | ||
| 413 | static void pseries_cmo_data(struct seq_file *m) | ||
| 414 | { | ||
| 415 | int cpu; | ||
| 416 | unsigned long cmo_faults = 0; | ||
| 417 | unsigned long cmo_fault_time = 0; | ||
| 418 | |||
| 419 | if (!firmware_has_feature(FW_FEATURE_CMO)) | ||
| 420 | return; | ||
| 421 | |||
| 422 | for_each_possible_cpu(cpu) { | ||
| 423 | cmo_faults += lppaca[cpu].cmo_faults; | ||
| 424 | cmo_fault_time += lppaca[cpu].cmo_fault_time; | ||
| 425 | } | ||
| 426 | |||
| 427 | seq_printf(m, "cmo_faults=%lu\n", cmo_faults); | ||
| 428 | seq_printf(m, "cmo_fault_time_usec=%lu\n", | ||
| 429 | cmo_fault_time / tb_ticks_per_usec); | ||
| 430 | } | ||
| 431 | |||
| 316 | static int pseries_lparcfg_data(struct seq_file *m, void *v) | 432 | static int pseries_lparcfg_data(struct seq_file *m, void *v) |
| 317 | { | 433 | { |
| 318 | int partition_potential_processors; | 434 | int partition_potential_processors; |
| @@ -334,60 +450,13 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
| 334 | partition_active_processors = lparcfg_count_active_processors(); | 450 | partition_active_processors = lparcfg_count_active_processors(); |
| 335 | 451 | ||
| 336 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | 452 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { |
| 337 | unsigned long h_entitled, h_unallocated; | ||
| 338 | unsigned long h_aggregation, h_resource; | ||
| 339 | unsigned long pool_idle_time, pool_procs; | ||
| 340 | unsigned long purr; | ||
| 341 | |||
| 342 | h_get_ppp(&h_entitled, &h_unallocated, &h_aggregation, | ||
| 343 | &h_resource); | ||
| 344 | |||
| 345 | seq_printf(m, "R4=0x%lx\n", h_entitled); | ||
| 346 | seq_printf(m, "R5=0x%lx\n", h_unallocated); | ||
| 347 | seq_printf(m, "R6=0x%lx\n", h_aggregation); | ||
| 348 | seq_printf(m, "R7=0x%lx\n", h_resource); | ||
| 349 | |||
| 350 | purr = get_purr(); | ||
| 351 | |||
| 352 | /* this call handles the ibm,get-system-parameter contents */ | 453 | /* this call handles the ibm,get-system-parameter contents */ |
| 353 | parse_system_parameter_string(m); | 454 | parse_system_parameter_string(m); |
| 455 | parse_ppp_data(m); | ||
| 456 | parse_mpp_data(m); | ||
| 457 | pseries_cmo_data(m); | ||
| 354 | 458 | ||
| 355 | seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled); | 459 | seq_printf(m, "purr=%ld\n", get_purr()); |
| 356 | |||
| 357 | seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff); | ||
| 358 | |||
| 359 | seq_printf(m, "system_active_processors=%ld\n", | ||
| 360 | (h_resource >> 0 * 8) & 0xffff); | ||
| 361 | |||
| 362 | /* pool related entries are apropriate for shared configs */ | ||
| 363 | if (lppaca[0].shared_proc) { | ||
| 364 | |||
| 365 | h_pic(&pool_idle_time, &pool_procs); | ||
| 366 | |||
| 367 | seq_printf(m, "pool=%ld\n", | ||
| 368 | (h_aggregation >> 0 * 8) & 0xffff); | ||
| 369 | |||
| 370 | /* report pool_capacity in percentage */ | ||
| 371 | seq_printf(m, "pool_capacity=%ld\n", | ||
| 372 | ((h_resource >> 2 * 8) & 0xffff) * 100); | ||
| 373 | |||
| 374 | seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time); | ||
| 375 | |||
| 376 | seq_printf(m, "pool_num_procs=%ld\n", pool_procs); | ||
| 377 | } | ||
| 378 | |||
| 379 | seq_printf(m, "unallocated_capacity_weight=%ld\n", | ||
| 380 | (h_resource >> 4 * 8) & 0xFF); | ||
| 381 | |||
| 382 | seq_printf(m, "capacity_weight=%ld\n", | ||
| 383 | (h_resource >> 5 * 8) & 0xFF); | ||
| 384 | |||
| 385 | seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01); | ||
| 386 | |||
| 387 | seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated); | ||
| 388 | |||
| 389 | seq_printf(m, "purr=%ld\n", purr); | ||
| 390 | |||
| 391 | } else { /* non SPLPAR case */ | 460 | } else { /* non SPLPAR case */ |
| 392 | 461 | ||
| 393 | seq_printf(m, "system_active_processors=%d\n", | 462 | seq_printf(m, "system_active_processors=%d\n", |
| @@ -414,6 +483,83 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
| 414 | return 0; | 483 | return 0; |
| 415 | } | 484 | } |
| 416 | 485 | ||
| 486 | static ssize_t update_ppp(u64 *entitlement, u8 *weight) | ||
| 487 | { | ||
| 488 | struct hvcall_ppp_data ppp_data; | ||
| 489 | u8 new_weight; | ||
| 490 | u64 new_entitled; | ||
| 491 | ssize_t retval; | ||
| 492 | |||
| 493 | /* Get our current parameters */ | ||
| 494 | retval = h_get_ppp(&ppp_data); | ||
| 495 | if (retval) | ||
| 496 | return retval; | ||
| 497 | |||
| 498 | if (entitlement) { | ||
| 499 | new_weight = ppp_data.weight; | ||
| 500 | new_entitled = *entitlement; | ||
| 501 | } else if (weight) { | ||
| 502 | new_weight = *weight; | ||
| 503 | new_entitled = ppp_data.entitlement; | ||
| 504 | } else | ||
| 505 | return -EINVAL; | ||
| 506 | |||
| 507 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", | ||
| 508 | __FUNCTION__, ppp_data.entitlement, ppp_data.weight); | ||
| 509 | |||
| 510 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", | ||
| 511 | __FUNCTION__, new_entitled, new_weight); | ||
| 512 | |||
| 513 | retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight); | ||
| 514 | return retval; | ||
| 515 | } | ||
| 516 | |||
| 517 | /** | ||
| 518 | * update_mpp | ||
| 519 | * | ||
| 520 | * Update the memory entitlement and weight for the partition. Caller must | ||
| 521 | * specify either a new entitlement or weight, not both, to be updated | ||
| 522 | * since the h_set_mpp call takes both entitlement and weight as parameters. | ||
| 523 | */ | ||
| 524 | static ssize_t update_mpp(u64 *entitlement, u8 *weight) | ||
| 525 | { | ||
| 526 | struct hvcall_mpp_data mpp_data; | ||
| 527 | u64 new_entitled; | ||
| 528 | u8 new_weight; | ||
| 529 | ssize_t rc; | ||
| 530 | |||
| 531 | if (entitlement) { | ||
| 532 | /* Check with vio to ensure the new memory entitlement | ||
| 533 | * can be handled. | ||
| 534 | */ | ||
| 535 | rc = vio_cmo_entitlement_update(*entitlement); | ||
| 536 | if (rc) | ||
| 537 | return rc; | ||
| 538 | } | ||
| 539 | |||
| 540 | rc = h_get_mpp(&mpp_data); | ||
| 541 | if (rc) | ||
| 542 | return rc; | ||
| 543 | |||
| 544 | if (entitlement) { | ||
| 545 | new_weight = mpp_data.mem_weight; | ||
| 546 | new_entitled = *entitlement; | ||
| 547 | } else if (weight) { | ||
| 548 | new_weight = *weight; | ||
| 549 | new_entitled = mpp_data.entitled_mem; | ||
| 550 | } else | ||
| 551 | return -EINVAL; | ||
| 552 | |||
| 553 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", | ||
| 554 | __FUNCTION__, mpp_data.entitled_mem, mpp_data.mem_weight); | ||
| 555 | |||
| 556 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", | ||
| 557 | __FUNCTION__, new_entitled, new_weight); | ||
| 558 | |||
| 559 | rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight); | ||
| 560 | return rc; | ||
| 561 | } | ||
| 562 | |||
| 417 | /* | 563 | /* |
| 418 | * Interface for changing system parameters (variable capacity weight | 564 | * Interface for changing system parameters (variable capacity weight |
| 419 | * and entitled capacity). Format of input is "param_name=value"; | 565 | * and entitled capacity). Format of input is "param_name=value"; |
| @@ -427,35 +573,27 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
| 427 | static ssize_t lparcfg_write(struct file *file, const char __user * buf, | 573 | static ssize_t lparcfg_write(struct file *file, const char __user * buf, |
| 428 | size_t count, loff_t * off) | 574 | size_t count, loff_t * off) |
| 429 | { | 575 | { |
| 430 | char *kbuf; | 576 | int kbuf_sz = 64; |
| 577 | char kbuf[kbuf_sz]; | ||
| 431 | char *tmp; | 578 | char *tmp; |
| 432 | u64 new_entitled, *new_entitled_ptr = &new_entitled; | 579 | u64 new_entitled, *new_entitled_ptr = &new_entitled; |
| 433 | u8 new_weight, *new_weight_ptr = &new_weight; | 580 | u8 new_weight, *new_weight_ptr = &new_weight; |
| 434 | 581 | ssize_t retval; | |
| 435 | unsigned long current_entitled; /* parameters for h_get_ppp */ | ||
| 436 | unsigned long dummy; | ||
| 437 | unsigned long resource; | ||
| 438 | u8 current_weight; | ||
| 439 | |||
| 440 | ssize_t retval = -ENOMEM; | ||
| 441 | 582 | ||
| 442 | if (!firmware_has_feature(FW_FEATURE_SPLPAR) || | 583 | if (!firmware_has_feature(FW_FEATURE_SPLPAR) || |
| 443 | firmware_has_feature(FW_FEATURE_ISERIES)) | 584 | firmware_has_feature(FW_FEATURE_ISERIES)) |
| 444 | return -EINVAL; | 585 | return -EINVAL; |
| 445 | 586 | ||
| 446 | kbuf = kmalloc(count, GFP_KERNEL); | 587 | if (count > kbuf_sz) |
| 447 | if (!kbuf) | 588 | return -EINVAL; |
| 448 | goto out; | ||
| 449 | 589 | ||
| 450 | retval = -EFAULT; | ||
| 451 | if (copy_from_user(kbuf, buf, count)) | 590 | if (copy_from_user(kbuf, buf, count)) |
| 452 | goto out; | 591 | return -EFAULT; |
| 453 | 592 | ||
| 454 | retval = -EINVAL; | ||
| 455 | kbuf[count - 1] = '\0'; | 593 | kbuf[count - 1] = '\0'; |
| 456 | tmp = strchr(kbuf, '='); | 594 | tmp = strchr(kbuf, '='); |
| 457 | if (!tmp) | 595 | if (!tmp) |
| 458 | goto out; | 596 | return -EINVAL; |
| 459 | 597 | ||
| 460 | *tmp++ = '\0'; | 598 | *tmp++ = '\0'; |
| 461 | 599 | ||
| @@ -463,34 +601,32 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
| 463 | char *endp; | 601 | char *endp; |
| 464 | *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); | 602 | *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); |
| 465 | if (endp == tmp) | 603 | if (endp == tmp) |
| 466 | goto out; | 604 | return -EINVAL; |
| 467 | new_weight_ptr = ¤t_weight; | 605 | |
| 606 | retval = update_ppp(new_entitled_ptr, NULL); | ||
| 468 | } else if (!strcmp(kbuf, "capacity_weight")) { | 607 | } else if (!strcmp(kbuf, "capacity_weight")) { |
| 469 | char *endp; | 608 | char *endp; |
| 470 | *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); | 609 | *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); |
| 471 | if (endp == tmp) | 610 | if (endp == tmp) |
| 472 | goto out; | 611 | return -EINVAL; |
| 473 | new_entitled_ptr = ¤t_entitled; | ||
| 474 | } else | ||
| 475 | goto out; | ||
| 476 | |||
| 477 | /* Get our current parameters */ | ||
| 478 | retval = h_get_ppp(¤t_entitled, &dummy, &dummy, &resource); | ||
| 479 | if (retval) { | ||
| 480 | retval = -EIO; | ||
| 481 | goto out; | ||
| 482 | } | ||
| 483 | |||
| 484 | current_weight = (resource >> 5 * 8) & 0xFF; | ||
| 485 | 612 | ||
| 486 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", | 613 | retval = update_ppp(NULL, new_weight_ptr); |
| 487 | __func__, current_entitled, current_weight); | 614 | } else if (!strcmp(kbuf, "entitled_memory")) { |
| 615 | char *endp; | ||
| 616 | *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); | ||
| 617 | if (endp == tmp) | ||
| 618 | return -EINVAL; | ||
| 488 | 619 | ||
| 489 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", | 620 | retval = update_mpp(new_entitled_ptr, NULL); |
| 490 | __func__, *new_entitled_ptr, *new_weight_ptr); | 621 | } else if (!strcmp(kbuf, "entitled_memory_weight")) { |
| 622 | char *endp; | ||
| 623 | *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); | ||
| 624 | if (endp == tmp) | ||
| 625 | return -EINVAL; | ||
| 491 | 626 | ||
| 492 | retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, | 627 | retval = update_mpp(NULL, new_weight_ptr); |
| 493 | *new_weight_ptr); | 628 | } else |
| 629 | return -EINVAL; | ||
| 494 | 630 | ||
| 495 | if (retval == H_SUCCESS || retval == H_CONSTRAINED) { | 631 | if (retval == H_SUCCESS || retval == H_CONSTRAINED) { |
| 496 | retval = count; | 632 | retval = count; |
| @@ -506,8 +642,6 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
| 506 | retval = -EIO; | 642 | retval = -EIO; |
| 507 | } | 643 | } |
| 508 | 644 | ||
| 509 | out: | ||
| 510 | kfree(kbuf); | ||
| 511 | return retval; | 645 | return retval; |
| 512 | } | 646 | } |
| 513 | 647 | ||
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 219f3634115e..db2497ccc111 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -47,6 +47,8 @@ | |||
| 47 | #ifdef CONFIG_PPC64 | 47 | #ifdef CONFIG_PPC64 |
| 48 | #include <asm/firmware.h> | 48 | #include <asm/firmware.h> |
| 49 | #endif | 49 | #endif |
| 50 | #include <linux/kprobes.h> | ||
| 51 | #include <linux/kdebug.h> | ||
| 50 | 52 | ||
| 51 | extern unsigned long _get_SP(void); | 53 | extern unsigned long _get_SP(void); |
| 52 | 54 | ||
| @@ -239,6 +241,35 @@ void discard_lazy_cpu_state(void) | |||
| 239 | } | 241 | } |
| 240 | #endif /* CONFIG_SMP */ | 242 | #endif /* CONFIG_SMP */ |
| 241 | 243 | ||
| 244 | void do_dabr(struct pt_regs *regs, unsigned long address, | ||
| 245 | unsigned long error_code) | ||
| 246 | { | ||
| 247 | siginfo_t info; | ||
| 248 | |||
| 249 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
| 250 | 11, SIGSEGV) == NOTIFY_STOP) | ||
| 251 | return; | ||
| 252 | |||
| 253 | if (debugger_dabr_match(regs)) | ||
| 254 | return; | ||
| 255 | |||
| 256 | /* Clear the DAC and struct entries. One shot trigger */ | ||
| 257 | #if (defined(CONFIG_44x) || defined(CONFIG_BOOKE)) | ||
| 258 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W | ||
| 259 | | DBCR0_IDM)); | ||
| 260 | #endif | ||
| 261 | |||
| 262 | /* Clear the DABR */ | ||
| 263 | set_dabr(0); | ||
| 264 | |||
| 265 | /* Deliver the signal to userspace */ | ||
| 266 | info.si_signo = SIGTRAP; | ||
| 267 | info.si_errno = 0; | ||
| 268 | info.si_code = TRAP_HWBKPT; | ||
| 269 | info.si_addr = (void __user *)address; | ||
| 270 | force_sig_info(SIGTRAP, &info, current); | ||
| 271 | } | ||
| 272 | |||
| 242 | static DEFINE_PER_CPU(unsigned long, current_dabr); | 273 | static DEFINE_PER_CPU(unsigned long, current_dabr); |
| 243 | 274 | ||
| 244 | int set_dabr(unsigned long dabr) | 275 | int set_dabr(unsigned long dabr) |
| @@ -254,6 +285,11 @@ int set_dabr(unsigned long dabr) | |||
| 254 | #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) | 285 | #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) |
| 255 | mtspr(SPRN_DABR, dabr); | 286 | mtspr(SPRN_DABR, dabr); |
| 256 | #endif | 287 | #endif |
| 288 | |||
| 289 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 290 | mtspr(SPRN_DAC1, dabr); | ||
| 291 | #endif | ||
| 292 | |||
| 257 | return 0; | 293 | return 0; |
| 258 | } | 294 | } |
| 259 | 295 | ||
| @@ -337,6 +373,12 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 337 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | 373 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) |
| 338 | set_dabr(new->thread.dabr); | 374 | set_dabr(new->thread.dabr); |
| 339 | 375 | ||
| 376 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 377 | /* If new thread DAC (HW breakpoint) is the same then leave it */ | ||
| 378 | if (new->thread.dabr) | ||
| 379 | set_dabr(new->thread.dabr); | ||
| 380 | #endif | ||
| 381 | |||
| 340 | new_thread = &new->thread; | 382 | new_thread = &new->thread; |
| 341 | old_thread = ¤t->thread; | 383 | old_thread = ¤t->thread; |
| 342 | 384 | ||
| @@ -525,6 +567,10 @@ void flush_thread(void) | |||
| 525 | if (current->thread.dabr) { | 567 | if (current->thread.dabr) { |
| 526 | current->thread.dabr = 0; | 568 | current->thread.dabr = 0; |
| 527 | set_dabr(0); | 569 | set_dabr(0); |
| 570 | |||
| 571 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 572 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W); | ||
| 573 | #endif | ||
| 528 | } | 574 | } |
| 529 | } | 575 | } |
| 530 | 576 | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 1ea8c8d3ce89..c4ab2195b9cb 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
| @@ -643,6 +643,11 @@ static void __init early_cmdline_parse(void) | |||
| 643 | #else | 643 | #else |
| 644 | #define OV5_MSI 0x00 | 644 | #define OV5_MSI 0x00 |
| 645 | #endif /* CONFIG_PCI_MSI */ | 645 | #endif /* CONFIG_PCI_MSI */ |
| 646 | #ifdef CONFIG_PPC_SMLPAR | ||
| 647 | #define OV5_CMO 0x80 /* Cooperative Memory Overcommitment */ | ||
| 648 | #else | ||
| 649 | #define OV5_CMO 0x00 | ||
| 650 | #endif | ||
| 646 | 651 | ||
| 647 | /* | 652 | /* |
| 648 | * The architecture vector has an array of PVR mask/value pairs, | 653 | * The architecture vector has an array of PVR mask/value pairs, |
| @@ -687,10 +692,12 @@ static unsigned char ibm_architecture_vec[] = { | |||
| 687 | 0, /* don't halt */ | 692 | 0, /* don't halt */ |
| 688 | 693 | ||
| 689 | /* option vector 5: PAPR/OF options */ | 694 | /* option vector 5: PAPR/OF options */ |
| 690 | 3 - 2, /* length */ | 695 | 5 - 2, /* length */ |
| 691 | 0, /* don't ignore, don't halt */ | 696 | 0, /* don't ignore, don't halt */ |
| 692 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | | 697 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | |
| 693 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, | 698 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, |
| 699 | 0, | ||
| 700 | OV5_CMO, | ||
| 694 | }; | 701 | }; |
| 695 | 702 | ||
| 696 | /* Old method - ELF header with PT_NOTE sections */ | 703 | /* Old method - ELF header with PT_NOTE sections */ |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 8feb93e7890c..a5d0e78779c8 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -703,7 +703,7 @@ void user_enable_single_step(struct task_struct *task) | |||
| 703 | 703 | ||
| 704 | if (regs != NULL) { | 704 | if (regs != NULL) { |
| 705 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 705 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) |
| 706 | task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC; | 706 | task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC; |
| 707 | regs->msr |= MSR_DE; | 707 | regs->msr |= MSR_DE; |
| 708 | #else | 708 | #else |
| 709 | regs->msr |= MSR_SE; | 709 | regs->msr |= MSR_SE; |
| @@ -716,9 +716,16 @@ void user_disable_single_step(struct task_struct *task) | |||
| 716 | { | 716 | { |
| 717 | struct pt_regs *regs = task->thread.regs; | 717 | struct pt_regs *regs = task->thread.regs; |
| 718 | 718 | ||
| 719 | |||
| 720 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 721 | /* If DAC then do not single step, skip */ | ||
| 722 | if (task->thread.dabr) | ||
| 723 | return; | ||
| 724 | #endif | ||
| 725 | |||
| 719 | if (regs != NULL) { | 726 | if (regs != NULL) { |
| 720 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 727 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) |
| 721 | task->thread.dbcr0 = 0; | 728 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM); |
| 722 | regs->msr &= ~MSR_DE; | 729 | regs->msr &= ~MSR_DE; |
| 723 | #else | 730 | #else |
| 724 | regs->msr &= ~MSR_SE; | 731 | regs->msr &= ~MSR_SE; |
| @@ -727,22 +734,75 @@ void user_disable_single_step(struct task_struct *task) | |||
| 727 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | 734 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); |
| 728 | } | 735 | } |
| 729 | 736 | ||
| 730 | static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | 737 | int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, |
| 731 | unsigned long data) | 738 | unsigned long data) |
| 732 | { | 739 | { |
| 733 | /* We only support one DABR and no IABRS at the moment */ | 740 | /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). |
| 741 | * For embedded processors we support one DAC and no IAC's at the | ||
| 742 | * moment. | ||
| 743 | */ | ||
| 734 | if (addr > 0) | 744 | if (addr > 0) |
| 735 | return -EINVAL; | 745 | return -EINVAL; |
| 736 | 746 | ||
| 737 | /* The bottom 3 bits are flags */ | ||
| 738 | if ((data & ~0x7UL) >= TASK_SIZE) | 747 | if ((data & ~0x7UL) >= TASK_SIZE) |
| 739 | return -EIO; | 748 | return -EIO; |
| 740 | 749 | ||
| 741 | /* Ensure translation is on */ | 750 | #ifdef CONFIG_PPC64 |
| 751 | |||
| 752 | /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. | ||
| 753 | * It was assumed, on previous implementations, that 3 bits were | ||
| 754 | * passed together with the data address, fitting the design of the | ||
| 755 | * DABR register, as follows: | ||
| 756 | * | ||
| 757 | * bit 0: Read flag | ||
| 758 | * bit 1: Write flag | ||
| 759 | * bit 2: Breakpoint translation | ||
| 760 | * | ||
| 761 | * Thus, we use them here as so. | ||
| 762 | */ | ||
| 763 | |||
| 764 | /* Ensure breakpoint translation bit is set */ | ||
| 742 | if (data && !(data & DABR_TRANSLATION)) | 765 | if (data && !(data & DABR_TRANSLATION)) |
| 743 | return -EIO; | 766 | return -EIO; |
| 744 | 767 | ||
| 768 | /* Move contents to the DABR register */ | ||
| 745 | task->thread.dabr = data; | 769 | task->thread.dabr = data; |
| 770 | |||
| 771 | #endif | ||
| 772 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 773 | |||
| 774 | /* As described above, it was assumed 3 bits were passed with the data | ||
| 775 | * address, but we will assume only the mode bits will be passed | ||
| 776 | * as to not cause alignment restrictions for DAC-based processors. | ||
| 777 | */ | ||
| 778 | |||
| 779 | /* DAC's hold the whole address without any mode flags */ | ||
| 780 | task->thread.dabr = data & ~0x3UL; | ||
| 781 | |||
| 782 | if (task->thread.dabr == 0) { | ||
| 783 | task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM); | ||
| 784 | task->thread.regs->msr &= ~MSR_DE; | ||
| 785 | return 0; | ||
| 786 | } | ||
| 787 | |||
| 788 | /* Read or Write bits must be set */ | ||
| 789 | |||
| 790 | if (!(data & 0x3UL)) | ||
| 791 | return -EINVAL; | ||
| 792 | |||
| 793 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 | ||
| 794 | register */ | ||
| 795 | task->thread.dbcr0 = DBCR0_IDM; | ||
| 796 | |||
| 797 | /* Check for write and read flags and set DBCR0 | ||
| 798 | accordingly */ | ||
| 799 | if (data & 0x1UL) | ||
| 800 | task->thread.dbcr0 |= DBSR_DAC1R; | ||
| 801 | if (data & 0x2UL) | ||
| 802 | task->thread.dbcr0 |= DBSR_DAC1W; | ||
| 803 | |||
| 804 | task->thread.regs->msr |= MSR_DE; | ||
| 805 | #endif | ||
| 746 | return 0; | 806 | return 0; |
| 747 | } | 807 | } |
| 748 | 808 | ||
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index ad55488939c3..7aada783ec6a 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -145,8 +145,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
| 145 | * user space. The DABR will have been cleared if it | 145 | * user space. The DABR will have been cleared if it |
| 146 | * triggered inside the kernel. | 146 | * triggered inside the kernel. |
| 147 | */ | 147 | */ |
| 148 | if (current->thread.dabr) | 148 | if (current->thread.dabr) { |
| 149 | set_dabr(current->thread.dabr); | 149 | set_dabr(current->thread.dabr); |
| 150 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 151 | mtspr(SPRN_DBCR0, current->thread.dbcr0); | ||
| 152 | #endif | ||
| 153 | } | ||
| 150 | 154 | ||
| 151 | if (is32) { | 155 | if (is32) { |
| 152 | if (ka.sa.sa_flags & SA_SIGINFO) | 156 | if (ka.sa.sa_flags & SA_SIGINFO) |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index aba0ba95f062..800e5e9a087b 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
| @@ -529,7 +529,8 @@ static void register_nodes(void) | |||
| 529 | #endif | 529 | #endif |
| 530 | 530 | ||
| 531 | /* Only valid if CPU is present. */ | 531 | /* Only valid if CPU is present. */ |
| 532 | static ssize_t show_physical_id(struct sys_device *dev, char *buf) | 532 | static ssize_t show_physical_id(struct sys_device *dev, |
| 533 | struct sysdev_attribute *attr, char *buf) | ||
| 533 | { | 534 | { |
| 534 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 535 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
| 535 | 536 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 878fbddb6ae1..81ccb8dd1a54 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -1067,6 +1067,22 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | |||
| 1067 | } | 1067 | } |
| 1068 | 1068 | ||
| 1069 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); | 1069 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); |
| 1070 | } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { | ||
| 1071 | regs->msr &= ~MSR_DE; | ||
| 1072 | |||
| 1073 | if (user_mode(regs)) { | ||
| 1074 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | | ||
| 1075 | DBCR0_IDM); | ||
| 1076 | } else { | ||
| 1077 | /* Disable DAC interupts */ | ||
| 1078 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | | ||
| 1079 | DBSR_DAC1W | DBCR0_IDM)); | ||
| 1080 | |||
| 1081 | /* Clear the DAC event */ | ||
| 1082 | mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W)); | ||
| 1083 | } | ||
| 1084 | /* Setup and send the trap to the handler */ | ||
| 1085 | do_dabr(regs, mfspr(SPRN_DAC1), debug_status); | ||
| 1070 | } | 1086 | } |
| 1071 | } | 1087 | } |
| 1072 | #endif /* CONFIG_4xx || CONFIG_BOOKE */ | 1088 | #endif /* CONFIG_4xx || CONFIG_BOOKE */ |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index b77f8af7ddde..ade8aeaa2e70 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
| @@ -1,11 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * IBM PowerPC Virtual I/O Infrastructure Support. | 2 | * IBM PowerPC Virtual I/O Infrastructure Support. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2003-2005 IBM Corp. | 4 | * Copyright (c) 2003,2008 IBM Corp. |
| 5 | * Dave Engebretsen engebret@us.ibm.com | 5 | * Dave Engebretsen engebret@us.ibm.com |
| 6 | * Santiago Leon santil@us.ibm.com | 6 | * Santiago Leon santil@us.ibm.com |
| 7 | * Hollis Blanchard <hollisb@us.ibm.com> | 7 | * Hollis Blanchard <hollisb@us.ibm.com> |
| 8 | * Stephen Rothwell | 8 | * Stephen Rothwell |
| 9 | * Robert Jennings <rcjenn@us.ibm.com> | ||
| 9 | * | 10 | * |
| 10 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
| 11 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
| @@ -46,6 +47,996 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */ | |||
| 46 | .dev.bus = &vio_bus_type, | 47 | .dev.bus = &vio_bus_type, |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 50 | #ifdef CONFIG_PPC_SMLPAR | ||
| 51 | /** | ||
| 52 | * vio_cmo_pool - A pool of IO memory for CMO use | ||
| 53 | * | ||
| 54 | * @size: The size of the pool in bytes | ||
| 55 | * @free: The amount of free memory in the pool | ||
| 56 | */ | ||
| 57 | struct vio_cmo_pool { | ||
| 58 | size_t size; | ||
| 59 | size_t free; | ||
| 60 | }; | ||
| 61 | |||
| 62 | /* How many ms to delay queued balance work */ | ||
| 63 | #define VIO_CMO_BALANCE_DELAY 100 | ||
| 64 | |||
| 65 | /* Portion out IO memory to CMO devices by this chunk size */ | ||
| 66 | #define VIO_CMO_BALANCE_CHUNK 131072 | ||
| 67 | |||
| 68 | /** | ||
| 69 | * vio_cmo_dev_entry - A device that is CMO-enabled and requires entitlement | ||
| 70 | * | ||
| 71 | * @vio_dev: struct vio_dev pointer | ||
| 72 | * @list: pointer to other devices on bus that are being tracked | ||
| 73 | */ | ||
| 74 | struct vio_cmo_dev_entry { | ||
| 75 | struct vio_dev *viodev; | ||
| 76 | struct list_head list; | ||
| 77 | }; | ||
| 78 | |||
| 79 | /** | ||
| 80 | * vio_cmo - VIO bus accounting structure for CMO entitlement | ||
| 81 | * | ||
| 82 | * @lock: spinlock for entire structure | ||
| 83 | * @balance_q: work queue for balancing system entitlement | ||
| 84 | * @device_list: list of CMO-enabled devices requiring entitlement | ||
| 85 | * @entitled: total system entitlement in bytes | ||
| 86 | * @reserve: pool of memory from which devices reserve entitlement, incl. spare | ||
| 87 | * @excess: pool of excess entitlement not needed for device reserves or spare | ||
| 88 | * @spare: IO memory for device hotplug functionality | ||
| 89 | * @min: minimum necessary for system operation | ||
| 90 | * @desired: desired memory for system operation | ||
| 91 | * @curr: bytes currently allocated | ||
| 92 | * @high: high water mark for IO data usage | ||
| 93 | */ | ||
| 94 | struct vio_cmo { | ||
| 95 | spinlock_t lock; | ||
| 96 | struct delayed_work balance_q; | ||
| 97 | struct list_head device_list; | ||
| 98 | size_t entitled; | ||
| 99 | struct vio_cmo_pool reserve; | ||
| 100 | struct vio_cmo_pool excess; | ||
| 101 | size_t spare; | ||
| 102 | size_t min; | ||
| 103 | size_t desired; | ||
| 104 | size_t curr; | ||
| 105 | size_t high; | ||
| 106 | } vio_cmo; | ||
| 107 | |||
| 108 | /** | ||
| 109 | * vio_cmo_OF_devices - Count the number of OF devices that have DMA windows | ||
| 110 | */ | ||
| 111 | static int vio_cmo_num_OF_devs(void) | ||
| 112 | { | ||
| 113 | struct device_node *node_vroot; | ||
| 114 | int count = 0; | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Count the number of vdevice entries with an | ||
| 118 | * ibm,my-dma-window OF property | ||
| 119 | */ | ||
| 120 | node_vroot = of_find_node_by_name(NULL, "vdevice"); | ||
| 121 | if (node_vroot) { | ||
| 122 | struct device_node *of_node; | ||
| 123 | struct property *prop; | ||
| 124 | |||
| 125 | for_each_child_of_node(node_vroot, of_node) { | ||
| 126 | prop = of_find_property(of_node, "ibm,my-dma-window", | ||
| 127 | NULL); | ||
| 128 | if (prop) | ||
| 129 | count++; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | of_node_put(node_vroot); | ||
| 133 | return count; | ||
| 134 | } | ||
| 135 | |||
| 136 | /** | ||
| 137 | * vio_cmo_alloc - allocate IO memory for CMO-enable devices | ||
| 138 | * | ||
| 139 | * @viodev: VIO device requesting IO memory | ||
| 140 | * @size: size of allocation requested | ||
| 141 | * | ||
| 142 | * Allocations come from memory reserved for the devices and any excess | ||
| 143 | * IO memory available to all devices. The spare pool used to service | ||
| 144 | * hotplug must be equal to %VIO_CMO_MIN_ENT for the excess pool to be | ||
| 145 | * made available. | ||
| 146 | * | ||
| 147 | * Return codes: | ||
| 148 | * 0 for successful allocation and -ENOMEM for a failure | ||
| 149 | */ | ||
| 150 | static inline int vio_cmo_alloc(struct vio_dev *viodev, size_t size) | ||
| 151 | { | ||
| 152 | unsigned long flags; | ||
| 153 | size_t reserve_free = 0; | ||
| 154 | size_t excess_free = 0; | ||
| 155 | int ret = -ENOMEM; | ||
| 156 | |||
| 157 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 158 | |||
| 159 | /* Determine the amount of free entitlement available in reserve */ | ||
| 160 | if (viodev->cmo.entitled > viodev->cmo.allocated) | ||
| 161 | reserve_free = viodev->cmo.entitled - viodev->cmo.allocated; | ||
| 162 | |||
| 163 | /* If spare is not fulfilled, the excess pool can not be used. */ | ||
| 164 | if (vio_cmo.spare >= VIO_CMO_MIN_ENT) | ||
| 165 | excess_free = vio_cmo.excess.free; | ||
| 166 | |||
| 167 | /* The request can be satisfied */ | ||
| 168 | if ((reserve_free + excess_free) >= size) { | ||
| 169 | vio_cmo.curr += size; | ||
| 170 | if (vio_cmo.curr > vio_cmo.high) | ||
| 171 | vio_cmo.high = vio_cmo.curr; | ||
| 172 | viodev->cmo.allocated += size; | ||
| 173 | size -= min(reserve_free, size); | ||
| 174 | vio_cmo.excess.free -= size; | ||
| 175 | ret = 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 179 | return ret; | ||
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 183 | * vio_cmo_dealloc - deallocate IO memory from CMO-enable devices | ||
| 184 | * @viodev: VIO device freeing IO memory | ||
| 185 | * @size: size of deallocation | ||
| 186 | * | ||
| 187 | * IO memory is freed by the device back to the correct memory pools. | ||
| 188 | * The spare pool is replenished first from either memory pool, then | ||
| 189 | * the reserve pool is used to reduce device entitlement, the excess | ||
| 190 | * pool is used to increase the reserve pool toward the desired entitlement | ||
| 191 | * target, and then the remaining memory is returned to the pools. | ||
| 192 | * | ||
| 193 | */ | ||
| 194 | static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size) | ||
| 195 | { | ||
| 196 | unsigned long flags; | ||
| 197 | size_t spare_needed = 0; | ||
| 198 | size_t excess_freed = 0; | ||
| 199 | size_t reserve_freed = size; | ||
| 200 | size_t tmp; | ||
| 201 | int balance = 0; | ||
| 202 | |||
| 203 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 204 | vio_cmo.curr -= size; | ||
| 205 | |||
| 206 | /* Amount of memory freed from the excess pool */ | ||
| 207 | if (viodev->cmo.allocated > viodev->cmo.entitled) { | ||
| 208 | excess_freed = min(reserve_freed, (viodev->cmo.allocated - | ||
| 209 | viodev->cmo.entitled)); | ||
| 210 | reserve_freed -= excess_freed; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* Remove allocation from device */ | ||
| 214 | viodev->cmo.allocated -= (reserve_freed + excess_freed); | ||
| 215 | |||
| 216 | /* Spare is a subset of the reserve pool, replenish it first. */ | ||
| 217 | spare_needed = VIO_CMO_MIN_ENT - vio_cmo.spare; | ||
| 218 | |||
| 219 | /* | ||
| 220 | * Replenish the spare in the reserve pool from the excess pool. | ||
| 221 | * This moves entitlement into the reserve pool. | ||
| 222 | */ | ||
| 223 | if (spare_needed && excess_freed) { | ||
| 224 | tmp = min(excess_freed, spare_needed); | ||
| 225 | vio_cmo.excess.size -= tmp; | ||
| 226 | vio_cmo.reserve.size += tmp; | ||
| 227 | vio_cmo.spare += tmp; | ||
| 228 | excess_freed -= tmp; | ||
| 229 | spare_needed -= tmp; | ||
| 230 | balance = 1; | ||
| 231 | } | ||
| 232 | |||
| 233 | /* | ||
| 234 | * Replenish the spare in the reserve pool from the reserve pool. | ||
| 235 | * This removes entitlement from the device down to VIO_CMO_MIN_ENT, | ||
| 236 | * if needed, and gives it to the spare pool. The amount of used | ||
| 237 | * memory in this pool does not change. | ||
| 238 | */ | ||
| 239 | if (spare_needed && reserve_freed) { | ||
| 240 | tmp = min(spare_needed, min(reserve_freed, | ||
| 241 | (viodev->cmo.entitled - | ||
| 242 | VIO_CMO_MIN_ENT))); | ||
| 243 | |||
| 244 | vio_cmo.spare += tmp; | ||
| 245 | viodev->cmo.entitled -= tmp; | ||
| 246 | reserve_freed -= tmp; | ||
| 247 | spare_needed -= tmp; | ||
| 248 | balance = 1; | ||
| 249 | } | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Increase the reserve pool until the desired allocation is met. | ||
| 253 | * Move an allocation freed from the excess pool into the reserve | ||
| 254 | * pool and schedule a balance operation. | ||
| 255 | */ | ||
| 256 | if (excess_freed && (vio_cmo.desired > vio_cmo.reserve.size)) { | ||
| 257 | tmp = min(excess_freed, (vio_cmo.desired - vio_cmo.reserve.size)); | ||
| 258 | |||
| 259 | vio_cmo.excess.size -= tmp; | ||
| 260 | vio_cmo.reserve.size += tmp; | ||
| 261 | excess_freed -= tmp; | ||
| 262 | balance = 1; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* Return memory from the excess pool to that pool */ | ||
| 266 | if (excess_freed) | ||
| 267 | vio_cmo.excess.free += excess_freed; | ||
| 268 | |||
| 269 | if (balance) | ||
| 270 | schedule_delayed_work(&vio_cmo.balance_q, VIO_CMO_BALANCE_DELAY); | ||
| 271 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 272 | } | ||
| 273 | |||
| 274 | /** | ||
| 275 | * vio_cmo_entitlement_update - Manage system entitlement changes | ||
| 276 | * | ||
| 277 | * @new_entitlement: new system entitlement to attempt to accommodate | ||
| 278 | * | ||
| 279 | * Increases in entitlement will be used to fulfill the spare entitlement | ||
| 280 | * and the rest is given to the excess pool. Decreases, if they are | ||
| 281 | * possible, come from the excess pool and from unused device entitlement | ||
| 282 | * | ||
| 283 | * Returns: 0 on success, -ENOMEM when change can not be made | ||
| 284 | */ | ||
| 285 | int vio_cmo_entitlement_update(size_t new_entitlement) | ||
| 286 | { | ||
| 287 | struct vio_dev *viodev; | ||
| 288 | struct vio_cmo_dev_entry *dev_ent; | ||
| 289 | unsigned long flags; | ||
| 290 | size_t avail, delta, tmp; | ||
| 291 | |||
| 292 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 293 | |||
| 294 | /* Entitlement increases */ | ||
| 295 | if (new_entitlement > vio_cmo.entitled) { | ||
| 296 | delta = new_entitlement - vio_cmo.entitled; | ||
| 297 | |||
| 298 | /* Fulfill spare allocation */ | ||
| 299 | if (vio_cmo.spare < VIO_CMO_MIN_ENT) { | ||
| 300 | tmp = min(delta, (VIO_CMO_MIN_ENT - vio_cmo.spare)); | ||
| 301 | vio_cmo.spare += tmp; | ||
| 302 | vio_cmo.reserve.size += tmp; | ||
| 303 | delta -= tmp; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* Remaining new allocation goes to the excess pool */ | ||
| 307 | vio_cmo.entitled += delta; | ||
| 308 | vio_cmo.excess.size += delta; | ||
| 309 | vio_cmo.excess.free += delta; | ||
| 310 | |||
| 311 | goto out; | ||
| 312 | } | ||
| 313 | |||
| 314 | /* Entitlement decreases */ | ||
| 315 | delta = vio_cmo.entitled - new_entitlement; | ||
| 316 | avail = vio_cmo.excess.free; | ||
| 317 | |||
| 318 | /* | ||
| 319 | * Need to check how much unused entitlement each device can | ||
| 320 | * sacrifice to fulfill entitlement change. | ||
| 321 | */ | ||
| 322 | list_for_each_entry(dev_ent, &vio_cmo.device_list, list) { | ||
| 323 | if (avail >= delta) | ||
| 324 | break; | ||
| 325 | |||
| 326 | viodev = dev_ent->viodev; | ||
| 327 | if ((viodev->cmo.entitled > viodev->cmo.allocated) && | ||
| 328 | (viodev->cmo.entitled > VIO_CMO_MIN_ENT)) | ||
| 329 | avail += viodev->cmo.entitled - | ||
| 330 | max_t(size_t, viodev->cmo.allocated, | ||
| 331 | VIO_CMO_MIN_ENT); | ||
| 332 | } | ||
| 333 | |||
| 334 | if (delta <= avail) { | ||
| 335 | vio_cmo.entitled -= delta; | ||
| 336 | |||
| 337 | /* Take entitlement from the excess pool first */ | ||
| 338 | tmp = min(vio_cmo.excess.free, delta); | ||
| 339 | vio_cmo.excess.size -= tmp; | ||
| 340 | vio_cmo.excess.free -= tmp; | ||
| 341 | delta -= tmp; | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Remove all but VIO_CMO_MIN_ENT bytes from devices | ||
| 345 | * until entitlement change is served | ||
| 346 | */ | ||
| 347 | list_for_each_entry(dev_ent, &vio_cmo.device_list, list) { | ||
| 348 | if (!delta) | ||
| 349 | break; | ||
| 350 | |||
| 351 | viodev = dev_ent->viodev; | ||
| 352 | tmp = 0; | ||
| 353 | if ((viodev->cmo.entitled > viodev->cmo.allocated) && | ||
| 354 | (viodev->cmo.entitled > VIO_CMO_MIN_ENT)) | ||
| 355 | tmp = viodev->cmo.entitled - | ||
| 356 | max_t(size_t, viodev->cmo.allocated, | ||
| 357 | VIO_CMO_MIN_ENT); | ||
| 358 | viodev->cmo.entitled -= min(tmp, delta); | ||
| 359 | delta -= min(tmp, delta); | ||
| 360 | } | ||
| 361 | } else { | ||
| 362 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 363 | return -ENOMEM; | ||
| 364 | } | ||
| 365 | |||
| 366 | out: | ||
| 367 | schedule_delayed_work(&vio_cmo.balance_q, 0); | ||
| 368 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 369 | return 0; | ||
| 370 | } | ||
| 371 | |||
| 372 | /** | ||
| 373 | * vio_cmo_balance - Balance entitlement among devices | ||
| 374 | * | ||
| 375 | * @work: work queue structure for this operation | ||
| 376 | * | ||
| 377 | * Any system entitlement above the minimum needed for devices, or | ||
| 378 | * already allocated to devices, can be distributed to the devices. | ||
| 379 | * The list of devices is iterated through to recalculate the desired | ||
| 380 | * entitlement level and to determine how much entitlement above the | ||
| 381 | * minimum entitlement is allocated to devices. | ||
| 382 | * | ||
| 383 | * Small chunks of the available entitlement are given to devices until | ||
| 384 | * their requirements are fulfilled or there is no entitlement left to give. | ||
| 385 | * Upon completion sizes of the reserve and excess pools are calculated. | ||
| 386 | * | ||
| 387 | * The system minimum entitlement level is also recalculated here. | ||
| 388 | * Entitlement will be reserved for devices even after vio_bus_remove to | ||
| 389 | * accommodate reloading the driver. The OF tree is walked to count the | ||
| 390 | * number of devices present and this will remove entitlement for devices | ||
| 391 | * that have actually left the system after having vio_bus_remove called. | ||
| 392 | */ | ||
| 393 | static void vio_cmo_balance(struct work_struct *work) | ||
| 394 | { | ||
| 395 | struct vio_cmo *cmo; | ||
| 396 | struct vio_dev *viodev; | ||
| 397 | struct vio_cmo_dev_entry *dev_ent; | ||
| 398 | unsigned long flags; | ||
| 399 | size_t avail = 0, level, chunk, need; | ||
| 400 | int devcount = 0, fulfilled; | ||
| 401 | |||
| 402 | cmo = container_of(work, struct vio_cmo, balance_q.work); | ||
| 403 | |||
| 404 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 405 | |||
| 406 | /* Calculate minimum entitlement and fulfill spare */ | ||
| 407 | cmo->min = vio_cmo_num_OF_devs() * VIO_CMO_MIN_ENT; | ||
| 408 | BUG_ON(cmo->min > cmo->entitled); | ||
| 409 | cmo->spare = min_t(size_t, VIO_CMO_MIN_ENT, (cmo->entitled - cmo->min)); | ||
| 410 | cmo->min += cmo->spare; | ||
| 411 | cmo->desired = cmo->min; | ||
| 412 | |||
| 413 | /* | ||
| 414 | * Determine how much entitlement is available and reset device | ||
| 415 | * entitlements | ||
| 416 | */ | ||
| 417 | avail = cmo->entitled - cmo->spare; | ||
| 418 | list_for_each_entry(dev_ent, &vio_cmo.device_list, list) { | ||
| 419 | viodev = dev_ent->viodev; | ||
| 420 | devcount++; | ||
| 421 | viodev->cmo.entitled = VIO_CMO_MIN_ENT; | ||
| 422 | cmo->desired += (viodev->cmo.desired - VIO_CMO_MIN_ENT); | ||
| 423 | avail -= max_t(size_t, viodev->cmo.allocated, VIO_CMO_MIN_ENT); | ||
| 424 | } | ||
| 425 | |||
| 426 | /* | ||
| 427 | * Having provided each device with the minimum entitlement, loop | ||
| 428 | * over the devices portioning out the remaining entitlement | ||
| 429 | * until there is nothing left. | ||
| 430 | */ | ||
| 431 | level = VIO_CMO_MIN_ENT; | ||
| 432 | while (avail) { | ||
| 433 | fulfilled = 0; | ||
| 434 | list_for_each_entry(dev_ent, &vio_cmo.device_list, list) { | ||
| 435 | viodev = dev_ent->viodev; | ||
| 436 | |||
| 437 | if (viodev->cmo.desired <= level) { | ||
| 438 | fulfilled++; | ||
| 439 | continue; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* | ||
| 443 | * Give the device up to VIO_CMO_BALANCE_CHUNK | ||
| 444 | * bytes of entitlement, but do not exceed the | ||
| 445 | * desired level of entitlement for the device. | ||
| 446 | */ | ||
| 447 | chunk = min_t(size_t, avail, VIO_CMO_BALANCE_CHUNK); | ||
| 448 | chunk = min(chunk, (viodev->cmo.desired - | ||
| 449 | viodev->cmo.entitled)); | ||
| 450 | viodev->cmo.entitled += chunk; | ||
| 451 | |||
| 452 | /* | ||
| 453 | * If the memory for this entitlement increase was | ||
| 454 | * already allocated to the device it does not come | ||
| 455 | * from the available pool being portioned out. | ||
| 456 | */ | ||
| 457 | need = max(viodev->cmo.allocated, viodev->cmo.entitled)- | ||
| 458 | max(viodev->cmo.allocated, level); | ||
| 459 | avail -= need; | ||
| 460 | |||
| 461 | } | ||
| 462 | if (fulfilled == devcount) | ||
| 463 | break; | ||
| 464 | level += VIO_CMO_BALANCE_CHUNK; | ||
| 465 | } | ||
| 466 | |||
| 467 | /* Calculate new reserve and excess pool sizes */ | ||
| 468 | cmo->reserve.size = cmo->min; | ||
| 469 | cmo->excess.free = 0; | ||
| 470 | cmo->excess.size = 0; | ||
| 471 | need = 0; | ||
| 472 | list_for_each_entry(dev_ent, &vio_cmo.device_list, list) { | ||
| 473 | viodev = dev_ent->viodev; | ||
| 474 | /* Calculated reserve size above the minimum entitlement */ | ||
| 475 | if (viodev->cmo.entitled) | ||
| 476 | cmo->reserve.size += (viodev->cmo.entitled - | ||
| 477 | VIO_CMO_MIN_ENT); | ||
| 478 | /* Calculated used excess entitlement */ | ||
| 479 | if (viodev->cmo.allocated > viodev->cmo.entitled) | ||
| 480 | need += viodev->cmo.allocated - viodev->cmo.entitled; | ||
| 481 | } | ||
| 482 | cmo->excess.size = cmo->entitled - cmo->reserve.size; | ||
| 483 | cmo->excess.free = cmo->excess.size - need; | ||
| 484 | |||
| 485 | cancel_delayed_work(container_of(work, struct delayed_work, work)); | ||
| 486 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 487 | } | ||
| 488 | |||
| 489 | static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size, | ||
| 490 | dma_addr_t *dma_handle, gfp_t flag) | ||
| 491 | { | ||
| 492 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 493 | void *ret; | ||
| 494 | |||
| 495 | if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) { | ||
| 496 | atomic_inc(&viodev->cmo.allocs_failed); | ||
| 497 | return NULL; | ||
| 498 | } | ||
| 499 | |||
| 500 | ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag); | ||
| 501 | if (unlikely(ret == NULL)) { | ||
| 502 | vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE)); | ||
| 503 | atomic_inc(&viodev->cmo.allocs_failed); | ||
| 504 | } | ||
| 505 | |||
| 506 | return ret; | ||
| 507 | } | ||
| 508 | |||
| 509 | static void vio_dma_iommu_free_coherent(struct device *dev, size_t size, | ||
| 510 | void *vaddr, dma_addr_t dma_handle) | ||
| 511 | { | ||
| 512 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 513 | |||
| 514 | dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle); | ||
| 515 | |||
| 516 | vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE)); | ||
| 517 | } | ||
| 518 | |||
| 519 | static dma_addr_t vio_dma_iommu_map_single(struct device *dev, void *vaddr, | ||
| 520 | size_t size, | ||
| 521 | enum dma_data_direction direction, | ||
| 522 | struct dma_attrs *attrs) | ||
| 523 | { | ||
| 524 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 525 | dma_addr_t ret = DMA_ERROR_CODE; | ||
| 526 | |||
| 527 | if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) { | ||
| 528 | atomic_inc(&viodev->cmo.allocs_failed); | ||
| 529 | return ret; | ||
| 530 | } | ||
| 531 | |||
| 532 | ret = dma_iommu_ops.map_single(dev, vaddr, size, direction, attrs); | ||
| 533 | if (unlikely(dma_mapping_error(ret))) { | ||
| 534 | vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE)); | ||
| 535 | atomic_inc(&viodev->cmo.allocs_failed); | ||
| 536 | } | ||
| 537 | |||
| 538 | return ret; | ||
| 539 | } | ||
| 540 | |||
| 541 | static void vio_dma_iommu_unmap_single(struct device *dev, | ||
| 542 | dma_addr_t dma_handle, size_t size, | ||
| 543 | enum dma_data_direction direction, | ||
| 544 | struct dma_attrs *attrs) | ||
| 545 | { | ||
| 546 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 547 | |||
| 548 | dma_iommu_ops.unmap_single(dev, dma_handle, size, direction, attrs); | ||
| 549 | |||
| 550 | vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE)); | ||
| 551 | } | ||
| 552 | |||
| 553 | static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist, | ||
| 554 | int nelems, enum dma_data_direction direction, | ||
| 555 | struct dma_attrs *attrs) | ||
| 556 | { | ||
| 557 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 558 | struct scatterlist *sgl; | ||
| 559 | int ret, count = 0; | ||
| 560 | size_t alloc_size = 0; | ||
| 561 | |||
| 562 | for (sgl = sglist; count < nelems; count++, sgl++) | ||
| 563 | alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE); | ||
| 564 | |||
| 565 | if (vio_cmo_alloc(viodev, alloc_size)) { | ||
| 566 | atomic_inc(&viodev->cmo.allocs_failed); | ||
| 567 | return 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | ret = dma_iommu_ops.map_sg(dev, sglist, nelems, direction, attrs); | ||
| 571 | |||
| 572 | if (unlikely(!ret)) { | ||
| 573 | vio_cmo_dealloc(viodev, alloc_size); | ||
| 574 | atomic_inc(&viodev->cmo.allocs_failed); | ||
| 575 | } | ||
| 576 | |||
| 577 | for (sgl = sglist, count = 0; count < ret; count++, sgl++) | ||
| 578 | alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE); | ||
| 579 | if (alloc_size) | ||
| 580 | vio_cmo_dealloc(viodev, alloc_size); | ||
| 581 | |||
| 582 | return ret; | ||
| 583 | } | ||
| 584 | |||
| 585 | static void vio_dma_iommu_unmap_sg(struct device *dev, | ||
| 586 | struct scatterlist *sglist, int nelems, | ||
| 587 | enum dma_data_direction direction, | ||
| 588 | struct dma_attrs *attrs) | ||
| 589 | { | ||
| 590 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 591 | struct scatterlist *sgl; | ||
| 592 | size_t alloc_size = 0; | ||
| 593 | int count = 0; | ||
| 594 | |||
| 595 | for (sgl = sglist; count < nelems; count++, sgl++) | ||
| 596 | alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE); | ||
| 597 | |||
| 598 | dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs); | ||
| 599 | |||
| 600 | vio_cmo_dealloc(viodev, alloc_size); | ||
| 601 | } | ||
| 602 | |||
| 603 | struct dma_mapping_ops vio_dma_mapping_ops = { | ||
| 604 | .alloc_coherent = vio_dma_iommu_alloc_coherent, | ||
| 605 | .free_coherent = vio_dma_iommu_free_coherent, | ||
| 606 | .map_single = vio_dma_iommu_map_single, | ||
| 607 | .unmap_single = vio_dma_iommu_unmap_single, | ||
| 608 | .map_sg = vio_dma_iommu_map_sg, | ||
| 609 | .unmap_sg = vio_dma_iommu_unmap_sg, | ||
| 610 | }; | ||
| 611 | |||
| 612 | /** | ||
| 613 | * vio_cmo_set_dev_desired - Set desired entitlement for a device | ||
| 614 | * | ||
| 615 | * @viodev: struct vio_dev for device to alter | ||
| 616 | * @new_desired: new desired entitlement level in bytes | ||
| 617 | * | ||
| 618 | * For use by devices to request a change to their entitlement at runtime or | ||
| 619 | * through sysfs. The desired entitlement level is changed and a balancing | ||
| 620 | * of system resources is scheduled to run in the future. | ||
| 621 | */ | ||
| 622 | void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) | ||
| 623 | { | ||
| 624 | unsigned long flags; | ||
| 625 | struct vio_cmo_dev_entry *dev_ent; | ||
| 626 | int found = 0; | ||
| 627 | |||
| 628 | if (!firmware_has_feature(FW_FEATURE_CMO)) | ||
| 629 | return; | ||
| 630 | |||
| 631 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 632 | if (desired < VIO_CMO_MIN_ENT) | ||
| 633 | desired = VIO_CMO_MIN_ENT; | ||
| 634 | |||
| 635 | /* | ||
| 636 | * Changes will not be made for devices not in the device list. | ||
| 637 | * If it is not in the device list, then no driver is loaded | ||
| 638 | * for the device and it can not receive entitlement. | ||
| 639 | */ | ||
| 640 | list_for_each_entry(dev_ent, &vio_cmo.device_list, list) | ||
| 641 | if (viodev == dev_ent->viodev) { | ||
| 642 | found = 1; | ||
| 643 | break; | ||
| 644 | } | ||
| 645 | if (!found) | ||
| 646 | return; | ||
| 647 | |||
| 648 | /* Increase/decrease in desired device entitlement */ | ||
| 649 | if (desired >= viodev->cmo.desired) { | ||
| 650 | /* Just bump the bus and device values prior to a balance*/ | ||
| 651 | vio_cmo.desired += desired - viodev->cmo.desired; | ||
| 652 | viodev->cmo.desired = desired; | ||
| 653 | } else { | ||
| 654 | /* Decrease bus and device values for desired entitlement */ | ||
| 655 | vio_cmo.desired -= viodev->cmo.desired - desired; | ||
| 656 | viodev->cmo.desired = desired; | ||
| 657 | /* | ||
| 658 | * If less entitlement is desired than current entitlement, move | ||
| 659 | * any reserve memory in the change region to the excess pool. | ||
| 660 | */ | ||
| 661 | if (viodev->cmo.entitled > desired) { | ||
| 662 | vio_cmo.reserve.size -= viodev->cmo.entitled - desired; | ||
| 663 | vio_cmo.excess.size += viodev->cmo.entitled - desired; | ||
| 664 | /* | ||
| 665 | * If entitlement moving from the reserve pool to the | ||
| 666 | * excess pool is currently unused, add to the excess | ||
| 667 | * free counter. | ||
| 668 | */ | ||
| 669 | if (viodev->cmo.allocated < viodev->cmo.entitled) | ||
| 670 | vio_cmo.excess.free += viodev->cmo.entitled - | ||
| 671 | max(viodev->cmo.allocated, desired); | ||
| 672 | viodev->cmo.entitled = desired; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | schedule_delayed_work(&vio_cmo.balance_q, 0); | ||
| 676 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 677 | } | ||
| 678 | |||
| 679 | /** | ||
| 680 | * vio_cmo_bus_probe - Handle CMO specific bus probe activities | ||
| 681 | * | ||
| 682 | * @viodev - Pointer to struct vio_dev for device | ||
| 683 | * | ||
| 684 | * Determine the devices IO memory entitlement needs, attempting | ||
| 685 | * to satisfy the system minimum entitlement at first and scheduling | ||
| 686 | * a balance operation to take care of the rest at a later time. | ||
| 687 | * | ||
| 688 | * Returns: 0 on success, -EINVAL when device doesn't support CMO, and | ||
| 689 | * -ENOMEM when entitlement is not available for device or | ||
| 690 | * device entry. | ||
| 691 | * | ||
| 692 | */ | ||
| 693 | static int vio_cmo_bus_probe(struct vio_dev *viodev) | ||
| 694 | { | ||
| 695 | struct vio_cmo_dev_entry *dev_ent; | ||
| 696 | struct device *dev = &viodev->dev; | ||
| 697 | struct vio_driver *viodrv = to_vio_driver(dev->driver); | ||
| 698 | unsigned long flags; | ||
| 699 | size_t size; | ||
| 700 | |||
| 701 | /* | ||
| 702 | * Check to see that device has a DMA window and configure | ||
| 703 | * entitlement for the device. | ||
| 704 | */ | ||
| 705 | if (of_get_property(viodev->dev.archdata.of_node, | ||
| 706 | "ibm,my-dma-window", NULL)) { | ||
| 707 | /* Check that the driver is CMO enabled and get desired DMA */ | ||
| 708 | if (!viodrv->get_desired_dma) { | ||
| 709 | dev_err(dev, "%s: device driver does not support CMO\n", | ||
| 710 | __func__); | ||
| 711 | return -EINVAL; | ||
| 712 | } | ||
| 713 | |||
| 714 | viodev->cmo.desired = IOMMU_PAGE_ALIGN(viodrv->get_desired_dma(viodev)); | ||
| 715 | if (viodev->cmo.desired < VIO_CMO_MIN_ENT) | ||
| 716 | viodev->cmo.desired = VIO_CMO_MIN_ENT; | ||
| 717 | size = VIO_CMO_MIN_ENT; | ||
| 718 | |||
| 719 | dev_ent = kmalloc(sizeof(struct vio_cmo_dev_entry), | ||
| 720 | GFP_KERNEL); | ||
| 721 | if (!dev_ent) | ||
| 722 | return -ENOMEM; | ||
| 723 | |||
| 724 | dev_ent->viodev = viodev; | ||
| 725 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 726 | list_add(&dev_ent->list, &vio_cmo.device_list); | ||
| 727 | } else { | ||
| 728 | viodev->cmo.desired = 0; | ||
| 729 | size = 0; | ||
| 730 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 731 | } | ||
| 732 | |||
| 733 | /* | ||
| 734 | * If the needs for vio_cmo.min have not changed since they | ||
| 735 | * were last set, the number of devices in the OF tree has | ||
| 736 | * been constant and the IO memory for this is already in | ||
| 737 | * the reserve pool. | ||
| 738 | */ | ||
| 739 | if (vio_cmo.min == ((vio_cmo_num_OF_devs() + 1) * | ||
| 740 | VIO_CMO_MIN_ENT)) { | ||
| 741 | /* Updated desired entitlement if device requires it */ | ||
| 742 | if (size) | ||
| 743 | vio_cmo.desired += (viodev->cmo.desired - | ||
| 744 | VIO_CMO_MIN_ENT); | ||
| 745 | } else { | ||
| 746 | size_t tmp; | ||
| 747 | |||
| 748 | tmp = vio_cmo.spare + vio_cmo.excess.free; | ||
| 749 | if (tmp < size) { | ||
| 750 | dev_err(dev, "%s: insufficient free " | ||
| 751 | "entitlement to add device. " | ||
| 752 | "Need %lu, have %lu\n", __func__, | ||
| 753 | size, (vio_cmo.spare + tmp)); | ||
| 754 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 755 | return -ENOMEM; | ||
| 756 | } | ||
| 757 | |||
| 758 | /* Use excess pool first to fulfill request */ | ||
| 759 | tmp = min(size, vio_cmo.excess.free); | ||
| 760 | vio_cmo.excess.free -= tmp; | ||
| 761 | vio_cmo.excess.size -= tmp; | ||
| 762 | vio_cmo.reserve.size += tmp; | ||
| 763 | |||
| 764 | /* Use spare if excess pool was insufficient */ | ||
| 765 | vio_cmo.spare -= size - tmp; | ||
| 766 | |||
| 767 | /* Update bus accounting */ | ||
| 768 | vio_cmo.min += size; | ||
| 769 | vio_cmo.desired += viodev->cmo.desired; | ||
| 770 | } | ||
| 771 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 772 | return 0; | ||
| 773 | } | ||
| 774 | |||
| 775 | /** | ||
| 776 | * vio_cmo_bus_remove - Handle CMO specific bus removal activities | ||
| 777 | * | ||
| 778 | * @viodev - Pointer to struct vio_dev for device | ||
| 779 | * | ||
| 780 | * Remove the device from the cmo device list. The minimum entitlement | ||
| 781 | * will be reserved for the device as long as it is in the system. The | ||
| 782 | * rest of the entitlement the device had been allocated will be returned | ||
| 783 | * to the system. | ||
| 784 | */ | ||
| 785 | static void vio_cmo_bus_remove(struct vio_dev *viodev) | ||
| 786 | { | ||
| 787 | struct vio_cmo_dev_entry *dev_ent; | ||
| 788 | unsigned long flags; | ||
| 789 | size_t tmp; | ||
| 790 | |||
| 791 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 792 | if (viodev->cmo.allocated) { | ||
| 793 | dev_err(&viodev->dev, "%s: device had %lu bytes of IO " | ||
| 794 | "allocated after remove operation.\n", | ||
| 795 | __func__, viodev->cmo.allocated); | ||
| 796 | BUG(); | ||
| 797 | } | ||
| 798 | |||
| 799 | /* | ||
| 800 | * Remove the device from the device list being maintained for | ||
| 801 | * CMO enabled devices. | ||
| 802 | */ | ||
| 803 | list_for_each_entry(dev_ent, &vio_cmo.device_list, list) | ||
| 804 | if (viodev == dev_ent->viodev) { | ||
| 805 | list_del(&dev_ent->list); | ||
| 806 | kfree(dev_ent); | ||
| 807 | break; | ||
| 808 | } | ||
| 809 | |||
| 810 | /* | ||
| 811 | * Devices may not require any entitlement and they do not need | ||
| 812 | * to be processed. Otherwise, return the device's entitlement | ||
| 813 | * back to the pools. | ||
| 814 | */ | ||
| 815 | if (viodev->cmo.entitled) { | ||
| 816 | /* | ||
| 817 | * This device has not yet left the OF tree, it's | ||
| 818 | * minimum entitlement remains in vio_cmo.min and | ||
| 819 | * vio_cmo.desired | ||
| 820 | */ | ||
| 821 | vio_cmo.desired -= (viodev->cmo.desired - VIO_CMO_MIN_ENT); | ||
| 822 | |||
| 823 | /* | ||
| 824 | * Save min allocation for device in reserve as long | ||
| 825 | * as it exists in OF tree as determined by later | ||
| 826 | * balance operation | ||
| 827 | */ | ||
| 828 | viodev->cmo.entitled -= VIO_CMO_MIN_ENT; | ||
| 829 | |||
| 830 | /* Replenish spare from freed reserve pool */ | ||
| 831 | if (viodev->cmo.entitled && (vio_cmo.spare < VIO_CMO_MIN_ENT)) { | ||
| 832 | tmp = min(viodev->cmo.entitled, (VIO_CMO_MIN_ENT - | ||
| 833 | vio_cmo.spare)); | ||
| 834 | vio_cmo.spare += tmp; | ||
| 835 | viodev->cmo.entitled -= tmp; | ||
| 836 | } | ||
| 837 | |||
| 838 | /* Remaining reserve goes to excess pool */ | ||
| 839 | vio_cmo.excess.size += viodev->cmo.entitled; | ||
| 840 | vio_cmo.excess.free += viodev->cmo.entitled; | ||
| 841 | vio_cmo.reserve.size -= viodev->cmo.entitled; | ||
| 842 | |||
| 843 | /* | ||
| 844 | * Until the device is removed it will keep a | ||
| 845 | * minimum entitlement; this will guarantee that | ||
| 846 | * a module unload/load will result in a success. | ||
| 847 | */ | ||
| 848 | viodev->cmo.entitled = VIO_CMO_MIN_ENT; | ||
| 849 | viodev->cmo.desired = VIO_CMO_MIN_ENT; | ||
| 850 | atomic_set(&viodev->cmo.allocs_failed, 0); | ||
| 851 | } | ||
| 852 | |||
| 853 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 854 | } | ||
| 855 | |||
| 856 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) | ||
| 857 | { | ||
| 858 | vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported; | ||
| 859 | viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops; | ||
| 860 | } | ||
| 861 | |||
| 862 | /** | ||
| 863 | * vio_cmo_bus_init - CMO entitlement initialization at bus init time | ||
| 864 | * | ||
| 865 | * Set up the reserve and excess entitlement pools based on available | ||
| 866 | * system entitlement and the number of devices in the OF tree that | ||
| 867 | * require entitlement in the reserve pool. | ||
| 868 | */ | ||
| 869 | static void vio_cmo_bus_init(void) | ||
| 870 | { | ||
| 871 | struct hvcall_mpp_data mpp_data; | ||
| 872 | int err; | ||
| 873 | |||
| 874 | memset(&vio_cmo, 0, sizeof(struct vio_cmo)); | ||
| 875 | spin_lock_init(&vio_cmo.lock); | ||
| 876 | INIT_LIST_HEAD(&vio_cmo.device_list); | ||
| 877 | INIT_DELAYED_WORK(&vio_cmo.balance_q, vio_cmo_balance); | ||
| 878 | |||
| 879 | /* Get current system entitlement */ | ||
| 880 | err = h_get_mpp(&mpp_data); | ||
| 881 | |||
| 882 | /* | ||
| 883 | * On failure, continue with entitlement set to 0, will panic() | ||
| 884 | * later when spare is reserved. | ||
| 885 | */ | ||
| 886 | if (err != H_SUCCESS) { | ||
| 887 | printk(KERN_ERR "%s: unable to determine system IO "\ | ||
| 888 | "entitlement. (%d)\n", __func__, err); | ||
| 889 | vio_cmo.entitled = 0; | ||
| 890 | } else { | ||
| 891 | vio_cmo.entitled = mpp_data.entitled_mem; | ||
| 892 | } | ||
| 893 | |||
| 894 | /* Set reservation and check against entitlement */ | ||
| 895 | vio_cmo.spare = VIO_CMO_MIN_ENT; | ||
| 896 | vio_cmo.reserve.size = vio_cmo.spare; | ||
| 897 | vio_cmo.reserve.size += (vio_cmo_num_OF_devs() * | ||
| 898 | VIO_CMO_MIN_ENT); | ||
| 899 | if (vio_cmo.reserve.size > vio_cmo.entitled) { | ||
| 900 | printk(KERN_ERR "%s: insufficient system entitlement\n", | ||
| 901 | __func__); | ||
| 902 | panic("%s: Insufficient system entitlement", __func__); | ||
| 903 | } | ||
| 904 | |||
| 905 | /* Set the remaining accounting variables */ | ||
| 906 | vio_cmo.excess.size = vio_cmo.entitled - vio_cmo.reserve.size; | ||
| 907 | vio_cmo.excess.free = vio_cmo.excess.size; | ||
| 908 | vio_cmo.min = vio_cmo.reserve.size; | ||
| 909 | vio_cmo.desired = vio_cmo.reserve.size; | ||
| 910 | } | ||
| 911 | |||
| 912 | /* sysfs device functions and data structures for CMO */ | ||
| 913 | |||
| 914 | #define viodev_cmo_rd_attr(name) \ | ||
| 915 | static ssize_t viodev_cmo_##name##_show(struct device *dev, \ | ||
| 916 | struct device_attribute *attr, \ | ||
| 917 | char *buf) \ | ||
| 918 | { \ | ||
| 919 | return sprintf(buf, "%lu\n", to_vio_dev(dev)->cmo.name); \ | ||
| 920 | } | ||
| 921 | |||
| 922 | static ssize_t viodev_cmo_allocs_failed_show(struct device *dev, | ||
| 923 | struct device_attribute *attr, char *buf) | ||
| 924 | { | ||
| 925 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 926 | return sprintf(buf, "%d\n", atomic_read(&viodev->cmo.allocs_failed)); | ||
| 927 | } | ||
| 928 | |||
| 929 | static ssize_t viodev_cmo_allocs_failed_reset(struct device *dev, | ||
| 930 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 931 | { | ||
| 932 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 933 | atomic_set(&viodev->cmo.allocs_failed, 0); | ||
| 934 | return count; | ||
| 935 | } | ||
| 936 | |||
| 937 | static ssize_t viodev_cmo_desired_set(struct device *dev, | ||
| 938 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 939 | { | ||
| 940 | struct vio_dev *viodev = to_vio_dev(dev); | ||
| 941 | size_t new_desired; | ||
| 942 | int ret; | ||
| 943 | |||
| 944 | ret = strict_strtoul(buf, 10, &new_desired); | ||
| 945 | if (ret) | ||
| 946 | return ret; | ||
| 947 | |||
| 948 | vio_cmo_set_dev_desired(viodev, new_desired); | ||
| 949 | return count; | ||
| 950 | } | ||
| 951 | |||
| 952 | viodev_cmo_rd_attr(desired); | ||
| 953 | viodev_cmo_rd_attr(entitled); | ||
| 954 | viodev_cmo_rd_attr(allocated); | ||
| 955 | |||
| 956 | static ssize_t name_show(struct device *, struct device_attribute *, char *); | ||
| 957 | static ssize_t devspec_show(struct device *, struct device_attribute *, char *); | ||
| 958 | static struct device_attribute vio_cmo_dev_attrs[] = { | ||
| 959 | __ATTR_RO(name), | ||
| 960 | __ATTR_RO(devspec), | ||
| 961 | __ATTR(cmo_desired, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH, | ||
| 962 | viodev_cmo_desired_show, viodev_cmo_desired_set), | ||
| 963 | __ATTR(cmo_entitled, S_IRUGO, viodev_cmo_entitled_show, NULL), | ||
| 964 | __ATTR(cmo_allocated, S_IRUGO, viodev_cmo_allocated_show, NULL), | ||
| 965 | __ATTR(cmo_allocs_failed, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH, | ||
| 966 | viodev_cmo_allocs_failed_show, viodev_cmo_allocs_failed_reset), | ||
| 967 | __ATTR_NULL | ||
| 968 | }; | ||
| 969 | |||
| 970 | /* sysfs bus functions and data structures for CMO */ | ||
| 971 | |||
| 972 | #define viobus_cmo_rd_attr(name) \ | ||
| 973 | static ssize_t \ | ||
| 974 | viobus_cmo_##name##_show(struct bus_type *bt, char *buf) \ | ||
| 975 | { \ | ||
| 976 | return sprintf(buf, "%lu\n", vio_cmo.name); \ | ||
| 977 | } | ||
| 978 | |||
| 979 | #define viobus_cmo_pool_rd_attr(name, var) \ | ||
| 980 | static ssize_t \ | ||
| 981 | viobus_cmo_##name##_pool_show_##var(struct bus_type *bt, char *buf) \ | ||
| 982 | { \ | ||
| 983 | return sprintf(buf, "%lu\n", vio_cmo.name.var); \ | ||
| 984 | } | ||
| 985 | |||
| 986 | static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf, | ||
| 987 | size_t count) | ||
| 988 | { | ||
| 989 | unsigned long flags; | ||
| 990 | |||
| 991 | spin_lock_irqsave(&vio_cmo.lock, flags); | ||
| 992 | vio_cmo.high = vio_cmo.curr; | ||
| 993 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | ||
| 994 | |||
| 995 | return count; | ||
| 996 | } | ||
| 997 | |||
| 998 | viobus_cmo_rd_attr(entitled); | ||
| 999 | viobus_cmo_pool_rd_attr(reserve, size); | ||
| 1000 | viobus_cmo_pool_rd_attr(excess, size); | ||
| 1001 | viobus_cmo_pool_rd_attr(excess, free); | ||
| 1002 | viobus_cmo_rd_attr(spare); | ||
| 1003 | viobus_cmo_rd_attr(min); | ||
| 1004 | viobus_cmo_rd_attr(desired); | ||
| 1005 | viobus_cmo_rd_attr(curr); | ||
| 1006 | viobus_cmo_rd_attr(high); | ||
| 1007 | |||
| 1008 | static struct bus_attribute vio_cmo_bus_attrs[] = { | ||
| 1009 | __ATTR(cmo_entitled, S_IRUGO, viobus_cmo_entitled_show, NULL), | ||
| 1010 | __ATTR(cmo_reserve_size, S_IRUGO, viobus_cmo_reserve_pool_show_size, NULL), | ||
| 1011 | __ATTR(cmo_excess_size, S_IRUGO, viobus_cmo_excess_pool_show_size, NULL), | ||
| 1012 | __ATTR(cmo_excess_free, S_IRUGO, viobus_cmo_excess_pool_show_free, NULL), | ||
| 1013 | __ATTR(cmo_spare, S_IRUGO, viobus_cmo_spare_show, NULL), | ||
| 1014 | __ATTR(cmo_min, S_IRUGO, viobus_cmo_min_show, NULL), | ||
| 1015 | __ATTR(cmo_desired, S_IRUGO, viobus_cmo_desired_show, NULL), | ||
| 1016 | __ATTR(cmo_curr, S_IRUGO, viobus_cmo_curr_show, NULL), | ||
| 1017 | __ATTR(cmo_high, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH, | ||
| 1018 | viobus_cmo_high_show, viobus_cmo_high_reset), | ||
| 1019 | __ATTR_NULL | ||
| 1020 | }; | ||
| 1021 | |||
| 1022 | static void vio_cmo_sysfs_init(void) | ||
| 1023 | { | ||
| 1024 | vio_bus_type.dev_attrs = vio_cmo_dev_attrs; | ||
| 1025 | vio_bus_type.bus_attrs = vio_cmo_bus_attrs; | ||
| 1026 | } | ||
| 1027 | #else /* CONFIG_PPC_SMLPAR */ | ||
| 1028 | /* Dummy functions for iSeries platform */ | ||
| 1029 | int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; } | ||
| 1030 | void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {} | ||
| 1031 | static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; } | ||
| 1032 | static void vio_cmo_bus_remove(struct vio_dev *viodev) {} | ||
| 1033 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) {} | ||
| 1034 | static void vio_cmo_bus_init() {} | ||
| 1035 | static void vio_cmo_sysfs_init() { } | ||
| 1036 | #endif /* CONFIG_PPC_SMLPAR */ | ||
| 1037 | EXPORT_SYMBOL(vio_cmo_entitlement_update); | ||
| 1038 | EXPORT_SYMBOL(vio_cmo_set_dev_desired); | ||
| 1039 | |||
| 49 | static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) | 1040 | static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) |
| 50 | { | 1041 | { |
| 51 | const unsigned char *dma_window; | 1042 | const unsigned char *dma_window; |
| @@ -114,8 +1105,17 @@ static int vio_bus_probe(struct device *dev) | |||
| 114 | return error; | 1105 | return error; |
| 115 | 1106 | ||
| 116 | id = vio_match_device(viodrv->id_table, viodev); | 1107 | id = vio_match_device(viodrv->id_table, viodev); |
| 117 | if (id) | 1108 | if (id) { |
| 1109 | memset(&viodev->cmo, 0, sizeof(viodev->cmo)); | ||
| 1110 | if (firmware_has_feature(FW_FEATURE_CMO)) { | ||
| 1111 | error = vio_cmo_bus_probe(viodev); | ||
| 1112 | if (error) | ||
| 1113 | return error; | ||
| 1114 | } | ||
| 118 | error = viodrv->probe(viodev, id); | 1115 | error = viodrv->probe(viodev, id); |
| 1116 | if (error) | ||
| 1117 | vio_cmo_bus_remove(viodev); | ||
| 1118 | } | ||
| 119 | 1119 | ||
| 120 | return error; | 1120 | return error; |
| 121 | } | 1121 | } |
| @@ -125,12 +1125,23 @@ static int vio_bus_remove(struct device *dev) | |||
| 125 | { | 1125 | { |
| 126 | struct vio_dev *viodev = to_vio_dev(dev); | 1126 | struct vio_dev *viodev = to_vio_dev(dev); |
| 127 | struct vio_driver *viodrv = to_vio_driver(dev->driver); | 1127 | struct vio_driver *viodrv = to_vio_driver(dev->driver); |
| 1128 | struct device *devptr; | ||
| 1129 | int ret = 1; | ||
| 1130 | |||
| 1131 | /* | ||
| 1132 | * Hold a reference to the device after the remove function is called | ||
| 1133 | * to allow for CMO accounting cleanup for the device. | ||
| 1134 | */ | ||
| 1135 | devptr = get_device(dev); | ||
| 128 | 1136 | ||
| 129 | if (viodrv->remove) | 1137 | if (viodrv->remove) |
| 130 | return viodrv->remove(viodev); | 1138 | ret = viodrv->remove(viodev); |
| 1139 | |||
| 1140 | if (!ret && firmware_has_feature(FW_FEATURE_CMO)) | ||
| 1141 | vio_cmo_bus_remove(viodev); | ||
| 131 | 1142 | ||
| 132 | /* driver can't remove */ | 1143 | put_device(devptr); |
| 133 | return 1; | 1144 | return ret; |
| 134 | } | 1145 | } |
| 135 | 1146 | ||
| 136 | /** | 1147 | /** |
| @@ -215,7 +1226,11 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
| 215 | viodev->unit_address = *unit_address; | 1226 | viodev->unit_address = *unit_address; |
| 216 | } | 1227 | } |
| 217 | viodev->dev.archdata.of_node = of_node_get(of_node); | 1228 | viodev->dev.archdata.of_node = of_node_get(of_node); |
| 218 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; | 1229 | |
| 1230 | if (firmware_has_feature(FW_FEATURE_CMO)) | ||
| 1231 | vio_cmo_set_dma_ops(viodev); | ||
| 1232 | else | ||
| 1233 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; | ||
| 219 | viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev); | 1234 | viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev); |
| 220 | viodev->dev.archdata.numa_node = of_node_to_nid(of_node); | 1235 | viodev->dev.archdata.numa_node = of_node_to_nid(of_node); |
| 221 | 1236 | ||
| @@ -245,6 +1260,9 @@ static int __init vio_bus_init(void) | |||
| 245 | int err; | 1260 | int err; |
| 246 | struct device_node *node_vroot; | 1261 | struct device_node *node_vroot; |
| 247 | 1262 | ||
| 1263 | if (firmware_has_feature(FW_FEATURE_CMO)) | ||
| 1264 | vio_cmo_sysfs_init(); | ||
| 1265 | |||
| 248 | err = bus_register(&vio_bus_type); | 1266 | err = bus_register(&vio_bus_type); |
| 249 | if (err) { | 1267 | if (err) { |
| 250 | printk(KERN_ERR "failed to register VIO bus\n"); | 1268 | printk(KERN_ERR "failed to register VIO bus\n"); |
| @@ -262,6 +1280,9 @@ static int __init vio_bus_init(void) | |||
| 262 | return err; | 1280 | return err; |
| 263 | } | 1281 | } |
| 264 | 1282 | ||
| 1283 | if (firmware_has_feature(FW_FEATURE_CMO)) | ||
| 1284 | vio_cmo_bus_init(); | ||
| 1285 | |||
| 265 | node_vroot = of_find_node_by_name(NULL, "vdevice"); | 1286 | node_vroot = of_find_node_by_name(NULL, "vdevice"); |
| 266 | if (node_vroot) { | 1287 | if (node_vroot) { |
| 267 | struct device_node *of_node; | 1288 | struct device_node *of_node; |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index a914411bced5..4a8ce62fe112 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
| @@ -85,7 +85,7 @@ SECTIONS | |||
| 85 | 85 | ||
| 86 | /* The dummy segment contents for the bug workaround mentioned above | 86 | /* The dummy segment contents for the bug workaround mentioned above |
| 87 | near PHDRS. */ | 87 | near PHDRS. */ |
| 88 | .dummy : { | 88 | .dummy : AT(ADDR(.dummy) - LOAD_OFFSET) { |
| 89 | LONG(0xf177) | 89 | LONG(0xf177) |
| 90 | } :kernel :dummy | 90 | } :kernel :dummy |
| 91 | 91 | ||
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 1707d00331fc..565b7a237c84 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -100,31 +100,6 @@ static int store_updates_sp(struct pt_regs *regs) | |||
| 100 | return 0; | 100 | return 0; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | ||
| 104 | static void do_dabr(struct pt_regs *regs, unsigned long address, | ||
| 105 | unsigned long error_code) | ||
| 106 | { | ||
| 107 | siginfo_t info; | ||
| 108 | |||
| 109 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
| 110 | 11, SIGSEGV) == NOTIFY_STOP) | ||
| 111 | return; | ||
| 112 | |||
| 113 | if (debugger_dabr_match(regs)) | ||
| 114 | return; | ||
| 115 | |||
| 116 | /* Clear the DABR */ | ||
| 117 | set_dabr(0); | ||
| 118 | |||
| 119 | /* Deliver the signal to userspace */ | ||
| 120 | info.si_signo = SIGTRAP; | ||
| 121 | info.si_errno = 0; | ||
| 122 | info.si_code = TRAP_HWBKPT; | ||
| 123 | info.si_addr = (void __user *)address; | ||
| 124 | force_sig_info(SIGTRAP, &info, current); | ||
| 125 | } | ||
| 126 | #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/ | ||
| 127 | |||
| 128 | /* | 103 | /* |
| 129 | * For 600- and 800-family processors, the error_code parameter is DSISR | 104 | * For 600- and 800-family processors, the error_code parameter is DSISR |
| 130 | * for a data fault, SRR1 for an instruction fault. For 400-family processors | 105 | * for a data fault, SRR1 for an instruction fault. For 400-family processors |
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index d664b1bce381..696a5ee4962d 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | config PPC_MPC52xx | 1 | config PPC_MPC52xx |
| 2 | bool "52xx-based boards" | 2 | bool "52xx-based boards" |
| 3 | depends on PPC_MULTIPLATFORM && PPC32 | 3 | depends on PPC_MULTIPLATFORM && PPC32 |
| 4 | select FSL_SOC | ||
| 5 | select PPC_CLOCK | 4 | select PPC_CLOCK |
| 6 | select PPC_PCI_CHOICE | 5 | select PPC_PCI_CHOICE |
| 7 | 6 | ||
| @@ -48,6 +47,7 @@ config PPC_MPC5200_BUGFIX | |||
| 48 | config PPC_MPC5200_GPIO | 47 | config PPC_MPC5200_GPIO |
| 49 | bool "MPC5200 GPIO support" | 48 | bool "MPC5200 GPIO support" |
| 50 | depends on PPC_MPC52xx | 49 | depends on PPC_MPC52xx |
| 51 | select HAVE_GPIO_LIB | 50 | select ARCH_REQUIRE_GPIOLIB |
| 51 | select GENERIC_GPIO | ||
| 52 | help | 52 | help |
| 53 | Enable gpiolib support for mpc5200 based boards | 53 | Enable gpiolib support for mpc5200 based boards |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 208005ca262c..e06420af5fe9 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
| @@ -172,7 +172,7 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte, | |||
| 172 | } | 172 | } |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | static void tce_build_cell(struct iommu_table *tbl, long index, long npages, | 175 | static int tce_build_cell(struct iommu_table *tbl, long index, long npages, |
| 176 | unsigned long uaddr, enum dma_data_direction direction, | 176 | unsigned long uaddr, enum dma_data_direction direction, |
| 177 | struct dma_attrs *attrs) | 177 | struct dma_attrs *attrs) |
| 178 | { | 178 | { |
| @@ -213,6 +213,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages, | |||
| 213 | 213 | ||
| 214 | pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n", | 214 | pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n", |
| 215 | index, npages, direction, base_pte); | 215 | index, npages, direction, base_pte); |
| 216 | return 0; | ||
| 216 | } | 217 | } |
| 217 | 218 | ||
| 218 | static void tce_free_cell(struct iommu_table *tbl, long index, long npages) | 219 | static void tce_free_cell(struct iommu_table *tbl, long index, long npages) |
| @@ -1150,12 +1151,23 @@ static int iommu_fixed_disabled; | |||
| 1150 | 1151 | ||
| 1151 | static int __init setup_iommu_fixed(char *str) | 1152 | static int __init setup_iommu_fixed(char *str) |
| 1152 | { | 1153 | { |
| 1154 | struct device_node *pciep; | ||
| 1155 | |||
| 1153 | if (strcmp(str, "off") == 0) | 1156 | if (strcmp(str, "off") == 0) |
| 1154 | iommu_fixed_disabled = 1; | 1157 | iommu_fixed_disabled = 1; |
| 1155 | 1158 | ||
| 1156 | else if (strcmp(str, "weak") == 0) | 1159 | /* If we can find a pcie-endpoint in the device tree assume that |
| 1160 | * we're on a triblade or a CAB so by default the fixed mapping | ||
| 1161 | * should be set to be weakly ordered; but only if the boot | ||
| 1162 | * option WASN'T set for strong ordering | ||
| 1163 | */ | ||
| 1164 | pciep = of_find_node_by_type(NULL, "pcie-endpoint"); | ||
| 1165 | |||
| 1166 | if (strcmp(str, "weak") == 0 || (pciep && strcmp(str, "strong") != 0)) | ||
| 1157 | iommu_fixed_is_weak = 1; | 1167 | iommu_fixed_is_weak = 1; |
| 1158 | 1168 | ||
| 1169 | of_node_put(pciep); | ||
| 1170 | |||
| 1159 | return 1; | 1171 | return 1; |
| 1160 | } | 1172 | } |
| 1161 | __setup("iommu_fixed=", setup_iommu_fixed); | 1173 | __setup("iommu_fixed=", setup_iommu_fixed); |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 34654743363d..2deeeba7eccf 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
| @@ -312,11 +312,28 @@ static struct spu *aff_ref_location(struct spu_context *ctx, int mem_aff, | |||
| 312 | */ | 312 | */ |
| 313 | node = cpu_to_node(raw_smp_processor_id()); | 313 | node = cpu_to_node(raw_smp_processor_id()); |
| 314 | for (n = 0; n < MAX_NUMNODES; n++, node++) { | 314 | for (n = 0; n < MAX_NUMNODES; n++, node++) { |
| 315 | int available_spus; | ||
| 316 | |||
| 315 | node = (node < MAX_NUMNODES) ? node : 0; | 317 | node = (node < MAX_NUMNODES) ? node : 0; |
| 316 | if (!node_allowed(ctx, node)) | 318 | if (!node_allowed(ctx, node)) |
| 317 | continue; | 319 | continue; |
| 320 | |||
| 321 | available_spus = 0; | ||
| 318 | mutex_lock(&cbe_spu_info[node].list_mutex); | 322 | mutex_lock(&cbe_spu_info[node].list_mutex); |
| 319 | list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { | 323 | list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { |
| 324 | if (spu->ctx && spu->ctx->gang | ||
| 325 | && spu->ctx->aff_offset == 0) | ||
| 326 | available_spus -= | ||
| 327 | (spu->ctx->gang->contexts - 1); | ||
| 328 | else | ||
| 329 | available_spus++; | ||
| 330 | } | ||
| 331 | if (available_spus < ctx->gang->contexts) { | ||
| 332 | mutex_unlock(&cbe_spu_info[node].list_mutex); | ||
| 333 | continue; | ||
| 334 | } | ||
| 335 | |||
| 336 | list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { | ||
| 320 | if ((!mem_aff || spu->has_mem_affinity) && | 337 | if ((!mem_aff || spu->has_mem_affinity) && |
| 321 | sched_spu(spu)) { | 338 | sched_spu(spu)) { |
| 322 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 339 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
| @@ -389,6 +406,9 @@ static int has_affinity(struct spu_context *ctx) | |||
| 389 | if (list_empty(&ctx->aff_list)) | 406 | if (list_empty(&ctx->aff_list)) |
| 390 | return 0; | 407 | return 0; |
| 391 | 408 | ||
| 409 | if (atomic_read(&ctx->gang->aff_sched_count) == 0) | ||
| 410 | ctx->gang->aff_ref_spu = NULL; | ||
| 411 | |||
| 392 | if (!gang->aff_ref_spu) { | 412 | if (!gang->aff_ref_spu) { |
| 393 | if (!(gang->aff_flags & AFF_MERGED)) | 413 | if (!(gang->aff_flags & AFF_MERGED)) |
| 394 | aff_merge_remaining_ctxs(gang); | 414 | aff_merge_remaining_ctxs(gang); |
| @@ -416,14 +436,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
| 416 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) | 436 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) |
| 417 | atomic_dec(&cbe_spu_info[spu->node].reserved_spus); | 437 | atomic_dec(&cbe_spu_info[spu->node].reserved_spus); |
| 418 | 438 | ||
| 419 | if (ctx->gang){ | 439 | if (ctx->gang) |
| 420 | mutex_lock(&ctx->gang->aff_mutex); | 440 | atomic_dec_if_positive(&ctx->gang->aff_sched_count); |
| 421 | if (has_affinity(ctx)) { | ||
| 422 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) | ||
| 423 | ctx->gang->aff_ref_spu = NULL; | ||
| 424 | } | ||
| 425 | mutex_unlock(&ctx->gang->aff_mutex); | ||
| 426 | } | ||
| 427 | 441 | ||
| 428 | spu_switch_notify(spu, NULL); | 442 | spu_switch_notify(spu, NULL); |
| 429 | spu_unmap_mappings(ctx); | 443 | spu_unmap_mappings(ctx); |
| @@ -562,10 +576,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
| 562 | goto found; | 576 | goto found; |
| 563 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 577 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
| 564 | 578 | ||
| 565 | mutex_lock(&ctx->gang->aff_mutex); | 579 | atomic_dec(&ctx->gang->aff_sched_count); |
| 566 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) | ||
| 567 | ctx->gang->aff_ref_spu = NULL; | ||
| 568 | mutex_unlock(&ctx->gang->aff_mutex); | ||
| 569 | goto not_found; | 580 | goto not_found; |
| 570 | } | 581 | } |
| 571 | mutex_unlock(&ctx->gang->aff_mutex); | 582 | mutex_unlock(&ctx->gang->aff_mutex); |
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c index 8c0e95766a62..92d20e993ede 100644 --- a/arch/powerpc/platforms/cell/spufs/sputrace.c +++ b/arch/powerpc/platforms/cell/spufs/sputrace.c | |||
| @@ -196,8 +196,7 @@ static int __init sputrace_init(void) | |||
| 196 | struct proc_dir_entry *entry; | 196 | struct proc_dir_entry *entry; |
| 197 | int i, error = -ENOMEM; | 197 | int i, error = -ENOMEM; |
| 198 | 198 | ||
| 199 | sputrace_log = kcalloc(sizeof(struct sputrace), | 199 | sputrace_log = kcalloc(bufsize, sizeof(struct sputrace), GFP_KERNEL); |
| 200 | bufsize, GFP_KERNEL); | ||
| 201 | if (!sputrace_log) | 200 | if (!sputrace_log) |
| 202 | goto out; | 201 | goto out; |
| 203 | 202 | ||
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index bc818e4e2033..bb464d1211b2 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | #include <asm/iseries/hv_call_event.h> | 41 | #include <asm/iseries/hv_call_event.h> |
| 42 | #include <asm/iseries/iommu.h> | 42 | #include <asm/iseries/iommu.h> |
| 43 | 43 | ||
| 44 | static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, | 44 | static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages, |
| 45 | unsigned long uaddr, enum dma_data_direction direction, | 45 | unsigned long uaddr, enum dma_data_direction direction, |
| 46 | struct dma_attrs *attrs) | 46 | struct dma_attrs *attrs) |
| 47 | { | 47 | { |
| @@ -71,6 +71,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, | |||
| 71 | index++; | 71 | index++; |
| 72 | uaddr += TCE_PAGE_SIZE; | 72 | uaddr += TCE_PAGE_SIZE; |
| 73 | } | 73 | } |
| 74 | return 0; | ||
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) | 77 | static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) |
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 70541b7a5013..a0ff03a3d8da 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c | |||
| @@ -83,7 +83,7 @@ static u32 *iob_l2_base; | |||
| 83 | static struct iommu_table iommu_table_iobmap; | 83 | static struct iommu_table iommu_table_iobmap; |
| 84 | static int iommu_table_iobmap_inited; | 84 | static int iommu_table_iobmap_inited; |
| 85 | 85 | ||
| 86 | static void iobmap_build(struct iommu_table *tbl, long index, | 86 | static int iobmap_build(struct iommu_table *tbl, long index, |
| 87 | long npages, unsigned long uaddr, | 87 | long npages, unsigned long uaddr, |
| 88 | enum dma_data_direction direction, | 88 | enum dma_data_direction direction, |
| 89 | struct dma_attrs *attrs) | 89 | struct dma_attrs *attrs) |
| @@ -108,6 +108,7 @@ static void iobmap_build(struct iommu_table *tbl, long index, | |||
| 108 | uaddr += IOBMAP_PAGE_SIZE; | 108 | uaddr += IOBMAP_PAGE_SIZE; |
| 109 | bus_addr += IOBMAP_PAGE_SIZE; | 109 | bus_addr += IOBMAP_PAGE_SIZE; |
| 110 | } | 110 | } |
| 111 | return 0; | ||
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | 114 | ||
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 757c0296e0b8..97619fd51e39 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
| @@ -40,3 +40,26 @@ config PPC_PSERIES_DEBUG | |||
| 40 | depends on PPC_PSERIES && PPC_EARLY_DEBUG | 40 | depends on PPC_PSERIES && PPC_EARLY_DEBUG |
| 41 | bool "Enable extra debug logging in platforms/pseries" | 41 | bool "Enable extra debug logging in platforms/pseries" |
| 42 | default y | 42 | default y |
| 43 | |||
| 44 | config PPC_SMLPAR | ||
| 45 | bool "Support for shared-memory logical partitions" | ||
| 46 | depends on PPC_PSERIES | ||
| 47 | select LPARCFG | ||
| 48 | default n | ||
| 49 | help | ||
| 50 | Select this option to enable shared memory partition support. | ||
| 51 | With this option a system running in an LPAR can be given more | ||
| 52 | memory than physically available and will allow firmware to | ||
| 53 | balance memory across many LPARs. | ||
| 54 | |||
| 55 | config CMM | ||
| 56 | tristate "Collaborative memory management" | ||
| 57 | depends on PPC_SMLPAR | ||
| 58 | default y | ||
| 59 | help | ||
| 60 | Select this option, if you want to enable the kernel interface | ||
| 61 | to reduce the memory size of the system. This is accomplished | ||
| 62 | by allocating pages of memory and put them "on hold". This only | ||
| 63 | makes sense for a system running in an LPAR where the unused pages | ||
| 64 | will be reused for other LPARs. The interface allows firmware to | ||
| 65 | balance memory across many LPARs. | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 554c6e42ef2a..dfe574af2dc0 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
| @@ -24,3 +24,4 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | |||
| 24 | obj-$(CONFIG_HVCS) += hvcserver.o | 24 | obj-$(CONFIG_HVCS) += hvcserver.o |
| 25 | obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o | 25 | obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o |
| 26 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o | 26 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o |
| 27 | obj-$(CONFIG_CMM) += cmm.o | ||
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c new file mode 100644 index 000000000000..c6b3be03168b --- /dev/null +++ b/arch/powerpc/platforms/pseries/cmm.c | |||
| @@ -0,0 +1,468 @@ | |||
| 1 | /* | ||
| 2 | * Collaborative memory management interface. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 IBM Corporation | ||
| 5 | * Author(s): Brian King (brking@linux.vnet.ibm.com), | ||
| 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/ctype.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/errno.h> | ||
| 26 | #include <linux/fs.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/kthread.h> | ||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/oom.h> | ||
| 31 | #include <linux/sched.h> | ||
| 32 | #include <linux/stringify.h> | ||
| 33 | #include <linux/swap.h> | ||
| 34 | #include <linux/sysdev.h> | ||
| 35 | #include <asm/firmware.h> | ||
| 36 | #include <asm/hvcall.h> | ||
| 37 | #include <asm/mmu.h> | ||
| 38 | #include <asm/pgalloc.h> | ||
| 39 | #include <asm/uaccess.h> | ||
| 40 | |||
| 41 | #include "plpar_wrappers.h" | ||
| 42 | |||
| 43 | #define CMM_DRIVER_VERSION "1.0.0" | ||
| 44 | #define CMM_DEFAULT_DELAY 1 | ||
| 45 | #define CMM_DEBUG 0 | ||
| 46 | #define CMM_DISABLE 0 | ||
| 47 | #define CMM_OOM_KB 1024 | ||
| 48 | #define CMM_MIN_MEM_MB 256 | ||
| 49 | #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10)) | ||
| 50 | #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) | ||
| 51 | |||
| 52 | static unsigned int delay = CMM_DEFAULT_DELAY; | ||
| 53 | static unsigned int oom_kb = CMM_OOM_KB; | ||
| 54 | static unsigned int cmm_debug = CMM_DEBUG; | ||
| 55 | static unsigned int cmm_disabled = CMM_DISABLE; | ||
| 56 | static unsigned long min_mem_mb = CMM_MIN_MEM_MB; | ||
| 57 | static struct sys_device cmm_sysdev; | ||
| 58 | |||
| 59 | MODULE_AUTHOR("Brian King <brking@linux.vnet.ibm.com>"); | ||
| 60 | MODULE_DESCRIPTION("IBM System p Collaborative Memory Manager"); | ||
| 61 | MODULE_LICENSE("GPL"); | ||
| 62 | MODULE_VERSION(CMM_DRIVER_VERSION); | ||
| 63 | |||
| 64 | module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR); | ||
| 65 | MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " | ||
| 66 | "[Default=" __stringify(CMM_DEFAULT_DELAY) "]"); | ||
| 67 | module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); | ||
| 68 | MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " | ||
| 69 | "[Default=" __stringify(CMM_OOM_KB) "]"); | ||
| 70 | module_param_named(min_mem_mb, min_mem_mb, ulong, S_IRUGO | S_IWUSR); | ||
| 71 | MODULE_PARM_DESC(min_mem_mb, "Minimum amount of memory (in MB) to not balloon. " | ||
| 72 | "[Default=" __stringify(CMM_MIN_MEM_MB) "]"); | ||
| 73 | module_param_named(debug, cmm_debug, uint, S_IRUGO | S_IWUSR); | ||
| 74 | MODULE_PARM_DESC(debug, "Enable module debugging logging. Set to 1 to enable. " | ||
| 75 | "[Default=" __stringify(CMM_DEBUG) "]"); | ||
| 76 | |||
| 77 | #define CMM_NR_PAGES ((PAGE_SIZE - sizeof(void *) - sizeof(unsigned long)) / sizeof(unsigned long)) | ||
| 78 | |||
| 79 | #define cmm_dbg(...) if (cmm_debug) { printk(KERN_INFO "cmm: "__VA_ARGS__); } | ||
| 80 | |||
| 81 | struct cmm_page_array { | ||
| 82 | struct cmm_page_array *next; | ||
| 83 | unsigned long index; | ||
| 84 | unsigned long page[CMM_NR_PAGES]; | ||
| 85 | }; | ||
| 86 | |||
| 87 | static unsigned long loaned_pages; | ||
| 88 | static unsigned long loaned_pages_target; | ||
| 89 | static unsigned long oom_freed_pages; | ||
| 90 | |||
| 91 | static struct cmm_page_array *cmm_page_list; | ||
| 92 | static DEFINE_SPINLOCK(cmm_lock); | ||
| 93 | |||
| 94 | static struct task_struct *cmm_thread_ptr; | ||
| 95 | |||
| 96 | /** | ||
| 97 | * cmm_alloc_pages - Allocate pages and mark them as loaned | ||
| 98 | * @nr: number of pages to allocate | ||
| 99 | * | ||
| 100 | * Return value: | ||
| 101 | * number of pages requested to be allocated which were not | ||
| 102 | **/ | ||
| 103 | static long cmm_alloc_pages(long nr) | ||
| 104 | { | ||
| 105 | struct cmm_page_array *pa, *npa; | ||
| 106 | unsigned long addr; | ||
| 107 | long rc; | ||
| 108 | |||
| 109 | cmm_dbg("Begin request for %ld pages\n", nr); | ||
| 110 | |||
| 111 | while (nr) { | ||
| 112 | addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | | ||
| 113 | __GFP_NORETRY | __GFP_NOMEMALLOC); | ||
| 114 | if (!addr) | ||
| 115 | break; | ||
| 116 | spin_lock(&cmm_lock); | ||
| 117 | pa = cmm_page_list; | ||
| 118 | if (!pa || pa->index >= CMM_NR_PAGES) { | ||
| 119 | /* Need a new page for the page list. */ | ||
| 120 | spin_unlock(&cmm_lock); | ||
| 121 | npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN | | ||
| 122 | __GFP_NORETRY | __GFP_NOMEMALLOC); | ||
| 123 | if (!npa) { | ||
| 124 | pr_info("%s: Can not allocate new page list\n", __FUNCTION__); | ||
| 125 | free_page(addr); | ||
| 126 | break; | ||
| 127 | } | ||
| 128 | spin_lock(&cmm_lock); | ||
| 129 | pa = cmm_page_list; | ||
| 130 | |||
| 131 | if (!pa || pa->index >= CMM_NR_PAGES) { | ||
| 132 | npa->next = pa; | ||
| 133 | npa->index = 0; | ||
| 134 | pa = npa; | ||
| 135 | cmm_page_list = pa; | ||
| 136 | } else | ||
| 137 | free_page((unsigned long) npa); | ||
| 138 | } | ||
| 139 | |||
| 140 | if ((rc = plpar_page_set_loaned(__pa(addr)))) { | ||
| 141 | pr_err("%s: Can not set page to loaned. rc=%ld\n", __FUNCTION__, rc); | ||
| 142 | spin_unlock(&cmm_lock); | ||
| 143 | free_page(addr); | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | |||
| 147 | pa->page[pa->index++] = addr; | ||
| 148 | loaned_pages++; | ||
| 149 | totalram_pages--; | ||
| 150 | spin_unlock(&cmm_lock); | ||
| 151 | nr--; | ||
| 152 | } | ||
| 153 | |||
| 154 | cmm_dbg("End request with %ld pages unfulfilled\n", nr); | ||
| 155 | return nr; | ||
| 156 | } | ||
| 157 | |||
| 158 | /** | ||
| 159 | * cmm_free_pages - Free pages and mark them as active | ||
| 160 | * @nr: number of pages to free | ||
| 161 | * | ||
| 162 | * Return value: | ||
| 163 | * number of pages requested to be freed which were not | ||
| 164 | **/ | ||
| 165 | static long cmm_free_pages(long nr) | ||
| 166 | { | ||
| 167 | struct cmm_page_array *pa; | ||
| 168 | unsigned long addr; | ||
| 169 | |||
| 170 | cmm_dbg("Begin free of %ld pages.\n", nr); | ||
| 171 | spin_lock(&cmm_lock); | ||
| 172 | pa = cmm_page_list; | ||
| 173 | while (nr) { | ||
| 174 | if (!pa || pa->index <= 0) | ||
| 175 | break; | ||
| 176 | addr = pa->page[--pa->index]; | ||
| 177 | |||
| 178 | if (pa->index == 0) { | ||
| 179 | pa = pa->next; | ||
| 180 | free_page((unsigned long) cmm_page_list); | ||
| 181 | cmm_page_list = pa; | ||
| 182 | } | ||
| 183 | |||
| 184 | plpar_page_set_active(__pa(addr)); | ||
| 185 | free_page(addr); | ||
| 186 | loaned_pages--; | ||
| 187 | nr--; | ||
| 188 | totalram_pages++; | ||
| 189 | } | ||
| 190 | spin_unlock(&cmm_lock); | ||
| 191 | cmm_dbg("End request with %ld pages unfulfilled\n", nr); | ||
| 192 | return nr; | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * cmm_oom_notify - OOM notifier | ||
| 197 | * @self: notifier block struct | ||
| 198 | * @dummy: not used | ||
| 199 | * @parm: returned - number of pages freed | ||
| 200 | * | ||
| 201 | * Return value: | ||
| 202 | * NOTIFY_OK | ||
| 203 | **/ | ||
| 204 | static int cmm_oom_notify(struct notifier_block *self, | ||
| 205 | unsigned long dummy, void *parm) | ||
| 206 | { | ||
| 207 | unsigned long *freed = parm; | ||
| 208 | long nr = KB2PAGES(oom_kb); | ||
| 209 | |||
| 210 | cmm_dbg("OOM processing started\n"); | ||
| 211 | nr = cmm_free_pages(nr); | ||
| 212 | loaned_pages_target = loaned_pages; | ||
| 213 | *freed += KB2PAGES(oom_kb) - nr; | ||
| 214 | oom_freed_pages += KB2PAGES(oom_kb) - nr; | ||
| 215 | cmm_dbg("OOM processing complete\n"); | ||
| 216 | return NOTIFY_OK; | ||
| 217 | } | ||
| 218 | |||
| 219 | /** | ||
| 220 | * cmm_get_mpp - Read memory performance parameters | ||
| 221 | * | ||
| 222 | * Makes hcall to query the current page loan request from the hypervisor. | ||
| 223 | * | ||
| 224 | * Return value: | ||
| 225 | * nothing | ||
| 226 | **/ | ||
| 227 | static void cmm_get_mpp(void) | ||
| 228 | { | ||
| 229 | int rc; | ||
| 230 | struct hvcall_mpp_data mpp_data; | ||
| 231 | unsigned long active_pages_target; | ||
| 232 | signed long page_loan_request; | ||
| 233 | |||
| 234 | rc = h_get_mpp(&mpp_data); | ||
| 235 | |||
| 236 | if (rc != H_SUCCESS) | ||
| 237 | return; | ||
| 238 | |||
| 239 | page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE); | ||
| 240 | loaned_pages_target = page_loan_request + loaned_pages; | ||
| 241 | if (loaned_pages_target > oom_freed_pages) | ||
| 242 | loaned_pages_target -= oom_freed_pages; | ||
| 243 | else | ||
| 244 | loaned_pages_target = 0; | ||
| 245 | |||
| 246 | active_pages_target = totalram_pages + loaned_pages - loaned_pages_target; | ||
| 247 | |||
| 248 | if ((min_mem_mb * 1024 * 1024) > (active_pages_target * PAGE_SIZE)) | ||
| 249 | loaned_pages_target = totalram_pages + loaned_pages - | ||
| 250 | ((min_mem_mb * 1024 * 1024) / PAGE_SIZE); | ||
| 251 | |||
| 252 | cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n", | ||
| 253 | page_loan_request, loaned_pages, loaned_pages_target, | ||
| 254 | oom_freed_pages, totalram_pages); | ||
| 255 | } | ||
| 256 | |||
| 257 | static struct notifier_block cmm_oom_nb = { | ||
| 258 | .notifier_call = cmm_oom_notify | ||
| 259 | }; | ||
| 260 | |||
| 261 | /** | ||
| 262 | * cmm_thread - CMM task thread | ||
| 263 | * @dummy: not used | ||
| 264 | * | ||
| 265 | * Return value: | ||
| 266 | * 0 | ||
| 267 | **/ | ||
| 268 | static int cmm_thread(void *dummy) | ||
| 269 | { | ||
| 270 | unsigned long timeleft; | ||
| 271 | |||
| 272 | while (1) { | ||
| 273 | timeleft = msleep_interruptible(delay * 1000); | ||
| 274 | |||
| 275 | if (kthread_should_stop() || timeleft) { | ||
| 276 | loaned_pages_target = loaned_pages; | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | |||
| 280 | cmm_get_mpp(); | ||
| 281 | |||
| 282 | if (loaned_pages_target > loaned_pages) { | ||
| 283 | if (cmm_alloc_pages(loaned_pages_target - loaned_pages)) | ||
| 284 | loaned_pages_target = loaned_pages; | ||
| 285 | } else if (loaned_pages_target < loaned_pages) | ||
| 286 | cmm_free_pages(loaned_pages - loaned_pages_target); | ||
| 287 | } | ||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | #define CMM_SHOW(name, format, args...) \ | ||
| 292 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | ||
| 293 | { \ | ||
| 294 | return sprintf(buf, format, ##args); \ | ||
| 295 | } \ | ||
| 296 | static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL) | ||
| 297 | |||
| 298 | CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(loaned_pages)); | ||
| 299 | CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target)); | ||
| 300 | |||
| 301 | static ssize_t show_oom_pages(struct sys_device *dev, char *buf) | ||
| 302 | { | ||
| 303 | return sprintf(buf, "%lu\n", PAGES2KB(oom_freed_pages)); | ||
| 304 | } | ||
| 305 | |||
| 306 | static ssize_t store_oom_pages(struct sys_device *dev, | ||
| 307 | const char *buf, size_t count) | ||
| 308 | { | ||
| 309 | unsigned long val = simple_strtoul (buf, NULL, 10); | ||
| 310 | |||
| 311 | if (!capable(CAP_SYS_ADMIN)) | ||
| 312 | return -EPERM; | ||
| 313 | if (val != 0) | ||
| 314 | return -EBADMSG; | ||
| 315 | |||
| 316 | oom_freed_pages = 0; | ||
| 317 | return count; | ||
| 318 | } | ||
| 319 | |||
| 320 | static SYSDEV_ATTR(oom_freed_kb, S_IWUSR| S_IRUGO, | ||
| 321 | show_oom_pages, store_oom_pages); | ||
| 322 | |||
| 323 | static struct sysdev_attribute *cmm_attrs[] = { | ||
| 324 | &attr_loaned_kb, | ||
| 325 | &attr_loaned_target_kb, | ||
| 326 | &attr_oom_freed_kb, | ||
| 327 | }; | ||
| 328 | |||
| 329 | static struct sysdev_class cmm_sysdev_class = { | ||
| 330 | .name = "cmm", | ||
| 331 | }; | ||
| 332 | |||
| 333 | /** | ||
| 334 | * cmm_sysfs_register - Register with sysfs | ||
| 335 | * | ||
| 336 | * Return value: | ||
| 337 | * 0 on success / other on failure | ||
| 338 | **/ | ||
| 339 | static int cmm_sysfs_register(struct sys_device *sysdev) | ||
| 340 | { | ||
| 341 | int i, rc; | ||
| 342 | |||
| 343 | if ((rc = sysdev_class_register(&cmm_sysdev_class))) | ||
| 344 | return rc; | ||
| 345 | |||
| 346 | sysdev->id = 0; | ||
| 347 | sysdev->cls = &cmm_sysdev_class; | ||
| 348 | |||
| 349 | if ((rc = sysdev_register(sysdev))) | ||
| 350 | goto class_unregister; | ||
| 351 | |||
| 352 | for (i = 0; i < ARRAY_SIZE(cmm_attrs); i++) { | ||
| 353 | if ((rc = sysdev_create_file(sysdev, cmm_attrs[i]))) | ||
| 354 | goto fail; | ||
| 355 | } | ||
| 356 | |||
| 357 | return 0; | ||
| 358 | |||
| 359 | fail: | ||
| 360 | while (--i >= 0) | ||
| 361 | sysdev_remove_file(sysdev, cmm_attrs[i]); | ||
| 362 | sysdev_unregister(sysdev); | ||
| 363 | class_unregister: | ||
| 364 | sysdev_class_unregister(&cmm_sysdev_class); | ||
| 365 | return rc; | ||
| 366 | } | ||
| 367 | |||
| 368 | /** | ||
| 369 | * cmm_unregister_sysfs - Unregister from sysfs | ||
| 370 | * | ||
| 371 | **/ | ||
| 372 | static void cmm_unregister_sysfs(struct sys_device *sysdev) | ||
| 373 | { | ||
| 374 | int i; | ||
| 375 | |||
| 376 | for (i = 0; i < ARRAY_SIZE(cmm_attrs); i++) | ||
| 377 | sysdev_remove_file(sysdev, cmm_attrs[i]); | ||
| 378 | sysdev_unregister(sysdev); | ||
| 379 | sysdev_class_unregister(&cmm_sysdev_class); | ||
| 380 | } | ||
| 381 | |||
| 382 | /** | ||
| 383 | * cmm_init - Module initialization | ||
| 384 | * | ||
| 385 | * Return value: | ||
| 386 | * 0 on success / other on failure | ||
| 387 | **/ | ||
| 388 | static int cmm_init(void) | ||
| 389 | { | ||
| 390 | int rc = -ENOMEM; | ||
| 391 | |||
| 392 | if (!firmware_has_feature(FW_FEATURE_CMO)) | ||
| 393 | return -EOPNOTSUPP; | ||
| 394 | |||
| 395 | if ((rc = register_oom_notifier(&cmm_oom_nb)) < 0) | ||
| 396 | return rc; | ||
| 397 | |||
| 398 | if ((rc = cmm_sysfs_register(&cmm_sysdev))) | ||
| 399 | goto out_oom_notifier; | ||
| 400 | |||
| 401 | if (cmm_disabled) | ||
| 402 | return rc; | ||
| 403 | |||
| 404 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); | ||
| 405 | if (IS_ERR(cmm_thread_ptr)) { | ||
| 406 | rc = PTR_ERR(cmm_thread_ptr); | ||
| 407 | goto out_unregister_sysfs; | ||
| 408 | } | ||
| 409 | |||
| 410 | return rc; | ||
| 411 | |||
| 412 | out_unregister_sysfs: | ||
| 413 | cmm_unregister_sysfs(&cmm_sysdev); | ||
| 414 | out_oom_notifier: | ||
| 415 | unregister_oom_notifier(&cmm_oom_nb); | ||
| 416 | return rc; | ||
| 417 | } | ||
| 418 | |||
| 419 | /** | ||
| 420 | * cmm_exit - Module exit | ||
| 421 | * | ||
| 422 | * Return value: | ||
| 423 | * nothing | ||
| 424 | **/ | ||
| 425 | static void cmm_exit(void) | ||
| 426 | { | ||
| 427 | if (cmm_thread_ptr) | ||
| 428 | kthread_stop(cmm_thread_ptr); | ||
| 429 | unregister_oom_notifier(&cmm_oom_nb); | ||
| 430 | cmm_free_pages(loaned_pages); | ||
| 431 | cmm_unregister_sysfs(&cmm_sysdev); | ||
| 432 | } | ||
| 433 | |||
| 434 | /** | ||
| 435 | * cmm_set_disable - Disable/Enable CMM | ||
| 436 | * | ||
| 437 | * Return value: | ||
| 438 | * 0 on success / other on failure | ||
| 439 | **/ | ||
| 440 | static int cmm_set_disable(const char *val, struct kernel_param *kp) | ||
| 441 | { | ||
| 442 | int disable = simple_strtoul(val, NULL, 10); | ||
| 443 | |||
| 444 | if (disable != 0 && disable != 1) | ||
| 445 | return -EINVAL; | ||
| 446 | |||
| 447 | if (disable && !cmm_disabled) { | ||
| 448 | if (cmm_thread_ptr) | ||
| 449 | kthread_stop(cmm_thread_ptr); | ||
| 450 | cmm_thread_ptr = NULL; | ||
| 451 | cmm_free_pages(loaned_pages); | ||
| 452 | } else if (!disable && cmm_disabled) { | ||
| 453 | cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); | ||
| 454 | if (IS_ERR(cmm_thread_ptr)) | ||
| 455 | return PTR_ERR(cmm_thread_ptr); | ||
| 456 | } | ||
| 457 | |||
| 458 | cmm_disabled = disable; | ||
| 459 | return 0; | ||
| 460 | } | ||
| 461 | |||
| 462 | module_param_call(disable, cmm_set_disable, param_get_uint, | ||
| 463 | &cmm_disabled, S_IRUGO | S_IWUSR); | ||
| 464 | MODULE_PARM_DESC(disable, "Disable CMM. Set to 1 to disable. " | ||
| 465 | "[Default=" __stringify(CMM_DISABLE) "]"); | ||
| 466 | |||
| 467 | module_init(cmm_init); | ||
| 468 | module_exit(cmm_exit); | ||
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 5377dd4b849a..a8c446697f9e 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
| @@ -48,7 +48,7 @@ | |||
| 48 | #include "plpar_wrappers.h" | 48 | #include "plpar_wrappers.h" |
| 49 | 49 | ||
| 50 | 50 | ||
| 51 | static void tce_build_pSeries(struct iommu_table *tbl, long index, | 51 | static int tce_build_pSeries(struct iommu_table *tbl, long index, |
| 52 | long npages, unsigned long uaddr, | 52 | long npages, unsigned long uaddr, |
| 53 | enum dma_data_direction direction, | 53 | enum dma_data_direction direction, |
| 54 | struct dma_attrs *attrs) | 54 | struct dma_attrs *attrs) |
| @@ -72,6 +72,7 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index, | |||
| 72 | uaddr += TCE_PAGE_SIZE; | 72 | uaddr += TCE_PAGE_SIZE; |
| 73 | tcep++; | 73 | tcep++; |
| 74 | } | 74 | } |
| 75 | return 0; | ||
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | 78 | ||
| @@ -94,14 +95,19 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) | |||
| 94 | return *tcep; | 95 | return *tcep; |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | 98 | static void tce_free_pSeriesLP(struct iommu_table*, long, long); |
| 99 | static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long); | ||
| 100 | |||
| 101 | static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | ||
| 98 | long npages, unsigned long uaddr, | 102 | long npages, unsigned long uaddr, |
| 99 | enum dma_data_direction direction, | 103 | enum dma_data_direction direction, |
| 100 | struct dma_attrs *attrs) | 104 | struct dma_attrs *attrs) |
| 101 | { | 105 | { |
| 102 | u64 rc; | 106 | u64 rc = 0; |
| 103 | u64 proto_tce, tce; | 107 | u64 proto_tce, tce; |
| 104 | u64 rpn; | 108 | u64 rpn; |
| 109 | int ret = 0; | ||
| 110 | long tcenum_start = tcenum, npages_start = npages; | ||
| 105 | 111 | ||
| 106 | rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; | 112 | rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; |
| 107 | proto_tce = TCE_PCI_READ; | 113 | proto_tce = TCE_PCI_READ; |
| @@ -112,6 +118,13 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
| 112 | tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; | 118 | tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; |
| 113 | rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); | 119 | rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); |
| 114 | 120 | ||
| 121 | if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { | ||
| 122 | ret = (int)rc; | ||
| 123 | tce_free_pSeriesLP(tbl, tcenum_start, | ||
| 124 | (npages_start - (npages + 1))); | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | |||
| 115 | if (rc && printk_ratelimit()) { | 128 | if (rc && printk_ratelimit()) { |
| 116 | printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); | 129 | printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); |
| 117 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); | 130 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); |
| @@ -123,25 +136,27 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
| 123 | tcenum++; | 136 | tcenum++; |
| 124 | rpn++; | 137 | rpn++; |
| 125 | } | 138 | } |
| 139 | return ret; | ||
| 126 | } | 140 | } |
| 127 | 141 | ||
| 128 | static DEFINE_PER_CPU(u64 *, tce_page) = NULL; | 142 | static DEFINE_PER_CPU(u64 *, tce_page) = NULL; |
| 129 | 143 | ||
| 130 | static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | 144 | static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, |
| 131 | long npages, unsigned long uaddr, | 145 | long npages, unsigned long uaddr, |
| 132 | enum dma_data_direction direction, | 146 | enum dma_data_direction direction, |
| 133 | struct dma_attrs *attrs) | 147 | struct dma_attrs *attrs) |
| 134 | { | 148 | { |
| 135 | u64 rc; | 149 | u64 rc = 0; |
| 136 | u64 proto_tce; | 150 | u64 proto_tce; |
| 137 | u64 *tcep; | 151 | u64 *tcep; |
| 138 | u64 rpn; | 152 | u64 rpn; |
| 139 | long l, limit; | 153 | long l, limit; |
| 154 | long tcenum_start = tcenum, npages_start = npages; | ||
| 155 | int ret = 0; | ||
| 140 | 156 | ||
| 141 | if (npages == 1) { | 157 | if (npages == 1) { |
| 142 | tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, | 158 | return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, |
| 143 | direction, attrs); | 159 | direction, attrs); |
| 144 | return; | ||
| 145 | } | 160 | } |
| 146 | 161 | ||
| 147 | tcep = __get_cpu_var(tce_page); | 162 | tcep = __get_cpu_var(tce_page); |
| @@ -153,9 +168,8 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
| 153 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); | 168 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); |
| 154 | /* If allocation fails, fall back to the loop implementation */ | 169 | /* If allocation fails, fall back to the loop implementation */ |
| 155 | if (!tcep) { | 170 | if (!tcep) { |
| 156 | tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, | 171 | return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, |
| 157 | direction, attrs); | 172 | direction, attrs); |
| 158 | return; | ||
| 159 | } | 173 | } |
| 160 | __get_cpu_var(tce_page) = tcep; | 174 | __get_cpu_var(tce_page) = tcep; |
| 161 | } | 175 | } |
| @@ -187,6 +201,13 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
| 187 | tcenum += limit; | 201 | tcenum += limit; |
| 188 | } while (npages > 0 && !rc); | 202 | } while (npages > 0 && !rc); |
| 189 | 203 | ||
| 204 | if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { | ||
| 205 | ret = (int)rc; | ||
| 206 | tce_freemulti_pSeriesLP(tbl, tcenum_start, | ||
| 207 | (npages_start - (npages + limit))); | ||
| 208 | return ret; | ||
| 209 | } | ||
| 210 | |||
| 190 | if (rc && printk_ratelimit()) { | 211 | if (rc && printk_ratelimit()) { |
| 191 | printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); | 212 | printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); |
| 192 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); | 213 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); |
| @@ -194,6 +215,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
| 194 | printk("\ttce[0] val = 0x%lx\n", tcep[0]); | 215 | printk("\ttce[0] val = 0x%lx\n", tcep[0]); |
| 195 | show_stack(current, (unsigned long *)__get_SP()); | 216 | show_stack(current, (unsigned long *)__get_SP()); |
| 196 | } | 217 | } |
| 218 | return ret; | ||
| 197 | } | 219 | } |
| 198 | 220 | ||
| 199 | static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) | 221 | static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) |
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index d8680b589dc9..a437267c6bf8 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h | |||
| @@ -42,6 +42,16 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa) | |||
| 42 | return vpa_call(0x3, cpu, vpa); | 42 | return vpa_call(0x3, cpu, vpa); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static inline long plpar_page_set_loaned(unsigned long vpa) | ||
| 46 | { | ||
| 47 | return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa, 0); | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline long plpar_page_set_active(unsigned long vpa) | ||
| 51 | { | ||
| 52 | return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa, 0); | ||
| 53 | } | ||
| 54 | |||
| 45 | extern void vpa_init(int cpu); | 55 | extern void vpa_init(int cpu); |
| 46 | 56 | ||
| 47 | static inline long plpar_pte_enter(unsigned long flags, | 57 | static inline long plpar_pte_enter(unsigned long flags, |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 90beb444e1dd..063a0d2fba30 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
| @@ -314,6 +314,76 @@ static int pseries_set_xdabr(unsigned long dabr) | |||
| 314 | H_DABRX_KERNEL | H_DABRX_USER); | 314 | H_DABRX_KERNEL | H_DABRX_USER); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | #define CMO_CHARACTERISTICS_TOKEN 44 | ||
| 318 | #define CMO_MAXLENGTH 1026 | ||
| 319 | |||
| 320 | /** | ||
| 321 | * fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions, | ||
| 322 | * handle that here. (Stolen from parse_system_parameter_string) | ||
| 323 | */ | ||
| 324 | void pSeries_cmo_feature_init(void) | ||
| 325 | { | ||
| 326 | char *ptr, *key, *value, *end; | ||
| 327 | int call_status; | ||
| 328 | int PrPSP = -1; | ||
| 329 | int SecPSP = -1; | ||
| 330 | |||
| 331 | pr_debug(" -> fw_cmo_feature_init()\n"); | ||
| 332 | spin_lock(&rtas_data_buf_lock); | ||
| 333 | memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE); | ||
| 334 | call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, | ||
| 335 | NULL, | ||
| 336 | CMO_CHARACTERISTICS_TOKEN, | ||
| 337 | __pa(rtas_data_buf), | ||
| 338 | RTAS_DATA_BUF_SIZE); | ||
| 339 | |||
| 340 | if (call_status != 0) { | ||
| 341 | spin_unlock(&rtas_data_buf_lock); | ||
| 342 | pr_debug("CMO not available\n"); | ||
| 343 | pr_debug(" <- fw_cmo_feature_init()\n"); | ||
| 344 | return; | ||
| 345 | } | ||
| 346 | |||
| 347 | end = rtas_data_buf + CMO_MAXLENGTH - 2; | ||
| 348 | ptr = rtas_data_buf + 2; /* step over strlen value */ | ||
| 349 | key = value = ptr; | ||
| 350 | |||
| 351 | while (*ptr && (ptr <= end)) { | ||
| 352 | /* Separate the key and value by replacing '=' with '\0' and | ||
| 353 | * point the value at the string after the '=' | ||
| 354 | */ | ||
| 355 | if (ptr[0] == '=') { | ||
| 356 | ptr[0] = '\0'; | ||
| 357 | value = ptr + 1; | ||
| 358 | } else if (ptr[0] == '\0' || ptr[0] == ',') { | ||
| 359 | /* Terminate the string containing the key/value pair */ | ||
| 360 | ptr[0] = '\0'; | ||
| 361 | |||
| 362 | if (key == value) { | ||
| 363 | pr_debug("Malformed key/value pair\n"); | ||
| 364 | /* Never found a '=', end processing */ | ||
| 365 | break; | ||
| 366 | } | ||
| 367 | |||
| 368 | if (0 == strcmp(key, "PrPSP")) | ||
| 369 | PrPSP = simple_strtol(value, NULL, 10); | ||
| 370 | else if (0 == strcmp(key, "SecPSP")) | ||
| 371 | SecPSP = simple_strtol(value, NULL, 10); | ||
| 372 | value = key = ptr + 1; | ||
| 373 | } | ||
| 374 | ptr++; | ||
| 375 | } | ||
| 376 | |||
| 377 | if (PrPSP != -1 || SecPSP != -1) { | ||
| 378 | pr_info("CMO enabled\n"); | ||
| 379 | pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP); | ||
| 380 | powerpc_firmware_features |= FW_FEATURE_CMO; | ||
| 381 | } else | ||
| 382 | pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP); | ||
| 383 | spin_unlock(&rtas_data_buf_lock); | ||
| 384 | pr_debug(" <- fw_cmo_feature_init()\n"); | ||
| 385 | } | ||
| 386 | |||
| 317 | /* | 387 | /* |
| 318 | * Early initialization. Relocation is on but do not reference unbolted pages | 388 | * Early initialization. Relocation is on but do not reference unbolted pages |
| 319 | */ | 389 | */ |
| @@ -329,6 +399,7 @@ static void __init pSeries_init_early(void) | |||
| 329 | else if (firmware_has_feature(FW_FEATURE_XDABR)) | 399 | else if (firmware_has_feature(FW_FEATURE_XDABR)) |
| 330 | ppc_md.set_dabr = pseries_set_xdabr; | 400 | ppc_md.set_dabr = pseries_set_xdabr; |
| 331 | 401 | ||
| 402 | pSeries_cmo_feature_init(); | ||
| 332 | iommu_init_early_pSeries(); | 403 | iommu_init_early_pSeries(); |
| 333 | 404 | ||
| 334 | pr_debug(" <- pSeries_init_early()\n"); | 405 | pr_debug(" <- pSeries_init_early()\n"); |
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index de8c8b542cfa..89639ecbf381 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
| @@ -147,7 +147,7 @@ static void dart_flush(struct iommu_table *tbl) | |||
| 147 | } | 147 | } |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | static void dart_build(struct iommu_table *tbl, long index, | 150 | static int dart_build(struct iommu_table *tbl, long index, |
| 151 | long npages, unsigned long uaddr, | 151 | long npages, unsigned long uaddr, |
| 152 | enum dma_data_direction direction, | 152 | enum dma_data_direction direction, |
| 153 | struct dma_attrs *attrs) | 153 | struct dma_attrs *attrs) |
| @@ -184,6 +184,7 @@ static void dart_build(struct iommu_table *tbl, long index, | |||
| 184 | } else { | 184 | } else { |
| 185 | dart_dirty = 1; | 185 | dart_dirty = 1; |
| 186 | } | 186 | } |
| 187 | return 0; | ||
| 187 | } | 188 | } |
| 188 | 189 | ||
| 189 | 190 | ||
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index 4bb18f57901e..1ce546462be5 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig | |||
| @@ -29,7 +29,7 @@ config QE_GPIO | |||
| 29 | bool "QE GPIO support" | 29 | bool "QE GPIO support" |
| 30 | depends on QUICC_ENGINE | 30 | depends on QUICC_ENGINE |
| 31 | select GENERIC_GPIO | 31 | select GENERIC_GPIO |
| 32 | select HAVE_GPIO_LIB | 32 | select ARCH_REQUIRE_GPIOLIB |
| 33 | help | 33 | help |
| 34 | Say Y here if you're going to use hardware that connects to the | 34 | Say Y here if you're going to use hardware that connects to the |
| 35 | QE GPIOs. | 35 | QE GPIOs. |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index eb530b4128ba..2ed88122be93 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -565,6 +565,7 @@ bool "s390 guest support (EXPERIMENTAL)" | |||
| 565 | depends on 64BIT && EXPERIMENTAL | 565 | depends on 64BIT && EXPERIMENTAL |
| 566 | select VIRTIO | 566 | select VIRTIO |
| 567 | select VIRTIO_RING | 567 | select VIRTIO_RING |
| 568 | select VIRTIO_CONSOLE | ||
| 568 | help | 569 | help |
| 569 | Select this option if you want to run the kernel under s390 linux | 570 | Select this option if you want to run the kernel under s390 linux |
| 570 | endmenu | 571 | endmenu |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 288ad490a6dd..4f82e5b5f879 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
| @@ -270,7 +270,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, | |||
| 270 | __ctl_store(kcb->kprobe_saved_ctl, 9, 11); | 270 | __ctl_store(kcb->kprobe_saved_ctl, 9, 11); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | /* Called with kretprobe_lock held */ | ||
| 274 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 273 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
| 275 | struct pt_regs *regs) | 274 | struct pt_regs *regs) |
| 276 | { | 275 | { |
| @@ -377,8 +376,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
| 377 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 376 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; |
| 378 | 377 | ||
| 379 | INIT_HLIST_HEAD(&empty_rp); | 378 | INIT_HLIST_HEAD(&empty_rp); |
| 380 | spin_lock_irqsave(&kretprobe_lock, flags); | 379 | kretprobe_hash_lock(current, &head, &flags); |
| 381 | head = kretprobe_inst_table_head(current); | ||
| 382 | 380 | ||
| 383 | /* | 381 | /* |
| 384 | * It is possible to have multiple instances associated with a given | 382 | * It is possible to have multiple instances associated with a given |
| @@ -417,7 +415,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
| 417 | regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE; | 415 | regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE; |
| 418 | 416 | ||
| 419 | reset_current_kprobe(); | 417 | reset_current_kprobe(); |
| 420 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 418 | kretprobe_hash_unlock(current, &flags); |
| 421 | preempt_enable_no_resched(); | 419 | preempt_enable_no_resched(); |
| 422 | 420 | ||
| 423 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 421 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index b358e18273b0..62122bad1e33 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #include <asm/sections.h> | 54 | #include <asm/sections.h> |
| 55 | #include <asm/ebcdic.h> | 55 | #include <asm/ebcdic.h> |
| 56 | #include <asm/compat.h> | 56 | #include <asm/compat.h> |
| 57 | #include <asm/kvm_virtio.h> | ||
| 57 | 58 | ||
| 58 | long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | | 59 | long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | |
| 59 | PSW_MASK_MCHECK | PSW_DEFAULT_KEY); | 60 | PSW_MASK_MCHECK | PSW_DEFAULT_KEY); |
| @@ -766,7 +767,8 @@ setup_arch(char **cmdline_p) | |||
| 766 | printk("We are running under VM (64 bit mode)\n"); | 767 | printk("We are running under VM (64 bit mode)\n"); |
| 767 | else if (MACHINE_IS_KVM) { | 768 | else if (MACHINE_IS_KVM) { |
| 768 | printk("We are running under KVM (64 bit mode)\n"); | 769 | printk("We are running under KVM (64 bit mode)\n"); |
| 769 | add_preferred_console("ttyS", 1, NULL); | 770 | add_preferred_console("hvc", 0, NULL); |
| 771 | s390_virtio_console_init(); | ||
| 770 | } else | 772 | } else |
| 771 | printk("We are running native (64 bit mode)\n"); | 773 | printk("We are running native (64 bit mode)\n"); |
| 772 | #endif /* CONFIG_64BIT */ | 774 | #endif /* CONFIG_64BIT */ |
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 212d618b0095..632b13e10053 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include <linux/device.h> | 9 | #include <linux/device.h> |
| 10 | #include <linux/bootmem.h> | 10 | #include <linux/bootmem.h> |
| 11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
| 12 | #include <linux/kthread.h> | ||
| 13 | #include <linux/workqueue.h> | 12 | #include <linux/workqueue.h> |
| 14 | #include <linux/cpu.h> | 13 | #include <linux/cpu.h> |
| 15 | #include <linux/smp.h> | 14 | #include <linux/smp.h> |
| @@ -230,20 +229,9 @@ void arch_update_cpu_topology(void) | |||
| 230 | } | 229 | } |
| 231 | } | 230 | } |
| 232 | 231 | ||
| 233 | static int topology_kthread(void *data) | ||
| 234 | { | ||
| 235 | arch_reinit_sched_domains(); | ||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | static void topology_work_fn(struct work_struct *work) | 232 | static void topology_work_fn(struct work_struct *work) |
| 240 | { | 233 | { |
| 241 | /* We can't call arch_reinit_sched_domains() from a multi-threaded | 234 | arch_reinit_sched_domains(); |
| 242 | * workqueue context since it may deadlock in case of cpu hotplug. | ||
| 243 | * So we have to create a kernel thread in order to call | ||
| 244 | * arch_reinit_sched_domains(). | ||
| 245 | */ | ||
| 246 | kthread_run(topology_kthread, NULL, "topology_update"); | ||
| 247 | } | 235 | } |
| 248 | 236 | ||
| 249 | void topology_schedule_update(void) | 237 | void topology_schedule_update(void) |
diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c index adcea31e663e..f386997e4d9c 100644 --- a/arch/sh/boot/compressed/misc_32.c +++ b/arch/sh/boot/compressed/misc_32.c | |||
| @@ -74,8 +74,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */ | |||
| 74 | static int fill_inbuf(void); | 74 | static int fill_inbuf(void); |
| 75 | static void flush_window(void); | 75 | static void flush_window(void); |
| 76 | static void error(char *m); | 76 | static void error(char *m); |
| 77 | static void gzip_mark(void **); | ||
| 78 | static void gzip_release(void **); | ||
| 79 | 77 | ||
| 80 | extern char input_data[]; | 78 | extern char input_data[]; |
| 81 | extern int input_len; | 79 | extern int input_len; |
| @@ -84,11 +82,7 @@ static long bytes_out = 0; | |||
| 84 | static uch *output_data; | 82 | static uch *output_data; |
| 85 | static unsigned long output_ptr = 0; | 83 | static unsigned long output_ptr = 0; |
| 86 | 84 | ||
| 87 | static void *malloc(int size); | ||
| 88 | static void free(void *where); | ||
| 89 | static void error(char *m); | 85 | static void error(char *m); |
| 90 | static void gzip_mark(void **); | ||
| 91 | static void gzip_release(void **); | ||
| 92 | 86 | ||
| 93 | int puts(const char *); | 87 | int puts(const char *); |
| 94 | 88 | ||
| @@ -101,38 +95,6 @@ static unsigned long free_mem_end_ptr; | |||
| 101 | 95 | ||
| 102 | #include "../../../../lib/inflate.c" | 96 | #include "../../../../lib/inflate.c" |
| 103 | 97 | ||
| 104 | static void *malloc(int size) | ||
| 105 | { | ||
| 106 | void *p; | ||
| 107 | |||
| 108 | if (size <0) error("Malloc error"); | ||
| 109 | if (free_mem_ptr == 0) error("Memory error"); | ||
| 110 | |||
| 111 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 112 | |||
| 113 | p = (void *)free_mem_ptr; | ||
| 114 | free_mem_ptr += size; | ||
| 115 | |||
| 116 | if (free_mem_ptr >= free_mem_end_ptr) | ||
| 117 | error("Out of memory"); | ||
| 118 | |||
| 119 | return p; | ||
| 120 | } | ||
| 121 | |||
| 122 | static void free(void *where) | ||
| 123 | { /* Don't care */ | ||
| 124 | } | ||
| 125 | |||
| 126 | static void gzip_mark(void **ptr) | ||
| 127 | { | ||
| 128 | *ptr = (void *) free_mem_ptr; | ||
| 129 | } | ||
| 130 | |||
| 131 | static void gzip_release(void **ptr) | ||
| 132 | { | ||
| 133 | free_mem_ptr = (long) *ptr; | ||
| 134 | } | ||
| 135 | |||
| 136 | #ifdef CONFIG_SH_STANDARD_BIOS | 98 | #ifdef CONFIG_SH_STANDARD_BIOS |
| 137 | size_t strlen(const char *s) | 99 | size_t strlen(const char *s) |
| 138 | { | 100 | { |
diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c index a006ef89b9dd..2941657e18aa 100644 --- a/arch/sh/boot/compressed/misc_64.c +++ b/arch/sh/boot/compressed/misc_64.c | |||
| @@ -72,8 +72,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */ | |||
| 72 | static int fill_inbuf(void); | 72 | static int fill_inbuf(void); |
| 73 | static void flush_window(void); | 73 | static void flush_window(void); |
| 74 | static void error(char *m); | 74 | static void error(char *m); |
| 75 | static void gzip_mark(void **); | ||
| 76 | static void gzip_release(void **); | ||
| 77 | 75 | ||
| 78 | extern char input_data[]; | 76 | extern char input_data[]; |
| 79 | extern int input_len; | 77 | extern int input_len; |
| @@ -82,11 +80,7 @@ static long bytes_out = 0; | |||
| 82 | static uch *output_data; | 80 | static uch *output_data; |
| 83 | static unsigned long output_ptr = 0; | 81 | static unsigned long output_ptr = 0; |
| 84 | 82 | ||
| 85 | static void *malloc(int size); | ||
| 86 | static void free(void *where); | ||
| 87 | static void error(char *m); | 83 | static void error(char *m); |
| 88 | static void gzip_mark(void **); | ||
| 89 | static void gzip_release(void **); | ||
| 90 | 84 | ||
| 91 | static void puts(const char *); | 85 | static void puts(const char *); |
| 92 | 86 | ||
| @@ -99,40 +93,6 @@ static unsigned long free_mem_end_ptr; | |||
| 99 | 93 | ||
| 100 | #include "../../../../lib/inflate.c" | 94 | #include "../../../../lib/inflate.c" |
| 101 | 95 | ||
| 102 | static void *malloc(int size) | ||
| 103 | { | ||
| 104 | void *p; | ||
| 105 | |||
| 106 | if (size < 0) | ||
| 107 | error("Malloc error\n"); | ||
| 108 | if (free_mem_ptr == 0) | ||
| 109 | error("Memory error\n"); | ||
| 110 | |||
| 111 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 112 | |||
| 113 | p = (void *) free_mem_ptr; | ||
| 114 | free_mem_ptr += size; | ||
| 115 | |||
| 116 | if (free_mem_ptr >= free_mem_end_ptr) | ||
| 117 | error("\nOut of memory\n"); | ||
| 118 | |||
| 119 | return p; | ||
| 120 | } | ||
| 121 | |||
| 122 | static void free(void *where) | ||
| 123 | { /* Don't care */ | ||
| 124 | } | ||
| 125 | |||
| 126 | static void gzip_mark(void **ptr) | ||
| 127 | { | ||
| 128 | *ptr = (void *) free_mem_ptr; | ||
| 129 | } | ||
| 130 | |||
| 131 | static void gzip_release(void **ptr) | ||
| 132 | { | ||
| 133 | free_mem_ptr = (long) *ptr; | ||
| 134 | } | ||
| 135 | |||
| 136 | void puts(const char *s) | 96 | void puts(const char *s) |
| 137 | { | 97 | { |
| 138 | } | 98 | } |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 789724e61e83..375de7c6d082 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
| @@ -298,20 +298,6 @@ config UNIX98_PTYS | |||
| 298 | Read the instructions in <file:Documentation/Changes> pertaining to | 298 | Read the instructions in <file:Documentation/Changes> pertaining to |
| 299 | pseudo terminals. It's safe to say N. | 299 | pseudo terminals. It's safe to say N. |
| 300 | 300 | ||
| 301 | config UNIX98_PTY_COUNT | ||
| 302 | int "Maximum number of Unix98 PTYs in use (0-2048)" | ||
| 303 | depends on UNIX98_PTYS | ||
| 304 | default "256" | ||
| 305 | help | ||
| 306 | The maximum number of Unix98 PTYs that can be used at any one time. | ||
| 307 | The default is 256, and should be enough for desktop systems. Server | ||
| 308 | machines which support incoming telnet/rlogin/ssh connections and/or | ||
| 309 | serve several X terminals may want to increase this: every incoming | ||
| 310 | connection and every xterm uses up one PTY. | ||
| 311 | |||
| 312 | When not in use, each additional set of 256 PTYs occupy | ||
| 313 | approximately 8 KB of kernel memory on 32-bit architectures. | ||
| 314 | |||
| 315 | endmenu | 301 | endmenu |
| 316 | 302 | ||
| 317 | source "fs/Kconfig" | 303 | source "fs/Kconfig" |
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index f43b5d755354..201a6e547e4a 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c | |||
| @@ -478,9 +478,9 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 478 | return 0; | 478 | return 0; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | /* Called with kretprobe_lock held. The value stored in the return | 481 | /* The value stored in the return address register is actually 2 |
| 482 | * address register is actually 2 instructions before where the | 482 | * instructions before where the callee will return to. |
| 483 | * callee will return to. Sequences usually look something like this | 483 | * Sequences usually look something like this |
| 484 | * | 484 | * |
| 485 | * call some_function <--- return register points here | 485 | * call some_function <--- return register points here |
| 486 | * nop <--- call delay slot | 486 | * nop <--- call delay slot |
| @@ -512,8 +512,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 512 | unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; | 512 | unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; |
| 513 | 513 | ||
| 514 | INIT_HLIST_HEAD(&empty_rp); | 514 | INIT_HLIST_HEAD(&empty_rp); |
| 515 | spin_lock_irqsave(&kretprobe_lock, flags); | 515 | kretprobe_hash_lock(current, &head, &flags); |
| 516 | head = kretprobe_inst_table_head(current); | ||
| 517 | 516 | ||
| 518 | /* | 517 | /* |
| 519 | * It is possible to have multiple instances associated with a given | 518 | * It is possible to have multiple instances associated with a given |
| @@ -553,7 +552,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 553 | regs->tnpc = orig_ret_address + 4; | 552 | regs->tnpc = orig_ret_address + 4; |
| 554 | 553 | ||
| 555 | reset_current_kprobe(); | 554 | reset_current_kprobe(); |
| 556 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 555 | kretprobe_hash_unlock(current, &flags); |
| 557 | preempt_enable_no_resched(); | 556 | preempt_enable_no_resched(); |
| 558 | 557 | ||
| 559 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 558 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b2ddfcf01728..e3cba0b45600 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -23,11 +23,13 @@ config X86 | |||
| 23 | select HAVE_OPROFILE | 23 | select HAVE_OPROFILE |
| 24 | select HAVE_IOREMAP_PROT | 24 | select HAVE_IOREMAP_PROT |
| 25 | select HAVE_KPROBES | 25 | select HAVE_KPROBES |
| 26 | select ARCH_WANT_OPTIONAL_GPIOLIB if !X86_RDC321X | ||
| 26 | select HAVE_KRETPROBES | 27 | select HAVE_KRETPROBES |
| 27 | select HAVE_DYNAMIC_FTRACE | 28 | select HAVE_DYNAMIC_FTRACE |
| 28 | select HAVE_FTRACE | 29 | select HAVE_FTRACE |
| 29 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) | 30 | select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) |
| 30 | select HAVE_ARCH_KGDB if !X86_VOYAGER | 31 | select HAVE_ARCH_KGDB if !X86_VOYAGER |
| 32 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
| 31 | 33 | ||
| 32 | config ARCH_DEFCONFIG | 34 | config ARCH_DEFCONFIG |
| 33 | string | 35 | string |
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index bc5553b496f7..9fea73706479 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
| @@ -182,8 +182,6 @@ static unsigned outcnt; | |||
| 182 | static int fill_inbuf(void); | 182 | static int fill_inbuf(void); |
| 183 | static void flush_window(void); | 183 | static void flush_window(void); |
| 184 | static void error(char *m); | 184 | static void error(char *m); |
| 185 | static void gzip_mark(void **); | ||
| 186 | static void gzip_release(void **); | ||
| 187 | 185 | ||
| 188 | /* | 186 | /* |
| 189 | * This is set up by the setup-routine at boot-time | 187 | * This is set up by the setup-routine at boot-time |
| @@ -196,9 +194,6 @@ extern int input_len; | |||
| 196 | 194 | ||
| 197 | static long bytes_out; | 195 | static long bytes_out; |
| 198 | 196 | ||
| 199 | static void *malloc(int size); | ||
| 200 | static void free(void *where); | ||
| 201 | |||
| 202 | static void *memset(void *s, int c, unsigned n); | 197 | static void *memset(void *s, int c, unsigned n); |
| 203 | static void *memcpy(void *dest, const void *src, unsigned n); | 198 | static void *memcpy(void *dest, const void *src, unsigned n); |
| 204 | 199 | ||
| @@ -220,40 +215,6 @@ static int lines, cols; | |||
| 220 | 215 | ||
| 221 | #include "../../../../lib/inflate.c" | 216 | #include "../../../../lib/inflate.c" |
| 222 | 217 | ||
| 223 | static void *malloc(int size) | ||
| 224 | { | ||
| 225 | void *p; | ||
| 226 | |||
| 227 | if (size < 0) | ||
| 228 | error("Malloc error"); | ||
| 229 | if (free_mem_ptr <= 0) | ||
| 230 | error("Memory error"); | ||
| 231 | |||
| 232 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
| 233 | |||
| 234 | p = (void *)free_mem_ptr; | ||
| 235 | free_mem_ptr += size; | ||
| 236 | |||
| 237 | if (free_mem_ptr >= free_mem_end_ptr) | ||
| 238 | error("Out of memory"); | ||
| 239 | |||
| 240 | return p; | ||
| 241 | } | ||
| 242 | |||
| 243 | static void free(void *where) | ||
| 244 | { /* Don't care */ | ||
| 245 | } | ||
| 246 | |||
| 247 | static void gzip_mark(void **ptr) | ||
| 248 | { | ||
| 249 | *ptr = (void *) free_mem_ptr; | ||
| 250 | } | ||
| 251 | |||
| 252 | static void gzip_release(void **ptr) | ||
| 253 | { | ||
| 254 | free_mem_ptr = (memptr) *ptr; | ||
| 255 | } | ||
| 256 | |||
| 257 | static void scroll(void) | 218 | static void scroll(void) |
| 258 | { | 219 | { |
| 259 | int i; | 220 | int i; |
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 43c019f85f0d..6c27679ec6aa 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
| @@ -431,7 +431,6 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
| 431 | regs->ip = (unsigned long)p->ainsn.insn; | 431 | regs->ip = (unsigned long)p->ainsn.insn; |
| 432 | } | 432 | } |
| 433 | 433 | ||
| 434 | /* Called with kretprobe_lock held */ | ||
| 435 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 434 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
| 436 | struct pt_regs *regs) | 435 | struct pt_regs *regs) |
| 437 | { | 436 | { |
| @@ -682,8 +681,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
| 682 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 681 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; |
| 683 | 682 | ||
| 684 | INIT_HLIST_HEAD(&empty_rp); | 683 | INIT_HLIST_HEAD(&empty_rp); |
| 685 | spin_lock_irqsave(&kretprobe_lock, flags); | 684 | kretprobe_hash_lock(current, &head, &flags); |
| 686 | head = kretprobe_inst_table_head(current); | ||
| 687 | /* fixup registers */ | 685 | /* fixup registers */ |
| 688 | #ifdef CONFIG_X86_64 | 686 | #ifdef CONFIG_X86_64 |
| 689 | regs->cs = __KERNEL_CS; | 687 | regs->cs = __KERNEL_CS; |
| @@ -732,7 +730,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) | |||
| 732 | 730 | ||
| 733 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 731 | kretprobe_assert(ri, orig_ret_address, trampoline_address); |
| 734 | 732 | ||
| 735 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 733 | kretprobe_hash_unlock(current, &flags); |
| 736 | 734 | ||
| 737 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 735 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
| 738 | hlist_del(&ri->hlist); | 736 | hlist_del(&ri->hlist); |
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 151f2d171f7c..19e7fc7c2c4f 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
| 30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
| 31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
| 32 | #include <linux/crash_dump.h> | ||
| 32 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
| 33 | #include <linux/bitops.h> | 34 | #include <linux/bitops.h> |
| 34 | #include <linux/pci_ids.h> | 35 | #include <linux/pci_ids.h> |
| @@ -167,6 +168,8 @@ static void calgary_dump_error_regs(struct iommu_table *tbl); | |||
| 167 | static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev); | 168 | static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev); |
| 168 | static void calioc2_tce_cache_blast(struct iommu_table *tbl); | 169 | static void calioc2_tce_cache_blast(struct iommu_table *tbl); |
| 169 | static void calioc2_dump_error_regs(struct iommu_table *tbl); | 170 | static void calioc2_dump_error_regs(struct iommu_table *tbl); |
| 171 | static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl); | ||
| 172 | static void get_tce_space_from_tar(void); | ||
| 170 | 173 | ||
| 171 | static struct cal_chipset_ops calgary_chip_ops = { | 174 | static struct cal_chipset_ops calgary_chip_ops = { |
| 172 | .handle_quirks = calgary_handle_quirks, | 175 | .handle_quirks = calgary_handle_quirks, |
| @@ -830,7 +833,11 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar) | |||
| 830 | 833 | ||
| 831 | tbl = pci_iommu(dev->bus); | 834 | tbl = pci_iommu(dev->bus); |
| 832 | tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space; | 835 | tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space; |
| 833 | tce_free(tbl, 0, tbl->it_size); | 836 | |
| 837 | if (is_kdump_kernel()) | ||
| 838 | calgary_init_bitmap_from_tce_table(tbl); | ||
| 839 | else | ||
| 840 | tce_free(tbl, 0, tbl->it_size); | ||
| 834 | 841 | ||
| 835 | if (is_calgary(dev->device)) | 842 | if (is_calgary(dev->device)) |
| 836 | tbl->chip_ops = &calgary_chip_ops; | 843 | tbl->chip_ops = &calgary_chip_ops; |
| @@ -1209,6 +1216,10 @@ static int __init calgary_init(void) | |||
| 1209 | if (ret) | 1216 | if (ret) |
| 1210 | return ret; | 1217 | return ret; |
| 1211 | 1218 | ||
| 1219 | /* Purely for kdump kernel case */ | ||
| 1220 | if (is_kdump_kernel()) | ||
| 1221 | get_tce_space_from_tar(); | ||
| 1222 | |||
| 1212 | do { | 1223 | do { |
| 1213 | dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev); | 1224 | dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev); |
| 1214 | if (!dev) | 1225 | if (!dev) |
| @@ -1339,6 +1350,61 @@ static int __init calgary_bus_has_devices(int bus, unsigned short pci_dev) | |||
| 1339 | return (val != 0xffffffff); | 1350 | return (val != 0xffffffff); |
| 1340 | } | 1351 | } |
| 1341 | 1352 | ||
| 1353 | /* | ||
| 1354 | * calgary_init_bitmap_from_tce_table(): | ||
| 1355 | * Funtion for kdump case. In the second/kdump kernel initialize | ||
| 1356 | * the bitmap based on the tce table entries obtained from first kernel | ||
| 1357 | */ | ||
| 1358 | static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl) | ||
| 1359 | { | ||
| 1360 | u64 *tp; | ||
| 1361 | unsigned int index; | ||
| 1362 | tp = ((u64 *)tbl->it_base); | ||
| 1363 | for (index = 0 ; index < tbl->it_size; index++) { | ||
| 1364 | if (*tp != 0x0) | ||
| 1365 | set_bit(index, tbl->it_map); | ||
| 1366 | tp++; | ||
| 1367 | } | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | /* | ||
| 1371 | * get_tce_space_from_tar(): | ||
| 1372 | * Function for kdump case. Get the tce tables from first kernel | ||
| 1373 | * by reading the contents of the base adress register of calgary iommu | ||
| 1374 | */ | ||
| 1375 | static void get_tce_space_from_tar() | ||
| 1376 | { | ||
| 1377 | int bus; | ||
| 1378 | void __iomem *target; | ||
| 1379 | unsigned long tce_space; | ||
| 1380 | |||
| 1381 | for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { | ||
| 1382 | struct calgary_bus_info *info = &bus_info[bus]; | ||
| 1383 | unsigned short pci_device; | ||
| 1384 | u32 val; | ||
| 1385 | |||
| 1386 | val = read_pci_config(bus, 0, 0, 0); | ||
| 1387 | pci_device = (val & 0xFFFF0000) >> 16; | ||
| 1388 | |||
| 1389 | if (!is_cal_pci_dev(pci_device)) | ||
| 1390 | continue; | ||
| 1391 | if (info->translation_disabled) | ||
| 1392 | continue; | ||
| 1393 | |||
| 1394 | if (calgary_bus_has_devices(bus, pci_device) || | ||
| 1395 | translate_empty_slots) { | ||
| 1396 | target = calgary_reg(bus_info[bus].bbar, | ||
| 1397 | tar_offset(bus)); | ||
| 1398 | tce_space = be64_to_cpu(readq(target)); | ||
| 1399 | tce_space = tce_space & TAR_SW_BITS; | ||
| 1400 | |||
| 1401 | tce_space = tce_space & (~specified_table_size); | ||
| 1402 | info->tce_space = (u64 *)__va(tce_space); | ||
| 1403 | } | ||
| 1404 | } | ||
| 1405 | return; | ||
| 1406 | } | ||
| 1407 | |||
| 1342 | void __init detect_calgary(void) | 1408 | void __init detect_calgary(void) |
| 1343 | { | 1409 | { |
| 1344 | int bus; | 1410 | int bus; |
| @@ -1394,7 +1460,8 @@ void __init detect_calgary(void) | |||
| 1394 | return; | 1460 | return; |
| 1395 | } | 1461 | } |
| 1396 | 1462 | ||
| 1397 | specified_table_size = determine_tce_table_size(max_pfn * PAGE_SIZE); | 1463 | specified_table_size = determine_tce_table_size((is_kdump_kernel() ? |
| 1464 | saved_max_pfn : max_pfn) * PAGE_SIZE); | ||
| 1398 | 1465 | ||
| 1399 | for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { | 1466 | for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { |
| 1400 | struct calgary_bus_info *info = &bus_info[bus]; | 1467 | struct calgary_bus_info *info = &bus_info[bus]; |
| @@ -1412,10 +1479,16 @@ void __init detect_calgary(void) | |||
| 1412 | 1479 | ||
| 1413 | if (calgary_bus_has_devices(bus, pci_device) || | 1480 | if (calgary_bus_has_devices(bus, pci_device) || |
| 1414 | translate_empty_slots) { | 1481 | translate_empty_slots) { |
| 1415 | tbl = alloc_tce_table(); | 1482 | /* |
| 1416 | if (!tbl) | 1483 | * If it is kdump kernel, find and use tce tables |
| 1417 | goto cleanup; | 1484 | * from first kernel, else allocate tce tables here |
| 1418 | info->tce_space = tbl; | 1485 | */ |
| 1486 | if (!is_kdump_kernel()) { | ||
| 1487 | tbl = alloc_tce_table(); | ||
| 1488 | if (!tbl) | ||
| 1489 | goto cleanup; | ||
| 1490 | info->tce_space = tbl; | ||
| 1491 | } | ||
| 1419 | calgary_found = 1; | 1492 | calgary_found = 1; |
| 1420 | } | 1493 | } |
| 1421 | } | 1494 | } |
diff --git a/block/ioctl.c b/block/ioctl.c index 52d6385216ad..77185e5c026a 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
| @@ -17,6 +17,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
| 17 | long long start, length; | 17 | long long start, length; |
| 18 | int part; | 18 | int part; |
| 19 | int i; | 19 | int i; |
| 20 | int err; | ||
| 20 | 21 | ||
| 21 | if (!capable(CAP_SYS_ADMIN)) | 22 | if (!capable(CAP_SYS_ADMIN)) |
| 22 | return -EACCES; | 23 | return -EACCES; |
| @@ -61,9 +62,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
| 61 | } | 62 | } |
| 62 | } | 63 | } |
| 63 | /* all seems OK */ | 64 | /* all seems OK */ |
| 64 | add_partition(disk, part, start, length, ADDPART_FLAG_NONE); | 65 | err = add_partition(disk, part, start, length, ADDPART_FLAG_NONE); |
| 65 | mutex_unlock(&bdev->bd_mutex); | 66 | mutex_unlock(&bdev->bd_mutex); |
| 66 | return 0; | 67 | return err; |
| 67 | case BLKPG_DEL_PARTITION: | 68 | case BLKPG_DEL_PARTITION: |
| 68 | if (!disk->part[part-1]) | 69 | if (!disk->part[part-1]) |
| 69 | return -ENXIO; | 70 | return -ENXIO; |
diff --git a/drivers/Makefile b/drivers/Makefile index 808e0ae66aa8..54ec5e718c0e 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | # Rewritten to use lists instead of if-statements. | 5 | # Rewritten to use lists instead of if-statements. |
| 6 | # | 6 | # |
| 7 | 7 | ||
| 8 | obj-$(CONFIG_HAVE_GPIO_LIB) += gpio/ | 8 | obj-y += gpio/ |
| 9 | obj-$(CONFIG_PCI) += pci/ | 9 | obj-$(CONFIG_PCI) += pci/ |
| 10 | obj-$(CONFIG_PARISC) += parisc/ | 10 | obj-$(CONFIG_PARISC) += parisc/ |
| 11 | obj-$(CONFIG_RAPIDIO) += rapidio/ | 11 | obj-$(CONFIG_RAPIDIO) += rapidio/ |
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index dc7596f028b6..ef3e5522e1a4 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -1273,7 +1273,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, | |||
| 1273 | void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; | 1273 | void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; |
| 1274 | u32 em_ctl; | 1274 | u32 em_ctl; |
| 1275 | u32 message[] = {0, 0}; | 1275 | u32 message[] = {0, 0}; |
| 1276 | unsigned int flags; | 1276 | unsigned long flags; |
| 1277 | int pmp; | 1277 | int pmp; |
| 1278 | struct ahci_em_priv *emp; | 1278 | struct ahci_em_priv *emp; |
| 1279 | 1279 | ||
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index b0be1d18fee2..c9c92b00fd55 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -184,7 +184,7 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
| 184 | struct device *dev = to_dev(kobj); | 184 | struct device *dev = to_dev(kobj); |
| 185 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); | 185 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
| 186 | struct firmware *fw; | 186 | struct firmware *fw; |
| 187 | ssize_t ret_count = count; | 187 | ssize_t ret_count; |
| 188 | 188 | ||
| 189 | mutex_lock(&fw_lock); | 189 | mutex_lock(&fw_lock); |
| 190 | fw = fw_priv->fw; | 190 | fw = fw_priv->fw; |
| @@ -192,14 +192,8 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
| 192 | ret_count = -ENODEV; | 192 | ret_count = -ENODEV; |
| 193 | goto out; | 193 | goto out; |
| 194 | } | 194 | } |
| 195 | if (offset > fw->size) { | 195 | ret_count = memory_read_from_buffer(buffer, count, &offset, |
| 196 | ret_count = 0; | 196 | fw->data, fw->size); |
| 197 | goto out; | ||
| 198 | } | ||
| 199 | if (offset + ret_count > fw->size) | ||
| 200 | ret_count = fw->size - offset; | ||
| 201 | |||
| 202 | memcpy(buffer, fw->data + offset, ret_count); | ||
| 203 | out: | 197 | out: |
| 204 | mutex_unlock(&fw_lock); | 198 | mutex_unlock(&fw_lock); |
| 205 | return ret_count; | 199 | return ret_count; |
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index c04440cd6a32..181ebb85f0be 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <linux/hdreg.h> | 7 | #include <linux/hdreg.h> |
| 8 | #include <linux/blkdev.h> | 8 | #include <linux/blkdev.h> |
| 9 | #include <linux/completion.h> | ||
| 9 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
| 10 | #include <linux/smp_lock.h> | 11 | #include <linux/smp_lock.h> |
| 11 | #include "aoe.h" | 12 | #include "aoe.h" |
| @@ -36,7 +37,7 @@ struct ErrMsg { | |||
| 36 | 37 | ||
| 37 | static struct ErrMsg emsgs[NMSG]; | 38 | static struct ErrMsg emsgs[NMSG]; |
| 38 | static int emsgs_head_idx, emsgs_tail_idx; | 39 | static int emsgs_head_idx, emsgs_tail_idx; |
| 39 | static struct semaphore emsgs_sema; | 40 | static struct completion emsgs_comp; |
| 40 | static spinlock_t emsgs_lock; | 41 | static spinlock_t emsgs_lock; |
| 41 | static int nblocked_emsgs_readers; | 42 | static int nblocked_emsgs_readers; |
| 42 | static struct class *aoe_class; | 43 | static struct class *aoe_class; |
| @@ -141,7 +142,7 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags); | |||
| 141 | spin_unlock_irqrestore(&emsgs_lock, flags); | 142 | spin_unlock_irqrestore(&emsgs_lock, flags); |
| 142 | 143 | ||
| 143 | if (nblocked_emsgs_readers) | 144 | if (nblocked_emsgs_readers) |
| 144 | up(&emsgs_sema); | 145 | complete(&emsgs_comp); |
| 145 | } | 146 | } |
| 146 | 147 | ||
| 147 | static ssize_t | 148 | static ssize_t |
| @@ -221,7 +222,7 @@ aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off) | |||
| 221 | 222 | ||
| 222 | spin_unlock_irqrestore(&emsgs_lock, flags); | 223 | spin_unlock_irqrestore(&emsgs_lock, flags); |
| 223 | 224 | ||
| 224 | n = down_interruptible(&emsgs_sema); | 225 | n = wait_for_completion_interruptible(&emsgs_comp); |
| 225 | 226 | ||
| 226 | spin_lock_irqsave(&emsgs_lock, flags); | 227 | spin_lock_irqsave(&emsgs_lock, flags); |
| 227 | 228 | ||
| @@ -269,7 +270,7 @@ aoechr_init(void) | |||
| 269 | printk(KERN_ERR "aoe: can't register char device\n"); | 270 | printk(KERN_ERR "aoe: can't register char device\n"); |
| 270 | return n; | 271 | return n; |
| 271 | } | 272 | } |
| 272 | sema_init(&emsgs_sema, 0); | 273 | init_completion(&emsgs_comp); |
| 273 | spin_lock_init(&emsgs_lock); | 274 | spin_lock_init(&emsgs_lock); |
| 274 | aoe_class = class_create(THIS_MODULE, "aoe"); | 275 | aoe_class = class_create(THIS_MODULE, "aoe"); |
| 275 | if (IS_ERR(aoe_class)) { | 276 | if (IS_ERR(aoe_class)) { |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index dd7ea203f940..42251095134f 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -196,6 +196,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 196 | int err; | 196 | int err; |
| 197 | u64 cap; | 197 | u64 cap; |
| 198 | u32 v; | 198 | u32 v; |
| 199 | u32 blk_size; | ||
| 199 | 200 | ||
| 200 | if (index_to_minor(index) >= 1 << MINORBITS) | 201 | if (index_to_minor(index) >= 1 << MINORBITS) |
| 201 | return -ENOSPC; | 202 | return -ENOSPC; |
| @@ -290,6 +291,13 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 290 | if (!err) | 291 | if (!err) |
| 291 | blk_queue_max_hw_segments(vblk->disk->queue, v); | 292 | blk_queue_max_hw_segments(vblk->disk->queue, v); |
| 292 | 293 | ||
| 294 | /* Host can optionally specify the block size of the device */ | ||
| 295 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, | ||
| 296 | offsetof(struct virtio_blk_config, blk_size), | ||
| 297 | &blk_size); | ||
| 298 | if (!err) | ||
| 299 | blk_queue_hardsect_size(vblk->disk->queue, blk_size); | ||
| 300 | |||
| 293 | add_disk(vblk->disk); | 301 | add_disk(vblk->disk); |
| 294 | return 0; | 302 | return 0; |
| 295 | 303 | ||
| @@ -330,7 +338,7 @@ static struct virtio_device_id id_table[] = { | |||
| 330 | 338 | ||
| 331 | static unsigned int features[] = { | 339 | static unsigned int features[] = { |
| 332 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 340 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
| 333 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, | 341 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, |
| 334 | }; | 342 | }; |
| 335 | 343 | ||
| 336 | static struct virtio_driver virtio_blk = { | 344 | static struct virtio_driver virtio_blk = { |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 67b07576f8bf..d0ac944e1696 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -36,6 +36,14 @@ config VT | |||
| 36 | If unsure, say Y, or else you won't be able to do much with your new | 36 | If unsure, say Y, or else you won't be able to do much with your new |
| 37 | shiny Linux system :-) | 37 | shiny Linux system :-) |
| 38 | 38 | ||
| 39 | config CONSOLE_TRANSLATIONS | ||
| 40 | depends on VT | ||
| 41 | default y | ||
| 42 | bool "Enable character translations in console" if EMBEDDED | ||
| 43 | ---help--- | ||
| 44 | This enables support for font mapping and Unicode translation | ||
| 45 | on virtual consoles. | ||
| 46 | |||
| 39 | config VT_CONSOLE | 47 | config VT_CONSOLE |
| 40 | bool "Support for console on virtual terminal" if EMBEDDED | 48 | bool "Support for console on virtual terminal" if EMBEDDED |
| 41 | depends on VT | 49 | depends on VT |
| @@ -578,11 +586,14 @@ config HVC_DRIVER | |||
| 578 | It will automatically be selected if one of the back-end console drivers | 586 | It will automatically be selected if one of the back-end console drivers |
| 579 | is selected. | 587 | is selected. |
| 580 | 588 | ||
| 589 | config HVC_IRQ | ||
| 590 | bool | ||
| 581 | 591 | ||
| 582 | config HVC_CONSOLE | 592 | config HVC_CONSOLE |
| 583 | bool "pSeries Hypervisor Virtual Console support" | 593 | bool "pSeries Hypervisor Virtual Console support" |
| 584 | depends on PPC_PSERIES | 594 | depends on PPC_PSERIES |
| 585 | select HVC_DRIVER | 595 | select HVC_DRIVER |
| 596 | select HVC_IRQ | ||
| 586 | help | 597 | help |
| 587 | pSeries machines when partitioned support a hypervisor virtual | 598 | pSeries machines when partitioned support a hypervisor virtual |
| 588 | console. This driver allows each pSeries partition to have a console | 599 | console. This driver allows each pSeries partition to have a console |
| @@ -593,6 +604,7 @@ config HVC_ISERIES | |||
| 593 | depends on PPC_ISERIES | 604 | depends on PPC_ISERIES |
| 594 | default y | 605 | default y |
| 595 | select HVC_DRIVER | 606 | select HVC_DRIVER |
| 607 | select HVC_IRQ | ||
| 596 | help | 608 | help |
| 597 | iSeries machines support a hypervisor virtual console. | 609 | iSeries machines support a hypervisor virtual console. |
| 598 | 610 | ||
| @@ -614,13 +626,18 @@ config HVC_XEN | |||
| 614 | bool "Xen Hypervisor Console support" | 626 | bool "Xen Hypervisor Console support" |
| 615 | depends on XEN | 627 | depends on XEN |
| 616 | select HVC_DRIVER | 628 | select HVC_DRIVER |
| 629 | select HVC_IRQ | ||
| 617 | default y | 630 | default y |
| 618 | help | 631 | help |
| 619 | Xen virtual console device driver | 632 | Xen virtual console device driver |
| 620 | 633 | ||
| 621 | config VIRTIO_CONSOLE | 634 | config VIRTIO_CONSOLE |
| 622 | bool | 635 | tristate "Virtio console" |
| 636 | depends on VIRTIO | ||
| 623 | select HVC_DRIVER | 637 | select HVC_DRIVER |
| 638 | help | ||
| 639 | Virtio console for use with lguest and other hypervisors. | ||
| 640 | |||
| 624 | 641 | ||
| 625 | config HVCS | 642 | config HVCS |
| 626 | tristate "IBM Hypervisor Virtual Console Server support" | 643 | tristate "IBM Hypervisor Virtual Console Server support" |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 4b6e736cfa02..8a161c30e1dc 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
| @@ -12,8 +12,8 @@ obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o | |||
| 12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
| 13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
| 14 | obj-y += misc.o | 14 | obj-y += misc.o |
| 15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ | 15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o |
| 16 | consolemap_deftbl.o selection.o keyboard.o | 16 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o |
| 17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o |
| 18 | obj-$(CONFIG_AUDIT) += tty_audit.o | 18 | obj-$(CONFIG_AUDIT) += tty_audit.o |
| 19 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 19 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o |
| @@ -48,6 +48,7 @@ obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | |||
| 48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o | 48 | obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o |
| 49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o | 49 | obj-$(CONFIG_HVC_BEAT) += hvc_beat.o |
| 50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o | 50 | obj-$(CONFIG_HVC_DRIVER) += hvc_console.o |
| 51 | obj-$(CONFIG_HVC_IRQ) += hvc_irq.o | ||
| 51 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o | 52 | obj-$(CONFIG_HVC_XEN) += hvc_xen.o |
| 52 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o | 53 | obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o |
| 53 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 54 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
| @@ -63,7 +64,6 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o | |||
| 63 | obj-$(CONFIG_BFIN_OTP) += bfin-otp.o | 64 | obj-$(CONFIG_BFIN_OTP) += bfin-otp.o |
| 64 | 65 | ||
| 65 | obj-$(CONFIG_PRINTER) += lp.o | 66 | obj-$(CONFIG_PRINTER) += lp.o |
| 66 | obj-$(CONFIG_TIPAR) += tipar.o | ||
| 67 | 67 | ||
| 68 | obj-$(CONFIG_APM_EMULATION) += apm-emulation.o | 68 | obj-$(CONFIG_APM_EMULATION) += apm-emulation.o |
| 69 | 69 | ||
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index fada6ddefbae..c5e67a623951 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c | |||
| @@ -20,10 +20,11 @@ | |||
| 20 | #include <linux/miscdevice.h> | 20 | #include <linux/miscdevice.h> |
| 21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 22 | #include <linux/bcd.h> | 22 | #include <linux/bcd.h> |
| 23 | #include <linux/smp_lock.h> | ||
| 24 | #include <linux/uaccess.h> | ||
| 25 | #include <linux/io.h> | ||
| 23 | 26 | ||
| 24 | #include <asm/uaccess.h> | ||
| 25 | #include <asm/system.h> | 27 | #include <asm/system.h> |
| 26 | #include <asm/io.h> | ||
| 27 | #include <asm/rtc.h> | 28 | #include <asm/rtc.h> |
| 28 | #if defined(CONFIG_M32R) | 29 | #if defined(CONFIG_M32R) |
| 29 | #include <asm/m32r.h> | 30 | #include <asm/m32r.h> |
| @@ -153,9 +154,7 @@ static unsigned char days_in_mo[] = | |||
| 153 | 154 | ||
| 154 | /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */ | 155 | /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */ |
| 155 | 156 | ||
| 156 | static int | 157 | static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 157 | rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
| 158 | unsigned long arg) | ||
| 159 | { | 158 | { |
| 160 | unsigned long flags; | 159 | unsigned long flags; |
| 161 | 160 | ||
| @@ -165,7 +164,9 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 165 | struct rtc_time rtc_tm; | 164 | struct rtc_time rtc_tm; |
| 166 | 165 | ||
| 167 | memset(&rtc_tm, 0, sizeof (struct rtc_time)); | 166 | memset(&rtc_tm, 0, sizeof (struct rtc_time)); |
| 167 | lock_kernel(); | ||
| 168 | get_rtc_time(&rtc_tm); | 168 | get_rtc_time(&rtc_tm); |
| 169 | unlock_kernel(); | ||
| 169 | if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) | 170 | if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) |
| 170 | return -EFAULT; | 171 | return -EFAULT; |
| 171 | return 0; | 172 | return 0; |
| @@ -217,6 +218,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 217 | BIN_TO_BCD(mon); | 218 | BIN_TO_BCD(mon); |
| 218 | BIN_TO_BCD(yrs); | 219 | BIN_TO_BCD(yrs); |
| 219 | 220 | ||
| 221 | lock_kernel(); | ||
| 220 | local_irq_save(flags); | 222 | local_irq_save(flags); |
| 221 | CMOS_WRITE(yrs, RTC_YEAR); | 223 | CMOS_WRITE(yrs, RTC_YEAR); |
| 222 | CMOS_WRITE(mon, RTC_MONTH); | 224 | CMOS_WRITE(mon, RTC_MONTH); |
| @@ -225,6 +227,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 225 | CMOS_WRITE(min, RTC_MINUTES); | 227 | CMOS_WRITE(min, RTC_MINUTES); |
| 226 | CMOS_WRITE(sec, RTC_SECONDS); | 228 | CMOS_WRITE(sec, RTC_SECONDS); |
| 227 | local_irq_restore(flags); | 229 | local_irq_restore(flags); |
| 230 | unlock_kernel(); | ||
| 228 | 231 | ||
| 229 | /* Notice that at this point, the RTC is updated but | 232 | /* Notice that at this point, the RTC is updated but |
| 230 | * the kernel is still running with the old time. | 233 | * the kernel is still running with the old time. |
| @@ -244,8 +247,10 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 244 | if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) | 247 | if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) |
| 245 | return -EFAULT; | 248 | return -EFAULT; |
| 246 | 249 | ||
| 250 | lock_kernel(); | ||
| 247 | tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); | 251 | tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); |
| 248 | ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); | 252 | ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); |
| 253 | unlock_kernel(); | ||
| 249 | return 0; | 254 | return 0; |
| 250 | } | 255 | } |
| 251 | default: | 256 | default: |
| @@ -282,7 +287,7 @@ get_rtc_status(char *buf) | |||
| 282 | 287 | ||
| 283 | static const struct file_operations rtc_fops = { | 288 | static const struct file_operations rtc_fops = { |
| 284 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
| 285 | .ioctl = rtc_ioctl, | 290 | .unlocked_ioctl = rtc_ioctl, |
| 286 | }; | 291 | }; |
| 287 | 292 | ||
| 288 | /* Probe for the chip by writing something to its RAM and try reading it back. */ | 293 | /* Probe for the chip by writing something to its RAM and try reading it back. */ |
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 33c466a4888f..19b88504e960 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c | |||
| @@ -36,10 +36,10 @@ | |||
| 36 | #include <linux/smp_lock.h> | 36 | #include <linux/smp_lock.h> |
| 37 | #include <linux/firmware.h> | 37 | #include <linux/firmware.h> |
| 38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
| 39 | #include <linux/uaccess.h> /* For put_user and get_user */ | ||
| 39 | 40 | ||
| 40 | #include <asm/atarihw.h> | 41 | #include <asm/atarihw.h> |
| 41 | #include <asm/traps.h> | 42 | #include <asm/traps.h> |
| 42 | #include <asm/uaccess.h> /* For put_user and get_user */ | ||
| 43 | 43 | ||
| 44 | #include <asm/dsp56k.h> | 44 | #include <asm/dsp56k.h> |
| 45 | 45 | ||
| @@ -303,8 +303,8 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co | |||
| 303 | } | 303 | } |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | static int dsp56k_ioctl(struct inode *inode, struct file *file, | 306 | static long dsp56k_ioctl(struct file *file, unsigned int cmd, |
| 307 | unsigned int cmd, unsigned long arg) | 307 | unsigned long arg) |
| 308 | { | 308 | { |
| 309 | int dev = iminor(inode) & 0x0f; | 309 | int dev = iminor(inode) & 0x0f; |
| 310 | void __user *argp = (void __user *)arg; | 310 | void __user *argp = (void __user *)arg; |
| @@ -331,8 +331,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
| 331 | if (len > DSP56K_MAX_BINARY_LENGTH) { | 331 | if (len > DSP56K_MAX_BINARY_LENGTH) { |
| 332 | return -EINVAL; | 332 | return -EINVAL; |
| 333 | } | 333 | } |
| 334 | 334 | lock_kernel(); | |
| 335 | r = dsp56k_upload(bin, len); | 335 | r = dsp56k_upload(bin, len); |
| 336 | unlock_kernel(); | ||
| 336 | if (r < 0) { | 337 | if (r < 0) { |
| 337 | return r; | 338 | return r; |
| 338 | } | 339 | } |
| @@ -342,12 +343,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
| 342 | case DSP56K_SET_TX_WSIZE: | 343 | case DSP56K_SET_TX_WSIZE: |
| 343 | if (arg > 4 || arg < 1) | 344 | if (arg > 4 || arg < 1) |
| 344 | return -EINVAL; | 345 | return -EINVAL; |
| 346 | lock_kernel(); | ||
| 345 | dsp56k.tx_wsize = (int) arg; | 347 | dsp56k.tx_wsize = (int) arg; |
| 348 | unlock_kernel(); | ||
| 346 | break; | 349 | break; |
| 347 | case DSP56K_SET_RX_WSIZE: | 350 | case DSP56K_SET_RX_WSIZE: |
| 348 | if (arg > 4 || arg < 1) | 351 | if (arg > 4 || arg < 1) |
| 349 | return -EINVAL; | 352 | return -EINVAL; |
| 353 | lock_kernel(); | ||
| 350 | dsp56k.rx_wsize = (int) arg; | 354 | dsp56k.rx_wsize = (int) arg; |
| 355 | unlock_kernel(); | ||
| 351 | break; | 356 | break; |
| 352 | case DSP56K_HOST_FLAGS: | 357 | case DSP56K_HOST_FLAGS: |
| 353 | { | 358 | { |
| @@ -359,6 +364,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
| 359 | if(get_user(out, &hf->out) < 0) | 364 | if(get_user(out, &hf->out) < 0) |
| 360 | return -EFAULT; | 365 | return -EFAULT; |
| 361 | 366 | ||
| 367 | lock_kernel(); | ||
| 362 | if ((dir & 0x1) && (out & 0x1)) | 368 | if ((dir & 0x1) && (out & 0x1)) |
| 363 | dsp56k_host_interface.icr |= DSP56K_ICR_HF0; | 369 | dsp56k_host_interface.icr |= DSP56K_ICR_HF0; |
| 364 | else if (dir & 0x1) | 370 | else if (dir & 0x1) |
| @@ -373,14 +379,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
| 373 | if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; | 379 | if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; |
| 374 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; | 380 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; |
| 375 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; | 381 | if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; |
| 376 | 382 | unlock_kernel(); | |
| 377 | return put_user(status, &hf->status); | 383 | return put_user(status, &hf->status); |
| 378 | } | 384 | } |
| 379 | case DSP56K_HOST_CMD: | 385 | case DSP56K_HOST_CMD: |
| 380 | if (arg > 31 || arg < 0) | 386 | if (arg > 31 || arg < 0) |
| 381 | return -EINVAL; | 387 | return -EINVAL; |
| 388 | lock_kernel(); | ||
| 382 | dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | | 389 | dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | |
| 383 | DSP56K_CVR_HC); | 390 | DSP56K_CVR_HC); |
| 391 | unlock_kernel(); | ||
| 384 | break; | 392 | break; |
| 385 | default: | 393 | default: |
| 386 | return -EINVAL; | 394 | return -EINVAL; |
| @@ -472,7 +480,7 @@ static const struct file_operations dsp56k_fops = { | |||
| 472 | .owner = THIS_MODULE, | 480 | .owner = THIS_MODULE, |
| 473 | .read = dsp56k_read, | 481 | .read = dsp56k_read, |
| 474 | .write = dsp56k_write, | 482 | .write = dsp56k_write, |
| 475 | .ioctl = dsp56k_ioctl, | 483 | .unlocked_ioctl = dsp56k_ioctl, |
| 476 | .open = dsp56k_open, | 484 | .open = dsp56k_open, |
| 477 | .release = dsp56k_release, | 485 | .release = dsp56k_release, |
| 478 | }; | 486 | }; |
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index d57ca3e4e534..67fbd7aab5db 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c | |||
| @@ -37,8 +37,9 @@ | |||
| 37 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
| 38 | #include <linux/proc_fs.h> | 38 | #include <linux/proc_fs.h> |
| 39 | #include <linux/efi.h> | 39 | #include <linux/efi.h> |
| 40 | #include <linux/smp_lock.h> | ||
| 41 | #include <linux/uaccess.h> | ||
| 40 | 42 | ||
| 41 | #include <asm/uaccess.h> | ||
| 42 | #include <asm/system.h> | 43 | #include <asm/system.h> |
| 43 | 44 | ||
| 44 | #define EFI_RTC_VERSION "0.4" | 45 | #define EFI_RTC_VERSION "0.4" |
| @@ -51,8 +52,8 @@ | |||
| 51 | 52 | ||
| 52 | static DEFINE_SPINLOCK(efi_rtc_lock); | 53 | static DEFINE_SPINLOCK(efi_rtc_lock); |
| 53 | 54 | ||
| 54 | static int efi_rtc_ioctl(struct inode *inode, struct file *file, | 55 | static long efi_rtc_ioctl(struct file *file, unsigned int cmd, |
| 55 | unsigned int cmd, unsigned long arg); | 56 | unsigned long arg); |
| 56 | 57 | ||
| 57 | #define is_leap(year) \ | 58 | #define is_leap(year) \ |
| 58 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | 59 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) |
| @@ -146,9 +147,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | |||
| 146 | } | 147 | } |
| 147 | } | 148 | } |
| 148 | 149 | ||
| 149 | static int | 150 | static long efi_rtc_ioctl(struct file *file, unsigned int cmd, |
| 150 | efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 151 | unsigned long arg) |
| 151 | unsigned long arg) | ||
| 152 | { | 152 | { |
| 153 | 153 | ||
| 154 | efi_status_t status; | 154 | efi_status_t status; |
| @@ -175,13 +175,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 175 | return -EINVAL; | 175 | return -EINVAL; |
| 176 | 176 | ||
| 177 | case RTC_RD_TIME: | 177 | case RTC_RD_TIME: |
| 178 | 178 | lock_kernel(); | |
| 179 | spin_lock_irqsave(&efi_rtc_lock, flags); | 179 | spin_lock_irqsave(&efi_rtc_lock, flags); |
| 180 | 180 | ||
| 181 | status = efi.get_time(&eft, &cap); | 181 | status = efi.get_time(&eft, &cap); |
| 182 | 182 | ||
| 183 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 183 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
| 184 | 184 | unlock_kernel(); | |
| 185 | if (status != EFI_SUCCESS) { | 185 | if (status != EFI_SUCCESS) { |
| 186 | /* should never happen */ | 186 | /* should never happen */ |
| 187 | printk(KERN_ERR "efitime: can't read time\n"); | 187 | printk(KERN_ERR "efitime: can't read time\n"); |
| @@ -203,11 +203,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 203 | 203 | ||
| 204 | convert_to_efi_time(&wtime, &eft); | 204 | convert_to_efi_time(&wtime, &eft); |
| 205 | 205 | ||
| 206 | lock_kernel(); | ||
| 206 | spin_lock_irqsave(&efi_rtc_lock, flags); | 207 | spin_lock_irqsave(&efi_rtc_lock, flags); |
| 207 | 208 | ||
| 208 | status = efi.set_time(&eft); | 209 | status = efi.set_time(&eft); |
| 209 | 210 | ||
| 210 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 211 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
| 212 | unlock_kernel(); | ||
| 211 | 213 | ||
| 212 | return status == EFI_SUCCESS ? 0 : -EINVAL; | 214 | return status == EFI_SUCCESS ? 0 : -EINVAL; |
| 213 | 215 | ||
| @@ -223,6 +225,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 223 | 225 | ||
| 224 | convert_to_efi_time(&wtime, &eft); | 226 | convert_to_efi_time(&wtime, &eft); |
| 225 | 227 | ||
| 228 | lock_kernel(); | ||
| 226 | spin_lock_irqsave(&efi_rtc_lock, flags); | 229 | spin_lock_irqsave(&efi_rtc_lock, flags); |
| 227 | /* | 230 | /* |
| 228 | * XXX Fixme: | 231 | * XXX Fixme: |
| @@ -233,16 +236,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 233 | status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); | 236 | status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); |
| 234 | 237 | ||
| 235 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 238 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
| 239 | unlock_kernel(); | ||
| 236 | 240 | ||
| 237 | return status == EFI_SUCCESS ? 0 : -EINVAL; | 241 | return status == EFI_SUCCESS ? 0 : -EINVAL; |
| 238 | 242 | ||
| 239 | case RTC_WKALM_RD: | 243 | case RTC_WKALM_RD: |
| 240 | 244 | ||
| 245 | lock_kernel(); | ||
| 241 | spin_lock_irqsave(&efi_rtc_lock, flags); | 246 | spin_lock_irqsave(&efi_rtc_lock, flags); |
| 242 | 247 | ||
| 243 | status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); | 248 | status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); |
| 244 | 249 | ||
| 245 | spin_unlock_irqrestore(&efi_rtc_lock,flags); | 250 | spin_unlock_irqrestore(&efi_rtc_lock,flags); |
| 251 | unlock_kernel(); | ||
| 246 | 252 | ||
| 247 | if (status != EFI_SUCCESS) return -EINVAL; | 253 | if (status != EFI_SUCCESS) return -EINVAL; |
| 248 | 254 | ||
| @@ -256,7 +262,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 256 | return copy_to_user(&ewp->time, &wtime, | 262 | return copy_to_user(&ewp->time, &wtime, |
| 257 | sizeof(struct rtc_time)) ? -EFAULT : 0; | 263 | sizeof(struct rtc_time)) ? -EFAULT : 0; |
| 258 | } | 264 | } |
| 259 | return -EINVAL; | 265 | return -ENOTTY; |
| 260 | } | 266 | } |
| 261 | 267 | ||
| 262 | /* | 268 | /* |
| @@ -265,8 +271,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 265 | * up things on a close. | 271 | * up things on a close. |
| 266 | */ | 272 | */ |
| 267 | 273 | ||
| 268 | static int | 274 | static int efi_rtc_open(struct inode *inode, struct file *file) |
| 269 | efi_rtc_open(struct inode *inode, struct file *file) | ||
| 270 | { | 275 | { |
| 271 | /* | 276 | /* |
| 272 | * nothing special to do here | 277 | * nothing special to do here |
| @@ -277,8 +282,7 @@ efi_rtc_open(struct inode *inode, struct file *file) | |||
| 277 | return 0; | 282 | return 0; |
| 278 | } | 283 | } |
| 279 | 284 | ||
| 280 | static int | 285 | static int efi_rtc_close(struct inode *inode, struct file *file) |
| 281 | efi_rtc_close(struct inode *inode, struct file *file) | ||
| 282 | { | 286 | { |
| 283 | return 0; | 287 | return 0; |
| 284 | } | 288 | } |
| @@ -289,13 +293,12 @@ efi_rtc_close(struct inode *inode, struct file *file) | |||
| 289 | 293 | ||
| 290 | static const struct file_operations efi_rtc_fops = { | 294 | static const struct file_operations efi_rtc_fops = { |
| 291 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
| 292 | .ioctl = efi_rtc_ioctl, | 296 | .unlocked_ioctl = efi_rtc_ioctl, |
| 293 | .open = efi_rtc_open, | 297 | .open = efi_rtc_open, |
| 294 | .release = efi_rtc_close, | 298 | .release = efi_rtc_close, |
| 295 | }; | 299 | }; |
| 296 | 300 | ||
| 297 | static struct miscdevice efi_rtc_dev= | 301 | static struct miscdevice efi_rtc_dev= { |
| 298 | { | ||
| 299 | EFI_RTC_MINOR, | 302 | EFI_RTC_MINOR, |
| 300 | "efirtc", | 303 | "efirtc", |
| 301 | &efi_rtc_fops | 304 | &efi_rtc_fops |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index fb0a85a1eb36..b3f5dbc6d880 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
| @@ -623,6 +623,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp) | |||
| 623 | return -ENXIO; | 623 | return -ENXIO; |
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | #if 0 | ||
| 626 | int hpet_unregister(struct hpet_task *tp) | 627 | int hpet_unregister(struct hpet_task *tp) |
| 627 | { | 628 | { |
| 628 | struct hpet_dev *devp; | 629 | struct hpet_dev *devp; |
| @@ -652,6 +653,7 @@ int hpet_unregister(struct hpet_task *tp) | |||
| 652 | 653 | ||
| 653 | return 0; | 654 | return 0; |
| 654 | } | 655 | } |
| 656 | #endif /* 0 */ | ||
| 655 | 657 | ||
| 656 | static ctl_table hpet_table[] = { | 658 | static ctl_table hpet_table[] = { |
| 657 | { | 659 | { |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2f9759d625cc..02aac104842d 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/kbd_kern.h> | 28 | #include <linux/kbd_kern.h> |
| 29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| 30 | #include <linux/kref.h> | ||
| 31 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
| 32 | #include <linux/list.h> | 31 | #include <linux/list.h> |
| 33 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| @@ -75,23 +74,6 @@ static int hvc_init(void); | |||
| 75 | static int sysrq_pressed; | 74 | static int sysrq_pressed; |
| 76 | #endif | 75 | #endif |
| 77 | 76 | ||
| 78 | struct hvc_struct { | ||
| 79 | spinlock_t lock; | ||
| 80 | int index; | ||
| 81 | struct tty_struct *tty; | ||
| 82 | unsigned int count; | ||
| 83 | int do_wakeup; | ||
| 84 | char *outbuf; | ||
| 85 | int outbuf_size; | ||
| 86 | int n_outbuf; | ||
| 87 | uint32_t vtermno; | ||
| 88 | struct hv_ops *ops; | ||
| 89 | int irq_requested; | ||
| 90 | int irq; | ||
| 91 | struct list_head next; | ||
| 92 | struct kref kref; /* ref count & hvc_struct lifetime */ | ||
| 93 | }; | ||
| 94 | |||
| 95 | /* dynamic list of hvc_struct instances */ | 77 | /* dynamic list of hvc_struct instances */ |
| 96 | static LIST_HEAD(hvc_structs); | 78 | static LIST_HEAD(hvc_structs); |
| 97 | 79 | ||
| @@ -298,27 +280,15 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) | |||
| 298 | 280 | ||
| 299 | return 0; | 281 | return 0; |
| 300 | } | 282 | } |
| 283 | EXPORT_SYMBOL_GPL(hvc_instantiate); | ||
| 301 | 284 | ||
| 302 | /* Wake the sleeping khvcd */ | 285 | /* Wake the sleeping khvcd */ |
| 303 | static void hvc_kick(void) | 286 | void hvc_kick(void) |
| 304 | { | 287 | { |
| 305 | hvc_kicked = 1; | 288 | hvc_kicked = 1; |
| 306 | wake_up_process(hvc_task); | 289 | wake_up_process(hvc_task); |
| 307 | } | 290 | } |
| 308 | 291 | EXPORT_SYMBOL_GPL(hvc_kick); | |
| 309 | static int hvc_poll(struct hvc_struct *hp); | ||
| 310 | |||
| 311 | /* | ||
| 312 | * NOTE: This API isn't used if the console adapter doesn't support interrupts. | ||
| 313 | * In this case the console is poll driven. | ||
| 314 | */ | ||
| 315 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) | ||
| 316 | { | ||
| 317 | /* if hvc_poll request a repoll, then kick the hvcd thread */ | ||
| 318 | if (hvc_poll(dev_instance)) | ||
| 319 | hvc_kick(); | ||
| 320 | return IRQ_HANDLED; | ||
| 321 | } | ||
| 322 | 292 | ||
| 323 | static void hvc_unthrottle(struct tty_struct *tty) | 293 | static void hvc_unthrottle(struct tty_struct *tty) |
| 324 | { | 294 | { |
| @@ -333,7 +303,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
| 333 | { | 303 | { |
| 334 | struct hvc_struct *hp; | 304 | struct hvc_struct *hp; |
| 335 | unsigned long flags; | 305 | unsigned long flags; |
| 336 | int irq = 0; | ||
| 337 | int rc = 0; | 306 | int rc = 0; |
| 338 | 307 | ||
| 339 | /* Auto increments kref reference if found. */ | 308 | /* Auto increments kref reference if found. */ |
| @@ -352,18 +321,15 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
| 352 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ | 321 | tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ |
| 353 | 322 | ||
| 354 | hp->tty = tty; | 323 | hp->tty = tty; |
| 355 | /* Save for request_irq outside of spin_lock. */ | 324 | |
| 356 | irq = hp->irq; | 325 | if (hp->ops->notifier_add) |
| 357 | if (irq) | 326 | rc = hp->ops->notifier_add(hp, hp->data); |
| 358 | hp->irq_requested = 1; | ||
| 359 | 327 | ||
| 360 | spin_unlock_irqrestore(&hp->lock, flags); | 328 | spin_unlock_irqrestore(&hp->lock, flags); |
| 361 | /* check error, fallback to non-irq */ | 329 | |
| 362 | if (irq) | ||
| 363 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp); | ||
| 364 | 330 | ||
| 365 | /* | 331 | /* |
| 366 | * If the request_irq() fails and we return an error. The tty layer | 332 | * If the notifier fails we return an error. The tty layer |
| 367 | * will call hvc_close() after a failed open but we don't want to clean | 333 | * will call hvc_close() after a failed open but we don't want to clean |
| 368 | * up there so we'll clean up here and clear out the previously set | 334 | * up there so we'll clean up here and clear out the previously set |
| 369 | * tty fields and return the kref reference. | 335 | * tty fields and return the kref reference. |
| @@ -371,7 +337,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
| 371 | if (rc) { | 337 | if (rc) { |
| 372 | spin_lock_irqsave(&hp->lock, flags); | 338 | spin_lock_irqsave(&hp->lock, flags); |
| 373 | hp->tty = NULL; | 339 | hp->tty = NULL; |
| 374 | hp->irq_requested = 0; | ||
| 375 | spin_unlock_irqrestore(&hp->lock, flags); | 340 | spin_unlock_irqrestore(&hp->lock, flags); |
| 376 | tty->driver_data = NULL; | 341 | tty->driver_data = NULL; |
| 377 | kref_put(&hp->kref, destroy_hvc_struct); | 342 | kref_put(&hp->kref, destroy_hvc_struct); |
| @@ -386,7 +351,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) | |||
| 386 | static void hvc_close(struct tty_struct *tty, struct file * filp) | 351 | static void hvc_close(struct tty_struct *tty, struct file * filp) |
| 387 | { | 352 | { |
| 388 | struct hvc_struct *hp; | 353 | struct hvc_struct *hp; |
| 389 | int irq = 0; | ||
| 390 | unsigned long flags; | 354 | unsigned long flags; |
| 391 | 355 | ||
| 392 | if (tty_hung_up_p(filp)) | 356 | if (tty_hung_up_p(filp)) |
| @@ -404,9 +368,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
| 404 | spin_lock_irqsave(&hp->lock, flags); | 368 | spin_lock_irqsave(&hp->lock, flags); |
| 405 | 369 | ||
| 406 | if (--hp->count == 0) { | 370 | if (--hp->count == 0) { |
| 407 | if (hp->irq_requested) | 371 | if (hp->ops->notifier_del) |
| 408 | irq = hp->irq; | 372 | hp->ops->notifier_del(hp, hp->data); |
| 409 | hp->irq_requested = 0; | ||
| 410 | 373 | ||
| 411 | /* We are done with the tty pointer now. */ | 374 | /* We are done with the tty pointer now. */ |
| 412 | hp->tty = NULL; | 375 | hp->tty = NULL; |
| @@ -418,10 +381,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
| 418 | * waking periodically to check chars_in_buffer(). | 381 | * waking periodically to check chars_in_buffer(). |
| 419 | */ | 382 | */ |
| 420 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); | 383 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); |
| 421 | |||
| 422 | if (irq) | ||
| 423 | free_irq(irq, hp); | ||
| 424 | |||
| 425 | } else { | 384 | } else { |
| 426 | if (hp->count < 0) | 385 | if (hp->count < 0) |
| 427 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", | 386 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", |
| @@ -436,7 +395,6 @@ static void hvc_hangup(struct tty_struct *tty) | |||
| 436 | { | 395 | { |
| 437 | struct hvc_struct *hp = tty->driver_data; | 396 | struct hvc_struct *hp = tty->driver_data; |
| 438 | unsigned long flags; | 397 | unsigned long flags; |
| 439 | int irq = 0; | ||
| 440 | int temp_open_count; | 398 | int temp_open_count; |
| 441 | 399 | ||
| 442 | if (!hp) | 400 | if (!hp) |
| @@ -458,13 +416,12 @@ static void hvc_hangup(struct tty_struct *tty) | |||
| 458 | hp->count = 0; | 416 | hp->count = 0; |
| 459 | hp->n_outbuf = 0; | 417 | hp->n_outbuf = 0; |
| 460 | hp->tty = NULL; | 418 | hp->tty = NULL; |
| 461 | if (hp->irq_requested) | 419 | |
| 462 | /* Saved for use outside of spin_lock. */ | 420 | if (hp->ops->notifier_del) |
| 463 | irq = hp->irq; | 421 | hp->ops->notifier_del(hp, hp->data); |
| 464 | hp->irq_requested = 0; | 422 | |
| 465 | spin_unlock_irqrestore(&hp->lock, flags); | 423 | spin_unlock_irqrestore(&hp->lock, flags); |
| 466 | if (irq) | 424 | |
| 467 | free_irq(irq, hp); | ||
| 468 | while(temp_open_count) { | 425 | while(temp_open_count) { |
| 469 | --temp_open_count; | 426 | --temp_open_count; |
| 470 | kref_put(&hp->kref, destroy_hvc_struct); | 427 | kref_put(&hp->kref, destroy_hvc_struct); |
| @@ -575,7 +532,7 @@ static u32 timeout = MIN_TIMEOUT; | |||
| 575 | #define HVC_POLL_READ 0x00000001 | 532 | #define HVC_POLL_READ 0x00000001 |
| 576 | #define HVC_POLL_WRITE 0x00000002 | 533 | #define HVC_POLL_WRITE 0x00000002 |
| 577 | 534 | ||
| 578 | static int hvc_poll(struct hvc_struct *hp) | 535 | int hvc_poll(struct hvc_struct *hp) |
| 579 | { | 536 | { |
| 580 | struct tty_struct *tty; | 537 | struct tty_struct *tty; |
| 581 | int i, n, poll_mask = 0; | 538 | int i, n, poll_mask = 0; |
| @@ -602,10 +559,10 @@ static int hvc_poll(struct hvc_struct *hp) | |||
| 602 | if (test_bit(TTY_THROTTLED, &tty->flags)) | 559 | if (test_bit(TTY_THROTTLED, &tty->flags)) |
| 603 | goto throttled; | 560 | goto throttled; |
| 604 | 561 | ||
| 605 | /* If we aren't interrupt driven and aren't throttled, we always | 562 | /* If we aren't notifier driven and aren't throttled, we always |
| 606 | * request a reschedule | 563 | * request a reschedule |
| 607 | */ | 564 | */ |
| 608 | if (hp->irq == 0) | 565 | if (!hp->irq_requested) |
| 609 | poll_mask |= HVC_POLL_READ; | 566 | poll_mask |= HVC_POLL_READ; |
| 610 | 567 | ||
| 611 | /* Read data if any */ | 568 | /* Read data if any */ |
| @@ -674,6 +631,7 @@ static int hvc_poll(struct hvc_struct *hp) | |||
| 674 | 631 | ||
| 675 | return poll_mask; | 632 | return poll_mask; |
| 676 | } | 633 | } |
| 634 | EXPORT_SYMBOL_GPL(hvc_poll); | ||
| 677 | 635 | ||
| 678 | /* | 636 | /* |
| 679 | * This kthread is either polling or interrupt driven. This is determined by | 637 | * This kthread is either polling or interrupt driven. This is determined by |
| @@ -733,7 +691,7 @@ static const struct tty_operations hvc_ops = { | |||
| 733 | .chars_in_buffer = hvc_chars_in_buffer, | 691 | .chars_in_buffer = hvc_chars_in_buffer, |
| 734 | }; | 692 | }; |
| 735 | 693 | ||
| 736 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | 694 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, |
| 737 | struct hv_ops *ops, int outbuf_size) | 695 | struct hv_ops *ops, int outbuf_size) |
| 738 | { | 696 | { |
| 739 | struct hvc_struct *hp; | 697 | struct hvc_struct *hp; |
| @@ -754,7 +712,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
| 754 | memset(hp, 0x00, sizeof(*hp)); | 712 | memset(hp, 0x00, sizeof(*hp)); |
| 755 | 713 | ||
| 756 | hp->vtermno = vtermno; | 714 | hp->vtermno = vtermno; |
| 757 | hp->irq = irq; | 715 | hp->data = data; |
| 758 | hp->ops = ops; | 716 | hp->ops = ops; |
| 759 | hp->outbuf_size = outbuf_size; | 717 | hp->outbuf_size = outbuf_size; |
| 760 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; | 718 | hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; |
| @@ -784,6 +742,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, | |||
| 784 | 742 | ||
| 785 | return hp; | 743 | return hp; |
| 786 | } | 744 | } |
| 745 | EXPORT_SYMBOL_GPL(hvc_alloc); | ||
| 787 | 746 | ||
| 788 | int __devexit hvc_remove(struct hvc_struct *hp) | 747 | int __devexit hvc_remove(struct hvc_struct *hp) |
| 789 | { | 748 | { |
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 42ffb17e15df..d9ce10915625 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #ifndef HVC_CONSOLE_H | 27 | #ifndef HVC_CONSOLE_H |
| 28 | #define HVC_CONSOLE_H | 28 | #define HVC_CONSOLE_H |
| 29 | #include <linux/kref.h> | ||
| 29 | 30 | ||
| 30 | /* | 31 | /* |
| 31 | * This is the max number of console adapters that can/will be found as | 32 | * This is the max number of console adapters that can/will be found as |
| @@ -42,24 +43,50 @@ | |||
| 42 | */ | 43 | */ |
| 43 | #define HVC_ALLOC_TTY_ADAPTERS 8 | 44 | #define HVC_ALLOC_TTY_ADAPTERS 8 |
| 44 | 45 | ||
| 46 | struct hvc_struct { | ||
| 47 | spinlock_t lock; | ||
| 48 | int index; | ||
| 49 | struct tty_struct *tty; | ||
| 50 | unsigned int count; | ||
| 51 | int do_wakeup; | ||
| 52 | char *outbuf; | ||
| 53 | int outbuf_size; | ||
| 54 | int n_outbuf; | ||
| 55 | uint32_t vtermno; | ||
| 56 | struct hv_ops *ops; | ||
| 57 | int irq_requested; | ||
| 58 | int data; | ||
| 59 | struct list_head next; | ||
| 60 | struct kref kref; /* ref count & hvc_struct lifetime */ | ||
| 61 | }; | ||
| 45 | 62 | ||
| 46 | /* implemented by a low level driver */ | 63 | /* implemented by a low level driver */ |
| 47 | struct hv_ops { | 64 | struct hv_ops { |
| 48 | int (*get_chars)(uint32_t vtermno, char *buf, int count); | 65 | int (*get_chars)(uint32_t vtermno, char *buf, int count); |
| 49 | int (*put_chars)(uint32_t vtermno, const char *buf, int count); | 66 | int (*put_chars)(uint32_t vtermno, const char *buf, int count); |
| 50 | }; | ||
| 51 | 67 | ||
| 52 | struct hvc_struct; | 68 | /* Callbacks for notification. Called in open and close */ |
| 69 | int (*notifier_add)(struct hvc_struct *hp, int irq); | ||
| 70 | void (*notifier_del)(struct hvc_struct *hp, int irq); | ||
| 71 | }; | ||
| 53 | 72 | ||
| 54 | /* Register a vterm and a slot index for use as a console (console_init) */ | 73 | /* Register a vterm and a slot index for use as a console (console_init) */ |
| 55 | extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); | 74 | extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); |
| 56 | 75 | ||
| 57 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ | 76 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ |
| 58 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, | 77 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, |
| 59 | struct hv_ops *ops, int outbuf_size); | 78 | struct hv_ops *ops, int outbuf_size); |
| 60 | /* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ | 79 | /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ |
| 61 | extern int __devexit hvc_remove(struct hvc_struct *hp); | 80 | extern int __devexit hvc_remove(struct hvc_struct *hp); |
| 62 | 81 | ||
| 82 | /* data available */ | ||
| 83 | int hvc_poll(struct hvc_struct *hp); | ||
| 84 | void hvc_kick(void); | ||
| 85 | |||
| 86 | /* default notifier for irq based notification */ | ||
| 87 | extern int notifier_add_irq(struct hvc_struct *hp, int data); | ||
| 88 | extern void notifier_del_irq(struct hvc_struct *hp, int data); | ||
| 89 | |||
| 63 | 90 | ||
| 64 | #if defined(CONFIG_XMON) && defined(CONFIG_SMP) | 91 | #if defined(CONFIG_XMON) && defined(CONFIG_SMP) |
| 65 | #include <asm/xmon.h> | 92 | #include <asm/xmon.h> |
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c new file mode 100644 index 000000000000..73a59cdb8947 --- /dev/null +++ b/drivers/char/hvc_irq.c | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* | ||
| 2 | * Copyright IBM Corp. 2001,2008 | ||
| 3 | * | ||
| 4 | * This file contains the IRQ specific code for hvc_console | ||
| 5 | * | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/interrupt.h> | ||
| 9 | |||
| 10 | #include "hvc_console.h" | ||
| 11 | |||
| 12 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) | ||
| 13 | { | ||
| 14 | /* if hvc_poll request a repoll, then kick the hvcd thread */ | ||
| 15 | if (hvc_poll(dev_instance)) | ||
| 16 | hvc_kick(); | ||
| 17 | return IRQ_HANDLED; | ||
| 18 | } | ||
| 19 | |||
| 20 | /* | ||
| 21 | * For IRQ based systems these callbacks can be used | ||
| 22 | */ | ||
| 23 | int notifier_add_irq(struct hvc_struct *hp, int irq) | ||
| 24 | { | ||
| 25 | int rc; | ||
| 26 | |||
| 27 | if (!irq) { | ||
| 28 | hp->irq_requested = 0; | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, | ||
| 32 | "hvc_console", hp); | ||
| 33 | if (!rc) | ||
| 34 | hp->irq_requested = 1; | ||
| 35 | return rc; | ||
| 36 | } | ||
| 37 | |||
| 38 | void notifier_del_irq(struct hvc_struct *hp, int irq) | ||
| 39 | { | ||
| 40 | if (!irq) | ||
| 41 | return; | ||
| 42 | free_irq(irq, hp); | ||
| 43 | hp->irq_requested = 0; | ||
| 44 | } | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index a08f8f981c11..b71c610fe5ae 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
| @@ -200,6 +200,8 @@ done: | |||
| 200 | static struct hv_ops hvc_get_put_ops = { | 200 | static struct hv_ops hvc_get_put_ops = { |
| 201 | .get_chars = get_chars, | 201 | .get_chars = get_chars, |
| 202 | .put_chars = put_chars, | 202 | .put_chars = put_chars, |
| 203 | .notifier_add = notifier_add_irq, | ||
| 204 | .notifier_del = notifier_del_irq, | ||
| 203 | }; | 205 | }; |
| 204 | 206 | ||
| 205 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, | 207 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, |
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 79711aa4b41d..93f3840c1682 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c | |||
| @@ -80,6 +80,8 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) | |||
| 80 | static struct hv_ops hvc_get_put_ops = { | 80 | static struct hv_ops hvc_get_put_ops = { |
| 81 | .get_chars = filtered_get_chars, | 81 | .get_chars = filtered_get_chars, |
| 82 | .put_chars = hvc_put_chars, | 82 | .put_chars = hvc_put_chars, |
| 83 | .notifier_add = notifier_add_irq, | ||
| 84 | .notifier_del = notifier_del_irq, | ||
| 83 | }; | 85 | }; |
| 84 | 86 | ||
| 85 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, | 87 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, |
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c index db2ae4216279..6b70aa66a587 100644 --- a/drivers/char/hvc_xen.c +++ b/drivers/char/hvc_xen.c | |||
| @@ -100,6 +100,8 @@ static int read_console(uint32_t vtermno, char *buf, int len) | |||
| 100 | static struct hv_ops hvc_ops = { | 100 | static struct hv_ops hvc_ops = { |
| 101 | .get_chars = read_console, | 101 | .get_chars = read_console, |
| 102 | .put_chars = write_console, | 102 | .put_chars = write_console, |
| 103 | .notifier_add = notifier_add_irq, | ||
| 104 | .notifier_del = notifier_del_irq, | ||
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| 105 | static int __init xen_init(void) | 107 | static int __init xen_init(void) |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 9cb48fcd316c..689f9dcd3b86 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
| @@ -203,7 +203,7 @@ static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); | |||
| 203 | 203 | ||
| 204 | static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); | 204 | static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); |
| 205 | static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); | 205 | static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); |
| 206 | static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG); | 206 | static long ip2_ipl_ioctl(struct file *, UINT, ULONG); |
| 207 | static int ip2_ipl_open(struct inode *, struct file *); | 207 | static int ip2_ipl_open(struct inode *, struct file *); |
| 208 | 208 | ||
| 209 | static int DumpTraceBuffer(char __user *, int); | 209 | static int DumpTraceBuffer(char __user *, int); |
| @@ -236,7 +236,7 @@ static const struct file_operations ip2_ipl = { | |||
| 236 | .owner = THIS_MODULE, | 236 | .owner = THIS_MODULE, |
| 237 | .read = ip2_ipl_read, | 237 | .read = ip2_ipl_read, |
| 238 | .write = ip2_ipl_write, | 238 | .write = ip2_ipl_write, |
| 239 | .ioctl = ip2_ipl_ioctl, | 239 | .unlocked_ioctl = ip2_ipl_ioctl, |
| 240 | .open = ip2_ipl_open, | 240 | .open = ip2_ipl_open, |
| 241 | }; | 241 | }; |
| 242 | 242 | ||
| @@ -2845,10 +2845,10 @@ ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t | |||
| 2845 | /* */ | 2845 | /* */ |
| 2846 | /* */ | 2846 | /* */ |
| 2847 | /******************************************************************************/ | 2847 | /******************************************************************************/ |
| 2848 | static int | 2848 | static long |
| 2849 | ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) | 2849 | ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) |
| 2850 | { | 2850 | { |
| 2851 | unsigned int iplminor = iminor(pInode); | 2851 | unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); |
| 2852 | int rc = 0; | 2852 | int rc = 0; |
| 2853 | void __user *argp = (void __user *)arg; | 2853 | void __user *argp = (void __user *)arg; |
| 2854 | ULONG __user *pIndex = argp; | 2854 | ULONG __user *pIndex = argp; |
| @@ -2859,6 +2859,8 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) | |||
| 2859 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); | 2859 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); |
| 2860 | #endif | 2860 | #endif |
| 2861 | 2861 | ||
| 2862 | lock_kernel(); | ||
| 2863 | |||
| 2862 | switch ( iplminor ) { | 2864 | switch ( iplminor ) { |
| 2863 | case 0: // IPL device | 2865 | case 0: // IPL device |
| 2864 | rc = -EINVAL; | 2866 | rc = -EINVAL; |
| @@ -2919,6 +2921,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) | |||
| 2919 | rc = -ENODEV; | 2921 | rc = -ENODEV; |
| 2920 | break; | 2922 | break; |
| 2921 | } | 2923 | } |
| 2924 | unlock_kernel(); | ||
| 2922 | return rc; | 2925 | return rc; |
| 2923 | } | 2926 | } |
| 2924 | 2927 | ||
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 50243fcd87e8..4f8d67fed292 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
| @@ -86,8 +86,8 @@ module_param(mwave_uart_io, int, 0); | |||
| 86 | 86 | ||
| 87 | static int mwave_open(struct inode *inode, struct file *file); | 87 | static int mwave_open(struct inode *inode, struct file *file); |
| 88 | static int mwave_close(struct inode *inode, struct file *file); | 88 | static int mwave_close(struct inode *inode, struct file *file); |
| 89 | static int mwave_ioctl(struct inode *inode, struct file *filp, | 89 | static long mwave_ioctl(struct file *filp, unsigned int iocmd, |
| 90 | unsigned int iocmd, unsigned long ioarg); | 90 | unsigned long ioarg); |
| 91 | 91 | ||
| 92 | MWAVE_DEVICE_DATA mwave_s_mdd; | 92 | MWAVE_DEVICE_DATA mwave_s_mdd; |
| 93 | 93 | ||
| @@ -119,16 +119,16 @@ static int mwave_close(struct inode *inode, struct file *file) | |||
| 119 | return retval; | 119 | return retval; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static int mwave_ioctl(struct inode *inode, struct file *file, | 122 | static long mwave_ioctl(struct file *file, unsigned int iocmd, |
| 123 | unsigned int iocmd, unsigned long ioarg) | 123 | unsigned long ioarg) |
| 124 | { | 124 | { |
| 125 | unsigned int retval = 0; | 125 | unsigned int retval = 0; |
| 126 | pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; | 126 | pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; |
| 127 | void __user *arg = (void __user *)ioarg; | 127 | void __user *arg = (void __user *)ioarg; |
| 128 | 128 | ||
| 129 | PRINTK_5(TRACE_MWAVE, | 129 | PRINTK_4(TRACE_MWAVE, |
| 130 | "mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n", | 130 | "mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n", |
| 131 | inode, file, iocmd, (int) ioarg); | 131 | file, iocmd, (int) ioarg); |
| 132 | 132 | ||
| 133 | switch (iocmd) { | 133 | switch (iocmd) { |
| 134 | 134 | ||
| @@ -136,7 +136,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 136 | PRINTK_1(TRACE_MWAVE, | 136 | PRINTK_1(TRACE_MWAVE, |
| 137 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | 137 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" |
| 138 | " calling tp3780I_ResetDSP\n"); | 138 | " calling tp3780I_ResetDSP\n"); |
| 139 | lock_kernel(); | ||
| 139 | retval = tp3780I_ResetDSP(&pDrvData->rBDData); | 140 | retval = tp3780I_ResetDSP(&pDrvData->rBDData); |
| 141 | unlock_kernel(); | ||
| 140 | PRINTK_2(TRACE_MWAVE, | 142 | PRINTK_2(TRACE_MWAVE, |
| 141 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | 143 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" |
| 142 | " retval %x from tp3780I_ResetDSP\n", | 144 | " retval %x from tp3780I_ResetDSP\n", |
| @@ -147,7 +149,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 147 | PRINTK_1(TRACE_MWAVE, | 149 | PRINTK_1(TRACE_MWAVE, |
| 148 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | 150 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" |
| 149 | " calling tp3780I_StartDSP\n"); | 151 | " calling tp3780I_StartDSP\n"); |
| 152 | lock_kernel(); | ||
| 150 | retval = tp3780I_StartDSP(&pDrvData->rBDData); | 153 | retval = tp3780I_StartDSP(&pDrvData->rBDData); |
| 154 | unlock_kernel(); | ||
| 151 | PRINTK_2(TRACE_MWAVE, | 155 | PRINTK_2(TRACE_MWAVE, |
| 152 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | 156 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" |
| 153 | " retval %x from tp3780I_StartDSP\n", | 157 | " retval %x from tp3780I_StartDSP\n", |
| @@ -161,8 +165,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 161 | "mwavedd::mwave_ioctl," | 165 | "mwavedd::mwave_ioctl," |
| 162 | " IOCTL_MW_DSP_ABILITIES calling" | 166 | " IOCTL_MW_DSP_ABILITIES calling" |
| 163 | " tp3780I_QueryAbilities\n"); | 167 | " tp3780I_QueryAbilities\n"); |
| 168 | lock_kernel(); | ||
| 164 | retval = tp3780I_QueryAbilities(&pDrvData->rBDData, | 169 | retval = tp3780I_QueryAbilities(&pDrvData->rBDData, |
| 165 | &rAbilities); | 170 | &rAbilities); |
| 171 | unlock_kernel(); | ||
| 166 | PRINTK_2(TRACE_MWAVE, | 172 | PRINTK_2(TRACE_MWAVE, |
| 167 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" | 173 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" |
| 168 | " retval %x from tp3780I_QueryAbilities\n", | 174 | " retval %x from tp3780I_QueryAbilities\n", |
| @@ -193,11 +199,13 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 193 | "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," | 199 | "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," |
| 194 | " size %lx, ioarg %lx pusBuffer %p\n", | 200 | " size %lx, ioarg %lx pusBuffer %p\n", |
| 195 | rReadData.ulDataLength, ioarg, pusBuffer); | 201 | rReadData.ulDataLength, ioarg, pusBuffer); |
| 202 | lock_kernel(); | ||
| 196 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 203 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
| 197 | iocmd, | 204 | iocmd, |
| 198 | pusBuffer, | 205 | pusBuffer, |
| 199 | rReadData.ulDataLength, | 206 | rReadData.ulDataLength, |
| 200 | rReadData.usDspAddress); | 207 | rReadData.usDspAddress); |
| 208 | unlock_kernel(); | ||
| 201 | } | 209 | } |
| 202 | break; | 210 | break; |
| 203 | 211 | ||
| @@ -215,10 +223,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 215 | " size %lx, ioarg %lx pusBuffer %p\n", | 223 | " size %lx, ioarg %lx pusBuffer %p\n", |
| 216 | rReadData.ulDataLength / 2, ioarg, | 224 | rReadData.ulDataLength / 2, ioarg, |
| 217 | pusBuffer); | 225 | pusBuffer); |
| 226 | lock_kernel(); | ||
| 218 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 227 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
| 219 | iocmd, pusBuffer, | 228 | iocmd, pusBuffer, |
| 220 | rReadData.ulDataLength / 2, | 229 | rReadData.ulDataLength / 2, |
| 221 | rReadData.usDspAddress); | 230 | rReadData.usDspAddress); |
| 231 | unlock_kernel(); | ||
| 222 | } | 232 | } |
| 223 | break; | 233 | break; |
| 224 | 234 | ||
| @@ -236,10 +246,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 236 | " size %lx, ioarg %lx pusBuffer %p\n", | 246 | " size %lx, ioarg %lx pusBuffer %p\n", |
| 237 | rWriteData.ulDataLength, ioarg, | 247 | rWriteData.ulDataLength, ioarg, |
| 238 | pusBuffer); | 248 | pusBuffer); |
| 249 | lock_kernel(); | ||
| 239 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | 250 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, |
| 240 | iocmd, pusBuffer, | 251 | iocmd, pusBuffer, |
| 241 | rWriteData.ulDataLength, | 252 | rWriteData.ulDataLength, |
| 242 | rWriteData.usDspAddress); | 253 | rWriteData.usDspAddress); |
| 254 | unlock_kernel(); | ||
| 243 | } | 255 | } |
| 244 | break; | 256 | break; |
| 245 | 257 | ||
| @@ -257,10 +269,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 257 | " size %lx, ioarg %lx pusBuffer %p\n", | 269 | " size %lx, ioarg %lx pusBuffer %p\n", |
| 258 | rWriteData.ulDataLength, ioarg, | 270 | rWriteData.ulDataLength, ioarg, |
| 259 | pusBuffer); | 271 | pusBuffer); |
| 272 | lock_kernel(); | ||
| 260 | retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, | 273 | retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, |
| 261 | iocmd, pusBuffer, | 274 | iocmd, pusBuffer, |
| 262 | rWriteData.ulDataLength, | 275 | rWriteData.ulDataLength, |
| 263 | rWriteData.usDspAddress); | 276 | rWriteData.usDspAddress); |
| 277 | unlock_kernel(); | ||
| 264 | } | 278 | } |
| 265 | break; | 279 | break; |
| 266 | 280 | ||
| @@ -281,8 +295,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 281 | ipcnum); | 295 | ipcnum); |
| 282 | return -EINVAL; | 296 | return -EINVAL; |
| 283 | } | 297 | } |
| 298 | lock_kernel(); | ||
| 284 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; | 299 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; |
| 285 | pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; | 300 | pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; |
| 301 | unlock_kernel(); | ||
| 286 | 302 | ||
| 287 | PRINTK_2(TRACE_MWAVE, | 303 | PRINTK_2(TRACE_MWAVE, |
| 288 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" | 304 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" |
| @@ -307,6 +323,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 307 | return -EINVAL; | 323 | return -EINVAL; |
| 308 | } | 324 | } |
| 309 | 325 | ||
| 326 | lock_kernel(); | ||
| 310 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | 327 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { |
| 311 | DECLARE_WAITQUEUE(wait, current); | 328 | DECLARE_WAITQUEUE(wait, current); |
| 312 | 329 | ||
| @@ -347,6 +364,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 347 | " processing\n", | 364 | " processing\n", |
| 348 | ipcnum); | 365 | ipcnum); |
| 349 | } | 366 | } |
| 367 | unlock_kernel(); | ||
| 350 | } | 368 | } |
| 351 | break; | 369 | break; |
| 352 | 370 | ||
| @@ -365,19 +383,18 @@ static int mwave_ioctl(struct inode *inode, struct file *file, | |||
| 365 | ipcnum); | 383 | ipcnum); |
| 366 | return -EINVAL; | 384 | return -EINVAL; |
| 367 | } | 385 | } |
| 386 | lock_kernel(); | ||
| 368 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | 387 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { |
| 369 | pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; | 388 | pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; |
| 370 | if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { | 389 | if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { |
| 371 | wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); | 390 | wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); |
| 372 | } | 391 | } |
| 373 | } | 392 | } |
| 393 | unlock_kernel(); | ||
| 374 | } | 394 | } |
| 375 | break; | 395 | break; |
| 376 | 396 | ||
| 377 | default: | 397 | default: |
| 378 | PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:" | ||
| 379 | " Error: Unrecognized iocmd %x\n", | ||
| 380 | iocmd); | ||
| 381 | return -ENOTTY; | 398 | return -ENOTTY; |
| 382 | break; | 399 | break; |
| 383 | } /* switch */ | 400 | } /* switch */ |
| @@ -460,7 +477,7 @@ static const struct file_operations mwave_fops = { | |||
| 460 | .owner = THIS_MODULE, | 477 | .owner = THIS_MODULE, |
| 461 | .read = mwave_read, | 478 | .read = mwave_read, |
| 462 | .write = mwave_write, | 479 | .write = mwave_write, |
| 463 | .ioctl = mwave_ioctl, | 480 | .unlocked_ioctl = mwave_ioctl, |
| 464 | .open = mwave_open, | 481 | .open = mwave_open, |
| 465 | .release = mwave_close | 482 | .release = mwave_close |
| 466 | }; | 483 | }; |
diff --git a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h index 8eca61e0a19c..7e0d530e2e07 100644 --- a/drivers/char/mwave/mwavedd.h +++ b/drivers/char/mwave/mwavedd.h | |||
| @@ -147,4 +147,6 @@ typedef struct _MWAVE_DEVICE_DATA { | |||
| 147 | 147 | ||
| 148 | } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA; | 148 | } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA; |
| 149 | 149 | ||
| 150 | extern MWAVE_DEVICE_DATA mwave_s_mdd; | ||
| 151 | |||
| 150 | #endif | 152 | #endif |
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index f282976daaac..c68969708068 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c | |||
| @@ -57,8 +57,6 @@ | |||
| 57 | #include "3780i.h" | 57 | #include "3780i.h" |
| 58 | #include "mwavepub.h" | 58 | #include "mwavepub.h" |
| 59 | 59 | ||
| 60 | extern MWAVE_DEVICE_DATA mwave_s_mdd; | ||
| 61 | |||
| 62 | static unsigned short s_ausThinkpadIrqToField[16] = | 60 | static unsigned short s_ausThinkpadIrqToField[16] = |
| 63 | { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004, | 61 | { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004, |
| 64 | 0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 }; | 62 | 0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 }; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 4c756bbba948..e30575e87648 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox | 16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox |
| 17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. | 17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. |
| 18 | * - Fixed x86_64 cleanness | 18 | * - Fixed x86_64 cleanness |
| 19 | * - Fixed sleep with spinlock held in mxser_send_break | ||
| 20 | */ | 19 | */ |
| 21 | 20 | ||
| 22 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| @@ -49,18 +48,12 @@ | |||
| 49 | 48 | ||
| 50 | #define MXSER_VERSION "2.0.4" /* 1.12 */ | 49 | #define MXSER_VERSION "2.0.4" /* 1.12 */ |
| 51 | #define MXSERMAJOR 174 | 50 | #define MXSERMAJOR 174 |
| 52 | #define MXSERCUMAJOR 175 | ||
| 53 | 51 | ||
| 54 | #define MXSER_BOARDS 4 /* Max. boards */ | 52 | #define MXSER_BOARDS 4 /* Max. boards */ |
| 55 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ | 53 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ |
| 56 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) | 54 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) |
| 57 | #define MXSER_ISR_PASS_LIMIT 100 | 55 | #define MXSER_ISR_PASS_LIMIT 100 |
| 58 | 56 | ||
| 59 | #define MXSER_ERR_IOADDR -1 | ||
| 60 | #define MXSER_ERR_IRQ -2 | ||
| 61 | #define MXSER_ERR_IRQ_CONFLIT -3 | ||
| 62 | #define MXSER_ERR_VECTOR -4 | ||
| 63 | |||
| 64 | /*CheckIsMoxaMust return value*/ | 57 | /*CheckIsMoxaMust return value*/ |
| 65 | #define MOXA_OTHER_UART 0x00 | 58 | #define MOXA_OTHER_UART 0x00 |
| 66 | #define MOXA_MUST_MU150_HWID 0x01 | 59 | #define MOXA_MUST_MU150_HWID 0x01 |
| @@ -179,14 +172,15 @@ static struct pci_device_id mxser_pcibrds[] = { | |||
| 179 | }; | 172 | }; |
| 180 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); | 173 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); |
| 181 | 174 | ||
| 182 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; | 175 | static unsigned long ioaddr[MXSER_BOARDS]; |
| 183 | static int ttymajor = MXSERMAJOR; | 176 | static int ttymajor = MXSERMAJOR; |
| 184 | 177 | ||
| 185 | /* Variables for insmod */ | 178 | /* Variables for insmod */ |
| 186 | 179 | ||
| 187 | MODULE_AUTHOR("Casper Yang"); | 180 | MODULE_AUTHOR("Casper Yang"); |
| 188 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); | 181 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); |
| 189 | module_param_array(ioaddr, int, NULL, 0); | 182 | module_param_array(ioaddr, ulong, NULL, 0); |
| 183 | MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); | ||
| 190 | module_param(ttymajor, int, 0); | 184 | module_param(ttymajor, int, 0); |
| 191 | MODULE_LICENSE("GPL"); | 185 | MODULE_LICENSE("GPL"); |
| 192 | 186 | ||
| @@ -196,7 +190,6 @@ struct mxser_log { | |||
| 196 | unsigned long txcnt[MXSER_PORTS]; | 190 | unsigned long txcnt[MXSER_PORTS]; |
| 197 | }; | 191 | }; |
| 198 | 192 | ||
| 199 | |||
| 200 | struct mxser_mon { | 193 | struct mxser_mon { |
| 201 | unsigned long rxcnt; | 194 | unsigned long rxcnt; |
| 202 | unsigned long txcnt; | 195 | unsigned long txcnt; |
| @@ -287,19 +280,9 @@ struct mxser_mstatus { | |||
| 287 | int dcd; | 280 | int dcd; |
| 288 | }; | 281 | }; |
| 289 | 282 | ||
| 290 | static struct mxser_mstatus GMStatus[MXSER_PORTS]; | ||
| 291 | |||
| 292 | static int mxserBoardCAP[MXSER_BOARDS] = { | ||
| 293 | 0, 0, 0, 0 | ||
| 294 | /* 0x180, 0x280, 0x200, 0x320 */ | ||
| 295 | }; | ||
| 296 | |||
| 297 | static struct mxser_board mxser_boards[MXSER_BOARDS]; | 283 | static struct mxser_board mxser_boards[MXSER_BOARDS]; |
| 298 | static struct tty_driver *mxvar_sdriver; | 284 | static struct tty_driver *mxvar_sdriver; |
| 299 | static struct mxser_log mxvar_log; | 285 | static struct mxser_log mxvar_log; |
| 300 | static int mxvar_diagflag; | ||
| 301 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | ||
| 302 | static struct mxser_mon_ext mon_data_ext; | ||
| 303 | static int mxser_set_baud_method[MXSER_PORTS + 1]; | 286 | static int mxser_set_baud_method[MXSER_PORTS + 1]; |
| 304 | 287 | ||
| 305 | static void mxser_enable_must_enchance_mode(unsigned long baseio) | 288 | static void mxser_enable_must_enchance_mode(unsigned long baseio) |
| @@ -543,6 +526,7 @@ static void process_txrx_fifo(struct mxser_port *info) | |||
| 543 | 526 | ||
| 544 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) | 527 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) |
| 545 | { | 528 | { |
| 529 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | ||
| 546 | unsigned char status = 0; | 530 | unsigned char status = 0; |
| 547 | 531 | ||
| 548 | status = inb(baseaddr + UART_MSR); | 532 | status = inb(baseaddr + UART_MSR); |
| @@ -1319,13 +1303,9 @@ static void mxser_flush_chars(struct tty_struct *tty) | |||
| 1319 | struct mxser_port *info = tty->driver_data; | 1303 | struct mxser_port *info = tty->driver_data; |
| 1320 | unsigned long flags; | 1304 | unsigned long flags; |
| 1321 | 1305 | ||
| 1322 | if (info->xmit_cnt <= 0 || | 1306 | if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || |
| 1323 | tty->stopped || | 1307 | (tty->hw_stopped && info->type != PORT_16550A && |
| 1324 | !info->port.xmit_buf || | 1308 | !info->board->chip_flag)) |
| 1325 | (tty->hw_stopped && | ||
| 1326 | (info->type != PORT_16550A) && | ||
| 1327 | (!info->board->chip_flag) | ||
| 1328 | )) | ||
| 1329 | return; | 1309 | return; |
| 1330 | 1310 | ||
| 1331 | spin_lock_irqsave(&info->slock, flags); | 1311 | spin_lock_irqsave(&info->slock, flags); |
| @@ -1343,9 +1323,7 @@ static int mxser_write_room(struct tty_struct *tty) | |||
| 1343 | int ret; | 1323 | int ret; |
| 1344 | 1324 | ||
| 1345 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | 1325 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; |
| 1346 | if (ret < 0) | 1326 | return ret < 0 ? 0 : ret; |
| 1347 | ret = 0; | ||
| 1348 | return ret; | ||
| 1349 | } | 1327 | } |
| 1350 | 1328 | ||
| 1351 | static int mxser_chars_in_buffer(struct tty_struct *tty) | 1329 | static int mxser_chars_in_buffer(struct tty_struct *tty) |
| @@ -1634,6 +1612,8 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1634 | 1612 | ||
| 1635 | switch (cmd) { | 1613 | switch (cmd) { |
| 1636 | case MOXA_GET_MAJOR: | 1614 | case MOXA_GET_MAJOR: |
| 1615 | printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl %x, fix " | ||
| 1616 | "your userspace\n", current->comm, cmd); | ||
| 1637 | return put_user(ttymajor, (int __user *)argp); | 1617 | return put_user(ttymajor, (int __user *)argp); |
| 1638 | 1618 | ||
| 1639 | case MOXA_CHKPORTENABLE: | 1619 | case MOXA_CHKPORTENABLE: |
| @@ -1651,62 +1631,60 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1651 | ret = -EFAULT; | 1631 | ret = -EFAULT; |
| 1652 | unlock_kernel(); | 1632 | unlock_kernel(); |
| 1653 | return ret; | 1633 | return ret; |
| 1654 | case MOXA_GETMSTATUS: | 1634 | case MOXA_GETMSTATUS: { |
| 1635 | struct mxser_mstatus ms, __user *msu = argp; | ||
| 1655 | lock_kernel(); | 1636 | lock_kernel(); |
| 1656 | for (i = 0; i < MXSER_BOARDS; i++) | 1637 | for (i = 0; i < MXSER_BOARDS; i++) |
| 1657 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1638 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { |
| 1658 | port = &mxser_boards[i].ports[j]; | 1639 | port = &mxser_boards[i].ports[j]; |
| 1640 | memset(&ms, 0, sizeof(ms)); | ||
| 1659 | 1641 | ||
| 1660 | GMStatus[i].ri = 0; | 1642 | if (!port->ioaddr) |
| 1661 | if (!port->ioaddr) { | 1643 | goto copy; |
| 1662 | GMStatus[i].dcd = 0; | ||
| 1663 | GMStatus[i].dsr = 0; | ||
| 1664 | GMStatus[i].cts = 0; | ||
| 1665 | continue; | ||
| 1666 | } | ||
| 1667 | 1644 | ||
| 1668 | if (!port->port.tty || !port->port.tty->termios) | 1645 | if (!port->port.tty || !port->port.tty->termios) |
| 1669 | GMStatus[i].cflag = | 1646 | ms.cflag = port->normal_termios.c_cflag; |
| 1670 | port->normal_termios.c_cflag; | ||
| 1671 | else | 1647 | else |
| 1672 | GMStatus[i].cflag = | 1648 | ms.cflag = port->port.tty->termios->c_cflag; |
| 1673 | port->port.tty->termios->c_cflag; | ||
| 1674 | 1649 | ||
| 1675 | status = inb(port->ioaddr + UART_MSR); | 1650 | status = inb(port->ioaddr + UART_MSR); |
| 1676 | if (status & 0x80 /*UART_MSR_DCD */ ) | 1651 | if (status & UART_MSR_DCD) |
| 1677 | GMStatus[i].dcd = 1; | 1652 | ms.dcd = 1; |
| 1678 | else | 1653 | if (status & UART_MSR_DSR) |
| 1679 | GMStatus[i].dcd = 0; | 1654 | ms.dsr = 1; |
| 1680 | 1655 | if (status & UART_MSR_CTS) | |
| 1681 | if (status & 0x20 /*UART_MSR_DSR */ ) | 1656 | ms.cts = 1; |
| 1682 | GMStatus[i].dsr = 1; | 1657 | copy: |
| 1683 | else | 1658 | if (copy_to_user(msu, &ms, sizeof(ms))) { |
| 1684 | GMStatus[i].dsr = 0; | 1659 | unlock_kernel(); |
| 1685 | 1660 | return -EFAULT; | |
| 1686 | 1661 | } | |
| 1687 | if (status & 0x10 /*UART_MSR_CTS */ ) | 1662 | msu++; |
| 1688 | GMStatus[i].cts = 1; | ||
| 1689 | else | ||
| 1690 | GMStatus[i].cts = 0; | ||
| 1691 | } | 1663 | } |
| 1692 | unlock_kernel(); | 1664 | unlock_kernel(); |
| 1693 | if (copy_to_user(argp, GMStatus, | ||
| 1694 | sizeof(struct mxser_mstatus) * MXSER_PORTS)) | ||
| 1695 | return -EFAULT; | ||
| 1696 | return 0; | 1665 | return 0; |
| 1666 | } | ||
| 1697 | case MOXA_ASPP_MON_EXT: { | 1667 | case MOXA_ASPP_MON_EXT: { |
| 1698 | int p, shiftbit; | 1668 | struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ |
| 1699 | unsigned long opmode; | 1669 | unsigned int cflag, iflag, p; |
| 1700 | unsigned cflag, iflag; | 1670 | u8 opmode; |
| 1671 | |||
| 1672 | me = kzalloc(sizeof(*me), GFP_KERNEL); | ||
| 1673 | if (!me) | ||
| 1674 | return -ENOMEM; | ||
| 1701 | 1675 | ||
| 1702 | lock_kernel(); | 1676 | lock_kernel(); |
| 1703 | for (i = 0; i < MXSER_BOARDS; i++) { | 1677 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { |
| 1704 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1678 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { |
| 1679 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | ||
| 1680 | i = MXSER_BOARDS; | ||
| 1681 | break; | ||
| 1682 | } | ||
| 1705 | port = &mxser_boards[i].ports[j]; | 1683 | port = &mxser_boards[i].ports[j]; |
| 1706 | if (!port->ioaddr) | 1684 | if (!port->ioaddr) |
| 1707 | continue; | 1685 | continue; |
| 1708 | 1686 | ||
| 1709 | status = mxser_get_msr(port->ioaddr, 0, i); | 1687 | status = mxser_get_msr(port->ioaddr, 0, p); |
| 1710 | 1688 | ||
| 1711 | if (status & UART_MSR_TERI) | 1689 | if (status & UART_MSR_TERI) |
| 1712 | port->icount.rng++; | 1690 | port->icount.rng++; |
| @@ -1718,16 +1696,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1718 | port->icount.cts++; | 1696 | port->icount.cts++; |
| 1719 | 1697 | ||
| 1720 | port->mon_data.modem_status = status; | 1698 | port->mon_data.modem_status = status; |
| 1721 | mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; | 1699 | me->rx_cnt[p] = port->mon_data.rxcnt; |
| 1722 | mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; | 1700 | me->tx_cnt[p] = port->mon_data.txcnt; |
| 1723 | mon_data_ext.up_rxcnt[i] = | 1701 | me->up_rxcnt[p] = port->mon_data.up_rxcnt; |
| 1724 | port->mon_data.up_rxcnt; | 1702 | me->up_txcnt[p] = port->mon_data.up_txcnt; |
| 1725 | mon_data_ext.up_txcnt[i] = | 1703 | me->modem_status[p] = |
| 1726 | port->mon_data.up_txcnt; | ||
| 1727 | mon_data_ext.modem_status[i] = | ||
| 1728 | port->mon_data.modem_status; | 1704 | port->mon_data.modem_status; |
| 1729 | mon_data_ext.baudrate[i] = | 1705 | me->baudrate[p] = tty_get_baud_rate(port->port.tty); |
| 1730 | tty_get_baud_rate(port->port.tty); | ||
| 1731 | 1706 | ||
| 1732 | if (!port->port.tty || !port->port.tty->termios) { | 1707 | if (!port->port.tty || !port->port.tty->termios) { |
| 1733 | cflag = port->normal_termios.c_cflag; | 1708 | cflag = port->normal_termios.c_cflag; |
| @@ -1737,40 +1712,31 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
| 1737 | iflag = port->port.tty->termios->c_iflag; | 1712 | iflag = port->port.tty->termios->c_iflag; |
| 1738 | } | 1713 | } |
| 1739 | 1714 | ||
| 1740 | mon_data_ext.databits[i] = cflag & CSIZE; | 1715 | me->databits[p] = cflag & CSIZE; |
| 1741 | 1716 | me->stopbits[p] = cflag & CSTOPB; | |
| 1742 | mon_data_ext.stopbits[i] = cflag & CSTOPB; | 1717 | me->parity[p] = cflag & (PARENB | PARODD | |
| 1743 | 1718 | CMSPAR); | |
| 1744 | mon_data_ext.parity[i] = | ||
| 1745 | cflag & (PARENB | PARODD | CMSPAR); | ||
| 1746 | |||
| 1747 | mon_data_ext.flowctrl[i] = 0x00; | ||
| 1748 | 1719 | ||
| 1749 | if (cflag & CRTSCTS) | 1720 | if (cflag & CRTSCTS) |
| 1750 | mon_data_ext.flowctrl[i] |= 0x03; | 1721 | me->flowctrl[p] |= 0x03; |
| 1751 | 1722 | ||
| 1752 | if (iflag & (IXON | IXOFF)) | 1723 | if (iflag & (IXON | IXOFF)) |
| 1753 | mon_data_ext.flowctrl[i] |= 0x0C; | 1724 | me->flowctrl[p] |= 0x0C; |
| 1754 | 1725 | ||
| 1755 | if (port->type == PORT_16550A) | 1726 | if (port->type == PORT_16550A) |
| 1756 | mon_data_ext.fifo[i] = 1; | 1727 | me->fifo[p] = 1; |
| 1757 | else | ||
| 1758 | mon_data_ext.fifo[i] = 0; | ||
| 1759 | 1728 | ||
| 1760 | p = i % 4; | 1729 | opmode = inb(port->opmode_ioaddr) >> |
| 1761 | shiftbit = p * 2; | 1730 | ((p % 4) * 2); |
| 1762 | opmode = inb(port->opmode_ioaddr) >> shiftbit; | ||
| 1763 | opmode &= OP_MODE_MASK; | 1731 | opmode &= OP_MODE_MASK; |
| 1764 | 1732 | me->iftype[p] = opmode; | |
| 1765 | mon_data_ext.iftype[i] = opmode; | ||
| 1766 | |||
| 1767 | } | 1733 | } |
| 1768 | } | 1734 | } |
| 1769 | unlock_kernel(); | 1735 | unlock_kernel(); |
| 1770 | if (copy_to_user(argp, &mon_data_ext, | 1736 | if (copy_to_user(argp, me, sizeof(*me))) |
| 1771 | sizeof(mon_data_ext))) | 1737 | ret = -EFAULT; |
| 1772 | return -EFAULT; | 1738 | kfree(me); |
| 1773 | return 0; | 1739 | return ret; |
| 1774 | } | 1740 | } |
| 1775 | default: | 1741 | default: |
| 1776 | return -ENOIOCTLCMD; | 1742 | return -ENOIOCTLCMD; |
| @@ -1804,7 +1770,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1804 | { | 1770 | { |
| 1805 | struct mxser_port *info = tty->driver_data; | 1771 | struct mxser_port *info = tty->driver_data; |
| 1806 | struct async_icount cnow; | 1772 | struct async_icount cnow; |
| 1807 | struct serial_icounter_struct __user *p_cuser; | ||
| 1808 | unsigned long flags; | 1773 | unsigned long flags; |
| 1809 | void __user *argp = (void __user *)arg; | 1774 | void __user *argp = (void __user *)arg; |
| 1810 | int retval; | 1775 | int retval; |
| @@ -1884,30 +1849,26 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1884 | * NB: both 1->0 and 0->1 transitions are counted except for | 1849 | * NB: both 1->0 and 0->1 transitions are counted except for |
| 1885 | * RI where only 0->1 is counted. | 1850 | * RI where only 0->1 is counted. |
| 1886 | */ | 1851 | */ |
| 1887 | case TIOCGICOUNT: | 1852 | case TIOCGICOUNT: { |
| 1853 | struct serial_icounter_struct icnt = { 0 }; | ||
| 1888 | spin_lock_irqsave(&info->slock, flags); | 1854 | spin_lock_irqsave(&info->slock, flags); |
| 1889 | cnow = info->icount; | 1855 | cnow = info->icount; |
| 1890 | spin_unlock_irqrestore(&info->slock, flags); | 1856 | spin_unlock_irqrestore(&info->slock, flags); |
| 1891 | p_cuser = argp; | 1857 | |
| 1892 | if (put_user(cnow.frame, &p_cuser->frame)) | 1858 | icnt.frame = cnow.frame; |
| 1893 | return -EFAULT; | 1859 | icnt.brk = cnow.brk; |
| 1894 | if (put_user(cnow.brk, &p_cuser->brk)) | 1860 | icnt.overrun = cnow.overrun; |
| 1895 | return -EFAULT; | 1861 | icnt.buf_overrun = cnow.buf_overrun; |
| 1896 | if (put_user(cnow.overrun, &p_cuser->overrun)) | 1862 | icnt.parity = cnow.parity; |
| 1897 | return -EFAULT; | 1863 | icnt.rx = cnow.rx; |
| 1898 | if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | 1864 | icnt.tx = cnow.tx; |
| 1899 | return -EFAULT; | 1865 | icnt.cts = cnow.cts; |
| 1900 | if (put_user(cnow.parity, &p_cuser->parity)) | 1866 | icnt.dsr = cnow.dsr; |
| 1901 | return -EFAULT; | 1867 | icnt.rng = cnow.rng; |
| 1902 | if (put_user(cnow.rx, &p_cuser->rx)) | 1868 | icnt.dcd = cnow.dcd; |
| 1903 | return -EFAULT; | 1869 | |
| 1904 | if (put_user(cnow.tx, &p_cuser->tx)) | 1870 | return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; |
| 1905 | return -EFAULT; | 1871 | } |
| 1906 | put_user(cnow.cts, &p_cuser->cts); | ||
| 1907 | put_user(cnow.dsr, &p_cuser->dsr); | ||
| 1908 | put_user(cnow.rng, &p_cuser->rng); | ||
| 1909 | put_user(cnow.dcd, &p_cuser->dcd); | ||
| 1910 | return 0; | ||
| 1911 | case MOXA_HighSpeedOn: | 1872 | case MOXA_HighSpeedOn: |
| 1912 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1873 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
| 1913 | case MOXA_SDS_RSTICOUNTER: | 1874 | case MOXA_SDS_RSTICOUNTER: |
| @@ -2503,7 +2464,8 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
| 2503 | unsigned int i; | 2464 | unsigned int i; |
| 2504 | int retval; | 2465 | int retval; |
| 2505 | 2466 | ||
| 2506 | printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); | 2467 | printk(KERN_INFO "mxser: max. baud rate = %d bps\n", |
| 2468 | brd->ports[0].max_baud); | ||
| 2507 | 2469 | ||
| 2508 | for (i = 0; i < brd->info->nports; i++) { | 2470 | for (i = 0; i < brd->info->nports; i++) { |
| 2509 | info = &brd->ports[i]; | 2471 | info = &brd->ports[i]; |
| @@ -2586,28 +2548,32 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | |||
| 2586 | irq = regs[9] & 0xF000; | 2548 | irq = regs[9] & 0xF000; |
| 2587 | irq = irq | (irq >> 4); | 2549 | irq = irq | (irq >> 4); |
| 2588 | if (irq != (regs[9] & 0xFF00)) | 2550 | if (irq != (regs[9] & 0xFF00)) |
| 2589 | return MXSER_ERR_IRQ_CONFLIT; | 2551 | goto err_irqconflict; |
| 2590 | } else if (brd->info->nports == 4) { | 2552 | } else if (brd->info->nports == 4) { |
| 2591 | irq = regs[9] & 0xF000; | 2553 | irq = regs[9] & 0xF000; |
| 2592 | irq = irq | (irq >> 4); | 2554 | irq = irq | (irq >> 4); |
| 2593 | irq = irq | (irq >> 8); | 2555 | irq = irq | (irq >> 8); |
| 2594 | if (irq != regs[9]) | 2556 | if (irq != regs[9]) |
| 2595 | return MXSER_ERR_IRQ_CONFLIT; | 2557 | goto err_irqconflict; |
| 2596 | } else if (brd->info->nports == 8) { | 2558 | } else if (brd->info->nports == 8) { |
| 2597 | irq = regs[9] & 0xF000; | 2559 | irq = regs[9] & 0xF000; |
| 2598 | irq = irq | (irq >> 4); | 2560 | irq = irq | (irq >> 4); |
| 2599 | irq = irq | (irq >> 8); | 2561 | irq = irq | (irq >> 8); |
| 2600 | if ((irq != regs[9]) || (irq != regs[10])) | 2562 | if ((irq != regs[9]) || (irq != regs[10])) |
| 2601 | return MXSER_ERR_IRQ_CONFLIT; | 2563 | goto err_irqconflict; |
| 2602 | } | 2564 | } |
| 2603 | 2565 | ||
| 2604 | if (!irq) | 2566 | if (!irq) { |
| 2605 | return MXSER_ERR_IRQ; | 2567 | printk(KERN_ERR "mxser: interrupt number unset\n"); |
| 2568 | return -EIO; | ||
| 2569 | } | ||
| 2606 | brd->irq = ((int)(irq & 0xF000) >> 12); | 2570 | brd->irq = ((int)(irq & 0xF000) >> 12); |
| 2607 | for (i = 0; i < 8; i++) | 2571 | for (i = 0; i < 8; i++) |
| 2608 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; | 2572 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; |
| 2609 | if ((regs[12] & 0x80) == 0) | 2573 | if ((regs[12] & 0x80) == 0) { |
| 2610 | return MXSER_ERR_VECTOR; | 2574 | printk(KERN_ERR "mxser: invalid interrupt vector\n"); |
| 2575 | return -EIO; | ||
| 2576 | } | ||
| 2611 | brd->vector = (int)regs[11]; /* interrupt vector */ | 2577 | brd->vector = (int)regs[11]; /* interrupt vector */ |
| 2612 | if (id == 1) | 2578 | if (id == 1) |
| 2613 | brd->vector_mask = 0x00FF; | 2579 | brd->vector_mask = 0x00FF; |
| @@ -2634,13 +2600,26 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | |||
| 2634 | else | 2600 | else |
| 2635 | brd->uart_type = PORT_16450; | 2601 | brd->uart_type = PORT_16450; |
| 2636 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, | 2602 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, |
| 2637 | "mxser(IO)")) | 2603 | "mxser(IO)")) { |
| 2638 | return MXSER_ERR_IOADDR; | 2604 | printk(KERN_ERR "mxser: can't request ports I/O region: " |
| 2605 | "0x%.8lx-0x%.8lx\n", | ||
| 2606 | brd->ports[0].ioaddr, brd->ports[0].ioaddr + | ||
| 2607 | 8 * brd->info->nports - 1); | ||
| 2608 | return -EIO; | ||
| 2609 | } | ||
| 2639 | if (!request_region(brd->vector, 1, "mxser(vector)")) { | 2610 | if (!request_region(brd->vector, 1, "mxser(vector)")) { |
| 2640 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); | 2611 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
| 2641 | return MXSER_ERR_VECTOR; | 2612 | printk(KERN_ERR "mxser: can't request interrupt vector region: " |
| 2613 | "0x%.8lx-0x%.8lx\n", | ||
| 2614 | brd->ports[0].ioaddr, brd->ports[0].ioaddr + | ||
| 2615 | 8 * brd->info->nports - 1); | ||
| 2616 | return -EIO; | ||
| 2642 | } | 2617 | } |
| 2643 | return brd->info->nports; | 2618 | return brd->info->nports; |
| 2619 | |||
| 2620 | err_irqconflict: | ||
| 2621 | printk(KERN_ERR "mxser: invalid interrupt number\n"); | ||
| 2622 | return -EIO; | ||
| 2644 | } | 2623 | } |
| 2645 | 2624 | ||
| 2646 | static int __devinit mxser_probe(struct pci_dev *pdev, | 2625 | static int __devinit mxser_probe(struct pci_dev *pdev, |
| @@ -2657,20 +2636,20 @@ static int __devinit mxser_probe(struct pci_dev *pdev, | |||
| 2657 | break; | 2636 | break; |
| 2658 | 2637 | ||
| 2659 | if (i >= MXSER_BOARDS) { | 2638 | if (i >= MXSER_BOARDS) { |
| 2660 | printk(KERN_ERR "Too many Smartio/Industio family boards found " | 2639 | dev_err(&pdev->dev, "too many boards found (maximum %d), board " |
| 2661 | "(maximum %d), board not configured\n", MXSER_BOARDS); | 2640 | "not configured\n", MXSER_BOARDS); |
| 2662 | goto err; | 2641 | goto err; |
| 2663 | } | 2642 | } |
| 2664 | 2643 | ||
| 2665 | brd = &mxser_boards[i]; | 2644 | brd = &mxser_boards[i]; |
| 2666 | brd->idx = i * MXSER_PORTS_PER_BOARD; | 2645 | brd->idx = i * MXSER_PORTS_PER_BOARD; |
| 2667 | printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", | 2646 | dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", |
| 2668 | mxser_cards[ent->driver_data].name, | 2647 | mxser_cards[ent->driver_data].name, |
| 2669 | pdev->bus->number, PCI_SLOT(pdev->devfn)); | 2648 | pdev->bus->number, PCI_SLOT(pdev->devfn)); |
| 2670 | 2649 | ||
| 2671 | retval = pci_enable_device(pdev); | 2650 | retval = pci_enable_device(pdev); |
| 2672 | if (retval) { | 2651 | if (retval) { |
| 2673 | printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); | 2652 | dev_err(&pdev->dev, "PCI enable failed\n"); |
| 2674 | goto err; | 2653 | goto err; |
| 2675 | } | 2654 | } |
| 2676 | 2655 | ||
| @@ -2772,11 +2751,8 @@ static struct pci_driver mxser_driver = { | |||
| 2772 | static int __init mxser_module_init(void) | 2751 | static int __init mxser_module_init(void) |
| 2773 | { | 2752 | { |
| 2774 | struct mxser_board *brd; | 2753 | struct mxser_board *brd; |
| 2775 | unsigned long cap; | 2754 | unsigned int b, i, m; |
| 2776 | unsigned int i, m, isaloop; | 2755 | int retval; |
| 2777 | int retval, b; | ||
| 2778 | |||
| 2779 | pr_debug("Loading module mxser ...\n"); | ||
| 2780 | 2756 | ||
| 2781 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); | 2757 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); |
| 2782 | if (!mxvar_sdriver) | 2758 | if (!mxvar_sdriver) |
| @@ -2806,74 +2782,43 @@ static int __init mxser_module_init(void) | |||
| 2806 | goto err_put; | 2782 | goto err_put; |
| 2807 | } | 2783 | } |
| 2808 | 2784 | ||
| 2809 | mxvar_diagflag = 0; | ||
| 2810 | |||
| 2811 | m = 0; | ||
| 2812 | /* Start finding ISA boards here */ | 2785 | /* Start finding ISA boards here */ |
| 2813 | for (isaloop = 0; isaloop < 2; isaloop++) | 2786 | for (m = 0, b = 0; b < MXSER_BOARDS; b++) { |
| 2814 | for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { | 2787 | if (!ioaddr[b]) |
| 2815 | if (!isaloop) | 2788 | continue; |
| 2816 | cap = mxserBoardCAP[b]; /* predefined */ | 2789 | |
| 2817 | else | 2790 | brd = &mxser_boards[m]; |
| 2818 | cap = ioaddr[b]; /* module param */ | 2791 | retval = mxser_get_ISA_conf(!ioaddr[b], brd); |
| 2819 | 2792 | if (retval <= 0) { | |
| 2820 | if (!cap) | 2793 | brd->info = NULL; |
| 2821 | continue; | 2794 | continue; |
| 2795 | } | ||
| 2822 | 2796 | ||
| 2823 | brd = &mxser_boards[m]; | 2797 | printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", |
| 2824 | retval = mxser_get_ISA_conf(cap, brd); | 2798 | brd->info->name, ioaddr[b]); |
| 2825 | |||
| 2826 | if (retval != 0) | ||
| 2827 | printk(KERN_INFO "Found MOXA %s board " | ||
| 2828 | "(CAP=0x%x)\n", | ||
| 2829 | brd->info->name, ioaddr[b]); | ||
| 2830 | |||
| 2831 | if (retval <= 0) { | ||
| 2832 | if (retval == MXSER_ERR_IRQ) | ||
| 2833 | printk(KERN_ERR "Invalid interrupt " | ||
| 2834 | "number, board not " | ||
| 2835 | "configured\n"); | ||
| 2836 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | ||
| 2837 | printk(KERN_ERR "Invalid interrupt " | ||
| 2838 | "number, board not " | ||
| 2839 | "configured\n"); | ||
| 2840 | else if (retval == MXSER_ERR_VECTOR) | ||
| 2841 | printk(KERN_ERR "Invalid interrupt " | ||
| 2842 | "vector, board not " | ||
| 2843 | "configured\n"); | ||
| 2844 | else if (retval == MXSER_ERR_IOADDR) | ||
| 2845 | printk(KERN_ERR "Invalid I/O address, " | ||
| 2846 | "board not configured\n"); | ||
| 2847 | |||
| 2848 | brd->info = NULL; | ||
| 2849 | continue; | ||
| 2850 | } | ||
| 2851 | 2799 | ||
| 2852 | /* mxser_initbrd will hook ISR. */ | 2800 | /* mxser_initbrd will hook ISR. */ |
| 2853 | if (mxser_initbrd(brd, NULL) < 0) { | 2801 | if (mxser_initbrd(brd, NULL) < 0) { |
| 2854 | brd->info = NULL; | 2802 | brd->info = NULL; |
| 2855 | continue; | 2803 | continue; |
| 2856 | } | 2804 | } |
| 2857 | 2805 | ||
| 2858 | brd->idx = m * MXSER_PORTS_PER_BOARD; | 2806 | brd->idx = m * MXSER_PORTS_PER_BOARD; |
| 2859 | for (i = 0; i < brd->info->nports; i++) | 2807 | for (i = 0; i < brd->info->nports; i++) |
| 2860 | tty_register_device(mxvar_sdriver, brd->idx + i, | 2808 | tty_register_device(mxvar_sdriver, brd->idx + i, NULL); |
| 2861 | NULL); | ||
| 2862 | 2809 | ||
| 2863 | m++; | 2810 | m++; |
| 2864 | } | 2811 | } |
| 2865 | 2812 | ||
| 2866 | retval = pci_register_driver(&mxser_driver); | 2813 | retval = pci_register_driver(&mxser_driver); |
| 2867 | if (retval) { | 2814 | if (retval) { |
| 2868 | printk(KERN_ERR "Can't register pci driver\n"); | 2815 | printk(KERN_ERR "mxser: can't register pci driver\n"); |
| 2869 | if (!m) { | 2816 | if (!m) { |
| 2870 | retval = -ENODEV; | 2817 | retval = -ENODEV; |
| 2871 | goto err_unr; | 2818 | goto err_unr; |
| 2872 | } /* else: we have some ISA cards under control */ | 2819 | } /* else: we have some ISA cards under control */ |
| 2873 | } | 2820 | } |
| 2874 | 2821 | ||
| 2875 | pr_debug("Done.\n"); | ||
| 2876 | |||
| 2877 | return 0; | 2822 | return 0; |
| 2878 | err_unr: | 2823 | err_unr: |
| 2879 | tty_unregister_driver(mxvar_sdriver); | 2824 | tty_unregister_driver(mxvar_sdriver); |
| @@ -2886,8 +2831,6 @@ static void __exit mxser_module_exit(void) | |||
| 2886 | { | 2831 | { |
| 2887 | unsigned int i, j; | 2832 | unsigned int i, j; |
| 2888 | 2833 | ||
| 2889 | pr_debug("Unloading module mxser ...\n"); | ||
| 2890 | |||
| 2891 | pci_unregister_driver(&mxser_driver); | 2834 | pci_unregister_driver(&mxser_driver); |
| 2892 | 2835 | ||
| 2893 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ | 2836 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ |
| @@ -2901,8 +2844,6 @@ static void __exit mxser_module_exit(void) | |||
| 2901 | for (i = 0; i < MXSER_BOARDS; i++) | 2844 | for (i = 0; i < MXSER_BOARDS; i++) |
| 2902 | if (mxser_boards[i].info != NULL) | 2845 | if (mxser_boards[i].info != NULL) |
| 2903 | mxser_release_res(&mxser_boards[i], NULL, 1); | 2846 | mxser_release_res(&mxser_boards[i], NULL, 1); |
| 2904 | |||
| 2905 | pr_debug("Done.\n"); | ||
| 2906 | } | 2847 | } |
| 2907 | 2848 | ||
| 2908 | module_init(mxser_module_init); | 2849 | module_init(mxser_module_init); |
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index ba012c2bdf7a..f9f72a211292 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c | |||
| @@ -122,35 +122,20 @@ static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cm | |||
| 122 | static ssize_t flash_read(struct file *file, char __user *buf, size_t size, | 122 | static ssize_t flash_read(struct file *file, char __user *buf, size_t size, |
| 123 | loff_t *ppos) | 123 | loff_t *ppos) |
| 124 | { | 124 | { |
| 125 | unsigned long p = *ppos; | 125 | ssize_t ret; |
| 126 | unsigned int count = size; | ||
| 127 | int ret = 0; | ||
| 128 | 126 | ||
| 129 | if (flashdebug) | 127 | if (flashdebug) |
| 130 | printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, " | 128 | printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, " |
| 131 | "buffer=%p, count=0x%X.\n", p, buf, count); | 129 | "buffer=%p, count=0x%X.\n", p, buf, count); |
| 130 | /* | ||
| 131 | * We now lock against reads and writes. --rmk | ||
| 132 | */ | ||
| 133 | if (mutex_lock_interruptible(&nwflash_mutex)) | ||
| 134 | return -ERESTARTSYS; | ||
| 132 | 135 | ||
| 133 | if (count) | 136 | ret = simple_read_from_buffer(buf, size, ppos, FLASH_BASE, gbFlashSize); |
| 134 | ret = -ENXIO; | 137 | mutex_unlock(&nwflash_mutex); |
| 135 | |||
| 136 | if (p < gbFlashSize) { | ||
| 137 | if (count > gbFlashSize - p) | ||
| 138 | count = gbFlashSize - p; | ||
| 139 | 138 | ||
| 140 | /* | ||
| 141 | * We now lock against reads and writes. --rmk | ||
| 142 | */ | ||
| 143 | if (mutex_lock_interruptible(&nwflash_mutex)) | ||
| 144 | return -ERESTARTSYS; | ||
| 145 | |||
| 146 | ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count); | ||
| 147 | if (ret == 0) { | ||
| 148 | ret = count; | ||
| 149 | *ppos += count; | ||
| 150 | } else | ||
| 151 | ret = -EFAULT; | ||
| 152 | mutex_unlock(&nwflash_mutex); | ||
| 153 | } | ||
| 154 | return ret; | 139 | return ret; |
| 155 | } | 140 | } |
| 156 | 141 | ||
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 7af7a7e6b9c2..bee39fdfba73 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
| @@ -67,7 +67,7 @@ | |||
| 67 | #include <linux/major.h> | 67 | #include <linux/major.h> |
| 68 | #include <linux/ppdev.h> | 68 | #include <linux/ppdev.h> |
| 69 | #include <linux/smp_lock.h> | 69 | #include <linux/smp_lock.h> |
| 70 | #include <asm/uaccess.h> | 70 | #include <linux/uaccess.h> |
| 71 | 71 | ||
| 72 | #define PP_VERSION "ppdev: user-space parallel port driver" | 72 | #define PP_VERSION "ppdev: user-space parallel port driver" |
| 73 | #define CHRDEV "ppdev" | 73 | #define CHRDEV "ppdev" |
| @@ -328,10 +328,9 @@ static enum ieee1284_phase init_phase (int mode) | |||
| 328 | return IEEE1284_PH_FWD_IDLE; | 328 | return IEEE1284_PH_FWD_IDLE; |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | static int pp_ioctl(struct inode *inode, struct file *file, | 331 | static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 332 | unsigned int cmd, unsigned long arg) | ||
| 333 | { | 332 | { |
| 334 | unsigned int minor = iminor(inode); | 333 | unsigned int minor = iminor(file->f_path.dentry->d_inode); |
| 335 | struct pp_struct *pp = file->private_data; | 334 | struct pp_struct *pp = file->private_data; |
| 336 | struct parport * port; | 335 | struct parport * port; |
| 337 | void __user *argp = (void __user *)arg; | 336 | void __user *argp = (void __user *)arg; |
| @@ -634,6 +633,15 @@ static int pp_ioctl(struct inode *inode, struct file *file, | |||
| 634 | return 0; | 633 | return 0; |
| 635 | } | 634 | } |
| 636 | 635 | ||
| 636 | static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 637 | { | ||
| 638 | long ret; | ||
| 639 | lock_kernel(); | ||
| 640 | ret = pp_do_ioctl(file, cmd, arg); | ||
| 641 | unlock_kernel(); | ||
| 642 | return ret; | ||
| 643 | } | ||
| 644 | |||
| 637 | static int pp_open (struct inode * inode, struct file * file) | 645 | static int pp_open (struct inode * inode, struct file * file) |
| 638 | { | 646 | { |
| 639 | unsigned int minor = iminor(inode); | 647 | unsigned int minor = iminor(inode); |
| @@ -745,7 +753,7 @@ static const struct file_operations pp_fops = { | |||
| 745 | .read = pp_read, | 753 | .read = pp_read, |
| 746 | .write = pp_write, | 754 | .write = pp_write, |
| 747 | .poll = pp_poll, | 755 | .poll = pp_poll, |
| 748 | .ioctl = pp_ioctl, | 756 | .unlocked_ioctl = pp_ioctl, |
| 749 | .open = pp_open, | 757 | .open = pp_open, |
| 750 | .release = pp_release, | 758 | .release = pp_release, |
| 751 | }; | 759 | }; |
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 0cdfee152916..a8f68a3f14dd 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
| @@ -179,7 +179,7 @@ static int rio_set_real_termios(void *ptr); | |||
| 179 | static void rio_hungup(void *ptr); | 179 | static void rio_hungup(void *ptr); |
| 180 | static void rio_close(void *ptr); | 180 | static void rio_close(void *ptr); |
| 181 | static int rio_chars_in_buffer(void *ptr); | 181 | static int rio_chars_in_buffer(void *ptr); |
| 182 | static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); | 182 | static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); |
| 183 | static int rio_init_drivers(void); | 183 | static int rio_init_drivers(void); |
| 184 | 184 | ||
| 185 | static void my_hd(void *addr, int len); | 185 | static void my_hd(void *addr, int len); |
| @@ -240,7 +240,7 @@ static struct real_driver rio_real_driver = { | |||
| 240 | 240 | ||
| 241 | static const struct file_operations rio_fw_fops = { | 241 | static const struct file_operations rio_fw_fops = { |
| 242 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
| 243 | .ioctl = rio_fw_ioctl, | 243 | .unlocked_ioctl = rio_fw_ioctl, |
| 244 | }; | 244 | }; |
| 245 | 245 | ||
| 246 | static struct miscdevice rio_fw_device = { | 246 | static struct miscdevice rio_fw_device = { |
| @@ -560,13 +560,15 @@ static void rio_close(void *ptr) | |||
| 560 | 560 | ||
| 561 | 561 | ||
| 562 | 562 | ||
| 563 | static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) | 563 | static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
| 564 | { | 564 | { |
| 565 | int rc = 0; | 565 | int rc = 0; |
| 566 | func_enter(); | 566 | func_enter(); |
| 567 | 567 | ||
| 568 | /* The "dev" argument isn't used. */ | 568 | /* The "dev" argument isn't used. */ |
| 569 | lock_kernel(); | ||
| 569 | rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); | 570 | rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); |
| 571 | unlock_kernel(); | ||
| 570 | 572 | ||
| 571 | func_exit(); | 573 | func_exit(); |
| 572 | return rc; | 574 | return rc; |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 2162439bbe48..c385206f9db5 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
| @@ -286,8 +286,8 @@ static void sx_close(void *ptr); | |||
| 286 | static int sx_chars_in_buffer(void *ptr); | 286 | static int sx_chars_in_buffer(void *ptr); |
| 287 | static int sx_init_board(struct sx_board *board); | 287 | static int sx_init_board(struct sx_board *board); |
| 288 | static int sx_init_portstructs(int nboards, int nports); | 288 | static int sx_init_portstructs(int nboards, int nports); |
| 289 | static int sx_fw_ioctl(struct inode *inode, struct file *filp, | 289 | static long sx_fw_ioctl(struct file *filp, unsigned int cmd, |
| 290 | unsigned int cmd, unsigned long arg); | 290 | unsigned long arg); |
| 291 | static int sx_init_drivers(void); | 291 | static int sx_init_drivers(void); |
| 292 | 292 | ||
| 293 | static struct tty_driver *sx_driver; | 293 | static struct tty_driver *sx_driver; |
| @@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = { | |||
| 396 | 396 | ||
| 397 | static const struct file_operations sx_fw_fops = { | 397 | static const struct file_operations sx_fw_fops = { |
| 398 | .owner = THIS_MODULE, | 398 | .owner = THIS_MODULE, |
| 399 | .ioctl = sx_fw_ioctl, | 399 | .unlocked_ioctl = sx_fw_ioctl, |
| 400 | }; | 400 | }; |
| 401 | 401 | ||
| 402 | static struct miscdevice sx_fw_device = { | 402 | static struct miscdevice sx_fw_device = { |
| @@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max) | |||
| 1686 | } | 1686 | } |
| 1687 | #endif | 1687 | #endif |
| 1688 | 1688 | ||
| 1689 | static int sx_fw_ioctl(struct inode *inode, struct file *filp, | 1689 | static long sx_fw_ioctl(struct file *filp, unsigned int cmd, |
| 1690 | unsigned int cmd, unsigned long arg) | 1690 | unsigned long arg) |
| 1691 | { | 1691 | { |
| 1692 | int rc = 0; | 1692 | long rc = 0; |
| 1693 | int __user *descr = (int __user *)arg; | 1693 | int __user *descr = (int __user *)arg; |
| 1694 | int i; | 1694 | int i; |
| 1695 | static struct sx_board *board = NULL; | 1695 | static struct sx_board *board = NULL; |
| @@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
| 1699 | 1699 | ||
| 1700 | func_enter(); | 1700 | func_enter(); |
| 1701 | 1701 | ||
| 1702 | #if 0 | 1702 | if (!capable(CAP_SYS_RAWIO)) |
| 1703 | /* Removed superuser check: Sysops can use the permissions on the device | ||
| 1704 | file to restrict access. Recommendation: Root only. (root.root 600) */ | ||
| 1705 | if (!capable(CAP_SYS_ADMIN)) { | ||
| 1706 | return -EPERM; | 1703 | return -EPERM; |
| 1707 | } | 1704 | |
| 1708 | #endif | 1705 | lock_kernel(); |
| 1709 | 1706 | ||
| 1710 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); | 1707 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); |
| 1711 | 1708 | ||
| @@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
| 1720 | for (i = 0; i < SX_NBOARDS; i++) | 1717 | for (i = 0; i < SX_NBOARDS; i++) |
| 1721 | sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); | 1718 | sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); |
| 1722 | sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); | 1719 | sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); |
| 1720 | unlock_kernel(); | ||
| 1723 | return -EIO; | 1721 | return -EIO; |
| 1724 | } | 1722 | } |
| 1725 | 1723 | ||
| 1726 | switch (cmd) { | 1724 | switch (cmd) { |
| 1727 | case SXIO_SET_BOARD: | 1725 | case SXIO_SET_BOARD: |
| 1728 | sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); | 1726 | sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); |
| 1727 | rc = -EIO; | ||
| 1729 | if (arg >= SX_NBOARDS) | 1728 | if (arg >= SX_NBOARDS) |
| 1730 | return -EIO; | 1729 | break; |
| 1731 | sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); | 1730 | sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); |
| 1732 | if (!(boards[arg].flags & SX_BOARD_PRESENT)) | 1731 | if (!(boards[arg].flags & SX_BOARD_PRESENT)) |
| 1733 | return -EIO; | 1732 | break; |
| 1734 | sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); | 1733 | sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); |
| 1735 | board = &boards[arg]; | 1734 | board = &boards[arg]; |
| 1735 | rc = 0; | ||
| 1736 | /* FIXME: And this does ... nothing?? */ | ||
| 1736 | break; | 1737 | break; |
| 1737 | case SXIO_GET_TYPE: | 1738 | case SXIO_GET_TYPE: |
| 1738 | rc = -ENOENT; /* If we manage to miss one, return error. */ | 1739 | rc = -ENOENT; /* If we manage to miss one, return error. */ |
| @@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
| 1746 | rc = SX_TYPE_SI; | 1747 | rc = SX_TYPE_SI; |
| 1747 | if (IS_EISA_BOARD(board)) | 1748 | if (IS_EISA_BOARD(board)) |
| 1748 | rc = SX_TYPE_SI; | 1749 | rc = SX_TYPE_SI; |
| 1749 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); | 1750 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc); |
| 1750 | break; | 1751 | break; |
| 1751 | case SXIO_DO_RAMTEST: | 1752 | case SXIO_DO_RAMTEST: |
| 1752 | if (sx_initialized) /* Already initialized: better not ramtest the board. */ | 1753 | if (sx_initialized) /* Already initialized: better not ramtest the board. */ |
| @@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
| 1760 | rc = do_memtest(board, 0, 0x7ff8); | 1761 | rc = do_memtest(board, 0, 0x7ff8); |
| 1761 | /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ | 1762 | /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ |
| 1762 | } | 1763 | } |
| 1763 | sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", | 1764 | sx_dprintk(SX_DEBUG_FIRMWARE, |
| 1764 | rc); | 1765 | "returning memtest result= %ld\n", rc); |
| 1765 | break; | 1766 | break; |
| 1766 | case SXIO_DOWNLOAD: | 1767 | case SXIO_DOWNLOAD: |
| 1767 | if (sx_initialized) /* Already initialized */ | 1768 | if (sx_initialized) {/* Already initialized */ |
| 1768 | return -EEXIST; | 1769 | rc = -EEXIST; |
| 1769 | if (!sx_reset(board)) | 1770 | break; |
| 1770 | return -EIO; | 1771 | } |
| 1772 | if (!sx_reset(board)) { | ||
| 1773 | rc = -EIO; | ||
| 1774 | break; | ||
| 1775 | } | ||
| 1771 | sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); | 1776 | sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); |
| 1772 | 1777 | ||
| 1773 | tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); | 1778 | tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); |
| 1774 | if (!tmp) | 1779 | if (!tmp) { |
| 1775 | return -ENOMEM; | 1780 | rc = -ENOMEM; |
| 1781 | break; | ||
| 1782 | } | ||
| 1783 | /* FIXME: check returns */ | ||
| 1776 | get_user(nbytes, descr++); | 1784 | get_user(nbytes, descr++); |
| 1777 | get_user(offset, descr++); | 1785 | get_user(offset, descr++); |
| 1778 | get_user(data, descr++); | 1786 | get_user(data, descr++); |
| @@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
| 1782 | (i + SX_CHUNK_SIZE > nbytes) ? | 1790 | (i + SX_CHUNK_SIZE > nbytes) ? |
| 1783 | nbytes - i : SX_CHUNK_SIZE)) { | 1791 | nbytes - i : SX_CHUNK_SIZE)) { |
| 1784 | kfree(tmp); | 1792 | kfree(tmp); |
| 1785 | return -EFAULT; | 1793 | rc = -EFAULT; |
| 1794 | break; | ||
| 1786 | } | 1795 | } |
| 1787 | memcpy_toio(board->base2 + offset + i, tmp, | 1796 | memcpy_toio(board->base2 + offset + i, tmp, |
| 1788 | (i + SX_CHUNK_SIZE > nbytes) ? | 1797 | (i + SX_CHUNK_SIZE > nbytes) ? |
| @@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
| 1798 | rc = sx_nports; | 1807 | rc = sx_nports; |
| 1799 | break; | 1808 | break; |
| 1800 | case SXIO_INIT: | 1809 | case SXIO_INIT: |
| 1801 | if (sx_initialized) /* Already initialized */ | 1810 | if (sx_initialized) { /* Already initialized */ |
| 1802 | return -EEXIST; | 1811 | rc = -EEXIST; |
| 1812 | break; | ||
| 1813 | } | ||
| 1803 | /* This is not allowed until all boards are initialized... */ | 1814 | /* This is not allowed until all boards are initialized... */ |
| 1804 | for (i = 0; i < SX_NBOARDS; i++) { | 1815 | for (i = 0; i < SX_NBOARDS; i++) { |
| 1805 | if ((boards[i].flags & SX_BOARD_PRESENT) && | 1816 | if ((boards[i].flags & SX_BOARD_PRESENT) && |
| 1806 | !(boards[i].flags & SX_BOARD_INITIALIZED)) | 1817 | !(boards[i].flags & SX_BOARD_INITIALIZED)) { |
| 1807 | return -EIO; | 1818 | rc = -EIO; |
| 1819 | break; | ||
| 1820 | } | ||
| 1808 | } | 1821 | } |
| 1809 | for (i = 0; i < SX_NBOARDS; i++) | 1822 | for (i = 0; i < SX_NBOARDS; i++) |
| 1810 | if (!(boards[i].flags & SX_BOARD_PRESENT)) | 1823 | if (!(boards[i].flags & SX_BOARD_PRESENT)) |
| @@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, | |||
| 1832 | rc = sx_nports; | 1845 | rc = sx_nports; |
| 1833 | break; | 1846 | break; |
| 1834 | default: | 1847 | default: |
| 1835 | printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", | 1848 | rc = -ENOTTY; |
| 1836 | cmd); | ||
| 1837 | break; | 1849 | break; |
| 1838 | } | 1850 | } |
| 1851 | unlock_kernel(); | ||
| 1839 | func_exit(); | 1852 | func_exit(); |
| 1840 | return rc; | 1853 | return rc; |
| 1841 | } | 1854 | } |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6f4d856df987..e1b46bc7e43c 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -3580,7 +3580,6 @@ void proc_clear_tty(struct task_struct *p) | |||
| 3580 | p->signal->tty = NULL; | 3580 | p->signal->tty = NULL; |
| 3581 | spin_unlock_irq(&p->sighand->siglock); | 3581 | spin_unlock_irq(&p->sighand->siglock); |
| 3582 | } | 3582 | } |
| 3583 | EXPORT_SYMBOL(proc_clear_tty); | ||
| 3584 | 3583 | ||
| 3585 | /* Called under the sighand lock */ | 3584 | /* Called under the sighand lock */ |
| 3586 | 3585 | ||
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index dc17fe3a88bc..d0f4eb6fdb7f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -46,6 +46,9 @@ static char *in, *inbuf; | |||
| 46 | /* The operations for our console. */ | 46 | /* The operations for our console. */ |
| 47 | static struct hv_ops virtio_cons; | 47 | static struct hv_ops virtio_cons; |
| 48 | 48 | ||
| 49 | /* The hvc device */ | ||
| 50 | static struct hvc_struct *hvc; | ||
| 51 | |||
| 49 | /*D:310 The put_chars() callback is pretty straightforward. | 52 | /*D:310 The put_chars() callback is pretty straightforward. |
| 50 | * | 53 | * |
| 51 | * We turn the characters into a scatter-gather list, add it to the output | 54 | * We turn the characters into a scatter-gather list, add it to the output |
| @@ -134,6 +137,27 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | |||
| 134 | return hvc_instantiate(0, 0, &virtio_cons); | 137 | return hvc_instantiate(0, 0, &virtio_cons); |
| 135 | } | 138 | } |
| 136 | 139 | ||
| 140 | /* | ||
| 141 | * we support only one console, the hvc struct is a global var | ||
| 142 | * There is no need to do anything | ||
| 143 | */ | ||
| 144 | static int notifier_add_vio(struct hvc_struct *hp, int data) | ||
| 145 | { | ||
| 146 | hp->irq_requested = 1; | ||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | static void notifier_del_vio(struct hvc_struct *hp, int data) | ||
| 151 | { | ||
| 152 | hp->irq_requested = 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static void hvc_handle_input(struct virtqueue *vq) | ||
| 156 | { | ||
| 157 | if (hvc_poll(hvc)) | ||
| 158 | hvc_kick(); | ||
| 159 | } | ||
| 160 | |||
| 137 | /*D:370 Once we're further in boot, we get probed like any other virtio device. | 161 | /*D:370 Once we're further in boot, we get probed like any other virtio device. |
| 138 | * At this stage we set up the output virtqueue. | 162 | * At this stage we set up the output virtqueue. |
| 139 | * | 163 | * |
| @@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | |||
| 144 | static int __devinit virtcons_probe(struct virtio_device *dev) | 168 | static int __devinit virtcons_probe(struct virtio_device *dev) |
| 145 | { | 169 | { |
| 146 | int err; | 170 | int err; |
| 147 | struct hvc_struct *hvc; | ||
| 148 | 171 | ||
| 149 | vdev = dev; | 172 | vdev = dev; |
| 150 | 173 | ||
| @@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
| 158 | /* Find the input queue. */ | 181 | /* Find the input queue. */ |
| 159 | /* FIXME: This is why we want to wean off hvc: we do nothing | 182 | /* FIXME: This is why we want to wean off hvc: we do nothing |
| 160 | * when input comes in. */ | 183 | * when input comes in. */ |
| 161 | in_vq = vdev->config->find_vq(vdev, 0, NULL); | 184 | in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input); |
| 162 | if (IS_ERR(in_vq)) { | 185 | if (IS_ERR(in_vq)) { |
| 163 | err = PTR_ERR(in_vq); | 186 | err = PTR_ERR(in_vq); |
| 164 | goto free; | 187 | goto free; |
| @@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
| 173 | /* Start using the new console output. */ | 196 | /* Start using the new console output. */ |
| 174 | virtio_cons.get_chars = get_chars; | 197 | virtio_cons.get_chars = get_chars; |
| 175 | virtio_cons.put_chars = put_chars; | 198 | virtio_cons.put_chars = put_chars; |
| 199 | virtio_cons.notifier_add = notifier_add_vio; | ||
| 200 | virtio_cons.notifier_del = notifier_del_vio; | ||
| 176 | 201 | ||
| 177 | /* The first argument of hvc_alloc() is the virtual console number, so | 202 | /* The first argument of hvc_alloc() is the virtual console number, so |
| 178 | * we use zero. The second argument is the interrupt number; we | 203 | * we use zero. The second argument is the parameter for the |
| 179 | * currently leave this as zero: it would be better not to use the | 204 | * notification mechanism (like irq number). We currently leave this |
| 180 | * hvc mechanism and fix this (FIXME!). | 205 | * as zero, virtqueues have implicit notifications. |
| 181 | * | 206 | * |
| 182 | * The third argument is a "struct hv_ops" containing the put_chars() | 207 | * The third argument is a "struct hv_ops" containing the put_chars() |
| 183 | * and get_chars() pointers. The final argument is the output buffer | 208 | * get_chars(), notifier_add() and notifier_del() pointers. |
| 184 | * size: we can do any size, so we put PAGE_SIZE here. */ | 209 | * The final argument is the output buffer size: we can do any size, |
| 210 | * so we put PAGE_SIZE here. */ | ||
| 185 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); | 211 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); |
| 186 | if (IS_ERR(hvc)) { | 212 | if (IS_ERR(hvc)) { |
| 187 | err = PTR_ERR(hvc); | 213 | err = PTR_ERR(hvc); |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index cb8c90da3934..82a51f38a546 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
| @@ -2211,7 +2211,7 @@ rescan_last_byte: | |||
| 2211 | c = 0xfffd; | 2211 | c = 0xfffd; |
| 2212 | tc = c; | 2212 | tc = c; |
| 2213 | } else { /* no utf or alternate charset mode */ | 2213 | } else { /* no utf or alternate charset mode */ |
| 2214 | tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; | 2214 | tc = vc_translate(vc, c); |
| 2215 | } | 2215 | } |
| 2216 | 2216 | ||
| 2217 | param.c = tc; | 2217 | param.c = tc; |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 51966ccf4ea3..8bfee5fb7223 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
| @@ -87,7 +87,6 @@ | |||
| 87 | #include <linux/mutex.h> | 87 | #include <linux/mutex.h> |
| 88 | #include <linux/smp_lock.h> | 88 | #include <linux/smp_lock.h> |
| 89 | #include <linux/sysctl.h> | 89 | #include <linux/sysctl.h> |
| 90 | #include <linux/version.h> | ||
| 91 | #include <linux/fs.h> | 90 | #include <linux/fs.h> |
| 92 | #include <linux/cdev.h> | 91 | #include <linux/cdev.h> |
| 93 | #include <linux/platform_device.h> | 92 | #include <linux/platform_device.h> |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 6e6c3c4aea6b..5a11e3cbcae2 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
| @@ -123,6 +123,13 @@ config EDAC_I5000 | |||
| 123 | Support for error detection and correction the Intel | 123 | Support for error detection and correction the Intel |
| 124 | Greekcreek/Blackford chipsets. | 124 | Greekcreek/Blackford chipsets. |
| 125 | 125 | ||
| 126 | config EDAC_I5100 | ||
| 127 | tristate "Intel San Clemente MCH" | ||
| 128 | depends on EDAC_MM_EDAC && X86 && PCI | ||
| 129 | help | ||
| 130 | Support for error detection and correction the Intel | ||
| 131 | San Clemente MCH. | ||
| 132 | |||
| 126 | config EDAC_MPC85XX | 133 | config EDAC_MPC85XX |
| 127 | tristate "Freescale MPC85xx" | 134 | tristate "Freescale MPC85xx" |
| 128 | depends on EDAC_MM_EDAC && FSL_SOC && MPC85xx | 135 | depends on EDAC_MM_EDAC && FSL_SOC && MPC85xx |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 83807731d4a9..e5e9104b5520 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
| @@ -19,6 +19,7 @@ endif | |||
| 19 | 19 | ||
| 20 | obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o | 20 | obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o |
| 21 | obj-$(CONFIG_EDAC_I5000) += i5000_edac.o | 21 | obj-$(CONFIG_EDAC_I5000) += i5000_edac.o |
| 22 | obj-$(CONFIG_EDAC_I5100) += i5100_edac.o | ||
| 22 | obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o | 23 | obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o |
| 23 | obj-$(CONFIG_EDAC_E752X) += e752x_edac.o | 24 | obj-$(CONFIG_EDAC_E752X) += e752x_edac.o |
| 24 | obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o | 25 | obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index c94a0eb492cb..facfdb1fa71c 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #define E752X_REVISION " Ver: 2.0.2 " __DATE__ | 28 | #define E752X_REVISION " Ver: 2.0.2 " __DATE__ |
| 29 | #define EDAC_MOD_STR "e752x_edac" | 29 | #define EDAC_MOD_STR "e752x_edac" |
| 30 | 30 | ||
| 31 | static int report_non_memory_errors; | ||
| 31 | static int force_function_unhide; | 32 | static int force_function_unhide; |
| 32 | static int sysbus_parity = -1; | 33 | static int sysbus_parity = -1; |
| 33 | 34 | ||
| @@ -117,7 +118,7 @@ static struct edac_pci_ctl_info *e752x_pci; | |||
| 117 | #define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */ | 118 | #define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */ |
| 118 | #define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */ | 119 | #define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */ |
| 119 | #define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */ | 120 | #define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */ |
| 120 | #define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI command reg (8b) */ | 121 | #define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI cmd reg (8b) */ |
| 121 | #define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */ | 122 | #define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */ |
| 122 | #define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */ | 123 | #define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */ |
| 123 | #define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */ | 124 | #define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */ |
| @@ -127,7 +128,7 @@ static struct edac_pci_ctl_info *e752x_pci; | |||
| 127 | /* error address register (32b) */ | 128 | /* error address register (32b) */ |
| 128 | /* | 129 | /* |
| 129 | * 31 Reserved | 130 | * 31 Reserved |
| 130 | * 30:2 CE address (64 byte block 34:6) | 131 | * 30:2 CE address (64 byte block 34:6 |
| 131 | * 1 Reserved | 132 | * 1 Reserved |
| 132 | * 0 HiLoCS | 133 | * 0 HiLoCS |
| 133 | */ | 134 | */ |
| @@ -147,11 +148,11 @@ static struct edac_pci_ctl_info *e752x_pci; | |||
| 147 | * 1 Reserved | 148 | * 1 Reserved |
| 148 | * 0 HiLoCS | 149 | * 0 HiLoCS |
| 149 | */ | 150 | */ |
| 150 | #define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM first uncorrectable scrub memory */ | 151 | #define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM 1st uncorrectable scrub mem */ |
| 151 | /* error address register (32b) */ | 152 | /* error address register (32b) */ |
| 152 | /* | 153 | /* |
| 153 | * 31 Reserved | 154 | * 31 Reserved |
| 154 | * 30:2 CE address (64 byte block 34:6) | 155 | * 30:2 CE address (64 byte block 34:6 |
| 155 | * 1 Reserved | 156 | * 1 Reserved |
| 156 | * 0 HiLoCS | 157 | * 0 HiLoCS |
| 157 | */ | 158 | */ |
| @@ -394,9 +395,12 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, | |||
| 394 | struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; | 395 | struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; |
| 395 | 396 | ||
| 396 | error_1b = retry_add; | 397 | error_1b = retry_add; |
| 397 | page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ | 398 | page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */ |
| 398 | row = pvt->mc_symmetric ? ((page >> 1) & 3) : /* chip select are bits 14 & 13 */ | 399 | |
| 400 | /* chip select are bits 14 & 13 */ | ||
| 401 | row = pvt->mc_symmetric ? ((page >> 1) & 3) : | ||
| 399 | edac_mc_find_csrow_by_page(mci, page); | 402 | edac_mc_find_csrow_by_page(mci, page); |
| 403 | |||
| 400 | e752x_mc_printk(mci, KERN_WARNING, | 404 | e752x_mc_printk(mci, KERN_WARNING, |
| 401 | "CE page 0x%lx, row %d : Memory read retry\n", | 405 | "CE page 0x%lx, row %d : Memory read retry\n", |
| 402 | (long unsigned int)page, row); | 406 | (long unsigned int)page, row); |
| @@ -422,12 +426,21 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error, | |||
| 422 | } | 426 | } |
| 423 | 427 | ||
| 424 | static char *global_message[11] = { | 428 | static char *global_message[11] = { |
| 425 | "PCI Express C1", "PCI Express C", "PCI Express B1", | 429 | "PCI Express C1", |
| 426 | "PCI Express B", "PCI Express A1", "PCI Express A", | 430 | "PCI Express C", |
| 427 | "DMA Controler", "HUB or NS Interface", "System Bus", | 431 | "PCI Express B1", |
| 428 | "DRAM Controler", "Internal Buffer" | 432 | "PCI Express B", |
| 433 | "PCI Express A1", | ||
| 434 | "PCI Express A", | ||
| 435 | "DMA Controller", | ||
| 436 | "HUB or NS Interface", | ||
| 437 | "System Bus", | ||
| 438 | "DRAM Controller", /* 9th entry */ | ||
| 439 | "Internal Buffer" | ||
| 429 | }; | 440 | }; |
| 430 | 441 | ||
| 442 | #define DRAM_ENTRY 9 | ||
| 443 | |||
| 431 | static char *fatal_message[2] = { "Non-Fatal ", "Fatal " }; | 444 | static char *fatal_message[2] = { "Non-Fatal ", "Fatal " }; |
| 432 | 445 | ||
| 433 | static void do_global_error(int fatal, u32 errors) | 446 | static void do_global_error(int fatal, u32 errors) |
| @@ -435,9 +448,16 @@ static void do_global_error(int fatal, u32 errors) | |||
| 435 | int i; | 448 | int i; |
| 436 | 449 | ||
| 437 | for (i = 0; i < 11; i++) { | 450 | for (i = 0; i < 11; i++) { |
| 438 | if (errors & (1 << i)) | 451 | if (errors & (1 << i)) { |
| 439 | e752x_printk(KERN_WARNING, "%sError %s\n", | 452 | /* If the error is from DRAM Controller OR |
| 440 | fatal_message[fatal], global_message[i]); | 453 | * we are to report ALL errors, then |
| 454 | * report the error | ||
| 455 | */ | ||
| 456 | if ((i == DRAM_ENTRY) || report_non_memory_errors) | ||
| 457 | e752x_printk(KERN_WARNING, "%sError %s\n", | ||
| 458 | fatal_message[fatal], | ||
| 459 | global_message[i]); | ||
| 460 | } | ||
| 441 | } | 461 | } |
| 442 | } | 462 | } |
| 443 | 463 | ||
| @@ -1021,7 +1041,7 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx, | |||
| 1021 | struct pci_dev *dev; | 1041 | struct pci_dev *dev; |
| 1022 | 1042 | ||
| 1023 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, | 1043 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, |
| 1024 | pvt->dev_info->err_dev, pvt->bridge_ck); | 1044 | pvt->dev_info->err_dev, pvt->bridge_ck); |
| 1025 | 1045 | ||
| 1026 | if (pvt->bridge_ck == NULL) | 1046 | if (pvt->bridge_ck == NULL) |
| 1027 | pvt->bridge_ck = pci_scan_single_device(pdev->bus, | 1047 | pvt->bridge_ck = pci_scan_single_device(pdev->bus, |
| @@ -1034,8 +1054,9 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx, | |||
| 1034 | return 1; | 1054 | return 1; |
| 1035 | } | 1055 | } |
| 1036 | 1056 | ||
| 1037 | dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev, | 1057 | dev = pci_get_device(PCI_VENDOR_ID_INTEL, |
| 1038 | NULL); | 1058 | e752x_devs[dev_idx].ctl_dev, |
| 1059 | NULL); | ||
| 1039 | 1060 | ||
| 1040 | if (dev == NULL) | 1061 | if (dev == NULL) |
| 1041 | goto fail; | 1062 | goto fail; |
| @@ -1316,7 +1337,8 @@ MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers"); | |||
| 1316 | 1337 | ||
| 1317 | module_param(force_function_unhide, int, 0444); | 1338 | module_param(force_function_unhide, int, 0444); |
| 1318 | MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:" | 1339 | MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:" |
| 1319 | " 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access"); | 1340 | " 1=force unhide and hope BIOS doesn't fight driver for " |
| 1341 | "Dev0:Fun1 access"); | ||
| 1320 | 1342 | ||
| 1321 | module_param(edac_op_state, int, 0444); | 1343 | module_param(edac_op_state, int, 0444); |
| 1322 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); | 1344 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); |
| @@ -1324,3 +1346,6 @@ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); | |||
| 1324 | module_param(sysbus_parity, int, 0444); | 1346 | module_param(sysbus_parity, int, 0444); |
| 1325 | MODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking," | 1347 | MODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking," |
| 1326 | " 1=enable system bus parity checking, default=auto-detect"); | 1348 | " 1=enable system bus parity checking, default=auto-detect"); |
| 1349 | module_param(report_non_memory_errors, int, 0644); | ||
| 1350 | MODULE_PARM_DESC(report_non_memory_errors, "0=disable non-memory error " | ||
| 1351 | "reporting, 1=enable non-memory error reporting"); | ||
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 021d18795145..ad218fe4942d 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
| @@ -44,6 +44,25 @@ int edac_mc_get_poll_msec(void) | |||
| 44 | return edac_mc_poll_msec; | 44 | return edac_mc_poll_msec; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | static int edac_set_poll_msec(const char *val, struct kernel_param *kp) | ||
| 48 | { | ||
| 49 | long l; | ||
| 50 | int ret; | ||
| 51 | |||
| 52 | if (!val) | ||
| 53 | return -EINVAL; | ||
| 54 | |||
| 55 | ret = strict_strtol(val, 0, &l); | ||
| 56 | if (ret == -EINVAL || ((int)l != l)) | ||
| 57 | return -EINVAL; | ||
| 58 | *((int *)kp->arg) = l; | ||
| 59 | |||
| 60 | /* notify edac_mc engine to reset the poll period */ | ||
| 61 | edac_mc_reset_delay_period(l); | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 47 | /* Parameter declarations for above */ | 66 | /* Parameter declarations for above */ |
| 48 | module_param(edac_mc_panic_on_ue, int, 0644); | 67 | module_param(edac_mc_panic_on_ue, int, 0644); |
| 49 | MODULE_PARM_DESC(edac_mc_panic_on_ue, "Panic on uncorrected error: 0=off 1=on"); | 68 | MODULE_PARM_DESC(edac_mc_panic_on_ue, "Panic on uncorrected error: 0=off 1=on"); |
| @@ -53,7 +72,8 @@ MODULE_PARM_DESC(edac_mc_log_ue, | |||
| 53 | module_param(edac_mc_log_ce, int, 0644); | 72 | module_param(edac_mc_log_ce, int, 0644); |
| 54 | MODULE_PARM_DESC(edac_mc_log_ce, | 73 | MODULE_PARM_DESC(edac_mc_log_ce, |
| 55 | "Log correctable error to console: 0=off 1=on"); | 74 | "Log correctable error to console: 0=off 1=on"); |
| 56 | module_param(edac_mc_poll_msec, int, 0644); | 75 | module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int, |
| 76 | &edac_mc_poll_msec, 0644); | ||
| 57 | MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds"); | 77 | MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds"); |
| 58 | 78 | ||
| 59 | /* | 79 | /* |
| @@ -103,16 +123,6 @@ static const char *edac_caps[] = { | |||
| 103 | 123 | ||
| 104 | 124 | ||
| 105 | 125 | ||
| 106 | /* | ||
| 107 | * /sys/devices/system/edac/mc; | ||
| 108 | * data structures and methods | ||
| 109 | */ | ||
| 110 | static ssize_t memctrl_int_show(void *ptr, char *buffer) | ||
| 111 | { | ||
| 112 | int *value = (int *)ptr; | ||
| 113 | return sprintf(buffer, "%u\n", *value); | ||
| 114 | } | ||
| 115 | |||
| 116 | static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) | 126 | static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) |
| 117 | { | 127 | { |
| 118 | int *value = (int *)ptr; | 128 | int *value = (int *)ptr; |
| @@ -123,23 +133,6 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) | |||
| 123 | return count; | 133 | return count; |
| 124 | } | 134 | } |
| 125 | 135 | ||
| 126 | /* | ||
| 127 | * mc poll_msec time value | ||
| 128 | */ | ||
| 129 | static ssize_t poll_msec_int_store(void *ptr, const char *buffer, size_t count) | ||
| 130 | { | ||
| 131 | int *value = (int *)ptr; | ||
| 132 | |||
| 133 | if (isdigit(*buffer)) { | ||
| 134 | *value = simple_strtoul(buffer, NULL, 0); | ||
| 135 | |||
| 136 | /* notify edac_mc engine to reset the poll period */ | ||
| 137 | edac_mc_reset_delay_period(*value); | ||
| 138 | } | ||
| 139 | |||
| 140 | return count; | ||
| 141 | } | ||
| 142 | |||
| 143 | 136 | ||
| 144 | /* EDAC sysfs CSROW data structures and methods | 137 | /* EDAC sysfs CSROW data structures and methods |
| 145 | */ | 138 | */ |
| @@ -185,7 +178,11 @@ static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, | |||
| 185 | static ssize_t channel_dimm_label_show(struct csrow_info *csrow, | 178 | static ssize_t channel_dimm_label_show(struct csrow_info *csrow, |
| 186 | char *data, int channel) | 179 | char *data, int channel) |
| 187 | { | 180 | { |
| 188 | return snprintf(data, EDAC_MC_LABEL_LEN, "%s", | 181 | /* if field has not been initialized, there is nothing to send */ |
| 182 | if (!csrow->channels[channel].label[0]) | ||
| 183 | return 0; | ||
| 184 | |||
| 185 | return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", | ||
| 189 | csrow->channels[channel].label); | 186 | csrow->channels[channel].label); |
| 190 | } | 187 | } |
| 191 | 188 | ||
| @@ -649,98 +646,10 @@ static struct kobj_type ktype_mci = { | |||
| 649 | .default_attrs = (struct attribute **)mci_attr, | 646 | .default_attrs = (struct attribute **)mci_attr, |
| 650 | }; | 647 | }; |
| 651 | 648 | ||
| 652 | /* show/store, tables, etc for the MC kset */ | ||
| 653 | |||
| 654 | |||
| 655 | struct memctrl_dev_attribute { | ||
| 656 | struct attribute attr; | ||
| 657 | void *value; | ||
| 658 | ssize_t(*show) (void *, char *); | ||
| 659 | ssize_t(*store) (void *, const char *, size_t); | ||
| 660 | }; | ||
| 661 | |||
| 662 | /* Set of show/store abstract level functions for memory control object */ | ||
| 663 | static ssize_t memctrl_dev_show(struct kobject *kobj, | ||
| 664 | struct attribute *attr, char *buffer) | ||
| 665 | { | ||
| 666 | struct memctrl_dev_attribute *memctrl_dev; | ||
| 667 | memctrl_dev = (struct memctrl_dev_attribute *)attr; | ||
| 668 | |||
| 669 | if (memctrl_dev->show) | ||
| 670 | return memctrl_dev->show(memctrl_dev->value, buffer); | ||
| 671 | |||
| 672 | return -EIO; | ||
| 673 | } | ||
| 674 | |||
| 675 | static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr, | ||
| 676 | const char *buffer, size_t count) | ||
| 677 | { | ||
| 678 | struct memctrl_dev_attribute *memctrl_dev; | ||
| 679 | memctrl_dev = (struct memctrl_dev_attribute *)attr; | ||
| 680 | |||
| 681 | if (memctrl_dev->store) | ||
| 682 | return memctrl_dev->store(memctrl_dev->value, buffer, count); | ||
| 683 | |||
| 684 | return -EIO; | ||
| 685 | } | ||
| 686 | |||
| 687 | static struct sysfs_ops memctrlfs_ops = { | ||
| 688 | .show = memctrl_dev_show, | ||
| 689 | .store = memctrl_dev_store | ||
| 690 | }; | ||
| 691 | |||
| 692 | #define MEMCTRL_ATTR(_name, _mode, _show, _store) \ | ||
| 693 | static struct memctrl_dev_attribute attr_##_name = { \ | ||
| 694 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
| 695 | .value = &_name, \ | ||
| 696 | .show = _show, \ | ||
| 697 | .store = _store, \ | ||
| 698 | }; | ||
| 699 | |||
| 700 | #define MEMCTRL_STRING_ATTR(_name, _data, _mode, _show, _store) \ | ||
| 701 | static struct memctrl_dev_attribute attr_##_name = { \ | ||
| 702 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
| 703 | .value = _data, \ | ||
| 704 | .show = _show, \ | ||
| 705 | .store = _store, \ | ||
| 706 | }; | ||
| 707 | |||
| 708 | /* csrow<id> control files */ | ||
| 709 | MEMCTRL_ATTR(edac_mc_panic_on_ue, | ||
| 710 | S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store); | ||
| 711 | |||
| 712 | MEMCTRL_ATTR(edac_mc_log_ue, | ||
| 713 | S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store); | ||
| 714 | |||
| 715 | MEMCTRL_ATTR(edac_mc_log_ce, | ||
| 716 | S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store); | ||
| 717 | |||
| 718 | MEMCTRL_ATTR(edac_mc_poll_msec, | ||
| 719 | S_IRUGO | S_IWUSR, memctrl_int_show, poll_msec_int_store); | ||
| 720 | |||
| 721 | /* Base Attributes of the memory ECC object */ | ||
| 722 | static struct memctrl_dev_attribute *memctrl_attr[] = { | ||
| 723 | &attr_edac_mc_panic_on_ue, | ||
| 724 | &attr_edac_mc_log_ue, | ||
| 725 | &attr_edac_mc_log_ce, | ||
| 726 | &attr_edac_mc_poll_msec, | ||
| 727 | NULL, | ||
| 728 | }; | ||
| 729 | |||
| 730 | |||
| 731 | /* the ktype for the mc_kset internal kobj */ | ||
| 732 | static struct kobj_type ktype_mc_set_attribs = { | ||
| 733 | .sysfs_ops = &memctrlfs_ops, | ||
| 734 | .default_attrs = (struct attribute **)memctrl_attr, | ||
| 735 | }; | ||
| 736 | |||
| 737 | /* EDAC memory controller sysfs kset: | 649 | /* EDAC memory controller sysfs kset: |
| 738 | * /sys/devices/system/edac/mc | 650 | * /sys/devices/system/edac/mc |
| 739 | */ | 651 | */ |
| 740 | static struct kset mc_kset = { | 652 | static struct kset *mc_kset; |
| 741 | .kobj = {.ktype = &ktype_mc_set_attribs }, | ||
| 742 | }; | ||
| 743 | |||
| 744 | 653 | ||
| 745 | /* | 654 | /* |
| 746 | * edac_mc_register_sysfs_main_kobj | 655 | * edac_mc_register_sysfs_main_kobj |
| @@ -771,7 +680,7 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci) | |||
| 771 | } | 680 | } |
| 772 | 681 | ||
| 773 | /* this instance become part of the mc_kset */ | 682 | /* this instance become part of the mc_kset */ |
| 774 | kobj_mci->kset = &mc_kset; | 683 | kobj_mci->kset = mc_kset; |
| 775 | 684 | ||
| 776 | /* register the mc<id> kobject to the mc_kset */ | 685 | /* register the mc<id> kobject to the mc_kset */ |
| 777 | err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL, | 686 | err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL, |
| @@ -1001,12 +910,9 @@ int edac_sysfs_setup_mc_kset(void) | |||
| 1001 | } | 910 | } |
| 1002 | 911 | ||
| 1003 | /* Init the MC's kobject */ | 912 | /* Init the MC's kobject */ |
| 1004 | kobject_set_name(&mc_kset.kobj, "mc"); | 913 | mc_kset = kset_create_and_add("mc", NULL, &edac_class->kset.kobj); |
| 1005 | mc_kset.kobj.parent = &edac_class->kset.kobj; | 914 | if (!mc_kset) { |
| 1006 | 915 | err = -ENOMEM; | |
| 1007 | /* register the mc_kset */ | ||
| 1008 | err = kset_register(&mc_kset); | ||
| 1009 | if (err) { | ||
| 1010 | debugf1("%s() Failed to register '.../edac/mc'\n", __func__); | 916 | debugf1("%s() Failed to register '.../edac/mc'\n", __func__); |
| 1011 | goto fail_out; | 917 | goto fail_out; |
| 1012 | } | 918 | } |
| @@ -1028,6 +934,6 @@ fail_out: | |||
| 1028 | */ | 934 | */ |
| 1029 | void edac_sysfs_teardown_mc_kset(void) | 935 | void edac_sysfs_teardown_mc_kset(void) |
| 1030 | { | 936 | { |
| 1031 | kset_unregister(&mc_kset); | 937 | kset_unregister(mc_kset); |
| 1032 | } | 938 | } |
| 1033 | 939 | ||
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 2c1fa1bb6df2..5c153dccc95e 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c | |||
| @@ -28,7 +28,7 @@ static int edac_pci_poll_msec = 1000; /* one second workq period */ | |||
| 28 | static atomic_t pci_parity_count = ATOMIC_INIT(0); | 28 | static atomic_t pci_parity_count = ATOMIC_INIT(0); |
| 29 | static atomic_t pci_nonparity_count = ATOMIC_INIT(0); | 29 | static atomic_t pci_nonparity_count = ATOMIC_INIT(0); |
| 30 | 30 | ||
| 31 | static struct kobject edac_pci_top_main_kobj; | 31 | static struct kobject *edac_pci_top_main_kobj; |
| 32 | static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0); | 32 | static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0); |
| 33 | 33 | ||
| 34 | /* getter functions for the data variables */ | 34 | /* getter functions for the data variables */ |
| @@ -83,7 +83,7 @@ static void edac_pci_instance_release(struct kobject *kobj) | |||
| 83 | pci = to_instance(kobj); | 83 | pci = to_instance(kobj); |
| 84 | 84 | ||
| 85 | /* decrement reference count on top main kobj */ | 85 | /* decrement reference count on top main kobj */ |
| 86 | kobject_put(&edac_pci_top_main_kobj); | 86 | kobject_put(edac_pci_top_main_kobj); |
| 87 | 87 | ||
| 88 | kfree(pci); /* Free the control struct */ | 88 | kfree(pci); /* Free the control struct */ |
| 89 | } | 89 | } |
| @@ -166,7 +166,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) | |||
| 166 | * track the number of PCI instances we have, and thus nest | 166 | * track the number of PCI instances we have, and thus nest |
| 167 | * properly on keeping the module loaded | 167 | * properly on keeping the module loaded |
| 168 | */ | 168 | */ |
| 169 | main_kobj = kobject_get(&edac_pci_top_main_kobj); | 169 | main_kobj = kobject_get(edac_pci_top_main_kobj); |
| 170 | if (!main_kobj) { | 170 | if (!main_kobj) { |
| 171 | err = -ENODEV; | 171 | err = -ENODEV; |
| 172 | goto error_out; | 172 | goto error_out; |
| @@ -174,11 +174,11 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) | |||
| 174 | 174 | ||
| 175 | /* And now register this new kobject under the main kobj */ | 175 | /* And now register this new kobject under the main kobj */ |
| 176 | err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance, | 176 | err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance, |
| 177 | &edac_pci_top_main_kobj, "pci%d", idx); | 177 | edac_pci_top_main_kobj, "pci%d", idx); |
| 178 | if (err != 0) { | 178 | if (err != 0) { |
| 179 | debugf2("%s() failed to register instance pci%d\n", | 179 | debugf2("%s() failed to register instance pci%d\n", |
| 180 | __func__, idx); | 180 | __func__, idx); |
| 181 | kobject_put(&edac_pci_top_main_kobj); | 181 | kobject_put(edac_pci_top_main_kobj); |
| 182 | goto error_out; | 182 | goto error_out; |
| 183 | } | 183 | } |
| 184 | 184 | ||
| @@ -316,9 +316,10 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { | |||
| 316 | */ | 316 | */ |
| 317 | static void edac_pci_release_main_kobj(struct kobject *kobj) | 317 | static void edac_pci_release_main_kobj(struct kobject *kobj) |
| 318 | { | 318 | { |
| 319 | |||
| 320 | debugf0("%s() here to module_put(THIS_MODULE)\n", __func__); | 319 | debugf0("%s() here to module_put(THIS_MODULE)\n", __func__); |
| 321 | 320 | ||
| 321 | kfree(kobj); | ||
| 322 | |||
| 322 | /* last reference to top EDAC PCI kobject has been removed, | 323 | /* last reference to top EDAC PCI kobject has been removed, |
| 323 | * NOW release our ref count on the core module | 324 | * NOW release our ref count on the core module |
| 324 | */ | 325 | */ |
| @@ -369,8 +370,16 @@ static int edac_pci_main_kobj_setup(void) | |||
| 369 | goto decrement_count_fail; | 370 | goto decrement_count_fail; |
| 370 | } | 371 | } |
| 371 | 372 | ||
| 373 | edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); | ||
| 374 | if (!edac_pci_top_main_kobj) { | ||
| 375 | debugf1("Failed to allocate\n"); | ||
| 376 | err = -ENOMEM; | ||
| 377 | goto kzalloc_fail; | ||
| 378 | } | ||
| 379 | |||
| 372 | /* Instanstiate the pci object */ | 380 | /* Instanstiate the pci object */ |
| 373 | err = kobject_init_and_add(&edac_pci_top_main_kobj, &ktype_edac_pci_main_kobj, | 381 | err = kobject_init_and_add(edac_pci_top_main_kobj, |
| 382 | &ktype_edac_pci_main_kobj, | ||
| 374 | &edac_class->kset.kobj, "pci"); | 383 | &edac_class->kset.kobj, "pci"); |
| 375 | if (err) { | 384 | if (err) { |
| 376 | debugf1("Failed to register '.../edac/pci'\n"); | 385 | debugf1("Failed to register '.../edac/pci'\n"); |
| @@ -381,13 +390,16 @@ static int edac_pci_main_kobj_setup(void) | |||
| 381 | * for EDAC PCI, then edac_pci_main_kobj_teardown() | 390 | * for EDAC PCI, then edac_pci_main_kobj_teardown() |
| 382 | * must be used, for resources to be cleaned up properly | 391 | * must be used, for resources to be cleaned up properly |
| 383 | */ | 392 | */ |
| 384 | kobject_uevent(&edac_pci_top_main_kobj, KOBJ_ADD); | 393 | kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD); |
| 385 | debugf1("Registered '.../edac/pci' kobject\n"); | 394 | debugf1("Registered '.../edac/pci' kobject\n"); |
| 386 | 395 | ||
| 387 | return 0; | 396 | return 0; |
| 388 | 397 | ||
| 389 | /* Error unwind statck */ | 398 | /* Error unwind statck */ |
| 390 | kobject_init_and_add_fail: | 399 | kobject_init_and_add_fail: |
| 400 | kfree(edac_pci_top_main_kobj); | ||
| 401 | |||
| 402 | kzalloc_fail: | ||
| 391 | module_put(THIS_MODULE); | 403 | module_put(THIS_MODULE); |
| 392 | 404 | ||
| 393 | decrement_count_fail: | 405 | decrement_count_fail: |
| @@ -414,7 +426,7 @@ static void edac_pci_main_kobj_teardown(void) | |||
| 414 | if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { | 426 | if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { |
| 415 | debugf0("%s() called kobject_put on main kobj\n", | 427 | debugf0("%s() called kobject_put on main kobj\n", |
| 416 | __func__); | 428 | __func__); |
| 417 | kobject_put(&edac_pci_top_main_kobj); | 429 | kobject_put(edac_pci_top_main_kobj); |
| 418 | } | 430 | } |
| 419 | } | 431 | } |
| 420 | 432 | ||
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c new file mode 100644 index 000000000000..22db05a67bfb --- /dev/null +++ b/drivers/edac/i5100_edac.c | |||
| @@ -0,0 +1,981 @@ | |||
| 1 | /* | ||
| 2 | * Intel 5100 Memory Controllers kernel module | ||
| 3 | * | ||
| 4 | * This file may be distributed under the terms of the | ||
| 5 | * GNU General Public License. | ||
| 6 | * | ||
| 7 | * This module is based on the following document: | ||
| 8 | * | ||
| 9 | * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet | ||
| 10 | * http://download.intel.com/design/chipsets/datashts/318378.pdf | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/pci.h> | ||
| 16 | #include <linux/pci_ids.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/edac.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/mmzone.h> | ||
| 21 | |||
| 22 | #include "edac_core.h" | ||
| 23 | |||
| 24 | /* register addresses */ | ||
| 25 | |||
| 26 | /* device 16, func 1 */ | ||
| 27 | #define I5100_MC 0x40 /* Memory Control Register */ | ||
| 28 | #define I5100_MS 0x44 /* Memory Status Register */ | ||
| 29 | #define I5100_SPDDATA 0x48 /* Serial Presence Detect Status Reg */ | ||
| 30 | #define I5100_SPDCMD 0x4c /* Serial Presence Detect Command Reg */ | ||
| 31 | #define I5100_TOLM 0x6c /* Top of Low Memory */ | ||
| 32 | #define I5100_MIR0 0x80 /* Memory Interleave Range 0 */ | ||
| 33 | #define I5100_MIR1 0x84 /* Memory Interleave Range 1 */ | ||
| 34 | #define I5100_AMIR_0 0x8c /* Adjusted Memory Interleave Range 0 */ | ||
| 35 | #define I5100_AMIR_1 0x90 /* Adjusted Memory Interleave Range 1 */ | ||
| 36 | #define I5100_FERR_NF_MEM 0xa0 /* MC First Non Fatal Errors */ | ||
| 37 | #define I5100_FERR_NF_MEM_M16ERR_MASK (1 << 16) | ||
| 38 | #define I5100_FERR_NF_MEM_M15ERR_MASK (1 << 15) | ||
| 39 | #define I5100_FERR_NF_MEM_M14ERR_MASK (1 << 14) | ||
| 40 | #define I5100_FERR_NF_MEM_M12ERR_MASK (1 << 12) | ||
| 41 | #define I5100_FERR_NF_MEM_M11ERR_MASK (1 << 11) | ||
| 42 | #define I5100_FERR_NF_MEM_M10ERR_MASK (1 << 10) | ||
| 43 | #define I5100_FERR_NF_MEM_M6ERR_MASK (1 << 6) | ||
| 44 | #define I5100_FERR_NF_MEM_M5ERR_MASK (1 << 5) | ||
| 45 | #define I5100_FERR_NF_MEM_M4ERR_MASK (1 << 4) | ||
| 46 | #define I5100_FERR_NF_MEM_M1ERR_MASK 1 | ||
| 47 | #define I5100_FERR_NF_MEM_ANY_MASK \ | ||
| 48 | (I5100_FERR_NF_MEM_M16ERR_MASK | \ | ||
| 49 | I5100_FERR_NF_MEM_M15ERR_MASK | \ | ||
| 50 | I5100_FERR_NF_MEM_M14ERR_MASK | \ | ||
| 51 | I5100_FERR_NF_MEM_M12ERR_MASK | \ | ||
| 52 | I5100_FERR_NF_MEM_M11ERR_MASK | \ | ||
| 53 | I5100_FERR_NF_MEM_M10ERR_MASK | \ | ||
| 54 | I5100_FERR_NF_MEM_M6ERR_MASK | \ | ||
| 55 | I5100_FERR_NF_MEM_M5ERR_MASK | \ | ||
| 56 | I5100_FERR_NF_MEM_M4ERR_MASK | \ | ||
| 57 | I5100_FERR_NF_MEM_M1ERR_MASK) | ||
| 58 | #define I5100_NERR_NF_MEM 0xa4 /* MC Next Non-Fatal Errors */ | ||
| 59 | #define I5100_EMASK_MEM 0xa8 /* MC Error Mask Register */ | ||
| 60 | |||
| 61 | /* device 21 and 22, func 0 */ | ||
| 62 | #define I5100_MTR_0 0x154 /* Memory Technology Registers 0-3 */ | ||
| 63 | #define I5100_DMIR 0x15c /* DIMM Interleave Range */ | ||
| 64 | #define I5100_VALIDLOG 0x18c /* Valid Log Markers */ | ||
| 65 | #define I5100_NRECMEMA 0x190 /* Non-Recoverable Memory Error Log Reg A */ | ||
| 66 | #define I5100_NRECMEMB 0x194 /* Non-Recoverable Memory Error Log Reg B */ | ||
| 67 | #define I5100_REDMEMA 0x198 /* Recoverable Memory Data Error Log Reg A */ | ||
| 68 | #define I5100_REDMEMB 0x19c /* Recoverable Memory Data Error Log Reg B */ | ||
| 69 | #define I5100_RECMEMA 0x1a0 /* Recoverable Memory Error Log Reg A */ | ||
| 70 | #define I5100_RECMEMB 0x1a4 /* Recoverable Memory Error Log Reg B */ | ||
| 71 | #define I5100_MTR_4 0x1b0 /* Memory Technology Registers 4,5 */ | ||
| 72 | |||
| 73 | /* bit field accessors */ | ||
| 74 | |||
| 75 | static inline u32 i5100_mc_errdeten(u32 mc) | ||
| 76 | { | ||
| 77 | return mc >> 5 & 1; | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline u16 i5100_spddata_rdo(u16 a) | ||
| 81 | { | ||
| 82 | return a >> 15 & 1; | ||
| 83 | } | ||
| 84 | |||
| 85 | static inline u16 i5100_spddata_sbe(u16 a) | ||
| 86 | { | ||
| 87 | return a >> 13 & 1; | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline u16 i5100_spddata_busy(u16 a) | ||
| 91 | { | ||
| 92 | return a >> 12 & 1; | ||
| 93 | } | ||
| 94 | |||
| 95 | static inline u16 i5100_spddata_data(u16 a) | ||
| 96 | { | ||
| 97 | return a & ((1 << 8) - 1); | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline u32 i5100_spdcmd_create(u32 dti, u32 ckovrd, u32 sa, u32 ba, | ||
| 101 | u32 data, u32 cmd) | ||
| 102 | { | ||
| 103 | return ((dti & ((1 << 4) - 1)) << 28) | | ||
| 104 | ((ckovrd & 1) << 27) | | ||
| 105 | ((sa & ((1 << 3) - 1)) << 24) | | ||
| 106 | ((ba & ((1 << 8) - 1)) << 16) | | ||
| 107 | ((data & ((1 << 8) - 1)) << 8) | | ||
| 108 | (cmd & 1); | ||
| 109 | } | ||
| 110 | |||
| 111 | static inline u16 i5100_tolm_tolm(u16 a) | ||
| 112 | { | ||
| 113 | return a >> 12 & ((1 << 4) - 1); | ||
| 114 | } | ||
| 115 | |||
| 116 | static inline u16 i5100_mir_limit(u16 a) | ||
| 117 | { | ||
| 118 | return a >> 4 & ((1 << 12) - 1); | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline u16 i5100_mir_way1(u16 a) | ||
| 122 | { | ||
| 123 | return a >> 1 & 1; | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline u16 i5100_mir_way0(u16 a) | ||
| 127 | { | ||
| 128 | return a & 1; | ||
| 129 | } | ||
| 130 | |||
| 131 | static inline u32 i5100_ferr_nf_mem_chan_indx(u32 a) | ||
| 132 | { | ||
| 133 | return a >> 28 & 1; | ||
| 134 | } | ||
| 135 | |||
| 136 | static inline u32 i5100_ferr_nf_mem_any(u32 a) | ||
| 137 | { | ||
| 138 | return a & I5100_FERR_NF_MEM_ANY_MASK; | ||
| 139 | } | ||
| 140 | |||
| 141 | static inline u32 i5100_nerr_nf_mem_any(u32 a) | ||
| 142 | { | ||
| 143 | return i5100_ferr_nf_mem_any(a); | ||
| 144 | } | ||
| 145 | |||
| 146 | static inline u32 i5100_dmir_limit(u32 a) | ||
| 147 | { | ||
| 148 | return a >> 16 & ((1 << 11) - 1); | ||
| 149 | } | ||
| 150 | |||
| 151 | static inline u32 i5100_dmir_rank(u32 a, u32 i) | ||
| 152 | { | ||
| 153 | return a >> (4 * i) & ((1 << 2) - 1); | ||
| 154 | } | ||
| 155 | |||
| 156 | static inline u16 i5100_mtr_present(u16 a) | ||
| 157 | { | ||
| 158 | return a >> 10 & 1; | ||
| 159 | } | ||
| 160 | |||
| 161 | static inline u16 i5100_mtr_ethrottle(u16 a) | ||
| 162 | { | ||
| 163 | return a >> 9 & 1; | ||
| 164 | } | ||
| 165 | |||
| 166 | static inline u16 i5100_mtr_width(u16 a) | ||
| 167 | { | ||
| 168 | return a >> 8 & 1; | ||
| 169 | } | ||
| 170 | |||
| 171 | static inline u16 i5100_mtr_numbank(u16 a) | ||
| 172 | { | ||
| 173 | return a >> 6 & 1; | ||
| 174 | } | ||
| 175 | |||
| 176 | static inline u16 i5100_mtr_numrow(u16 a) | ||
| 177 | { | ||
| 178 | return a >> 2 & ((1 << 2) - 1); | ||
| 179 | } | ||
| 180 | |||
| 181 | static inline u16 i5100_mtr_numcol(u16 a) | ||
| 182 | { | ||
| 183 | return a & ((1 << 2) - 1); | ||
| 184 | } | ||
| 185 | |||
| 186 | |||
| 187 | static inline u32 i5100_validlog_redmemvalid(u32 a) | ||
| 188 | { | ||
| 189 | return a >> 2 & 1; | ||
| 190 | } | ||
| 191 | |||
| 192 | static inline u32 i5100_validlog_recmemvalid(u32 a) | ||
| 193 | { | ||
| 194 | return a >> 1 & 1; | ||
| 195 | } | ||
| 196 | |||
| 197 | static inline u32 i5100_validlog_nrecmemvalid(u32 a) | ||
| 198 | { | ||
| 199 | return a & 1; | ||
| 200 | } | ||
| 201 | |||
| 202 | static inline u32 i5100_nrecmema_merr(u32 a) | ||
| 203 | { | ||
| 204 | return a >> 15 & ((1 << 5) - 1); | ||
| 205 | } | ||
| 206 | |||
| 207 | static inline u32 i5100_nrecmema_bank(u32 a) | ||
| 208 | { | ||
| 209 | return a >> 12 & ((1 << 3) - 1); | ||
| 210 | } | ||
| 211 | |||
| 212 | static inline u32 i5100_nrecmema_rank(u32 a) | ||
| 213 | { | ||
| 214 | return a >> 8 & ((1 << 3) - 1); | ||
| 215 | } | ||
| 216 | |||
| 217 | static inline u32 i5100_nrecmema_dm_buf_id(u32 a) | ||
| 218 | { | ||
| 219 | return a & ((1 << 8) - 1); | ||
| 220 | } | ||
| 221 | |||
| 222 | static inline u32 i5100_nrecmemb_cas(u32 a) | ||
| 223 | { | ||
| 224 | return a >> 16 & ((1 << 13) - 1); | ||
| 225 | } | ||
| 226 | |||
| 227 | static inline u32 i5100_nrecmemb_ras(u32 a) | ||
| 228 | { | ||
| 229 | return a & ((1 << 16) - 1); | ||
| 230 | } | ||
| 231 | |||
| 232 | static inline u32 i5100_redmemb_ecc_locator(u32 a) | ||
| 233 | { | ||
| 234 | return a & ((1 << 18) - 1); | ||
| 235 | } | ||
| 236 | |||
| 237 | static inline u32 i5100_recmema_merr(u32 a) | ||
| 238 | { | ||
| 239 | return i5100_nrecmema_merr(a); | ||
| 240 | } | ||
| 241 | |||
| 242 | static inline u32 i5100_recmema_bank(u32 a) | ||
| 243 | { | ||
| 244 | return i5100_nrecmema_bank(a); | ||
| 245 | } | ||
| 246 | |||
| 247 | static inline u32 i5100_recmema_rank(u32 a) | ||
| 248 | { | ||
| 249 | return i5100_nrecmema_rank(a); | ||
| 250 | } | ||
| 251 | |||
| 252 | static inline u32 i5100_recmema_dm_buf_id(u32 a) | ||
| 253 | { | ||
| 254 | return i5100_nrecmema_dm_buf_id(a); | ||
| 255 | } | ||
| 256 | |||
| 257 | static inline u32 i5100_recmemb_cas(u32 a) | ||
| 258 | { | ||
| 259 | return i5100_nrecmemb_cas(a); | ||
| 260 | } | ||
| 261 | |||
| 262 | static inline u32 i5100_recmemb_ras(u32 a) | ||
| 263 | { | ||
| 264 | return i5100_nrecmemb_ras(a); | ||
| 265 | } | ||
| 266 | |||
| 267 | /* some generic limits */ | ||
| 268 | #define I5100_MAX_RANKS_PER_CTLR 6 | ||
| 269 | #define I5100_MAX_CTLRS 2 | ||
| 270 | #define I5100_MAX_RANKS_PER_DIMM 4 | ||
| 271 | #define I5100_DIMM_ADDR_LINES (6 - 3) /* 64 bits / 8 bits per byte */ | ||
| 272 | #define I5100_MAX_DIMM_SLOTS_PER_CTLR 4 | ||
| 273 | #define I5100_MAX_RANK_INTERLEAVE 4 | ||
| 274 | #define I5100_MAX_DMIRS 5 | ||
| 275 | |||
| 276 | struct i5100_priv { | ||
| 277 | /* ranks on each dimm -- 0 maps to not present -- obtained via SPD */ | ||
| 278 | int dimm_numrank[I5100_MAX_CTLRS][I5100_MAX_DIMM_SLOTS_PER_CTLR]; | ||
| 279 | |||
| 280 | /* | ||
| 281 | * mainboard chip select map -- maps i5100 chip selects to | ||
| 282 | * DIMM slot chip selects. In the case of only 4 ranks per | ||
| 283 | * controller, the mapping is fairly obvious but not unique. | ||
| 284 | * we map -1 -> NC and assume both controllers use the same | ||
| 285 | * map... | ||
| 286 | * | ||
| 287 | */ | ||
| 288 | int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CTLR][I5100_MAX_RANKS_PER_DIMM]; | ||
| 289 | |||
| 290 | /* memory interleave range */ | ||
| 291 | struct { | ||
| 292 | u64 limit; | ||
| 293 | unsigned way[2]; | ||
| 294 | } mir[I5100_MAX_CTLRS]; | ||
| 295 | |||
| 296 | /* adjusted memory interleave range register */ | ||
| 297 | unsigned amir[I5100_MAX_CTLRS]; | ||
| 298 | |||
| 299 | /* dimm interleave range */ | ||
| 300 | struct { | ||
| 301 | unsigned rank[I5100_MAX_RANK_INTERLEAVE]; | ||
| 302 | u64 limit; | ||
| 303 | } dmir[I5100_MAX_CTLRS][I5100_MAX_DMIRS]; | ||
| 304 | |||
| 305 | /* memory technology registers... */ | ||
| 306 | struct { | ||
| 307 | unsigned present; /* 0 or 1 */ | ||
| 308 | unsigned ethrottle; /* 0 or 1 */ | ||
| 309 | unsigned width; /* 4 or 8 bits */ | ||
| 310 | unsigned numbank; /* 2 or 3 lines */ | ||
| 311 | unsigned numrow; /* 13 .. 16 lines */ | ||
| 312 | unsigned numcol; /* 11 .. 12 lines */ | ||
| 313 | } mtr[I5100_MAX_CTLRS][I5100_MAX_RANKS_PER_CTLR]; | ||
| 314 | |||
| 315 | u64 tolm; /* top of low memory in bytes */ | ||
| 316 | unsigned ranksperctlr; /* number of ranks per controller */ | ||
| 317 | |||
| 318 | struct pci_dev *mc; /* device 16 func 1 */ | ||
| 319 | struct pci_dev *ch0mm; /* device 21 func 0 */ | ||
| 320 | struct pci_dev *ch1mm; /* device 22 func 0 */ | ||
| 321 | }; | ||
| 322 | |||
| 323 | /* map a rank/ctlr to a slot number on the mainboard */ | ||
| 324 | static int i5100_rank_to_slot(const struct mem_ctl_info *mci, | ||
| 325 | int ctlr, int rank) | ||
| 326 | { | ||
| 327 | const struct i5100_priv *priv = mci->pvt_info; | ||
| 328 | int i; | ||
| 329 | |||
| 330 | for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) { | ||
| 331 | int j; | ||
| 332 | const int numrank = priv->dimm_numrank[ctlr][i]; | ||
| 333 | |||
| 334 | for (j = 0; j < numrank; j++) | ||
| 335 | if (priv->dimm_csmap[i][j] == rank) | ||
| 336 | return i * 2 + ctlr; | ||
| 337 | } | ||
| 338 | |||
| 339 | return -1; | ||
| 340 | } | ||
| 341 | |||
| 342 | static const char *i5100_err_msg(unsigned err) | ||
| 343 | { | ||
| 344 | static const char *merrs[] = { | ||
| 345 | "unknown", /* 0 */ | ||
| 346 | "uncorrectable data ECC on replay", /* 1 */ | ||
| 347 | "unknown", /* 2 */ | ||
| 348 | "unknown", /* 3 */ | ||
| 349 | "aliased uncorrectable demand data ECC", /* 4 */ | ||
| 350 | "aliased uncorrectable spare-copy data ECC", /* 5 */ | ||
| 351 | "aliased uncorrectable patrol data ECC", /* 6 */ | ||
| 352 | "unknown", /* 7 */ | ||
| 353 | "unknown", /* 8 */ | ||
| 354 | "unknown", /* 9 */ | ||
| 355 | "non-aliased uncorrectable demand data ECC", /* 10 */ | ||
| 356 | "non-aliased uncorrectable spare-copy data ECC", /* 11 */ | ||
| 357 | "non-aliased uncorrectable patrol data ECC", /* 12 */ | ||
| 358 | "unknown", /* 13 */ | ||
| 359 | "correctable demand data ECC", /* 14 */ | ||
| 360 | "correctable spare-copy data ECC", /* 15 */ | ||
| 361 | "correctable patrol data ECC", /* 16 */ | ||
| 362 | "unknown", /* 17 */ | ||
| 363 | "SPD protocol error", /* 18 */ | ||
| 364 | "unknown", /* 19 */ | ||
| 365 | "spare copy initiated", /* 20 */ | ||
| 366 | "spare copy completed", /* 21 */ | ||
| 367 | }; | ||
| 368 | unsigned i; | ||
| 369 | |||
| 370 | for (i = 0; i < ARRAY_SIZE(merrs); i++) | ||
| 371 | if (1 << i & err) | ||
| 372 | return merrs[i]; | ||
| 373 | |||
| 374 | return "none"; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* convert csrow index into a rank (per controller -- 0..5) */ | ||
| 378 | static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow) | ||
| 379 | { | ||
| 380 | const struct i5100_priv *priv = mci->pvt_info; | ||
| 381 | |||
| 382 | return csrow % priv->ranksperctlr; | ||
| 383 | } | ||
| 384 | |||
| 385 | /* convert csrow index into a controller (0..1) */ | ||
| 386 | static int i5100_csrow_to_cntlr(const struct mem_ctl_info *mci, int csrow) | ||
| 387 | { | ||
| 388 | const struct i5100_priv *priv = mci->pvt_info; | ||
| 389 | |||
| 390 | return csrow / priv->ranksperctlr; | ||
| 391 | } | ||
| 392 | |||
| 393 | static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci, | ||
| 394 | int ctlr, int rank) | ||
| 395 | { | ||
| 396 | const struct i5100_priv *priv = mci->pvt_info; | ||
| 397 | |||
| 398 | return ctlr * priv->ranksperctlr + rank; | ||
| 399 | } | ||
| 400 | |||
| 401 | static void i5100_handle_ce(struct mem_ctl_info *mci, | ||
| 402 | int ctlr, | ||
| 403 | unsigned bank, | ||
| 404 | unsigned rank, | ||
| 405 | unsigned long syndrome, | ||
| 406 | unsigned cas, | ||
| 407 | unsigned ras, | ||
| 408 | const char *msg) | ||
| 409 | { | ||
| 410 | const int csrow = i5100_rank_to_csrow(mci, ctlr, rank); | ||
| 411 | |||
| 412 | printk(KERN_ERR | ||
| 413 | "CE ctlr %d, bank %u, rank %u, syndrome 0x%lx, " | ||
| 414 | "cas %u, ras %u, csrow %u, label \"%s\": %s\n", | ||
| 415 | ctlr, bank, rank, syndrome, cas, ras, | ||
| 416 | csrow, mci->csrows[csrow].channels[0].label, msg); | ||
| 417 | |||
| 418 | mci->ce_count++; | ||
| 419 | mci->csrows[csrow].ce_count++; | ||
| 420 | mci->csrows[csrow].channels[0].ce_count++; | ||
| 421 | } | ||
| 422 | |||
| 423 | static void i5100_handle_ue(struct mem_ctl_info *mci, | ||
| 424 | int ctlr, | ||
| 425 | unsigned bank, | ||
| 426 | unsigned rank, | ||
| 427 | unsigned long syndrome, | ||
| 428 | unsigned cas, | ||
| 429 | unsigned ras, | ||
| 430 | const char *msg) | ||
| 431 | { | ||
| 432 | const int csrow = i5100_rank_to_csrow(mci, ctlr, rank); | ||
| 433 | |||
| 434 | printk(KERN_ERR | ||
| 435 | "UE ctlr %d, bank %u, rank %u, syndrome 0x%lx, " | ||
| 436 | "cas %u, ras %u, csrow %u, label \"%s\": %s\n", | ||
| 437 | ctlr, bank, rank, syndrome, cas, ras, | ||
| 438 | csrow, mci->csrows[csrow].channels[0].label, msg); | ||
| 439 | |||
| 440 | mci->ue_count++; | ||
| 441 | mci->csrows[csrow].ue_count++; | ||
| 442 | } | ||
| 443 | |||
| 444 | static void i5100_read_log(struct mem_ctl_info *mci, int ctlr, | ||
| 445 | u32 ferr, u32 nerr) | ||
| 446 | { | ||
| 447 | struct i5100_priv *priv = mci->pvt_info; | ||
| 448 | struct pci_dev *pdev = (ctlr) ? priv->ch1mm : priv->ch0mm; | ||
| 449 | u32 dw; | ||
| 450 | u32 dw2; | ||
| 451 | unsigned syndrome = 0; | ||
| 452 | unsigned ecc_loc = 0; | ||
| 453 | unsigned merr; | ||
| 454 | unsigned bank; | ||
| 455 | unsigned rank; | ||
| 456 | unsigned cas; | ||
| 457 | unsigned ras; | ||
| 458 | |||
| 459 | pci_read_config_dword(pdev, I5100_VALIDLOG, &dw); | ||
| 460 | |||
| 461 | if (i5100_validlog_redmemvalid(dw)) { | ||
| 462 | pci_read_config_dword(pdev, I5100_REDMEMA, &dw2); | ||
| 463 | syndrome = dw2; | ||
| 464 | pci_read_config_dword(pdev, I5100_REDMEMB, &dw2); | ||
| 465 | ecc_loc = i5100_redmemb_ecc_locator(dw2); | ||
| 466 | } | ||
| 467 | |||
| 468 | if (i5100_validlog_recmemvalid(dw)) { | ||
| 469 | const char *msg; | ||
| 470 | |||
| 471 | pci_read_config_dword(pdev, I5100_RECMEMA, &dw2); | ||
| 472 | merr = i5100_recmema_merr(dw2); | ||
| 473 | bank = i5100_recmema_bank(dw2); | ||
| 474 | rank = i5100_recmema_rank(dw2); | ||
| 475 | |||
| 476 | pci_read_config_dword(pdev, I5100_RECMEMB, &dw2); | ||
| 477 | cas = i5100_recmemb_cas(dw2); | ||
| 478 | ras = i5100_recmemb_ras(dw2); | ||
| 479 | |||
| 480 | /* FIXME: not really sure if this is what merr is... | ||
| 481 | */ | ||
| 482 | if (!merr) | ||
| 483 | msg = i5100_err_msg(ferr); | ||
| 484 | else | ||
| 485 | msg = i5100_err_msg(nerr); | ||
| 486 | |||
| 487 | i5100_handle_ce(mci, ctlr, bank, rank, syndrome, cas, ras, msg); | ||
| 488 | } | ||
| 489 | |||
| 490 | if (i5100_validlog_nrecmemvalid(dw)) { | ||
| 491 | const char *msg; | ||
| 492 | |||
| 493 | pci_read_config_dword(pdev, I5100_NRECMEMA, &dw2); | ||
| 494 | merr = i5100_nrecmema_merr(dw2); | ||
| 495 | bank = i5100_nrecmema_bank(dw2); | ||
| 496 | rank = i5100_nrecmema_rank(dw2); | ||
| 497 | |||
| 498 | pci_read_config_dword(pdev, I5100_NRECMEMB, &dw2); | ||
| 499 | cas = i5100_nrecmemb_cas(dw2); | ||
| 500 | ras = i5100_nrecmemb_ras(dw2); | ||
| 501 | |||
| 502 | /* FIXME: not really sure if this is what merr is... | ||
| 503 | */ | ||
| 504 | if (!merr) | ||
| 505 | msg = i5100_err_msg(ferr); | ||
| 506 | else | ||
| 507 | msg = i5100_err_msg(nerr); | ||
| 508 | |||
| 509 | i5100_handle_ue(mci, ctlr, bank, rank, syndrome, cas, ras, msg); | ||
| 510 | } | ||
| 511 | |||
| 512 | pci_write_config_dword(pdev, I5100_VALIDLOG, dw); | ||
| 513 | } | ||
| 514 | |||
| 515 | static void i5100_check_error(struct mem_ctl_info *mci) | ||
| 516 | { | ||
| 517 | struct i5100_priv *priv = mci->pvt_info; | ||
| 518 | u32 dw; | ||
| 519 | |||
| 520 | |||
| 521 | pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw); | ||
| 522 | if (i5100_ferr_nf_mem_any(dw)) { | ||
| 523 | u32 dw2; | ||
| 524 | |||
| 525 | pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2); | ||
| 526 | if (dw2) | ||
| 527 | pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM, | ||
| 528 | dw2); | ||
| 529 | pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw); | ||
| 530 | |||
| 531 | i5100_read_log(mci, i5100_ferr_nf_mem_chan_indx(dw), | ||
| 532 | i5100_ferr_nf_mem_any(dw), | ||
| 533 | i5100_nerr_nf_mem_any(dw2)); | ||
| 534 | } | ||
| 535 | } | ||
| 536 | |||
| 537 | static struct pci_dev *pci_get_device_func(unsigned vendor, | ||
| 538 | unsigned device, | ||
| 539 | unsigned func) | ||
| 540 | { | ||
| 541 | struct pci_dev *ret = NULL; | ||
| 542 | |||
| 543 | while (1) { | ||
| 544 | ret = pci_get_device(vendor, device, ret); | ||
| 545 | |||
| 546 | if (!ret) | ||
| 547 | break; | ||
| 548 | |||
| 549 | if (PCI_FUNC(ret->devfn) == func) | ||
| 550 | break; | ||
| 551 | } | ||
| 552 | |||
| 553 | return ret; | ||
| 554 | } | ||
| 555 | |||
| 556 | static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci, | ||
| 557 | int csrow) | ||
| 558 | { | ||
| 559 | struct i5100_priv *priv = mci->pvt_info; | ||
| 560 | const unsigned ctlr_rank = i5100_csrow_to_rank(mci, csrow); | ||
| 561 | const unsigned ctlr = i5100_csrow_to_cntlr(mci, csrow); | ||
| 562 | unsigned addr_lines; | ||
| 563 | |||
| 564 | /* dimm present? */ | ||
| 565 | if (!priv->mtr[ctlr][ctlr_rank].present) | ||
| 566 | return 0ULL; | ||
| 567 | |||
| 568 | addr_lines = | ||
| 569 | I5100_DIMM_ADDR_LINES + | ||
| 570 | priv->mtr[ctlr][ctlr_rank].numcol + | ||
| 571 | priv->mtr[ctlr][ctlr_rank].numrow + | ||
| 572 | priv->mtr[ctlr][ctlr_rank].numbank; | ||
| 573 | |||
| 574 | return (unsigned long) | ||
| 575 | ((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void __devinit i5100_init_mtr(struct mem_ctl_info *mci) | ||
| 579 | { | ||
| 580 | struct i5100_priv *priv = mci->pvt_info; | ||
| 581 | struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm }; | ||
| 582 | int i; | ||
| 583 | |||
| 584 | for (i = 0; i < I5100_MAX_CTLRS; i++) { | ||
| 585 | int j; | ||
| 586 | struct pci_dev *pdev = mms[i]; | ||
| 587 | |||
| 588 | for (j = 0; j < I5100_MAX_RANKS_PER_CTLR; j++) { | ||
| 589 | const unsigned addr = | ||
| 590 | (j < 4) ? I5100_MTR_0 + j * 2 : | ||
| 591 | I5100_MTR_4 + (j - 4) * 2; | ||
| 592 | u16 w; | ||
| 593 | |||
| 594 | pci_read_config_word(pdev, addr, &w); | ||
| 595 | |||
| 596 | priv->mtr[i][j].present = i5100_mtr_present(w); | ||
| 597 | priv->mtr[i][j].ethrottle = i5100_mtr_ethrottle(w); | ||
| 598 | priv->mtr[i][j].width = 4 + 4 * i5100_mtr_width(w); | ||
| 599 | priv->mtr[i][j].numbank = 2 + i5100_mtr_numbank(w); | ||
| 600 | priv->mtr[i][j].numrow = 13 + i5100_mtr_numrow(w); | ||
| 601 | priv->mtr[i][j].numcol = 10 + i5100_mtr_numcol(w); | ||
| 602 | } | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 606 | /* | ||
| 607 | * FIXME: make this into a real i2c adapter (so that dimm-decode | ||
| 608 | * will work)? | ||
| 609 | */ | ||
| 610 | static int i5100_read_spd_byte(const struct mem_ctl_info *mci, | ||
| 611 | u8 ch, u8 slot, u8 addr, u8 *byte) | ||
| 612 | { | ||
| 613 | struct i5100_priv *priv = mci->pvt_info; | ||
| 614 | u16 w; | ||
| 615 | unsigned long et; | ||
| 616 | |||
| 617 | pci_read_config_word(priv->mc, I5100_SPDDATA, &w); | ||
| 618 | if (i5100_spddata_busy(w)) | ||
| 619 | return -1; | ||
| 620 | |||
| 621 | pci_write_config_dword(priv->mc, I5100_SPDCMD, | ||
| 622 | i5100_spdcmd_create(0xa, 1, ch * 4 + slot, addr, | ||
| 623 | 0, 0)); | ||
| 624 | |||
| 625 | /* wait up to 100ms */ | ||
| 626 | et = jiffies + HZ / 10; | ||
| 627 | udelay(100); | ||
| 628 | while (1) { | ||
| 629 | pci_read_config_word(priv->mc, I5100_SPDDATA, &w); | ||
| 630 | if (!i5100_spddata_busy(w)) | ||
| 631 | break; | ||
| 632 | udelay(100); | ||
| 633 | } | ||
| 634 | |||
| 635 | if (!i5100_spddata_rdo(w) || i5100_spddata_sbe(w)) | ||
| 636 | return -1; | ||
| 637 | |||
| 638 | *byte = i5100_spddata_data(w); | ||
| 639 | |||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | /* | ||
| 644 | * fill dimm chip select map | ||
| 645 | * | ||
| 646 | * FIXME: | ||
| 647 | * o only valid for 4 ranks per controller | ||
| 648 | * o not the only way to may chip selects to dimm slots | ||
| 649 | * o investigate if there is some way to obtain this map from the bios | ||
| 650 | */ | ||
| 651 | static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci) | ||
| 652 | { | ||
| 653 | struct i5100_priv *priv = mci->pvt_info; | ||
| 654 | int i; | ||
| 655 | |||
| 656 | WARN_ON(priv->ranksperctlr != 4); | ||
| 657 | |||
| 658 | for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) { | ||
| 659 | int j; | ||
| 660 | |||
| 661 | for (j = 0; j < I5100_MAX_RANKS_PER_DIMM; j++) | ||
| 662 | priv->dimm_csmap[i][j] = -1; /* default NC */ | ||
| 663 | } | ||
| 664 | |||
| 665 | /* only 2 chip selects per slot... */ | ||
| 666 | priv->dimm_csmap[0][0] = 0; | ||
| 667 | priv->dimm_csmap[0][1] = 3; | ||
| 668 | priv->dimm_csmap[1][0] = 1; | ||
| 669 | priv->dimm_csmap[1][1] = 2; | ||
| 670 | priv->dimm_csmap[2][0] = 2; | ||
| 671 | priv->dimm_csmap[3][0] = 3; | ||
| 672 | } | ||
| 673 | |||
| 674 | static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev, | ||
| 675 | struct mem_ctl_info *mci) | ||
| 676 | { | ||
| 677 | struct i5100_priv *priv = mci->pvt_info; | ||
| 678 | int i; | ||
| 679 | |||
| 680 | for (i = 0; i < I5100_MAX_CTLRS; i++) { | ||
| 681 | int j; | ||
| 682 | |||
| 683 | for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CTLR; j++) { | ||
| 684 | u8 rank; | ||
| 685 | |||
| 686 | if (i5100_read_spd_byte(mci, i, j, 5, &rank) < 0) | ||
| 687 | priv->dimm_numrank[i][j] = 0; | ||
| 688 | else | ||
| 689 | priv->dimm_numrank[i][j] = (rank & 3) + 1; | ||
| 690 | } | ||
| 691 | } | ||
| 692 | |||
| 693 | i5100_init_dimm_csmap(mci); | ||
| 694 | } | ||
| 695 | |||
| 696 | static void __devinit i5100_init_interleaving(struct pci_dev *pdev, | ||
| 697 | struct mem_ctl_info *mci) | ||
| 698 | { | ||
| 699 | u16 w; | ||
| 700 | u32 dw; | ||
| 701 | struct i5100_priv *priv = mci->pvt_info; | ||
| 702 | struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm }; | ||
| 703 | int i; | ||
| 704 | |||
| 705 | pci_read_config_word(pdev, I5100_TOLM, &w); | ||
| 706 | priv->tolm = (u64) i5100_tolm_tolm(w) * 256 * 1024 * 1024; | ||
| 707 | |||
| 708 | pci_read_config_word(pdev, I5100_MIR0, &w); | ||
| 709 | priv->mir[0].limit = (u64) i5100_mir_limit(w) << 28; | ||
| 710 | priv->mir[0].way[1] = i5100_mir_way1(w); | ||
| 711 | priv->mir[0].way[0] = i5100_mir_way0(w); | ||
| 712 | |||
| 713 | pci_read_config_word(pdev, I5100_MIR1, &w); | ||
| 714 | priv->mir[1].limit = (u64) i5100_mir_limit(w) << 28; | ||
| 715 | priv->mir[1].way[1] = i5100_mir_way1(w); | ||
| 716 | priv->mir[1].way[0] = i5100_mir_way0(w); | ||
| 717 | |||
| 718 | pci_read_config_word(pdev, I5100_AMIR_0, &w); | ||
| 719 | priv->amir[0] = w; | ||
| 720 | pci_read_config_word(pdev, I5100_AMIR_1, &w); | ||
| 721 | priv->amir[1] = w; | ||
| 722 | |||
| 723 | for (i = 0; i < I5100_MAX_CTLRS; i++) { | ||
| 724 | int j; | ||
| 725 | |||
| 726 | for (j = 0; j < 5; j++) { | ||
| 727 | int k; | ||
| 728 | |||
| 729 | pci_read_config_dword(mms[i], I5100_DMIR + j * 4, &dw); | ||
| 730 | |||
| 731 | priv->dmir[i][j].limit = | ||
| 732 | (u64) i5100_dmir_limit(dw) << 28; | ||
| 733 | for (k = 0; k < I5100_MAX_RANKS_PER_DIMM; k++) | ||
| 734 | priv->dmir[i][j].rank[k] = | ||
| 735 | i5100_dmir_rank(dw, k); | ||
| 736 | } | ||
| 737 | } | ||
| 738 | |||
| 739 | i5100_init_mtr(mci); | ||
| 740 | } | ||
| 741 | |||
| 742 | static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) | ||
| 743 | { | ||
| 744 | int i; | ||
| 745 | unsigned long total_pages = 0UL; | ||
| 746 | struct i5100_priv *priv = mci->pvt_info; | ||
| 747 | |||
| 748 | for (i = 0; i < mci->nr_csrows; i++) { | ||
| 749 | const unsigned long npages = i5100_npages(mci, i); | ||
| 750 | const unsigned cntlr = i5100_csrow_to_cntlr(mci, i); | ||
| 751 | const unsigned rank = i5100_csrow_to_rank(mci, i); | ||
| 752 | |||
| 753 | if (!npages) | ||
| 754 | continue; | ||
| 755 | |||
| 756 | /* | ||
| 757 | * FIXME: these two are totally bogus -- I don't see how to | ||
| 758 | * map them correctly to this structure... | ||
| 759 | */ | ||
| 760 | mci->csrows[i].first_page = total_pages; | ||
| 761 | mci->csrows[i].last_page = total_pages + npages - 1; | ||
| 762 | mci->csrows[i].page_mask = 0UL; | ||
| 763 | |||
| 764 | mci->csrows[i].nr_pages = npages; | ||
| 765 | mci->csrows[i].grain = 32; | ||
| 766 | mci->csrows[i].csrow_idx = i; | ||
| 767 | mci->csrows[i].dtype = | ||
| 768 | (priv->mtr[cntlr][rank].width == 4) ? DEV_X4 : DEV_X8; | ||
| 769 | mci->csrows[i].ue_count = 0; | ||
| 770 | mci->csrows[i].ce_count = 0; | ||
| 771 | mci->csrows[i].mtype = MEM_RDDR2; | ||
| 772 | mci->csrows[i].edac_mode = EDAC_SECDED; | ||
| 773 | mci->csrows[i].mci = mci; | ||
| 774 | mci->csrows[i].nr_channels = 1; | ||
| 775 | mci->csrows[i].channels[0].chan_idx = 0; | ||
| 776 | mci->csrows[i].channels[0].ce_count = 0; | ||
| 777 | mci->csrows[i].channels[0].csrow = mci->csrows + i; | ||
| 778 | snprintf(mci->csrows[i].channels[0].label, | ||
| 779 | sizeof(mci->csrows[i].channels[0].label), | ||
| 780 | "DIMM%u", i5100_rank_to_slot(mci, cntlr, rank)); | ||
| 781 | |||
| 782 | total_pages += npages; | ||
| 783 | } | ||
| 784 | } | ||
| 785 | |||
| 786 | static int __devinit i5100_init_one(struct pci_dev *pdev, | ||
| 787 | const struct pci_device_id *id) | ||
| 788 | { | ||
| 789 | int rc; | ||
| 790 | struct mem_ctl_info *mci; | ||
| 791 | struct i5100_priv *priv; | ||
| 792 | struct pci_dev *ch0mm, *ch1mm; | ||
| 793 | int ret = 0; | ||
| 794 | u32 dw; | ||
| 795 | int ranksperch; | ||
| 796 | |||
| 797 | if (PCI_FUNC(pdev->devfn) != 1) | ||
| 798 | return -ENODEV; | ||
| 799 | |||
| 800 | rc = pci_enable_device(pdev); | ||
| 801 | if (rc < 0) { | ||
| 802 | ret = rc; | ||
| 803 | goto bail; | ||
| 804 | } | ||
| 805 | |||
| 806 | /* ECC enabled? */ | ||
| 807 | pci_read_config_dword(pdev, I5100_MC, &dw); | ||
| 808 | if (!i5100_mc_errdeten(dw)) { | ||
| 809 | printk(KERN_INFO "i5100_edac: ECC not enabled.\n"); | ||
| 810 | ret = -ENODEV; | ||
| 811 | goto bail_pdev; | ||
| 812 | } | ||
| 813 | |||
| 814 | /* figure out how many ranks, from strapped state of 48GB_Mode input */ | ||
| 815 | pci_read_config_dword(pdev, I5100_MS, &dw); | ||
| 816 | ranksperch = !!(dw & (1 << 8)) * 2 + 4; | ||
| 817 | |||
| 818 | if (ranksperch != 4) { | ||
| 819 | /* FIXME: get 6 ranks / controller to work - need hw... */ | ||
| 820 | printk(KERN_INFO "i5100_edac: unsupported configuration.\n"); | ||
| 821 | ret = -ENODEV; | ||
| 822 | goto bail_pdev; | ||
| 823 | } | ||
| 824 | |||
| 825 | /* enable error reporting... */ | ||
| 826 | pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw); | ||
| 827 | dw &= ~I5100_FERR_NF_MEM_ANY_MASK; | ||
| 828 | pci_write_config_dword(pdev, I5100_EMASK_MEM, dw); | ||
| 829 | |||
| 830 | /* device 21, func 0, Channel 0 Memory Map, Error Flag/Mask, etc... */ | ||
| 831 | ch0mm = pci_get_device_func(PCI_VENDOR_ID_INTEL, | ||
| 832 | PCI_DEVICE_ID_INTEL_5100_21, 0); | ||
| 833 | if (!ch0mm) { | ||
| 834 | ret = -ENODEV; | ||
| 835 | goto bail_pdev; | ||
| 836 | } | ||
| 837 | |||
| 838 | rc = pci_enable_device(ch0mm); | ||
| 839 | if (rc < 0) { | ||
| 840 | ret = rc; | ||
| 841 | goto bail_ch0; | ||
| 842 | } | ||
| 843 | |||
| 844 | /* device 22, func 0, Channel 1 Memory Map, Error Flag/Mask, etc... */ | ||
| 845 | ch1mm = pci_get_device_func(PCI_VENDOR_ID_INTEL, | ||
| 846 | PCI_DEVICE_ID_INTEL_5100_22, 0); | ||
| 847 | if (!ch1mm) { | ||
| 848 | ret = -ENODEV; | ||
| 849 | goto bail_disable_ch0; | ||
| 850 | } | ||
| 851 | |||
| 852 | rc = pci_enable_device(ch1mm); | ||
| 853 | if (rc < 0) { | ||
| 854 | ret = rc; | ||
| 855 | goto bail_ch1; | ||
| 856 | } | ||
| 857 | |||
| 858 | mci = edac_mc_alloc(sizeof(*priv), ranksperch * 2, 1, 0); | ||
| 859 | if (!mci) { | ||
| 860 | ret = -ENOMEM; | ||
| 861 | goto bail_disable_ch1; | ||
| 862 | } | ||
| 863 | |||
| 864 | mci->dev = &pdev->dev; | ||
| 865 | |||
| 866 | priv = mci->pvt_info; | ||
| 867 | priv->ranksperctlr = ranksperch; | ||
| 868 | priv->mc = pdev; | ||
| 869 | priv->ch0mm = ch0mm; | ||
| 870 | priv->ch1mm = ch1mm; | ||
| 871 | |||
| 872 | i5100_init_dimm_layout(pdev, mci); | ||
| 873 | i5100_init_interleaving(pdev, mci); | ||
| 874 | |||
| 875 | mci->mtype_cap = MEM_FLAG_FB_DDR2; | ||
| 876 | mci->edac_ctl_cap = EDAC_FLAG_SECDED; | ||
| 877 | mci->edac_cap = EDAC_FLAG_SECDED; | ||
| 878 | mci->mod_name = "i5100_edac.c"; | ||
| 879 | mci->mod_ver = "not versioned"; | ||
| 880 | mci->ctl_name = "i5100"; | ||
| 881 | mci->dev_name = pci_name(pdev); | ||
| 882 | mci->ctl_page_to_phys = NULL; | ||
| 883 | |||
| 884 | mci->edac_check = i5100_check_error; | ||
| 885 | |||
| 886 | i5100_init_csrows(mci); | ||
| 887 | |||
| 888 | /* this strange construction seems to be in every driver, dunno why */ | ||
| 889 | switch (edac_op_state) { | ||
| 890 | case EDAC_OPSTATE_POLL: | ||
| 891 | case EDAC_OPSTATE_NMI: | ||
| 892 | break; | ||
| 893 | default: | ||
| 894 | edac_op_state = EDAC_OPSTATE_POLL; | ||
| 895 | break; | ||
| 896 | } | ||
| 897 | |||
| 898 | if (edac_mc_add_mc(mci)) { | ||
| 899 | ret = -ENODEV; | ||
| 900 | goto bail_mc; | ||
| 901 | } | ||
| 902 | |||
| 903 | return ret; | ||
| 904 | |||
| 905 | bail_mc: | ||
| 906 | edac_mc_free(mci); | ||
| 907 | |||
| 908 | bail_disable_ch1: | ||
| 909 | pci_disable_device(ch1mm); | ||
| 910 | |||
| 911 | bail_ch1: | ||
| 912 | pci_dev_put(ch1mm); | ||
| 913 | |||
| 914 | bail_disable_ch0: | ||
| 915 | pci_disable_device(ch0mm); | ||
| 916 | |||
| 917 | bail_ch0: | ||
| 918 | pci_dev_put(ch0mm); | ||
| 919 | |||
| 920 | bail_pdev: | ||
| 921 | pci_disable_device(pdev); | ||
| 922 | |||
| 923 | bail: | ||
| 924 | return ret; | ||
| 925 | } | ||
| 926 | |||
| 927 | static void __devexit i5100_remove_one(struct pci_dev *pdev) | ||
| 928 | { | ||
| 929 | struct mem_ctl_info *mci; | ||
| 930 | struct i5100_priv *priv; | ||
| 931 | |||
| 932 | mci = edac_mc_del_mc(&pdev->dev); | ||
| 933 | |||
| 934 | if (!mci) | ||
| 935 | return; | ||
| 936 | |||
| 937 | priv = mci->pvt_info; | ||
| 938 | pci_disable_device(pdev); | ||
| 939 | pci_disable_device(priv->ch0mm); | ||
| 940 | pci_disable_device(priv->ch1mm); | ||
| 941 | pci_dev_put(priv->ch0mm); | ||
| 942 | pci_dev_put(priv->ch1mm); | ||
| 943 | |||
| 944 | edac_mc_free(mci); | ||
| 945 | } | ||
| 946 | |||
| 947 | static const struct pci_device_id i5100_pci_tbl[] __devinitdata = { | ||
| 948 | /* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */ | ||
| 949 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) }, | ||
| 950 | { 0, } | ||
| 951 | }; | ||
| 952 | MODULE_DEVICE_TABLE(pci, i5100_pci_tbl); | ||
| 953 | |||
| 954 | static struct pci_driver i5100_driver = { | ||
| 955 | .name = KBUILD_BASENAME, | ||
| 956 | .probe = i5100_init_one, | ||
| 957 | .remove = __devexit_p(i5100_remove_one), | ||
| 958 | .id_table = i5100_pci_tbl, | ||
| 959 | }; | ||
| 960 | |||
| 961 | static int __init i5100_init(void) | ||
| 962 | { | ||
| 963 | int pci_rc; | ||
| 964 | |||
| 965 | pci_rc = pci_register_driver(&i5100_driver); | ||
| 966 | |||
| 967 | return (pci_rc < 0) ? pci_rc : 0; | ||
| 968 | } | ||
| 969 | |||
| 970 | static void __exit i5100_exit(void) | ||
| 971 | { | ||
| 972 | pci_unregister_driver(&i5100_driver); | ||
| 973 | } | ||
| 974 | |||
| 975 | module_init(i5100_init); | ||
| 976 | module_exit(i5100_exit); | ||
| 977 | |||
| 978 | MODULE_LICENSE("GPL"); | ||
| 979 | MODULE_AUTHOR | ||
| 980 | ("Arthur Jones <ajones@riverbed.com>"); | ||
| 981 | MODULE_DESCRIPTION("MC Driver for Intel I5100 memory controllers"); | ||
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index d49361bfe670..2265d9ca1535 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
| @@ -195,14 +195,15 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) | |||
| 195 | return IRQ_HANDLED; | 195 | return IRQ_HANDLED; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev) | 198 | static int __devinit mpc85xx_pci_err_probe(struct of_device *op, |
| 199 | const struct of_device_id *match) | ||
| 199 | { | 200 | { |
| 200 | struct edac_pci_ctl_info *pci; | 201 | struct edac_pci_ctl_info *pci; |
| 201 | struct mpc85xx_pci_pdata *pdata; | 202 | struct mpc85xx_pci_pdata *pdata; |
| 202 | struct resource *r; | 203 | struct resource r; |
| 203 | int res = 0; | 204 | int res = 0; |
| 204 | 205 | ||
| 205 | if (!devres_open_group(&pdev->dev, mpc85xx_pci_err_probe, GFP_KERNEL)) | 206 | if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL)) |
| 206 | return -ENOMEM; | 207 | return -ENOMEM; |
| 207 | 208 | ||
| 208 | pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err"); | 209 | pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err"); |
| @@ -212,34 +213,37 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev) | |||
| 212 | pdata = pci->pvt_info; | 213 | pdata = pci->pvt_info; |
| 213 | pdata->name = "mpc85xx_pci_err"; | 214 | pdata->name = "mpc85xx_pci_err"; |
| 214 | pdata->irq = NO_IRQ; | 215 | pdata->irq = NO_IRQ; |
| 215 | platform_set_drvdata(pdev, pci); | 216 | dev_set_drvdata(&op->dev, pci); |
| 216 | pci->dev = &pdev->dev; | 217 | pci->dev = &op->dev; |
| 217 | pci->mod_name = EDAC_MOD_STR; | 218 | pci->mod_name = EDAC_MOD_STR; |
| 218 | pci->ctl_name = pdata->name; | 219 | pci->ctl_name = pdata->name; |
| 219 | pci->dev_name = pdev->dev.bus_id; | 220 | pci->dev_name = op->dev.bus_id; |
| 220 | 221 | ||
| 221 | if (edac_op_state == EDAC_OPSTATE_POLL) | 222 | if (edac_op_state == EDAC_OPSTATE_POLL) |
| 222 | pci->edac_check = mpc85xx_pci_check; | 223 | pci->edac_check = mpc85xx_pci_check; |
| 223 | 224 | ||
| 224 | pdata->edac_idx = edac_pci_idx++; | 225 | pdata->edac_idx = edac_pci_idx++; |
| 225 | 226 | ||
| 226 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 227 | res = of_address_to_resource(op->node, 0, &r); |
| 227 | if (!r) { | 228 | if (res) { |
| 228 | printk(KERN_ERR "%s: Unable to get resource for " | 229 | printk(KERN_ERR "%s: Unable to get resource for " |
| 229 | "PCI err regs\n", __func__); | 230 | "PCI err regs\n", __func__); |
| 230 | goto err; | 231 | goto err; |
| 231 | } | 232 | } |
| 232 | 233 | ||
| 233 | if (!devm_request_mem_region(&pdev->dev, r->start, | 234 | /* we only need the error registers */ |
| 234 | r->end - r->start + 1, pdata->name)) { | 235 | r.start += 0xe00; |
| 236 | |||
| 237 | if (!devm_request_mem_region(&op->dev, r.start, | ||
| 238 | r.end - r.start + 1, pdata->name)) { | ||
| 235 | printk(KERN_ERR "%s: Error while requesting mem region\n", | 239 | printk(KERN_ERR "%s: Error while requesting mem region\n", |
| 236 | __func__); | 240 | __func__); |
| 237 | res = -EBUSY; | 241 | res = -EBUSY; |
| 238 | goto err; | 242 | goto err; |
| 239 | } | 243 | } |
| 240 | 244 | ||
| 241 | pdata->pci_vbase = devm_ioremap(&pdev->dev, r->start, | 245 | pdata->pci_vbase = devm_ioremap(&op->dev, r.start, |
| 242 | r->end - r->start + 1); | 246 | r.end - r.start + 1); |
| 243 | if (!pdata->pci_vbase) { | 247 | if (!pdata->pci_vbase) { |
| 244 | printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); | 248 | printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); |
| 245 | res = -ENOMEM; | 249 | res = -ENOMEM; |
| @@ -266,14 +270,15 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev) | |||
| 266 | } | 270 | } |
| 267 | 271 | ||
| 268 | if (edac_op_state == EDAC_OPSTATE_INT) { | 272 | if (edac_op_state == EDAC_OPSTATE_INT) { |
| 269 | pdata->irq = platform_get_irq(pdev, 0); | 273 | pdata->irq = irq_of_parse_and_map(op->node, 0); |
| 270 | res = devm_request_irq(&pdev->dev, pdata->irq, | 274 | res = devm_request_irq(&op->dev, pdata->irq, |
| 271 | mpc85xx_pci_isr, IRQF_DISABLED, | 275 | mpc85xx_pci_isr, IRQF_DISABLED, |
| 272 | "[EDAC] PCI err", pci); | 276 | "[EDAC] PCI err", pci); |
| 273 | if (res < 0) { | 277 | if (res < 0) { |
| 274 | printk(KERN_ERR | 278 | printk(KERN_ERR |
| 275 | "%s: Unable to requiest irq %d for " | 279 | "%s: Unable to requiest irq %d for " |
| 276 | "MPC85xx PCI err\n", __func__, pdata->irq); | 280 | "MPC85xx PCI err\n", __func__, pdata->irq); |
| 281 | irq_dispose_mapping(pdata->irq); | ||
| 277 | res = -ENODEV; | 282 | res = -ENODEV; |
| 278 | goto err2; | 283 | goto err2; |
| 279 | } | 284 | } |
| @@ -282,23 +287,23 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev) | |||
| 282 | pdata->irq); | 287 | pdata->irq); |
| 283 | } | 288 | } |
| 284 | 289 | ||
| 285 | devres_remove_group(&pdev->dev, mpc85xx_pci_err_probe); | 290 | devres_remove_group(&op->dev, mpc85xx_pci_err_probe); |
| 286 | debugf3("%s(): success\n", __func__); | 291 | debugf3("%s(): success\n", __func__); |
| 287 | printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); | 292 | printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); |
| 288 | 293 | ||
| 289 | return 0; | 294 | return 0; |
| 290 | 295 | ||
| 291 | err2: | 296 | err2: |
| 292 | edac_pci_del_device(&pdev->dev); | 297 | edac_pci_del_device(&op->dev); |
| 293 | err: | 298 | err: |
| 294 | edac_pci_free_ctl_info(pci); | 299 | edac_pci_free_ctl_info(pci); |
| 295 | devres_release_group(&pdev->dev, mpc85xx_pci_err_probe); | 300 | devres_release_group(&op->dev, mpc85xx_pci_err_probe); |
| 296 | return res; | 301 | return res; |
| 297 | } | 302 | } |
| 298 | 303 | ||
| 299 | static int mpc85xx_pci_err_remove(struct platform_device *pdev) | 304 | static int mpc85xx_pci_err_remove(struct of_device *op) |
| 300 | { | 305 | { |
| 301 | struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); | 306 | struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); |
| 302 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; | 307 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; |
| 303 | 308 | ||
| 304 | debugf0("%s()\n", __func__); | 309 | debugf0("%s()\n", __func__); |
| @@ -318,12 +323,26 @@ static int mpc85xx_pci_err_remove(struct platform_device *pdev) | |||
| 318 | return 0; | 323 | return 0; |
| 319 | } | 324 | } |
| 320 | 325 | ||
| 321 | static struct platform_driver mpc85xx_pci_err_driver = { | 326 | static struct of_device_id mpc85xx_pci_err_of_match[] = { |
| 327 | { | ||
| 328 | .compatible = "fsl,mpc8540-pcix", | ||
| 329 | }, | ||
| 330 | { | ||
| 331 | .compatible = "fsl,mpc8540-pci", | ||
| 332 | }, | ||
| 333 | {}, | ||
| 334 | }; | ||
| 335 | |||
| 336 | static struct of_platform_driver mpc85xx_pci_err_driver = { | ||
| 337 | .owner = THIS_MODULE, | ||
| 338 | .name = "mpc85xx_pci_err", | ||
| 339 | .match_table = mpc85xx_pci_err_of_match, | ||
| 322 | .probe = mpc85xx_pci_err_probe, | 340 | .probe = mpc85xx_pci_err_probe, |
| 323 | .remove = __devexit_p(mpc85xx_pci_err_remove), | 341 | .remove = __devexit_p(mpc85xx_pci_err_remove), |
| 324 | .driver = { | 342 | .driver = { |
| 325 | .name = "mpc85xx_pci_err", | 343 | .name = "mpc85xx_pci_err", |
| 326 | } | 344 | .owner = THIS_MODULE, |
| 345 | }, | ||
| 327 | }; | 346 | }; |
| 328 | 347 | ||
| 329 | #endif /* CONFIG_PCI */ | 348 | #endif /* CONFIG_PCI */ |
| @@ -1002,7 +1021,7 @@ static int __init mpc85xx_mc_init(void) | |||
| 1002 | printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n"); | 1021 | printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n"); |
| 1003 | 1022 | ||
| 1004 | #ifdef CONFIG_PCI | 1023 | #ifdef CONFIG_PCI |
| 1005 | res = platform_driver_register(&mpc85xx_pci_err_driver); | 1024 | res = of_register_platform_driver(&mpc85xx_pci_err_driver); |
| 1006 | if (res) | 1025 | if (res) |
| 1007 | printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n"); | 1026 | printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n"); |
| 1008 | #endif | 1027 | #endif |
| @@ -1025,7 +1044,7 @@ static void __exit mpc85xx_mc_exit(void) | |||
| 1025 | { | 1044 | { |
| 1026 | mtspr(SPRN_HID1, orig_hid1); | 1045 | mtspr(SPRN_HID1, orig_hid1); |
| 1027 | #ifdef CONFIG_PCI | 1046 | #ifdef CONFIG_PCI |
| 1028 | platform_driver_unregister(&mpc85xx_pci_err_driver); | 1047 | of_unregister_platform_driver(&mpc85xx_pci_err_driver); |
| 1029 | #endif | 1048 | #endif |
| 1030 | of_unregister_platform_driver(&mpc85xx_l2_err_driver); | 1049 | of_unregister_platform_driver(&mpc85xx_l2_err_driver); |
| 1031 | of_unregister_platform_driver(&mpc85xx_mc_err_driver); | 1050 | of_unregister_platform_driver(&mpc85xx_mc_err_driver); |
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index bf071f140a05..083ce8d0c63d 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c | |||
| @@ -71,6 +71,35 @@ static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id) | |||
| 71 | return IRQ_HANDLED; | 71 | return IRQ_HANDLED; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /* | ||
| 75 | * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of | ||
| 76 | * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as | ||
| 77 | * well. IOW, don't set bit 0. | ||
| 78 | */ | ||
| 79 | |||
| 80 | /* Erratum FEr PCI-#16: clear bit 0 of PCI SERRn Mask reg. */ | ||
| 81 | static int __init mv64x60_pci_fixup(struct platform_device *pdev) | ||
| 82 | { | ||
| 83 | struct resource *r; | ||
| 84 | void __iomem *pci_serr; | ||
| 85 | |||
| 86 | r = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 87 | if (!r) { | ||
| 88 | printk(KERN_ERR "%s: Unable to get resource for " | ||
| 89 | "PCI err regs\n", __func__); | ||
| 90 | return -ENOENT; | ||
| 91 | } | ||
| 92 | |||
| 93 | pci_serr = ioremap(r->start, r->end - r->start + 1); | ||
| 94 | if (!pci_serr) | ||
| 95 | return -ENOMEM; | ||
| 96 | |||
| 97 | out_le32(pci_serr, in_le32(pci_serr) & ~0x1); | ||
| 98 | iounmap(pci_serr); | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 74 | static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) | 103 | static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) |
| 75 | { | 104 | { |
| 76 | struct edac_pci_ctl_info *pci; | 105 | struct edac_pci_ctl_info *pci; |
| @@ -128,6 +157,12 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) | |||
| 128 | goto err; | 157 | goto err; |
| 129 | } | 158 | } |
| 130 | 159 | ||
| 160 | res = mv64x60_pci_fixup(pdev); | ||
| 161 | if (res < 0) { | ||
| 162 | printk(KERN_ERR "%s: PCI fixup failed\n", __func__); | ||
| 163 | goto err; | ||
| 164 | } | ||
| 165 | |||
| 131 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0); | 166 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0); |
| 132 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0); | 167 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0); |
| 133 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, | 168 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, |
| @@ -612,7 +647,7 @@ static void get_total_mem(struct mv64x60_mc_pdata *pdata) | |||
| 612 | if (!np) | 647 | if (!np) |
| 613 | return; | 648 | return; |
| 614 | 649 | ||
| 615 | reg = get_property(np, "reg", NULL); | 650 | reg = of_get_property(np, "reg", NULL); |
| 616 | 651 | ||
| 617 | pdata->total_mem = reg[1]; | 652 | pdata->total_mem = reg[1]; |
| 618 | } | 653 | } |
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 0b624e927a6f..c66817e7717b 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c | |||
| @@ -152,20 +152,11 @@ static ssize_t smi_data_read(struct kobject *kobj, | |||
| 152 | struct bin_attribute *bin_attr, | 152 | struct bin_attribute *bin_attr, |
| 153 | char *buf, loff_t pos, size_t count) | 153 | char *buf, loff_t pos, size_t count) |
| 154 | { | 154 | { |
| 155 | size_t max_read; | ||
| 156 | ssize_t ret; | 155 | ssize_t ret; |
| 157 | 156 | ||
| 158 | mutex_lock(&smi_data_lock); | 157 | mutex_lock(&smi_data_lock); |
| 159 | 158 | ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf, | |
| 160 | if (pos >= smi_data_buf_size) { | 159 | smi_data_buf_size); |
| 161 | ret = 0; | ||
| 162 | goto out; | ||
| 163 | } | ||
| 164 | |||
| 165 | max_read = smi_data_buf_size - pos; | ||
| 166 | ret = min(max_read, count); | ||
| 167 | memcpy(buf, smi_data_buf + pos, ret); | ||
| 168 | out: | ||
| 169 | mutex_unlock(&smi_data_lock); | 160 | mutex_unlock(&smi_data_lock); |
| 170 | return ret; | 161 | return ret; |
| 171 | } | 162 | } |
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 7430e218cda6..13946ebd77d6 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
| @@ -507,11 +507,6 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) | |||
| 507 | 507 | ||
| 508 | static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | 508 | static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) |
| 509 | { | 509 | { |
| 510 | unsigned char *ptemp = NULL; | ||
| 511 | size_t bytes_left = 0; | ||
| 512 | size_t data_length = 0; | ||
| 513 | ssize_t ret_count = 0; | ||
| 514 | |||
| 515 | /* check to see if we have something to return */ | 510 | /* check to see if we have something to return */ |
| 516 | if ((rbu_data.image_update_buffer == NULL) || | 511 | if ((rbu_data.image_update_buffer == NULL) || |
| 517 | (rbu_data.bios_image_size == 0)) { | 512 | (rbu_data.bios_image_size == 0)) { |
| @@ -519,28 +514,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
| 519 | "bios_image_size %lu\n", | 514 | "bios_image_size %lu\n", |
| 520 | rbu_data.image_update_buffer, | 515 | rbu_data.image_update_buffer, |
| 521 | rbu_data.bios_image_size); | 516 | rbu_data.bios_image_size); |
| 522 | ret_count = -ENOMEM; | 517 | return -ENOMEM; |
| 523 | goto read_rbu_data_exit; | ||
| 524 | } | ||
| 525 | |||
| 526 | if (pos > rbu_data.bios_image_size) { | ||
| 527 | ret_count = 0; | ||
| 528 | goto read_rbu_data_exit; | ||
| 529 | } | 518 | } |
| 530 | 519 | ||
| 531 | bytes_left = rbu_data.bios_image_size - pos; | 520 | return memory_read_from_buffer(buffer, count, &pos, |
| 532 | data_length = min(bytes_left, count); | 521 | rbu_data.image_update_buffer, rbu_data.bios_image_size); |
| 533 | |||
| 534 | ptemp = rbu_data.image_update_buffer; | ||
| 535 | memcpy(buffer, (ptemp + pos), data_length); | ||
| 536 | |||
| 537 | if ((pos + count) > rbu_data.bios_image_size) | ||
| 538 | /* this was the last copy */ | ||
| 539 | ret_count = bytes_left; | ||
| 540 | else | ||
| 541 | ret_count = count; | ||
| 542 | read_rbu_data_exit: | ||
| 543 | return ret_count; | ||
| 544 | } | 522 | } |
| 545 | 523 | ||
| 546 | static ssize_t read_rbu_data(struct kobject *kobj, | 524 | static ssize_t read_rbu_data(struct kobject *kobj, |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index fced1909cbba..dbd42d6c93a7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -2,15 +2,40 @@ | |||
| 2 | # GPIO infrastructure and expanders | 2 | # GPIO infrastructure and expanders |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | config HAVE_GPIO_LIB | 5 | config ARCH_WANT_OPTIONAL_GPIOLIB |
| 6 | bool | 6 | bool |
| 7 | help | 7 | help |
| 8 | Select this config option from the architecture Kconfig, if | ||
| 9 | it is possible to use gpiolib on the architecture, but let the | ||
| 10 | user decide whether to actually build it or not. | ||
| 11 | Select this instead of ARCH_REQUIRE_GPIOLIB, if your architecture does | ||
| 12 | not depend on GPIOs being available, but rather let the user | ||
| 13 | decide whether he needs it or not. | ||
| 14 | |||
| 15 | config ARCH_REQUIRE_GPIOLIB | ||
| 16 | bool | ||
| 17 | select GPIOLIB | ||
| 18 | help | ||
| 8 | Platforms select gpiolib if they use this infrastructure | 19 | Platforms select gpiolib if they use this infrastructure |
| 9 | for all their GPIOs, usually starting with ones integrated | 20 | for all their GPIOs, usually starting with ones integrated |
| 10 | into SOC processors. | 21 | into SOC processors. |
| 22 | Selecting this from the architecture code will cause the gpiolib | ||
| 23 | code to always get built in. | ||
| 24 | |||
| 25 | |||
| 26 | |||
| 27 | menuconfig GPIOLIB | ||
| 28 | bool "GPIO Support" | ||
| 29 | depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB | ||
| 30 | select GENERIC_GPIO | ||
| 31 | help | ||
| 32 | This enables GPIO support through the generic GPIO library. | ||
| 33 | You only need to enable this, if you also want to enable | ||
| 34 | one or more of the GPIO expansion card drivers below. | ||
| 11 | 35 | ||
| 12 | menu "GPIO Support" | 36 | If unsure, say N. |
| 13 | depends on HAVE_GPIO_LIB | 37 | |
| 38 | if GPIOLIB | ||
| 14 | 39 | ||
| 15 | config DEBUG_GPIO | 40 | config DEBUG_GPIO |
| 16 | bool "Debug GPIO calls" | 41 | bool "Debug GPIO calls" |
| @@ -23,10 +48,44 @@ config DEBUG_GPIO | |||
| 23 | slower. The diagnostics help catch the type of setup errors | 48 | slower. The diagnostics help catch the type of setup errors |
| 24 | that are most common when setting up new platforms or boards. | 49 | that are most common when setting up new platforms or boards. |
| 25 | 50 | ||
| 51 | config GPIO_SYSFS | ||
| 52 | bool "/sys/class/gpio/... (sysfs interface)" | ||
| 53 | depends on SYSFS && EXPERIMENTAL | ||
| 54 | help | ||
| 55 | Say Y here to add a sysfs interface for GPIOs. | ||
| 56 | |||
| 57 | This is mostly useful to work around omissions in a system's | ||
| 58 | kernel support. Those are common in custom and semicustom | ||
| 59 | hardware assembled using standard kernels with a minimum of | ||
| 60 | custom patches. In those cases, userspace code may import | ||
| 61 | a given GPIO from the kernel, if no kernel driver requested it. | ||
| 62 | |||
| 63 | Kernel drivers may also request that a particular GPIO be | ||
| 64 | exported to userspace; this can be useful when debugging. | ||
| 65 | |||
| 26 | # put expanders in the right section, in alphabetical order | 66 | # put expanders in the right section, in alphabetical order |
| 27 | 67 | ||
| 28 | comment "I2C GPIO expanders:" | 68 | comment "I2C GPIO expanders:" |
| 29 | 69 | ||
| 70 | config GPIO_MAX732X | ||
| 71 | tristate "MAX7319, MAX7320-7327 I2C Port Expanders" | ||
| 72 | depends on I2C | ||
| 73 | help | ||
| 74 | Say yes here to support the MAX7319, MAX7320-7327 series of I2C | ||
| 75 | Port Expanders. Each IO port on these chips has a fixed role of | ||
| 76 | Input (designated by 'I'), Push-Pull Output ('O'), or Open-Drain | ||
| 77 | Input and Output (designed by 'P'). The combinations are listed | ||
| 78 | below: | ||
| 79 | |||
| 80 | 8 bits: max7319 (8I), max7320 (8O), max7321 (8P), | ||
| 81 | max7322 (4I4O), max7323 (4P4O) | ||
| 82 | |||
| 83 | 16 bits: max7324 (8I8O), max7325 (8P8O), | ||
| 84 | max7326 (4I12O), max7327 (4P12O) | ||
| 85 | |||
| 86 | Board setup code must specify the model to use, and the start | ||
| 87 | number for these GPIOs. | ||
| 88 | |||
| 30 | config GPIO_PCA953X | 89 | config GPIO_PCA953X |
| 31 | tristate "PCA953x, PCA955x, and MAX7310 I/O ports" | 90 | tristate "PCA953x, PCA955x, and MAX7310 I/O ports" |
| 32 | depends on I2C | 91 | depends on I2C |
| @@ -68,6 +127,24 @@ config GPIO_PCF857X | |||
| 68 | This driver provides an in-kernel interface to those GPIOs using | 127 | This driver provides an in-kernel interface to those GPIOs using |
| 69 | platform-neutral GPIO calls. | 128 | platform-neutral GPIO calls. |
| 70 | 129 | ||
| 130 | comment "PCI GPIO expanders:" | ||
| 131 | |||
| 132 | config GPIO_BT8XX | ||
| 133 | tristate "BT8XX GPIO abuser" | ||
| 134 | depends on PCI && VIDEO_BT848=n | ||
| 135 | help | ||
| 136 | The BT8xx frame grabber chip has 24 GPIO pins than can be abused | ||
| 137 | as a cheap PCI GPIO card. | ||
| 138 | |||
| 139 | This chip can be found on Miro, Hauppauge and STB TV-cards. | ||
| 140 | |||
| 141 | The card needs to be physically altered for using it as a | ||
| 142 | GPIO card. For more information on how to build a GPIO card | ||
| 143 | from a BT8xx TV card, see the documentation file at | ||
| 144 | Documentation/bt8xxgpio.txt | ||
| 145 | |||
| 146 | If unsure, say N. | ||
| 147 | |||
| 71 | comment "SPI GPIO expanders:" | 148 | comment "SPI GPIO expanders:" |
| 72 | 149 | ||
| 73 | config GPIO_MAX7301 | 150 | config GPIO_MAX7301 |
| @@ -83,4 +160,4 @@ config GPIO_MCP23S08 | |||
| 83 | SPI driver for Microchip MCP23S08 I/O expander. This provides | 160 | SPI driver for Microchip MCP23S08 I/O expander. This provides |
| 84 | a GPIO interface supporting inputs and outputs. | 161 | a GPIO interface supporting inputs and outputs. |
| 85 | 162 | ||
| 86 | endmenu | 163 | endif |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 16e796dc5410..01b4bbde1956 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -2,9 +2,11 @@ | |||
| 2 | 2 | ||
| 3 | ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG | 3 | ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o | 5 | obj-$(CONFIG_GPIOLIB) += gpiolib.o |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_GPIO_MAX7301) += max7301.o | 7 | obj-$(CONFIG_GPIO_MAX7301) += max7301.o |
| 8 | obj-$(CONFIG_GPIO_MAX732X) += max732x.o | ||
| 8 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | 9 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o |
| 9 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 10 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
| 10 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 11 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
| 12 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | ||
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c new file mode 100644 index 000000000000..7a1168249dd5 --- /dev/null +++ b/drivers/gpio/bt8xxgpio.c | |||
| @@ -0,0 +1,348 @@ | |||
| 1 | /* | ||
| 2 | |||
| 3 | bt8xx GPIO abuser | ||
| 4 | |||
| 5 | Copyright (C) 2008 Michael Buesch <mb@bu3sch.de> | ||
| 6 | |||
| 7 | Please do _only_ contact the people listed _above_ with issues related to this driver. | ||
| 8 | All the other people listed below are not related to this driver. Their names | ||
| 9 | are only here, because this driver is derived from the bt848 driver. | ||
| 10 | |||
| 11 | |||
| 12 | Derived from the bt848 driver: | ||
| 13 | |||
| 14 | Copyright (C) 1996,97,98 Ralph Metzler | ||
| 15 | & Marcus Metzler | ||
| 16 | (c) 1999-2002 Gerd Knorr | ||
| 17 | |||
| 18 | some v4l2 code lines are taken from Justin's bttv2 driver which is | ||
| 19 | (c) 2000 Justin Schoeman | ||
| 20 | |||
| 21 | V4L1 removal from: | ||
| 22 | (c) 2005-2006 Nickolay V. Shmyrev | ||
| 23 | |||
| 24 | Fixes to be fully V4L2 compliant by | ||
| 25 | (c) 2006 Mauro Carvalho Chehab | ||
| 26 | |||
| 27 | Cropping and overscan support | ||
| 28 | Copyright (C) 2005, 2006 Michael H. Schimek | ||
| 29 | Sponsored by OPQ Systems AB | ||
| 30 | |||
| 31 | This program is free software; you can redistribute it and/or modify | ||
| 32 | it under the terms of the GNU General Public License as published by | ||
| 33 | the Free Software Foundation; either version 2 of the License, or | ||
| 34 | (at your option) any later version. | ||
| 35 | |||
| 36 | This program is distributed in the hope that it will be useful, | ||
| 37 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 38 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 39 | GNU General Public License for more details. | ||
| 40 | |||
| 41 | You should have received a copy of the GNU General Public License | ||
| 42 | along with this program; if not, write to the Free Software | ||
| 43 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 44 | */ | ||
| 45 | |||
| 46 | #include <linux/module.h> | ||
| 47 | #include <linux/pci.h> | ||
| 48 | #include <linux/spinlock.h> | ||
| 49 | |||
| 50 | #include <asm/gpio.h> | ||
| 51 | |||
| 52 | /* Steal the hardware definitions from the bttv driver. */ | ||
| 53 | #include "../media/video/bt8xx/bt848.h" | ||
| 54 | |||
| 55 | |||
| 56 | #define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */ | ||
| 57 | |||
| 58 | |||
| 59 | struct bt8xxgpio { | ||
| 60 | spinlock_t lock; | ||
| 61 | |||
| 62 | void __iomem *mmio; | ||
| 63 | struct pci_dev *pdev; | ||
| 64 | struct gpio_chip gpio; | ||
| 65 | |||
| 66 | #ifdef CONFIG_PM | ||
| 67 | u32 saved_outen; | ||
| 68 | u32 saved_data; | ||
| 69 | #endif | ||
| 70 | }; | ||
| 71 | |||
| 72 | #define bgwrite(dat, adr) writel((dat), bg->mmio+(adr)) | ||
| 73 | #define bgread(adr) readl(bg->mmio+(adr)) | ||
| 74 | |||
| 75 | |||
| 76 | static int modparam_gpiobase = -1/* dynamic */; | ||
| 77 | module_param_named(gpiobase, modparam_gpiobase, int, 0444); | ||
| 78 | MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default."); | ||
| 79 | |||
| 80 | |||
| 81 | static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | ||
| 82 | { | ||
| 83 | struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); | ||
| 84 | unsigned long flags; | ||
| 85 | u32 outen, data; | ||
| 86 | |||
| 87 | spin_lock_irqsave(&bg->lock, flags); | ||
| 88 | |||
| 89 | data = bgread(BT848_GPIO_DATA); | ||
| 90 | data &= ~(1 << nr); | ||
| 91 | bgwrite(data, BT848_GPIO_DATA); | ||
| 92 | |||
| 93 | outen = bgread(BT848_GPIO_OUT_EN); | ||
| 94 | outen &= ~(1 << nr); | ||
| 95 | bgwrite(outen, BT848_GPIO_OUT_EN); | ||
| 96 | |||
| 97 | spin_unlock_irqrestore(&bg->lock, flags); | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) | ||
| 103 | { | ||
| 104 | struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); | ||
| 105 | unsigned long flags; | ||
| 106 | u32 val; | ||
| 107 | |||
| 108 | spin_lock_irqsave(&bg->lock, flags); | ||
| 109 | val = bgread(BT848_GPIO_DATA); | ||
| 110 | spin_unlock_irqrestore(&bg->lock, flags); | ||
| 111 | |||
| 112 | return !!(val & (1 << nr)); | ||
| 113 | } | ||
| 114 | |||
| 115 | static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio, | ||
| 116 | unsigned nr, int val) | ||
| 117 | { | ||
| 118 | struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); | ||
| 119 | unsigned long flags; | ||
| 120 | u32 outen, data; | ||
| 121 | |||
| 122 | spin_lock_irqsave(&bg->lock, flags); | ||
| 123 | |||
| 124 | outen = bgread(BT848_GPIO_OUT_EN); | ||
| 125 | outen |= (1 << nr); | ||
| 126 | bgwrite(outen, BT848_GPIO_OUT_EN); | ||
| 127 | |||
| 128 | data = bgread(BT848_GPIO_DATA); | ||
| 129 | if (val) | ||
| 130 | data |= (1 << nr); | ||
| 131 | else | ||
| 132 | data &= ~(1 << nr); | ||
| 133 | bgwrite(data, BT848_GPIO_DATA); | ||
| 134 | |||
| 135 | spin_unlock_irqrestore(&bg->lock, flags); | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void bt8xxgpio_gpio_set(struct gpio_chip *gpio, | ||
| 141 | unsigned nr, int val) | ||
| 142 | { | ||
| 143 | struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio); | ||
| 144 | unsigned long flags; | ||
| 145 | u32 data; | ||
| 146 | |||
| 147 | spin_lock_irqsave(&bg->lock, flags); | ||
| 148 | |||
| 149 | data = bgread(BT848_GPIO_DATA); | ||
| 150 | if (val) | ||
| 151 | data |= (1 << nr); | ||
| 152 | else | ||
| 153 | data &= ~(1 << nr); | ||
| 154 | bgwrite(data, BT848_GPIO_DATA); | ||
| 155 | |||
| 156 | spin_unlock_irqrestore(&bg->lock, flags); | ||
| 157 | } | ||
| 158 | |||
| 159 | static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) | ||
| 160 | { | ||
| 161 | struct gpio_chip *c = &bg->gpio; | ||
| 162 | |||
| 163 | c->label = bg->pdev->dev.bus_id; | ||
| 164 | c->owner = THIS_MODULE; | ||
| 165 | c->direction_input = bt8xxgpio_gpio_direction_input; | ||
| 166 | c->get = bt8xxgpio_gpio_get; | ||
| 167 | c->direction_output = bt8xxgpio_gpio_direction_output; | ||
| 168 | c->set = bt8xxgpio_gpio_set; | ||
| 169 | c->dbg_show = NULL; | ||
| 170 | c->base = modparam_gpiobase; | ||
| 171 | c->ngpio = BT8XXGPIO_NR_GPIOS; | ||
| 172 | c->can_sleep = 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | static int bt8xxgpio_probe(struct pci_dev *dev, | ||
| 176 | const struct pci_device_id *pci_id) | ||
| 177 | { | ||
| 178 | struct bt8xxgpio *bg; | ||
| 179 | int err; | ||
| 180 | |||
| 181 | bg = kzalloc(sizeof(*bg), GFP_KERNEL); | ||
| 182 | if (!bg) | ||
| 183 | return -ENOMEM; | ||
| 184 | |||
| 185 | bg->pdev = dev; | ||
| 186 | spin_lock_init(&bg->lock); | ||
| 187 | |||
| 188 | err = pci_enable_device(dev); | ||
| 189 | if (err) { | ||
| 190 | printk(KERN_ERR "bt8xxgpio: Can't enable device.\n"); | ||
| 191 | goto err_freebg; | ||
| 192 | } | ||
| 193 | if (!request_mem_region(pci_resource_start(dev, 0), | ||
| 194 | pci_resource_len(dev, 0), | ||
| 195 | "bt8xxgpio")) { | ||
| 196 | printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n", | ||
| 197 | (unsigned long long)pci_resource_start(dev, 0)); | ||
| 198 | err = -EBUSY; | ||
| 199 | goto err_disable; | ||
| 200 | } | ||
| 201 | pci_set_master(dev); | ||
| 202 | pci_set_drvdata(dev, bg); | ||
| 203 | |||
| 204 | bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000); | ||
| 205 | if (!bg->mmio) { | ||
| 206 | printk(KERN_ERR "bt8xxgpio: ioremap() failed\n"); | ||
| 207 | err = -EIO; | ||
| 208 | goto err_release_mem; | ||
| 209 | } | ||
| 210 | |||
| 211 | /* Disable interrupts */ | ||
| 212 | bgwrite(0, BT848_INT_MASK); | ||
| 213 | |||
| 214 | /* gpio init */ | ||
| 215 | bgwrite(0, BT848_GPIO_DMA_CTL); | ||
| 216 | bgwrite(0, BT848_GPIO_REG_INP); | ||
| 217 | bgwrite(0, BT848_GPIO_OUT_EN); | ||
| 218 | |||
| 219 | bt8xxgpio_gpio_setup(bg); | ||
| 220 | err = gpiochip_add(&bg->gpio); | ||
| 221 | if (err) { | ||
| 222 | printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n"); | ||
| 223 | goto err_release_mem; | ||
| 224 | } | ||
| 225 | |||
| 226 | printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n", | ||
| 227 | bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1); | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | |||
| 231 | err_release_mem: | ||
| 232 | release_mem_region(pci_resource_start(dev, 0), | ||
| 233 | pci_resource_len(dev, 0)); | ||
| 234 | pci_set_drvdata(dev, NULL); | ||
| 235 | err_disable: | ||
| 236 | pci_disable_device(dev); | ||
| 237 | err_freebg: | ||
| 238 | kfree(bg); | ||
| 239 | |||
| 240 | return err; | ||
| 241 | } | ||
| 242 | |||
| 243 | static void bt8xxgpio_remove(struct pci_dev *pdev) | ||
| 244 | { | ||
| 245 | struct bt8xxgpio *bg = pci_get_drvdata(pdev); | ||
| 246 | |||
| 247 | gpiochip_remove(&bg->gpio); | ||
| 248 | |||
| 249 | bgwrite(0, BT848_INT_MASK); | ||
| 250 | bgwrite(~0x0, BT848_INT_STAT); | ||
| 251 | bgwrite(0x0, BT848_GPIO_OUT_EN); | ||
| 252 | |||
| 253 | iounmap(bg->mmio); | ||
| 254 | release_mem_region(pci_resource_start(pdev, 0), | ||
| 255 | pci_resource_len(pdev, 0)); | ||
| 256 | pci_disable_device(pdev); | ||
| 257 | |||
| 258 | pci_set_drvdata(pdev, NULL); | ||
| 259 | kfree(bg); | ||
| 260 | } | ||
| 261 | |||
| 262 | #ifdef CONFIG_PM | ||
| 263 | static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 264 | { | ||
| 265 | struct bt8xxgpio *bg = pci_get_drvdata(pdev); | ||
| 266 | unsigned long flags; | ||
| 267 | |||
| 268 | spin_lock_irqsave(&bg->lock, flags); | ||
| 269 | |||
| 270 | bg->saved_outen = bgread(BT848_GPIO_OUT_EN); | ||
| 271 | bg->saved_data = bgread(BT848_GPIO_DATA); | ||
| 272 | |||
| 273 | bgwrite(0, BT848_INT_MASK); | ||
| 274 | bgwrite(~0x0, BT848_INT_STAT); | ||
| 275 | bgwrite(0x0, BT848_GPIO_OUT_EN); | ||
| 276 | |||
| 277 | spin_unlock_irqrestore(&bg->lock, flags); | ||
| 278 | |||
| 279 | pci_save_state(pdev); | ||
| 280 | pci_disable_device(pdev); | ||
| 281 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
| 282 | |||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | static int bt8xxgpio_resume(struct pci_dev *pdev) | ||
| 287 | { | ||
| 288 | struct bt8xxgpio *bg = pci_get_drvdata(pdev); | ||
| 289 | unsigned long flags; | ||
| 290 | int err; | ||
| 291 | |||
| 292 | pci_set_power_state(pdev, 0); | ||
| 293 | err = pci_enable_device(pdev); | ||
| 294 | if (err) | ||
| 295 | return err; | ||
| 296 | pci_restore_state(pdev); | ||
| 297 | |||
| 298 | spin_lock_irqsave(&bg->lock, flags); | ||
| 299 | |||
| 300 | bgwrite(0, BT848_INT_MASK); | ||
| 301 | bgwrite(0, BT848_GPIO_DMA_CTL); | ||
| 302 | bgwrite(0, BT848_GPIO_REG_INP); | ||
| 303 | bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN); | ||
| 304 | bgwrite(bg->saved_data & bg->saved_outen, | ||
| 305 | BT848_GPIO_DATA); | ||
| 306 | |||
| 307 | spin_unlock_irqrestore(&bg->lock, flags); | ||
| 308 | |||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | #else | ||
| 312 | #define bt8xxgpio_suspend NULL | ||
| 313 | #define bt8xxgpio_resume NULL | ||
| 314 | #endif /* CONFIG_PM */ | ||
| 315 | |||
| 316 | static struct pci_device_id bt8xxgpio_pci_tbl[] = { | ||
| 317 | { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) }, | ||
| 318 | { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) }, | ||
| 319 | { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) }, | ||
| 320 | { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) }, | ||
| 321 | { 0, }, | ||
| 322 | }; | ||
| 323 | MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl); | ||
| 324 | |||
| 325 | static struct pci_driver bt8xxgpio_pci_driver = { | ||
| 326 | .name = "bt8xxgpio", | ||
| 327 | .id_table = bt8xxgpio_pci_tbl, | ||
| 328 | .probe = bt8xxgpio_probe, | ||
| 329 | .remove = bt8xxgpio_remove, | ||
| 330 | .suspend = bt8xxgpio_suspend, | ||
| 331 | .resume = bt8xxgpio_resume, | ||
| 332 | }; | ||
| 333 | |||
| 334 | static int bt8xxgpio_init(void) | ||
| 335 | { | ||
| 336 | return pci_register_driver(&bt8xxgpio_pci_driver); | ||
| 337 | } | ||
| 338 | module_init(bt8xxgpio_init) | ||
| 339 | |||
| 340 | static void bt8xxgpio_exit(void) | ||
| 341 | { | ||
| 342 | pci_unregister_driver(&bt8xxgpio_pci_driver); | ||
| 343 | } | ||
| 344 | module_exit(bt8xxgpio_exit) | ||
| 345 | |||
| 346 | MODULE_LICENSE("GPL"); | ||
| 347 | MODULE_AUTHOR("Michael Buesch"); | ||
| 348 | MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card"); | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index beaf6b3a37dc..8d2940517c99 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -2,8 +2,11 @@ | |||
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/irq.h> | 3 | #include <linux/irq.h> |
| 4 | #include <linux/spinlock.h> | 4 | #include <linux/spinlock.h> |
| 5 | 5 | #include <linux/device.h> | |
| 6 | #include <asm/gpio.h> | 6 | #include <linux/err.h> |
| 7 | #include <linux/debugfs.h> | ||
| 8 | #include <linux/seq_file.h> | ||
| 9 | #include <linux/gpio.h> | ||
| 7 | 10 | ||
| 8 | 11 | ||
| 9 | /* Optional implementation infrastructure for GPIO interfaces. | 12 | /* Optional implementation infrastructure for GPIO interfaces. |
| @@ -44,6 +47,8 @@ struct gpio_desc { | |||
| 44 | #define FLAG_REQUESTED 0 | 47 | #define FLAG_REQUESTED 0 |
| 45 | #define FLAG_IS_OUT 1 | 48 | #define FLAG_IS_OUT 1 |
| 46 | #define FLAG_RESERVED 2 | 49 | #define FLAG_RESERVED 2 |
| 50 | #define FLAG_EXPORT 3 /* protected by sysfs_lock */ | ||
| 51 | #define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ | ||
| 47 | 52 | ||
| 48 | #ifdef CONFIG_DEBUG_FS | 53 | #ifdef CONFIG_DEBUG_FS |
| 49 | const char *label; | 54 | const char *label; |
| @@ -151,6 +156,482 @@ err: | |||
| 151 | return ret; | 156 | return ret; |
| 152 | } | 157 | } |
| 153 | 158 | ||
| 159 | #ifdef CONFIG_GPIO_SYSFS | ||
| 160 | |||
| 161 | /* lock protects against unexport_gpio() being called while | ||
| 162 | * sysfs files are active. | ||
| 163 | */ | ||
| 164 | static DEFINE_MUTEX(sysfs_lock); | ||
| 165 | |||
| 166 | /* | ||
| 167 | * /sys/class/gpio/gpioN... only for GPIOs that are exported | ||
| 168 | * /direction | ||
| 169 | * * MAY BE OMITTED if kernel won't allow direction changes | ||
| 170 | * * is read/write as "in" or "out" | ||
| 171 | * * may also be written as "high" or "low", initializing | ||
| 172 | * output value as specified ("out" implies "low") | ||
| 173 | * /value | ||
| 174 | * * always readable, subject to hardware behavior | ||
| 175 | * * may be writable, as zero/nonzero | ||
| 176 | * | ||
| 177 | * REVISIT there will likely be an attribute for configuring async | ||
| 178 | * notifications, e.g. to specify polling interval or IRQ trigger type | ||
| 179 | * that would for example trigger a poll() on the "value". | ||
| 180 | */ | ||
| 181 | |||
| 182 | static ssize_t gpio_direction_show(struct device *dev, | ||
| 183 | struct device_attribute *attr, char *buf) | ||
| 184 | { | ||
| 185 | const struct gpio_desc *desc = dev_get_drvdata(dev); | ||
| 186 | ssize_t status; | ||
| 187 | |||
| 188 | mutex_lock(&sysfs_lock); | ||
| 189 | |||
| 190 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | ||
| 191 | status = -EIO; | ||
| 192 | else | ||
| 193 | status = sprintf(buf, "%s\n", | ||
| 194 | test_bit(FLAG_IS_OUT, &desc->flags) | ||
| 195 | ? "out" : "in"); | ||
| 196 | |||
| 197 | mutex_unlock(&sysfs_lock); | ||
| 198 | return status; | ||
| 199 | } | ||
| 200 | |||
| 201 | static ssize_t gpio_direction_store(struct device *dev, | ||
| 202 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 203 | { | ||
| 204 | const struct gpio_desc *desc = dev_get_drvdata(dev); | ||
| 205 | unsigned gpio = desc - gpio_desc; | ||
| 206 | ssize_t status; | ||
| 207 | |||
| 208 | mutex_lock(&sysfs_lock); | ||
| 209 | |||
| 210 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | ||
| 211 | status = -EIO; | ||
| 212 | else if (sysfs_streq(buf, "high")) | ||
| 213 | status = gpio_direction_output(gpio, 1); | ||
| 214 | else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low")) | ||
| 215 | status = gpio_direction_output(gpio, 0); | ||
| 216 | else if (sysfs_streq(buf, "in")) | ||
| 217 | status = gpio_direction_input(gpio); | ||
| 218 | else | ||
| 219 | status = -EINVAL; | ||
| 220 | |||
| 221 | mutex_unlock(&sysfs_lock); | ||
| 222 | return status ? : size; | ||
| 223 | } | ||
| 224 | |||
| 225 | static const DEVICE_ATTR(direction, 0644, | ||
| 226 | gpio_direction_show, gpio_direction_store); | ||
| 227 | |||
| 228 | static ssize_t gpio_value_show(struct device *dev, | ||
| 229 | struct device_attribute *attr, char *buf) | ||
| 230 | { | ||
| 231 | const struct gpio_desc *desc = dev_get_drvdata(dev); | ||
| 232 | unsigned gpio = desc - gpio_desc; | ||
| 233 | ssize_t status; | ||
| 234 | |||
| 235 | mutex_lock(&sysfs_lock); | ||
| 236 | |||
| 237 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | ||
| 238 | status = -EIO; | ||
| 239 | else | ||
| 240 | status = sprintf(buf, "%d\n", gpio_get_value_cansleep(gpio)); | ||
| 241 | |||
| 242 | mutex_unlock(&sysfs_lock); | ||
| 243 | return status; | ||
| 244 | } | ||
| 245 | |||
| 246 | static ssize_t gpio_value_store(struct device *dev, | ||
| 247 | struct device_attribute *attr, const char *buf, size_t size) | ||
| 248 | { | ||
| 249 | const struct gpio_desc *desc = dev_get_drvdata(dev); | ||
| 250 | unsigned gpio = desc - gpio_desc; | ||
| 251 | ssize_t status; | ||
| 252 | |||
| 253 | mutex_lock(&sysfs_lock); | ||
| 254 | |||
| 255 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | ||
| 256 | status = -EIO; | ||
| 257 | else if (!test_bit(FLAG_IS_OUT, &desc->flags)) | ||
| 258 | status = -EPERM; | ||
| 259 | else { | ||
| 260 | long value; | ||
| 261 | |||
| 262 | status = strict_strtol(buf, 0, &value); | ||
| 263 | if (status == 0) { | ||
| 264 | gpio_set_value_cansleep(gpio, value != 0); | ||
| 265 | status = size; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | mutex_unlock(&sysfs_lock); | ||
| 270 | return status; | ||
| 271 | } | ||
| 272 | |||
| 273 | static /*const*/ DEVICE_ATTR(value, 0644, | ||
| 274 | gpio_value_show, gpio_value_store); | ||
| 275 | |||
| 276 | static const struct attribute *gpio_attrs[] = { | ||
| 277 | &dev_attr_direction.attr, | ||
| 278 | &dev_attr_value.attr, | ||
| 279 | NULL, | ||
| 280 | }; | ||
| 281 | |||
| 282 | static const struct attribute_group gpio_attr_group = { | ||
| 283 | .attrs = (struct attribute **) gpio_attrs, | ||
| 284 | }; | ||
| 285 | |||
| 286 | /* | ||
| 287 | * /sys/class/gpio/gpiochipN/ | ||
| 288 | * /base ... matching gpio_chip.base (N) | ||
| 289 | * /label ... matching gpio_chip.label | ||
| 290 | * /ngpio ... matching gpio_chip.ngpio | ||
| 291 | */ | ||
| 292 | |||
| 293 | static ssize_t chip_base_show(struct device *dev, | ||
| 294 | struct device_attribute *attr, char *buf) | ||
| 295 | { | ||
| 296 | const struct gpio_chip *chip = dev_get_drvdata(dev); | ||
| 297 | |||
| 298 | return sprintf(buf, "%d\n", chip->base); | ||
| 299 | } | ||
| 300 | static DEVICE_ATTR(base, 0444, chip_base_show, NULL); | ||
| 301 | |||
| 302 | static ssize_t chip_label_show(struct device *dev, | ||
| 303 | struct device_attribute *attr, char *buf) | ||
| 304 | { | ||
| 305 | const struct gpio_chip *chip = dev_get_drvdata(dev); | ||
| 306 | |||
| 307 | return sprintf(buf, "%s\n", chip->label ? : ""); | ||
| 308 | } | ||
| 309 | static DEVICE_ATTR(label, 0444, chip_label_show, NULL); | ||
| 310 | |||
| 311 | static ssize_t chip_ngpio_show(struct device *dev, | ||
| 312 | struct device_attribute *attr, char *buf) | ||
| 313 | { | ||
| 314 | const struct gpio_chip *chip = dev_get_drvdata(dev); | ||
| 315 | |||
| 316 | return sprintf(buf, "%u\n", chip->ngpio); | ||
| 317 | } | ||
| 318 | static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); | ||
| 319 | |||
| 320 | static const struct attribute *gpiochip_attrs[] = { | ||
| 321 | &dev_attr_base.attr, | ||
| 322 | &dev_attr_label.attr, | ||
| 323 | &dev_attr_ngpio.attr, | ||
| 324 | NULL, | ||
| 325 | }; | ||
| 326 | |||
| 327 | static const struct attribute_group gpiochip_attr_group = { | ||
| 328 | .attrs = (struct attribute **) gpiochip_attrs, | ||
| 329 | }; | ||
| 330 | |||
| 331 | /* | ||
| 332 | * /sys/class/gpio/export ... write-only | ||
| 333 | * integer N ... number of GPIO to export (full access) | ||
| 334 | * /sys/class/gpio/unexport ... write-only | ||
| 335 | * integer N ... number of GPIO to unexport | ||
| 336 | */ | ||
| 337 | static ssize_t export_store(struct class *class, const char *buf, size_t len) | ||
| 338 | { | ||
| 339 | long gpio; | ||
| 340 | int status; | ||
| 341 | |||
| 342 | status = strict_strtol(buf, 0, &gpio); | ||
| 343 | if (status < 0) | ||
| 344 | goto done; | ||
| 345 | |||
| 346 | /* No extra locking here; FLAG_SYSFS just signifies that the | ||
| 347 | * request and export were done by on behalf of userspace, so | ||
| 348 | * they may be undone on its behalf too. | ||
| 349 | */ | ||
| 350 | |||
| 351 | status = gpio_request(gpio, "sysfs"); | ||
| 352 | if (status < 0) | ||
| 353 | goto done; | ||
| 354 | |||
| 355 | status = gpio_export(gpio, true); | ||
| 356 | if (status < 0) | ||
| 357 | gpio_free(gpio); | ||
| 358 | else | ||
| 359 | set_bit(FLAG_SYSFS, &gpio_desc[gpio].flags); | ||
| 360 | |||
| 361 | done: | ||
| 362 | if (status) | ||
| 363 | pr_debug("%s: status %d\n", __func__, status); | ||
| 364 | return status ? : len; | ||
| 365 | } | ||
| 366 | |||
| 367 | static ssize_t unexport_store(struct class *class, const char *buf, size_t len) | ||
| 368 | { | ||
| 369 | long gpio; | ||
| 370 | int status; | ||
| 371 | |||
| 372 | status = strict_strtol(buf, 0, &gpio); | ||
| 373 | if (status < 0) | ||
| 374 | goto done; | ||
| 375 | |||
| 376 | status = -EINVAL; | ||
| 377 | |||
| 378 | /* reject bogus commands (gpio_unexport ignores them) */ | ||
| 379 | if (!gpio_is_valid(gpio)) | ||
| 380 | goto done; | ||
| 381 | |||
| 382 | /* No extra locking here; FLAG_SYSFS just signifies that the | ||
| 383 | * request and export were done by on behalf of userspace, so | ||
| 384 | * they may be undone on its behalf too. | ||
| 385 | */ | ||
| 386 | if (test_and_clear_bit(FLAG_SYSFS, &gpio_desc[gpio].flags)) { | ||
| 387 | status = 0; | ||
| 388 | gpio_free(gpio); | ||
| 389 | } | ||
| 390 | done: | ||
| 391 | if (status) | ||
| 392 | pr_debug("%s: status %d\n", __func__, status); | ||
| 393 | return status ? : len; | ||
| 394 | } | ||
| 395 | |||
| 396 | static struct class_attribute gpio_class_attrs[] = { | ||
| 397 | __ATTR(export, 0200, NULL, export_store), | ||
| 398 | __ATTR(unexport, 0200, NULL, unexport_store), | ||
| 399 | __ATTR_NULL, | ||
| 400 | }; | ||
| 401 | |||
| 402 | static struct class gpio_class = { | ||
| 403 | .name = "gpio", | ||
| 404 | .owner = THIS_MODULE, | ||
| 405 | |||
| 406 | .class_attrs = gpio_class_attrs, | ||
| 407 | }; | ||
| 408 | |||
| 409 | |||
| 410 | /** | ||
| 411 | * gpio_export - export a GPIO through sysfs | ||
| 412 | * @gpio: gpio to make available, already requested | ||
| 413 | * @direction_may_change: true if userspace may change gpio direction | ||
| 414 | * Context: arch_initcall or later | ||
| 415 | * | ||
| 416 | * When drivers want to make a GPIO accessible to userspace after they | ||
| 417 | * have requested it -- perhaps while debugging, or as part of their | ||
| 418 | * public interface -- they may use this routine. If the GPIO can | ||
| 419 | * change direction (some can't) and the caller allows it, userspace | ||
| 420 | * will see "direction" sysfs attribute which may be used to change | ||
| 421 | * the gpio's direction. A "value" attribute will always be provided. | ||
| 422 | * | ||
| 423 | * Returns zero on success, else an error. | ||
| 424 | */ | ||
| 425 | int gpio_export(unsigned gpio, bool direction_may_change) | ||
| 426 | { | ||
| 427 | unsigned long flags; | ||
| 428 | struct gpio_desc *desc; | ||
| 429 | int status = -EINVAL; | ||
| 430 | |||
| 431 | /* can't export until sysfs is available ... */ | ||
| 432 | if (!gpio_class.p) { | ||
| 433 | pr_debug("%s: called too early!\n", __func__); | ||
| 434 | return -ENOENT; | ||
| 435 | } | ||
| 436 | |||
| 437 | if (!gpio_is_valid(gpio)) | ||
| 438 | goto done; | ||
| 439 | |||
| 440 | mutex_lock(&sysfs_lock); | ||
| 441 | |||
| 442 | spin_lock_irqsave(&gpio_lock, flags); | ||
| 443 | desc = &gpio_desc[gpio]; | ||
| 444 | if (test_bit(FLAG_REQUESTED, &desc->flags) | ||
| 445 | && !test_bit(FLAG_EXPORT, &desc->flags)) { | ||
| 446 | status = 0; | ||
| 447 | if (!desc->chip->direction_input | ||
| 448 | || !desc->chip->direction_output) | ||
| 449 | direction_may_change = false; | ||
| 450 | } | ||
| 451 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
| 452 | |||
| 453 | if (status == 0) { | ||
| 454 | struct device *dev; | ||
| 455 | |||
| 456 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), | ||
| 457 | desc, "gpio%d", gpio); | ||
| 458 | if (dev) { | ||
| 459 | if (direction_may_change) | ||
| 460 | status = sysfs_create_group(&dev->kobj, | ||
| 461 | &gpio_attr_group); | ||
| 462 | else | ||
| 463 | status = device_create_file(dev, | ||
| 464 | &dev_attr_value); | ||
| 465 | if (status != 0) | ||
| 466 | device_unregister(dev); | ||
| 467 | } else | ||
| 468 | status = -ENODEV; | ||
| 469 | if (status == 0) | ||
| 470 | set_bit(FLAG_EXPORT, &desc->flags); | ||
| 471 | } | ||
| 472 | |||
| 473 | mutex_unlock(&sysfs_lock); | ||
| 474 | |||
| 475 | done: | ||
| 476 | if (status) | ||
| 477 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | ||
| 478 | |||
| 479 | return status; | ||
| 480 | } | ||
| 481 | EXPORT_SYMBOL_GPL(gpio_export); | ||
| 482 | |||
| 483 | static int match_export(struct device *dev, void *data) | ||
| 484 | { | ||
| 485 | return dev_get_drvdata(dev) == data; | ||
| 486 | } | ||
| 487 | |||
| 488 | /** | ||
| 489 | * gpio_unexport - reverse effect of gpio_export() | ||
| 490 | * @gpio: gpio to make unavailable | ||
| 491 | * | ||
| 492 | * This is implicit on gpio_free(). | ||
| 493 | */ | ||
| 494 | void gpio_unexport(unsigned gpio) | ||
| 495 | { | ||
| 496 | struct gpio_desc *desc; | ||
| 497 | int status = -EINVAL; | ||
| 498 | |||
| 499 | if (!gpio_is_valid(gpio)) | ||
| 500 | goto done; | ||
| 501 | |||
| 502 | mutex_lock(&sysfs_lock); | ||
| 503 | |||
| 504 | desc = &gpio_desc[gpio]; | ||
| 505 | if (test_bit(FLAG_EXPORT, &desc->flags)) { | ||
| 506 | struct device *dev = NULL; | ||
| 507 | |||
| 508 | dev = class_find_device(&gpio_class, NULL, desc, match_export); | ||
| 509 | if (dev) { | ||
| 510 | clear_bit(FLAG_EXPORT, &desc->flags); | ||
| 511 | put_device(dev); | ||
| 512 | device_unregister(dev); | ||
| 513 | status = 0; | ||
| 514 | } else | ||
| 515 | status = -ENODEV; | ||
| 516 | } | ||
| 517 | |||
| 518 | mutex_unlock(&sysfs_lock); | ||
| 519 | done: | ||
| 520 | if (status) | ||
| 521 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | ||
| 522 | } | ||
| 523 | EXPORT_SYMBOL_GPL(gpio_unexport); | ||
| 524 | |||
| 525 | static int gpiochip_export(struct gpio_chip *chip) | ||
| 526 | { | ||
| 527 | int status; | ||
| 528 | struct device *dev; | ||
| 529 | |||
| 530 | /* Many systems register gpio chips for SOC support very early, | ||
| 531 | * before driver model support is available. In those cases we | ||
| 532 | * export this later, in gpiolib_sysfs_init() ... here we just | ||
| 533 | * verify that _some_ field of gpio_class got initialized. | ||
| 534 | */ | ||
| 535 | if (!gpio_class.p) | ||
| 536 | return 0; | ||
| 537 | |||
| 538 | /* use chip->base for the ID; it's already known to be unique */ | ||
| 539 | mutex_lock(&sysfs_lock); | ||
| 540 | dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip, | ||
| 541 | "gpiochip%d", chip->base); | ||
| 542 | if (dev) { | ||
| 543 | status = sysfs_create_group(&dev->kobj, | ||
| 544 | &gpiochip_attr_group); | ||
| 545 | } else | ||
| 546 | status = -ENODEV; | ||
| 547 | chip->exported = (status == 0); | ||
| 548 | mutex_unlock(&sysfs_lock); | ||
| 549 | |||
| 550 | if (status) { | ||
| 551 | unsigned long flags; | ||
| 552 | unsigned gpio; | ||
| 553 | |||
| 554 | spin_lock_irqsave(&gpio_lock, flags); | ||
| 555 | gpio = chip->base; | ||
| 556 | while (gpio_desc[gpio].chip == chip) | ||
| 557 | gpio_desc[gpio++].chip = NULL; | ||
| 558 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
| 559 | |||
| 560 | pr_debug("%s: chip %s status %d\n", __func__, | ||
| 561 | chip->label, status); | ||
| 562 | } | ||
| 563 | |||
| 564 | return status; | ||
| 565 | } | ||
| 566 | |||
| 567 | static void gpiochip_unexport(struct gpio_chip *chip) | ||
| 568 | { | ||
| 569 | int status; | ||
| 570 | struct device *dev; | ||
| 571 | |||
| 572 | mutex_lock(&sysfs_lock); | ||
| 573 | dev = class_find_device(&gpio_class, NULL, chip, match_export); | ||
| 574 | if (dev) { | ||
| 575 | put_device(dev); | ||
| 576 | device_unregister(dev); | ||
| 577 | chip->exported = 0; | ||
| 578 | status = 0; | ||
| 579 | } else | ||
| 580 | status = -ENODEV; | ||
| 581 | mutex_unlock(&sysfs_lock); | ||
| 582 | |||
| 583 | if (status) | ||
| 584 | pr_debug("%s: chip %s status %d\n", __func__, | ||
| 585 | chip->label, status); | ||
| 586 | } | ||
| 587 | |||
| 588 | static int __init gpiolib_sysfs_init(void) | ||
| 589 | { | ||
| 590 | int status; | ||
| 591 | unsigned long flags; | ||
| 592 | unsigned gpio; | ||
| 593 | |||
| 594 | status = class_register(&gpio_class); | ||
| 595 | if (status < 0) | ||
| 596 | return status; | ||
| 597 | |||
| 598 | /* Scan and register the gpio_chips which registered very | ||
| 599 | * early (e.g. before the class_register above was called). | ||
| 600 | * | ||
| 601 | * We run before arch_initcall() so chip->dev nodes can have | ||
| 602 | * registered, and so arch_initcall() can always gpio_export(). | ||
| 603 | */ | ||
| 604 | spin_lock_irqsave(&gpio_lock, flags); | ||
| 605 | for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) { | ||
| 606 | struct gpio_chip *chip; | ||
| 607 | |||
| 608 | chip = gpio_desc[gpio].chip; | ||
| 609 | if (!chip || chip->exported) | ||
| 610 | continue; | ||
| 611 | |||
| 612 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
| 613 | status = gpiochip_export(chip); | ||
| 614 | spin_lock_irqsave(&gpio_lock, flags); | ||
| 615 | } | ||
| 616 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
| 617 | |||
| 618 | |||
| 619 | return status; | ||
| 620 | } | ||
| 621 | postcore_initcall(gpiolib_sysfs_init); | ||
| 622 | |||
| 623 | #else | ||
| 624 | static inline int gpiochip_export(struct gpio_chip *chip) | ||
| 625 | { | ||
| 626 | return 0; | ||
| 627 | } | ||
| 628 | |||
| 629 | static inline void gpiochip_unexport(struct gpio_chip *chip) | ||
| 630 | { | ||
| 631 | } | ||
| 632 | |||
| 633 | #endif /* CONFIG_GPIO_SYSFS */ | ||
| 634 | |||
| 154 | /** | 635 | /** |
| 155 | * gpiochip_add() - register a gpio_chip | 636 | * gpiochip_add() - register a gpio_chip |
| 156 | * @chip: the chip to register, with chip->base initialized | 637 | * @chip: the chip to register, with chip->base initialized |
| @@ -160,6 +641,11 @@ err: | |||
| 160 | * because the chip->base is invalid or already associated with a | 641 | * because the chip->base is invalid or already associated with a |
| 161 | * different chip. Otherwise it returns zero as a success code. | 642 | * different chip. Otherwise it returns zero as a success code. |
| 162 | * | 643 | * |
| 644 | * When gpiochip_add() is called very early during boot, so that GPIOs | ||
| 645 | * can be freely used, the chip->dev device must be registered before | ||
| 646 | * the gpio framework's arch_initcall(). Otherwise sysfs initialization | ||
| 647 | * for GPIOs will fail rudely. | ||
| 648 | * | ||
| 163 | * If chip->base is negative, this requests dynamic assignment of | 649 | * If chip->base is negative, this requests dynamic assignment of |
| 164 | * a range of valid GPIOs. | 650 | * a range of valid GPIOs. |
| 165 | */ | 651 | */ |
| @@ -182,7 +668,7 @@ int gpiochip_add(struct gpio_chip *chip) | |||
| 182 | base = gpiochip_find_base(chip->ngpio); | 668 | base = gpiochip_find_base(chip->ngpio); |
| 183 | if (base < 0) { | 669 | if (base < 0) { |
| 184 | status = base; | 670 | status = base; |
| 185 | goto fail_unlock; | 671 | goto unlock; |
| 186 | } | 672 | } |
| 187 | chip->base = base; | 673 | chip->base = base; |
| 188 | } | 674 | } |
| @@ -197,12 +683,23 @@ int gpiochip_add(struct gpio_chip *chip) | |||
| 197 | if (status == 0) { | 683 | if (status == 0) { |
| 198 | for (id = base; id < base + chip->ngpio; id++) { | 684 | for (id = base; id < base + chip->ngpio; id++) { |
| 199 | gpio_desc[id].chip = chip; | 685 | gpio_desc[id].chip = chip; |
| 200 | gpio_desc[id].flags = 0; | 686 | |
| 687 | /* REVISIT: most hardware initializes GPIOs as | ||
| 688 | * inputs (often with pullups enabled) so power | ||
| 689 | * usage is minimized. Linux code should set the | ||
| 690 | * gpio direction first thing; but until it does, | ||
| 691 | * we may expose the wrong direction in sysfs. | ||
| 692 | */ | ||
| 693 | gpio_desc[id].flags = !chip->direction_input | ||
| 694 | ? (1 << FLAG_IS_OUT) | ||
| 695 | : 0; | ||
| 201 | } | 696 | } |
| 202 | } | 697 | } |
| 203 | 698 | ||
| 204 | fail_unlock: | 699 | unlock: |
| 205 | spin_unlock_irqrestore(&gpio_lock, flags); | 700 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 701 | if (status == 0) | ||
| 702 | status = gpiochip_export(chip); | ||
| 206 | fail: | 703 | fail: |
| 207 | /* failures here can mean systems won't boot... */ | 704 | /* failures here can mean systems won't boot... */ |
| 208 | if (status) | 705 | if (status) |
| @@ -239,6 +736,10 @@ int gpiochip_remove(struct gpio_chip *chip) | |||
| 239 | } | 736 | } |
| 240 | 737 | ||
| 241 | spin_unlock_irqrestore(&gpio_lock, flags); | 738 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 739 | |||
| 740 | if (status == 0) | ||
| 741 | gpiochip_unexport(chip); | ||
| 742 | |||
| 242 | return status; | 743 | return status; |
| 243 | } | 744 | } |
| 244 | EXPORT_SYMBOL_GPL(gpiochip_remove); | 745 | EXPORT_SYMBOL_GPL(gpiochip_remove); |
| @@ -296,6 +797,8 @@ void gpio_free(unsigned gpio) | |||
| 296 | return; | 797 | return; |
| 297 | } | 798 | } |
| 298 | 799 | ||
| 800 | gpio_unexport(gpio); | ||
| 801 | |||
| 299 | spin_lock_irqsave(&gpio_lock, flags); | 802 | spin_lock_irqsave(&gpio_lock, flags); |
| 300 | 803 | ||
| 301 | desc = &gpio_desc[gpio]; | 804 | desc = &gpio_desc[gpio]; |
| @@ -534,10 +1037,6 @@ EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); | |||
| 534 | 1037 | ||
| 535 | #ifdef CONFIG_DEBUG_FS | 1038 | #ifdef CONFIG_DEBUG_FS |
| 536 | 1039 | ||
| 537 | #include <linux/debugfs.h> | ||
| 538 | #include <linux/seq_file.h> | ||
| 539 | |||
| 540 | |||
| 541 | static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | 1040 | static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
| 542 | { | 1041 | { |
| 543 | unsigned i; | 1042 | unsigned i; |
| @@ -614,17 +1113,28 @@ static int gpiolib_show(struct seq_file *s, void *unused) | |||
| 614 | /* REVISIT this isn't locked against gpio_chip removal ... */ | 1113 | /* REVISIT this isn't locked against gpio_chip removal ... */ |
| 615 | 1114 | ||
| 616 | for (gpio = 0; gpio_is_valid(gpio); gpio++) { | 1115 | for (gpio = 0; gpio_is_valid(gpio); gpio++) { |
| 1116 | struct device *dev; | ||
| 1117 | |||
| 617 | if (chip == gpio_desc[gpio].chip) | 1118 | if (chip == gpio_desc[gpio].chip) |
| 618 | continue; | 1119 | continue; |
| 619 | chip = gpio_desc[gpio].chip; | 1120 | chip = gpio_desc[gpio].chip; |
| 620 | if (!chip) | 1121 | if (!chip) |
| 621 | continue; | 1122 | continue; |
| 622 | 1123 | ||
| 623 | seq_printf(s, "%sGPIOs %d-%d, %s%s:\n", | 1124 | seq_printf(s, "%sGPIOs %d-%d", |
| 624 | started ? "\n" : "", | 1125 | started ? "\n" : "", |
| 625 | chip->base, chip->base + chip->ngpio - 1, | 1126 | chip->base, chip->base + chip->ngpio - 1); |
| 626 | chip->label ? : "generic", | 1127 | dev = chip->dev; |
| 627 | chip->can_sleep ? ", can sleep" : ""); | 1128 | if (dev) |
| 1129 | seq_printf(s, ", %s/%s", | ||
| 1130 | dev->bus ? dev->bus->name : "no-bus", | ||
| 1131 | dev->bus_id); | ||
| 1132 | if (chip->label) | ||
| 1133 | seq_printf(s, ", %s", chip->label); | ||
| 1134 | if (chip->can_sleep) | ||
| 1135 | seq_printf(s, ", can sleep"); | ||
| 1136 | seq_printf(s, ":\n"); | ||
| 1137 | |||
| 628 | started = 1; | 1138 | started = 1; |
| 629 | if (chip->dbg_show) | 1139 | if (chip->dbg_show) |
| 630 | chip->dbg_show(s, chip); | 1140 | chip->dbg_show(s, chip); |
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c new file mode 100644 index 000000000000..b51c8135ca28 --- /dev/null +++ b/drivers/gpio/max732x.c | |||
| @@ -0,0 +1,385 @@ | |||
| 1 | /* | ||
| 2 | * max732x.c - I2C Port Expander with 8/16 I/O | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Marvell International Ltd. | ||
| 5 | * Copyright (C) 2008 Jack Ren <jack.ren@marvell.com> | ||
| 6 | * Copyright (C) 2008 Eric Miao <eric.miao@marvell.com> | ||
| 7 | * | ||
| 8 | * Derived from drivers/gpio/pca953x.c | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; version 2 of the License. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/string.h> | ||
| 19 | #include <linux/gpio.h> | ||
| 20 | |||
| 21 | #include <linux/i2c.h> | ||
| 22 | #include <linux/i2c/max732x.h> | ||
| 23 | |||
| 24 | |||
| 25 | /* | ||
| 26 | * Each port of MAX732x (including MAX7319) falls into one of the | ||
| 27 | * following three types: | ||
| 28 | * | ||
| 29 | * - Push Pull Output | ||
| 30 | * - Input | ||
| 31 | * - Open Drain I/O | ||
| 32 | * | ||
| 33 | * designated by 'O', 'I' and 'P' individually according to MAXIM's | ||
| 34 | * datasheets. | ||
| 35 | * | ||
| 36 | * There are two groups of I/O ports, each group usually includes | ||
| 37 | * up to 8 I/O ports, and is accessed by a specific I2C address: | ||
| 38 | * | ||
| 39 | * - Group A : by I2C address 0b'110xxxx | ||
| 40 | * - Group B : by I2C address 0b'101xxxx | ||
| 41 | * | ||
| 42 | * where 'xxxx' is decided by the connections of pin AD2/AD0. The | ||
| 43 | * address used also affects the initial state of output signals. | ||
| 44 | * | ||
| 45 | * Within each group of ports, there are five known combinations of | ||
| 46 | * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for | ||
| 47 | * the detailed organization of these ports. | ||
| 48 | * | ||
| 49 | * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16', | ||
| 50 | * and GPIOs from GROUP_A are numbered before those from GROUP_B | ||
| 51 | * (if there are two groups). | ||
| 52 | * | ||
| 53 | * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so | ||
| 54 | * they are not supported by this driver. | ||
| 55 | */ | ||
| 56 | |||
| 57 | #define PORT_NONE 0x0 /* '/' No Port */ | ||
| 58 | #define PORT_OUTPUT 0x1 /* 'O' Push-Pull, Output Only */ | ||
| 59 | #define PORT_INPUT 0x2 /* 'I' Input Only */ | ||
| 60 | #define PORT_OPENDRAIN 0x3 /* 'P' Open-Drain, I/O */ | ||
| 61 | |||
| 62 | #define IO_4I4O 0x5AA5 /* O7 O6 I5 I4 I3 I2 O1 O0 */ | ||
| 63 | #define IO_4P4O 0x5FF5 /* O7 O6 P5 P4 P3 P2 O1 O0 */ | ||
| 64 | #define IO_8I 0xAAAA /* I7 I6 I5 I4 I3 I2 I1 I0 */ | ||
| 65 | #define IO_8P 0xFFFF /* P7 P6 P5 P4 P3 P2 P1 P0 */ | ||
| 66 | #define IO_8O 0x5555 /* O7 O6 O5 O4 O3 O2 O1 O0 */ | ||
| 67 | |||
| 68 | #define GROUP_A(x) ((x) & 0xffff) /* I2C Addr: 0b'110xxxx */ | ||
| 69 | #define GROUP_B(x) ((x) << 16) /* I2C Addr: 0b'101xxxx */ | ||
| 70 | |||
| 71 | static const struct i2c_device_id max732x_id[] = { | ||
| 72 | { "max7319", GROUP_A(IO_8I) }, | ||
| 73 | { "max7320", GROUP_B(IO_8O) }, | ||
| 74 | { "max7321", GROUP_A(IO_8P) }, | ||
| 75 | { "max7322", GROUP_A(IO_4I4O) }, | ||
| 76 | { "max7323", GROUP_A(IO_4P4O) }, | ||
| 77 | { "max7324", GROUP_A(IO_8I) | GROUP_B(IO_8O) }, | ||
| 78 | { "max7325", GROUP_A(IO_8P) | GROUP_B(IO_8O) }, | ||
| 79 | { "max7326", GROUP_A(IO_4I4O) | GROUP_B(IO_8O) }, | ||
| 80 | { "max7327", GROUP_A(IO_4P4O) | GROUP_B(IO_8O) }, | ||
| 81 | { }, | ||
| 82 | }; | ||
| 83 | MODULE_DEVICE_TABLE(i2c, max732x_id); | ||
| 84 | |||
| 85 | struct max732x_chip { | ||
| 86 | struct gpio_chip gpio_chip; | ||
| 87 | |||
| 88 | struct i2c_client *client; /* "main" client */ | ||
| 89 | struct i2c_client *client_dummy; | ||
| 90 | struct i2c_client *client_group_a; | ||
| 91 | struct i2c_client *client_group_b; | ||
| 92 | |||
| 93 | unsigned int mask_group_a; | ||
| 94 | unsigned int dir_input; | ||
| 95 | unsigned int dir_output; | ||
| 96 | |||
| 97 | struct mutex lock; | ||
| 98 | uint8_t reg_out[2]; | ||
| 99 | }; | ||
| 100 | |||
| 101 | static int max732x_write(struct max732x_chip *chip, int group_a, uint8_t val) | ||
| 102 | { | ||
| 103 | struct i2c_client *client; | ||
| 104 | int ret; | ||
| 105 | |||
| 106 | client = group_a ? chip->client_group_a : chip->client_group_b; | ||
| 107 | ret = i2c_smbus_write_byte(client, val); | ||
| 108 | if (ret < 0) { | ||
| 109 | dev_err(&client->dev, "failed writing\n"); | ||
| 110 | return ret; | ||
| 111 | } | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int max732x_read(struct max732x_chip *chip, int group_a, uint8_t *val) | ||
| 117 | { | ||
| 118 | struct i2c_client *client; | ||
| 119 | int ret; | ||
| 120 | |||
| 121 | client = group_a ? chip->client_group_a : chip->client_group_b; | ||
| 122 | ret = i2c_smbus_read_byte(client); | ||
| 123 | if (ret < 0) { | ||
| 124 | dev_err(&client->dev, "failed reading\n"); | ||
| 125 | return ret; | ||
| 126 | } | ||
| 127 | |||
| 128 | *val = (uint8_t)ret; | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static inline int is_group_a(struct max732x_chip *chip, unsigned off) | ||
| 133 | { | ||
| 134 | return (1u << off) & chip->mask_group_a; | ||
| 135 | } | ||
| 136 | |||
| 137 | static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off) | ||
| 138 | { | ||
| 139 | struct max732x_chip *chip; | ||
| 140 | uint8_t reg_val; | ||
| 141 | int ret; | ||
| 142 | |||
| 143 | chip = container_of(gc, struct max732x_chip, gpio_chip); | ||
| 144 | |||
| 145 | ret = max732x_read(chip, is_group_a(chip, off), ®_val); | ||
| 146 | if (ret < 0) | ||
| 147 | return 0; | ||
| 148 | |||
| 149 | return reg_val & (1u << (off & 0x7)); | ||
| 150 | } | ||
| 151 | |||
| 152 | static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) | ||
| 153 | { | ||
| 154 | struct max732x_chip *chip; | ||
| 155 | uint8_t reg_out, mask = 1u << (off & 0x7); | ||
| 156 | int ret; | ||
| 157 | |||
| 158 | chip = container_of(gc, struct max732x_chip, gpio_chip); | ||
| 159 | |||
| 160 | mutex_lock(&chip->lock); | ||
| 161 | |||
| 162 | reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0]; | ||
| 163 | reg_out = (val) ? reg_out | mask : reg_out & ~mask; | ||
| 164 | |||
| 165 | ret = max732x_write(chip, is_group_a(chip, off), reg_out); | ||
| 166 | if (ret < 0) | ||
| 167 | goto out; | ||
| 168 | |||
| 169 | /* update the shadow register then */ | ||
| 170 | if (off > 7) | ||
| 171 | chip->reg_out[1] = reg_out; | ||
| 172 | else | ||
| 173 | chip->reg_out[0] = reg_out; | ||
| 174 | out: | ||
| 175 | mutex_unlock(&chip->lock); | ||
| 176 | } | ||
| 177 | |||
| 178 | static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off) | ||
| 179 | { | ||
| 180 | struct max732x_chip *chip; | ||
| 181 | unsigned int mask = 1u << off; | ||
| 182 | |||
| 183 | chip = container_of(gc, struct max732x_chip, gpio_chip); | ||
| 184 | |||
| 185 | if ((mask & chip->dir_input) == 0) { | ||
| 186 | dev_dbg(&chip->client->dev, "%s port %d is output only\n", | ||
| 187 | chip->client->name, off); | ||
| 188 | return -EACCES; | ||
| 189 | } | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static int max732x_gpio_direction_output(struct gpio_chip *gc, | ||
| 195 | unsigned off, int val) | ||
| 196 | { | ||
| 197 | struct max732x_chip *chip; | ||
| 198 | unsigned int mask = 1u << off; | ||
| 199 | |||
| 200 | chip = container_of(gc, struct max732x_chip, gpio_chip); | ||
| 201 | |||
| 202 | if ((mask & chip->dir_output) == 0) { | ||
| 203 | dev_dbg(&chip->client->dev, "%s port %d is input only\n", | ||
| 204 | chip->client->name, off); | ||
| 205 | return -EACCES; | ||
| 206 | } | ||
| 207 | |||
| 208 | max732x_gpio_set_value(gc, off, val); | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int __devinit max732x_setup_gpio(struct max732x_chip *chip, | ||
| 213 | const struct i2c_device_id *id, | ||
| 214 | unsigned gpio_start) | ||
| 215 | { | ||
| 216 | struct gpio_chip *gc = &chip->gpio_chip; | ||
| 217 | uint32_t id_data = id->driver_data; | ||
| 218 | int i, port = 0; | ||
| 219 | |||
| 220 | for (i = 0; i < 16; i++, id_data >>= 2) { | ||
| 221 | unsigned int mask = 1 << port; | ||
| 222 | |||
| 223 | switch (id_data & 0x3) { | ||
| 224 | case PORT_OUTPUT: | ||
| 225 | chip->dir_output |= mask; | ||
| 226 | break; | ||
| 227 | case PORT_INPUT: | ||
| 228 | chip->dir_input |= mask; | ||
| 229 | break; | ||
| 230 | case PORT_OPENDRAIN: | ||
| 231 | chip->dir_output |= mask; | ||
| 232 | chip->dir_input |= mask; | ||
| 233 | break; | ||
| 234 | default: | ||
| 235 | continue; | ||
| 236 | } | ||
| 237 | |||
| 238 | if (i < 8) | ||
| 239 | chip->mask_group_a |= mask; | ||
| 240 | port++; | ||
| 241 | } | ||
| 242 | |||
| 243 | if (chip->dir_input) | ||
| 244 | gc->direction_input = max732x_gpio_direction_input; | ||
| 245 | if (chip->dir_output) { | ||
| 246 | gc->direction_output = max732x_gpio_direction_output; | ||
| 247 | gc->set = max732x_gpio_set_value; | ||
| 248 | } | ||
| 249 | gc->get = max732x_gpio_get_value; | ||
| 250 | gc->can_sleep = 1; | ||
| 251 | |||
| 252 | gc->base = gpio_start; | ||
| 253 | gc->ngpio = port; | ||
| 254 | gc->label = chip->client->name; | ||
| 255 | gc->owner = THIS_MODULE; | ||
| 256 | |||
| 257 | return port; | ||
| 258 | } | ||
| 259 | |||
| 260 | static int __devinit max732x_probe(struct i2c_client *client, | ||
| 261 | const struct i2c_device_id *id) | ||
| 262 | { | ||
| 263 | struct max732x_platform_data *pdata; | ||
| 264 | struct max732x_chip *chip; | ||
| 265 | struct i2c_client *c; | ||
| 266 | uint16_t addr_a, addr_b; | ||
| 267 | int ret, nr_port; | ||
| 268 | |||
| 269 | pdata = client->dev.platform_data; | ||
| 270 | if (pdata == NULL) | ||
| 271 | return -ENODEV; | ||
| 272 | |||
| 273 | chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL); | ||
| 274 | if (chip == NULL) | ||
| 275 | return -ENOMEM; | ||
| 276 | chip->client = client; | ||
| 277 | |||
| 278 | nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base); | ||
| 279 | |||
| 280 | addr_a = (client->addr & 0x0f) | 0x60; | ||
| 281 | addr_b = (client->addr & 0x0f) | 0x50; | ||
| 282 | |||
| 283 | switch (client->addr & 0x70) { | ||
| 284 | case 0x60: | ||
| 285 | chip->client_group_a = client; | ||
| 286 | if (nr_port > 7) { | ||
| 287 | c = i2c_new_dummy(client->adapter, addr_b); | ||
| 288 | chip->client_group_b = chip->client_dummy = c; | ||
| 289 | } | ||
| 290 | break; | ||
| 291 | case 0x50: | ||
| 292 | chip->client_group_b = client; | ||
| 293 | if (nr_port > 7) { | ||
| 294 | c = i2c_new_dummy(client->adapter, addr_a); | ||
| 295 | chip->client_group_a = chip->client_dummy = c; | ||
| 296 | } | ||
| 297 | break; | ||
| 298 | default: | ||
| 299 | dev_err(&client->dev, "invalid I2C address specified %02x\n", | ||
| 300 | client->addr); | ||
| 301 | ret = -EINVAL; | ||
| 302 | goto out_failed; | ||
| 303 | } | ||
| 304 | |||
| 305 | mutex_init(&chip->lock); | ||
| 306 | |||
| 307 | max732x_read(chip, is_group_a(chip, 0), &chip->reg_out[0]); | ||
| 308 | if (nr_port > 7) | ||
| 309 | max732x_read(chip, is_group_a(chip, 8), &chip->reg_out[1]); | ||
| 310 | |||
| 311 | ret = gpiochip_add(&chip->gpio_chip); | ||
| 312 | if (ret) | ||
| 313 | goto out_failed; | ||
| 314 | |||
| 315 | if (pdata->setup) { | ||
| 316 | ret = pdata->setup(client, chip->gpio_chip.base, | ||
| 317 | chip->gpio_chip.ngpio, pdata->context); | ||
| 318 | if (ret < 0) | ||
| 319 | dev_warn(&client->dev, "setup failed, %d\n", ret); | ||
| 320 | } | ||
| 321 | |||
| 322 | i2c_set_clientdata(client, chip); | ||
| 323 | return 0; | ||
| 324 | |||
| 325 | out_failed: | ||
| 326 | kfree(chip); | ||
| 327 | return ret; | ||
| 328 | } | ||
| 329 | |||
| 330 | static int __devexit max732x_remove(struct i2c_client *client) | ||
| 331 | { | ||
| 332 | struct max732x_platform_data *pdata = client->dev.platform_data; | ||
| 333 | struct max732x_chip *chip = i2c_get_clientdata(client); | ||
| 334 | int ret; | ||
| 335 | |||
| 336 | if (pdata->teardown) { | ||
| 337 | ret = pdata->teardown(client, chip->gpio_chip.base, | ||
| 338 | chip->gpio_chip.ngpio, pdata->context); | ||
| 339 | if (ret < 0) { | ||
| 340 | dev_err(&client->dev, "%s failed, %d\n", | ||
| 341 | "teardown", ret); | ||
| 342 | return ret; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | ret = gpiochip_remove(&chip->gpio_chip); | ||
| 347 | if (ret) { | ||
| 348 | dev_err(&client->dev, "%s failed, %d\n", | ||
| 349 | "gpiochip_remove()", ret); | ||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 353 | /* unregister any dummy i2c_client */ | ||
| 354 | if (chip->client_dummy) | ||
| 355 | i2c_unregister_device(chip->client_dummy); | ||
| 356 | |||
| 357 | kfree(chip); | ||
| 358 | return 0; | ||
| 359 | } | ||
| 360 | |||
| 361 | static struct i2c_driver max732x_driver = { | ||
| 362 | .driver = { | ||
| 363 | .name = "max732x", | ||
| 364 | .owner = THIS_MODULE, | ||
| 365 | }, | ||
| 366 | .probe = max732x_probe, | ||
| 367 | .remove = __devexit_p(max732x_remove), | ||
| 368 | .id_table = max732x_id, | ||
| 369 | }; | ||
| 370 | |||
| 371 | static int __init max732x_init(void) | ||
| 372 | { | ||
| 373 | return i2c_add_driver(&max732x_driver); | ||
| 374 | } | ||
| 375 | module_init(max732x_init); | ||
| 376 | |||
| 377 | static void __exit max732x_exit(void) | ||
| 378 | { | ||
| 379 | i2c_del_driver(&max732x_driver); | ||
| 380 | } | ||
| 381 | module_exit(max732x_exit); | ||
| 382 | |||
| 383 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); | ||
| 384 | MODULE_DESCRIPTION("GPIO expander driver for MAX732X"); | ||
| 385 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c index 7f92fdd5f0e2..8a1b405fefda 100644 --- a/drivers/gpio/mcp23s08.c +++ b/drivers/gpio/mcp23s08.c | |||
| @@ -40,15 +40,26 @@ struct mcp23s08 { | |||
| 40 | struct spi_device *spi; | 40 | struct spi_device *spi; |
| 41 | u8 addr; | 41 | u8 addr; |
| 42 | 42 | ||
| 43 | u8 cache[11]; | ||
| 43 | /* lock protects the cached values */ | 44 | /* lock protects the cached values */ |
| 44 | struct mutex lock; | 45 | struct mutex lock; |
| 45 | u8 cache[11]; | ||
| 46 | 46 | ||
| 47 | struct gpio_chip chip; | 47 | struct gpio_chip chip; |
| 48 | 48 | ||
| 49 | struct work_struct work; | 49 | struct work_struct work; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | /* A given spi_device can represent up to four mcp23s08 chips | ||
| 53 | * sharing the same chipselect but using different addresses | ||
| 54 | * (e.g. chips #0 and #3 might be populated, but not #1 or $2). | ||
| 55 | * Driver data holds all the per-chip data. | ||
| 56 | */ | ||
| 57 | struct mcp23s08_driver_data { | ||
| 58 | unsigned ngpio; | ||
| 59 | struct mcp23s08 *mcp[4]; | ||
| 60 | struct mcp23s08 chip[]; | ||
| 61 | }; | ||
| 62 | |||
| 52 | static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) | 63 | static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) |
| 53 | { | 64 | { |
| 54 | u8 tx[2], rx[1]; | 65 | u8 tx[2], rx[1]; |
| @@ -208,25 +219,18 @@ done: | |||
| 208 | 219 | ||
| 209 | /*----------------------------------------------------------------------*/ | 220 | /*----------------------------------------------------------------------*/ |
| 210 | 221 | ||
| 211 | static int mcp23s08_probe(struct spi_device *spi) | 222 | static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, |
| 223 | unsigned base, unsigned pullups) | ||
| 212 | { | 224 | { |
| 213 | struct mcp23s08 *mcp; | 225 | struct mcp23s08_driver_data *data = spi_get_drvdata(spi); |
| 214 | struct mcp23s08_platform_data *pdata; | 226 | struct mcp23s08 *mcp = data->mcp[addr]; |
| 215 | int status; | 227 | int status; |
| 216 | int do_update = 0; | 228 | int do_update = 0; |
| 217 | 229 | ||
| 218 | pdata = spi->dev.platform_data; | ||
| 219 | if (!pdata || pdata->slave > 3 || !pdata->base) | ||
| 220 | return -ENODEV; | ||
| 221 | |||
| 222 | mcp = kzalloc(sizeof *mcp, GFP_KERNEL); | ||
| 223 | if (!mcp) | ||
| 224 | return -ENOMEM; | ||
| 225 | |||
| 226 | mutex_init(&mcp->lock); | 230 | mutex_init(&mcp->lock); |
| 227 | 231 | ||
| 228 | mcp->spi = spi; | 232 | mcp->spi = spi; |
| 229 | mcp->addr = 0x40 | (pdata->slave << 1); | 233 | mcp->addr = 0x40 | (addr << 1); |
| 230 | 234 | ||
| 231 | mcp->chip.label = "mcp23s08", | 235 | mcp->chip.label = "mcp23s08", |
| 232 | 236 | ||
| @@ -236,26 +240,28 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
| 236 | mcp->chip.set = mcp23s08_set; | 240 | mcp->chip.set = mcp23s08_set; |
| 237 | mcp->chip.dbg_show = mcp23s08_dbg_show; | 241 | mcp->chip.dbg_show = mcp23s08_dbg_show; |
| 238 | 242 | ||
| 239 | mcp->chip.base = pdata->base; | 243 | mcp->chip.base = base; |
| 240 | mcp->chip.ngpio = 8; | 244 | mcp->chip.ngpio = 8; |
| 241 | mcp->chip.can_sleep = 1; | 245 | mcp->chip.can_sleep = 1; |
| 246 | mcp->chip.dev = &spi->dev; | ||
| 242 | mcp->chip.owner = THIS_MODULE; | 247 | mcp->chip.owner = THIS_MODULE; |
| 243 | 248 | ||
| 244 | spi_set_drvdata(spi, mcp); | 249 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, |
| 245 | 250 | * and MCP_IOCON.HAEN = 1, so we work with all chips. | |
| 246 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work */ | 251 | */ |
| 247 | status = mcp23s08_read(mcp, MCP_IOCON); | 252 | status = mcp23s08_read(mcp, MCP_IOCON); |
| 248 | if (status < 0) | 253 | if (status < 0) |
| 249 | goto fail; | 254 | goto fail; |
| 250 | if (status & IOCON_SEQOP) { | 255 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) { |
| 251 | status &= ~IOCON_SEQOP; | 256 | status &= ~IOCON_SEQOP; |
| 257 | status |= IOCON_HAEN; | ||
| 252 | status = mcp23s08_write(mcp, MCP_IOCON, (u8) status); | 258 | status = mcp23s08_write(mcp, MCP_IOCON, (u8) status); |
| 253 | if (status < 0) | 259 | if (status < 0) |
| 254 | goto fail; | 260 | goto fail; |
| 255 | } | 261 | } |
| 256 | 262 | ||
| 257 | /* configure ~100K pullups */ | 263 | /* configure ~100K pullups */ |
| 258 | status = mcp23s08_write(mcp, MCP_GPPU, pdata->pullups); | 264 | status = mcp23s08_write(mcp, MCP_GPPU, pullups); |
| 259 | if (status < 0) | 265 | if (status < 0) |
| 260 | goto fail; | 266 | goto fail; |
| 261 | 267 | ||
| @@ -282,11 +288,58 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
| 282 | tx[1] = MCP_IPOL; | 288 | tx[1] = MCP_IPOL; |
| 283 | memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2); | 289 | memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2); |
| 284 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); | 290 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); |
| 285 | 291 | if (status < 0) | |
| 286 | /* FIXME check status... */ | 292 | goto fail; |
| 287 | } | 293 | } |
| 288 | 294 | ||
| 289 | status = gpiochip_add(&mcp->chip); | 295 | status = gpiochip_add(&mcp->chip); |
| 296 | fail: | ||
| 297 | if (status < 0) | ||
| 298 | dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n", | ||
| 299 | addr, status); | ||
| 300 | return status; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int mcp23s08_probe(struct spi_device *spi) | ||
| 304 | { | ||
| 305 | struct mcp23s08_platform_data *pdata; | ||
| 306 | unsigned addr; | ||
| 307 | unsigned chips = 0; | ||
| 308 | struct mcp23s08_driver_data *data; | ||
| 309 | int status; | ||
| 310 | unsigned base; | ||
| 311 | |||
| 312 | pdata = spi->dev.platform_data; | ||
| 313 | if (!pdata || !gpio_is_valid(pdata->base)) | ||
| 314 | return -ENODEV; | ||
| 315 | |||
| 316 | for (addr = 0; addr < 4; addr++) { | ||
| 317 | if (!pdata->chip[addr].is_present) | ||
| 318 | continue; | ||
| 319 | chips++; | ||
| 320 | } | ||
| 321 | if (!chips) | ||
| 322 | return -ENODEV; | ||
| 323 | |||
| 324 | data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08), | ||
| 325 | GFP_KERNEL); | ||
| 326 | if (!data) | ||
| 327 | return -ENOMEM; | ||
| 328 | spi_set_drvdata(spi, data); | ||
| 329 | |||
| 330 | base = pdata->base; | ||
| 331 | for (addr = 0; addr < 4; addr++) { | ||
| 332 | if (!pdata->chip[addr].is_present) | ||
| 333 | continue; | ||
| 334 | chips--; | ||
| 335 | data->mcp[addr] = &data->chip[chips]; | ||
| 336 | status = mcp23s08_probe_one(spi, addr, base, | ||
| 337 | pdata->chip[addr].pullups); | ||
| 338 | if (status < 0) | ||
| 339 | goto fail; | ||
| 340 | base += 8; | ||
| 341 | } | ||
| 342 | data->ngpio = base - pdata->base; | ||
| 290 | 343 | ||
| 291 | /* NOTE: these chips have a relatively sane IRQ framework, with | 344 | /* NOTE: these chips have a relatively sane IRQ framework, with |
| 292 | * per-signal masking and level/edge triggering. It's not yet | 345 | * per-signal masking and level/edge triggering. It's not yet |
| @@ -294,8 +347,9 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
| 294 | */ | 347 | */ |
| 295 | 348 | ||
| 296 | if (pdata->setup) { | 349 | if (pdata->setup) { |
| 297 | status = pdata->setup(spi, mcp->chip.base, | 350 | status = pdata->setup(spi, |
| 298 | mcp->chip.ngpio, pdata->context); | 351 | pdata->base, data->ngpio, |
| 352 | pdata->context); | ||
| 299 | if (status < 0) | 353 | if (status < 0) |
| 300 | dev_dbg(&spi->dev, "setup --> %d\n", status); | 354 | dev_dbg(&spi->dev, "setup --> %d\n", status); |
| 301 | } | 355 | } |
| @@ -303,19 +357,29 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
| 303 | return 0; | 357 | return 0; |
| 304 | 358 | ||
| 305 | fail: | 359 | fail: |
| 306 | kfree(mcp); | 360 | for (addr = 0; addr < 4; addr++) { |
| 361 | int tmp; | ||
| 362 | |||
| 363 | if (!data->mcp[addr]) | ||
| 364 | continue; | ||
| 365 | tmp = gpiochip_remove(&data->mcp[addr]->chip); | ||
| 366 | if (tmp < 0) | ||
| 367 | dev_err(&spi->dev, "%s --> %d\n", "remove", tmp); | ||
| 368 | } | ||
| 369 | kfree(data); | ||
| 307 | return status; | 370 | return status; |
| 308 | } | 371 | } |
| 309 | 372 | ||
| 310 | static int mcp23s08_remove(struct spi_device *spi) | 373 | static int mcp23s08_remove(struct spi_device *spi) |
| 311 | { | 374 | { |
| 312 | struct mcp23s08 *mcp = spi_get_drvdata(spi); | 375 | struct mcp23s08_driver_data *data = spi_get_drvdata(spi); |
| 313 | struct mcp23s08_platform_data *pdata = spi->dev.platform_data; | 376 | struct mcp23s08_platform_data *pdata = spi->dev.platform_data; |
| 377 | unsigned addr; | ||
| 314 | int status = 0; | 378 | int status = 0; |
| 315 | 379 | ||
| 316 | if (pdata->teardown) { | 380 | if (pdata->teardown) { |
| 317 | status = pdata->teardown(spi, | 381 | status = pdata->teardown(spi, |
| 318 | mcp->chip.base, mcp->chip.ngpio, | 382 | pdata->base, data->ngpio, |
| 319 | pdata->context); | 383 | pdata->context); |
| 320 | if (status < 0) { | 384 | if (status < 0) { |
| 321 | dev_err(&spi->dev, "%s --> %d\n", "teardown", status); | 385 | dev_err(&spi->dev, "%s --> %d\n", "teardown", status); |
| @@ -323,11 +387,20 @@ static int mcp23s08_remove(struct spi_device *spi) | |||
| 323 | } | 387 | } |
| 324 | } | 388 | } |
| 325 | 389 | ||
| 326 | status = gpiochip_remove(&mcp->chip); | 390 | for (addr = 0; addr < 4; addr++) { |
| 391 | int tmp; | ||
| 392 | |||
| 393 | if (!data->mcp[addr]) | ||
| 394 | continue; | ||
| 395 | |||
| 396 | tmp = gpiochip_remove(&data->mcp[addr]->chip); | ||
| 397 | if (tmp < 0) { | ||
| 398 | dev_err(&spi->dev, "%s --> %d\n", "remove", tmp); | ||
| 399 | status = tmp; | ||
| 400 | } | ||
| 401 | } | ||
| 327 | if (status == 0) | 402 | if (status == 0) |
| 328 | kfree(mcp); | 403 | kfree(data); |
| 329 | else | ||
| 330 | dev_err(&spi->dev, "%s --> %d\n", "remove", status); | ||
| 331 | return status; | 404 | return status; |
| 332 | } | 405 | } |
| 333 | 406 | ||
| @@ -355,4 +428,3 @@ static void __exit mcp23s08_exit(void) | |||
| 355 | module_exit(mcp23s08_exit); | 428 | module_exit(mcp23s08_exit); |
| 356 | 429 | ||
| 357 | MODULE_LICENSE("GPL"); | 430 | MODULE_LICENSE("GPL"); |
| 358 | |||
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index a380730b61ab..cc8468692ae0 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
| @@ -188,6 +188,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | |||
| 188 | gc->base = chip->gpio_start; | 188 | gc->base = chip->gpio_start; |
| 189 | gc->ngpio = gpios; | 189 | gc->ngpio = gpios; |
| 190 | gc->label = chip->client->name; | 190 | gc->label = chip->client->name; |
| 191 | gc->dev = &chip->client->dev; | ||
| 191 | gc->owner = THIS_MODULE; | 192 | gc->owner = THIS_MODULE; |
| 192 | } | 193 | } |
| 193 | 194 | ||
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index d25d356c4f20..fc9c6ae739ee 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c | |||
| @@ -200,6 +200,7 @@ static int pcf857x_probe(struct i2c_client *client, | |||
| 200 | 200 | ||
| 201 | gpio->chip.base = pdata->gpio_base; | 201 | gpio->chip.base = pdata->gpio_base; |
| 202 | gpio->chip.can_sleep = 1; | 202 | gpio->chip.can_sleep = 1; |
| 203 | gpio->chip.dev = &client->dev; | ||
| 203 | gpio->chip.owner = THIS_MODULE; | 204 | gpio->chip.owner = THIS_MODULE; |
| 204 | 205 | ||
| 205 | /* NOTE: the OnSemi jlc1562b is also largely compatible with | 206 | /* NOTE: the OnSemi jlc1562b is also largely compatible with |
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 50e0a4653741..a95cb9465d65 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig | |||
| @@ -126,7 +126,7 @@ config ISP1301_OMAP | |||
| 126 | 126 | ||
| 127 | config TPS65010 | 127 | config TPS65010 |
| 128 | tristate "TPS6501x Power Management chips" | 128 | tristate "TPS6501x Power Management chips" |
| 129 | depends on HAVE_GPIO_LIB | 129 | depends on GPIOLIB |
| 130 | default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK | 130 | default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK |
| 131 | help | 131 | help |
| 132 | If you say yes here you get support for the TPS6501x series of | 132 | If you say yes here you get support for the TPS6501x series of |
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 85949685191b..cf02e8fceb42 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c | |||
| @@ -636,6 +636,8 @@ static int tps65010_probe(struct i2c_client *client, | |||
| 636 | tps->outmask = board->outmask; | 636 | tps->outmask = board->outmask; |
| 637 | 637 | ||
| 638 | tps->chip.label = client->name; | 638 | tps->chip.label = client->name; |
| 639 | tps->chip.dev = &client->dev; | ||
| 640 | tps->chip.owner = THIS_MODULE; | ||
| 639 | 641 | ||
| 640 | tps->chip.set = tps65010_gpio_set; | 642 | tps->chip.set = tps65010_gpio_set; |
| 641 | tps->chip.direction_output = tps65010_output; | 643 | tps->chip.direction_output = tps65010_output; |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index aad664d5259f..0d395979b2d1 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
| @@ -70,7 +70,6 @@ | |||
| 70 | #include <linux/semaphore.h> | 70 | #include <linux/semaphore.h> |
| 71 | #include <linux/slab.h> | 71 | #include <linux/slab.h> |
| 72 | #include <linux/hil.h> | 72 | #include <linux/hil.h> |
| 73 | #include <linux/semaphore.h> | ||
| 74 | #include <asm/io.h> | 73 | #include <asm/io.h> |
| 75 | #include <asm/system.h> | 74 | #include <asm/system.h> |
| 76 | 75 | ||
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h index 2044e7173ab4..cff7a6354334 100644 --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h | |||
| @@ -220,7 +220,7 @@ enum { | |||
| 220 | #define ERR(format, arg...) \ | 220 | #define ERR(format, arg...) \ |
| 221 | printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) | 221 | printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) |
| 222 | 222 | ||
| 223 | #define WARN(format, arg...) \ | 223 | #define WARNING(format, arg...) \ |
| 224 | printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) | 224 | printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) |
| 225 | 225 | ||
| 226 | #define INFO(format, arg...) \ | 226 | #define INFO(format, arg...) \ |
| @@ -412,7 +412,7 @@ struct st5481_adapter { | |||
| 412 | ({ \ | 412 | ({ \ |
| 413 | int status; \ | 413 | int status; \ |
| 414 | if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \ | 414 | if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \ |
| 415 | WARN("usb_submit_urb failed,status=%d", status); \ | 415 | WARNING("usb_submit_urb failed,status=%d", status); \ |
| 416 | } \ | 416 | } \ |
| 417 | status; \ | 417 | status; \ |
| 418 | }) | 418 | }) |
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index fa64115cd7c7..0074b600a0ef 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c | |||
| @@ -180,7 +180,7 @@ static void usb_b_out_complete(struct urb *urb) | |||
| 180 | DBG(4,"urb killed status %d", urb->status); | 180 | DBG(4,"urb killed status %d", urb->status); |
| 181 | return; // Give up | 181 | return; // Give up |
| 182 | default: | 182 | default: |
| 183 | WARN("urb status %d",urb->status); | 183 | WARNING("urb status %d",urb->status); |
| 184 | if (b_out->busy == 0) { | 184 | if (b_out->busy == 0) { |
| 185 | st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); | 185 | st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); |
| 186 | } | 186 | } |
| @@ -372,6 +372,6 @@ void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg) | |||
| 372 | B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL); | 372 | B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL); |
| 373 | break; | 373 | break; |
| 374 | default: | 374 | default: |
| 375 | WARN("pr %#x\n", pr); | 375 | WARNING("pr %#x\n", pr); |
| 376 | } | 376 | } |
| 377 | } | 377 | } |
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index b8c4855cc889..077991c1cd05 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c | |||
| @@ -389,7 +389,7 @@ static void usb_d_out_complete(struct urb *urb) | |||
| 389 | DBG(1,"urb killed status %d", urb->status); | 389 | DBG(1,"urb killed status %d", urb->status); |
| 390 | break; | 390 | break; |
| 391 | default: | 391 | default: |
| 392 | WARN("urb status %d",urb->status); | 392 | WARNING("urb status %d",urb->status); |
| 393 | if (d_out->busy == 0) { | 393 | if (d_out->busy == 0) { |
| 394 | st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); | 394 | st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); |
| 395 | } | 395 | } |
| @@ -420,7 +420,7 @@ static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg) | |||
| 420 | isdnhdlc_out_init(&d_out->hdlc_state, 1, 0); | 420 | isdnhdlc_out_init(&d_out->hdlc_state, 1, 0); |
| 421 | 421 | ||
| 422 | if (test_and_set_bit(buf_nr, &d_out->busy)) { | 422 | if (test_and_set_bit(buf_nr, &d_out->busy)) { |
| 423 | WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy); | 423 | WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy); |
| 424 | return; | 424 | return; |
| 425 | } | 425 | } |
| 426 | urb = d_out->urb[buf_nr]; | 426 | urb = d_out->urb[buf_nr]; |
| @@ -601,7 +601,7 @@ void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) | |||
| 601 | FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL); | 601 | FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL); |
| 602 | break; | 602 | break; |
| 603 | default: | 603 | default: |
| 604 | WARN("pr %#x\n", pr); | 604 | WARNING("pr %#x\n", pr); |
| 605 | break; | 605 | break; |
| 606 | } | 606 | } |
| 607 | } | 607 | } |
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index 427a8b0520f5..ec3c0e507669 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c | |||
| @@ -66,7 +66,7 @@ static void usb_ctrl_msg(struct st5481_adapter *adapter, | |||
| 66 | struct ctrl_msg *ctrl_msg; | 66 | struct ctrl_msg *ctrl_msg; |
| 67 | 67 | ||
| 68 | if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) { | 68 | if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) { |
| 69 | WARN("control msg FIFO full"); | 69 | WARNING("control msg FIFO full"); |
| 70 | return; | 70 | return; |
| 71 | } | 71 | } |
| 72 | ctrl_msg = &ctrl->msg_fifo.data[w_index]; | 72 | ctrl_msg = &ctrl->msg_fifo.data[w_index]; |
| @@ -139,7 +139,7 @@ static void usb_ctrl_complete(struct urb *urb) | |||
| 139 | DBG(1,"urb killed status %d", urb->status); | 139 | DBG(1,"urb killed status %d", urb->status); |
| 140 | return; // Give up | 140 | return; // Give up |
| 141 | default: | 141 | default: |
| 142 | WARN("urb status %d",urb->status); | 142 | WARNING("urb status %d",urb->status); |
| 143 | break; | 143 | break; |
| 144 | } | 144 | } |
| 145 | } | 145 | } |
| @@ -198,7 +198,7 @@ static void usb_int_complete(struct urb *urb) | |||
| 198 | DBG(2, "urb shutting down with status: %d", urb->status); | 198 | DBG(2, "urb shutting down with status: %d", urb->status); |
| 199 | return; | 199 | return; |
| 200 | default: | 200 | default: |
| 201 | WARN("nonzero urb status received: %d", urb->status); | 201 | WARNING("nonzero urb status received: %d", urb->status); |
| 202 | goto exit; | 202 | goto exit; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| @@ -235,7 +235,7 @@ static void usb_int_complete(struct urb *urb) | |||
| 235 | exit: | 235 | exit: |
| 236 | status = usb_submit_urb (urb, GFP_ATOMIC); | 236 | status = usb_submit_urb (urb, GFP_ATOMIC); |
| 237 | if (status) | 237 | if (status) |
| 238 | WARN("usb_submit_urb failed with result %d", status); | 238 | WARNING("usb_submit_urb failed with result %d", status); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | /* ====================================================================== | 241 | /* ====================================================================== |
| @@ -257,7 +257,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
| 257 | DBG(2,""); | 257 | DBG(2,""); |
| 258 | 258 | ||
| 259 | if ((status = usb_reset_configuration (dev)) < 0) { | 259 | if ((status = usb_reset_configuration (dev)) < 0) { |
| 260 | WARN("reset_configuration failed,status=%d",status); | 260 | WARNING("reset_configuration failed,status=%d",status); |
| 261 | return status; | 261 | return status; |
| 262 | } | 262 | } |
| 263 | 263 | ||
| @@ -269,7 +269,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
| 269 | 269 | ||
| 270 | // Check if the config is sane | 270 | // Check if the config is sane |
| 271 | if ( altsetting->desc.bNumEndpoints != 7 ) { | 271 | if ( altsetting->desc.bNumEndpoints != 7 ) { |
| 272 | WARN("expecting 7 got %d endpoints!", altsetting->desc.bNumEndpoints); | 272 | WARNING("expecting 7 got %d endpoints!", altsetting->desc.bNumEndpoints); |
| 273 | return -EINVAL; | 273 | return -EINVAL; |
| 274 | } | 274 | } |
| 275 | 275 | ||
| @@ -279,7 +279,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
| 279 | 279 | ||
| 280 | // Use alternative setting 3 on interface 0 to have 2B+D | 280 | // Use alternative setting 3 on interface 0 to have 2B+D |
| 281 | if ((status = usb_set_interface (dev, 0, 3)) < 0) { | 281 | if ((status = usb_set_interface (dev, 0, 3)) < 0) { |
| 282 | WARN("usb_set_interface failed,status=%d",status); | 282 | WARNING("usb_set_interface failed,status=%d",status); |
| 283 | return status; | 283 | return status; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| @@ -497,7 +497,7 @@ static void usb_in_complete(struct urb *urb) | |||
| 497 | DBG(1,"urb killed status %d", urb->status); | 497 | DBG(1,"urb killed status %d", urb->status); |
| 498 | return; // Give up | 498 | return; // Give up |
| 499 | default: | 499 | default: |
| 500 | WARN("urb status %d",urb->status); | 500 | WARNING("urb status %d",urb->status); |
| 501 | break; | 501 | break; |
| 502 | } | 502 | } |
| 503 | } | 503 | } |
| @@ -523,7 +523,7 @@ static void usb_in_complete(struct urb *urb) | |||
| 523 | DBG(4,"count=%d",status); | 523 | DBG(4,"count=%d",status); |
| 524 | DBG_PACKET(0x400, in->rcvbuf, status); | 524 | DBG_PACKET(0x400, in->rcvbuf, status); |
| 525 | if (!(skb = dev_alloc_skb(status))) { | 525 | if (!(skb = dev_alloc_skb(status))) { |
| 526 | WARN("receive out of memory\n"); | 526 | WARNING("receive out of memory\n"); |
| 527 | break; | 527 | break; |
| 528 | } | 528 | } |
| 529 | memcpy(skb_put(skb, status), in->rcvbuf, status); | 529 | memcpy(skb_put(skb, status), in->rcvbuf, status); |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 1a8de57289eb..37344aaee22f 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
| @@ -98,16 +98,20 @@ static u32 lg_get_features(struct virtio_device *vdev) | |||
| 98 | return features; | 98 | return features; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | static void lg_set_features(struct virtio_device *vdev, u32 features) | 101 | static void lg_finalize_features(struct virtio_device *vdev) |
| 102 | { | 102 | { |
| 103 | unsigned int i; | 103 | unsigned int i, bits; |
| 104 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; | 104 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; |
| 105 | /* Second half of bitmap is features we accept. */ | 105 | /* Second half of bitmap is features we accept. */ |
| 106 | u8 *out_features = lg_features(desc) + desc->feature_len; | 106 | u8 *out_features = lg_features(desc) + desc->feature_len; |
| 107 | 107 | ||
| 108 | /* Give virtio_ring a chance to accept features. */ | ||
| 109 | vring_transport_features(vdev); | ||
| 110 | |||
| 108 | memset(out_features, 0, desc->feature_len); | 111 | memset(out_features, 0, desc->feature_len); |
| 109 | for (i = 0; i < min(desc->feature_len * 8, 32); i++) { | 112 | bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; |
| 110 | if (features & (1 << i)) | 113 | for (i = 0; i < bits; i++) { |
| 114 | if (test_bit(i, vdev->features)) | ||
| 111 | out_features[i / 8] |= (1 << (i % 8)); | 115 | out_features[i / 8] |= (1 << (i % 8)); |
| 112 | } | 116 | } |
| 113 | } | 117 | } |
| @@ -297,7 +301,7 @@ static void lg_del_vq(struct virtqueue *vq) | |||
| 297 | /* The ops structure which hooks everything together. */ | 301 | /* The ops structure which hooks everything together. */ |
| 298 | static struct virtio_config_ops lguest_config_ops = { | 302 | static struct virtio_config_ops lguest_config_ops = { |
| 299 | .get_features = lg_get_features, | 303 | .get_features = lg_get_features, |
| 300 | .set_features = lg_set_features, | 304 | .finalize_features = lg_finalize_features, |
| 301 | .get = lg_get, | 305 | .get = lg_get, |
| 302 | .set = lg_set, | 306 | .set = lg_set, |
| 303 | .get_status = lg_get_status, | 307 | .get_status = lg_get_status, |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9f93c29fed35..1f57a99fd968 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
| @@ -19,6 +19,14 @@ config MFD_SM501 | |||
| 19 | interface. The device may be connected by PCI or local bus with | 19 | interface. The device may be connected by PCI or local bus with |
| 20 | varying functions enabled. | 20 | varying functions enabled. |
| 21 | 21 | ||
| 22 | config MFD_SM501_GPIO | ||
| 23 | bool "Export GPIO via GPIO layer" | ||
| 24 | depends on MFD_SM501 && HAVE_GPIO_LIB | ||
| 25 | ---help--- | ||
| 26 | This option uses the gpio library layer to export the 64 GPIO | ||
| 27 | lines on the SM501. The platform data is used to supply the | ||
| 28 | base number for the first GPIO line to register. | ||
| 29 | |||
| 22 | config MFD_ASIC3 | 30 | config MFD_ASIC3 |
| 23 | bool "Support for Compaq ASIC3" | 31 | bool "Support for Compaq ASIC3" |
| 24 | depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM | 32 | depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM |
| @@ -28,7 +36,7 @@ config MFD_ASIC3 | |||
| 28 | 36 | ||
| 29 | config HTC_EGPIO | 37 | config HTC_EGPIO |
| 30 | bool "HTC EGPIO support" | 38 | bool "HTC EGPIO support" |
| 31 | depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM | 39 | depends on GENERIC_HARDIRQS && GPIOLIB && ARM |
| 32 | help | 40 | help |
| 33 | This driver supports the CPLD egpio chip present on | 41 | This driver supports the CPLD egpio chip present on |
| 34 | several HTC phones. It provides basic support for input | 42 | several HTC phones. It provides basic support for input |
| @@ -44,7 +52,7 @@ config HTC_PASIC3 | |||
| 44 | 52 | ||
| 45 | config MFD_TC6393XB | 53 | config MFD_TC6393XB |
| 46 | bool "Support Toshiba TC6393XB" | 54 | bool "Support Toshiba TC6393XB" |
| 47 | depends on HAVE_GPIO_LIB | 55 | depends on GPIOLIB |
| 48 | select MFD_CORE | 56 | select MFD_CORE |
| 49 | help | 57 | help |
| 50 | Support for Toshiba Mobile IO Controller TC6393XB | 58 | Support for Toshiba Mobile IO Controller TC6393XB |
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index 8872cc077519..6be43172dc65 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c | |||
| @@ -318,6 +318,8 @@ static int __init egpio_probe(struct platform_device *pdev) | |||
| 318 | ei->chip[i].dev = &(pdev->dev); | 318 | ei->chip[i].dev = &(pdev->dev); |
| 319 | chip = &(ei->chip[i].chip); | 319 | chip = &(ei->chip[i].chip); |
| 320 | chip->label = "htc-egpio"; | 320 | chip->label = "htc-egpio"; |
| 321 | chip->dev = &pdev->dev; | ||
| 322 | chip->owner = THIS_MODULE; | ||
| 321 | chip->get = egpio_get; | 323 | chip->get = egpio_get; |
| 322 | chip->set = egpio_set; | 324 | chip->set = egpio_set; |
| 323 | chip->direction_input = egpio_direction_input; | 325 | chip->direction_input = egpio_direction_input; |
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 633cbba072f0..91b294dcc133 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c | |||
| @@ -238,6 +238,8 @@ static int pasic3_remove(struct platform_device *pdev) | |||
| 238 | return 0; | 238 | return 0; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | MODULE_ALIAS("platform:pasic3"); | ||
| 242 | |||
| 241 | static struct platform_driver pasic3_driver = { | 243 | static struct platform_driver pasic3_driver = { |
| 242 | .driver = { | 244 | .driver = { |
| 243 | .name = "pasic3", | 245 | .name = "pasic3", |
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 1eab7cffceaa..b5272b5ce3fa 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c | |||
| @@ -242,6 +242,8 @@ static int mcp_sa11x0_resume(struct platform_device *dev) | |||
| 242 | /* | 242 | /* |
| 243 | * The driver for the SA11x0 MCP port. | 243 | * The driver for the SA11x0 MCP port. |
| 244 | */ | 244 | */ |
| 245 | MODULE_ALIAS("platform:sa11x0-mcp"); | ||
| 246 | |||
| 245 | static struct platform_driver mcp_sa11x0_driver = { | 247 | static struct platform_driver mcp_sa11x0_driver = { |
| 246 | .probe = mcp_sa11x0_probe, | 248 | .probe = mcp_sa11x0_probe, |
| 247 | .remove = mcp_sa11x0_remove, | 249 | .remove = mcp_sa11x0_remove, |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index d7d88ce053a6..0454be4266c1 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
| @@ -36,7 +36,7 @@ static int mfd_add_device(struct platform_device *parent, | |||
| 36 | if (ret) | 36 | if (ret) |
| 37 | goto fail_device; | 37 | goto fail_device; |
| 38 | 38 | ||
| 39 | memzero(res, sizeof(res)); | 39 | memset(res, 0, sizeof(res)); |
| 40 | for (r = 0; r < cell->num_resources; r++) { | 40 | for (r = 0; r < cell->num_resources; r++) { |
| 41 | res[r].name = cell->resources[r].name; | 41 | res[r].name = cell->resources[r].name; |
| 42 | res[r].flags = cell->resources[r].flags; | 42 | res[r].flags = cell->resources[r].flags; |
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 2fe64734d8af..7aebad4c06ff 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
| 20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
| 22 | #include <linux/i2c-gpio.h> | ||
| 22 | 23 | ||
| 23 | #include <linux/sm501.h> | 24 | #include <linux/sm501.h> |
| 24 | #include <linux/sm501-regs.h> | 25 | #include <linux/sm501-regs.h> |
| @@ -31,10 +32,37 @@ struct sm501_device { | |||
| 31 | struct platform_device pdev; | 32 | struct platform_device pdev; |
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| 35 | struct sm501_gpio; | ||
| 36 | |||
| 37 | #ifdef CONFIG_MFD_SM501_GPIO | ||
| 38 | #include <linux/gpio.h> | ||
| 39 | |||
| 40 | struct sm501_gpio_chip { | ||
| 41 | struct gpio_chip gpio; | ||
| 42 | struct sm501_gpio *ourgpio; /* to get back to parent. */ | ||
| 43 | void __iomem *regbase; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct sm501_gpio { | ||
| 47 | struct sm501_gpio_chip low; | ||
| 48 | struct sm501_gpio_chip high; | ||
| 49 | spinlock_t lock; | ||
| 50 | |||
| 51 | unsigned int registered : 1; | ||
| 52 | void __iomem *regs; | ||
| 53 | struct resource *regs_res; | ||
| 54 | }; | ||
| 55 | #else | ||
| 56 | struct sm501_gpio { | ||
| 57 | /* no gpio support, empty definition for sm501_devdata. */ | ||
| 58 | }; | ||
| 59 | #endif | ||
| 60 | |||
| 34 | struct sm501_devdata { | 61 | struct sm501_devdata { |
| 35 | spinlock_t reg_lock; | 62 | spinlock_t reg_lock; |
| 36 | struct mutex clock_lock; | 63 | struct mutex clock_lock; |
| 37 | struct list_head devices; | 64 | struct list_head devices; |
| 65 | struct sm501_gpio gpio; | ||
| 38 | 66 | ||
| 39 | struct device *dev; | 67 | struct device *dev; |
| 40 | struct resource *io_res; | 68 | struct resource *io_res; |
| @@ -42,6 +70,7 @@ struct sm501_devdata { | |||
| 42 | struct resource *regs_claim; | 70 | struct resource *regs_claim; |
| 43 | struct sm501_platdata *platdata; | 71 | struct sm501_platdata *platdata; |
| 44 | 72 | ||
| 73 | |||
| 45 | unsigned int in_suspend; | 74 | unsigned int in_suspend; |
| 46 | unsigned long pm_misc; | 75 | unsigned long pm_misc; |
| 47 | 76 | ||
| @@ -52,6 +81,7 @@ struct sm501_devdata { | |||
| 52 | unsigned int rev; | 81 | unsigned int rev; |
| 53 | }; | 82 | }; |
| 54 | 83 | ||
| 84 | |||
| 55 | #define MHZ (1000 * 1000) | 85 | #define MHZ (1000 * 1000) |
| 56 | 86 | ||
| 57 | #ifdef DEBUG | 87 | #ifdef DEBUG |
| @@ -276,58 +306,6 @@ unsigned long sm501_modify_reg(struct device *dev, | |||
| 276 | 306 | ||
| 277 | EXPORT_SYMBOL_GPL(sm501_modify_reg); | 307 | EXPORT_SYMBOL_GPL(sm501_modify_reg); |
| 278 | 308 | ||
| 279 | unsigned long sm501_gpio_get(struct device *dev, | ||
| 280 | unsigned long gpio) | ||
| 281 | { | ||
| 282 | struct sm501_devdata *sm = dev_get_drvdata(dev); | ||
| 283 | unsigned long result; | ||
| 284 | unsigned long reg; | ||
| 285 | |||
| 286 | reg = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW; | ||
| 287 | result = readl(sm->regs + reg); | ||
| 288 | |||
| 289 | result >>= (gpio & 31); | ||
| 290 | return result & 1UL; | ||
| 291 | } | ||
| 292 | |||
| 293 | EXPORT_SYMBOL_GPL(sm501_gpio_get); | ||
| 294 | |||
| 295 | void sm501_gpio_set(struct device *dev, | ||
| 296 | unsigned long gpio, | ||
| 297 | unsigned int to, | ||
| 298 | unsigned int dir) | ||
| 299 | { | ||
| 300 | struct sm501_devdata *sm = dev_get_drvdata(dev); | ||
| 301 | |||
| 302 | unsigned long bit = 1 << (gpio & 31); | ||
| 303 | unsigned long base; | ||
| 304 | unsigned long save; | ||
| 305 | unsigned long val; | ||
| 306 | |||
| 307 | base = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW; | ||
| 308 | base += SM501_GPIO; | ||
| 309 | |||
| 310 | spin_lock_irqsave(&sm->reg_lock, save); | ||
| 311 | |||
| 312 | val = readl(sm->regs + base) & ~bit; | ||
| 313 | if (to) | ||
| 314 | val |= bit; | ||
| 315 | writel(val, sm->regs + base); | ||
| 316 | |||
| 317 | val = readl(sm->regs + SM501_GPIO_DDR_LOW) & ~bit; | ||
| 318 | if (dir) | ||
| 319 | val |= bit; | ||
| 320 | |||
| 321 | writel(val, sm->regs + SM501_GPIO_DDR_LOW); | ||
| 322 | sm501_sync_regs(sm); | ||
| 323 | |||
| 324 | spin_unlock_irqrestore(&sm->reg_lock, save); | ||
| 325 | |||
| 326 | } | ||
| 327 | |||
| 328 | EXPORT_SYMBOL_GPL(sm501_gpio_set); | ||
| 329 | |||
| 330 | |||
| 331 | /* sm501_unit_power | 309 | /* sm501_unit_power |
| 332 | * | 310 | * |
| 333 | * alters the power active gate to set specific units on or off | 311 | * alters the power active gate to set specific units on or off |
| @@ -906,6 +884,313 @@ static int sm501_register_display(struct sm501_devdata *sm, | |||
| 906 | return sm501_register_device(sm, pdev); | 884 | return sm501_register_device(sm, pdev); |
| 907 | } | 885 | } |
| 908 | 886 | ||
| 887 | #ifdef CONFIG_MFD_SM501_GPIO | ||
| 888 | |||
| 889 | static inline struct sm501_gpio_chip *to_sm501_gpio(struct gpio_chip *gc) | ||
| 890 | { | ||
| 891 | return container_of(gc, struct sm501_gpio_chip, gpio); | ||
| 892 | } | ||
| 893 | |||
| 894 | static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio) | ||
| 895 | { | ||
| 896 | return container_of(gpio, struct sm501_devdata, gpio); | ||
| 897 | } | ||
| 898 | |||
| 899 | static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
| 900 | |||
| 901 | { | ||
| 902 | struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip); | ||
| 903 | unsigned long result; | ||
| 904 | |||
| 905 | result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW); | ||
| 906 | result >>= offset; | ||
| 907 | |||
| 908 | return result & 1UL; | ||
| 909 | } | ||
| 910 | |||
| 911 | static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
| 912 | |||
| 913 | { | ||
| 914 | struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); | ||
| 915 | struct sm501_gpio *smgpio = smchip->ourgpio; | ||
| 916 | unsigned long bit = 1 << offset; | ||
| 917 | void __iomem *regs = smchip->regbase; | ||
| 918 | unsigned long save; | ||
| 919 | unsigned long val; | ||
| 920 | |||
| 921 | dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n", | ||
| 922 | __func__, chip, offset); | ||
| 923 | |||
| 924 | spin_lock_irqsave(&smgpio->lock, save); | ||
| 925 | |||
| 926 | val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit; | ||
| 927 | if (value) | ||
| 928 | val |= bit; | ||
| 929 | writel(val, regs); | ||
| 930 | |||
| 931 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
| 932 | spin_unlock_irqrestore(&smgpio->lock, save); | ||
| 933 | } | ||
| 934 | |||
| 935 | static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) | ||
| 936 | { | ||
| 937 | struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); | ||
| 938 | struct sm501_gpio *smgpio = smchip->ourgpio; | ||
| 939 | void __iomem *regs = smchip->regbase; | ||
| 940 | unsigned long bit = 1 << offset; | ||
| 941 | unsigned long save; | ||
| 942 | unsigned long ddr; | ||
| 943 | |||
| 944 | dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n", | ||
| 945 | __func__, chip, offset); | ||
| 946 | |||
| 947 | spin_lock_irqsave(&smgpio->lock, save); | ||
| 948 | |||
| 949 | ddr = readl(regs + SM501_GPIO_DDR_LOW); | ||
| 950 | writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW); | ||
| 951 | |||
| 952 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
| 953 | spin_unlock_irqrestore(&smgpio->lock, save); | ||
| 954 | |||
| 955 | return 0; | ||
| 956 | } | ||
| 957 | |||
| 958 | static int sm501_gpio_output(struct gpio_chip *chip, | ||
| 959 | unsigned offset, int value) | ||
| 960 | { | ||
| 961 | struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); | ||
| 962 | struct sm501_gpio *smgpio = smchip->ourgpio; | ||
| 963 | unsigned long bit = 1 << offset; | ||
| 964 | void __iomem *regs = smchip->regbase; | ||
| 965 | unsigned long save; | ||
| 966 | unsigned long val; | ||
| 967 | unsigned long ddr; | ||
| 968 | |||
| 969 | dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d,%d)\n", | ||
| 970 | __func__, chip, offset, value); | ||
| 971 | |||
| 972 | spin_lock_irqsave(&smgpio->lock, save); | ||
| 973 | |||
| 974 | val = readl(regs + SM501_GPIO_DATA_LOW); | ||
| 975 | if (value) | ||
| 976 | val |= bit; | ||
| 977 | else | ||
| 978 | val &= ~bit; | ||
| 979 | writel(val, regs); | ||
| 980 | |||
| 981 | ddr = readl(regs + SM501_GPIO_DDR_LOW); | ||
| 982 | writel(ddr | bit, regs + SM501_GPIO_DDR_LOW); | ||
| 983 | |||
| 984 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
| 985 | writel(val, regs + SM501_GPIO_DATA_LOW); | ||
| 986 | |||
| 987 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
| 988 | spin_unlock_irqrestore(&smgpio->lock, save); | ||
| 989 | |||
| 990 | return 0; | ||
| 991 | } | ||
| 992 | |||
| 993 | static struct gpio_chip gpio_chip_template = { | ||
| 994 | .ngpio = 32, | ||
| 995 | .direction_input = sm501_gpio_input, | ||
| 996 | .direction_output = sm501_gpio_output, | ||
| 997 | .set = sm501_gpio_set, | ||
| 998 | .get = sm501_gpio_get, | ||
| 999 | }; | ||
| 1000 | |||
| 1001 | static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm, | ||
| 1002 | struct sm501_gpio *gpio, | ||
| 1003 | struct sm501_gpio_chip *chip) | ||
| 1004 | { | ||
| 1005 | struct sm501_platdata *pdata = sm->platdata; | ||
| 1006 | struct gpio_chip *gchip = &chip->gpio; | ||
| 1007 | int base = pdata->gpio_base; | ||
| 1008 | |||
| 1009 | chip->gpio = gpio_chip_template; | ||
| 1010 | |||
| 1011 | if (chip == &gpio->high) { | ||
| 1012 | if (base > 0) | ||
| 1013 | base += 32; | ||
| 1014 | chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH; | ||
| 1015 | gchip->label = "SM501-HIGH"; | ||
| 1016 | } else { | ||
| 1017 | chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW; | ||
| 1018 | gchip->label = "SM501-LOW"; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | gchip->base = base; | ||
| 1022 | chip->ourgpio = gpio; | ||
| 1023 | |||
| 1024 | return gpiochip_add(gchip); | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | static int sm501_register_gpio(struct sm501_devdata *sm) | ||
| 1028 | { | ||
| 1029 | struct sm501_gpio *gpio = &sm->gpio; | ||
| 1030 | resource_size_t iobase = sm->io_res->start + SM501_GPIO; | ||
| 1031 | int ret; | ||
| 1032 | int tmp; | ||
| 1033 | |||
| 1034 | dev_dbg(sm->dev, "registering gpio block %08llx\n", | ||
| 1035 | (unsigned long long)iobase); | ||
| 1036 | |||
| 1037 | spin_lock_init(&gpio->lock); | ||
| 1038 | |||
| 1039 | gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio"); | ||
| 1040 | if (gpio->regs_res == NULL) { | ||
| 1041 | dev_err(sm->dev, "gpio: failed to request region\n"); | ||
| 1042 | return -ENXIO; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | gpio->regs = ioremap(iobase, 0x20); | ||
| 1046 | if (gpio->regs == NULL) { | ||
| 1047 | dev_err(sm->dev, "gpio: failed to remap registers\n"); | ||
| 1048 | ret = -ENXIO; | ||
| 1049 | goto err_claimed; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | /* Register both our chips. */ | ||
| 1053 | |||
| 1054 | ret = sm501_gpio_register_chip(sm, gpio, &gpio->low); | ||
| 1055 | if (ret) { | ||
| 1056 | dev_err(sm->dev, "failed to add low chip\n"); | ||
| 1057 | goto err_mapped; | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | ret = sm501_gpio_register_chip(sm, gpio, &gpio->high); | ||
| 1061 | if (ret) { | ||
| 1062 | dev_err(sm->dev, "failed to add high chip\n"); | ||
| 1063 | goto err_low_chip; | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | gpio->registered = 1; | ||
| 1067 | |||
| 1068 | return 0; | ||
| 1069 | |||
| 1070 | err_low_chip: | ||
| 1071 | tmp = gpiochip_remove(&gpio->low.gpio); | ||
| 1072 | if (tmp) { | ||
| 1073 | dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n"); | ||
| 1074 | return ret; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | err_mapped: | ||
| 1078 | iounmap(gpio->regs); | ||
| 1079 | |||
| 1080 | err_claimed: | ||
| 1081 | release_resource(gpio->regs_res); | ||
| 1082 | kfree(gpio->regs_res); | ||
| 1083 | |||
| 1084 | return ret; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | static void sm501_gpio_remove(struct sm501_devdata *sm) | ||
| 1088 | { | ||
| 1089 | struct sm501_gpio *gpio = &sm->gpio; | ||
| 1090 | int ret; | ||
| 1091 | |||
| 1092 | if (!sm->gpio.registered) | ||
| 1093 | return; | ||
| 1094 | |||
| 1095 | ret = gpiochip_remove(&gpio->low.gpio); | ||
| 1096 | if (ret) | ||
| 1097 | dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n"); | ||
| 1098 | |||
| 1099 | ret = gpiochip_remove(&gpio->high.gpio); | ||
| 1100 | if (ret) | ||
| 1101 | dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n"); | ||
| 1102 | |||
| 1103 | iounmap(gpio->regs); | ||
| 1104 | release_resource(gpio->regs_res); | ||
| 1105 | kfree(gpio->regs_res); | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) | ||
| 1109 | { | ||
| 1110 | struct sm501_gpio *gpio = &sm->gpio; | ||
| 1111 | int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base; | ||
| 1112 | |||
| 1113 | return (pin % 32) + base; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) | ||
| 1117 | { | ||
| 1118 | return sm->gpio.registered; | ||
| 1119 | } | ||
| 1120 | #else | ||
| 1121 | static inline int sm501_register_gpio(struct sm501_devdata *sm) | ||
| 1122 | { | ||
| 1123 | return 0; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | static inline void sm501_gpio_remove(struct sm501_devdata *sm) | ||
| 1127 | { | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) | ||
| 1131 | { | ||
| 1132 | return -1; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) | ||
| 1136 | { | ||
| 1137 | return 0; | ||
| 1138 | } | ||
| 1139 | #endif | ||
| 1140 | |||
| 1141 | static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, | ||
| 1142 | struct sm501_platdata_gpio_i2c *iic) | ||
| 1143 | { | ||
| 1144 | struct i2c_gpio_platform_data *icd; | ||
| 1145 | struct platform_device *pdev; | ||
| 1146 | |||
| 1147 | pdev = sm501_create_subdev(sm, "i2c-gpio", 0, | ||
| 1148 | sizeof(struct i2c_gpio_platform_data)); | ||
| 1149 | if (!pdev) | ||
| 1150 | return -ENOMEM; | ||
| 1151 | |||
| 1152 | icd = pdev->dev.platform_data; | ||
| 1153 | |||
| 1154 | /* We keep the pin_sda and pin_scl fields relative in case the | ||
| 1155 | * same platform data is passed to >1 SM501. | ||
| 1156 | */ | ||
| 1157 | |||
| 1158 | icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda); | ||
| 1159 | icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl); | ||
| 1160 | icd->timeout = iic->timeout; | ||
| 1161 | icd->udelay = iic->udelay; | ||
| 1162 | |||
| 1163 | /* note, we can't use either of the pin numbers, as the i2c-gpio | ||
| 1164 | * driver uses the platform.id field to generate the bus number | ||
| 1165 | * to register with the i2c core; The i2c core doesn't have enough | ||
| 1166 | * entries to deal with anything we currently use. | ||
| 1167 | */ | ||
| 1168 | |||
| 1169 | pdev->id = iic->bus_num; | ||
| 1170 | |||
| 1171 | dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n", | ||
| 1172 | iic->bus_num, | ||
| 1173 | icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl); | ||
| 1174 | |||
| 1175 | return sm501_register_device(sm, pdev); | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | static int sm501_register_gpio_i2c(struct sm501_devdata *sm, | ||
| 1179 | struct sm501_platdata *pdata) | ||
| 1180 | { | ||
| 1181 | struct sm501_platdata_gpio_i2c *iic = pdata->gpio_i2c; | ||
| 1182 | int index; | ||
| 1183 | int ret; | ||
| 1184 | |||
| 1185 | for (index = 0; index < pdata->gpio_i2c_nr; index++, iic++) { | ||
| 1186 | ret = sm501_register_gpio_i2c_instance(sm, iic); | ||
| 1187 | if (ret < 0) | ||
| 1188 | return ret; | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | return 0; | ||
| 1192 | } | ||
| 1193 | |||
| 909 | /* sm501_dbg_regs | 1194 | /* sm501_dbg_regs |
| 910 | * | 1195 | * |
| 911 | * Debug attribute to attach to parent device to show core registers | 1196 | * Debug attribute to attach to parent device to show core registers |
| @@ -1013,6 +1298,7 @@ static unsigned int sm501_mem_local[] = { | |||
| 1013 | static int sm501_init_dev(struct sm501_devdata *sm) | 1298 | static int sm501_init_dev(struct sm501_devdata *sm) |
| 1014 | { | 1299 | { |
| 1015 | struct sm501_initdata *idata; | 1300 | struct sm501_initdata *idata; |
| 1301 | struct sm501_platdata *pdata; | ||
| 1016 | resource_size_t mem_avail; | 1302 | resource_size_t mem_avail; |
| 1017 | unsigned long dramctrl; | 1303 | unsigned long dramctrl; |
| 1018 | unsigned long devid; | 1304 | unsigned long devid; |
| @@ -1051,7 +1337,9 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
| 1051 | 1337 | ||
| 1052 | /* check to see if we have some device initialisation */ | 1338 | /* check to see if we have some device initialisation */ |
| 1053 | 1339 | ||
| 1054 | idata = sm->platdata ? sm->platdata->init : NULL; | 1340 | pdata = sm->platdata; |
| 1341 | idata = pdata ? pdata->init : NULL; | ||
| 1342 | |||
| 1055 | if (idata) { | 1343 | if (idata) { |
| 1056 | sm501_init_regs(sm, idata); | 1344 | sm501_init_regs(sm, idata); |
| 1057 | 1345 | ||
| @@ -1059,6 +1347,15 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
| 1059 | sm501_register_usbhost(sm, &mem_avail); | 1347 | sm501_register_usbhost(sm, &mem_avail); |
| 1060 | if (idata->devices & (SM501_USE_UART0 | SM501_USE_UART1)) | 1348 | if (idata->devices & (SM501_USE_UART0 | SM501_USE_UART1)) |
| 1061 | sm501_register_uart(sm, idata->devices); | 1349 | sm501_register_uart(sm, idata->devices); |
| 1350 | if (idata->devices & SM501_USE_GPIO) | ||
| 1351 | sm501_register_gpio(sm); | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) { | ||
| 1355 | if (!sm501_gpio_isregistered(sm)) | ||
| 1356 | dev_err(sm->dev, "no gpio available for i2c gpio.\n"); | ||
| 1357 | else | ||
| 1358 | sm501_register_gpio_i2c(sm, pdata); | ||
| 1062 | } | 1359 | } |
| 1063 | 1360 | ||
| 1064 | ret = sm501_check_clocks(sm); | 1361 | ret = sm501_check_clocks(sm); |
| @@ -1138,8 +1435,31 @@ static int sm501_plat_probe(struct platform_device *dev) | |||
| 1138 | } | 1435 | } |
| 1139 | 1436 | ||
| 1140 | #ifdef CONFIG_PM | 1437 | #ifdef CONFIG_PM |
| 1438 | |||
| 1141 | /* power management support */ | 1439 | /* power management support */ |
| 1142 | 1440 | ||
| 1441 | static void sm501_set_power(struct sm501_devdata *sm, int on) | ||
| 1442 | { | ||
| 1443 | struct sm501_platdata *pd = sm->platdata; | ||
| 1444 | |||
| 1445 | if (pd == NULL) | ||
| 1446 | return; | ||
| 1447 | |||
| 1448 | if (pd->get_power) { | ||
| 1449 | if (pd->get_power(sm->dev) == on) { | ||
| 1450 | dev_dbg(sm->dev, "is already %d\n", on); | ||
| 1451 | return; | ||
| 1452 | } | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | if (pd->set_power) { | ||
| 1456 | dev_dbg(sm->dev, "setting power to %d\n", on); | ||
| 1457 | |||
| 1458 | pd->set_power(sm->dev, on); | ||
| 1459 | sm501_mdelay(sm, 10); | ||
| 1460 | } | ||
| 1461 | } | ||
| 1462 | |||
| 1143 | static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state) | 1463 | static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state) |
| 1144 | { | 1464 | { |
| 1145 | struct sm501_devdata *sm = platform_get_drvdata(pdev); | 1465 | struct sm501_devdata *sm = platform_get_drvdata(pdev); |
| @@ -1148,6 +1468,12 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 1148 | sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL); | 1468 | sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL); |
| 1149 | 1469 | ||
| 1150 | sm501_dump_regs(sm); | 1470 | sm501_dump_regs(sm); |
| 1471 | |||
| 1472 | if (sm->platdata) { | ||
| 1473 | if (sm->platdata->flags & SM501_FLAG_SUSPEND_OFF) | ||
| 1474 | sm501_set_power(sm, 0); | ||
| 1475 | } | ||
| 1476 | |||
| 1151 | return 0; | 1477 | return 0; |
| 1152 | } | 1478 | } |
| 1153 | 1479 | ||
| @@ -1155,6 +1481,8 @@ static int sm501_plat_resume(struct platform_device *pdev) | |||
| 1155 | { | 1481 | { |
| 1156 | struct sm501_devdata *sm = platform_get_drvdata(pdev); | 1482 | struct sm501_devdata *sm = platform_get_drvdata(pdev); |
| 1157 | 1483 | ||
| 1484 | sm501_set_power(sm, 1); | ||
| 1485 | |||
| 1158 | sm501_dump_regs(sm); | 1486 | sm501_dump_regs(sm); |
| 1159 | sm501_dump_gate(sm); | 1487 | sm501_dump_gate(sm); |
| 1160 | sm501_dump_clk(sm); | 1488 | sm501_dump_clk(sm); |
| @@ -1229,6 +1557,7 @@ static struct sm501_platdata_fb sm501_fb_pdata = { | |||
| 1229 | static struct sm501_platdata sm501_pci_platdata = { | 1557 | static struct sm501_platdata sm501_pci_platdata = { |
| 1230 | .init = &sm501_pci_initdata, | 1558 | .init = &sm501_pci_initdata, |
| 1231 | .fb = &sm501_fb_pdata, | 1559 | .fb = &sm501_fb_pdata, |
| 1560 | .gpio_base = -1, | ||
| 1232 | }; | 1561 | }; |
| 1233 | 1562 | ||
| 1234 | static int sm501_pci_probe(struct pci_dev *dev, | 1563 | static int sm501_pci_probe(struct pci_dev *dev, |
| @@ -1335,6 +1664,8 @@ static void sm501_dev_remove(struct sm501_devdata *sm) | |||
| 1335 | sm501_remove_sub(sm, smdev); | 1664 | sm501_remove_sub(sm, smdev); |
| 1336 | 1665 | ||
| 1337 | device_remove_file(sm->dev, &dev_attr_dbg_regs); | 1666 | device_remove_file(sm->dev, &dev_attr_dbg_regs); |
| 1667 | |||
| 1668 | sm501_gpio_remove(sm); | ||
| 1338 | } | 1669 | } |
| 1339 | 1670 | ||
| 1340 | static void sm501_pci_remove(struct pci_dev *dev) | 1671 | static void sm501_pci_remove(struct pci_dev *dev) |
| @@ -1378,6 +1709,8 @@ static struct pci_driver sm501_pci_drv = { | |||
| 1378 | .remove = sm501_pci_remove, | 1709 | .remove = sm501_pci_remove, |
| 1379 | }; | 1710 | }; |
| 1380 | 1711 | ||
| 1712 | MODULE_ALIAS("platform:sm501"); | ||
| 1713 | |||
| 1381 | static struct platform_driver sm501_plat_drv = { | 1714 | static struct platform_driver sm501_plat_drv = { |
| 1382 | .driver = { | 1715 | .driver = { |
| 1383 | .name = "sm501", | 1716 | .name = "sm501", |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index d5bc288b1b0d..321eb9134635 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -77,11 +77,13 @@ config IBM_ASM | |||
| 77 | for your IBM server. | 77 | for your IBM server. |
| 78 | 78 | ||
| 79 | config PHANTOM | 79 | config PHANTOM |
| 80 | tristate "Sensable PHANToM" | 80 | tristate "Sensable PHANToM (PCI)" |
| 81 | depends on PCI | 81 | depends on PCI |
| 82 | help | 82 | help |
| 83 | Say Y here if you want to build a driver for Sensable PHANToM device. | 83 | Say Y here if you want to build a driver for Sensable PHANToM device. |
| 84 | 84 | ||
| 85 | This driver is only for PCI PHANToMs. | ||
| 86 | |||
| 85 | If you choose to build module, its name will be phantom. If unsure, | 87 | If you choose to build module, its name will be phantom. If unsure, |
| 86 | say N here. | 88 | say N here. |
| 87 | 89 | ||
| @@ -212,6 +214,18 @@ config TC1100_WMI | |||
| 212 | This is a driver for the WMI extensions (wireless and bluetooth power | 214 | This is a driver for the WMI extensions (wireless and bluetooth power |
| 213 | control) of the HP Compaq TC1100 tablet. | 215 | control) of the HP Compaq TC1100 tablet. |
| 214 | 216 | ||
| 217 | config HP_WMI | ||
| 218 | tristate "HP WMI extras" | ||
| 219 | depends on ACPI_WMI | ||
| 220 | depends on INPUT | ||
| 221 | depends on RFKILL | ||
| 222 | help | ||
| 223 | Say Y here if you want to support WMI-based hotkeys on HP laptops and | ||
| 224 | to read data from WMI such as docking or ambient light sensor state. | ||
| 225 | |||
| 226 | To compile this driver as a module, choose M here: the module will | ||
| 227 | be called hp-wmi. | ||
| 228 | |||
| 215 | config MSI_LAPTOP | 229 | config MSI_LAPTOP |
| 216 | tristate "MSI Laptop Extras" | 230 | tristate "MSI Laptop Extras" |
| 217 | depends on X86 | 231 | depends on X86 |
| @@ -424,6 +438,7 @@ config SGI_XP | |||
| 424 | 438 | ||
| 425 | config HP_ILO | 439 | config HP_ILO |
| 426 | tristate "Channel interface driver for HP iLO/iLO2 processor" | 440 | tristate "Channel interface driver for HP iLO/iLO2 processor" |
| 441 | depends on PCI | ||
| 427 | default n | 442 | default n |
| 428 | help | 443 | help |
| 429 | The channel interface driver allows applications to communicate | 444 | The channel interface driver allows applications to communicate |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 688fe76135e0..f5e273420c09 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -13,6 +13,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o | |||
| 13 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o | 13 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o |
| 14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o | 14 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
| 15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | 15 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o |
| 16 | obj-$(CONFIG_HP_WMI) += hp-wmi.o | ||
| 16 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o | 17 | obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o |
| 17 | obj-$(CONFIG_LKDTM) += lkdtm.o | 18 | obj-$(CONFIG_LKDTM) += lkdtm.o |
| 18 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o | 19 | obj-$(CONFIG_TIFM_CORE) += tifm_core.o |
diff --git a/drivers/misc/hp-wmi.c b/drivers/misc/hp-wmi.c new file mode 100644 index 000000000000..1dbcbcb323a2 --- /dev/null +++ b/drivers/misc/hp-wmi.c | |||
| @@ -0,0 +1,494 @@ | |||
| 1 | /* | ||
| 2 | * HP WMI hotkeys | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Red Hat <mjg@redhat.com> | ||
| 5 | * | ||
| 6 | * Portions based on wistron_btns.c: | ||
| 7 | * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> | ||
| 8 | * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> | ||
| 9 | * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/init.h> | ||
| 29 | #include <linux/types.h> | ||
| 30 | #include <linux/input.h> | ||
| 31 | #include <acpi/acpi_drivers.h> | ||
| 32 | #include <linux/platform_device.h> | ||
| 33 | #include <linux/acpi.h> | ||
| 34 | #include <linux/rfkill.h> | ||
| 35 | #include <linux/string.h> | ||
| 36 | |||
| 37 | MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>"); | ||
| 38 | MODULE_DESCRIPTION("HP laptop WMI hotkeys driver"); | ||
| 39 | MODULE_LICENSE("GPL"); | ||
| 40 | |||
| 41 | MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C"); | ||
| 42 | MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); | ||
| 43 | |||
| 44 | #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" | ||
| 45 | #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4" | ||
| 46 | |||
| 47 | #define HPWMI_DISPLAY_QUERY 0x1 | ||
| 48 | #define HPWMI_HDDTEMP_QUERY 0x2 | ||
| 49 | #define HPWMI_ALS_QUERY 0x3 | ||
| 50 | #define HPWMI_DOCK_QUERY 0x4 | ||
| 51 | #define HPWMI_WIRELESS_QUERY 0x5 | ||
| 52 | |||
| 53 | static int __init hp_wmi_bios_setup(struct platform_device *device); | ||
| 54 | static int __exit hp_wmi_bios_remove(struct platform_device *device); | ||
| 55 | |||
| 56 | struct bios_args { | ||
| 57 | u32 signature; | ||
| 58 | u32 command; | ||
| 59 | u32 commandtype; | ||
| 60 | u32 datasize; | ||
| 61 | u32 data; | ||
| 62 | }; | ||
| 63 | |||
| 64 | struct bios_return { | ||
| 65 | u32 sigpass; | ||
| 66 | u32 return_code; | ||
| 67 | u32 value; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct key_entry { | ||
| 71 | char type; /* See KE_* below */ | ||
| 72 | u8 code; | ||
| 73 | u16 keycode; | ||
| 74 | }; | ||
| 75 | |||
| 76 | enum { KE_KEY, KE_SW, KE_END }; | ||
| 77 | |||
| 78 | static struct key_entry hp_wmi_keymap[] = { | ||
| 79 | {KE_SW, 0x01, SW_DOCK}, | ||
| 80 | {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, | ||
| 81 | {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, | ||
| 82 | {KE_KEY, 0x04, KEY_HELP}, | ||
| 83 | {KE_END, 0} | ||
| 84 | }; | ||
| 85 | |||
| 86 | static struct input_dev *hp_wmi_input_dev; | ||
| 87 | static struct platform_device *hp_wmi_platform_dev; | ||
| 88 | |||
| 89 | static struct rfkill *wifi_rfkill; | ||
| 90 | static struct rfkill *bluetooth_rfkill; | ||
| 91 | static struct rfkill *wwan_rfkill; | ||
| 92 | |||
| 93 | static struct platform_driver hp_wmi_driver = { | ||
| 94 | .driver = { | ||
| 95 | .name = "hp-wmi", | ||
| 96 | .owner = THIS_MODULE, | ||
| 97 | }, | ||
| 98 | .probe = hp_wmi_bios_setup, | ||
| 99 | .remove = hp_wmi_bios_remove, | ||
| 100 | }; | ||
| 101 | |||
| 102 | static int hp_wmi_perform_query(int query, int write, int value) | ||
| 103 | { | ||
| 104 | struct bios_return bios_return; | ||
| 105 | acpi_status status; | ||
| 106 | union acpi_object *obj; | ||
| 107 | struct bios_args args = { | ||
| 108 | .signature = 0x55434553, | ||
| 109 | .command = write ? 0x2 : 0x1, | ||
| 110 | .commandtype = query, | ||
| 111 | .datasize = write ? 0x4 : 0, | ||
| 112 | .data = value, | ||
| 113 | }; | ||
| 114 | struct acpi_buffer input = { sizeof(struct bios_args), &args }; | ||
| 115 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 116 | |||
| 117 | status = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output); | ||
| 118 | |||
| 119 | obj = output.pointer; | ||
| 120 | |||
| 121 | if (!obj || obj->type != ACPI_TYPE_BUFFER) | ||
| 122 | return -EINVAL; | ||
| 123 | |||
| 124 | bios_return = *((struct bios_return *)obj->buffer.pointer); | ||
| 125 | if (bios_return.return_code > 0) | ||
| 126 | return bios_return.return_code * -1; | ||
| 127 | else | ||
| 128 | return bios_return.value; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int hp_wmi_display_state(void) | ||
| 132 | { | ||
| 133 | return hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, 0); | ||
| 134 | } | ||
| 135 | |||
| 136 | static int hp_wmi_hddtemp_state(void) | ||
| 137 | { | ||
| 138 | return hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, 0); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int hp_wmi_als_state(void) | ||
| 142 | { | ||
| 143 | return hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, 0); | ||
| 144 | } | ||
| 145 | |||
| 146 | static int hp_wmi_dock_state(void) | ||
| 147 | { | ||
| 148 | return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0); | ||
| 149 | } | ||
| 150 | |||
| 151 | static int hp_wmi_wifi_set(void *data, enum rfkill_state state) | ||
| 152 | { | ||
| 153 | if (state) | ||
| 154 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x101); | ||
| 155 | else | ||
| 156 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x100); | ||
| 157 | } | ||
| 158 | |||
| 159 | static int hp_wmi_bluetooth_set(void *data, enum rfkill_state state) | ||
| 160 | { | ||
| 161 | if (state) | ||
| 162 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x202); | ||
| 163 | else | ||
| 164 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x200); | ||
| 165 | } | ||
| 166 | |||
| 167 | static int hp_wmi_wwan_set(void *data, enum rfkill_state state) | ||
| 168 | { | ||
| 169 | if (state) | ||
| 170 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x404); | ||
| 171 | else | ||
| 172 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x400); | ||
| 173 | } | ||
| 174 | |||
| 175 | static int hp_wmi_wifi_state(void) | ||
| 176 | { | ||
| 177 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); | ||
| 178 | |||
| 179 | if (wireless & 0x100) | ||
| 180 | return 1; | ||
| 181 | else | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | static int hp_wmi_bluetooth_state(void) | ||
| 186 | { | ||
| 187 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); | ||
| 188 | |||
| 189 | if (wireless & 0x10000) | ||
| 190 | return 1; | ||
| 191 | else | ||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int hp_wmi_wwan_state(void) | ||
| 196 | { | ||
| 197 | int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); | ||
| 198 | |||
| 199 | if (wireless & 0x1000000) | ||
| 200 | return 1; | ||
| 201 | else | ||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | static ssize_t show_display(struct device *dev, struct device_attribute *attr, | ||
| 206 | char *buf) | ||
| 207 | { | ||
| 208 | int value = hp_wmi_display_state(); | ||
| 209 | if (value < 0) | ||
| 210 | return -EINVAL; | ||
| 211 | return sprintf(buf, "%d\n", value); | ||
| 212 | } | ||
| 213 | |||
| 214 | static ssize_t show_hddtemp(struct device *dev, struct device_attribute *attr, | ||
| 215 | char *buf) | ||
| 216 | { | ||
| 217 | int value = hp_wmi_hddtemp_state(); | ||
| 218 | if (value < 0) | ||
| 219 | return -EINVAL; | ||
| 220 | return sprintf(buf, "%d\n", value); | ||
| 221 | } | ||
| 222 | |||
| 223 | static ssize_t show_als(struct device *dev, struct device_attribute *attr, | ||
| 224 | char *buf) | ||
| 225 | { | ||
| 226 | int value = hp_wmi_als_state(); | ||
| 227 | if (value < 0) | ||
| 228 | return -EINVAL; | ||
| 229 | return sprintf(buf, "%d\n", value); | ||
| 230 | } | ||
| 231 | |||
| 232 | static ssize_t show_dock(struct device *dev, struct device_attribute *attr, | ||
| 233 | char *buf) | ||
| 234 | { | ||
| 235 | int value = hp_wmi_dock_state(); | ||
| 236 | if (value < 0) | ||
| 237 | return -EINVAL; | ||
| 238 | return sprintf(buf, "%d\n", value); | ||
| 239 | } | ||
| 240 | |||
| 241 | static ssize_t set_als(struct device *dev, struct device_attribute *attr, | ||
| 242 | const char *buf, size_t count) | ||
| 243 | { | ||
| 244 | u32 tmp = simple_strtoul(buf, NULL, 10); | ||
| 245 | hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, tmp); | ||
| 246 | return count; | ||
| 247 | } | ||
| 248 | |||
| 249 | static DEVICE_ATTR(display, S_IRUGO, show_display, NULL); | ||
| 250 | static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); | ||
| 251 | static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); | ||
| 252 | static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); | ||
| 253 | |||
| 254 | static struct key_entry *hp_wmi_get_entry_by_scancode(int code) | ||
| 255 | { | ||
| 256 | struct key_entry *key; | ||
| 257 | |||
| 258 | for (key = hp_wmi_keymap; key->type != KE_END; key++) | ||
| 259 | if (code == key->code) | ||
| 260 | return key; | ||
| 261 | |||
| 262 | return NULL; | ||
| 263 | } | ||
| 264 | |||
| 265 | static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) | ||
| 266 | { | ||
| 267 | struct key_entry *key; | ||
| 268 | |||
| 269 | for (key = hp_wmi_keymap; key->type != KE_END; key++) | ||
| 270 | if (key->type == KE_KEY && keycode == key->keycode) | ||
| 271 | return key; | ||
| 272 | |||
| 273 | return NULL; | ||
| 274 | } | ||
| 275 | |||
| 276 | static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
| 277 | { | ||
| 278 | struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode); | ||
| 279 | |||
| 280 | if (key && key->type == KE_KEY) { | ||
| 281 | *keycode = key->keycode; | ||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | return -EINVAL; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) | ||
| 289 | { | ||
| 290 | struct key_entry *key; | ||
| 291 | int old_keycode; | ||
| 292 | |||
| 293 | if (keycode < 0 || keycode > KEY_MAX) | ||
| 294 | return -EINVAL; | ||
| 295 | |||
| 296 | key = hp_wmi_get_entry_by_scancode(scancode); | ||
| 297 | if (key && key->type == KE_KEY) { | ||
| 298 | old_keycode = key->keycode; | ||
| 299 | key->keycode = keycode; | ||
| 300 | set_bit(keycode, dev->keybit); | ||
| 301 | if (!hp_wmi_get_entry_by_keycode(old_keycode)) | ||
| 302 | clear_bit(old_keycode, dev->keybit); | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | return -EINVAL; | ||
| 307 | } | ||
| 308 | |||
| 309 | void hp_wmi_notify(u32 value, void *context) | ||
| 310 | { | ||
| 311 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 312 | static struct key_entry *key; | ||
| 313 | union acpi_object *obj; | ||
| 314 | |||
| 315 | wmi_get_event_data(value, &response); | ||
| 316 | |||
| 317 | obj = (union acpi_object *)response.pointer; | ||
| 318 | |||
| 319 | if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) { | ||
| 320 | int eventcode = *((u8 *) obj->buffer.pointer); | ||
| 321 | key = hp_wmi_get_entry_by_scancode(eventcode); | ||
| 322 | if (key) { | ||
| 323 | switch (key->type) { | ||
| 324 | case KE_KEY: | ||
| 325 | input_report_key(hp_wmi_input_dev, | ||
| 326 | key->keycode, 1); | ||
| 327 | input_sync(hp_wmi_input_dev); | ||
| 328 | input_report_key(hp_wmi_input_dev, | ||
| 329 | key->keycode, 0); | ||
| 330 | input_sync(hp_wmi_input_dev); | ||
| 331 | break; | ||
| 332 | case KE_SW: | ||
| 333 | input_report_switch(hp_wmi_input_dev, | ||
| 334 | key->keycode, | ||
| 335 | hp_wmi_dock_state()); | ||
| 336 | input_sync(hp_wmi_input_dev); | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | } else if (eventcode == 0x5) { | ||
| 340 | if (wifi_rfkill) | ||
| 341 | wifi_rfkill->state = hp_wmi_wifi_state(); | ||
| 342 | if (bluetooth_rfkill) | ||
| 343 | bluetooth_rfkill->state = | ||
| 344 | hp_wmi_bluetooth_state(); | ||
| 345 | if (wwan_rfkill) | ||
| 346 | wwan_rfkill->state = hp_wmi_wwan_state(); | ||
| 347 | } else | ||
| 348 | printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", | ||
| 349 | eventcode); | ||
| 350 | } else | ||
| 351 | printk(KERN_INFO "HP WMI: Unknown response received\n"); | ||
| 352 | } | ||
| 353 | |||
| 354 | static int __init hp_wmi_input_setup(void) | ||
| 355 | { | ||
| 356 | struct key_entry *key; | ||
| 357 | int err; | ||
| 358 | |||
| 359 | hp_wmi_input_dev = input_allocate_device(); | ||
| 360 | |||
| 361 | hp_wmi_input_dev->name = "HP WMI hotkeys"; | ||
| 362 | hp_wmi_input_dev->phys = "wmi/input0"; | ||
| 363 | hp_wmi_input_dev->id.bustype = BUS_HOST; | ||
| 364 | hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode; | ||
| 365 | hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode; | ||
| 366 | |||
| 367 | for (key = hp_wmi_keymap; key->type != KE_END; key++) { | ||
| 368 | switch (key->type) { | ||
| 369 | case KE_KEY: | ||
| 370 | set_bit(EV_KEY, hp_wmi_input_dev->evbit); | ||
| 371 | set_bit(key->keycode, hp_wmi_input_dev->keybit); | ||
| 372 | break; | ||
| 373 | case KE_SW: | ||
| 374 | set_bit(EV_SW, hp_wmi_input_dev->evbit); | ||
| 375 | set_bit(key->keycode, hp_wmi_input_dev->swbit); | ||
| 376 | break; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | |||
| 380 | err = input_register_device(hp_wmi_input_dev); | ||
| 381 | |||
| 382 | if (err) { | ||
| 383 | input_free_device(hp_wmi_input_dev); | ||
| 384 | return err; | ||
| 385 | } | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | static void cleanup_sysfs(struct platform_device *device) | ||
| 391 | { | ||
| 392 | device_remove_file(&device->dev, &dev_attr_display); | ||
| 393 | device_remove_file(&device->dev, &dev_attr_hddtemp); | ||
| 394 | device_remove_file(&device->dev, &dev_attr_als); | ||
| 395 | device_remove_file(&device->dev, &dev_attr_dock); | ||
| 396 | } | ||
| 397 | |||
| 398 | static int __init hp_wmi_bios_setup(struct platform_device *device) | ||
| 399 | { | ||
| 400 | int err; | ||
| 401 | |||
| 402 | err = device_create_file(&device->dev, &dev_attr_display); | ||
| 403 | if (err) | ||
| 404 | goto add_sysfs_error; | ||
| 405 | err = device_create_file(&device->dev, &dev_attr_hddtemp); | ||
| 406 | if (err) | ||
| 407 | goto add_sysfs_error; | ||
| 408 | err = device_create_file(&device->dev, &dev_attr_als); | ||
| 409 | if (err) | ||
| 410 | goto add_sysfs_error; | ||
| 411 | err = device_create_file(&device->dev, &dev_attr_dock); | ||
| 412 | if (err) | ||
| 413 | goto add_sysfs_error; | ||
| 414 | |||
| 415 | wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); | ||
| 416 | wifi_rfkill->name = "hp-wifi"; | ||
| 417 | wifi_rfkill->state = hp_wmi_wifi_state(); | ||
| 418 | wifi_rfkill->toggle_radio = hp_wmi_wifi_set; | ||
| 419 | wifi_rfkill->user_claim_unsupported = 1; | ||
| 420 | |||
| 421 | bluetooth_rfkill = rfkill_allocate(&device->dev, | ||
| 422 | RFKILL_TYPE_BLUETOOTH); | ||
| 423 | bluetooth_rfkill->name = "hp-bluetooth"; | ||
| 424 | bluetooth_rfkill->state = hp_wmi_bluetooth_state(); | ||
| 425 | bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set; | ||
| 426 | bluetooth_rfkill->user_claim_unsupported = 1; | ||
| 427 | |||
| 428 | wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); | ||
| 429 | wwan_rfkill->name = "hp-wwan"; | ||
| 430 | wwan_rfkill->state = hp_wmi_wwan_state(); | ||
| 431 | wwan_rfkill->toggle_radio = hp_wmi_wwan_set; | ||
| 432 | wwan_rfkill->user_claim_unsupported = 1; | ||
| 433 | |||
| 434 | rfkill_register(wifi_rfkill); | ||
| 435 | rfkill_register(bluetooth_rfkill); | ||
| 436 | rfkill_register(wwan_rfkill); | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | add_sysfs_error: | ||
| 440 | cleanup_sysfs(device); | ||
| 441 | return err; | ||
| 442 | } | ||
| 443 | |||
| 444 | static int __exit hp_wmi_bios_remove(struct platform_device *device) | ||
| 445 | { | ||
| 446 | cleanup_sysfs(device); | ||
| 447 | |||
| 448 | rfkill_unregister(wifi_rfkill); | ||
| 449 | rfkill_unregister(bluetooth_rfkill); | ||
| 450 | rfkill_unregister(wwan_rfkill); | ||
| 451 | |||
| 452 | return 0; | ||
| 453 | } | ||
| 454 | |||
| 455 | static int __init hp_wmi_init(void) | ||
| 456 | { | ||
| 457 | int err; | ||
| 458 | |||
| 459 | if (wmi_has_guid(HPWMI_EVENT_GUID)) { | ||
| 460 | err = wmi_install_notify_handler(HPWMI_EVENT_GUID, | ||
| 461 | hp_wmi_notify, NULL); | ||
| 462 | if (!err) | ||
| 463 | hp_wmi_input_setup(); | ||
| 464 | } | ||
| 465 | |||
| 466 | if (wmi_has_guid(HPWMI_BIOS_GUID)) { | ||
| 467 | err = platform_driver_register(&hp_wmi_driver); | ||
| 468 | if (err) | ||
| 469 | return 0; | ||
| 470 | hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1); | ||
| 471 | if (!hp_wmi_platform_dev) { | ||
| 472 | platform_driver_unregister(&hp_wmi_driver); | ||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | platform_device_add(hp_wmi_platform_dev); | ||
| 476 | } | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | |||
| 481 | static void __exit hp_wmi_exit(void) | ||
| 482 | { | ||
| 483 | if (wmi_has_guid(HPWMI_EVENT_GUID)) { | ||
| 484 | wmi_remove_notify_handler(HPWMI_EVENT_GUID); | ||
| 485 | input_unregister_device(hp_wmi_input_dev); | ||
| 486 | } | ||
| 487 | if (hp_wmi_platform_dev) { | ||
| 488 | platform_device_del(hp_wmi_platform_dev); | ||
| 489 | platform_driver_unregister(&hp_wmi_driver); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | module_init(hp_wmi_init); | ||
| 494 | module_exit(hp_wmi_exit); | ||
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 4ce3bdc2f959..daf585689ce3 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
| @@ -563,6 +563,6 @@ module_init(phantom_init); | |||
| 563 | module_exit(phantom_exit); | 563 | module_exit(phantom_exit); |
| 564 | 564 | ||
| 565 | MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>"); | 565 | MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>"); |
| 566 | MODULE_DESCRIPTION("Sensable Phantom driver"); | 566 | MODULE_DESCRIPTION("Sensable Phantom driver (PCI devices)"); |
| 567 | MODULE_LICENSE("GPL"); | 567 | MODULE_LICENSE("GPL"); |
| 568 | MODULE_VERSION(PHANTOM_VERSION); | 568 | MODULE_VERSION(PHANTOM_VERSION); |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 961416ac0616..c7630a228310 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -51,14 +51,13 @@ | |||
| 51 | * @name: MTD device name or number string | 51 | * @name: MTD device name or number string |
| 52 | * @vid_hdr_offs: VID header offset | 52 | * @vid_hdr_offs: VID header offset |
| 53 | */ | 53 | */ |
| 54 | struct mtd_dev_param | 54 | struct mtd_dev_param { |
| 55 | { | ||
| 56 | char name[MTD_PARAM_LEN_MAX]; | 55 | char name[MTD_PARAM_LEN_MAX]; |
| 57 | int vid_hdr_offs; | 56 | int vid_hdr_offs; |
| 58 | }; | 57 | }; |
| 59 | 58 | ||
| 60 | /* Numbers of elements set in the @mtd_dev_param array */ | 59 | /* Numbers of elements set in the @mtd_dev_param array */ |
| 61 | static int mtd_devs = 0; | 60 | static int mtd_devs; |
| 62 | 61 | ||
| 63 | /* MTD devices specification parameters */ | 62 | /* MTD devices specification parameters */ |
| 64 | static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; | 63 | static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; |
| @@ -160,8 +159,7 @@ void ubi_put_device(struct ubi_device *ubi) | |||
| 160 | } | 159 | } |
| 161 | 160 | ||
| 162 | /** | 161 | /** |
| 163 | * ubi_get_by_major - get UBI device description object by character device | 162 | * ubi_get_by_major - get UBI device by character device major number. |
| 164 | * major number. | ||
| 165 | * @major: major number | 163 | * @major: major number |
| 166 | * | 164 | * |
| 167 | * This function is similar to 'ubi_get_device()', but it searches the device | 165 | * This function is similar to 'ubi_get_device()', but it searches the device |
| @@ -355,15 +353,34 @@ static void kill_volumes(struct ubi_device *ubi) | |||
| 355 | } | 353 | } |
| 356 | 354 | ||
| 357 | /** | 355 | /** |
| 356 | * free_user_volumes - free all user volumes. | ||
| 357 | * @ubi: UBI device description object | ||
| 358 | * | ||
| 359 | * Normally the volumes are freed at the release function of the volume device | ||
| 360 | * objects. However, on error paths the volumes have to be freed before the | ||
| 361 | * device objects have been initialized. | ||
| 362 | */ | ||
| 363 | static void free_user_volumes(struct ubi_device *ubi) | ||
| 364 | { | ||
| 365 | int i; | ||
| 366 | |||
| 367 | for (i = 0; i < ubi->vtbl_slots; i++) | ||
| 368 | if (ubi->volumes[i]) { | ||
| 369 | kfree(ubi->volumes[i]->eba_tbl); | ||
| 370 | kfree(ubi->volumes[i]); | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | /** | ||
| 358 | * uif_init - initialize user interfaces for an UBI device. | 375 | * uif_init - initialize user interfaces for an UBI device. |
| 359 | * @ubi: UBI device description object | 376 | * @ubi: UBI device description object |
| 360 | * | 377 | * |
| 361 | * This function returns zero in case of success and a negative error code in | 378 | * This function returns zero in case of success and a negative error code in |
| 362 | * case of failure. | 379 | * case of failure. Note, this function destroys all volumes if it failes. |
| 363 | */ | 380 | */ |
| 364 | static int uif_init(struct ubi_device *ubi) | 381 | static int uif_init(struct ubi_device *ubi) |
| 365 | { | 382 | { |
| 366 | int i, err; | 383 | int i, err, do_free = 0; |
| 367 | dev_t dev; | 384 | dev_t dev; |
| 368 | 385 | ||
| 369 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); | 386 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); |
| @@ -384,7 +401,7 @@ static int uif_init(struct ubi_device *ubi) | |||
| 384 | 401 | ||
| 385 | ubi_assert(MINOR(dev) == 0); | 402 | ubi_assert(MINOR(dev) == 0); |
| 386 | cdev_init(&ubi->cdev, &ubi_cdev_operations); | 403 | cdev_init(&ubi->cdev, &ubi_cdev_operations); |
| 387 | dbg_msg("%s major is %u", ubi->ubi_name, MAJOR(dev)); | 404 | dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev)); |
| 388 | ubi->cdev.owner = THIS_MODULE; | 405 | ubi->cdev.owner = THIS_MODULE; |
| 389 | 406 | ||
| 390 | err = cdev_add(&ubi->cdev, dev, 1); | 407 | err = cdev_add(&ubi->cdev, dev, 1); |
| @@ -410,10 +427,13 @@ static int uif_init(struct ubi_device *ubi) | |||
| 410 | 427 | ||
| 411 | out_volumes: | 428 | out_volumes: |
| 412 | kill_volumes(ubi); | 429 | kill_volumes(ubi); |
| 430 | do_free = 0; | ||
| 413 | out_sysfs: | 431 | out_sysfs: |
| 414 | ubi_sysfs_close(ubi); | 432 | ubi_sysfs_close(ubi); |
| 415 | cdev_del(&ubi->cdev); | 433 | cdev_del(&ubi->cdev); |
| 416 | out_unreg: | 434 | out_unreg: |
| 435 | if (do_free) | ||
| 436 | free_user_volumes(ubi); | ||
| 417 | unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); | 437 | unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); |
| 418 | ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); | 438 | ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); |
| 419 | return err; | 439 | return err; |
| @@ -422,6 +442,10 @@ out_unreg: | |||
| 422 | /** | 442 | /** |
| 423 | * uif_close - close user interfaces for an UBI device. | 443 | * uif_close - close user interfaces for an UBI device. |
| 424 | * @ubi: UBI device description object | 444 | * @ubi: UBI device description object |
| 445 | * | ||
| 446 | * Note, since this function un-registers UBI volume device objects (@vol->dev), | ||
| 447 | * the memory allocated voe the volumes is freed as well (in the release | ||
| 448 | * function). | ||
| 425 | */ | 449 | */ |
| 426 | static void uif_close(struct ubi_device *ubi) | 450 | static void uif_close(struct ubi_device *ubi) |
| 427 | { | 451 | { |
| @@ -432,6 +456,21 @@ static void uif_close(struct ubi_device *ubi) | |||
| 432 | } | 456 | } |
| 433 | 457 | ||
| 434 | /** | 458 | /** |
| 459 | * free_internal_volumes - free internal volumes. | ||
| 460 | * @ubi: UBI device description object | ||
| 461 | */ | ||
| 462 | static void free_internal_volumes(struct ubi_device *ubi) | ||
| 463 | { | ||
| 464 | int i; | ||
| 465 | |||
| 466 | for (i = ubi->vtbl_slots; | ||
| 467 | i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { | ||
| 468 | kfree(ubi->volumes[i]->eba_tbl); | ||
| 469 | kfree(ubi->volumes[i]); | ||
| 470 | } | ||
| 471 | } | ||
| 472 | |||
| 473 | /** | ||
| 435 | * attach_by_scanning - attach an MTD device using scanning method. | 474 | * attach_by_scanning - attach an MTD device using scanning method. |
| 436 | * @ubi: UBI device descriptor | 475 | * @ubi: UBI device descriptor |
| 437 | * | 476 | * |
| @@ -475,6 +514,7 @@ static int attach_by_scanning(struct ubi_device *ubi) | |||
| 475 | out_wl: | 514 | out_wl: |
| 476 | ubi_wl_close(ubi); | 515 | ubi_wl_close(ubi); |
| 477 | out_vtbl: | 516 | out_vtbl: |
| 517 | free_internal_volumes(ubi); | ||
| 478 | vfree(ubi->vtbl); | 518 | vfree(ubi->vtbl); |
| 479 | out_si: | 519 | out_si: |
| 480 | ubi_scan_destroy_si(si); | 520 | ubi_scan_destroy_si(si); |
| @@ -482,7 +522,7 @@ out_si: | |||
| 482 | } | 522 | } |
| 483 | 523 | ||
| 484 | /** | 524 | /** |
| 485 | * io_init - initialize I/O unit for a given UBI device. | 525 | * io_init - initialize I/O sub-system for a given UBI device. |
| 486 | * @ubi: UBI device description object | 526 | * @ubi: UBI device description object |
| 487 | * | 527 | * |
| 488 | * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are | 528 | * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are |
| @@ -530,7 +570,11 @@ static int io_init(struct ubi_device *ubi) | |||
| 530 | ubi->min_io_size = ubi->mtd->writesize; | 570 | ubi->min_io_size = ubi->mtd->writesize; |
| 531 | ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; | 571 | ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; |
| 532 | 572 | ||
| 533 | /* Make sure minimal I/O unit is power of 2 */ | 573 | /* |
| 574 | * Make sure minimal I/O unit is power of 2. Note, there is no | ||
| 575 | * fundamental reason for this assumption. It is just an optimization | ||
| 576 | * which allows us to avoid costly division operations. | ||
| 577 | */ | ||
| 534 | if (!is_power_of_2(ubi->min_io_size)) { | 578 | if (!is_power_of_2(ubi->min_io_size)) { |
| 535 | ubi_err("min. I/O unit (%d) is not power of 2", | 579 | ubi_err("min. I/O unit (%d) is not power of 2", |
| 536 | ubi->min_io_size); | 580 | ubi->min_io_size); |
| @@ -581,7 +625,7 @@ static int io_init(struct ubi_device *ubi) | |||
| 581 | if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE || | 625 | if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE || |
| 582 | ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE || | 626 | ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE || |
| 583 | ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE || | 627 | ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE || |
| 584 | ubi->leb_start % ubi->min_io_size) { | 628 | ubi->leb_start & (ubi->min_io_size - 1)) { |
| 585 | ubi_err("bad VID header (%d) or data offsets (%d)", | 629 | ubi_err("bad VID header (%d) or data offsets (%d)", |
| 586 | ubi->vid_hdr_offset, ubi->leb_start); | 630 | ubi->vid_hdr_offset, ubi->leb_start); |
| 587 | return -EINVAL; | 631 | return -EINVAL; |
| @@ -646,7 +690,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) | |||
| 646 | 690 | ||
| 647 | /* | 691 | /* |
| 648 | * Clear the auto-resize flag in the volume in-memory copy of the | 692 | * Clear the auto-resize flag in the volume in-memory copy of the |
| 649 | * volume table, and 'ubi_resize_volume()' will propogate this change | 693 | * volume table, and 'ubi_resize_volume()' will propagate this change |
| 650 | * to the flash. | 694 | * to the flash. |
| 651 | */ | 695 | */ |
| 652 | ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; | 696 | ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; |
| @@ -655,7 +699,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) | |||
| 655 | struct ubi_vtbl_record vtbl_rec; | 699 | struct ubi_vtbl_record vtbl_rec; |
| 656 | 700 | ||
| 657 | /* | 701 | /* |
| 658 | * No avalilable PEBs to re-size the volume, clear the flag on | 702 | * No available PEBs to re-size the volume, clear the flag on |
| 659 | * flash and exit. | 703 | * flash and exit. |
| 660 | */ | 704 | */ |
| 661 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], | 705 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], |
| @@ -682,13 +726,13 @@ static int autoresize(struct ubi_device *ubi, int vol_id) | |||
| 682 | 726 | ||
| 683 | /** | 727 | /** |
| 684 | * ubi_attach_mtd_dev - attach an MTD device. | 728 | * ubi_attach_mtd_dev - attach an MTD device. |
| 685 | * @mtd_dev: MTD device description object | 729 | * @mtd: MTD device description object |
| 686 | * @ubi_num: number to assign to the new UBI device | 730 | * @ubi_num: number to assign to the new UBI device |
| 687 | * @vid_hdr_offset: VID header offset | 731 | * @vid_hdr_offset: VID header offset |
| 688 | * | 732 | * |
| 689 | * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number | 733 | * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number |
| 690 | * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in | 734 | * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in |
| 691 | * which case this function finds a vacant device nubert and assings it | 735 | * which case this function finds a vacant device number and assigns it |
| 692 | * automatically. Returns the new UBI device number in case of success and a | 736 | * automatically. Returns the new UBI device number in case of success and a |
| 693 | * negative error code in case of failure. | 737 | * negative error code in case of failure. |
| 694 | * | 738 | * |
| @@ -698,7 +742,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) | |||
| 698 | int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | 742 | int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) |
| 699 | { | 743 | { |
| 700 | struct ubi_device *ubi; | 744 | struct ubi_device *ubi; |
| 701 | int i, err; | 745 | int i, err, do_free = 1; |
| 702 | 746 | ||
| 703 | /* | 747 | /* |
| 704 | * Check if we already have the same MTD device attached. | 748 | * Check if we already have the same MTD device attached. |
| @@ -735,7 +779,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 735 | if (!ubi_devices[ubi_num]) | 779 | if (!ubi_devices[ubi_num]) |
| 736 | break; | 780 | break; |
| 737 | if (ubi_num == UBI_MAX_DEVICES) { | 781 | if (ubi_num == UBI_MAX_DEVICES) { |
| 738 | dbg_err("only %d UBI devices may be created", UBI_MAX_DEVICES); | 782 | dbg_err("only %d UBI devices may be created", |
| 783 | UBI_MAX_DEVICES); | ||
| 739 | return -ENFILE; | 784 | return -ENFILE; |
| 740 | } | 785 | } |
| 741 | } else { | 786 | } else { |
| @@ -760,6 +805,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 760 | 805 | ||
| 761 | mutex_init(&ubi->buf_mutex); | 806 | mutex_init(&ubi->buf_mutex); |
| 762 | mutex_init(&ubi->ckvol_mutex); | 807 | mutex_init(&ubi->ckvol_mutex); |
| 808 | mutex_init(&ubi->mult_mutex); | ||
| 763 | mutex_init(&ubi->volumes_mutex); | 809 | mutex_init(&ubi->volumes_mutex); |
| 764 | spin_lock_init(&ubi->volumes_lock); | 810 | spin_lock_init(&ubi->volumes_lock); |
| 765 | 811 | ||
| @@ -798,7 +844,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 798 | 844 | ||
| 799 | err = uif_init(ubi); | 845 | err = uif_init(ubi); |
| 800 | if (err) | 846 | if (err) |
| 801 | goto out_detach; | 847 | goto out_nofree; |
| 802 | 848 | ||
| 803 | ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); | 849 | ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); |
| 804 | if (IS_ERR(ubi->bgt_thread)) { | 850 | if (IS_ERR(ubi->bgt_thread)) { |
| @@ -824,20 +870,22 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 824 | ubi->beb_rsvd_pebs); | 870 | ubi->beb_rsvd_pebs); |
| 825 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); | 871 | ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); |
| 826 | 872 | ||
| 827 | /* Enable the background thread */ | 873 | if (!DBG_DISABLE_BGT) |
| 828 | if (!DBG_DISABLE_BGT) { | ||
| 829 | ubi->thread_enabled = 1; | 874 | ubi->thread_enabled = 1; |
| 830 | wake_up_process(ubi->bgt_thread); | 875 | wake_up_process(ubi->bgt_thread); |
| 831 | } | ||
| 832 | 876 | ||
| 833 | ubi_devices[ubi_num] = ubi; | 877 | ubi_devices[ubi_num] = ubi; |
| 834 | return ubi_num; | 878 | return ubi_num; |
| 835 | 879 | ||
| 836 | out_uif: | 880 | out_uif: |
| 837 | uif_close(ubi); | 881 | uif_close(ubi); |
| 882 | out_nofree: | ||
| 883 | do_free = 0; | ||
| 838 | out_detach: | 884 | out_detach: |
| 839 | ubi_eba_close(ubi); | ||
| 840 | ubi_wl_close(ubi); | 885 | ubi_wl_close(ubi); |
| 886 | if (do_free) | ||
| 887 | free_user_volumes(ubi); | ||
| 888 | free_internal_volumes(ubi); | ||
| 841 | vfree(ubi->vtbl); | 889 | vfree(ubi->vtbl); |
| 842 | out_free: | 890 | out_free: |
| 843 | vfree(ubi->peb_buf1); | 891 | vfree(ubi->peb_buf1); |
| @@ -899,8 +947,8 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
| 899 | kthread_stop(ubi->bgt_thread); | 947 | kthread_stop(ubi->bgt_thread); |
| 900 | 948 | ||
| 901 | uif_close(ubi); | 949 | uif_close(ubi); |
| 902 | ubi_eba_close(ubi); | ||
| 903 | ubi_wl_close(ubi); | 950 | ubi_wl_close(ubi); |
| 951 | free_internal_volumes(ubi); | ||
| 904 | vfree(ubi->vtbl); | 952 | vfree(ubi->vtbl); |
| 905 | put_mtd_device(ubi->mtd); | 953 | put_mtd_device(ubi->mtd); |
| 906 | vfree(ubi->peb_buf1); | 954 | vfree(ubi->peb_buf1); |
| @@ -1044,8 +1092,7 @@ static void __exit ubi_exit(void) | |||
| 1044 | module_exit(ubi_exit); | 1092 | module_exit(ubi_exit); |
| 1045 | 1093 | ||
| 1046 | /** | 1094 | /** |
| 1047 | * bytes_str_to_int - convert a string representing number of bytes to an | 1095 | * bytes_str_to_int - convert a number of bytes string into an integer. |
| 1048 | * integer. | ||
| 1049 | * @str: the string to convert | 1096 | * @str: the string to convert |
| 1050 | * | 1097 | * |
| 1051 | * This function returns positive resulting integer in case of success and a | 1098 | * This function returns positive resulting integer in case of success and a |
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 89193ba9451e..03c759b4eeb5 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
| @@ -39,9 +39,9 @@ | |||
| 39 | #include <linux/stat.h> | 39 | #include <linux/stat.h> |
| 40 | #include <linux/ioctl.h> | 40 | #include <linux/ioctl.h> |
| 41 | #include <linux/capability.h> | 41 | #include <linux/capability.h> |
| 42 | #include <linux/uaccess.h> | ||
| 42 | #include <linux/smp_lock.h> | 43 | #include <linux/smp_lock.h> |
| 43 | #include <mtd/ubi-user.h> | 44 | #include <mtd/ubi-user.h> |
| 44 | #include <asm/uaccess.h> | ||
| 45 | #include <asm/div64.h> | 45 | #include <asm/div64.h> |
| 46 | #include "ubi.h" | 46 | #include "ubi.h" |
| 47 | 47 | ||
| @@ -116,7 +116,7 @@ static int vol_cdev_open(struct inode *inode, struct file *file) | |||
| 116 | else | 116 | else |
| 117 | mode = UBI_READONLY; | 117 | mode = UBI_READONLY; |
| 118 | 118 | ||
| 119 | dbg_msg("open volume %d, mode %d", vol_id, mode); | 119 | dbg_gen("open volume %d, mode %d", vol_id, mode); |
| 120 | 120 | ||
| 121 | desc = ubi_open_volume(ubi_num, vol_id, mode); | 121 | desc = ubi_open_volume(ubi_num, vol_id, mode); |
| 122 | unlock_kernel(); | 122 | unlock_kernel(); |
| @@ -132,7 +132,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file) | |||
| 132 | struct ubi_volume_desc *desc = file->private_data; | 132 | struct ubi_volume_desc *desc = file->private_data; |
| 133 | struct ubi_volume *vol = desc->vol; | 133 | struct ubi_volume *vol = desc->vol; |
| 134 | 134 | ||
| 135 | dbg_msg("release volume %d, mode %d", vol->vol_id, desc->mode); | 135 | dbg_gen("release volume %d, mode %d", vol->vol_id, desc->mode); |
| 136 | 136 | ||
| 137 | if (vol->updating) { | 137 | if (vol->updating) { |
| 138 | ubi_warn("update of volume %d not finished, volume is damaged", | 138 | ubi_warn("update of volume %d not finished, volume is damaged", |
| @@ -141,7 +141,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file) | |||
| 141 | vol->updating = 0; | 141 | vol->updating = 0; |
| 142 | vfree(vol->upd_buf); | 142 | vfree(vol->upd_buf); |
| 143 | } else if (vol->changing_leb) { | 143 | } else if (vol->changing_leb) { |
| 144 | dbg_msg("only %lld of %lld bytes received for atomic LEB change" | 144 | dbg_gen("only %lld of %lld bytes received for atomic LEB change" |
| 145 | " for volume %d:%d, cancel", vol->upd_received, | 145 | " for volume %d:%d, cancel", vol->upd_received, |
| 146 | vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id); | 146 | vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id); |
| 147 | vol->changing_leb = 0; | 147 | vol->changing_leb = 0; |
| @@ -183,7 +183,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin) | |||
| 183 | return -EINVAL; | 183 | return -EINVAL; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | dbg_msg("seek volume %d, offset %lld, origin %d, new offset %lld", | 186 | dbg_gen("seek volume %d, offset %lld, origin %d, new offset %lld", |
| 187 | vol->vol_id, offset, origin, new_offset); | 187 | vol->vol_id, offset, origin, new_offset); |
| 188 | 188 | ||
| 189 | file->f_pos = new_offset; | 189 | file->f_pos = new_offset; |
| @@ -201,7 +201,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, | |||
| 201 | void *tbuf; | 201 | void *tbuf; |
| 202 | uint64_t tmp; | 202 | uint64_t tmp; |
| 203 | 203 | ||
| 204 | dbg_msg("read %zd bytes from offset %lld of volume %d", | 204 | dbg_gen("read %zd bytes from offset %lld of volume %d", |
| 205 | count, *offp, vol->vol_id); | 205 | count, *offp, vol->vol_id); |
| 206 | 206 | ||
| 207 | if (vol->updating) { | 207 | if (vol->updating) { |
| @@ -216,7 +216,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, | |||
| 216 | return 0; | 216 | return 0; |
| 217 | 217 | ||
| 218 | if (vol->corrupted) | 218 | if (vol->corrupted) |
| 219 | dbg_msg("read from corrupted volume %d", vol->vol_id); | 219 | dbg_gen("read from corrupted volume %d", vol->vol_id); |
| 220 | 220 | ||
| 221 | if (*offp + count > vol->used_bytes) | 221 | if (*offp + count > vol->used_bytes) |
| 222 | count_save = count = vol->used_bytes - *offp; | 222 | count_save = count = vol->used_bytes - *offp; |
| @@ -285,7 +285,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
| 285 | char *tbuf; | 285 | char *tbuf; |
| 286 | uint64_t tmp; | 286 | uint64_t tmp; |
| 287 | 287 | ||
| 288 | dbg_msg("requested: write %zd bytes to offset %lld of volume %u", | 288 | dbg_gen("requested: write %zd bytes to offset %lld of volume %u", |
| 289 | count, *offp, vol->vol_id); | 289 | count, *offp, vol->vol_id); |
| 290 | 290 | ||
| 291 | if (vol->vol_type == UBI_STATIC_VOLUME) | 291 | if (vol->vol_type == UBI_STATIC_VOLUME) |
| @@ -295,7 +295,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
| 295 | off = do_div(tmp, vol->usable_leb_size); | 295 | off = do_div(tmp, vol->usable_leb_size); |
| 296 | lnum = tmp; | 296 | lnum = tmp; |
| 297 | 297 | ||
| 298 | if (off % ubi->min_io_size) { | 298 | if (off & (ubi->min_io_size - 1)) { |
| 299 | dbg_err("unaligned position"); | 299 | dbg_err("unaligned position"); |
| 300 | return -EINVAL; | 300 | return -EINVAL; |
| 301 | } | 301 | } |
| @@ -304,7 +304,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
| 304 | count_save = count = vol->used_bytes - *offp; | 304 | count_save = count = vol->used_bytes - *offp; |
| 305 | 305 | ||
| 306 | /* We can write only in fractions of the minimum I/O unit */ | 306 | /* We can write only in fractions of the minimum I/O unit */ |
| 307 | if (count % ubi->min_io_size) { | 307 | if (count & (ubi->min_io_size - 1)) { |
| 308 | dbg_err("unaligned write length"); | 308 | dbg_err("unaligned write length"); |
| 309 | return -EINVAL; | 309 | return -EINVAL; |
| 310 | } | 310 | } |
| @@ -352,7 +352,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | #else | 354 | #else |
| 355 | #define vol_cdev_direct_write(file, buf, count, offp) -EPERM | 355 | #define vol_cdev_direct_write(file, buf, count, offp) (-EPERM) |
| 356 | #endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */ | 356 | #endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */ |
| 357 | 357 | ||
| 358 | static ssize_t vol_cdev_write(struct file *file, const char __user *buf, | 358 | static ssize_t vol_cdev_write(struct file *file, const char __user *buf, |
| @@ -437,7 +437,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 437 | break; | 437 | break; |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad); | 440 | rsvd_bytes = (long long)vol->reserved_pebs * |
| 441 | ubi->leb_size-vol->data_pad; | ||
| 441 | if (bytes < 0 || bytes > rsvd_bytes) { | 442 | if (bytes < 0 || bytes > rsvd_bytes) { |
| 442 | err = -EINVAL; | 443 | err = -EINVAL; |
| 443 | break; | 444 | break; |
| @@ -513,7 +514,7 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 513 | break; | 514 | break; |
| 514 | } | 515 | } |
| 515 | 516 | ||
| 516 | dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); | 517 | dbg_gen("erase LEB %d:%d", vol->vol_id, lnum); |
| 517 | err = ubi_eba_unmap_leb(ubi, vol, lnum); | 518 | err = ubi_eba_unmap_leb(ubi, vol, lnum); |
| 518 | if (err) | 519 | if (err) |
| 519 | break; | 520 | break; |
| @@ -564,7 +565,7 @@ static int verify_mkvol_req(const struct ubi_device *ubi, | |||
| 564 | if (req->alignment > ubi->leb_size) | 565 | if (req->alignment > ubi->leb_size) |
| 565 | goto bad; | 566 | goto bad; |
| 566 | 567 | ||
| 567 | n = req->alignment % ubi->min_io_size; | 568 | n = req->alignment & (ubi->min_io_size - 1); |
| 568 | if (req->alignment != 1 && n) | 569 | if (req->alignment != 1 && n) |
| 569 | goto bad; | 570 | goto bad; |
| 570 | 571 | ||
| @@ -573,6 +574,10 @@ static int verify_mkvol_req(const struct ubi_device *ubi, | |||
| 573 | goto bad; | 574 | goto bad; |
| 574 | } | 575 | } |
| 575 | 576 | ||
| 577 | n = strnlen(req->name, req->name_len + 1); | ||
| 578 | if (n != req->name_len) | ||
| 579 | goto bad; | ||
| 580 | |||
| 576 | return 0; | 581 | return 0; |
| 577 | 582 | ||
| 578 | bad: | 583 | bad: |
| @@ -600,6 +605,166 @@ static int verify_rsvol_req(const struct ubi_device *ubi, | |||
| 600 | return 0; | 605 | return 0; |
| 601 | } | 606 | } |
| 602 | 607 | ||
| 608 | /** | ||
| 609 | * rename_volumes - rename UBI volumes. | ||
| 610 | * @ubi: UBI device description object | ||
| 611 | * @req: volumes re-name request | ||
| 612 | * | ||
| 613 | * This is a helper function for the volume re-name IOCTL which validates the | ||
| 614 | * the request, opens the volume and calls corresponding volumes management | ||
| 615 | * function. Returns zero in case of success and a negative error code in case | ||
| 616 | * of failure. | ||
| 617 | */ | ||
| 618 | static int rename_volumes(struct ubi_device *ubi, | ||
| 619 | struct ubi_rnvol_req *req) | ||
| 620 | { | ||
| 621 | int i, n, err; | ||
| 622 | struct list_head rename_list; | ||
| 623 | struct ubi_rename_entry *re, *re1; | ||
| 624 | |||
| 625 | if (req->count < 0 || req->count > UBI_MAX_RNVOL) | ||
| 626 | return -EINVAL; | ||
| 627 | |||
| 628 | if (req->count == 0) | ||
| 629 | return 0; | ||
| 630 | |||
| 631 | /* Validate volume IDs and names in the request */ | ||
| 632 | for (i = 0; i < req->count; i++) { | ||
| 633 | if (req->ents[i].vol_id < 0 || | ||
| 634 | req->ents[i].vol_id >= ubi->vtbl_slots) | ||
| 635 | return -EINVAL; | ||
| 636 | if (req->ents[i].name_len < 0) | ||
| 637 | return -EINVAL; | ||
| 638 | if (req->ents[i].name_len > UBI_VOL_NAME_MAX) | ||
| 639 | return -ENAMETOOLONG; | ||
| 640 | req->ents[i].name[req->ents[i].name_len] = '\0'; | ||
| 641 | n = strlen(req->ents[i].name); | ||
| 642 | if (n != req->ents[i].name_len) | ||
| 643 | err = -EINVAL; | ||
| 644 | } | ||
| 645 | |||
| 646 | /* Make sure volume IDs and names are unique */ | ||
| 647 | for (i = 0; i < req->count - 1; i++) { | ||
| 648 | for (n = i + 1; n < req->count; n++) { | ||
| 649 | if (req->ents[i].vol_id == req->ents[n].vol_id) { | ||
| 650 | dbg_err("duplicated volume id %d", | ||
| 651 | req->ents[i].vol_id); | ||
| 652 | return -EINVAL; | ||
| 653 | } | ||
| 654 | if (!strcmp(req->ents[i].name, req->ents[n].name)) { | ||
| 655 | dbg_err("duplicated volume name \"%s\"", | ||
| 656 | req->ents[i].name); | ||
| 657 | return -EINVAL; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | /* Create the re-name list */ | ||
| 663 | INIT_LIST_HEAD(&rename_list); | ||
| 664 | for (i = 0; i < req->count; i++) { | ||
| 665 | int vol_id = req->ents[i].vol_id; | ||
| 666 | int name_len = req->ents[i].name_len; | ||
| 667 | const char *name = req->ents[i].name; | ||
| 668 | |||
| 669 | re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); | ||
| 670 | if (!re) { | ||
| 671 | err = -ENOMEM; | ||
| 672 | goto out_free; | ||
| 673 | } | ||
| 674 | |||
| 675 | re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); | ||
| 676 | if (IS_ERR(re->desc)) { | ||
| 677 | err = PTR_ERR(re->desc); | ||
| 678 | dbg_err("cannot open volume %d, error %d", vol_id, err); | ||
| 679 | kfree(re); | ||
| 680 | goto out_free; | ||
| 681 | } | ||
| 682 | |||
| 683 | /* Skip this re-naming if the name does not really change */ | ||
| 684 | if (re->desc->vol->name_len == name_len && | ||
| 685 | !memcmp(re->desc->vol->name, name, name_len)) { | ||
| 686 | ubi_close_volume(re->desc); | ||
| 687 | kfree(re); | ||
| 688 | continue; | ||
| 689 | } | ||
| 690 | |||
| 691 | re->new_name_len = name_len; | ||
| 692 | memcpy(re->new_name, name, name_len); | ||
| 693 | list_add_tail(&re->list, &rename_list); | ||
| 694 | dbg_msg("will rename volume %d from \"%s\" to \"%s\"", | ||
| 695 | vol_id, re->desc->vol->name, name); | ||
| 696 | } | ||
| 697 | |||
| 698 | if (list_empty(&rename_list)) | ||
| 699 | return 0; | ||
| 700 | |||
| 701 | /* Find out the volumes which have to be removed */ | ||
| 702 | list_for_each_entry(re, &rename_list, list) { | ||
| 703 | struct ubi_volume_desc *desc; | ||
| 704 | int no_remove_needed = 0; | ||
| 705 | |||
| 706 | /* | ||
| 707 | * Volume @re->vol_id is going to be re-named to | ||
| 708 | * @re->new_name, while its current name is @name. If a volume | ||
| 709 | * with name @re->new_name currently exists, it has to be | ||
| 710 | * removed, unless it is also re-named in the request (@req). | ||
| 711 | */ | ||
| 712 | list_for_each_entry(re1, &rename_list, list) { | ||
| 713 | if (re->new_name_len == re1->desc->vol->name_len && | ||
| 714 | !memcmp(re->new_name, re1->desc->vol->name, | ||
| 715 | re1->desc->vol->name_len)) { | ||
| 716 | no_remove_needed = 1; | ||
| 717 | break; | ||
| 718 | } | ||
| 719 | } | ||
| 720 | |||
| 721 | if (no_remove_needed) | ||
| 722 | continue; | ||
| 723 | |||
| 724 | /* | ||
| 725 | * It seems we need to remove volume with name @re->new_name, | ||
| 726 | * if it exists. | ||
| 727 | */ | ||
| 728 | desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name, UBI_EXCLUSIVE); | ||
| 729 | if (IS_ERR(desc)) { | ||
| 730 | err = PTR_ERR(desc); | ||
| 731 | if (err == -ENODEV) | ||
| 732 | /* Re-naming into a non-existing volume name */ | ||
| 733 | continue; | ||
| 734 | |||
| 735 | /* The volume exists but busy, or an error occurred */ | ||
| 736 | dbg_err("cannot open volume \"%s\", error %d", | ||
| 737 | re->new_name, err); | ||
| 738 | goto out_free; | ||
| 739 | } | ||
| 740 | |||
| 741 | re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); | ||
| 742 | if (!re) { | ||
| 743 | err = -ENOMEM; | ||
| 744 | ubi_close_volume(desc); | ||
| 745 | goto out_free; | ||
| 746 | } | ||
| 747 | |||
| 748 | re->remove = 1; | ||
| 749 | re->desc = desc; | ||
| 750 | list_add(&re->list, &rename_list); | ||
| 751 | dbg_msg("will remove volume %d, name \"%s\"", | ||
| 752 | re->desc->vol->vol_id, re->desc->vol->name); | ||
| 753 | } | ||
| 754 | |||
| 755 | mutex_lock(&ubi->volumes_mutex); | ||
| 756 | err = ubi_rename_volumes(ubi, &rename_list); | ||
| 757 | mutex_unlock(&ubi->volumes_mutex); | ||
| 758 | |||
| 759 | out_free: | ||
| 760 | list_for_each_entry_safe(re, re1, &rename_list, list) { | ||
| 761 | ubi_close_volume(re->desc); | ||
| 762 | list_del(&re->list); | ||
| 763 | kfree(re); | ||
| 764 | } | ||
| 765 | return err; | ||
| 766 | } | ||
| 767 | |||
| 603 | static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | 768 | static int ubi_cdev_ioctl(struct inode *inode, struct file *file, |
| 604 | unsigned int cmd, unsigned long arg) | 769 | unsigned int cmd, unsigned long arg) |
| 605 | { | 770 | { |
| @@ -621,19 +786,18 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 621 | { | 786 | { |
| 622 | struct ubi_mkvol_req req; | 787 | struct ubi_mkvol_req req; |
| 623 | 788 | ||
| 624 | dbg_msg("create volume"); | 789 | dbg_gen("create volume"); |
| 625 | err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); | 790 | err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req)); |
| 626 | if (err) { | 791 | if (err) { |
| 627 | err = -EFAULT; | 792 | err = -EFAULT; |
| 628 | break; | 793 | break; |
| 629 | } | 794 | } |
| 630 | 795 | ||
| 796 | req.name[req.name_len] = '\0'; | ||
| 631 | err = verify_mkvol_req(ubi, &req); | 797 | err = verify_mkvol_req(ubi, &req); |
| 632 | if (err) | 798 | if (err) |
| 633 | break; | 799 | break; |
| 634 | 800 | ||
| 635 | req.name[req.name_len] = '\0'; | ||
| 636 | |||
| 637 | mutex_lock(&ubi->volumes_mutex); | 801 | mutex_lock(&ubi->volumes_mutex); |
| 638 | err = ubi_create_volume(ubi, &req); | 802 | err = ubi_create_volume(ubi, &req); |
| 639 | mutex_unlock(&ubi->volumes_mutex); | 803 | mutex_unlock(&ubi->volumes_mutex); |
| @@ -652,7 +816,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 652 | { | 816 | { |
| 653 | int vol_id; | 817 | int vol_id; |
| 654 | 818 | ||
| 655 | dbg_msg("remove volume"); | 819 | dbg_gen("remove volume"); |
| 656 | err = get_user(vol_id, (__user int32_t *)argp); | 820 | err = get_user(vol_id, (__user int32_t *)argp); |
| 657 | if (err) { | 821 | if (err) { |
| 658 | err = -EFAULT; | 822 | err = -EFAULT; |
| @@ -666,7 +830,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 666 | } | 830 | } |
| 667 | 831 | ||
| 668 | mutex_lock(&ubi->volumes_mutex); | 832 | mutex_lock(&ubi->volumes_mutex); |
| 669 | err = ubi_remove_volume(desc); | 833 | err = ubi_remove_volume(desc, 0); |
| 670 | mutex_unlock(&ubi->volumes_mutex); | 834 | mutex_unlock(&ubi->volumes_mutex); |
| 671 | 835 | ||
| 672 | /* | 836 | /* |
| @@ -685,7 +849,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 685 | uint64_t tmp; | 849 | uint64_t tmp; |
| 686 | struct ubi_rsvol_req req; | 850 | struct ubi_rsvol_req req; |
| 687 | 851 | ||
| 688 | dbg_msg("re-size volume"); | 852 | dbg_gen("re-size volume"); |
| 689 | err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); | 853 | err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req)); |
| 690 | if (err) { | 854 | if (err) { |
| 691 | err = -EFAULT; | 855 | err = -EFAULT; |
| @@ -713,6 +877,32 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 713 | break; | 877 | break; |
| 714 | } | 878 | } |
| 715 | 879 | ||
| 880 | /* Re-name volumes command */ | ||
| 881 | case UBI_IOCRNVOL: | ||
| 882 | { | ||
| 883 | struct ubi_rnvol_req *req; | ||
| 884 | |||
| 885 | dbg_msg("re-name volumes"); | ||
| 886 | req = kmalloc(sizeof(struct ubi_rnvol_req), GFP_KERNEL); | ||
| 887 | if (!req) { | ||
| 888 | err = -ENOMEM; | ||
| 889 | break; | ||
| 890 | }; | ||
| 891 | |||
| 892 | err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req)); | ||
| 893 | if (err) { | ||
| 894 | err = -EFAULT; | ||
| 895 | kfree(req); | ||
| 896 | break; | ||
| 897 | } | ||
| 898 | |||
| 899 | mutex_lock(&ubi->mult_mutex); | ||
| 900 | err = rename_volumes(ubi, req); | ||
| 901 | mutex_unlock(&ubi->mult_mutex); | ||
| 902 | kfree(req); | ||
| 903 | break; | ||
| 904 | } | ||
| 905 | |||
| 716 | default: | 906 | default: |
| 717 | err = -ENOTTY; | 907 | err = -ENOTTY; |
| 718 | break; | 908 | break; |
| @@ -738,7 +928,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 738 | struct ubi_attach_req req; | 928 | struct ubi_attach_req req; |
| 739 | struct mtd_info *mtd; | 929 | struct mtd_info *mtd; |
| 740 | 930 | ||
| 741 | dbg_msg("attach MTD device"); | 931 | dbg_gen("attach MTD device"); |
| 742 | err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req)); | 932 | err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req)); |
| 743 | if (err) { | 933 | if (err) { |
| 744 | err = -EFAULT; | 934 | err = -EFAULT; |
| @@ -778,7 +968,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 778 | { | 968 | { |
| 779 | int ubi_num; | 969 | int ubi_num; |
| 780 | 970 | ||
| 781 | dbg_msg("dettach MTD device"); | 971 | dbg_gen("dettach MTD device"); |
| 782 | err = get_user(ubi_num, (__user int32_t *)argp); | 972 | err = get_user(ubi_num, (__user int32_t *)argp); |
| 783 | if (err) { | 973 | if (err) { |
| 784 | err = -EFAULT; | 974 | err = -EFAULT; |
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 56956ec2845f..c0ed60e8ade9 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | * changes. | 24 | * changes. |
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG | 27 | #ifdef CONFIG_MTD_UBI_DEBUG |
| 28 | 28 | ||
| 29 | #include "ubi.h" | 29 | #include "ubi.h" |
| 30 | 30 | ||
| @@ -34,14 +34,19 @@ | |||
| 34 | */ | 34 | */ |
| 35 | void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) | 35 | void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) |
| 36 | { | 36 | { |
| 37 | dbg_msg("erase counter header dump:"); | 37 | printk(KERN_DEBUG "Erase counter header dump:\n"); |
| 38 | dbg_msg("magic %#08x", be32_to_cpu(ec_hdr->magic)); | 38 | printk(KERN_DEBUG "\tmagic %#08x\n", |
| 39 | dbg_msg("version %d", (int)ec_hdr->version); | 39 | be32_to_cpu(ec_hdr->magic)); |
| 40 | dbg_msg("ec %llu", (long long)be64_to_cpu(ec_hdr->ec)); | 40 | printk(KERN_DEBUG "\tversion %d\n", (int)ec_hdr->version); |
| 41 | dbg_msg("vid_hdr_offset %d", be32_to_cpu(ec_hdr->vid_hdr_offset)); | 41 | printk(KERN_DEBUG "\tec %llu\n", |
| 42 | dbg_msg("data_offset %d", be32_to_cpu(ec_hdr->data_offset)); | 42 | (long long)be64_to_cpu(ec_hdr->ec)); |
| 43 | dbg_msg("hdr_crc %#08x", be32_to_cpu(ec_hdr->hdr_crc)); | 43 | printk(KERN_DEBUG "\tvid_hdr_offset %d\n", |
| 44 | dbg_msg("erase counter header hexdump:"); | 44 | be32_to_cpu(ec_hdr->vid_hdr_offset)); |
| 45 | printk(KERN_DEBUG "\tdata_offset %d\n", | ||
| 46 | be32_to_cpu(ec_hdr->data_offset)); | ||
| 47 | printk(KERN_DEBUG "\thdr_crc %#08x\n", | ||
| 48 | be32_to_cpu(ec_hdr->hdr_crc)); | ||
| 49 | printk(KERN_DEBUG "erase counter header hexdump:\n"); | ||
| 45 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | 50 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, |
| 46 | ec_hdr, UBI_EC_HDR_SIZE, 1); | 51 | ec_hdr, UBI_EC_HDR_SIZE, 1); |
| 47 | } | 52 | } |
| @@ -52,22 +57,23 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) | |||
| 52 | */ | 57 | */ |
| 53 | void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) | 58 | void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) |
| 54 | { | 59 | { |
| 55 | dbg_msg("volume identifier header dump:"); | 60 | printk(KERN_DEBUG "Volume identifier header dump:\n"); |
| 56 | dbg_msg("magic %08x", be32_to_cpu(vid_hdr->magic)); | 61 | printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic)); |
| 57 | dbg_msg("version %d", (int)vid_hdr->version); | 62 | printk(KERN_DEBUG "\tversion %d\n", (int)vid_hdr->version); |
| 58 | dbg_msg("vol_type %d", (int)vid_hdr->vol_type); | 63 | printk(KERN_DEBUG "\tvol_type %d\n", (int)vid_hdr->vol_type); |
| 59 | dbg_msg("copy_flag %d", (int)vid_hdr->copy_flag); | 64 | printk(KERN_DEBUG "\tcopy_flag %d\n", (int)vid_hdr->copy_flag); |
| 60 | dbg_msg("compat %d", (int)vid_hdr->compat); | 65 | printk(KERN_DEBUG "\tcompat %d\n", (int)vid_hdr->compat); |
| 61 | dbg_msg("vol_id %d", be32_to_cpu(vid_hdr->vol_id)); | 66 | printk(KERN_DEBUG "\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id)); |
| 62 | dbg_msg("lnum %d", be32_to_cpu(vid_hdr->lnum)); | 67 | printk(KERN_DEBUG "\tlnum %d\n", be32_to_cpu(vid_hdr->lnum)); |
| 63 | dbg_msg("leb_ver %u", be32_to_cpu(vid_hdr->leb_ver)); | 68 | printk(KERN_DEBUG "\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size)); |
| 64 | dbg_msg("data_size %d", be32_to_cpu(vid_hdr->data_size)); | 69 | printk(KERN_DEBUG "\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs)); |
| 65 | dbg_msg("used_ebs %d", be32_to_cpu(vid_hdr->used_ebs)); | 70 | printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad)); |
| 66 | dbg_msg("data_pad %d", be32_to_cpu(vid_hdr->data_pad)); | 71 | printk(KERN_DEBUG "\tsqnum %llu\n", |
| 67 | dbg_msg("sqnum %llu", | ||
| 68 | (unsigned long long)be64_to_cpu(vid_hdr->sqnum)); | 72 | (unsigned long long)be64_to_cpu(vid_hdr->sqnum)); |
| 69 | dbg_msg("hdr_crc %08x", be32_to_cpu(vid_hdr->hdr_crc)); | 73 | printk(KERN_DEBUG "\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc)); |
| 70 | dbg_msg("volume identifier header hexdump:"); | 74 | printk(KERN_DEBUG "Volume identifier header hexdump:\n"); |
| 75 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
| 76 | vid_hdr, UBI_VID_HDR_SIZE, 1); | ||
| 71 | } | 77 | } |
| 72 | 78 | ||
| 73 | /** | 79 | /** |
| @@ -76,27 +82,27 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) | |||
| 76 | */ | 82 | */ |
| 77 | void ubi_dbg_dump_vol_info(const struct ubi_volume *vol) | 83 | void ubi_dbg_dump_vol_info(const struct ubi_volume *vol) |
| 78 | { | 84 | { |
| 79 | dbg_msg("volume information dump:"); | 85 | printk(KERN_DEBUG "Volume information dump:\n"); |
| 80 | dbg_msg("vol_id %d", vol->vol_id); | 86 | printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id); |
| 81 | dbg_msg("reserved_pebs %d", vol->reserved_pebs); | 87 | printk(KERN_DEBUG "\treserved_pebs %d\n", vol->reserved_pebs); |
| 82 | dbg_msg("alignment %d", vol->alignment); | 88 | printk(KERN_DEBUG "\talignment %d\n", vol->alignment); |
| 83 | dbg_msg("data_pad %d", vol->data_pad); | 89 | printk(KERN_DEBUG "\tdata_pad %d\n", vol->data_pad); |
| 84 | dbg_msg("vol_type %d", vol->vol_type); | 90 | printk(KERN_DEBUG "\tvol_type %d\n", vol->vol_type); |
| 85 | dbg_msg("name_len %d", vol->name_len); | 91 | printk(KERN_DEBUG "\tname_len %d\n", vol->name_len); |
| 86 | dbg_msg("usable_leb_size %d", vol->usable_leb_size); | 92 | printk(KERN_DEBUG "\tusable_leb_size %d\n", vol->usable_leb_size); |
| 87 | dbg_msg("used_ebs %d", vol->used_ebs); | 93 | printk(KERN_DEBUG "\tused_ebs %d\n", vol->used_ebs); |
| 88 | dbg_msg("used_bytes %lld", vol->used_bytes); | 94 | printk(KERN_DEBUG "\tused_bytes %lld\n", vol->used_bytes); |
| 89 | dbg_msg("last_eb_bytes %d", vol->last_eb_bytes); | 95 | printk(KERN_DEBUG "\tlast_eb_bytes %d\n", vol->last_eb_bytes); |
| 90 | dbg_msg("corrupted %d", vol->corrupted); | 96 | printk(KERN_DEBUG "\tcorrupted %d\n", vol->corrupted); |
| 91 | dbg_msg("upd_marker %d", vol->upd_marker); | 97 | printk(KERN_DEBUG "\tupd_marker %d\n", vol->upd_marker); |
| 92 | 98 | ||
| 93 | if (vol->name_len <= UBI_VOL_NAME_MAX && | 99 | if (vol->name_len <= UBI_VOL_NAME_MAX && |
| 94 | strnlen(vol->name, vol->name_len + 1) == vol->name_len) { | 100 | strnlen(vol->name, vol->name_len + 1) == vol->name_len) { |
| 95 | dbg_msg("name %s", vol->name); | 101 | printk(KERN_DEBUG "\tname %s\n", vol->name); |
| 96 | } else { | 102 | } else { |
| 97 | dbg_msg("the 1st 5 characters of the name: %c%c%c%c%c", | 103 | printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n", |
| 98 | vol->name[0], vol->name[1], vol->name[2], | 104 | vol->name[0], vol->name[1], vol->name[2], |
| 99 | vol->name[3], vol->name[4]); | 105 | vol->name[3], vol->name[4]); |
| 100 | } | 106 | } |
| 101 | } | 107 | } |
| 102 | 108 | ||
| @@ -109,28 +115,29 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) | |||
| 109 | { | 115 | { |
| 110 | int name_len = be16_to_cpu(r->name_len); | 116 | int name_len = be16_to_cpu(r->name_len); |
| 111 | 117 | ||
| 112 | dbg_msg("volume table record %d dump:", idx); | 118 | printk(KERN_DEBUG "Volume table record %d dump:\n", idx); |
| 113 | dbg_msg("reserved_pebs %d", be32_to_cpu(r->reserved_pebs)); | 119 | printk(KERN_DEBUG "\treserved_pebs %d\n", |
| 114 | dbg_msg("alignment %d", be32_to_cpu(r->alignment)); | 120 | be32_to_cpu(r->reserved_pebs)); |
| 115 | dbg_msg("data_pad %d", be32_to_cpu(r->data_pad)); | 121 | printk(KERN_DEBUG "\talignment %d\n", be32_to_cpu(r->alignment)); |
| 116 | dbg_msg("vol_type %d", (int)r->vol_type); | 122 | printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(r->data_pad)); |
| 117 | dbg_msg("upd_marker %d", (int)r->upd_marker); | 123 | printk(KERN_DEBUG "\tvol_type %d\n", (int)r->vol_type); |
| 118 | dbg_msg("name_len %d", name_len); | 124 | printk(KERN_DEBUG "\tupd_marker %d\n", (int)r->upd_marker); |
| 125 | printk(KERN_DEBUG "\tname_len %d\n", name_len); | ||
| 119 | 126 | ||
| 120 | if (r->name[0] == '\0') { | 127 | if (r->name[0] == '\0') { |
| 121 | dbg_msg("name NULL"); | 128 | printk(KERN_DEBUG "\tname NULL\n"); |
| 122 | return; | 129 | return; |
| 123 | } | 130 | } |
| 124 | 131 | ||
| 125 | if (name_len <= UBI_VOL_NAME_MAX && | 132 | if (name_len <= UBI_VOL_NAME_MAX && |
| 126 | strnlen(&r->name[0], name_len + 1) == name_len) { | 133 | strnlen(&r->name[0], name_len + 1) == name_len) { |
| 127 | dbg_msg("name %s", &r->name[0]); | 134 | printk(KERN_DEBUG "\tname %s\n", &r->name[0]); |
| 128 | } else { | 135 | } else { |
| 129 | dbg_msg("1st 5 characters of the name: %c%c%c%c%c", | 136 | printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n", |
| 130 | r->name[0], r->name[1], r->name[2], r->name[3], | 137 | r->name[0], r->name[1], r->name[2], r->name[3], |
| 131 | r->name[4]); | 138 | r->name[4]); |
| 132 | } | 139 | } |
| 133 | dbg_msg("crc %#08x", be32_to_cpu(r->crc)); | 140 | printk(KERN_DEBUG "\tcrc %#08x\n", be32_to_cpu(r->crc)); |
| 134 | } | 141 | } |
| 135 | 142 | ||
| 136 | /** | 143 | /** |
| @@ -139,15 +146,15 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) | |||
| 139 | */ | 146 | */ |
| 140 | void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) | 147 | void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) |
| 141 | { | 148 | { |
| 142 | dbg_msg("volume scanning information dump:"); | 149 | printk(KERN_DEBUG "Volume scanning information dump:\n"); |
| 143 | dbg_msg("vol_id %d", sv->vol_id); | 150 | printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id); |
| 144 | dbg_msg("highest_lnum %d", sv->highest_lnum); | 151 | printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum); |
| 145 | dbg_msg("leb_count %d", sv->leb_count); | 152 | printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count); |
| 146 | dbg_msg("compat %d", sv->compat); | 153 | printk(KERN_DEBUG "\tcompat %d\n", sv->compat); |
| 147 | dbg_msg("vol_type %d", sv->vol_type); | 154 | printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type); |
| 148 | dbg_msg("used_ebs %d", sv->used_ebs); | 155 | printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs); |
| 149 | dbg_msg("last_data_size %d", sv->last_data_size); | 156 | printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size); |
| 150 | dbg_msg("data_pad %d", sv->data_pad); | 157 | printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad); |
| 151 | } | 158 | } |
| 152 | 159 | ||
| 153 | /** | 160 | /** |
| @@ -157,14 +164,13 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) | |||
| 157 | */ | 164 | */ |
| 158 | void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type) | 165 | void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type) |
| 159 | { | 166 | { |
| 160 | dbg_msg("eraseblock scanning information dump:"); | 167 | printk(KERN_DEBUG "eraseblock scanning information dump:\n"); |
| 161 | dbg_msg("ec %d", seb->ec); | 168 | printk(KERN_DEBUG "\tec %d\n", seb->ec); |
| 162 | dbg_msg("pnum %d", seb->pnum); | 169 | printk(KERN_DEBUG "\tpnum %d\n", seb->pnum); |
| 163 | if (type == 0) { | 170 | if (type == 0) { |
| 164 | dbg_msg("lnum %d", seb->lnum); | 171 | printk(KERN_DEBUG "\tlnum %d\n", seb->lnum); |
| 165 | dbg_msg("scrub %d", seb->scrub); | 172 | printk(KERN_DEBUG "\tscrub %d\n", seb->scrub); |
| 166 | dbg_msg("sqnum %llu", seb->sqnum); | 173 | printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum); |
| 167 | dbg_msg("leb_ver %u", seb->leb_ver); | ||
| 168 | } | 174 | } |
| 169 | } | 175 | } |
| 170 | 176 | ||
| @@ -176,16 +182,16 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) | |||
| 176 | { | 182 | { |
| 177 | char nm[17]; | 183 | char nm[17]; |
| 178 | 184 | ||
| 179 | dbg_msg("volume creation request dump:"); | 185 | printk(KERN_DEBUG "Volume creation request dump:\n"); |
| 180 | dbg_msg("vol_id %d", req->vol_id); | 186 | printk(KERN_DEBUG "\tvol_id %d\n", req->vol_id); |
| 181 | dbg_msg("alignment %d", req->alignment); | 187 | printk(KERN_DEBUG "\talignment %d\n", req->alignment); |
| 182 | dbg_msg("bytes %lld", (long long)req->bytes); | 188 | printk(KERN_DEBUG "\tbytes %lld\n", (long long)req->bytes); |
| 183 | dbg_msg("vol_type %d", req->vol_type); | 189 | printk(KERN_DEBUG "\tvol_type %d\n", req->vol_type); |
| 184 | dbg_msg("name_len %d", req->name_len); | 190 | printk(KERN_DEBUG "\tname_len %d\n", req->name_len); |
| 185 | 191 | ||
| 186 | memcpy(nm, req->name, 16); | 192 | memcpy(nm, req->name, 16); |
| 187 | nm[16] = 0; | 193 | nm[16] = 0; |
| 188 | dbg_msg("the 1st 16 characters of the name: %s", nm); | 194 | printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm); |
| 189 | } | 195 | } |
| 190 | 196 | ||
| 191 | #endif /* CONFIG_MTD_UBI_DEBUG_MSG */ | 197 | #endif /* CONFIG_MTD_UBI_DEBUG */ |
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 8ea99d8c9e1f..78e914d23ece 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
| @@ -24,21 +24,16 @@ | |||
| 24 | #ifdef CONFIG_MTD_UBI_DEBUG | 24 | #ifdef CONFIG_MTD_UBI_DEBUG |
| 25 | #include <linux/random.h> | 25 | #include <linux/random.h> |
| 26 | 26 | ||
| 27 | #define ubi_assert(expr) BUG_ON(!(expr)) | ||
| 28 | #define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__) | 27 | #define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__) |
| 29 | #else | ||
| 30 | #define ubi_assert(expr) ({}) | ||
| 31 | #define dbg_err(fmt, ...) ({}) | ||
| 32 | #endif | ||
| 33 | 28 | ||
| 34 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | 29 | #define ubi_assert(expr) do { \ |
| 35 | #define DBG_DISABLE_BGT 1 | 30 | if (unlikely(!(expr))) { \ |
| 36 | #else | 31 | printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \ |
| 37 | #define DBG_DISABLE_BGT 0 | 32 | __func__, __LINE__, current->pid); \ |
| 38 | #endif | 33 | ubi_dbg_dump_stack(); \ |
| 34 | } \ | ||
| 35 | } while (0) | ||
| 39 | 36 | ||
| 40 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG | ||
| 41 | /* Generic debugging message */ | ||
| 42 | #define dbg_msg(fmt, ...) \ | 37 | #define dbg_msg(fmt, ...) \ |
| 43 | printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \ | 38 | printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \ |
| 44 | current->pid, __func__, ##__VA_ARGS__) | 39 | current->pid, __func__, ##__VA_ARGS__) |
| @@ -61,36 +56,29 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv); | |||
| 61 | void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type); | 56 | void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type); |
| 62 | void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); | 57 | void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); |
| 63 | 58 | ||
| 59 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG | ||
| 60 | /* General debugging messages */ | ||
| 61 | #define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) | ||
| 64 | #else | 62 | #else |
| 65 | 63 | #define dbg_gen(fmt, ...) ({}) | |
| 66 | #define dbg_msg(fmt, ...) ({}) | 64 | #endif |
| 67 | #define ubi_dbg_dump_stack() ({}) | ||
| 68 | #define ubi_dbg_dump_ec_hdr(ec_hdr) ({}) | ||
| 69 | #define ubi_dbg_dump_vid_hdr(vid_hdr) ({}) | ||
| 70 | #define ubi_dbg_dump_vol_info(vol) ({}) | ||
| 71 | #define ubi_dbg_dump_vtbl_record(r, idx) ({}) | ||
| 72 | #define ubi_dbg_dump_sv(sv) ({}) | ||
| 73 | #define ubi_dbg_dump_seb(seb, type) ({}) | ||
| 74 | #define ubi_dbg_dump_mkvol_req(req) ({}) | ||
| 75 | |||
| 76 | #endif /* CONFIG_MTD_UBI_DEBUG_MSG */ | ||
| 77 | 65 | ||
| 78 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA | 66 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA |
| 79 | /* Messages from the eraseblock association unit */ | 67 | /* Messages from the eraseblock association sub-system */ |
| 80 | #define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) | 68 | #define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) |
| 81 | #else | 69 | #else |
| 82 | #define dbg_eba(fmt, ...) ({}) | 70 | #define dbg_eba(fmt, ...) ({}) |
| 83 | #endif | 71 | #endif |
| 84 | 72 | ||
| 85 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL | 73 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL |
| 86 | /* Messages from the wear-leveling unit */ | 74 | /* Messages from the wear-leveling sub-system */ |
| 87 | #define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) | 75 | #define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) |
| 88 | #else | 76 | #else |
| 89 | #define dbg_wl(fmt, ...) ({}) | 77 | #define dbg_wl(fmt, ...) ({}) |
| 90 | #endif | 78 | #endif |
| 91 | 79 | ||
| 92 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO | 80 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO |
| 93 | /* Messages from the input/output unit */ | 81 | /* Messages from the input/output sub-system */ |
| 94 | #define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) | 82 | #define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) |
| 95 | #else | 83 | #else |
| 96 | #define dbg_io(fmt, ...) ({}) | 84 | #define dbg_io(fmt, ...) ({}) |
| @@ -105,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); | |||
| 105 | #define UBI_IO_DEBUG 0 | 93 | #define UBI_IO_DEBUG 0 |
| 106 | #endif | 94 | #endif |
| 107 | 95 | ||
| 96 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | ||
| 97 | #define DBG_DISABLE_BGT 1 | ||
| 98 | #else | ||
| 99 | #define DBG_DISABLE_BGT 0 | ||
| 100 | #endif | ||
| 101 | |||
| 108 | #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS | 102 | #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS |
| 109 | /** | 103 | /** |
| 110 | * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip. | 104 | * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip. |
| @@ -149,4 +143,30 @@ static inline int ubi_dbg_is_erase_failure(void) | |||
| 149 | #define ubi_dbg_is_erase_failure() 0 | 143 | #define ubi_dbg_is_erase_failure() 0 |
| 150 | #endif | 144 | #endif |
| 151 | 145 | ||
| 146 | #else | ||
| 147 | |||
| 148 | #define ubi_assert(expr) ({}) | ||
| 149 | #define dbg_err(fmt, ...) ({}) | ||
| 150 | #define dbg_msg(fmt, ...) ({}) | ||
| 151 | #define dbg_gen(fmt, ...) ({}) | ||
| 152 | #define dbg_eba(fmt, ...) ({}) | ||
| 153 | #define dbg_wl(fmt, ...) ({}) | ||
| 154 | #define dbg_io(fmt, ...) ({}) | ||
| 155 | #define dbg_bld(fmt, ...) ({}) | ||
| 156 | #define ubi_dbg_dump_stack() ({}) | ||
| 157 | #define ubi_dbg_dump_ec_hdr(ec_hdr) ({}) | ||
| 158 | #define ubi_dbg_dump_vid_hdr(vid_hdr) ({}) | ||
| 159 | #define ubi_dbg_dump_vol_info(vol) ({}) | ||
| 160 | #define ubi_dbg_dump_vtbl_record(r, idx) ({}) | ||
| 161 | #define ubi_dbg_dump_sv(sv) ({}) | ||
| 162 | #define ubi_dbg_dump_seb(seb, type) ({}) | ||
| 163 | #define ubi_dbg_dump_mkvol_req(req) ({}) | ||
| 164 | |||
| 165 | #define UBI_IO_DEBUG 0 | ||
| 166 | #define DBG_DISABLE_BGT 0 | ||
| 167 | #define ubi_dbg_is_bitflip() 0 | ||
| 168 | #define ubi_dbg_is_write_failure() 0 | ||
| 169 | #define ubi_dbg_is_erase_failure() 0 | ||
| 170 | |||
| 171 | #endif /* !CONFIG_MTD_UBI_DEBUG */ | ||
| 152 | #endif /* !__UBI_DEBUG_H__ */ | 172 | #endif /* !__UBI_DEBUG_H__ */ |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 7ce91ca742b1..e04bcf1dff87 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
| @@ -19,20 +19,20 @@ | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| 22 | * The UBI Eraseblock Association (EBA) unit. | 22 | * The UBI Eraseblock Association (EBA) sub-system. |
| 23 | * | 23 | * |
| 24 | * This unit is responsible for I/O to/from logical eraseblock. | 24 | * This sub-system is responsible for I/O to/from logical eraseblock. |
| 25 | * | 25 | * |
| 26 | * Although in this implementation the EBA table is fully kept and managed in | 26 | * Although in this implementation the EBA table is fully kept and managed in |
| 27 | * RAM, which assumes poor scalability, it might be (partially) maintained on | 27 | * RAM, which assumes poor scalability, it might be (partially) maintained on |
| 28 | * flash in future implementations. | 28 | * flash in future implementations. |
| 29 | * | 29 | * |
| 30 | * The EBA unit implements per-logical eraseblock locking. Before accessing a | 30 | * The EBA sub-system implements per-logical eraseblock locking. Before |
| 31 | * logical eraseblock it is locked for reading or writing. The per-logical | 31 | * accessing a logical eraseblock it is locked for reading or writing. The |
| 32 | * eraseblock locking is implemented by means of the lock tree. The lock tree | 32 | * per-logical eraseblock locking is implemented by means of the lock tree. The |
| 33 | * is an RB-tree which refers all the currently locked logical eraseblocks. The | 33 | * lock tree is an RB-tree which refers all the currently locked logical |
| 34 | * lock tree elements are &struct ubi_ltree_entry objects. They are indexed by | 34 | * eraseblocks. The lock tree elements are &struct ubi_ltree_entry objects. |
| 35 | * (@vol_id, @lnum) pairs. | 35 | * They are indexed by (@vol_id, @lnum) pairs. |
| 36 | * | 36 | * |
| 37 | * EBA also maintains the global sequence counter which is incremented each | 37 | * EBA also maintains the global sequence counter which is incremented each |
| 38 | * time a logical eraseblock is mapped to a physical eraseblock and it is | 38 | * time a logical eraseblock is mapped to a physical eraseblock and it is |
| @@ -189,9 +189,7 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi, | |||
| 189 | le->users += 1; | 189 | le->users += 1; |
| 190 | spin_unlock(&ubi->ltree_lock); | 190 | spin_unlock(&ubi->ltree_lock); |
| 191 | 191 | ||
| 192 | if (le_free) | 192 | kfree(le_free); |
| 193 | kfree(le_free); | ||
| 194 | |||
| 195 | return le; | 193 | return le; |
| 196 | } | 194 | } |
| 197 | 195 | ||
| @@ -223,22 +221,18 @@ static int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum) | |||
| 223 | */ | 221 | */ |
| 224 | static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) | 222 | static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) |
| 225 | { | 223 | { |
| 226 | int free = 0; | ||
| 227 | struct ubi_ltree_entry *le; | 224 | struct ubi_ltree_entry *le; |
| 228 | 225 | ||
| 229 | spin_lock(&ubi->ltree_lock); | 226 | spin_lock(&ubi->ltree_lock); |
| 230 | le = ltree_lookup(ubi, vol_id, lnum); | 227 | le = ltree_lookup(ubi, vol_id, lnum); |
| 231 | le->users -= 1; | 228 | le->users -= 1; |
| 232 | ubi_assert(le->users >= 0); | 229 | ubi_assert(le->users >= 0); |
| 230 | up_read(&le->mutex); | ||
| 233 | if (le->users == 0) { | 231 | if (le->users == 0) { |
| 234 | rb_erase(&le->rb, &ubi->ltree); | 232 | rb_erase(&le->rb, &ubi->ltree); |
| 235 | free = 1; | 233 | kfree(le); |
| 236 | } | 234 | } |
| 237 | spin_unlock(&ubi->ltree_lock); | 235 | spin_unlock(&ubi->ltree_lock); |
| 238 | |||
| 239 | up_read(&le->mutex); | ||
| 240 | if (free) | ||
| 241 | kfree(le); | ||
| 242 | } | 236 | } |
| 243 | 237 | ||
| 244 | /** | 238 | /** |
| @@ -274,7 +268,6 @@ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum) | |||
| 274 | */ | 268 | */ |
| 275 | static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | 269 | static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) |
| 276 | { | 270 | { |
| 277 | int free; | ||
| 278 | struct ubi_ltree_entry *le; | 271 | struct ubi_ltree_entry *le; |
| 279 | 272 | ||
| 280 | le = ltree_add_entry(ubi, vol_id, lnum); | 273 | le = ltree_add_entry(ubi, vol_id, lnum); |
| @@ -289,12 +282,9 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | |||
| 289 | ubi_assert(le->users >= 0); | 282 | ubi_assert(le->users >= 0); |
| 290 | if (le->users == 0) { | 283 | if (le->users == 0) { |
| 291 | rb_erase(&le->rb, &ubi->ltree); | 284 | rb_erase(&le->rb, &ubi->ltree); |
| 292 | free = 1; | ||
| 293 | } else | ||
| 294 | free = 0; | ||
| 295 | spin_unlock(&ubi->ltree_lock); | ||
| 296 | if (free) | ||
| 297 | kfree(le); | 285 | kfree(le); |
| 286 | } | ||
| 287 | spin_unlock(&ubi->ltree_lock); | ||
| 298 | 288 | ||
| 299 | return 1; | 289 | return 1; |
| 300 | } | 290 | } |
| @@ -307,23 +297,18 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) | |||
| 307 | */ | 297 | */ |
| 308 | static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) | 298 | static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) |
| 309 | { | 299 | { |
| 310 | int free; | ||
| 311 | struct ubi_ltree_entry *le; | 300 | struct ubi_ltree_entry *le; |
| 312 | 301 | ||
| 313 | spin_lock(&ubi->ltree_lock); | 302 | spin_lock(&ubi->ltree_lock); |
| 314 | le = ltree_lookup(ubi, vol_id, lnum); | 303 | le = ltree_lookup(ubi, vol_id, lnum); |
| 315 | le->users -= 1; | 304 | le->users -= 1; |
| 316 | ubi_assert(le->users >= 0); | 305 | ubi_assert(le->users >= 0); |
| 306 | up_write(&le->mutex); | ||
| 317 | if (le->users == 0) { | 307 | if (le->users == 0) { |
| 318 | rb_erase(&le->rb, &ubi->ltree); | 308 | rb_erase(&le->rb, &ubi->ltree); |
| 319 | free = 1; | ||
| 320 | } else | ||
| 321 | free = 0; | ||
| 322 | spin_unlock(&ubi->ltree_lock); | ||
| 323 | |||
| 324 | up_write(&le->mutex); | ||
| 325 | if (free) | ||
| 326 | kfree(le); | 309 | kfree(le); |
| 310 | } | ||
| 311 | spin_unlock(&ubi->ltree_lock); | ||
| 327 | } | 312 | } |
| 328 | 313 | ||
| 329 | /** | 314 | /** |
| @@ -516,9 +501,8 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, | |||
| 516 | struct ubi_vid_hdr *vid_hdr; | 501 | struct ubi_vid_hdr *vid_hdr; |
| 517 | 502 | ||
| 518 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); | 503 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); |
| 519 | if (!vid_hdr) { | 504 | if (!vid_hdr) |
| 520 | return -ENOMEM; | 505 | return -ENOMEM; |
| 521 | } | ||
| 522 | 506 | ||
| 523 | mutex_lock(&ubi->buf_mutex); | 507 | mutex_lock(&ubi->buf_mutex); |
| 524 | 508 | ||
| @@ -752,7 +736,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 752 | /* If this is the last LEB @len may be unaligned */ | 736 | /* If this is the last LEB @len may be unaligned */ |
| 753 | len = ALIGN(data_size, ubi->min_io_size); | 737 | len = ALIGN(data_size, ubi->min_io_size); |
| 754 | else | 738 | else |
| 755 | ubi_assert(len % ubi->min_io_size == 0); | 739 | ubi_assert(!(len & (ubi->min_io_size - 1))); |
| 756 | 740 | ||
| 757 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); | 741 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); |
| 758 | if (!vid_hdr) | 742 | if (!vid_hdr) |
| @@ -919,7 +903,7 @@ retry: | |||
| 919 | } | 903 | } |
| 920 | 904 | ||
| 921 | if (vol->eba_tbl[lnum] >= 0) { | 905 | if (vol->eba_tbl[lnum] >= 0) { |
| 922 | err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1); | 906 | err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0); |
| 923 | if (err) | 907 | if (err) |
| 924 | goto out_leb_unlock; | 908 | goto out_leb_unlock; |
| 925 | } | 909 | } |
| @@ -1141,7 +1125,7 @@ out_unlock_leb: | |||
| 1141 | } | 1125 | } |
| 1142 | 1126 | ||
| 1143 | /** | 1127 | /** |
| 1144 | * ubi_eba_init_scan - initialize the EBA unit using scanning information. | 1128 | * ubi_eba_init_scan - initialize the EBA sub-system using scanning information. |
| 1145 | * @ubi: UBI device description object | 1129 | * @ubi: UBI device description object |
| 1146 | * @si: scanning information | 1130 | * @si: scanning information |
| 1147 | * | 1131 | * |
| @@ -1156,7 +1140,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
| 1156 | struct ubi_scan_leb *seb; | 1140 | struct ubi_scan_leb *seb; |
| 1157 | struct rb_node *rb; | 1141 | struct rb_node *rb; |
| 1158 | 1142 | ||
| 1159 | dbg_eba("initialize EBA unit"); | 1143 | dbg_eba("initialize EBA sub-system"); |
| 1160 | 1144 | ||
| 1161 | spin_lock_init(&ubi->ltree_lock); | 1145 | spin_lock_init(&ubi->ltree_lock); |
| 1162 | mutex_init(&ubi->alc_mutex); | 1146 | mutex_init(&ubi->alc_mutex); |
| @@ -1222,7 +1206,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
| 1222 | ubi->rsvd_pebs += ubi->beb_rsvd_pebs; | 1206 | ubi->rsvd_pebs += ubi->beb_rsvd_pebs; |
| 1223 | } | 1207 | } |
| 1224 | 1208 | ||
| 1225 | dbg_eba("EBA unit is initialized"); | 1209 | dbg_eba("EBA sub-system is initialized"); |
| 1226 | return 0; | 1210 | return 0; |
| 1227 | 1211 | ||
| 1228 | out_free: | 1212 | out_free: |
| @@ -1233,20 +1217,3 @@ out_free: | |||
| 1233 | } | 1217 | } |
| 1234 | return err; | 1218 | return err; |
| 1235 | } | 1219 | } |
| 1236 | |||
| 1237 | /** | ||
| 1238 | * ubi_eba_close - close EBA unit. | ||
| 1239 | * @ubi: UBI device description object | ||
| 1240 | */ | ||
| 1241 | void ubi_eba_close(const struct ubi_device *ubi) | ||
| 1242 | { | ||
| 1243 | int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; | ||
| 1244 | |||
| 1245 | dbg_eba("close EBA unit"); | ||
| 1246 | |||
| 1247 | for (i = 0; i < num_volumes; i++) { | ||
| 1248 | if (!ubi->volumes[i]) | ||
| 1249 | continue; | ||
| 1250 | kfree(ubi->volumes[i]->eba_tbl); | ||
| 1251 | } | ||
| 1252 | } | ||
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index e909b390069a..605812bb0b1a 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
| @@ -111,7 +111,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 111 | struct ubi_device *ubi; | 111 | struct ubi_device *ubi; |
| 112 | uint64_t tmp = from; | 112 | uint64_t tmp = from; |
| 113 | 113 | ||
| 114 | dbg_msg("read %zd bytes from offset %lld", len, from); | 114 | dbg_gen("read %zd bytes from offset %lld", len, from); |
| 115 | 115 | ||
| 116 | if (len < 0 || from < 0 || from + len > mtd->size) | 116 | if (len < 0 || from < 0 || from + len > mtd->size) |
| 117 | return -EINVAL; | 117 | return -EINVAL; |
| @@ -162,7 +162,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 162 | struct ubi_device *ubi; | 162 | struct ubi_device *ubi; |
| 163 | uint64_t tmp = to; | 163 | uint64_t tmp = to; |
| 164 | 164 | ||
| 165 | dbg_msg("write %zd bytes to offset %lld", len, to); | 165 | dbg_gen("write %zd bytes to offset %lld", len, to); |
| 166 | 166 | ||
| 167 | if (len < 0 || to < 0 || len + to > mtd->size) | 167 | if (len < 0 || to < 0 || len + to > mtd->size) |
| 168 | return -EINVAL; | 168 | return -EINVAL; |
| @@ -215,7 +215,7 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
| 215 | struct ubi_volume *vol; | 215 | struct ubi_volume *vol; |
| 216 | struct ubi_device *ubi; | 216 | struct ubi_device *ubi; |
| 217 | 217 | ||
| 218 | dbg_msg("erase %u bytes at offset %u", instr->len, instr->addr); | 218 | dbg_gen("erase %u bytes at offset %u", instr->len, instr->addr); |
| 219 | 219 | ||
| 220 | if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize) | 220 | if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize) |
| 221 | return -EINVAL; | 221 | return -EINVAL; |
| @@ -249,8 +249,8 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
| 249 | if (err) | 249 | if (err) |
| 250 | goto out_err; | 250 | goto out_err; |
| 251 | 251 | ||
| 252 | instr->state = MTD_ERASE_DONE; | 252 | instr->state = MTD_ERASE_DONE; |
| 253 | mtd_erase_callback(instr); | 253 | mtd_erase_callback(instr); |
| 254 | return 0; | 254 | return 0; |
| 255 | 255 | ||
| 256 | out_err: | 256 | out_err: |
| @@ -299,12 +299,12 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 299 | mtd->size = vol->used_bytes; | 299 | mtd->size = vol->used_bytes; |
| 300 | 300 | ||
| 301 | if (add_mtd_device(mtd)) { | 301 | if (add_mtd_device(mtd)) { |
| 302 | ubi_err("cannot not add MTD device\n"); | 302 | ubi_err("cannot not add MTD device"); |
| 303 | kfree(mtd->name); | 303 | kfree(mtd->name); |
| 304 | return -ENFILE; | 304 | return -ENFILE; |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | dbg_msg("added mtd%d (\"%s\"), size %u, EB size %u", | 307 | dbg_gen("added mtd%d (\"%s\"), size %u, EB size %u", |
| 308 | mtd->index, mtd->name, mtd->size, mtd->erasesize); | 308 | mtd->index, mtd->name, mtd->size, mtd->erasesize); |
| 309 | return 0; | 309 | return 0; |
| 310 | } | 310 | } |
| @@ -322,7 +322,7 @@ int ubi_destroy_gluebi(struct ubi_volume *vol) | |||
| 322 | int err; | 322 | int err; |
| 323 | struct mtd_info *mtd = &vol->gluebi_mtd; | 323 | struct mtd_info *mtd = &vol->gluebi_mtd; |
| 324 | 324 | ||
| 325 | dbg_msg("remove mtd%d", mtd->index); | 325 | dbg_gen("remove mtd%d", mtd->index); |
| 326 | err = del_mtd_device(mtd); | 326 | err = del_mtd_device(mtd); |
| 327 | if (err) | 327 | if (err) |
| 328 | return err; | 328 | return err; |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 4ac11df7b048..2fb64be44f1b 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
| @@ -20,15 +20,15 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | /* | 22 | /* |
| 23 | * UBI input/output unit. | 23 | * UBI input/output sub-system. |
| 24 | * | 24 | * |
| 25 | * This unit provides a uniform way to work with all kinds of the underlying | 25 | * This sub-system provides a uniform way to work with all kinds of the |
| 26 | * MTD devices. It also implements handy functions for reading and writing UBI | 26 | * underlying MTD devices. It also implements handy functions for reading and |
| 27 | * headers. | 27 | * writing UBI headers. |
| 28 | * | 28 | * |
| 29 | * We are trying to have a paranoid mindset and not to trust to what we read | 29 | * We are trying to have a paranoid mindset and not to trust to what we read |
| 30 | * from the flash media in order to be more secure and robust. So this unit | 30 | * from the flash media in order to be more secure and robust. So this |
| 31 | * validates every single header it reads from the flash media. | 31 | * sub-system validates every single header it reads from the flash media. |
| 32 | * | 32 | * |
| 33 | * Some words about how the eraseblock headers are stored. | 33 | * Some words about how the eraseblock headers are stored. |
| 34 | * | 34 | * |
| @@ -79,11 +79,11 @@ | |||
| 79 | * 512-byte chunks, we have to allocate one more buffer and copy our VID header | 79 | * 512-byte chunks, we have to allocate one more buffer and copy our VID header |
| 80 | * to offset 448 of this buffer. | 80 | * to offset 448 of this buffer. |
| 81 | * | 81 | * |
| 82 | * The I/O unit does the following trick in order to avoid this extra copy. | 82 | * The I/O sub-system does the following trick in order to avoid this extra |
| 83 | * It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID header | 83 | * copy. It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID |
| 84 | * and returns a pointer to offset @ubi->vid_hdr_shift of this buffer. When the | 84 | * header and returns a pointer to offset @ubi->vid_hdr_shift of this buffer. |
| 85 | * VID header is being written out, it shifts the VID header pointer back and | 85 | * When the VID header is being written out, it shifts the VID header pointer |
| 86 | * writes the whole sub-page. | 86 | * back and writes the whole sub-page. |
| 87 | */ | 87 | */ |
| 88 | 88 | ||
| 89 | #include <linux/crc32.h> | 89 | #include <linux/crc32.h> |
| @@ -156,15 +156,19 @@ retry: | |||
| 156 | /* | 156 | /* |
| 157 | * -EUCLEAN is reported if there was a bit-flip which | 157 | * -EUCLEAN is reported if there was a bit-flip which |
| 158 | * was corrected, so this is harmless. | 158 | * was corrected, so this is harmless. |
| 159 | * | ||
| 160 | * We do not report about it here unless debugging is | ||
| 161 | * enabled. A corresponding message will be printed | ||
| 162 | * later, when it is has been scrubbed. | ||
| 159 | */ | 163 | */ |
| 160 | ubi_msg("fixable bit-flip detected at PEB %d", pnum); | 164 | dbg_msg("fixable bit-flip detected at PEB %d", pnum); |
| 161 | ubi_assert(len == read); | 165 | ubi_assert(len == read); |
| 162 | return UBI_IO_BITFLIPS; | 166 | return UBI_IO_BITFLIPS; |
| 163 | } | 167 | } |
| 164 | 168 | ||
| 165 | if (read != len && retries++ < UBI_IO_RETRIES) { | 169 | if (read != len && retries++ < UBI_IO_RETRIES) { |
| 166 | dbg_io("error %d while reading %d bytes from PEB %d:%d, " | 170 | dbg_io("error %d while reading %d bytes from PEB %d:%d," |
| 167 | "read only %zd bytes, retry", | 171 | " read only %zd bytes, retry", |
| 168 | err, len, pnum, offset, read); | 172 | err, len, pnum, offset, read); |
| 169 | yield(); | 173 | yield(); |
| 170 | goto retry; | 174 | goto retry; |
| @@ -187,7 +191,7 @@ retry: | |||
| 187 | ubi_assert(len == read); | 191 | ubi_assert(len == read); |
| 188 | 192 | ||
| 189 | if (ubi_dbg_is_bitflip()) { | 193 | if (ubi_dbg_is_bitflip()) { |
| 190 | dbg_msg("bit-flip (emulated)"); | 194 | dbg_gen("bit-flip (emulated)"); |
| 191 | err = UBI_IO_BITFLIPS; | 195 | err = UBI_IO_BITFLIPS; |
| 192 | } | 196 | } |
| 193 | } | 197 | } |
| @@ -391,6 +395,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) | |||
| 391 | { | 395 | { |
| 392 | int err, i, patt_count; | 396 | int err, i, patt_count; |
| 393 | 397 | ||
| 398 | ubi_msg("run torture test for PEB %d", pnum); | ||
| 394 | patt_count = ARRAY_SIZE(patterns); | 399 | patt_count = ARRAY_SIZE(patterns); |
| 395 | ubi_assert(patt_count > 0); | 400 | ubi_assert(patt_count > 0); |
| 396 | 401 | ||
| @@ -434,6 +439,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) | |||
| 434 | } | 439 | } |
| 435 | 440 | ||
| 436 | err = patt_count; | 441 | err = patt_count; |
| 442 | ubi_msg("PEB %d passed torture test, do not mark it a bad", pnum); | ||
| 437 | 443 | ||
| 438 | out: | 444 | out: |
| 439 | mutex_unlock(&ubi->buf_mutex); | 445 | mutex_unlock(&ubi->buf_mutex); |
| @@ -699,8 +705,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, | |||
| 699 | 705 | ||
| 700 | if (hdr_crc != crc) { | 706 | if (hdr_crc != crc) { |
| 701 | if (verbose) { | 707 | if (verbose) { |
| 702 | ubi_warn("bad EC header CRC at PEB %d, calculated %#08x," | 708 | ubi_warn("bad EC header CRC at PEB %d, calculated " |
| 703 | " read %#08x", pnum, crc, hdr_crc); | 709 | "%#08x, read %#08x", pnum, crc, hdr_crc); |
| 704 | ubi_dbg_dump_ec_hdr(ec_hdr); | 710 | ubi_dbg_dump_ec_hdr(ec_hdr); |
| 705 | } | 711 | } |
| 706 | return UBI_IO_BAD_EC_HDR; | 712 | return UBI_IO_BAD_EC_HDR; |
| @@ -1095,8 +1101,7 @@ fail: | |||
| 1095 | } | 1101 | } |
| 1096 | 1102 | ||
| 1097 | /** | 1103 | /** |
| 1098 | * paranoid_check_peb_ec_hdr - check that the erase counter header of a | 1104 | * paranoid_check_peb_ec_hdr - check erase counter header. |
| 1099 | * physical eraseblock is in-place and is all right. | ||
| 1100 | * @ubi: UBI device description object | 1105 | * @ubi: UBI device description object |
| 1101 | * @pnum: the physical eraseblock number to check | 1106 | * @pnum: the physical eraseblock number to check |
| 1102 | * | 1107 | * |
| @@ -1174,8 +1179,7 @@ fail: | |||
| 1174 | } | 1179 | } |
| 1175 | 1180 | ||
| 1176 | /** | 1181 | /** |
| 1177 | * paranoid_check_peb_vid_hdr - check that the volume identifier header of a | 1182 | * paranoid_check_peb_vid_hdr - check volume identifier header. |
| 1178 | * physical eraseblock is in-place and is all right. | ||
| 1179 | * @ubi: UBI device description object | 1183 | * @ubi: UBI device description object |
| 1180 | * @pnum: the physical eraseblock number to check | 1184 | * @pnum: the physical eraseblock number to check |
| 1181 | * | 1185 | * |
| @@ -1256,7 +1260,7 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | |||
| 1256 | 1260 | ||
| 1257 | fail: | 1261 | fail: |
| 1258 | ubi_err("paranoid check failed for PEB %d", pnum); | 1262 | ubi_err("paranoid check failed for PEB %d", pnum); |
| 1259 | dbg_msg("hex dump of the %d-%d region", offset, offset + len); | 1263 | ubi_msg("hex dump of the %d-%d region", offset, offset + len); |
| 1260 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | 1264 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, |
| 1261 | ubi->dbg_peb_buf, len, 1); | 1265 | ubi->dbg_peb_buf, len, 1); |
| 1262 | err = 1; | 1266 | err = 1; |
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index a70d58823f8d..5d9bcf109c13 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c | |||
| @@ -106,7 +106,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) | |||
| 106 | struct ubi_device *ubi; | 106 | struct ubi_device *ubi; |
| 107 | struct ubi_volume *vol; | 107 | struct ubi_volume *vol; |
| 108 | 108 | ||
| 109 | dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode); | 109 | dbg_gen("open device %d volume %d, mode %d", ubi_num, vol_id, mode); |
| 110 | 110 | ||
| 111 | if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) | 111 | if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) |
| 112 | return ERR_PTR(-EINVAL); | 112 | return ERR_PTR(-EINVAL); |
| @@ -215,7 +215,7 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, | |||
| 215 | struct ubi_device *ubi; | 215 | struct ubi_device *ubi; |
| 216 | struct ubi_volume_desc *ret; | 216 | struct ubi_volume_desc *ret; |
| 217 | 217 | ||
| 218 | dbg_msg("open volume %s, mode %d", name, mode); | 218 | dbg_gen("open volume %s, mode %d", name, mode); |
| 219 | 219 | ||
| 220 | if (!name) | 220 | if (!name) |
| 221 | return ERR_PTR(-EINVAL); | 221 | return ERR_PTR(-EINVAL); |
| @@ -266,7 +266,7 @@ void ubi_close_volume(struct ubi_volume_desc *desc) | |||
| 266 | struct ubi_volume *vol = desc->vol; | 266 | struct ubi_volume *vol = desc->vol; |
| 267 | struct ubi_device *ubi = vol->ubi; | 267 | struct ubi_device *ubi = vol->ubi; |
| 268 | 268 | ||
| 269 | dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode); | 269 | dbg_gen("close volume %d, mode %d", vol->vol_id, desc->mode); |
| 270 | 270 | ||
| 271 | spin_lock(&ubi->volumes_lock); | 271 | spin_lock(&ubi->volumes_lock); |
| 272 | switch (desc->mode) { | 272 | switch (desc->mode) { |
| @@ -323,7 +323,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, | |||
| 323 | struct ubi_device *ubi = vol->ubi; | 323 | struct ubi_device *ubi = vol->ubi; |
| 324 | int err, vol_id = vol->vol_id; | 324 | int err, vol_id = vol->vol_id; |
| 325 | 325 | ||
| 326 | dbg_msg("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); | 326 | dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); |
| 327 | 327 | ||
| 328 | if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 || | 328 | if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 || |
| 329 | lnum >= vol->used_ebs || offset < 0 || len < 0 || | 329 | lnum >= vol->used_ebs || offset < 0 || len < 0 || |
| @@ -388,7 +388,7 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
| 388 | struct ubi_device *ubi = vol->ubi; | 388 | struct ubi_device *ubi = vol->ubi; |
| 389 | int vol_id = vol->vol_id; | 389 | int vol_id = vol->vol_id; |
| 390 | 390 | ||
| 391 | dbg_msg("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset); | 391 | dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset); |
| 392 | 392 | ||
| 393 | if (vol_id < 0 || vol_id >= ubi->vtbl_slots) | 393 | if (vol_id < 0 || vol_id >= ubi->vtbl_slots) |
| 394 | return -EINVAL; | 394 | return -EINVAL; |
| @@ -397,8 +397,8 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
| 397 | return -EROFS; | 397 | return -EROFS; |
| 398 | 398 | ||
| 399 | if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 || | 399 | if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 || |
| 400 | offset + len > vol->usable_leb_size || offset % ubi->min_io_size || | 400 | offset + len > vol->usable_leb_size || |
| 401 | len % ubi->min_io_size) | 401 | offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1)) |
| 402 | return -EINVAL; | 402 | return -EINVAL; |
| 403 | 403 | ||
| 404 | if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && | 404 | if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && |
| @@ -438,7 +438,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
| 438 | struct ubi_device *ubi = vol->ubi; | 438 | struct ubi_device *ubi = vol->ubi; |
| 439 | int vol_id = vol->vol_id; | 439 | int vol_id = vol->vol_id; |
| 440 | 440 | ||
| 441 | dbg_msg("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum); | 441 | dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum); |
| 442 | 442 | ||
| 443 | if (vol_id < 0 || vol_id >= ubi->vtbl_slots) | 443 | if (vol_id < 0 || vol_id >= ubi->vtbl_slots) |
| 444 | return -EINVAL; | 444 | return -EINVAL; |
| @@ -447,7 +447,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
| 447 | return -EROFS; | 447 | return -EROFS; |
| 448 | 448 | ||
| 449 | if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 || | 449 | if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 || |
| 450 | len > vol->usable_leb_size || len % ubi->min_io_size) | 450 | len > vol->usable_leb_size || len & (ubi->min_io_size - 1)) |
| 451 | return -EINVAL; | 451 | return -EINVAL; |
| 452 | 452 | ||
| 453 | if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && | 453 | if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && |
| @@ -482,7 +482,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) | |||
| 482 | struct ubi_device *ubi = vol->ubi; | 482 | struct ubi_device *ubi = vol->ubi; |
| 483 | int err; | 483 | int err; |
| 484 | 484 | ||
| 485 | dbg_msg("erase LEB %d:%d", vol->vol_id, lnum); | 485 | dbg_gen("erase LEB %d:%d", vol->vol_id, lnum); |
| 486 | 486 | ||
| 487 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) | 487 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) |
| 488 | return -EROFS; | 488 | return -EROFS; |
| @@ -542,7 +542,7 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum) | |||
| 542 | struct ubi_volume *vol = desc->vol; | 542 | struct ubi_volume *vol = desc->vol; |
| 543 | struct ubi_device *ubi = vol->ubi; | 543 | struct ubi_device *ubi = vol->ubi; |
| 544 | 544 | ||
| 545 | dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); | 545 | dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); |
| 546 | 546 | ||
| 547 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) | 547 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) |
| 548 | return -EROFS; | 548 | return -EROFS; |
| @@ -579,7 +579,7 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) | |||
| 579 | struct ubi_volume *vol = desc->vol; | 579 | struct ubi_volume *vol = desc->vol; |
| 580 | struct ubi_device *ubi = vol->ubi; | 580 | struct ubi_device *ubi = vol->ubi; |
| 581 | 581 | ||
| 582 | dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum); | 582 | dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); |
| 583 | 583 | ||
| 584 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) | 584 | if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) |
| 585 | return -EROFS; | 585 | return -EROFS; |
| @@ -621,7 +621,7 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum) | |||
| 621 | { | 621 | { |
| 622 | struct ubi_volume *vol = desc->vol; | 622 | struct ubi_volume *vol = desc->vol; |
| 623 | 623 | ||
| 624 | dbg_msg("test LEB %d:%d", vol->vol_id, lnum); | 624 | dbg_gen("test LEB %d:%d", vol->vol_id, lnum); |
| 625 | 625 | ||
| 626 | if (lnum < 0 || lnum >= vol->reserved_pebs) | 626 | if (lnum < 0 || lnum >= vol->reserved_pebs) |
| 627 | return -EINVAL; | 627 | return -EINVAL; |
| @@ -632,3 +632,27 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum) | |||
| 632 | return vol->eba_tbl[lnum] >= 0; | 632 | return vol->eba_tbl[lnum] >= 0; |
| 633 | } | 633 | } |
| 634 | EXPORT_SYMBOL_GPL(ubi_is_mapped); | 634 | EXPORT_SYMBOL_GPL(ubi_is_mapped); |
| 635 | |||
| 636 | /** | ||
| 637 | * ubi_sync - synchronize UBI device buffers. | ||
| 638 | * @ubi_num: UBI device to synchronize | ||
| 639 | * | ||
| 640 | * The underlying MTD device may cache data in hardware or in software. This | ||
| 641 | * function ensures the caches are flushed. Returns zero in case of success and | ||
| 642 | * a negative error code in case of failure. | ||
| 643 | */ | ||
| 644 | int ubi_sync(int ubi_num) | ||
| 645 | { | ||
| 646 | struct ubi_device *ubi; | ||
| 647 | |||
| 648 | ubi = ubi_get_device(ubi_num); | ||
| 649 | if (!ubi) | ||
| 650 | return -ENODEV; | ||
| 651 | |||
| 652 | if (ubi->mtd->sync) | ||
| 653 | ubi->mtd->sync(ubi->mtd); | ||
| 654 | |||
| 655 | ubi_put_device(ubi); | ||
| 656 | return 0; | ||
| 657 | } | ||
| 658 | EXPORT_SYMBOL_GPL(ubi_sync); | ||
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c index 93e052812012..22ad31402945 100644 --- a/drivers/mtd/ubi/misc.c +++ b/drivers/mtd/ubi/misc.c | |||
| @@ -37,7 +37,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, | |||
| 37 | { | 37 | { |
| 38 | int i; | 38 | int i; |
| 39 | 39 | ||
| 40 | ubi_assert(length % ubi->min_io_size == 0); | 40 | ubi_assert(!(length & (ubi->min_io_size - 1))); |
| 41 | 41 | ||
| 42 | for (i = length - 1; i >= 0; i--) | 42 | for (i = length - 1; i >= 0; i--) |
| 43 | if (((const uint8_t *)buf)[i] != 0xFF) | 43 | if (((const uint8_t *)buf)[i] != 0xFF) |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 96d410e106ab..967bb4406df9 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
| @@ -19,9 +19,9 @@ | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| 22 | * UBI scanning unit. | 22 | * UBI scanning sub-system. |
| 23 | * | 23 | * |
| 24 | * This unit is responsible for scanning the flash media, checking UBI | 24 | * This sub-system is responsible for scanning the flash media, checking UBI |
| 25 | * headers and providing complete information about the UBI flash image. | 25 | * headers and providing complete information about the UBI flash image. |
| 26 | * | 26 | * |
| 27 | * The scanning information is represented by a &struct ubi_scan_info' object. | 27 | * The scanning information is represented by a &struct ubi_scan_info' object. |
| @@ -93,8 +93,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /** | 95 | /** |
| 96 | * validate_vid_hdr - check that volume identifier header is correct and | 96 | * validate_vid_hdr - check volume identifier header. |
| 97 | * consistent. | ||
| 98 | * @vid_hdr: the volume identifier header to check | 97 | * @vid_hdr: the volume identifier header to check |
| 99 | * @sv: information about the volume this logical eraseblock belongs to | 98 | * @sv: information about the volume this logical eraseblock belongs to |
| 100 | * @pnum: physical eraseblock number the VID header came from | 99 | * @pnum: physical eraseblock number the VID header came from |
| @@ -103,7 +102,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, | |||
| 103 | * non-zero if an inconsistency was found and zero if not. | 102 | * non-zero if an inconsistency was found and zero if not. |
| 104 | * | 103 | * |
| 105 | * Note, UBI does sanity check of everything it reads from the flash media. | 104 | * Note, UBI does sanity check of everything it reads from the flash media. |
| 106 | * Most of the checks are done in the I/O unit. Here we check that the | 105 | * Most of the checks are done in the I/O sub-system. Here we check that the |
| 107 | * information in the VID header is consistent to the information in other VID | 106 | * information in the VID header is consistent to the information in other VID |
| 108 | * headers of the same volume. | 107 | * headers of the same volume. |
| 109 | */ | 108 | */ |
| @@ -247,45 +246,21 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, | |||
| 247 | struct ubi_vid_hdr *vh = NULL; | 246 | struct ubi_vid_hdr *vh = NULL; |
| 248 | unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); | 247 | unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); |
| 249 | 248 | ||
| 250 | if (seb->sqnum == 0 && sqnum2 == 0) { | 249 | if (sqnum2 == seb->sqnum) { |
| 251 | long long abs, v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver); | ||
| 252 | |||
| 253 | /* | 250 | /* |
| 254 | * UBI constantly increases the logical eraseblock version | 251 | * This must be a really ancient UBI image which has been |
| 255 | * number and it can overflow. Thus, we have to bear in mind | 252 | * created before sequence numbers support has been added. At |
| 256 | * that versions that are close to %0xFFFFFFFF are less then | 253 | * that times we used 32-bit LEB versions stored in logical |
| 257 | * versions that are close to %0. | 254 | * eraseblocks. That was before UBI got into mainline. We do not |
| 258 | * | 255 | * support these images anymore. Well, those images will work |
| 259 | * The UBI WL unit guarantees that the number of pending tasks | 256 | * still work, but only if no unclean reboots happened. |
| 260 | * is not greater then %0x7FFFFFFF. So, if the difference | ||
| 261 | * between any two versions is greater or equivalent to | ||
| 262 | * %0x7FFFFFFF, there was an overflow and the logical | ||
| 263 | * eraseblock with lower version is actually newer then the one | ||
| 264 | * with higher version. | ||
| 265 | * | ||
| 266 | * FIXME: but this is anyway obsolete and will be removed at | ||
| 267 | * some point. | ||
| 268 | */ | 257 | */ |
| 269 | dbg_bld("using old crappy leb_ver stuff"); | 258 | ubi_err("unsupported on-flash UBI format\n"); |
| 270 | 259 | return -EINVAL; | |
| 271 | if (v1 == v2) { | 260 | } |
| 272 | ubi_err("PEB %d and PEB %d have the same version %lld", | ||
| 273 | seb->pnum, pnum, v1); | ||
| 274 | return -EINVAL; | ||
| 275 | } | ||
| 276 | |||
| 277 | abs = v1 - v2; | ||
| 278 | if (abs < 0) | ||
| 279 | abs = -abs; | ||
| 280 | 261 | ||
| 281 | if (abs < 0x7FFFFFFF) | 262 | /* Obviously the LEB with lower sequence counter is older */ |
| 282 | /* Non-overflow situation */ | 263 | second_is_newer = !!(sqnum2 > seb->sqnum); |
| 283 | second_is_newer = (v2 > v1); | ||
| 284 | else | ||
| 285 | second_is_newer = (v2 < v1); | ||
| 286 | } else | ||
| 287 | /* Obviously the LEB with lower sequence counter is older */ | ||
| 288 | second_is_newer = sqnum2 > seb->sqnum; | ||
| 289 | 264 | ||
| 290 | /* | 265 | /* |
| 291 | * Now we know which copy is newer. If the copy flag of the PEB with | 266 | * Now we know which copy is newer. If the copy flag of the PEB with |
| @@ -293,7 +268,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, | |||
| 293 | * check data CRC. For the second PEB we already have the VID header, | 268 | * check data CRC. For the second PEB we already have the VID header, |
| 294 | * for the first one - we'll need to re-read it from flash. | 269 | * for the first one - we'll need to re-read it from flash. |
| 295 | * | 270 | * |
| 296 | * FIXME: this may be optimized so that we wouldn't read twice. | 271 | * Note: this may be optimized so that we wouldn't read twice. |
| 297 | */ | 272 | */ |
| 298 | 273 | ||
| 299 | if (second_is_newer) { | 274 | if (second_is_newer) { |
| @@ -379,8 +354,7 @@ out_free_vidh: | |||
| 379 | } | 354 | } |
| 380 | 355 | ||
| 381 | /** | 356 | /** |
| 382 | * ubi_scan_add_used - add information about a physical eraseblock to the | 357 | * ubi_scan_add_used - add physical eraseblock to the scanning information. |
| 383 | * scanning information. | ||
| 384 | * @ubi: UBI device description object | 358 | * @ubi: UBI device description object |
| 385 | * @si: scanning information | 359 | * @si: scanning information |
| 386 | * @pnum: the physical eraseblock number | 360 | * @pnum: the physical eraseblock number |
| @@ -400,7 +374,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 400 | int bitflips) | 374 | int bitflips) |
| 401 | { | 375 | { |
| 402 | int err, vol_id, lnum; | 376 | int err, vol_id, lnum; |
| 403 | uint32_t leb_ver; | ||
| 404 | unsigned long long sqnum; | 377 | unsigned long long sqnum; |
| 405 | struct ubi_scan_volume *sv; | 378 | struct ubi_scan_volume *sv; |
| 406 | struct ubi_scan_leb *seb; | 379 | struct ubi_scan_leb *seb; |
| @@ -409,10 +382,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 409 | vol_id = be32_to_cpu(vid_hdr->vol_id); | 382 | vol_id = be32_to_cpu(vid_hdr->vol_id); |
| 410 | lnum = be32_to_cpu(vid_hdr->lnum); | 383 | lnum = be32_to_cpu(vid_hdr->lnum); |
| 411 | sqnum = be64_to_cpu(vid_hdr->sqnum); | 384 | sqnum = be64_to_cpu(vid_hdr->sqnum); |
| 412 | leb_ver = be32_to_cpu(vid_hdr->leb_ver); | ||
| 413 | 385 | ||
| 414 | dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, ver %u, bitflips %d", | 386 | dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d", |
| 415 | pnum, vol_id, lnum, ec, sqnum, leb_ver, bitflips); | 387 | pnum, vol_id, lnum, ec, sqnum, bitflips); |
| 416 | 388 | ||
| 417 | sv = add_volume(si, vol_id, pnum, vid_hdr); | 389 | sv = add_volume(si, vol_id, pnum, vid_hdr); |
| 418 | if (IS_ERR(sv) < 0) | 390 | if (IS_ERR(sv) < 0) |
| @@ -445,25 +417,20 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 445 | */ | 417 | */ |
| 446 | 418 | ||
| 447 | dbg_bld("this LEB already exists: PEB %d, sqnum %llu, " | 419 | dbg_bld("this LEB already exists: PEB %d, sqnum %llu, " |
| 448 | "LEB ver %u, EC %d", seb->pnum, seb->sqnum, | 420 | "EC %d", seb->pnum, seb->sqnum, seb->ec); |
| 449 | seb->leb_ver, seb->ec); | ||
| 450 | |||
| 451 | /* | ||
| 452 | * Make sure that the logical eraseblocks have different | ||
| 453 | * versions. Otherwise the image is bad. | ||
| 454 | */ | ||
| 455 | if (seb->leb_ver == leb_ver && leb_ver != 0) { | ||
| 456 | ubi_err("two LEBs with same version %u", leb_ver); | ||
| 457 | ubi_dbg_dump_seb(seb, 0); | ||
| 458 | ubi_dbg_dump_vid_hdr(vid_hdr); | ||
| 459 | return -EINVAL; | ||
| 460 | } | ||
| 461 | 421 | ||
| 462 | /* | 422 | /* |
| 463 | * Make sure that the logical eraseblocks have different | 423 | * Make sure that the logical eraseblocks have different |
| 464 | * sequence numbers. Otherwise the image is bad. | 424 | * sequence numbers. Otherwise the image is bad. |
| 465 | * | 425 | * |
| 466 | * FIXME: remove 'sqnum != 0' check when leb_ver is removed. | 426 | * However, if the sequence number is zero, we assume it must |
| 427 | * be an ancient UBI image from the era when UBI did not have | ||
| 428 | * sequence numbers. We still can attach these images, unless | ||
| 429 | * there is a need to distinguish between old and new | ||
| 430 | * eraseblocks, in which case we'll refuse the image in | ||
| 431 | * 'compare_lebs()'. In other words, we attach old clean | ||
| 432 | * images, but refuse attaching old images with duplicated | ||
| 433 | * logical eraseblocks because there was an unclean reboot. | ||
| 467 | */ | 434 | */ |
| 468 | if (seb->sqnum == sqnum && sqnum != 0) { | 435 | if (seb->sqnum == sqnum && sqnum != 0) { |
| 469 | ubi_err("two LEBs with same sequence number %llu", | 436 | ubi_err("two LEBs with same sequence number %llu", |
| @@ -503,7 +470,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 503 | seb->pnum = pnum; | 470 | seb->pnum = pnum; |
| 504 | seb->scrub = ((cmp_res & 2) || bitflips); | 471 | seb->scrub = ((cmp_res & 2) || bitflips); |
| 505 | seb->sqnum = sqnum; | 472 | seb->sqnum = sqnum; |
| 506 | seb->leb_ver = leb_ver; | ||
| 507 | 473 | ||
| 508 | if (sv->highest_lnum == lnum) | 474 | if (sv->highest_lnum == lnum) |
| 509 | sv->last_data_size = | 475 | sv->last_data_size = |
| @@ -540,7 +506,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 540 | seb->lnum = lnum; | 506 | seb->lnum = lnum; |
| 541 | seb->sqnum = sqnum; | 507 | seb->sqnum = sqnum; |
| 542 | seb->scrub = bitflips; | 508 | seb->scrub = bitflips; |
| 543 | seb->leb_ver = leb_ver; | ||
| 544 | 509 | ||
| 545 | if (sv->highest_lnum <= lnum) { | 510 | if (sv->highest_lnum <= lnum) { |
| 546 | sv->highest_lnum = lnum; | 511 | sv->highest_lnum = lnum; |
| @@ -554,8 +519,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
| 554 | } | 519 | } |
| 555 | 520 | ||
| 556 | /** | 521 | /** |
| 557 | * ubi_scan_find_sv - find information about a particular volume in the | 522 | * ubi_scan_find_sv - find volume in the scanning information. |
| 558 | * scanning information. | ||
| 559 | * @si: scanning information | 523 | * @si: scanning information |
| 560 | * @vol_id: the requested volume ID | 524 | * @vol_id: the requested volume ID |
| 561 | * | 525 | * |
| @@ -584,8 +548,7 @@ struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si, | |||
| 584 | } | 548 | } |
| 585 | 549 | ||
| 586 | /** | 550 | /** |
| 587 | * ubi_scan_find_seb - find information about a particular logical | 551 | * ubi_scan_find_seb - find LEB in the volume scanning information. |
| 588 | * eraseblock in the volume scanning information. | ||
| 589 | * @sv: a pointer to the volume scanning information | 552 | * @sv: a pointer to the volume scanning information |
| 590 | * @lnum: the requested logical eraseblock | 553 | * @lnum: the requested logical eraseblock |
| 591 | * | 554 | * |
| @@ -645,9 +608,9 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv) | |||
| 645 | * | 608 | * |
| 646 | * This function erases physical eraseblock 'pnum', and writes the erase | 609 | * This function erases physical eraseblock 'pnum', and writes the erase |
| 647 | * counter header to it. This function should only be used on UBI device | 610 | * counter header to it. This function should only be used on UBI device |
| 648 | * initialization stages, when the EBA unit had not been yet initialized. This | 611 | * initialization stages, when the EBA sub-system had not been yet initialized. |
| 649 | * function returns zero in case of success and a negative error code in case | 612 | * This function returns zero in case of success and a negative error code in |
| 650 | * of failure. | 613 | * case of failure. |
| 651 | */ | 614 | */ |
| 652 | int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, | 615 | int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, |
| 653 | int pnum, int ec) | 616 | int pnum, int ec) |
| @@ -687,9 +650,10 @@ out_free: | |||
| 687 | * @si: scanning information | 650 | * @si: scanning information |
| 688 | * | 651 | * |
| 689 | * This function returns a free physical eraseblock. It is supposed to be | 652 | * This function returns a free physical eraseblock. It is supposed to be |
| 690 | * called on the UBI initialization stages when the wear-leveling unit is not | 653 | * called on the UBI initialization stages when the wear-leveling sub-system is |
| 691 | * initialized yet. This function picks a physical eraseblocks from one of the | 654 | * not initialized yet. This function picks a physical eraseblocks from one of |
| 692 | * lists, writes the EC header if it is needed, and removes it from the list. | 655 | * the lists, writes the EC header if it is needed, and removes it from the |
| 656 | * list. | ||
| 693 | * | 657 | * |
| 694 | * This function returns scanning physical eraseblock information in case of | 658 | * This function returns scanning physical eraseblock information in case of |
| 695 | * success and an error code in case of failure. | 659 | * success and an error code in case of failure. |
| @@ -742,8 +706,7 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, | |||
| 742 | } | 706 | } |
| 743 | 707 | ||
| 744 | /** | 708 | /** |
| 745 | * process_eb - read UBI headers, check them and add corresponding data | 709 | * process_eb - read, check UBI headers, and add them to scanning information. |
| 746 | * to the scanning information. | ||
| 747 | * @ubi: UBI device description object | 710 | * @ubi: UBI device description object |
| 748 | * @si: scanning information | 711 | * @si: scanning information |
| 749 | * @pnum: the physical eraseblock number | 712 | * @pnum: the physical eraseblock number |
| @@ -751,7 +714,8 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, | |||
| 751 | * This function returns a zero if the physical eraseblock was successfully | 714 | * This function returns a zero if the physical eraseblock was successfully |
| 752 | * handled and a negative error code in case of failure. | 715 | * handled and a negative error code in case of failure. |
| 753 | */ | 716 | */ |
| 754 | static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum) | 717 | static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, |
| 718 | int pnum) | ||
| 755 | { | 719 | { |
| 756 | long long uninitialized_var(ec); | 720 | long long uninitialized_var(ec); |
| 757 | int err, bitflips = 0, vol_id, ec_corr = 0; | 721 | int err, bitflips = 0, vol_id, ec_corr = 0; |
| @@ -764,8 +728,9 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum | |||
| 764 | return err; | 728 | return err; |
| 765 | else if (err) { | 729 | else if (err) { |
| 766 | /* | 730 | /* |
| 767 | * FIXME: this is actually duty of the I/O unit to initialize | 731 | * FIXME: this is actually duty of the I/O sub-system to |
| 768 | * this, but MTD does not provide enough information. | 732 | * initialize this, but MTD does not provide enough |
| 733 | * information. | ||
| 769 | */ | 734 | */ |
| 770 | si->bad_peb_count += 1; | 735 | si->bad_peb_count += 1; |
| 771 | return 0; | 736 | return 0; |
| @@ -930,7 +895,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) | |||
| 930 | for (pnum = 0; pnum < ubi->peb_count; pnum++) { | 895 | for (pnum = 0; pnum < ubi->peb_count; pnum++) { |
| 931 | cond_resched(); | 896 | cond_resched(); |
| 932 | 897 | ||
| 933 | dbg_msg("process PEB %d", pnum); | 898 | dbg_gen("process PEB %d", pnum); |
| 934 | err = process_eb(ubi, si, pnum); | 899 | err = process_eb(ubi, si, pnum); |
| 935 | if (err < 0) | 900 | if (err < 0) |
| 936 | goto out_vidh; | 901 | goto out_vidh; |
| @@ -1079,8 +1044,7 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) | |||
| 1079 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 1044 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| 1080 | 1045 | ||
| 1081 | /** | 1046 | /** |
| 1082 | * paranoid_check_si - check if the scanning information is correct and | 1047 | * paranoid_check_si - check the scanning information. |
| 1083 | * consistent. | ||
| 1084 | * @ubi: UBI device description object | 1048 | * @ubi: UBI device description object |
| 1085 | * @si: scanning information | 1049 | * @si: scanning information |
| 1086 | * | 1050 | * |
| @@ -1265,11 +1229,6 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
| 1265 | ubi_err("bad data_pad %d", sv->data_pad); | 1229 | ubi_err("bad data_pad %d", sv->data_pad); |
| 1266 | goto bad_vid_hdr; | 1230 | goto bad_vid_hdr; |
| 1267 | } | 1231 | } |
| 1268 | |||
| 1269 | if (seb->leb_ver != be32_to_cpu(vidh->leb_ver)) { | ||
| 1270 | ubi_err("bad leb_ver %u", seb->leb_ver); | ||
| 1271 | goto bad_vid_hdr; | ||
| 1272 | } | ||
| 1273 | } | 1232 | } |
| 1274 | 1233 | ||
| 1275 | if (!last_seb) | 1234 | if (!last_seb) |
| @@ -1299,8 +1258,7 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
| 1299 | if (err < 0) { | 1258 | if (err < 0) { |
| 1300 | kfree(buf); | 1259 | kfree(buf); |
| 1301 | return err; | 1260 | return err; |
| 1302 | } | 1261 | } else if (err) |
| 1303 | else if (err) | ||
| 1304 | buf[pnum] = 1; | 1262 | buf[pnum] = 1; |
| 1305 | } | 1263 | } |
| 1306 | 1264 | ||
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 966b9b682a42..61df208e2f20 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | * @u: unions RB-tree or @list links | 34 | * @u: unions RB-tree or @list links |
| 35 | * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects | 35 | * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects |
| 36 | * @u.list: link in one of the eraseblock lists | 36 | * @u.list: link in one of the eraseblock lists |
| 37 | * @leb_ver: logical eraseblock version (obsolete) | ||
| 38 | * | 37 | * |
| 39 | * One object of this type is allocated for each physical eraseblock during | 38 | * One object of this type is allocated for each physical eraseblock during |
| 40 | * scanning. | 39 | * scanning. |
| @@ -49,7 +48,6 @@ struct ubi_scan_leb { | |||
| 49 | struct rb_node rb; | 48 | struct rb_node rb; |
| 50 | struct list_head list; | 49 | struct list_head list; |
| 51 | } u; | 50 | } u; |
| 52 | uint32_t leb_ver; | ||
| 53 | }; | 51 | }; |
| 54 | 52 | ||
| 55 | /** | 53 | /** |
| @@ -59,16 +57,16 @@ struct ubi_scan_leb { | |||
| 59 | * @leb_count: number of logical eraseblocks in this volume | 57 | * @leb_count: number of logical eraseblocks in this volume |
| 60 | * @vol_type: volume type | 58 | * @vol_type: volume type |
| 61 | * @used_ebs: number of used logical eraseblocks in this volume (only for | 59 | * @used_ebs: number of used logical eraseblocks in this volume (only for |
| 62 | * static volumes) | 60 | * static volumes) |
| 63 | * @last_data_size: amount of data in the last logical eraseblock of this | 61 | * @last_data_size: amount of data in the last logical eraseblock of this |
| 64 | * volume (always equivalent to the usable logical eraseblock size in case of | 62 | * volume (always equivalent to the usable logical eraseblock |
| 65 | * dynamic volumes) | 63 | * size in case of dynamic volumes) |
| 66 | * @data_pad: how many bytes at the end of logical eraseblocks of this volume | 64 | * @data_pad: how many bytes at the end of logical eraseblocks of this volume |
| 67 | * are not used (due to volume alignment) | 65 | * are not used (due to volume alignment) |
| 68 | * @compat: compatibility flags of this volume | 66 | * @compat: compatibility flags of this volume |
| 69 | * @rb: link in the volume RB-tree | 67 | * @rb: link in the volume RB-tree |
| 70 | * @root: root of the RB-tree containing all the eraseblock belonging to this | 68 | * @root: root of the RB-tree containing all the eraseblock belonging to this |
| 71 | * volume (&struct ubi_scan_leb objects) | 69 | * volume (&struct ubi_scan_leb objects) |
| 72 | * | 70 | * |
| 73 | * One object of this type is allocated for each volume during scanning. | 71 | * One object of this type is allocated for each volume during scanning. |
| 74 | */ | 72 | */ |
| @@ -92,8 +90,8 @@ struct ubi_scan_volume { | |||
| 92 | * @free: list of free physical eraseblocks | 90 | * @free: list of free physical eraseblocks |
| 93 | * @erase: list of physical eraseblocks which have to be erased | 91 | * @erase: list of physical eraseblocks which have to be erased |
| 94 | * @alien: list of physical eraseblocks which should not be used by UBI (e.g., | 92 | * @alien: list of physical eraseblocks which should not be used by UBI (e.g., |
| 93 | * those belonging to "preserve"-compatible internal volumes) | ||
| 95 | * @bad_peb_count: count of bad physical eraseblocks | 94 | * @bad_peb_count: count of bad physical eraseblocks |
| 96 | * those belonging to "preserve"-compatible internal volumes) | ||
| 97 | * @vols_found: number of volumes found during scanning | 95 | * @vols_found: number of volumes found during scanning |
| 98 | * @highest_vol_id: highest volume ID | 96 | * @highest_vol_id: highest volume ID |
| 99 | * @alien_peb_count: count of physical eraseblocks in the @alien list | 97 | * @alien_peb_count: count of physical eraseblocks in the @alien list |
| @@ -106,8 +104,8 @@ struct ubi_scan_volume { | |||
| 106 | * @ec_count: a temporary variable used when calculating @mean_ec | 104 | * @ec_count: a temporary variable used when calculating @mean_ec |
| 107 | * | 105 | * |
| 108 | * This data structure contains the result of scanning and may be used by other | 106 | * This data structure contains the result of scanning and may be used by other |
| 109 | * UBI units to build final UBI data structures, further error-recovery and so | 107 | * UBI sub-systems to build final UBI data structures, further error-recovery |
| 110 | * on. | 108 | * and so on. |
| 111 | */ | 109 | */ |
| 112 | struct ubi_scan_info { | 110 | struct ubi_scan_info { |
| 113 | struct rb_root volumes; | 111 | struct rb_root volumes; |
| @@ -132,8 +130,7 @@ struct ubi_device; | |||
| 132 | struct ubi_vid_hdr; | 130 | struct ubi_vid_hdr; |
| 133 | 131 | ||
| 134 | /* | 132 | /* |
| 135 | * ubi_scan_move_to_list - move a physical eraseblock from the volume tree to a | 133 | * ubi_scan_move_to_list - move a PEB from the volume tree to a list. |
| 136 | * list. | ||
| 137 | * | 134 | * |
| 138 | * @sv: volume scanning information | 135 | * @sv: volume scanning information |
| 139 | * @seb: scanning eraseblock infprmation | 136 | * @seb: scanning eraseblock infprmation |
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index c3185d9fd048..2ad940409053 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h | |||
| @@ -98,10 +98,11 @@ enum { | |||
| 98 | * Compatibility constants used by internal volumes. | 98 | * Compatibility constants used by internal volumes. |
| 99 | * | 99 | * |
| 100 | * @UBI_COMPAT_DELETE: delete this internal volume before anything is written | 100 | * @UBI_COMPAT_DELETE: delete this internal volume before anything is written |
| 101 | * to the flash | 101 | * to the flash |
| 102 | * @UBI_COMPAT_RO: attach this device in read-only mode | 102 | * @UBI_COMPAT_RO: attach this device in read-only mode |
| 103 | * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its | 103 | * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its |
| 104 | * physical eraseblocks, don't allow the wear-leveling unit to move them | 104 | * physical eraseblocks, don't allow the wear-leveling |
| 105 | * sub-system to move them | ||
| 105 | * @UBI_COMPAT_REJECT: reject this UBI image | 106 | * @UBI_COMPAT_REJECT: reject this UBI image |
| 106 | */ | 107 | */ |
| 107 | enum { | 108 | enum { |
| @@ -123,7 +124,7 @@ enum { | |||
| 123 | * struct ubi_ec_hdr - UBI erase counter header. | 124 | * struct ubi_ec_hdr - UBI erase counter header. |
| 124 | * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC) | 125 | * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC) |
| 125 | * @version: version of UBI implementation which is supposed to accept this | 126 | * @version: version of UBI implementation which is supposed to accept this |
| 126 | * UBI image | 127 | * UBI image |
| 127 | * @padding1: reserved for future, zeroes | 128 | * @padding1: reserved for future, zeroes |
| 128 | * @ec: the erase counter | 129 | * @ec: the erase counter |
| 129 | * @vid_hdr_offset: where the VID header starts | 130 | * @vid_hdr_offset: where the VID header starts |
| @@ -159,24 +160,23 @@ struct ubi_ec_hdr { | |||
| 159 | * struct ubi_vid_hdr - on-flash UBI volume identifier header. | 160 | * struct ubi_vid_hdr - on-flash UBI volume identifier header. |
| 160 | * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC) | 161 | * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC) |
| 161 | * @version: UBI implementation version which is supposed to accept this UBI | 162 | * @version: UBI implementation version which is supposed to accept this UBI |
| 162 | * image (%UBI_VERSION) | 163 | * image (%UBI_VERSION) |
| 163 | * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) | 164 | * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) |
| 164 | * @copy_flag: if this logical eraseblock was copied from another physical | 165 | * @copy_flag: if this logical eraseblock was copied from another physical |
| 165 | * eraseblock (for wear-leveling reasons) | 166 | * eraseblock (for wear-leveling reasons) |
| 166 | * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, | 167 | * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, |
| 167 | * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) | 168 | * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) |
| 168 | * @vol_id: ID of this volume | 169 | * @vol_id: ID of this volume |
| 169 | * @lnum: logical eraseblock number | 170 | * @lnum: logical eraseblock number |
| 170 | * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be | 171 | * @padding1: reserved for future, zeroes |
| 171 | * removed, kept only for not breaking older UBI users) | ||
| 172 | * @data_size: how many bytes of data this logical eraseblock contains | 172 | * @data_size: how many bytes of data this logical eraseblock contains |
| 173 | * @used_ebs: total number of used logical eraseblocks in this volume | 173 | * @used_ebs: total number of used logical eraseblocks in this volume |
| 174 | * @data_pad: how many bytes at the end of this physical eraseblock are not | 174 | * @data_pad: how many bytes at the end of this physical eraseblock are not |
| 175 | * used | 175 | * used |
| 176 | * @data_crc: CRC checksum of the data stored in this logical eraseblock | 176 | * @data_crc: CRC checksum of the data stored in this logical eraseblock |
| 177 | * @padding1: reserved for future, zeroes | ||
| 178 | * @sqnum: sequence number | ||
| 179 | * @padding2: reserved for future, zeroes | 177 | * @padding2: reserved for future, zeroes |
| 178 | * @sqnum: sequence number | ||
| 179 | * @padding3: reserved for future, zeroes | ||
| 180 | * @hdr_crc: volume identifier header CRC checksum | 180 | * @hdr_crc: volume identifier header CRC checksum |
| 181 | * | 181 | * |
| 182 | * The @sqnum is the value of the global sequence counter at the time when this | 182 | * The @sqnum is the value of the global sequence counter at the time when this |
| @@ -224,10 +224,6 @@ struct ubi_ec_hdr { | |||
| 224 | * checksum is correct, this physical eraseblock is selected (P1). Otherwise | 224 | * checksum is correct, this physical eraseblock is selected (P1). Otherwise |
| 225 | * the older one (P) is selected. | 225 | * the older one (P) is selected. |
| 226 | * | 226 | * |
| 227 | * Note, there is an obsolete @leb_ver field which was used instead of @sqnum | ||
| 228 | * in the past. But it is not used anymore and we keep it in order to be able | ||
| 229 | * to deal with old UBI images. It will be removed at some point. | ||
| 230 | * | ||
| 231 | * There are 2 sorts of volumes in UBI: user volumes and internal volumes. | 227 | * There are 2 sorts of volumes in UBI: user volumes and internal volumes. |
| 232 | * Internal volumes are not seen from outside and are used for various internal | 228 | * Internal volumes are not seen from outside and are used for various internal |
| 233 | * UBI purposes. In this implementation there is only one internal volume - the | 229 | * UBI purposes. In this implementation there is only one internal volume - the |
| @@ -248,9 +244,9 @@ struct ubi_ec_hdr { | |||
| 248 | * The @data_crc field contains the CRC checksum of the contents of the logical | 244 | * The @data_crc field contains the CRC checksum of the contents of the logical |
| 249 | * eraseblock if this is a static volume. In case of dynamic volumes, it does | 245 | * eraseblock if this is a static volume. In case of dynamic volumes, it does |
| 250 | * not contain the CRC checksum as a rule. The only exception is when the | 246 | * not contain the CRC checksum as a rule. The only exception is when the |
| 251 | * data of the physical eraseblock was moved by the wear-leveling unit, then | 247 | * data of the physical eraseblock was moved by the wear-leveling sub-system, |
| 252 | * the wear-leveling unit calculates the data CRC and stores it in the | 248 | * then the wear-leveling sub-system calculates the data CRC and stores it in |
| 253 | * @data_crc field. And of course, the @copy_flag is %in this case. | 249 | * the @data_crc field. And of course, the @copy_flag is %in this case. |
| 254 | * | 250 | * |
| 255 | * The @data_size field is used only for static volumes because UBI has to know | 251 | * The @data_size field is used only for static volumes because UBI has to know |
| 256 | * how many bytes of data are stored in this eraseblock. For dynamic volumes, | 252 | * how many bytes of data are stored in this eraseblock. For dynamic volumes, |
| @@ -277,14 +273,14 @@ struct ubi_vid_hdr { | |||
| 277 | __u8 compat; | 273 | __u8 compat; |
| 278 | __be32 vol_id; | 274 | __be32 vol_id; |
| 279 | __be32 lnum; | 275 | __be32 lnum; |
| 280 | __be32 leb_ver; /* obsolete, to be removed, don't use */ | 276 | __u8 padding1[4]; |
| 281 | __be32 data_size; | 277 | __be32 data_size; |
| 282 | __be32 used_ebs; | 278 | __be32 used_ebs; |
| 283 | __be32 data_pad; | 279 | __be32 data_pad; |
| 284 | __be32 data_crc; | 280 | __be32 data_crc; |
| 285 | __u8 padding1[4]; | 281 | __u8 padding2[4]; |
| 286 | __be64 sqnum; | 282 | __be64 sqnum; |
| 287 | __u8 padding2[12]; | 283 | __u8 padding3[12]; |
| 288 | __be32 hdr_crc; | 284 | __be32 hdr_crc; |
| 289 | } __attribute__ ((packed)); | 285 | } __attribute__ ((packed)); |
| 290 | 286 | ||
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 67dcbd11c15c..1c3fa18c26a7 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
| @@ -74,15 +74,15 @@ | |||
| 74 | #define UBI_IO_RETRIES 3 | 74 | #define UBI_IO_RETRIES 3 |
| 75 | 75 | ||
| 76 | /* | 76 | /* |
| 77 | * Error codes returned by the I/O unit. | 77 | * Error codes returned by the I/O sub-system. |
| 78 | * | 78 | * |
| 79 | * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only | 79 | * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only |
| 80 | * 0xFF bytes | 80 | * %0xFF bytes |
| 81 | * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a | 81 | * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a |
| 82 | * valid erase counter header, and the rest are %0xFF bytes | 82 | * valid erase counter header, and the rest are %0xFF bytes |
| 83 | * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC) | 83 | * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC) |
| 84 | * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or | 84 | * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or |
| 85 | * CRC) | 85 | * CRC) |
| 86 | * UBI_IO_BITFLIPS: bit-flips were detected and corrected | 86 | * UBI_IO_BITFLIPS: bit-flips were detected and corrected |
| 87 | */ | 87 | */ |
| 88 | enum { | 88 | enum { |
| @@ -99,9 +99,9 @@ enum { | |||
| 99 | * @ec: erase counter | 99 | * @ec: erase counter |
| 100 | * @pnum: physical eraseblock number | 100 | * @pnum: physical eraseblock number |
| 101 | * | 101 | * |
| 102 | * This data structure is used in the WL unit. Each physical eraseblock has a | 102 | * This data structure is used in the WL sub-system. Each physical eraseblock |
| 103 | * corresponding &struct wl_entry object which may be kept in different | 103 | * has a corresponding &struct wl_entry object which may be kept in different |
| 104 | * RB-trees. See WL unit for details. | 104 | * RB-trees. See WL sub-system for details. |
| 105 | */ | 105 | */ |
| 106 | struct ubi_wl_entry { | 106 | struct ubi_wl_entry { |
| 107 | struct rb_node rb; | 107 | struct rb_node rb; |
| @@ -118,10 +118,10 @@ struct ubi_wl_entry { | |||
| 118 | * @mutex: read/write mutex to implement read/write access serialization to | 118 | * @mutex: read/write mutex to implement read/write access serialization to |
| 119 | * the (@vol_id, @lnum) logical eraseblock | 119 | * the (@vol_id, @lnum) logical eraseblock |
| 120 | * | 120 | * |
| 121 | * This data structure is used in the EBA unit to implement per-LEB locking. | 121 | * This data structure is used in the EBA sub-system to implement per-LEB |
| 122 | * When a logical eraseblock is being locked - corresponding | 122 | * locking. When a logical eraseblock is being locked - corresponding |
| 123 | * &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree). | 123 | * &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree). |
| 124 | * See EBA unit for details. | 124 | * See EBA sub-system for details. |
| 125 | */ | 125 | */ |
| 126 | struct ubi_ltree_entry { | 126 | struct ubi_ltree_entry { |
| 127 | struct rb_node rb; | 127 | struct rb_node rb; |
| @@ -131,6 +131,27 @@ struct ubi_ltree_entry { | |||
| 131 | struct rw_semaphore mutex; | 131 | struct rw_semaphore mutex; |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | /** | ||
| 135 | * struct ubi_rename_entry - volume re-name description data structure. | ||
| 136 | * @new_name_len: new volume name length | ||
| 137 | * @new_name: new volume name | ||
| 138 | * @remove: if not zero, this volume should be removed, not re-named | ||
| 139 | * @desc: descriptor of the volume | ||
| 140 | * @list: links re-name entries into a list | ||
| 141 | * | ||
| 142 | * This data structure is utilized in the multiple volume re-name code. Namely, | ||
| 143 | * UBI first creates a list of &struct ubi_rename_entry objects from the | ||
| 144 | * &struct ubi_rnvol_req request object, and then utilizes this list to do all | ||
| 145 | * the job. | ||
| 146 | */ | ||
| 147 | struct ubi_rename_entry { | ||
| 148 | int new_name_len; | ||
| 149 | char new_name[UBI_VOL_NAME_MAX + 1]; | ||
| 150 | int remove; | ||
| 151 | struct ubi_volume_desc *desc; | ||
| 152 | struct list_head list; | ||
| 153 | }; | ||
| 154 | |||
| 134 | struct ubi_volume_desc; | 155 | struct ubi_volume_desc; |
| 135 | 156 | ||
| 136 | /** | 157 | /** |
| @@ -206,7 +227,7 @@ struct ubi_volume { | |||
| 206 | int alignment; | 227 | int alignment; |
| 207 | int data_pad; | 228 | int data_pad; |
| 208 | int name_len; | 229 | int name_len; |
| 209 | char name[UBI_VOL_NAME_MAX+1]; | 230 | char name[UBI_VOL_NAME_MAX + 1]; |
| 210 | 231 | ||
| 211 | int upd_ebs; | 232 | int upd_ebs; |
| 212 | int ch_lnum; | 233 | int ch_lnum; |
| @@ -225,7 +246,7 @@ struct ubi_volume { | |||
| 225 | #ifdef CONFIG_MTD_UBI_GLUEBI | 246 | #ifdef CONFIG_MTD_UBI_GLUEBI |
| 226 | /* | 247 | /* |
| 227 | * Gluebi-related stuff may be compiled out. | 248 | * Gluebi-related stuff may be compiled out. |
| 228 | * TODO: this should not be built into UBI but should be a separate | 249 | * Note: this should not be built into UBI but should be a separate |
| 229 | * ubimtd driver which works on top of UBI and emulates MTD devices. | 250 | * ubimtd driver which works on top of UBI and emulates MTD devices. |
| 230 | */ | 251 | */ |
| 231 | struct ubi_volume_desc *gluebi_desc; | 252 | struct ubi_volume_desc *gluebi_desc; |
| @@ -235,8 +256,7 @@ struct ubi_volume { | |||
| 235 | }; | 256 | }; |
| 236 | 257 | ||
| 237 | /** | 258 | /** |
| 238 | * struct ubi_volume_desc - descriptor of the UBI volume returned when it is | 259 | * struct ubi_volume_desc - UBI volume descriptor returned when it is opened. |
| 239 | * opened. | ||
| 240 | * @vol: reference to the corresponding volume description object | 260 | * @vol: reference to the corresponding volume description object |
| 241 | * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE) | 261 | * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE) |
| 242 | */ | 262 | */ |
| @@ -273,7 +293,7 @@ struct ubi_wl_entry; | |||
| 273 | * @vtbl_size: size of the volume table in bytes | 293 | * @vtbl_size: size of the volume table in bytes |
| 274 | * @vtbl: in-RAM volume table copy | 294 | * @vtbl: in-RAM volume table copy |
| 275 | * @volumes_mutex: protects on-flash volume table and serializes volume | 295 | * @volumes_mutex: protects on-flash volume table and serializes volume |
| 276 | * changes, like creation, deletion, update, resize | 296 | * changes, like creation, deletion, update, re-size and re-name |
| 277 | * | 297 | * |
| 278 | * @max_ec: current highest erase counter value | 298 | * @max_ec: current highest erase counter value |
| 279 | * @mean_ec: current mean erase counter value | 299 | * @mean_ec: current mean erase counter value |
| @@ -293,6 +313,7 @@ struct ubi_wl_entry; | |||
| 293 | * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works | 313 | * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works |
| 294 | * fields | 314 | * fields |
| 295 | * @move_mutex: serializes eraseblock moves | 315 | * @move_mutex: serializes eraseblock moves |
| 316 | * @work_sem: sycnhronizes the WL worker with use tasks | ||
| 296 | * @wl_scheduled: non-zero if the wear-leveling was scheduled | 317 | * @wl_scheduled: non-zero if the wear-leveling was scheduled |
| 297 | * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any | 318 | * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any |
| 298 | * physical eraseblock | 319 | * physical eraseblock |
| @@ -316,11 +337,11 @@ struct ubi_wl_entry; | |||
| 316 | * @ro_mode: if the UBI device is in read-only mode | 337 | * @ro_mode: if the UBI device is in read-only mode |
| 317 | * @leb_size: logical eraseblock size | 338 | * @leb_size: logical eraseblock size |
| 318 | * @leb_start: starting offset of logical eraseblocks within physical | 339 | * @leb_start: starting offset of logical eraseblocks within physical |
| 319 | * eraseblocks | 340 | * eraseblocks |
| 320 | * @ec_hdr_alsize: size of the EC header aligned to @hdrs_min_io_size | 341 | * @ec_hdr_alsize: size of the EC header aligned to @hdrs_min_io_size |
| 321 | * @vid_hdr_alsize: size of the VID header aligned to @hdrs_min_io_size | 342 | * @vid_hdr_alsize: size of the VID header aligned to @hdrs_min_io_size |
| 322 | * @vid_hdr_offset: starting offset of the volume identifier header (might be | 343 | * @vid_hdr_offset: starting offset of the volume identifier header (might be |
| 323 | * unaligned) | 344 | * unaligned) |
| 324 | * @vid_hdr_aloffset: starting offset of the VID header aligned to | 345 | * @vid_hdr_aloffset: starting offset of the VID header aligned to |
| 325 | * @hdrs_min_io_size | 346 | * @hdrs_min_io_size |
| 326 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset | 347 | * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset |
| @@ -331,6 +352,8 @@ struct ubi_wl_entry; | |||
| 331 | * @peb_buf1: a buffer of PEB size used for different purposes | 352 | * @peb_buf1: a buffer of PEB size used for different purposes |
| 332 | * @peb_buf2: another buffer of PEB size used for different purposes | 353 | * @peb_buf2: another buffer of PEB size used for different purposes |
| 333 | * @buf_mutex: proptects @peb_buf1 and @peb_buf2 | 354 | * @buf_mutex: proptects @peb_buf1 and @peb_buf2 |
| 355 | * @ckvol_mutex: serializes static volume checking when opening | ||
| 356 | * @mult_mutex: serializes operations on multiple volumes, like re-nameing | ||
| 334 | * @dbg_peb_buf: buffer of PEB size used for debugging | 357 | * @dbg_peb_buf: buffer of PEB size used for debugging |
| 335 | * @dbg_buf_mutex: proptects @dbg_peb_buf | 358 | * @dbg_buf_mutex: proptects @dbg_peb_buf |
| 336 | */ | 359 | */ |
| @@ -356,16 +379,16 @@ struct ubi_device { | |||
| 356 | struct mutex volumes_mutex; | 379 | struct mutex volumes_mutex; |
| 357 | 380 | ||
| 358 | int max_ec; | 381 | int max_ec; |
| 359 | /* TODO: mean_ec is not updated run-time, fix */ | 382 | /* Note, mean_ec is not updated run-time - should be fixed */ |
| 360 | int mean_ec; | 383 | int mean_ec; |
| 361 | 384 | ||
| 362 | /* EBA unit's stuff */ | 385 | /* EBA sub-system's stuff */ |
| 363 | unsigned long long global_sqnum; | 386 | unsigned long long global_sqnum; |
| 364 | spinlock_t ltree_lock; | 387 | spinlock_t ltree_lock; |
| 365 | struct rb_root ltree; | 388 | struct rb_root ltree; |
| 366 | struct mutex alc_mutex; | 389 | struct mutex alc_mutex; |
| 367 | 390 | ||
| 368 | /* Wear-leveling unit's stuff */ | 391 | /* Wear-leveling sub-system's stuff */ |
| 369 | struct rb_root used; | 392 | struct rb_root used; |
| 370 | struct rb_root free; | 393 | struct rb_root free; |
| 371 | struct rb_root scrub; | 394 | struct rb_root scrub; |
| @@ -388,7 +411,7 @@ struct ubi_device { | |||
| 388 | int thread_enabled; | 411 | int thread_enabled; |
| 389 | char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2]; | 412 | char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2]; |
| 390 | 413 | ||
| 391 | /* I/O unit's stuff */ | 414 | /* I/O sub-system's stuff */ |
| 392 | long long flash_size; | 415 | long long flash_size; |
| 393 | int peb_count; | 416 | int peb_count; |
| 394 | int peb_size; | 417 | int peb_size; |
| @@ -411,6 +434,7 @@ struct ubi_device { | |||
| 411 | void *peb_buf2; | 434 | void *peb_buf2; |
| 412 | struct mutex buf_mutex; | 435 | struct mutex buf_mutex; |
| 413 | struct mutex ckvol_mutex; | 436 | struct mutex ckvol_mutex; |
| 437 | struct mutex mult_mutex; | ||
| 414 | #ifdef CONFIG_MTD_UBI_DEBUG | 438 | #ifdef CONFIG_MTD_UBI_DEBUG |
| 415 | void *dbg_peb_buf; | 439 | void *dbg_peb_buf; |
| 416 | struct mutex dbg_buf_mutex; | 440 | struct mutex dbg_buf_mutex; |
| @@ -427,12 +451,15 @@ extern struct mutex ubi_devices_mutex; | |||
| 427 | /* vtbl.c */ | 451 | /* vtbl.c */ |
| 428 | int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, | 452 | int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, |
| 429 | struct ubi_vtbl_record *vtbl_rec); | 453 | struct ubi_vtbl_record *vtbl_rec); |
| 454 | int ubi_vtbl_rename_volumes(struct ubi_device *ubi, | ||
| 455 | struct list_head *rename_list); | ||
| 430 | int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si); | 456 | int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si); |
| 431 | 457 | ||
| 432 | /* vmt.c */ | 458 | /* vmt.c */ |
| 433 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req); | 459 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req); |
| 434 | int ubi_remove_volume(struct ubi_volume_desc *desc); | 460 | int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl); |
| 435 | int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs); | 461 | int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs); |
| 462 | int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list); | ||
| 436 | int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol); | 463 | int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol); |
| 437 | void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol); | 464 | void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol); |
| 438 | 465 | ||
| @@ -447,7 +474,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 447 | const void __user *buf, int count); | 474 | const void __user *buf, int count); |
| 448 | 475 | ||
| 449 | /* misc.c */ | 476 | /* misc.c */ |
| 450 | int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length); | 477 | int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, |
| 478 | int length); | ||
| 451 | int ubi_check_volume(struct ubi_device *ubi, int vol_id); | 479 | int ubi_check_volume(struct ubi_device *ubi, int vol_id); |
| 452 | void ubi_calculate_reserved(struct ubi_device *ubi); | 480 | void ubi_calculate_reserved(struct ubi_device *ubi); |
| 453 | 481 | ||
| @@ -477,7 +505,6 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 477 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | 505 | int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, |
| 478 | struct ubi_vid_hdr *vid_hdr); | 506 | struct ubi_vid_hdr *vid_hdr); |
| 479 | int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); | 507 | int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); |
| 480 | void ubi_eba_close(const struct ubi_device *ubi); | ||
| 481 | 508 | ||
| 482 | /* wl.c */ | 509 | /* wl.c */ |
| 483 | int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); | 510 | int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); |
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index ddaa1a56cc69..8b89cc18ff0b 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | */ | 39 | */ |
| 40 | 40 | ||
| 41 | #include <linux/err.h> | 41 | #include <linux/err.h> |
| 42 | #include <asm/uaccess.h> | 42 | #include <linux/uaccess.h> |
| 43 | #include <asm/div64.h> | 43 | #include <asm/div64.h> |
| 44 | #include "ubi.h" | 44 | #include "ubi.h" |
| 45 | 45 | ||
| @@ -56,11 +56,11 @@ static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 56 | int err; | 56 | int err; |
| 57 | struct ubi_vtbl_record vtbl_rec; | 57 | struct ubi_vtbl_record vtbl_rec; |
| 58 | 58 | ||
| 59 | dbg_msg("set update marker for volume %d", vol->vol_id); | 59 | dbg_gen("set update marker for volume %d", vol->vol_id); |
| 60 | 60 | ||
| 61 | if (vol->upd_marker) { | 61 | if (vol->upd_marker) { |
| 62 | ubi_assert(ubi->vtbl[vol->vol_id].upd_marker); | 62 | ubi_assert(ubi->vtbl[vol->vol_id].upd_marker); |
| 63 | dbg_msg("already set"); | 63 | dbg_gen("already set"); |
| 64 | return 0; | 64 | return 0; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| @@ -92,7 +92,7 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 92 | uint64_t tmp; | 92 | uint64_t tmp; |
| 93 | struct ubi_vtbl_record vtbl_rec; | 93 | struct ubi_vtbl_record vtbl_rec; |
| 94 | 94 | ||
| 95 | dbg_msg("clear update marker for volume %d", vol->vol_id); | 95 | dbg_gen("clear update marker for volume %d", vol->vol_id); |
| 96 | 96 | ||
| 97 | memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], | 97 | memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], |
| 98 | sizeof(struct ubi_vtbl_record)); | 98 | sizeof(struct ubi_vtbl_record)); |
| @@ -133,7 +133,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 133 | int i, err; | 133 | int i, err; |
| 134 | uint64_t tmp; | 134 | uint64_t tmp; |
| 135 | 135 | ||
| 136 | dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes); | 136 | dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes); |
| 137 | ubi_assert(!vol->updating && !vol->changing_leb); | 137 | ubi_assert(!vol->updating && !vol->changing_leb); |
| 138 | vol->updating = 1; | 138 | vol->updating = 1; |
| 139 | 139 | ||
| @@ -183,7 +183,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 183 | { | 183 | { |
| 184 | ubi_assert(!vol->updating && !vol->changing_leb); | 184 | ubi_assert(!vol->updating && !vol->changing_leb); |
| 185 | 185 | ||
| 186 | dbg_msg("start changing LEB %d:%d, %u bytes", | 186 | dbg_gen("start changing LEB %d:%d, %u bytes", |
| 187 | vol->vol_id, req->lnum, req->bytes); | 187 | vol->vol_id, req->lnum, req->bytes); |
| 188 | if (req->bytes == 0) | 188 | if (req->bytes == 0) |
| 189 | return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0, | 189 | return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0, |
| @@ -237,16 +237,17 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
| 237 | int err; | 237 | int err; |
| 238 | 238 | ||
| 239 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { | 239 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
| 240 | len = ALIGN(len, ubi->min_io_size); | 240 | int l = ALIGN(len, ubi->min_io_size); |
| 241 | memset(buf + len, 0xFF, len - len); | ||
| 242 | 241 | ||
| 243 | len = ubi_calc_data_len(ubi, buf, len); | 242 | memset(buf + len, 0xFF, l - len); |
| 243 | len = ubi_calc_data_len(ubi, buf, l); | ||
| 244 | if (len == 0) { | 244 | if (len == 0) { |
| 245 | dbg_msg("all %d bytes contain 0xFF - skip", len); | 245 | dbg_gen("all %d bytes contain 0xFF - skip", len); |
| 246 | return 0; | 246 | return 0; |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN); | 249 | err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, |
| 250 | UBI_UNKNOWN); | ||
| 250 | } else { | 251 | } else { |
| 251 | /* | 252 | /* |
| 252 | * When writing static volume, and this is the last logical | 253 | * When writing static volume, and this is the last logical |
| @@ -267,6 +268,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
| 267 | 268 | ||
| 268 | /** | 269 | /** |
| 269 | * ubi_more_update_data - write more update data. | 270 | * ubi_more_update_data - write more update data. |
| 271 | * @ubi: UBI device description object | ||
| 270 | * @vol: volume description object | 272 | * @vol: volume description object |
| 271 | * @buf: write data (user-space memory buffer) | 273 | * @buf: write data (user-space memory buffer) |
| 272 | * @count: how much bytes to write | 274 | * @count: how much bytes to write |
| @@ -283,7 +285,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 283 | uint64_t tmp; | 285 | uint64_t tmp; |
| 284 | int lnum, offs, err = 0, len, to_write = count; | 286 | int lnum, offs, err = 0, len, to_write = count; |
| 285 | 287 | ||
| 286 | dbg_msg("write %d of %lld bytes, %lld already passed", | 288 | dbg_gen("write %d of %lld bytes, %lld already passed", |
| 287 | count, vol->upd_bytes, vol->upd_received); | 289 | count, vol->upd_bytes, vol->upd_received); |
| 288 | 290 | ||
| 289 | if (ubi->ro_mode) | 291 | if (ubi->ro_mode) |
| @@ -384,6 +386,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 384 | 386 | ||
| 385 | /** | 387 | /** |
| 386 | * ubi_more_leb_change_data - accept more data for atomic LEB change. | 388 | * ubi_more_leb_change_data - accept more data for atomic LEB change. |
| 389 | * @ubi: UBI device description object | ||
| 387 | * @vol: volume description object | 390 | * @vol: volume description object |
| 388 | * @buf: write data (user-space memory buffer) | 391 | * @buf: write data (user-space memory buffer) |
| 389 | * @count: how much bytes to write | 392 | * @count: how much bytes to write |
| @@ -400,7 +403,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 400 | { | 403 | { |
| 401 | int err; | 404 | int err; |
| 402 | 405 | ||
| 403 | dbg_msg("write %d of %lld bytes, %lld already passed", | 406 | dbg_gen("write %d of %lld bytes, %lld already passed", |
| 404 | count, vol->upd_bytes, vol->upd_received); | 407 | count, vol->upd_bytes, vol->upd_received); |
| 405 | 408 | ||
| 406 | if (ubi->ro_mode) | 409 | if (ubi->ro_mode) |
| @@ -418,7 +421,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 418 | if (vol->upd_received == vol->upd_bytes) { | 421 | if (vol->upd_received == vol->upd_bytes) { |
| 419 | int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size); | 422 | int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size); |
| 420 | 423 | ||
| 421 | memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes); | 424 | memset(vol->upd_buf + vol->upd_bytes, 0xFF, |
| 425 | len - vol->upd_bytes); | ||
| 422 | len = ubi_calc_data_len(ubi, vol->upd_buf, len); | 426 | len = ubi_calc_data_len(ubi, vol->upd_buf, len); |
| 423 | err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, | 427 | err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, |
| 424 | vol->upd_buf, len, UBI_UNKNOWN); | 428 | vol->upd_buf, len, UBI_UNKNOWN); |
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 5be58d85c639..3531ca9a1e24 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
| @@ -28,9 +28,9 @@ | |||
| 28 | #include "ubi.h" | 28 | #include "ubi.h" |
| 29 | 29 | ||
| 30 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 30 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| 31 | static void paranoid_check_volumes(struct ubi_device *ubi); | 31 | static int paranoid_check_volumes(struct ubi_device *ubi); |
| 32 | #else | 32 | #else |
| 33 | #define paranoid_check_volumes(ubi) | 33 | #define paranoid_check_volumes(ubi) 0 |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | static ssize_t vol_attribute_show(struct device *dev, | 36 | static ssize_t vol_attribute_show(struct device *dev, |
| @@ -127,6 +127,7 @@ static void vol_release(struct device *dev) | |||
| 127 | { | 127 | { |
| 128 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); | 128 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
| 129 | 129 | ||
| 130 | kfree(vol->eba_tbl); | ||
| 130 | kfree(vol); | 131 | kfree(vol); |
| 131 | } | 132 | } |
| 132 | 133 | ||
| @@ -201,7 +202,7 @@ static void volume_sysfs_close(struct ubi_volume *vol) | |||
| 201 | */ | 202 | */ |
| 202 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | 203 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) |
| 203 | { | 204 | { |
| 204 | int i, err, vol_id = req->vol_id, dont_free = 0; | 205 | int i, err, vol_id = req->vol_id, do_free = 1; |
| 205 | struct ubi_volume *vol; | 206 | struct ubi_volume *vol; |
| 206 | struct ubi_vtbl_record vtbl_rec; | 207 | struct ubi_vtbl_record vtbl_rec; |
| 207 | uint64_t bytes; | 208 | uint64_t bytes; |
| @@ -217,7 +218,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 217 | spin_lock(&ubi->volumes_lock); | 218 | spin_lock(&ubi->volumes_lock); |
| 218 | if (vol_id == UBI_VOL_NUM_AUTO) { | 219 | if (vol_id == UBI_VOL_NUM_AUTO) { |
| 219 | /* Find unused volume ID */ | 220 | /* Find unused volume ID */ |
| 220 | dbg_msg("search for vacant volume ID"); | 221 | dbg_gen("search for vacant volume ID"); |
| 221 | for (i = 0; i < ubi->vtbl_slots; i++) | 222 | for (i = 0; i < ubi->vtbl_slots; i++) |
| 222 | if (!ubi->volumes[i]) { | 223 | if (!ubi->volumes[i]) { |
| 223 | vol_id = i; | 224 | vol_id = i; |
| @@ -232,7 +233,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 232 | req->vol_id = vol_id; | 233 | req->vol_id = vol_id; |
| 233 | } | 234 | } |
| 234 | 235 | ||
| 235 | dbg_msg("volume ID %d, %llu bytes, type %d, name %s", | 236 | dbg_gen("volume ID %d, %llu bytes, type %d, name %s", |
| 236 | vol_id, (unsigned long long)req->bytes, | 237 | vol_id, (unsigned long long)req->bytes, |
| 237 | (int)req->vol_type, req->name); | 238 | (int)req->vol_type, req->name); |
| 238 | 239 | ||
| @@ -252,7 +253,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 252 | goto out_unlock; | 253 | goto out_unlock; |
| 253 | } | 254 | } |
| 254 | 255 | ||
| 255 | /* Calculate how many eraseblocks are requested */ | 256 | /* Calculate how many eraseblocks are requested */ |
| 256 | vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; | 257 | vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; |
| 257 | bytes = req->bytes; | 258 | bytes = req->bytes; |
| 258 | if (do_div(bytes, vol->usable_leb_size)) | 259 | if (do_div(bytes, vol->usable_leb_size)) |
| @@ -274,7 +275,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 274 | vol->data_pad = ubi->leb_size % vol->alignment; | 275 | vol->data_pad = ubi->leb_size % vol->alignment; |
| 275 | vol->vol_type = req->vol_type; | 276 | vol->vol_type = req->vol_type; |
| 276 | vol->name_len = req->name_len; | 277 | vol->name_len = req->name_len; |
| 277 | memcpy(vol->name, req->name, vol->name_len + 1); | 278 | memcpy(vol->name, req->name, vol->name_len); |
| 278 | vol->ubi = ubi; | 279 | vol->ubi = ubi; |
| 279 | 280 | ||
| 280 | /* | 281 | /* |
| @@ -349,7 +350,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 349 | vtbl_rec.vol_type = UBI_VID_DYNAMIC; | 350 | vtbl_rec.vol_type = UBI_VID_DYNAMIC; |
| 350 | else | 351 | else |
| 351 | vtbl_rec.vol_type = UBI_VID_STATIC; | 352 | vtbl_rec.vol_type = UBI_VID_STATIC; |
| 352 | memcpy(vtbl_rec.name, vol->name, vol->name_len + 1); | 353 | memcpy(vtbl_rec.name, vol->name, vol->name_len); |
| 353 | 354 | ||
| 354 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | 355 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); |
| 355 | if (err) | 356 | if (err) |
| @@ -360,19 +361,19 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 360 | ubi->vol_count += 1; | 361 | ubi->vol_count += 1; |
| 361 | spin_unlock(&ubi->volumes_lock); | 362 | spin_unlock(&ubi->volumes_lock); |
| 362 | 363 | ||
| 363 | paranoid_check_volumes(ubi); | 364 | err = paranoid_check_volumes(ubi); |
| 364 | return 0; | 365 | return err; |
| 365 | 366 | ||
| 366 | out_sysfs: | 367 | out_sysfs: |
| 367 | /* | 368 | /* |
| 368 | * We have registered our device, we should not free the volume* | 369 | * We have registered our device, we should not free the volume |
| 369 | * description object in this function in case of an error - it is | 370 | * description object in this function in case of an error - it is |
| 370 | * freed by the release function. | 371 | * freed by the release function. |
| 371 | * | 372 | * |
| 372 | * Get device reference to prevent the release function from being | 373 | * Get device reference to prevent the release function from being |
| 373 | * called just after sysfs has been closed. | 374 | * called just after sysfs has been closed. |
| 374 | */ | 375 | */ |
| 375 | dont_free = 1; | 376 | do_free = 0; |
| 376 | get_device(&vol->dev); | 377 | get_device(&vol->dev); |
| 377 | volume_sysfs_close(vol); | 378 | volume_sysfs_close(vol); |
| 378 | out_gluebi: | 379 | out_gluebi: |
| @@ -382,17 +383,18 @@ out_gluebi: | |||
| 382 | out_cdev: | 383 | out_cdev: |
| 383 | cdev_del(&vol->cdev); | 384 | cdev_del(&vol->cdev); |
| 384 | out_mapping: | 385 | out_mapping: |
| 385 | kfree(vol->eba_tbl); | 386 | if (do_free) |
| 387 | kfree(vol->eba_tbl); | ||
| 386 | out_acc: | 388 | out_acc: |
| 387 | spin_lock(&ubi->volumes_lock); | 389 | spin_lock(&ubi->volumes_lock); |
| 388 | ubi->rsvd_pebs -= vol->reserved_pebs; | 390 | ubi->rsvd_pebs -= vol->reserved_pebs; |
| 389 | ubi->avail_pebs += vol->reserved_pebs; | 391 | ubi->avail_pebs += vol->reserved_pebs; |
| 390 | out_unlock: | 392 | out_unlock: |
| 391 | spin_unlock(&ubi->volumes_lock); | 393 | spin_unlock(&ubi->volumes_lock); |
| 392 | if (dont_free) | 394 | if (do_free) |
| 393 | put_device(&vol->dev); | ||
| 394 | else | ||
| 395 | kfree(vol); | 395 | kfree(vol); |
| 396 | else | ||
| 397 | put_device(&vol->dev); | ||
| 396 | ubi_err("cannot create volume %d, error %d", vol_id, err); | 398 | ubi_err("cannot create volume %d, error %d", vol_id, err); |
| 397 | return err; | 399 | return err; |
| 398 | } | 400 | } |
| @@ -400,19 +402,20 @@ out_unlock: | |||
| 400 | /** | 402 | /** |
| 401 | * ubi_remove_volume - remove volume. | 403 | * ubi_remove_volume - remove volume. |
| 402 | * @desc: volume descriptor | 404 | * @desc: volume descriptor |
| 405 | * @no_vtbl: do not change volume table if not zero | ||
| 403 | * | 406 | * |
| 404 | * This function removes volume described by @desc. The volume has to be opened | 407 | * This function removes volume described by @desc. The volume has to be opened |
| 405 | * in "exclusive" mode. Returns zero in case of success and a negative error | 408 | * in "exclusive" mode. Returns zero in case of success and a negative error |
| 406 | * code in case of failure. The caller has to have the @ubi->volumes_mutex | 409 | * code in case of failure. The caller has to have the @ubi->volumes_mutex |
| 407 | * locked. | 410 | * locked. |
| 408 | */ | 411 | */ |
| 409 | int ubi_remove_volume(struct ubi_volume_desc *desc) | 412 | int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) |
| 410 | { | 413 | { |
| 411 | struct ubi_volume *vol = desc->vol; | 414 | struct ubi_volume *vol = desc->vol; |
| 412 | struct ubi_device *ubi = vol->ubi; | 415 | struct ubi_device *ubi = vol->ubi; |
| 413 | int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs; | 416 | int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs; |
| 414 | 417 | ||
| 415 | dbg_msg("remove UBI volume %d", vol_id); | 418 | dbg_gen("remove UBI volume %d", vol_id); |
| 416 | ubi_assert(desc->mode == UBI_EXCLUSIVE); | 419 | ubi_assert(desc->mode == UBI_EXCLUSIVE); |
| 417 | ubi_assert(vol == ubi->volumes[vol_id]); | 420 | ubi_assert(vol == ubi->volumes[vol_id]); |
| 418 | 421 | ||
| @@ -435,9 +438,11 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
| 435 | if (err) | 438 | if (err) |
| 436 | goto out_err; | 439 | goto out_err; |
| 437 | 440 | ||
| 438 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); | 441 | if (!no_vtbl) { |
| 439 | if (err) | 442 | err = ubi_change_vtbl_record(ubi, vol_id, NULL); |
| 440 | goto out_err; | 443 | if (err) |
| 444 | goto out_err; | ||
| 445 | } | ||
| 441 | 446 | ||
| 442 | for (i = 0; i < vol->reserved_pebs; i++) { | 447 | for (i = 0; i < vol->reserved_pebs; i++) { |
| 443 | err = ubi_eba_unmap_leb(ubi, vol, i); | 448 | err = ubi_eba_unmap_leb(ubi, vol, i); |
| @@ -445,8 +450,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
| 445 | goto out_err; | 450 | goto out_err; |
| 446 | } | 451 | } |
| 447 | 452 | ||
| 448 | kfree(vol->eba_tbl); | ||
| 449 | vol->eba_tbl = NULL; | ||
| 450 | cdev_del(&vol->cdev); | 453 | cdev_del(&vol->cdev); |
| 451 | volume_sysfs_close(vol); | 454 | volume_sysfs_close(vol); |
| 452 | 455 | ||
| @@ -465,8 +468,9 @@ int ubi_remove_volume(struct ubi_volume_desc *desc) | |||
| 465 | ubi->vol_count -= 1; | 468 | ubi->vol_count -= 1; |
| 466 | spin_unlock(&ubi->volumes_lock); | 469 | spin_unlock(&ubi->volumes_lock); |
| 467 | 470 | ||
| 468 | paranoid_check_volumes(ubi); | 471 | if (!no_vtbl) |
| 469 | return 0; | 472 | err = paranoid_check_volumes(ubi); |
| 473 | return err; | ||
| 470 | 474 | ||
| 471 | out_err: | 475 | out_err: |
| 472 | ubi_err("cannot remove volume %d, error %d", vol_id, err); | 476 | ubi_err("cannot remove volume %d, error %d", vol_id, err); |
| @@ -497,7 +501,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
| 497 | if (ubi->ro_mode) | 501 | if (ubi->ro_mode) |
| 498 | return -EROFS; | 502 | return -EROFS; |
| 499 | 503 | ||
| 500 | dbg_msg("re-size volume %d to from %d to %d PEBs", | 504 | dbg_gen("re-size volume %d to from %d to %d PEBs", |
| 501 | vol_id, vol->reserved_pebs, reserved_pebs); | 505 | vol_id, vol->reserved_pebs, reserved_pebs); |
| 502 | 506 | ||
| 503 | if (vol->vol_type == UBI_STATIC_VOLUME && | 507 | if (vol->vol_type == UBI_STATIC_VOLUME && |
| @@ -586,8 +590,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
| 586 | (long long)vol->used_ebs * vol->usable_leb_size; | 590 | (long long)vol->used_ebs * vol->usable_leb_size; |
| 587 | } | 591 | } |
| 588 | 592 | ||
| 589 | paranoid_check_volumes(ubi); | 593 | err = paranoid_check_volumes(ubi); |
| 590 | return 0; | 594 | return err; |
| 591 | 595 | ||
| 592 | out_acc: | 596 | out_acc: |
| 593 | if (pebs > 0) { | 597 | if (pebs > 0) { |
| @@ -602,6 +606,44 @@ out_free: | |||
| 602 | } | 606 | } |
| 603 | 607 | ||
| 604 | /** | 608 | /** |
| 609 | * ubi_rename_volumes - re-name UBI volumes. | ||
| 610 | * @ubi: UBI device description object | ||
| 611 | * @rename_list: list of &struct ubi_rename_entry objects | ||
| 612 | * | ||
| 613 | * This function re-names or removes volumes specified in the re-name list. | ||
| 614 | * Returns zero in case of success and a negative error code in case of | ||
| 615 | * failure. | ||
| 616 | */ | ||
| 617 | int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list) | ||
| 618 | { | ||
| 619 | int err; | ||
| 620 | struct ubi_rename_entry *re; | ||
| 621 | |||
| 622 | err = ubi_vtbl_rename_volumes(ubi, rename_list); | ||
| 623 | if (err) | ||
| 624 | return err; | ||
| 625 | |||
| 626 | list_for_each_entry(re, rename_list, list) { | ||
| 627 | if (re->remove) { | ||
| 628 | err = ubi_remove_volume(re->desc, 1); | ||
| 629 | if (err) | ||
| 630 | break; | ||
| 631 | } else { | ||
| 632 | struct ubi_volume *vol = re->desc->vol; | ||
| 633 | |||
| 634 | spin_lock(&ubi->volumes_lock); | ||
| 635 | vol->name_len = re->new_name_len; | ||
| 636 | memcpy(vol->name, re->new_name, re->new_name_len + 1); | ||
| 637 | spin_unlock(&ubi->volumes_lock); | ||
| 638 | } | ||
| 639 | } | ||
| 640 | |||
| 641 | if (!err) | ||
| 642 | err = paranoid_check_volumes(ubi); | ||
| 643 | return err; | ||
| 644 | } | ||
| 645 | |||
| 646 | /** | ||
| 605 | * ubi_add_volume - add volume. | 647 | * ubi_add_volume - add volume. |
| 606 | * @ubi: UBI device description object | 648 | * @ubi: UBI device description object |
| 607 | * @vol: volume description object | 649 | * @vol: volume description object |
| @@ -615,8 +657,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 615 | int err, vol_id = vol->vol_id; | 657 | int err, vol_id = vol->vol_id; |
| 616 | dev_t dev; | 658 | dev_t dev; |
| 617 | 659 | ||
| 618 | dbg_msg("add volume %d", vol_id); | 660 | dbg_gen("add volume %d", vol_id); |
| 619 | ubi_dbg_dump_vol_info(vol); | ||
| 620 | 661 | ||
| 621 | /* Register character device for the volume */ | 662 | /* Register character device for the volume */ |
| 622 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); | 663 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); |
| @@ -650,8 +691,8 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 650 | return err; | 691 | return err; |
| 651 | } | 692 | } |
| 652 | 693 | ||
| 653 | paranoid_check_volumes(ubi); | 694 | err = paranoid_check_volumes(ubi); |
| 654 | return 0; | 695 | return err; |
| 655 | 696 | ||
| 656 | out_gluebi: | 697 | out_gluebi: |
| 657 | err = ubi_destroy_gluebi(vol); | 698 | err = ubi_destroy_gluebi(vol); |
| @@ -672,7 +713,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 672 | { | 713 | { |
| 673 | int err; | 714 | int err; |
| 674 | 715 | ||
| 675 | dbg_msg("free volume %d", vol->vol_id); | 716 | dbg_gen("free volume %d", vol->vol_id); |
| 676 | 717 | ||
| 677 | ubi->volumes[vol->vol_id] = NULL; | 718 | ubi->volumes[vol->vol_id] = NULL; |
| 678 | err = ubi_destroy_gluebi(vol); | 719 | err = ubi_destroy_gluebi(vol); |
| @@ -686,8 +727,10 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 686 | * paranoid_check_volume - check volume information. | 727 | * paranoid_check_volume - check volume information. |
| 687 | * @ubi: UBI device description object | 728 | * @ubi: UBI device description object |
| 688 | * @vol_id: volume ID | 729 | * @vol_id: volume ID |
| 730 | * | ||
| 731 | * Returns zero if volume is all right and a a negative error code if not. | ||
| 689 | */ | 732 | */ |
| 690 | static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | 733 | static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) |
| 691 | { | 734 | { |
| 692 | int idx = vol_id2idx(ubi, vol_id); | 735 | int idx = vol_id2idx(ubi, vol_id); |
| 693 | int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; | 736 | int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; |
| @@ -705,16 +748,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
| 705 | goto fail; | 748 | goto fail; |
| 706 | } | 749 | } |
| 707 | spin_unlock(&ubi->volumes_lock); | 750 | spin_unlock(&ubi->volumes_lock); |
| 708 | return; | 751 | return 0; |
| 709 | } | ||
| 710 | |||
| 711 | if (vol->exclusive) { | ||
| 712 | /* | ||
| 713 | * The volume may be being created at the moment, do not check | ||
| 714 | * it (e.g., it may be in the middle of ubi_create_volume(). | ||
| 715 | */ | ||
| 716 | spin_unlock(&ubi->volumes_lock); | ||
| 717 | return; | ||
| 718 | } | 752 | } |
| 719 | 753 | ||
| 720 | if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 || | 754 | if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 || |
| @@ -727,7 +761,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
| 727 | goto fail; | 761 | goto fail; |
| 728 | } | 762 | } |
| 729 | 763 | ||
| 730 | n = vol->alignment % ubi->min_io_size; | 764 | n = vol->alignment & (ubi->min_io_size - 1); |
| 731 | if (vol->alignment != 1 && n) { | 765 | if (vol->alignment != 1 && n) { |
| 732 | ubi_err("alignment is not multiple of min I/O unit"); | 766 | ubi_err("alignment is not multiple of min I/O unit"); |
| 733 | goto fail; | 767 | goto fail; |
| @@ -824,31 +858,39 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) | |||
| 824 | 858 | ||
| 825 | if (alignment != vol->alignment || data_pad != vol->data_pad || | 859 | if (alignment != vol->alignment || data_pad != vol->data_pad || |
| 826 | upd_marker != vol->upd_marker || vol_type != vol->vol_type || | 860 | upd_marker != vol->upd_marker || vol_type != vol->vol_type || |
| 827 | name_len!= vol->name_len || strncmp(name, vol->name, name_len)) { | 861 | name_len != vol->name_len || strncmp(name, vol->name, name_len)) { |
| 828 | ubi_err("volume info is different"); | 862 | ubi_err("volume info is different"); |
| 829 | goto fail; | 863 | goto fail; |
| 830 | } | 864 | } |
| 831 | 865 | ||
| 832 | spin_unlock(&ubi->volumes_lock); | 866 | spin_unlock(&ubi->volumes_lock); |
| 833 | return; | 867 | return 0; |
| 834 | 868 | ||
| 835 | fail: | 869 | fail: |
| 836 | ubi_err("paranoid check failed for volume %d", vol_id); | 870 | ubi_err("paranoid check failed for volume %d", vol_id); |
| 837 | ubi_dbg_dump_vol_info(vol); | 871 | if (vol) |
| 872 | ubi_dbg_dump_vol_info(vol); | ||
| 838 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); | 873 | ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); |
| 839 | spin_unlock(&ubi->volumes_lock); | 874 | spin_unlock(&ubi->volumes_lock); |
| 840 | BUG(); | 875 | return -EINVAL; |
| 841 | } | 876 | } |
| 842 | 877 | ||
| 843 | /** | 878 | /** |
| 844 | * paranoid_check_volumes - check information about all volumes. | 879 | * paranoid_check_volumes - check information about all volumes. |
| 845 | * @ubi: UBI device description object | 880 | * @ubi: UBI device description object |
| 881 | * | ||
| 882 | * Returns zero if volumes are all right and a a negative error code if not. | ||
| 846 | */ | 883 | */ |
| 847 | static void paranoid_check_volumes(struct ubi_device *ubi) | 884 | static int paranoid_check_volumes(struct ubi_device *ubi) |
| 848 | { | 885 | { |
| 849 | int i; | 886 | int i, err = 0; |
| 850 | 887 | ||
| 851 | for (i = 0; i < ubi->vtbl_slots; i++) | 888 | for (i = 0; i < ubi->vtbl_slots; i++) { |
| 852 | paranoid_check_volume(ubi, i); | 889 | err = paranoid_check_volume(ubi, i); |
| 890 | if (err) | ||
| 891 | break; | ||
| 892 | } | ||
| 893 | |||
| 894 | return err; | ||
| 853 | } | 895 | } |
| 854 | #endif | 896 | #endif |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index af36b12be278..217d0e111b2a 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
| @@ -115,8 +115,58 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, | |||
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | /** | 117 | /** |
| 118 | * vtbl_check - check if volume table is not corrupted and contains sensible | 118 | * ubi_vtbl_rename_volumes - rename UBI volumes in the volume table. |
| 119 | * data. | 119 | * @ubi: UBI device description object |
| 120 | * @rename_list: list of &struct ubi_rename_entry objects | ||
| 121 | * | ||
| 122 | * This function re-names multiple volumes specified in @req in the volume | ||
| 123 | * table. Returns zero in case of success and a negative error code in case of | ||
| 124 | * failure. | ||
| 125 | */ | ||
| 126 | int ubi_vtbl_rename_volumes(struct ubi_device *ubi, | ||
| 127 | struct list_head *rename_list) | ||
| 128 | { | ||
| 129 | int i, err; | ||
| 130 | struct ubi_rename_entry *re; | ||
| 131 | struct ubi_volume *layout_vol; | ||
| 132 | |||
| 133 | list_for_each_entry(re, rename_list, list) { | ||
| 134 | uint32_t crc; | ||
| 135 | struct ubi_volume *vol = re->desc->vol; | ||
| 136 | struct ubi_vtbl_record *vtbl_rec = &ubi->vtbl[vol->vol_id]; | ||
| 137 | |||
| 138 | if (re->remove) { | ||
| 139 | memcpy(vtbl_rec, &empty_vtbl_record, | ||
| 140 | sizeof(struct ubi_vtbl_record)); | ||
| 141 | continue; | ||
| 142 | } | ||
| 143 | |||
| 144 | vtbl_rec->name_len = cpu_to_be16(re->new_name_len); | ||
| 145 | memcpy(vtbl_rec->name, re->new_name, re->new_name_len); | ||
| 146 | memset(vtbl_rec->name + re->new_name_len, 0, | ||
| 147 | UBI_VOL_NAME_MAX + 1 - re->new_name_len); | ||
| 148 | crc = crc32(UBI_CRC32_INIT, vtbl_rec, | ||
| 149 | UBI_VTBL_RECORD_SIZE_CRC); | ||
| 150 | vtbl_rec->crc = cpu_to_be32(crc); | ||
| 151 | } | ||
| 152 | |||
| 153 | layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)]; | ||
| 154 | for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { | ||
| 155 | err = ubi_eba_unmap_leb(ubi, layout_vol, i); | ||
| 156 | if (err) | ||
| 157 | return err; | ||
| 158 | |||
| 159 | err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, | ||
| 160 | ubi->vtbl_size, UBI_LONGTERM); | ||
| 161 | if (err) | ||
| 162 | return err; | ||
| 163 | } | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * vtbl_check - check if volume table is not corrupted and sensible. | ||
| 120 | * @ubi: UBI device description object | 170 | * @ubi: UBI device description object |
| 121 | * @vtbl: volume table | 171 | * @vtbl: volume table |
| 122 | * | 172 | * |
| @@ -127,7 +177,7 @@ static int vtbl_check(const struct ubi_device *ubi, | |||
| 127 | const struct ubi_vtbl_record *vtbl) | 177 | const struct ubi_vtbl_record *vtbl) |
| 128 | { | 178 | { |
| 129 | int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len; | 179 | int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len; |
| 130 | int upd_marker; | 180 | int upd_marker, err; |
| 131 | uint32_t crc; | 181 | uint32_t crc; |
| 132 | const char *name; | 182 | const char *name; |
| 133 | 183 | ||
| @@ -153,7 +203,7 @@ static int vtbl_check(const struct ubi_device *ubi, | |||
| 153 | if (reserved_pebs == 0) { | 203 | if (reserved_pebs == 0) { |
| 154 | if (memcmp(&vtbl[i], &empty_vtbl_record, | 204 | if (memcmp(&vtbl[i], &empty_vtbl_record, |
| 155 | UBI_VTBL_RECORD_SIZE)) { | 205 | UBI_VTBL_RECORD_SIZE)) { |
| 156 | dbg_err("bad empty record"); | 206 | err = 2; |
| 157 | goto bad; | 207 | goto bad; |
| 158 | } | 208 | } |
| 159 | continue; | 209 | continue; |
| @@ -161,56 +211,57 @@ static int vtbl_check(const struct ubi_device *ubi, | |||
| 161 | 211 | ||
| 162 | if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 || | 212 | if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 || |
| 163 | name_len < 0) { | 213 | name_len < 0) { |
| 164 | dbg_err("negative values"); | 214 | err = 3; |
| 165 | goto bad; | 215 | goto bad; |
| 166 | } | 216 | } |
| 167 | 217 | ||
| 168 | if (alignment > ubi->leb_size || alignment == 0) { | 218 | if (alignment > ubi->leb_size || alignment == 0) { |
| 169 | dbg_err("bad alignment"); | 219 | err = 4; |
| 170 | goto bad; | 220 | goto bad; |
| 171 | } | 221 | } |
| 172 | 222 | ||
| 173 | n = alignment % ubi->min_io_size; | 223 | n = alignment & (ubi->min_io_size - 1); |
| 174 | if (alignment != 1 && n) { | 224 | if (alignment != 1 && n) { |
| 175 | dbg_err("alignment is not multiple of min I/O unit"); | 225 | err = 5; |
| 176 | goto bad; | 226 | goto bad; |
| 177 | } | 227 | } |
| 178 | 228 | ||
| 179 | n = ubi->leb_size % alignment; | 229 | n = ubi->leb_size % alignment; |
| 180 | if (data_pad != n) { | 230 | if (data_pad != n) { |
| 181 | dbg_err("bad data_pad, has to be %d", n); | 231 | dbg_err("bad data_pad, has to be %d", n); |
| 232 | err = 6; | ||
| 182 | goto bad; | 233 | goto bad; |
| 183 | } | 234 | } |
| 184 | 235 | ||
| 185 | if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) { | 236 | if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) { |
| 186 | dbg_err("bad vol_type"); | 237 | err = 7; |
| 187 | goto bad; | 238 | goto bad; |
| 188 | } | 239 | } |
| 189 | 240 | ||
| 190 | if (upd_marker != 0 && upd_marker != 1) { | 241 | if (upd_marker != 0 && upd_marker != 1) { |
| 191 | dbg_err("bad upd_marker"); | 242 | err = 8; |
| 192 | goto bad; | 243 | goto bad; |
| 193 | } | 244 | } |
| 194 | 245 | ||
| 195 | if (reserved_pebs > ubi->good_peb_count) { | 246 | if (reserved_pebs > ubi->good_peb_count) { |
| 196 | dbg_err("too large reserved_pebs, good PEBs %d", | 247 | dbg_err("too large reserved_pebs, good PEBs %d", |
| 197 | ubi->good_peb_count); | 248 | ubi->good_peb_count); |
| 249 | err = 9; | ||
| 198 | goto bad; | 250 | goto bad; |
| 199 | } | 251 | } |
| 200 | 252 | ||
| 201 | if (name_len > UBI_VOL_NAME_MAX) { | 253 | if (name_len > UBI_VOL_NAME_MAX) { |
| 202 | dbg_err("too long volume name, max %d", | 254 | err = 10; |
| 203 | UBI_VOL_NAME_MAX); | ||
| 204 | goto bad; | 255 | goto bad; |
| 205 | } | 256 | } |
| 206 | 257 | ||
| 207 | if (name[0] == '\0') { | 258 | if (name[0] == '\0') { |
| 208 | dbg_err("NULL volume name"); | 259 | err = 11; |
| 209 | goto bad; | 260 | goto bad; |
| 210 | } | 261 | } |
| 211 | 262 | ||
| 212 | if (name_len != strnlen(name, name_len + 1)) { | 263 | if (name_len != strnlen(name, name_len + 1)) { |
| 213 | dbg_err("bad name_len"); | 264 | err = 12; |
| 214 | goto bad; | 265 | goto bad; |
| 215 | } | 266 | } |
| 216 | } | 267 | } |
| @@ -235,7 +286,7 @@ static int vtbl_check(const struct ubi_device *ubi, | |||
| 235 | return 0; | 286 | return 0; |
| 236 | 287 | ||
| 237 | bad: | 288 | bad: |
| 238 | ubi_err("volume table check failed, record %d", i); | 289 | ubi_err("volume table check failed: record %d, error %d", i, err); |
| 239 | ubi_dbg_dump_vtbl_record(&vtbl[i], i); | 290 | ubi_dbg_dump_vtbl_record(&vtbl[i], i); |
| 240 | return -EINVAL; | 291 | return -EINVAL; |
| 241 | } | 292 | } |
| @@ -287,7 +338,6 @@ retry: | |||
| 287 | vid_hdr->data_pad = cpu_to_be32(0); | 338 | vid_hdr->data_pad = cpu_to_be32(0); |
| 288 | vid_hdr->lnum = cpu_to_be32(copy); | 339 | vid_hdr->lnum = cpu_to_be32(copy); |
| 289 | vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum); | 340 | vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum); |
| 290 | vid_hdr->leb_ver = cpu_to_be32(old_seb ? old_seb->leb_ver + 1: 0); | ||
| 291 | 341 | ||
| 292 | /* The EC header is already there, write the VID header */ | 342 | /* The EC header is already there, write the VID header */ |
| 293 | err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr); | 343 | err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr); |
| @@ -370,7 +420,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, | |||
| 370 | * to LEB 0. | 420 | * to LEB 0. |
| 371 | */ | 421 | */ |
| 372 | 422 | ||
| 373 | dbg_msg("check layout volume"); | 423 | dbg_gen("check layout volume"); |
| 374 | 424 | ||
| 375 | /* Read both LEB 0 and LEB 1 into memory */ | 425 | /* Read both LEB 0 and LEB 1 into memory */ |
| 376 | ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { | 426 | ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { |
| @@ -384,7 +434,16 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, | |||
| 384 | err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, | 434 | err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, |
| 385 | ubi->vtbl_size); | 435 | ubi->vtbl_size); |
| 386 | if (err == UBI_IO_BITFLIPS || err == -EBADMSG) | 436 | if (err == UBI_IO_BITFLIPS || err == -EBADMSG) |
| 387 | /* Scrub the PEB later */ | 437 | /* |
| 438 | * Scrub the PEB later. Note, -EBADMSG indicates an | ||
| 439 | * uncorrectable ECC error, but we have our own CRC and | ||
| 440 | * the data will be checked later. If the data is OK, | ||
| 441 | * the PEB will be scrubbed (because we set | ||
| 442 | * seb->scrub). If the data is not OK, the contents of | ||
| 443 | * the PEB will be recovered from the second copy, and | ||
| 444 | * seb->scrub will be cleared in | ||
| 445 | * 'ubi_scan_add_used()'. | ||
| 446 | */ | ||
| 388 | seb->scrub = 1; | 447 | seb->scrub = 1; |
| 389 | else if (err) | 448 | else if (err) |
| 390 | goto out_free; | 449 | goto out_free; |
| @@ -400,7 +459,8 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, | |||
| 400 | if (!leb_corrupted[0]) { | 459 | if (!leb_corrupted[0]) { |
| 401 | /* LEB 0 is OK */ | 460 | /* LEB 0 is OK */ |
| 402 | if (leb[1]) | 461 | if (leb[1]) |
| 403 | leb_corrupted[1] = memcmp(leb[0], leb[1], ubi->vtbl_size); | 462 | leb_corrupted[1] = memcmp(leb[0], leb[1], |
| 463 | ubi->vtbl_size); | ||
| 404 | if (leb_corrupted[1]) { | 464 | if (leb_corrupted[1]) { |
| 405 | ubi_warn("volume table copy #2 is corrupted"); | 465 | ubi_warn("volume table copy #2 is corrupted"); |
| 406 | err = create_vtbl(ubi, si, 1, leb[0]); | 466 | err = create_vtbl(ubi, si, 1, leb[0]); |
| @@ -620,30 +680,32 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
| 620 | static int check_sv(const struct ubi_volume *vol, | 680 | static int check_sv(const struct ubi_volume *vol, |
| 621 | const struct ubi_scan_volume *sv) | 681 | const struct ubi_scan_volume *sv) |
| 622 | { | 682 | { |
| 683 | int err; | ||
| 684 | |||
| 623 | if (sv->highest_lnum >= vol->reserved_pebs) { | 685 | if (sv->highest_lnum >= vol->reserved_pebs) { |
| 624 | dbg_err("bad highest_lnum"); | 686 | err = 1; |
| 625 | goto bad; | 687 | goto bad; |
| 626 | } | 688 | } |
| 627 | if (sv->leb_count > vol->reserved_pebs) { | 689 | if (sv->leb_count > vol->reserved_pebs) { |
| 628 | dbg_err("bad leb_count"); | 690 | err = 2; |
| 629 | goto bad; | 691 | goto bad; |
| 630 | } | 692 | } |
| 631 | if (sv->vol_type != vol->vol_type) { | 693 | if (sv->vol_type != vol->vol_type) { |
| 632 | dbg_err("bad vol_type"); | 694 | err = 3; |
| 633 | goto bad; | 695 | goto bad; |
| 634 | } | 696 | } |
| 635 | if (sv->used_ebs > vol->reserved_pebs) { | 697 | if (sv->used_ebs > vol->reserved_pebs) { |
| 636 | dbg_err("bad used_ebs"); | 698 | err = 4; |
| 637 | goto bad; | 699 | goto bad; |
| 638 | } | 700 | } |
| 639 | if (sv->data_pad != vol->data_pad) { | 701 | if (sv->data_pad != vol->data_pad) { |
| 640 | dbg_err("bad data_pad"); | 702 | err = 5; |
| 641 | goto bad; | 703 | goto bad; |
| 642 | } | 704 | } |
| 643 | return 0; | 705 | return 0; |
| 644 | 706 | ||
| 645 | bad: | 707 | bad: |
| 646 | ubi_err("bad scanning information"); | 708 | ubi_err("bad scanning information, error %d", err); |
| 647 | ubi_dbg_dump_sv(sv); | 709 | ubi_dbg_dump_sv(sv); |
| 648 | ubi_dbg_dump_vol_info(vol); | 710 | ubi_dbg_dump_vol_info(vol); |
| 649 | return -EINVAL; | 711 | return -EINVAL; |
| @@ -672,14 +734,13 @@ static int check_scanning_info(const struct ubi_device *ubi, | |||
| 672 | return -EINVAL; | 734 | return -EINVAL; |
| 673 | } | 735 | } |
| 674 | 736 | ||
| 675 | if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT&& | 737 | if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT && |
| 676 | si->highest_vol_id < UBI_INTERNAL_VOL_START) { | 738 | si->highest_vol_id < UBI_INTERNAL_VOL_START) { |
| 677 | ubi_err("too large volume ID %d found by scanning", | 739 | ubi_err("too large volume ID %d found by scanning", |
| 678 | si->highest_vol_id); | 740 | si->highest_vol_id); |
| 679 | return -EINVAL; | 741 | return -EINVAL; |
| 680 | } | 742 | } |
| 681 | 743 | ||
| 682 | |||
| 683 | for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { | 744 | for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { |
| 684 | cond_resched(); | 745 | cond_resched(); |
| 685 | 746 | ||
| @@ -717,8 +778,7 @@ static int check_scanning_info(const struct ubi_device *ubi, | |||
| 717 | } | 778 | } |
| 718 | 779 | ||
| 719 | /** | 780 | /** |
| 720 | * ubi_read_volume_table - read volume table. | 781 | * ubi_read_volume_table - read the volume table. |
| 721 | * information. | ||
| 722 | * @ubi: UBI device description object | 782 | * @ubi: UBI device description object |
| 723 | * @si: scanning information | 783 | * @si: scanning information |
| 724 | * | 784 | * |
| @@ -797,11 +857,10 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) | |||
| 797 | 857 | ||
| 798 | out_free: | 858 | out_free: |
| 799 | vfree(ubi->vtbl); | 859 | vfree(ubi->vtbl); |
| 800 | for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) | 860 | for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { |
| 801 | if (ubi->volumes[i]) { | 861 | kfree(ubi->volumes[i]); |
| 802 | kfree(ubi->volumes[i]); | 862 | ubi->volumes[i] = NULL; |
| 803 | ubi->volumes[i] = NULL; | 863 | } |
| 804 | } | ||
| 805 | return err; | 864 | return err; |
| 806 | } | 865 | } |
| 807 | 866 | ||
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index a471a491f0ab..05d70937b543 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
| @@ -19,22 +19,22 @@ | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| 22 | * UBI wear-leveling unit. | 22 | * UBI wear-leveling sub-system. |
| 23 | * | 23 | * |
| 24 | * This unit is responsible for wear-leveling. It works in terms of physical | 24 | * This sub-system is responsible for wear-leveling. It works in terms of |
| 25 | * eraseblocks and erase counters and knows nothing about logical eraseblocks, | 25 | * physical* eraseblocks and erase counters and knows nothing about logical |
| 26 | * volumes, etc. From this unit's perspective all physical eraseblocks are of | 26 | * eraseblocks, volumes, etc. From this sub-system's perspective all physical |
| 27 | * two types - used and free. Used physical eraseblocks are those that were | 27 | * eraseblocks are of two types - used and free. Used physical eraseblocks are |
| 28 | * "get" by the 'ubi_wl_get_peb()' function, and free physical eraseblocks are | 28 | * those that were "get" by the 'ubi_wl_get_peb()' function, and free physical |
| 29 | * those that were put by the 'ubi_wl_put_peb()' function. | 29 | * eraseblocks are those that were put by the 'ubi_wl_put_peb()' function. |
| 30 | * | 30 | * |
| 31 | * Physical eraseblocks returned by 'ubi_wl_get_peb()' have only erase counter | 31 | * Physical eraseblocks returned by 'ubi_wl_get_peb()' have only erase counter |
| 32 | * header. The rest of the physical eraseblock contains only 0xFF bytes. | 32 | * header. The rest of the physical eraseblock contains only %0xFF bytes. |
| 33 | * | 33 | * |
| 34 | * When physical eraseblocks are returned to the WL unit by means of the | 34 | * When physical eraseblocks are returned to the WL sub-system by means of the |
| 35 | * 'ubi_wl_put_peb()' function, they are scheduled for erasure. The erasure is | 35 | * 'ubi_wl_put_peb()' function, they are scheduled for erasure. The erasure is |
| 36 | * done asynchronously in context of the per-UBI device background thread, | 36 | * done asynchronously in context of the per-UBI device background thread, |
| 37 | * which is also managed by the WL unit. | 37 | * which is also managed by the WL sub-system. |
| 38 | * | 38 | * |
| 39 | * The wear-leveling is ensured by means of moving the contents of used | 39 | * The wear-leveling is ensured by means of moving the contents of used |
| 40 | * physical eraseblocks with low erase counter to free physical eraseblocks | 40 | * physical eraseblocks with low erase counter to free physical eraseblocks |
| @@ -43,34 +43,36 @@ | |||
| 43 | * The 'ubi_wl_get_peb()' function accepts data type hints which help to pick | 43 | * The 'ubi_wl_get_peb()' function accepts data type hints which help to pick |
| 44 | * an "optimal" physical eraseblock. For example, when it is known that the | 44 | * an "optimal" physical eraseblock. For example, when it is known that the |
| 45 | * physical eraseblock will be "put" soon because it contains short-term data, | 45 | * physical eraseblock will be "put" soon because it contains short-term data, |
| 46 | * the WL unit may pick a free physical eraseblock with low erase counter, and | 46 | * the WL sub-system may pick a free physical eraseblock with low erase |
| 47 | * so forth. | 47 | * counter, and so forth. |
| 48 | * | 48 | * |
| 49 | * If the WL unit fails to erase a physical eraseblock, it marks it as bad. | 49 | * If the WL sub-system fails to erase a physical eraseblock, it marks it as |
| 50 | * bad. | ||
| 50 | * | 51 | * |
| 51 | * This unit is also responsible for scrubbing. If a bit-flip is detected in a | 52 | * This sub-system is also responsible for scrubbing. If a bit-flip is detected |
| 52 | * physical eraseblock, it has to be moved. Technically this is the same as | 53 | * in a physical eraseblock, it has to be moved. Technically this is the same |
| 53 | * moving it for wear-leveling reasons. | 54 | * as moving it for wear-leveling reasons. |
| 54 | * | 55 | * |
| 55 | * As it was said, for the UBI unit all physical eraseblocks are either "free" | 56 | * As it was said, for the UBI sub-system all physical eraseblocks are either |
| 56 | * or "used". Free eraseblock are kept in the @wl->free RB-tree, while used | 57 | * "free" or "used". Free eraseblock are kept in the @wl->free RB-tree, while |
| 57 | * eraseblocks are kept in a set of different RB-trees: @wl->used, | 58 | * used eraseblocks are kept in a set of different RB-trees: @wl->used, |
| 58 | * @wl->prot.pnum, @wl->prot.aec, and @wl->scrub. | 59 | * @wl->prot.pnum, @wl->prot.aec, and @wl->scrub. |
| 59 | * | 60 | * |
| 60 | * Note, in this implementation, we keep a small in-RAM object for each physical | 61 | * Note, in this implementation, we keep a small in-RAM object for each physical |
| 61 | * eraseblock. This is surely not a scalable solution. But it appears to be good | 62 | * eraseblock. This is surely not a scalable solution. But it appears to be good |
| 62 | * enough for moderately large flashes and it is simple. In future, one may | 63 | * enough for moderately large flashes and it is simple. In future, one may |
| 63 | * re-work this unit and make it more scalable. | 64 | * re-work this sub-system and make it more scalable. |
| 64 | * | 65 | * |
| 65 | * At the moment this unit does not utilize the sequence number, which was | 66 | * At the moment this sub-system does not utilize the sequence number, which |
| 66 | * introduced relatively recently. But it would be wise to do this because the | 67 | * was introduced relatively recently. But it would be wise to do this because |
| 67 | * sequence number of a logical eraseblock characterizes how old is it. For | 68 | * the sequence number of a logical eraseblock characterizes how old is it. For |
| 68 | * example, when we move a PEB with low erase counter, and we need to pick the | 69 | * example, when we move a PEB with low erase counter, and we need to pick the |
| 69 | * target PEB, we pick a PEB with the highest EC if our PEB is "old" and we | 70 | * target PEB, we pick a PEB with the highest EC if our PEB is "old" and we |
| 70 | * pick target PEB with an average EC if our PEB is not very "old". This is a | 71 | * pick target PEB with an average EC if our PEB is not very "old". This is a |
| 71 | * room for future re-works of the WL unit. | 72 | * room for future re-works of the WL sub-system. |
| 72 | * | 73 | * |
| 73 | * FIXME: looks too complex, should be simplified (later). | 74 | * Note: the stuff with protection trees looks too complex and is difficult to |
| 75 | * understand. Should be fixed. | ||
| 74 | */ | 76 | */ |
| 75 | 77 | ||
| 76 | #include <linux/slab.h> | 78 | #include <linux/slab.h> |
| @@ -92,20 +94,21 @@ | |||
| 92 | 94 | ||
| 93 | /* | 95 | /* |
| 94 | * Maximum difference between two erase counters. If this threshold is | 96 | * Maximum difference between two erase counters. If this threshold is |
| 95 | * exceeded, the WL unit starts moving data from used physical eraseblocks with | 97 | * exceeded, the WL sub-system starts moving data from used physical |
| 96 | * low erase counter to free physical eraseblocks with high erase counter. | 98 | * eraseblocks with low erase counter to free physical eraseblocks with high |
| 99 | * erase counter. | ||
| 97 | */ | 100 | */ |
| 98 | #define UBI_WL_THRESHOLD CONFIG_MTD_UBI_WL_THRESHOLD | 101 | #define UBI_WL_THRESHOLD CONFIG_MTD_UBI_WL_THRESHOLD |
| 99 | 102 | ||
| 100 | /* | 103 | /* |
| 101 | * When a physical eraseblock is moved, the WL unit has to pick the target | 104 | * When a physical eraseblock is moved, the WL sub-system has to pick the target |
| 102 | * physical eraseblock to move to. The simplest way would be just to pick the | 105 | * physical eraseblock to move to. The simplest way would be just to pick the |
| 103 | * one with the highest erase counter. But in certain workloads this could lead | 106 | * one with the highest erase counter. But in certain workloads this could lead |
| 104 | * to an unlimited wear of one or few physical eraseblock. Indeed, imagine a | 107 | * to an unlimited wear of one or few physical eraseblock. Indeed, imagine a |
| 105 | * situation when the picked physical eraseblock is constantly erased after the | 108 | * situation when the picked physical eraseblock is constantly erased after the |
| 106 | * data is written to it. So, we have a constant which limits the highest erase | 109 | * data is written to it. So, we have a constant which limits the highest erase |
| 107 | * counter of the free physical eraseblock to pick. Namely, the WL unit does | 110 | * counter of the free physical eraseblock to pick. Namely, the WL sub-system |
| 108 | * not pick eraseblocks with erase counter greater then the lowest erase | 111 | * does not pick eraseblocks with erase counter greater then the lowest erase |
| 109 | * counter plus %WL_FREE_MAX_DIFF. | 112 | * counter plus %WL_FREE_MAX_DIFF. |
| 110 | */ | 113 | */ |
| 111 | #define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD) | 114 | #define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD) |
| @@ -123,11 +126,11 @@ | |||
| 123 | * @abs_ec: the absolute erase counter value when the protection ends | 126 | * @abs_ec: the absolute erase counter value when the protection ends |
| 124 | * @e: the wear-leveling entry of the physical eraseblock under protection | 127 | * @e: the wear-leveling entry of the physical eraseblock under protection |
| 125 | * | 128 | * |
| 126 | * When the WL unit returns a physical eraseblock, the physical eraseblock is | 129 | * When the WL sub-system returns a physical eraseblock, the physical |
| 127 | * protected from being moved for some "time". For this reason, the physical | 130 | * eraseblock is protected from being moved for some "time". For this reason, |
| 128 | * eraseblock is not directly moved from the @wl->free tree to the @wl->used | 131 | * the physical eraseblock is not directly moved from the @wl->free tree to the |
| 129 | * tree. There is one more tree in between where this physical eraseblock is | 132 | * @wl->used tree. There is one more tree in between where this physical |
| 130 | * temporarily stored (@wl->prot). | 133 | * eraseblock is temporarily stored (@wl->prot). |
| 131 | * | 134 | * |
| 132 | * All this protection stuff is needed because: | 135 | * All this protection stuff is needed because: |
| 133 | * o we don't want to move physical eraseblocks just after we have given them | 136 | * o we don't want to move physical eraseblocks just after we have given them |
| @@ -175,7 +178,6 @@ struct ubi_wl_prot_entry { | |||
| 175 | * @list: a link in the list of pending works | 178 | * @list: a link in the list of pending works |
| 176 | * @func: worker function | 179 | * @func: worker function |
| 177 | * @priv: private data of the worker function | 180 | * @priv: private data of the worker function |
| 178 | * | ||
| 179 | * @e: physical eraseblock to erase | 181 | * @e: physical eraseblock to erase |
| 180 | * @torture: if the physical eraseblock has to be tortured | 182 | * @torture: if the physical eraseblock has to be tortured |
| 181 | * | 183 | * |
| @@ -473,52 +475,47 @@ retry: | |||
| 473 | } | 475 | } |
| 474 | 476 | ||
| 475 | switch (dtype) { | 477 | switch (dtype) { |
| 476 | case UBI_LONGTERM: | 478 | case UBI_LONGTERM: |
| 477 | /* | 479 | /* |
| 478 | * For long term data we pick a physical eraseblock | 480 | * For long term data we pick a physical eraseblock with high |
| 479 | * with high erase counter. But the highest erase | 481 | * erase counter. But the highest erase counter we can pick is |
| 480 | * counter we can pick is bounded by the the lowest | 482 | * bounded by the the lowest erase counter plus |
| 481 | * erase counter plus %WL_FREE_MAX_DIFF. | 483 | * %WL_FREE_MAX_DIFF. |
| 482 | */ | 484 | */ |
| 483 | e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF); | 485 | e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF); |
| 484 | protect = LT_PROTECTION; | 486 | protect = LT_PROTECTION; |
| 485 | break; | 487 | break; |
| 486 | case UBI_UNKNOWN: | 488 | case UBI_UNKNOWN: |
| 487 | /* | 489 | /* |
| 488 | * For unknown data we pick a physical eraseblock with | 490 | * For unknown data we pick a physical eraseblock with medium |
| 489 | * medium erase counter. But we by no means can pick a | 491 | * erase counter. But we by no means can pick a physical |
| 490 | * physical eraseblock with erase counter greater or | 492 | * eraseblock with erase counter greater or equivalent than the |
| 491 | * equivalent than the lowest erase counter plus | 493 | * lowest erase counter plus %WL_FREE_MAX_DIFF. |
| 492 | * %WL_FREE_MAX_DIFF. | 494 | */ |
| 493 | */ | 495 | first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb); |
| 494 | first = rb_entry(rb_first(&ubi->free), | 496 | last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, rb); |
| 495 | struct ubi_wl_entry, rb); | ||
| 496 | last = rb_entry(rb_last(&ubi->free), | ||
| 497 | struct ubi_wl_entry, rb); | ||
| 498 | 497 | ||
| 499 | if (last->ec - first->ec < WL_FREE_MAX_DIFF) | 498 | if (last->ec - first->ec < WL_FREE_MAX_DIFF) |
| 500 | e = rb_entry(ubi->free.rb_node, | 499 | e = rb_entry(ubi->free.rb_node, |
| 501 | struct ubi_wl_entry, rb); | 500 | struct ubi_wl_entry, rb); |
| 502 | else { | 501 | else { |
| 503 | medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2; | 502 | medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2; |
| 504 | e = find_wl_entry(&ubi->free, medium_ec); | 503 | e = find_wl_entry(&ubi->free, medium_ec); |
| 505 | } | 504 | } |
| 506 | protect = U_PROTECTION; | 505 | protect = U_PROTECTION; |
| 507 | break; | 506 | break; |
| 508 | case UBI_SHORTTERM: | 507 | case UBI_SHORTTERM: |
| 509 | /* | 508 | /* |
| 510 | * For short term data we pick a physical eraseblock | 509 | * For short term data we pick a physical eraseblock with the |
| 511 | * with the lowest erase counter as we expect it will | 510 | * lowest erase counter as we expect it will be erased soon. |
| 512 | * be erased soon. | 511 | */ |
| 513 | */ | 512 | e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb); |
| 514 | e = rb_entry(rb_first(&ubi->free), | 513 | protect = ST_PROTECTION; |
| 515 | struct ubi_wl_entry, rb); | 514 | break; |
| 516 | protect = ST_PROTECTION; | 515 | default: |
| 517 | break; | 516 | protect = 0; |
| 518 | default: | 517 | e = NULL; |
| 519 | protect = 0; | 518 | BUG(); |
| 520 | e = NULL; | ||
| 521 | BUG(); | ||
| 522 | } | 519 | } |
| 523 | 520 | ||
| 524 | /* | 521 | /* |
| @@ -582,7 +579,8 @@ found: | |||
| 582 | * This function returns zero in case of success and a negative error code in | 579 | * This function returns zero in case of success and a negative error code in |
| 583 | * case of failure. | 580 | * case of failure. |
| 584 | */ | 581 | */ |
| 585 | static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int torture) | 582 | static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, |
| 583 | int torture) | ||
| 586 | { | 584 | { |
| 587 | int err; | 585 | int err; |
| 588 | struct ubi_ec_hdr *ec_hdr; | 586 | struct ubi_ec_hdr *ec_hdr; |
| @@ -634,8 +632,7 @@ out_free: | |||
| 634 | } | 632 | } |
| 635 | 633 | ||
| 636 | /** | 634 | /** |
| 637 | * check_protection_over - check if it is time to stop protecting some | 635 | * check_protection_over - check if it is time to stop protecting some PEBs. |
| 638 | * physical eraseblocks. | ||
| 639 | * @ubi: UBI device description object | 636 | * @ubi: UBI device description object |
| 640 | * | 637 | * |
| 641 | * This function is called after each erase operation, when the absolute erase | 638 | * This function is called after each erase operation, when the absolute erase |
| @@ -871,6 +868,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, | |||
| 871 | } | 868 | } |
| 872 | 869 | ||
| 873 | ubi_free_vid_hdr(ubi, vid_hdr); | 870 | ubi_free_vid_hdr(ubi, vid_hdr); |
| 871 | if (scrubbing && !protect) | ||
| 872 | ubi_msg("scrubbed PEB %d, data moved to PEB %d", | ||
| 873 | e1->pnum, e2->pnum); | ||
| 874 | |||
| 874 | spin_lock(&ubi->wl_lock); | 875 | spin_lock(&ubi->wl_lock); |
| 875 | if (protect) | 876 | if (protect) |
| 876 | prot_tree_add(ubi, e1, pe, protect); | 877 | prot_tree_add(ubi, e1, pe, protect); |
| @@ -1054,8 +1055,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, | |||
| 1054 | spin_unlock(&ubi->wl_lock); | 1055 | spin_unlock(&ubi->wl_lock); |
| 1055 | 1056 | ||
| 1056 | /* | 1057 | /* |
| 1057 | * One more erase operation has happened, take care about protected | 1058 | * One more erase operation has happened, take care about |
| 1058 | * physical eraseblocks. | 1059 | * protected physical eraseblocks. |
| 1059 | */ | 1060 | */ |
| 1060 | check_protection_over(ubi); | 1061 | check_protection_over(ubi); |
| 1061 | 1062 | ||
| @@ -1136,7 +1137,7 @@ out_ro: | |||
| 1136 | } | 1137 | } |
| 1137 | 1138 | ||
| 1138 | /** | 1139 | /** |
| 1139 | * ubi_wl_put_peb - return a physical eraseblock to the wear-leveling unit. | 1140 | * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system. |
| 1140 | * @ubi: UBI device description object | 1141 | * @ubi: UBI device description object |
| 1141 | * @pnum: physical eraseblock to return | 1142 | * @pnum: physical eraseblock to return |
| 1142 | * @torture: if this physical eraseblock has to be tortured | 1143 | * @torture: if this physical eraseblock has to be tortured |
| @@ -1175,11 +1176,11 @@ retry: | |||
| 1175 | /* | 1176 | /* |
| 1176 | * User is putting the physical eraseblock which was selected | 1177 | * User is putting the physical eraseblock which was selected |
| 1177 | * as the target the data is moved to. It may happen if the EBA | 1178 | * as the target the data is moved to. It may happen if the EBA |
| 1178 | * unit already re-mapped the LEB in 'ubi_eba_copy_leb()' but | 1179 | * sub-system already re-mapped the LEB in 'ubi_eba_copy_leb()' |
| 1179 | * the WL unit has not put the PEB to the "used" tree yet, but | 1180 | * but the WL sub-system has not put the PEB to the "used" tree |
| 1180 | * it is about to do this. So we just set a flag which will | 1181 | * yet, but it is about to do this. So we just set a flag which |
| 1181 | * tell the WL worker that the PEB is not needed anymore and | 1182 | * will tell the WL worker that the PEB is not needed anymore |
| 1182 | * should be scheduled for erasure. | 1183 | * and should be scheduled for erasure. |
| 1183 | */ | 1184 | */ |
| 1184 | dbg_wl("PEB %d is the target of data moving", pnum); | 1185 | dbg_wl("PEB %d is the target of data moving", pnum); |
| 1185 | ubi_assert(!ubi->move_to_put); | 1186 | ubi_assert(!ubi->move_to_put); |
| @@ -1229,7 +1230,7 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum) | |||
| 1229 | { | 1230 | { |
| 1230 | struct ubi_wl_entry *e; | 1231 | struct ubi_wl_entry *e; |
| 1231 | 1232 | ||
| 1232 | ubi_msg("schedule PEB %d for scrubbing", pnum); | 1233 | dbg_msg("schedule PEB %d for scrubbing", pnum); |
| 1233 | 1234 | ||
| 1234 | retry: | 1235 | retry: |
| 1235 | spin_lock(&ubi->wl_lock); | 1236 | spin_lock(&ubi->wl_lock); |
| @@ -1368,7 +1369,7 @@ int ubi_thread(void *u) | |||
| 1368 | int err; | 1369 | int err; |
| 1369 | 1370 | ||
| 1370 | if (kthread_should_stop()) | 1371 | if (kthread_should_stop()) |
| 1371 | goto out; | 1372 | break; |
| 1372 | 1373 | ||
| 1373 | if (try_to_freeze()) | 1374 | if (try_to_freeze()) |
| 1374 | continue; | 1375 | continue; |
| @@ -1403,7 +1404,6 @@ int ubi_thread(void *u) | |||
| 1403 | cond_resched(); | 1404 | cond_resched(); |
| 1404 | } | 1405 | } |
| 1405 | 1406 | ||
| 1406 | out: | ||
| 1407 | dbg_wl("background thread \"%s\" is killed", ubi->bgt_name); | 1407 | dbg_wl("background thread \"%s\" is killed", ubi->bgt_name); |
| 1408 | return 0; | 1408 | return 0; |
| 1409 | } | 1409 | } |
| @@ -1426,8 +1426,7 @@ static void cancel_pending(struct ubi_device *ubi) | |||
| 1426 | } | 1426 | } |
| 1427 | 1427 | ||
| 1428 | /** | 1428 | /** |
| 1429 | * ubi_wl_init_scan - initialize the wear-leveling unit using scanning | 1429 | * ubi_wl_init_scan - initialize the WL sub-system using scanning information. |
| 1430 | * information. | ||
| 1431 | * @ubi: UBI device description object | 1430 | * @ubi: UBI device description object |
| 1432 | * @si: scanning information | 1431 | * @si: scanning information |
| 1433 | * | 1432 | * |
| @@ -1584,13 +1583,12 @@ static void protection_trees_destroy(struct ubi_device *ubi) | |||
| 1584 | } | 1583 | } |
| 1585 | 1584 | ||
| 1586 | /** | 1585 | /** |
| 1587 | * ubi_wl_close - close the wear-leveling unit. | 1586 | * ubi_wl_close - close the wear-leveling sub-system. |
| 1588 | * @ubi: UBI device description object | 1587 | * @ubi: UBI device description object |
| 1589 | */ | 1588 | */ |
| 1590 | void ubi_wl_close(struct ubi_device *ubi) | 1589 | void ubi_wl_close(struct ubi_device *ubi) |
| 1591 | { | 1590 | { |
| 1592 | dbg_wl("close the UBI wear-leveling unit"); | 1591 | dbg_wl("close the WL sub-system"); |
| 1593 | |||
| 1594 | cancel_pending(ubi); | 1592 | cancel_pending(ubi); |
| 1595 | protection_trees_destroy(ubi); | 1593 | protection_trees_destroy(ubi); |
| 1596 | tree_destroy(&ubi->used); | 1594 | tree_destroy(&ubi->used); |
| @@ -1602,8 +1600,7 @@ void ubi_wl_close(struct ubi_device *ubi) | |||
| 1602 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 1600 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| 1603 | 1601 | ||
| 1604 | /** | 1602 | /** |
| 1605 | * paranoid_check_ec - make sure that the erase counter of a physical eraseblock | 1603 | * paranoid_check_ec - make sure that the erase counter of a PEB is correct. |
| 1606 | * is correct. | ||
| 1607 | * @ubi: UBI device description object | 1604 | * @ubi: UBI device description object |
| 1608 | * @pnum: the physical eraseblock number to check | 1605 | * @pnum: the physical eraseblock number to check |
| 1609 | * @ec: the erase counter to check | 1606 | * @ec: the erase counter to check |
| @@ -1644,13 +1641,12 @@ out_free: | |||
| 1644 | } | 1641 | } |
| 1645 | 1642 | ||
| 1646 | /** | 1643 | /** |
| 1647 | * paranoid_check_in_wl_tree - make sure that a wear-leveling entry is present | 1644 | * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree. |
| 1648 | * in a WL RB-tree. | ||
| 1649 | * @e: the wear-leveling entry to check | 1645 | * @e: the wear-leveling entry to check |
| 1650 | * @root: the root of the tree | 1646 | * @root: the root of the tree |
| 1651 | * | 1647 | * |
| 1652 | * This function returns zero if @e is in the @root RB-tree and %1 if it | 1648 | * This function returns zero if @e is in the @root RB-tree and %1 if it is |
| 1653 | * is not. | 1649 | * not. |
| 1654 | */ | 1650 | */ |
| 1655 | static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, | 1651 | static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, |
| 1656 | struct rb_root *root) | 1652 | struct rb_root *root) |
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 00527805e4f1..e5a6e2e84540 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
| 36 | #include <linux/moduleparam.h> | ||
| 36 | #include <linux/types.h> | 37 | #include <linux/types.h> |
| 37 | #include <linux/errno.h> | 38 | #include <linux/errno.h> |
| 38 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
| @@ -52,7 +53,9 @@ | |||
| 52 | #include <asm/hvcall.h> | 53 | #include <asm/hvcall.h> |
| 53 | #include <asm/atomic.h> | 54 | #include <asm/atomic.h> |
| 54 | #include <asm/vio.h> | 55 | #include <asm/vio.h> |
| 56 | #include <asm/iommu.h> | ||
| 55 | #include <asm/uaccess.h> | 57 | #include <asm/uaccess.h> |
| 58 | #include <asm/firmware.h> | ||
| 56 | #include <linux/seq_file.h> | 59 | #include <linux/seq_file.h> |
| 57 | 60 | ||
| 58 | #include "ibmveth.h" | 61 | #include "ibmveth.h" |
| @@ -94,8 +97,10 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter); | |||
| 94 | static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); | 97 | static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); |
| 95 | static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance); | 98 | static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance); |
| 96 | static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter); | 99 | static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter); |
| 100 | static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev); | ||
| 97 | static struct kobj_type ktype_veth_pool; | 101 | static struct kobj_type ktype_veth_pool; |
| 98 | 102 | ||
| 103 | |||
| 99 | #ifdef CONFIG_PROC_FS | 104 | #ifdef CONFIG_PROC_FS |
| 100 | #define IBMVETH_PROC_DIR "ibmveth" | 105 | #define IBMVETH_PROC_DIR "ibmveth" |
| 101 | static struct proc_dir_entry *ibmveth_proc_dir; | 106 | static struct proc_dir_entry *ibmveth_proc_dir; |
| @@ -226,16 +231,16 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc | |||
| 226 | u32 i; | 231 | u32 i; |
| 227 | u32 count = pool->size - atomic_read(&pool->available); | 232 | u32 count = pool->size - atomic_read(&pool->available); |
| 228 | u32 buffers_added = 0; | 233 | u32 buffers_added = 0; |
| 234 | struct sk_buff *skb; | ||
| 235 | unsigned int free_index, index; | ||
| 236 | u64 correlator; | ||
| 237 | unsigned long lpar_rc; | ||
| 238 | dma_addr_t dma_addr; | ||
| 229 | 239 | ||
| 230 | mb(); | 240 | mb(); |
| 231 | 241 | ||
| 232 | for(i = 0; i < count; ++i) { | 242 | for(i = 0; i < count; ++i) { |
| 233 | struct sk_buff *skb; | ||
| 234 | unsigned int free_index, index; | ||
| 235 | u64 correlator; | ||
| 236 | union ibmveth_buf_desc desc; | 243 | union ibmveth_buf_desc desc; |
| 237 | unsigned long lpar_rc; | ||
| 238 | dma_addr_t dma_addr; | ||
| 239 | 244 | ||
| 240 | skb = alloc_skb(pool->buff_size, GFP_ATOMIC); | 245 | skb = alloc_skb(pool->buff_size, GFP_ATOMIC); |
| 241 | 246 | ||
| @@ -255,6 +260,9 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc | |||
| 255 | dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, | 260 | dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, |
| 256 | pool->buff_size, DMA_FROM_DEVICE); | 261 | pool->buff_size, DMA_FROM_DEVICE); |
| 257 | 262 | ||
| 263 | if (dma_mapping_error(dma_addr)) | ||
| 264 | goto failure; | ||
| 265 | |||
| 258 | pool->free_map[free_index] = IBM_VETH_INVALID_MAP; | 266 | pool->free_map[free_index] = IBM_VETH_INVALID_MAP; |
| 259 | pool->dma_addr[index] = dma_addr; | 267 | pool->dma_addr[index] = dma_addr; |
| 260 | pool->skbuff[index] = skb; | 268 | pool->skbuff[index] = skb; |
| @@ -267,20 +275,9 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc | |||
| 267 | 275 | ||
| 268 | lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); | 276 | lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); |
| 269 | 277 | ||
| 270 | if(lpar_rc != H_SUCCESS) { | 278 | if (lpar_rc != H_SUCCESS) |
| 271 | pool->free_map[free_index] = index; | 279 | goto failure; |
| 272 | pool->skbuff[index] = NULL; | 280 | else { |
| 273 | if (pool->consumer_index == 0) | ||
| 274 | pool->consumer_index = pool->size - 1; | ||
| 275 | else | ||
| 276 | pool->consumer_index--; | ||
| 277 | dma_unmap_single(&adapter->vdev->dev, | ||
| 278 | pool->dma_addr[index], pool->buff_size, | ||
| 279 | DMA_FROM_DEVICE); | ||
| 280 | dev_kfree_skb_any(skb); | ||
| 281 | adapter->replenish_add_buff_failure++; | ||
| 282 | break; | ||
| 283 | } else { | ||
| 284 | buffers_added++; | 281 | buffers_added++; |
| 285 | adapter->replenish_add_buff_success++; | 282 | adapter->replenish_add_buff_success++; |
| 286 | } | 283 | } |
| @@ -288,6 +285,24 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc | |||
| 288 | 285 | ||
| 289 | mb(); | 286 | mb(); |
| 290 | atomic_add(buffers_added, &(pool->available)); | 287 | atomic_add(buffers_added, &(pool->available)); |
| 288 | return; | ||
| 289 | |||
| 290 | failure: | ||
| 291 | pool->free_map[free_index] = index; | ||
| 292 | pool->skbuff[index] = NULL; | ||
| 293 | if (pool->consumer_index == 0) | ||
| 294 | pool->consumer_index = pool->size - 1; | ||
| 295 | else | ||
| 296 | pool->consumer_index--; | ||
| 297 | if (!dma_mapping_error(dma_addr)) | ||
| 298 | dma_unmap_single(&adapter->vdev->dev, | ||
| 299 | pool->dma_addr[index], pool->buff_size, | ||
| 300 | DMA_FROM_DEVICE); | ||
| 301 | dev_kfree_skb_any(skb); | ||
| 302 | adapter->replenish_add_buff_failure++; | ||
| 303 | |||
| 304 | mb(); | ||
| 305 | atomic_add(buffers_added, &(pool->available)); | ||
| 291 | } | 306 | } |
| 292 | 307 | ||
| 293 | /* replenish routine */ | 308 | /* replenish routine */ |
| @@ -297,7 +312,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) | |||
| 297 | 312 | ||
| 298 | adapter->replenish_task_cycles++; | 313 | adapter->replenish_task_cycles++; |
| 299 | 314 | ||
| 300 | for(i = 0; i < IbmVethNumBufferPools; i++) | 315 | for (i = (IbmVethNumBufferPools - 1); i >= 0; i--) |
| 301 | if(adapter->rx_buff_pool[i].active) | 316 | if(adapter->rx_buff_pool[i].active) |
| 302 | ibmveth_replenish_buffer_pool(adapter, | 317 | ibmveth_replenish_buffer_pool(adapter, |
| 303 | &adapter->rx_buff_pool[i]); | 318 | &adapter->rx_buff_pool[i]); |
| @@ -472,6 +487,18 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) | |||
| 472 | if (adapter->rx_buff_pool[i].active) | 487 | if (adapter->rx_buff_pool[i].active) |
| 473 | ibmveth_free_buffer_pool(adapter, | 488 | ibmveth_free_buffer_pool(adapter, |
| 474 | &adapter->rx_buff_pool[i]); | 489 | &adapter->rx_buff_pool[i]); |
| 490 | |||
| 491 | if (adapter->bounce_buffer != NULL) { | ||
| 492 | if (!dma_mapping_error(adapter->bounce_buffer_dma)) { | ||
| 493 | dma_unmap_single(&adapter->vdev->dev, | ||
| 494 | adapter->bounce_buffer_dma, | ||
| 495 | adapter->netdev->mtu + IBMVETH_BUFF_OH, | ||
| 496 | DMA_BIDIRECTIONAL); | ||
| 497 | adapter->bounce_buffer_dma = DMA_ERROR_CODE; | ||
| 498 | } | ||
| 499 | kfree(adapter->bounce_buffer); | ||
| 500 | adapter->bounce_buffer = NULL; | ||
| 501 | } | ||
| 475 | } | 502 | } |
| 476 | 503 | ||
| 477 | static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, | 504 | static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter, |
| @@ -607,6 +634,24 @@ static int ibmveth_open(struct net_device *netdev) | |||
| 607 | return rc; | 634 | return rc; |
| 608 | } | 635 | } |
| 609 | 636 | ||
| 637 | adapter->bounce_buffer = | ||
| 638 | kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL); | ||
| 639 | if (!adapter->bounce_buffer) { | ||
| 640 | ibmveth_error_printk("unable to allocate bounce buffer\n"); | ||
| 641 | ibmveth_cleanup(adapter); | ||
| 642 | napi_disable(&adapter->napi); | ||
| 643 | return -ENOMEM; | ||
| 644 | } | ||
| 645 | adapter->bounce_buffer_dma = | ||
| 646 | dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer, | ||
| 647 | netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL); | ||
| 648 | if (dma_mapping_error(adapter->bounce_buffer_dma)) { | ||
| 649 | ibmveth_error_printk("unable to map bounce buffer\n"); | ||
| 650 | ibmveth_cleanup(adapter); | ||
| 651 | napi_disable(&adapter->napi); | ||
| 652 | return -ENOMEM; | ||
| 653 | } | ||
| 654 | |||
| 610 | ibmveth_debug_printk("initial replenish cycle\n"); | 655 | ibmveth_debug_printk("initial replenish cycle\n"); |
| 611 | ibmveth_interrupt(netdev->irq, netdev); | 656 | ibmveth_interrupt(netdev->irq, netdev); |
| 612 | 657 | ||
| @@ -853,10 +898,12 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
| 853 | unsigned int tx_packets = 0; | 898 | unsigned int tx_packets = 0; |
| 854 | unsigned int tx_send_failed = 0; | 899 | unsigned int tx_send_failed = 0; |
| 855 | unsigned int tx_map_failed = 0; | 900 | unsigned int tx_map_failed = 0; |
| 901 | int used_bounce = 0; | ||
| 902 | unsigned long data_dma_addr; | ||
| 856 | 903 | ||
| 857 | desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len; | 904 | desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len; |
| 858 | desc.fields.address = dma_map_single(&adapter->vdev->dev, skb->data, | 905 | data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, |
| 859 | skb->len, DMA_TO_DEVICE); | 906 | skb->len, DMA_TO_DEVICE); |
| 860 | 907 | ||
| 861 | if (skb->ip_summed == CHECKSUM_PARTIAL && | 908 | if (skb->ip_summed == CHECKSUM_PARTIAL && |
| 862 | ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) { | 909 | ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) { |
| @@ -875,12 +922,16 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
| 875 | buf[1] = 0; | 922 | buf[1] = 0; |
| 876 | } | 923 | } |
| 877 | 924 | ||
| 878 | if (dma_mapping_error(desc.fields.address)) { | 925 | if (dma_mapping_error(data_dma_addr)) { |
| 879 | ibmveth_error_printk("tx: unable to map xmit buffer\n"); | 926 | if (!firmware_has_feature(FW_FEATURE_CMO)) |
| 927 | ibmveth_error_printk("tx: unable to map xmit buffer\n"); | ||
| 928 | skb_copy_from_linear_data(skb, adapter->bounce_buffer, | ||
| 929 | skb->len); | ||
| 930 | desc.fields.address = adapter->bounce_buffer_dma; | ||
| 880 | tx_map_failed++; | 931 | tx_map_failed++; |
| 881 | tx_dropped++; | 932 | used_bounce = 1; |
| 882 | goto out; | 933 | } else |
| 883 | } | 934 | desc.fields.address = data_dma_addr; |
| 884 | 935 | ||
| 885 | /* send the frame. Arbitrarily set retrycount to 1024 */ | 936 | /* send the frame. Arbitrarily set retrycount to 1024 */ |
| 886 | correlator = 0; | 937 | correlator = 0; |
| @@ -904,8 +955,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
| 904 | netdev->trans_start = jiffies; | 955 | netdev->trans_start = jiffies; |
| 905 | } | 956 | } |
| 906 | 957 | ||
| 907 | dma_unmap_single(&adapter->vdev->dev, desc.fields.address, | 958 | if (!used_bounce) |
| 908 | skb->len, DMA_TO_DEVICE); | 959 | dma_unmap_single(&adapter->vdev->dev, data_dma_addr, |
| 960 | skb->len, DMA_TO_DEVICE); | ||
| 909 | 961 | ||
| 910 | out: spin_lock_irqsave(&adapter->stats_lock, flags); | 962 | out: spin_lock_irqsave(&adapter->stats_lock, flags); |
| 911 | netdev->stats.tx_dropped += tx_dropped; | 963 | netdev->stats.tx_dropped += tx_dropped; |
| @@ -1053,9 +1105,9 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) | |||
| 1053 | static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) | 1105 | static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) |
| 1054 | { | 1106 | { |
| 1055 | struct ibmveth_adapter *adapter = dev->priv; | 1107 | struct ibmveth_adapter *adapter = dev->priv; |
| 1108 | struct vio_dev *viodev = adapter->vdev; | ||
| 1056 | int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; | 1109 | int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; |
| 1057 | int reinit = 0; | 1110 | int i; |
| 1058 | int i, rc; | ||
| 1059 | 1111 | ||
| 1060 | if (new_mtu < IBMVETH_MAX_MTU) | 1112 | if (new_mtu < IBMVETH_MAX_MTU) |
| 1061 | return -EINVAL; | 1113 | return -EINVAL; |
| @@ -1067,23 +1119,34 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) | |||
| 1067 | if (i == IbmVethNumBufferPools) | 1119 | if (i == IbmVethNumBufferPools) |
| 1068 | return -EINVAL; | 1120 | return -EINVAL; |
| 1069 | 1121 | ||
| 1122 | /* Deactivate all the buffer pools so that the next loop can activate | ||
| 1123 | only the buffer pools necessary to hold the new MTU */ | ||
| 1124 | for (i = 0; i < IbmVethNumBufferPools; i++) | ||
| 1125 | if (adapter->rx_buff_pool[i].active) { | ||
| 1126 | ibmveth_free_buffer_pool(adapter, | ||
| 1127 | &adapter->rx_buff_pool[i]); | ||
| 1128 | adapter->rx_buff_pool[i].active = 0; | ||
| 1129 | } | ||
| 1130 | |||
| 1070 | /* Look for an active buffer pool that can hold the new MTU */ | 1131 | /* Look for an active buffer pool that can hold the new MTU */ |
| 1071 | for(i = 0; i<IbmVethNumBufferPools; i++) { | 1132 | for(i = 0; i<IbmVethNumBufferPools; i++) { |
| 1072 | if (!adapter->rx_buff_pool[i].active) { | 1133 | adapter->rx_buff_pool[i].active = 1; |
| 1073 | adapter->rx_buff_pool[i].active = 1; | ||
| 1074 | reinit = 1; | ||
| 1075 | } | ||
| 1076 | 1134 | ||
| 1077 | if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) { | 1135 | if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) { |
| 1078 | if (reinit && netif_running(adapter->netdev)) { | 1136 | if (netif_running(adapter->netdev)) { |
| 1079 | adapter->pool_config = 1; | 1137 | adapter->pool_config = 1; |
| 1080 | ibmveth_close(adapter->netdev); | 1138 | ibmveth_close(adapter->netdev); |
| 1081 | adapter->pool_config = 0; | 1139 | adapter->pool_config = 0; |
| 1082 | dev->mtu = new_mtu; | 1140 | dev->mtu = new_mtu; |
| 1083 | if ((rc = ibmveth_open(adapter->netdev))) | 1141 | vio_cmo_set_dev_desired(viodev, |
| 1084 | return rc; | 1142 | ibmveth_get_desired_dma |
| 1085 | } else | 1143 | (viodev)); |
| 1086 | dev->mtu = new_mtu; | 1144 | return ibmveth_open(adapter->netdev); |
| 1145 | } | ||
| 1146 | dev->mtu = new_mtu; | ||
| 1147 | vio_cmo_set_dev_desired(viodev, | ||
| 1148 | ibmveth_get_desired_dma | ||
| 1149 | (viodev)); | ||
| 1087 | return 0; | 1150 | return 0; |
| 1088 | } | 1151 | } |
| 1089 | } | 1152 | } |
| @@ -1098,6 +1161,46 @@ static void ibmveth_poll_controller(struct net_device *dev) | |||
| 1098 | } | 1161 | } |
| 1099 | #endif | 1162 | #endif |
| 1100 | 1163 | ||
| 1164 | /** | ||
| 1165 | * ibmveth_get_desired_dma - Calculate IO memory desired by the driver | ||
| 1166 | * | ||
| 1167 | * @vdev: struct vio_dev for the device whose desired IO mem is to be returned | ||
| 1168 | * | ||
| 1169 | * Return value: | ||
| 1170 | * Number of bytes of IO data the driver will need to perform well. | ||
| 1171 | */ | ||
| 1172 | static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev) | ||
| 1173 | { | ||
| 1174 | struct net_device *netdev = dev_get_drvdata(&vdev->dev); | ||
| 1175 | struct ibmveth_adapter *adapter; | ||
| 1176 | unsigned long ret; | ||
| 1177 | int i; | ||
| 1178 | int rxqentries = 1; | ||
| 1179 | |||
| 1180 | /* netdev inits at probe time along with the structures we need below*/ | ||
| 1181 | if (netdev == NULL) | ||
| 1182 | return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT); | ||
| 1183 | |||
| 1184 | adapter = netdev_priv(netdev); | ||
| 1185 | |||
| 1186 | ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE; | ||
| 1187 | ret += IOMMU_PAGE_ALIGN(netdev->mtu); | ||
| 1188 | |||
| 1189 | for (i = 0; i < IbmVethNumBufferPools; i++) { | ||
| 1190 | /* add the size of the active receive buffers */ | ||
| 1191 | if (adapter->rx_buff_pool[i].active) | ||
| 1192 | ret += | ||
| 1193 | adapter->rx_buff_pool[i].size * | ||
| 1194 | IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i]. | ||
| 1195 | buff_size); | ||
| 1196 | rxqentries += adapter->rx_buff_pool[i].size; | ||
| 1197 | } | ||
| 1198 | /* add the size of the receive queue entries */ | ||
| 1199 | ret += IOMMU_PAGE_ALIGN(rxqentries * sizeof(struct ibmveth_rx_q_entry)); | ||
| 1200 | |||
| 1201 | return ret; | ||
| 1202 | } | ||
| 1203 | |||
| 1101 | static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) | 1204 | static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) |
| 1102 | { | 1205 | { |
| 1103 | int rc, i; | 1206 | int rc, i; |
| @@ -1242,6 +1345,8 @@ static int __devexit ibmveth_remove(struct vio_dev *dev) | |||
| 1242 | ibmveth_proc_unregister_adapter(adapter); | 1345 | ibmveth_proc_unregister_adapter(adapter); |
| 1243 | 1346 | ||
| 1244 | free_netdev(netdev); | 1347 | free_netdev(netdev); |
| 1348 | dev_set_drvdata(&dev->dev, NULL); | ||
| 1349 | |||
| 1245 | return 0; | 1350 | return 0; |
| 1246 | } | 1351 | } |
| 1247 | 1352 | ||
| @@ -1402,14 +1507,15 @@ const char * buf, size_t count) | |||
| 1402 | return -EPERM; | 1507 | return -EPERM; |
| 1403 | } | 1508 | } |
| 1404 | 1509 | ||
| 1405 | pool->active = 0; | ||
| 1406 | if (netif_running(netdev)) { | 1510 | if (netif_running(netdev)) { |
| 1407 | adapter->pool_config = 1; | 1511 | adapter->pool_config = 1; |
| 1408 | ibmveth_close(netdev); | 1512 | ibmveth_close(netdev); |
| 1513 | pool->active = 0; | ||
| 1409 | adapter->pool_config = 0; | 1514 | adapter->pool_config = 0; |
| 1410 | if ((rc = ibmveth_open(netdev))) | 1515 | if ((rc = ibmveth_open(netdev))) |
| 1411 | return rc; | 1516 | return rc; |
| 1412 | } | 1517 | } |
| 1518 | pool->active = 0; | ||
| 1413 | } | 1519 | } |
| 1414 | } else if (attr == &veth_num_attr) { | 1520 | } else if (attr == &veth_num_attr) { |
| 1415 | if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) | 1521 | if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) |
| @@ -1485,6 +1591,7 @@ static struct vio_driver ibmveth_driver = { | |||
| 1485 | .id_table = ibmveth_device_table, | 1591 | .id_table = ibmveth_device_table, |
| 1486 | .probe = ibmveth_probe, | 1592 | .probe = ibmveth_probe, |
| 1487 | .remove = ibmveth_remove, | 1593 | .remove = ibmveth_remove, |
| 1594 | .get_desired_dma = ibmveth_get_desired_dma, | ||
| 1488 | .driver = { | 1595 | .driver = { |
| 1489 | .name = ibmveth_driver_name, | 1596 | .name = ibmveth_driver_name, |
| 1490 | .owner = THIS_MODULE, | 1597 | .owner = THIS_MODULE, |
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h index 41f61cd18852..d28186948752 100644 --- a/drivers/net/ibmveth.h +++ b/drivers/net/ibmveth.h | |||
| @@ -93,9 +93,12 @@ static inline long h_illan_attributes(unsigned long unit_address, | |||
| 93 | plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) | 93 | plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) |
| 94 | 94 | ||
| 95 | #define IbmVethNumBufferPools 5 | 95 | #define IbmVethNumBufferPools 5 |
| 96 | #define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb */ | ||
| 96 | #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */ | 97 | #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */ |
| 97 | #define IBMVETH_MAX_MTU 68 | 98 | #define IBMVETH_MAX_MTU 68 |
| 98 | #define IBMVETH_MAX_POOL_COUNT 4096 | 99 | #define IBMVETH_MAX_POOL_COUNT 4096 |
| 100 | #define IBMVETH_BUFF_LIST_SIZE 4096 | ||
| 101 | #define IBMVETH_FILT_LIST_SIZE 4096 | ||
| 99 | #define IBMVETH_MAX_BUF_SIZE (1024 * 128) | 102 | #define IBMVETH_MAX_BUF_SIZE (1024 * 128) |
| 100 | 103 | ||
| 101 | static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 }; | 104 | static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 }; |
| @@ -143,6 +146,8 @@ struct ibmveth_adapter { | |||
| 143 | struct ibmveth_rx_q rx_queue; | 146 | struct ibmveth_rx_q rx_queue; |
| 144 | int pool_config; | 147 | int pool_config; |
| 145 | int rx_csum; | 148 | int rx_csum; |
| 149 | void *bounce_buffer; | ||
| 150 | dma_addr_t bounce_buffer_dma; | ||
| 146 | 151 | ||
| 147 | /* adapter specific stats */ | 152 | /* adapter specific stats */ |
| 148 | u64 replenish_task_cycles; | 153 | u64 replenish_task_cycles; |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c28d7cb2035b..0196a0df9021 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | //#define DEBUG | 19 | //#define DEBUG |
| 20 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
| 21 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
| 22 | #include <linux/ethtool.h> | ||
| 22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 23 | #include <linux/virtio.h> | 24 | #include <linux/virtio.h> |
| 24 | #include <linux/virtio_net.h> | 25 | #include <linux/virtio_net.h> |
| @@ -54,9 +55,15 @@ struct virtnet_info | |||
| 54 | struct tasklet_struct tasklet; | 55 | struct tasklet_struct tasklet; |
| 55 | bool free_in_tasklet; | 56 | bool free_in_tasklet; |
| 56 | 57 | ||
| 58 | /* I like... big packets and I cannot lie! */ | ||
| 59 | bool big_packets; | ||
| 60 | |||
| 57 | /* Receive & send queues. */ | 61 | /* Receive & send queues. */ |
| 58 | struct sk_buff_head recv; | 62 | struct sk_buff_head recv; |
| 59 | struct sk_buff_head send; | 63 | struct sk_buff_head send; |
| 64 | |||
| 65 | /* Chain pages by the private ptr. */ | ||
| 66 | struct page *pages; | ||
| 60 | }; | 67 | }; |
| 61 | 68 | ||
| 62 | static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb) | 69 | static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb) |
| @@ -69,6 +76,23 @@ static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb) | |||
| 69 | sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr)); | 76 | sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr)); |
| 70 | } | 77 | } |
| 71 | 78 | ||
| 79 | static void give_a_page(struct virtnet_info *vi, struct page *page) | ||
| 80 | { | ||
| 81 | page->private = (unsigned long)vi->pages; | ||
| 82 | vi->pages = page; | ||
| 83 | } | ||
| 84 | |||
| 85 | static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask) | ||
| 86 | { | ||
| 87 | struct page *p = vi->pages; | ||
| 88 | |||
| 89 | if (p) | ||
| 90 | vi->pages = (struct page *)p->private; | ||
| 91 | else | ||
| 92 | p = alloc_page(gfp_mask); | ||
| 93 | return p; | ||
| 94 | } | ||
| 95 | |||
| 72 | static void skb_xmit_done(struct virtqueue *svq) | 96 | static void skb_xmit_done(struct virtqueue *svq) |
| 73 | { | 97 | { |
| 74 | struct virtnet_info *vi = svq->vdev->priv; | 98 | struct virtnet_info *vi = svq->vdev->priv; |
| @@ -88,6 +112,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
| 88 | unsigned len) | 112 | unsigned len) |
| 89 | { | 113 | { |
| 90 | struct virtio_net_hdr *hdr = skb_vnet_hdr(skb); | 114 | struct virtio_net_hdr *hdr = skb_vnet_hdr(skb); |
| 115 | int err; | ||
| 91 | 116 | ||
| 92 | if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { | 117 | if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { |
| 93 | pr_debug("%s: short packet %i\n", dev->name, len); | 118 | pr_debug("%s: short packet %i\n", dev->name, len); |
| @@ -95,10 +120,23 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
| 95 | goto drop; | 120 | goto drop; |
| 96 | } | 121 | } |
| 97 | len -= sizeof(struct virtio_net_hdr); | 122 | len -= sizeof(struct virtio_net_hdr); |
| 98 | BUG_ON(len > MAX_PACKET_LEN); | ||
| 99 | 123 | ||
| 100 | skb_trim(skb, len); | 124 | if (len <= MAX_PACKET_LEN) { |
| 125 | unsigned int i; | ||
| 101 | 126 | ||
| 127 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) | ||
| 128 | give_a_page(dev->priv, skb_shinfo(skb)->frags[i].page); | ||
| 129 | skb->data_len = 0; | ||
| 130 | skb_shinfo(skb)->nr_frags = 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | err = pskb_trim(skb, len); | ||
| 134 | if (err) { | ||
| 135 | pr_debug("%s: pskb_trim failed %i %d\n", dev->name, len, err); | ||
| 136 | dev->stats.rx_dropped++; | ||
| 137 | goto drop; | ||
| 138 | } | ||
| 139 | skb->truesize += skb->data_len; | ||
| 102 | dev->stats.rx_bytes += skb->len; | 140 | dev->stats.rx_bytes += skb->len; |
| 103 | dev->stats.rx_packets++; | 141 | dev->stats.rx_packets++; |
| 104 | 142 | ||
| @@ -160,7 +198,7 @@ static void try_fill_recv(struct virtnet_info *vi) | |||
| 160 | { | 198 | { |
| 161 | struct sk_buff *skb; | 199 | struct sk_buff *skb; |
| 162 | struct scatterlist sg[2+MAX_SKB_FRAGS]; | 200 | struct scatterlist sg[2+MAX_SKB_FRAGS]; |
| 163 | int num, err; | 201 | int num, err, i; |
| 164 | 202 | ||
| 165 | sg_init_table(sg, 2+MAX_SKB_FRAGS); | 203 | sg_init_table(sg, 2+MAX_SKB_FRAGS); |
| 166 | for (;;) { | 204 | for (;;) { |
| @@ -170,6 +208,24 @@ static void try_fill_recv(struct virtnet_info *vi) | |||
| 170 | 208 | ||
| 171 | skb_put(skb, MAX_PACKET_LEN); | 209 | skb_put(skb, MAX_PACKET_LEN); |
| 172 | vnet_hdr_to_sg(sg, skb); | 210 | vnet_hdr_to_sg(sg, skb); |
| 211 | |||
| 212 | if (vi->big_packets) { | ||
| 213 | for (i = 0; i < MAX_SKB_FRAGS; i++) { | ||
| 214 | skb_frag_t *f = &skb_shinfo(skb)->frags[i]; | ||
| 215 | f->page = get_a_page(vi, GFP_ATOMIC); | ||
| 216 | if (!f->page) | ||
| 217 | break; | ||
| 218 | |||
| 219 | f->page_offset = 0; | ||
| 220 | f->size = PAGE_SIZE; | ||
| 221 | |||
| 222 | skb->data_len += PAGE_SIZE; | ||
| 223 | skb->len += PAGE_SIZE; | ||
| 224 | |||
| 225 | skb_shinfo(skb)->nr_frags++; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 173 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; | 229 | num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; |
| 174 | skb_queue_head(&vi->recv, skb); | 230 | skb_queue_head(&vi->recv, skb); |
| 175 | 231 | ||
| @@ -335,16 +391,11 @@ again: | |||
| 335 | free_old_xmit_skbs(vi); | 391 | free_old_xmit_skbs(vi); |
| 336 | 392 | ||
| 337 | /* If we has a buffer left over from last time, send it now. */ | 393 | /* If we has a buffer left over from last time, send it now. */ |
| 338 | if (unlikely(vi->last_xmit_skb)) { | 394 | if (unlikely(vi->last_xmit_skb) && |
| 339 | if (xmit_skb(vi, vi->last_xmit_skb) != 0) { | 395 | xmit_skb(vi, vi->last_xmit_skb) != 0) |
| 340 | /* Drop this skb: we only queue one. */ | 396 | goto stop_queue; |
| 341 | vi->dev->stats.tx_dropped++; | 397 | |
| 342 | kfree_skb(skb); | 398 | vi->last_xmit_skb = NULL; |
| 343 | skb = NULL; | ||
| 344 | goto stop_queue; | ||
| 345 | } | ||
| 346 | vi->last_xmit_skb = NULL; | ||
| 347 | } | ||
| 348 | 399 | ||
| 349 | /* Put new one in send queue and do transmit */ | 400 | /* Put new one in send queue and do transmit */ |
| 350 | if (likely(skb)) { | 401 | if (likely(skb)) { |
| @@ -370,6 +421,11 @@ stop_queue: | |||
| 370 | netif_start_queue(dev); | 421 | netif_start_queue(dev); |
| 371 | goto again; | 422 | goto again; |
| 372 | } | 423 | } |
| 424 | if (skb) { | ||
| 425 | /* Drop this skb: we only queue one. */ | ||
| 426 | vi->dev->stats.tx_dropped++; | ||
| 427 | kfree_skb(skb); | ||
| 428 | } | ||
| 373 | goto done; | 429 | goto done; |
| 374 | } | 430 | } |
| 375 | 431 | ||
| @@ -408,6 +464,22 @@ static int virtnet_close(struct net_device *dev) | |||
| 408 | return 0; | 464 | return 0; |
| 409 | } | 465 | } |
| 410 | 466 | ||
| 467 | static int virtnet_set_tx_csum(struct net_device *dev, u32 data) | ||
| 468 | { | ||
| 469 | struct virtnet_info *vi = netdev_priv(dev); | ||
| 470 | struct virtio_device *vdev = vi->vdev; | ||
| 471 | |||
| 472 | if (data && !virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) | ||
| 473 | return -ENOSYS; | ||
| 474 | |||
| 475 | return ethtool_op_set_tx_hw_csum(dev, data); | ||
| 476 | } | ||
| 477 | |||
| 478 | static struct ethtool_ops virtnet_ethtool_ops = { | ||
| 479 | .set_tx_csum = virtnet_set_tx_csum, | ||
| 480 | .set_sg = ethtool_op_set_sg, | ||
| 481 | }; | ||
| 482 | |||
| 411 | static int virtnet_probe(struct virtio_device *vdev) | 483 | static int virtnet_probe(struct virtio_device *vdev) |
| 412 | { | 484 | { |
| 413 | int err; | 485 | int err; |
| @@ -427,6 +499,7 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
| 427 | #ifdef CONFIG_NET_POLL_CONTROLLER | 499 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 428 | dev->poll_controller = virtnet_netpoll; | 500 | dev->poll_controller = virtnet_netpoll; |
| 429 | #endif | 501 | #endif |
| 502 | SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops); | ||
| 430 | SET_NETDEV_DEV(dev, &vdev->dev); | 503 | SET_NETDEV_DEV(dev, &vdev->dev); |
| 431 | 504 | ||
| 432 | /* Do we support "hardware" checksums? */ | 505 | /* Do we support "hardware" checksums? */ |
| @@ -462,11 +535,18 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
| 462 | vi->dev = dev; | 535 | vi->dev = dev; |
| 463 | vi->vdev = vdev; | 536 | vi->vdev = vdev; |
| 464 | vdev->priv = vi; | 537 | vdev->priv = vi; |
| 538 | vi->pages = NULL; | ||
| 465 | 539 | ||
| 466 | /* If they give us a callback when all buffers are done, we don't need | 540 | /* If they give us a callback when all buffers are done, we don't need |
| 467 | * the timer. */ | 541 | * the timer. */ |
| 468 | vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY); | 542 | vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY); |
| 469 | 543 | ||
| 544 | /* If we can receive ANY GSO packets, we must allocate large ones. */ | ||
| 545 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) | ||
| 546 | || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) | ||
| 547 | || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN)) | ||
| 548 | vi->big_packets = true; | ||
| 549 | |||
| 470 | /* We expect two virtqueues, receive then send. */ | 550 | /* We expect two virtqueues, receive then send. */ |
| 471 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); | 551 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); |
| 472 | if (IS_ERR(vi->rvq)) { | 552 | if (IS_ERR(vi->rvq)) { |
| @@ -541,6 +621,10 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
| 541 | vdev->config->del_vq(vi->svq); | 621 | vdev->config->del_vq(vi->svq); |
| 542 | vdev->config->del_vq(vi->rvq); | 622 | vdev->config->del_vq(vi->rvq); |
| 543 | unregister_netdev(vi->dev); | 623 | unregister_netdev(vi->dev); |
| 624 | |||
| 625 | while (vi->pages) | ||
| 626 | __free_pages(get_a_page(vi, GFP_KERNEL), 0); | ||
| 627 | |||
| 544 | free_netdev(vi->dev); | 628 | free_netdev(vi->dev); |
| 545 | } | 629 | } |
| 546 | 630 | ||
| @@ -553,7 +637,9 @@ static unsigned int features[] = { | |||
| 553 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, | 637 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, |
| 554 | VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, | 638 | VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, |
| 555 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, | 639 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, |
| 556 | VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY, | 640 | VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, |
| 641 | VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ | ||
| 642 | VIRTIO_F_NOTIFY_ON_EMPTY, | ||
| 557 | }; | 643 | }; |
| 558 | 644 | ||
| 559 | static struct virtio_driver virtio_net = { | 645 | static struct virtio_driver virtio_net = { |
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 3a7a11a75fb4..1d7ec3129349 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
| @@ -4,7 +4,7 @@ config OF_DEVICE | |||
| 4 | 4 | ||
| 5 | config OF_GPIO | 5 | config OF_GPIO |
| 6 | def_bool y | 6 | def_bool y |
| 7 | depends on OF && PPC_OF && HAVE_GPIO_LIB | 7 | depends on OF && PPC_OF && GPIOLIB |
| 8 | help | 8 | help |
| 9 | OpenFirmware GPIO accessors | 9 | OpenFirmware GPIO accessors |
| 10 | 10 | ||
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index 5c015d310d4a..344e1b03dd8b 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c | |||
| @@ -91,8 +91,6 @@ void of_register_i2c_devices(struct i2c_adapter *adap, | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | info.irq = irq_of_parse_and_map(node, 0); | 93 | info.irq = irq_of_parse_and_map(node, 0); |
| 94 | if (info.irq == NO_IRQ) | ||
| 95 | info.irq = -1; | ||
| 96 | 94 | ||
| 97 | if (of_find_i2c_driver(node, &info) < 0) { | 95 | if (of_find_i2c_driver(node, &info) < 0) { |
| 98 | irq_dispose_mapping(info.irq); | 96 | irq_dispose_mapping(info.irq); |
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c index 4ec220b2eae7..6938d2e9f18f 100644 --- a/drivers/parport/parport_ax88796.c +++ b/drivers/parport/parport_ax88796.c | |||
| @@ -406,6 +406,8 @@ static int parport_ax88796_resume(struct platform_device *dev) | |||
| 406 | #define parport_ax88796_resume NULL | 406 | #define parport_ax88796_resume NULL |
| 407 | #endif | 407 | #endif |
| 408 | 408 | ||
| 409 | MODULE_ALIAS("platform:ax88796-pp"); | ||
| 410 | |||
| 409 | static struct platform_driver axdrv = { | 411 | static struct platform_driver axdrv = { |
| 410 | .driver = { | 412 | .driver = { |
| 411 | .name = "ax88796-pp", | 413 | .name = "ax88796-pp", |
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index 71be36f18709..308ddb201b66 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c | |||
| @@ -433,6 +433,8 @@ static int ds2760_battery_resume(struct platform_device *pdev) | |||
| 433 | 433 | ||
| 434 | #endif /* CONFIG_PM */ | 434 | #endif /* CONFIG_PM */ |
| 435 | 435 | ||
| 436 | MODULE_ALIAS("platform:ds2760-battery"); | ||
| 437 | |||
| 436 | static struct platform_driver ds2760_battery_driver = { | 438 | static struct platform_driver ds2760_battery_driver = { |
| 437 | .driver = { | 439 | .driver = { |
| 438 | .name = "ds2760-battery", | 440 | .name = "ds2760-battery", |
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index 82810b7bff9c..0471ec743ab9 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c | |||
| @@ -362,6 +362,8 @@ static int pda_power_resume(struct platform_device *pdev) | |||
| 362 | #define pda_power_resume NULL | 362 | #define pda_power_resume NULL |
| 363 | #endif /* CONFIG_PM */ | 363 | #endif /* CONFIG_PM */ |
| 364 | 364 | ||
| 365 | MODULE_ALIAS("platform:pda-power"); | ||
| 366 | |||
| 365 | static struct platform_driver pda_power_pdrv = { | 367 | static struct platform_driver pda_power_pdrv = { |
| 366 | .driver = { | 368 | .driver = { |
| 367 | .name = "pda-power", | 369 | .name = "pda-power", |
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 5ab34340919b..79954bd6bfa5 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/virtio.h> | 16 | #include <linux/virtio.h> |
| 17 | #include <linux/virtio_config.h> | 17 | #include <linux/virtio_config.h> |
| 18 | #include <linux/virtio_console.h> | ||
| 18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 19 | #include <linux/virtio_ring.h> | 20 | #include <linux/virtio_ring.h> |
| 20 | #include <linux/pfn.h> | 21 | #include <linux/pfn.h> |
| @@ -87,16 +88,20 @@ static u32 kvm_get_features(struct virtio_device *vdev) | |||
| 87 | return features; | 88 | return features; |
| 88 | } | 89 | } |
| 89 | 90 | ||
| 90 | static void kvm_set_features(struct virtio_device *vdev, u32 features) | 91 | static void kvm_finalize_features(struct virtio_device *vdev) |
| 91 | { | 92 | { |
| 92 | unsigned int i; | 93 | unsigned int i, bits; |
| 93 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; | 94 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; |
| 94 | /* Second half of bitmap is features we accept. */ | 95 | /* Second half of bitmap is features we accept. */ |
| 95 | u8 *out_features = kvm_vq_features(desc) + desc->feature_len; | 96 | u8 *out_features = kvm_vq_features(desc) + desc->feature_len; |
| 96 | 97 | ||
| 98 | /* Give virtio_ring a chance to accept features. */ | ||
| 99 | vring_transport_features(vdev); | ||
| 100 | |||
| 97 | memset(out_features, 0, desc->feature_len); | 101 | memset(out_features, 0, desc->feature_len); |
| 98 | for (i = 0; i < min(desc->feature_len * 8, 32); i++) { | 102 | bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; |
| 99 | if (features & (1 << i)) | 103 | for (i = 0; i < bits; i++) { |
| 104 | if (test_bit(i, vdev->features)) | ||
| 100 | out_features[i / 8] |= (1 << (i % 8)); | 105 | out_features[i / 8] |= (1 << (i % 8)); |
| 101 | } | 106 | } |
| 102 | } | 107 | } |
| @@ -222,7 +227,7 @@ static void kvm_del_vq(struct virtqueue *vq) | |||
| 222 | */ | 227 | */ |
| 223 | static struct virtio_config_ops kvm_vq_configspace_ops = { | 228 | static struct virtio_config_ops kvm_vq_configspace_ops = { |
| 224 | .get_features = kvm_get_features, | 229 | .get_features = kvm_get_features, |
| 225 | .set_features = kvm_set_features, | 230 | .finalize_features = kvm_finalize_features, |
| 226 | .get = kvm_get, | 231 | .get = kvm_get, |
| 227 | .set = kvm_set, | 232 | .set = kvm_set, |
| 228 | .get_status = kvm_get_status, | 233 | .get_status = kvm_get_status, |
| @@ -333,6 +338,25 @@ static int __init kvm_devices_init(void) | |||
| 333 | return 0; | 338 | return 0; |
| 334 | } | 339 | } |
| 335 | 340 | ||
| 341 | /* code for early console output with virtio_console */ | ||
| 342 | static __init int early_put_chars(u32 vtermno, const char *buf, int count) | ||
| 343 | { | ||
| 344 | char scratch[17]; | ||
| 345 | unsigned int len = count; | ||
| 346 | |||
| 347 | if (len > sizeof(scratch) - 1) | ||
| 348 | len = sizeof(scratch) - 1; | ||
| 349 | scratch[len] = '\0'; | ||
| 350 | memcpy(scratch, buf, len); | ||
| 351 | kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, __pa(scratch)); | ||
| 352 | return len; | ||
| 353 | } | ||
| 354 | |||
| 355 | void s390_virtio_console_init(void) | ||
| 356 | { | ||
| 357 | virtio_cons_early_init(early_put_chars); | ||
| 358 | } | ||
| 359 | |||
| 336 | /* | 360 | /* |
| 337 | * We do this after core stuff, but before the drivers. | 361 | * We do this after core stuff, but before the drivers. |
| 338 | */ | 362 | */ |
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index eb702b96d57c..c4a7c06793c5 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
| @@ -3819,6 +3819,20 @@ static int ibmvfc_remove(struct vio_dev *vdev) | |||
| 3819 | return 0; | 3819 | return 0; |
| 3820 | } | 3820 | } |
| 3821 | 3821 | ||
| 3822 | /** | ||
| 3823 | * ibmvfc_get_desired_dma - Calculate DMA resources needed by the driver | ||
| 3824 | * @vdev: vio device struct | ||
| 3825 | * | ||
| 3826 | * Return value: | ||
| 3827 | * Number of bytes the driver will need to DMA map at the same time in | ||
| 3828 | * order to perform well. | ||
| 3829 | */ | ||
| 3830 | static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev) | ||
| 3831 | { | ||
| 3832 | unsigned long pool_dma = max_requests * sizeof(union ibmvfc_iu); | ||
| 3833 | return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun); | ||
| 3834 | } | ||
| 3835 | |||
| 3822 | static struct vio_device_id ibmvfc_device_table[] __devinitdata = { | 3836 | static struct vio_device_id ibmvfc_device_table[] __devinitdata = { |
| 3823 | {"fcp", "IBM,vfc-client"}, | 3837 | {"fcp", "IBM,vfc-client"}, |
| 3824 | { "", "" } | 3838 | { "", "" } |
| @@ -3829,6 +3843,7 @@ static struct vio_driver ibmvfc_driver = { | |||
| 3829 | .id_table = ibmvfc_device_table, | 3843 | .id_table = ibmvfc_device_table, |
| 3830 | .probe = ibmvfc_probe, | 3844 | .probe = ibmvfc_probe, |
| 3831 | .remove = ibmvfc_remove, | 3845 | .remove = ibmvfc_remove, |
| 3846 | .get_desired_dma = ibmvfc_get_desired_dma, | ||
| 3832 | .driver = { | 3847 | .driver = { |
| 3833 | .name = IBMVFC_NAME, | 3848 | .name = IBMVFC_NAME, |
| 3834 | .owner = THIS_MODULE, | 3849 | .owner = THIS_MODULE, |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5d23368a1bce..20000ec79b04 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | #include <linux/delay.h> | 72 | #include <linux/delay.h> |
| 73 | #include <asm/firmware.h> | 73 | #include <asm/firmware.h> |
| 74 | #include <asm/vio.h> | 74 | #include <asm/vio.h> |
| 75 | #include <asm/firmware.h> | ||
| 75 | #include <scsi/scsi.h> | 76 | #include <scsi/scsi.h> |
| 76 | #include <scsi/scsi_cmnd.h> | 77 | #include <scsi/scsi_cmnd.h> |
| 77 | #include <scsi/scsi_host.h> | 78 | #include <scsi/scsi_host.h> |
| @@ -426,8 +427,10 @@ static int map_sg_data(struct scsi_cmnd *cmd, | |||
| 426 | SG_ALL * sizeof(struct srp_direct_buf), | 427 | SG_ALL * sizeof(struct srp_direct_buf), |
| 427 | &evt_struct->ext_list_token, 0); | 428 | &evt_struct->ext_list_token, 0); |
| 428 | if (!evt_struct->ext_list) { | 429 | if (!evt_struct->ext_list) { |
| 429 | sdev_printk(KERN_ERR, cmd->device, | 430 | if (!firmware_has_feature(FW_FEATURE_CMO)) |
| 430 | "Can't allocate memory for indirect table\n"); | 431 | sdev_printk(KERN_ERR, cmd->device, |
| 432 | "Can't allocate memory " | ||
| 433 | "for indirect table\n"); | ||
| 431 | return 0; | 434 | return 0; |
| 432 | } | 435 | } |
| 433 | } | 436 | } |
| @@ -743,7 +746,9 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, | |||
| 743 | srp_cmd->lun = ((u64) lun) << 48; | 746 | srp_cmd->lun = ((u64) lun) << 48; |
| 744 | 747 | ||
| 745 | if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { | 748 | if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) { |
| 746 | sdev_printk(KERN_ERR, cmnd->device, "couldn't convert cmd to srp_cmd\n"); | 749 | if (!firmware_has_feature(FW_FEATURE_CMO)) |
| 750 | sdev_printk(KERN_ERR, cmnd->device, | ||
| 751 | "couldn't convert cmd to srp_cmd\n"); | ||
| 747 | free_event_struct(&hostdata->pool, evt_struct); | 752 | free_event_struct(&hostdata->pool, evt_struct); |
| 748 | return SCSI_MLQUEUE_HOST_BUSY; | 753 | return SCSI_MLQUEUE_HOST_BUSY; |
| 749 | } | 754 | } |
| @@ -855,7 +860,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata) | |||
| 855 | DMA_BIDIRECTIONAL); | 860 | DMA_BIDIRECTIONAL); |
| 856 | 861 | ||
| 857 | if (dma_mapping_error(req->buffer)) { | 862 | if (dma_mapping_error(req->buffer)) { |
| 858 | dev_err(hostdata->dev, "Unable to map request_buffer for adapter_info!\n"); | 863 | if (!firmware_has_feature(FW_FEATURE_CMO)) |
| 864 | dev_err(hostdata->dev, | ||
| 865 | "Unable to map request_buffer for " | ||
| 866 | "adapter_info!\n"); | ||
| 859 | free_event_struct(&hostdata->pool, evt_struct); | 867 | free_event_struct(&hostdata->pool, evt_struct); |
| 860 | return; | 868 | return; |
| 861 | } | 869 | } |
| @@ -1400,7 +1408,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, | |||
| 1400 | DMA_BIDIRECTIONAL); | 1408 | DMA_BIDIRECTIONAL); |
| 1401 | 1409 | ||
| 1402 | if (dma_mapping_error(host_config->buffer)) { | 1410 | if (dma_mapping_error(host_config->buffer)) { |
| 1403 | dev_err(hostdata->dev, "dma_mapping error getting host config\n"); | 1411 | if (!firmware_has_feature(FW_FEATURE_CMO)) |
| 1412 | dev_err(hostdata->dev, | ||
| 1413 | "dma_mapping error getting host config\n"); | ||
| 1404 | free_event_struct(&hostdata->pool, evt_struct); | 1414 | free_event_struct(&hostdata->pool, evt_struct); |
| 1405 | return -1; | 1415 | return -1; |
| 1406 | } | 1416 | } |
| @@ -1604,7 +1614,7 @@ static struct scsi_host_template driver_template = { | |||
| 1604 | .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, | 1614 | .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, |
| 1605 | .slave_configure = ibmvscsi_slave_configure, | 1615 | .slave_configure = ibmvscsi_slave_configure, |
| 1606 | .change_queue_depth = ibmvscsi_change_queue_depth, | 1616 | .change_queue_depth = ibmvscsi_change_queue_depth, |
| 1607 | .cmd_per_lun = 16, | 1617 | .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT, |
| 1608 | .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, | 1618 | .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, |
| 1609 | .this_id = -1, | 1619 | .this_id = -1, |
| 1610 | .sg_tablesize = SG_ALL, | 1620 | .sg_tablesize = SG_ALL, |
| @@ -1613,6 +1623,26 @@ static struct scsi_host_template driver_template = { | |||
| 1613 | }; | 1623 | }; |
| 1614 | 1624 | ||
| 1615 | /** | 1625 | /** |
| 1626 | * ibmvscsi_get_desired_dma - Calculate IO memory desired by the driver | ||
| 1627 | * | ||
| 1628 | * @vdev: struct vio_dev for the device whose desired IO mem is to be returned | ||
| 1629 | * | ||
| 1630 | * Return value: | ||
| 1631 | * Number of bytes of IO data the driver will need to perform well. | ||
| 1632 | */ | ||
| 1633 | static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev) | ||
| 1634 | { | ||
| 1635 | /* iu_storage data allocated in initialize_event_pool */ | ||
| 1636 | unsigned long desired_io = max_requests * sizeof(union viosrp_iu); | ||
| 1637 | |||
| 1638 | /* add io space for sg data */ | ||
| 1639 | desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * | ||
| 1640 | IBMVSCSI_CMDS_PER_LUN_DEFAULT); | ||
| 1641 | |||
| 1642 | return desired_io; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | /** | ||
| 1616 | * Called by bus code for each adapter | 1646 | * Called by bus code for each adapter |
| 1617 | */ | 1647 | */ |
| 1618 | static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | 1648 | static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) |
| @@ -1641,7 +1671,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
| 1641 | hostdata->host = host; | 1671 | hostdata->host = host; |
| 1642 | hostdata->dev = dev; | 1672 | hostdata->dev = dev; |
| 1643 | atomic_set(&hostdata->request_limit, -1); | 1673 | atomic_set(&hostdata->request_limit, -1); |
| 1644 | hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */ | 1674 | hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT; |
| 1645 | 1675 | ||
| 1646 | rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests); | 1676 | rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests); |
| 1647 | if (rc != 0 && rc != H_RESOURCE) { | 1677 | if (rc != 0 && rc != H_RESOURCE) { |
| @@ -1735,6 +1765,7 @@ static struct vio_driver ibmvscsi_driver = { | |||
| 1735 | .id_table = ibmvscsi_device_table, | 1765 | .id_table = ibmvscsi_device_table, |
| 1736 | .probe = ibmvscsi_probe, | 1766 | .probe = ibmvscsi_probe, |
| 1737 | .remove = ibmvscsi_remove, | 1767 | .remove = ibmvscsi_remove, |
| 1768 | .get_desired_dma = ibmvscsi_get_desired_dma, | ||
| 1738 | .driver = { | 1769 | .driver = { |
| 1739 | .name = "ibmvscsi", | 1770 | .name = "ibmvscsi", |
| 1740 | .owner = THIS_MODULE, | 1771 | .owner = THIS_MODULE, |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index 46e850e302c7..2d4339d5e16e 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h | |||
| @@ -45,6 +45,8 @@ struct Scsi_Host; | |||
| 45 | #define MAX_INDIRECT_BUFS 10 | 45 | #define MAX_INDIRECT_BUFS 10 |
| 46 | 46 | ||
| 47 | #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100 | 47 | #define IBMVSCSI_MAX_REQUESTS_DEFAULT 100 |
| 48 | #define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16 | ||
| 49 | #define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */ | ||
| 48 | #define IBMVSCSI_MAX_CMDS_PER_LUN 64 | 50 | #define IBMVSCSI_MAX_CMDS_PER_LUN 64 |
| 49 | 51 | ||
| 50 | /* ------------------------------------------------------------ | 52 | /* ------------------------------------------------------------ |
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index 49cd9793404f..ec7aeb502d15 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c | |||
| @@ -6095,15 +6095,15 @@ static int capabilities_check(IXJ *j, struct phone_capability *pcreq) | |||
| 6095 | return retval; | 6095 | return retval; |
| 6096 | } | 6096 | } |
| 6097 | 6097 | ||
| 6098 | static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg) | 6098 | static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg) |
| 6099 | { | 6099 | { |
| 6100 | IXJ_TONE ti; | 6100 | IXJ_TONE ti; |
| 6101 | IXJ_FILTER jf; | 6101 | IXJ_FILTER jf; |
| 6102 | IXJ_FILTER_RAW jfr; | 6102 | IXJ_FILTER_RAW jfr; |
| 6103 | void __user *argp = (void __user *)arg; | 6103 | void __user *argp = (void __user *)arg; |
| 6104 | 6104 | struct inode *inode = file_p->f_path.dentry->d_inode; | |
| 6105 | unsigned int raise, mant; | ||
| 6106 | unsigned int minor = iminor(inode); | 6105 | unsigned int minor = iminor(inode); |
| 6106 | unsigned int raise, mant; | ||
| 6107 | int board = NUM(inode); | 6107 | int board = NUM(inode); |
| 6108 | 6108 | ||
| 6109 | IXJ *j = get_ixj(NUM(inode)); | 6109 | IXJ *j = get_ixj(NUM(inode)); |
| @@ -6661,6 +6661,15 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, | |||
| 6661 | return retval; | 6661 | return retval; |
| 6662 | } | 6662 | } |
| 6663 | 6663 | ||
| 6664 | static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg) | ||
| 6665 | { | ||
| 6666 | long ret; | ||
| 6667 | lock_kernel(); | ||
| 6668 | ret = do_ixj_ioctl(file_p, cmd, arg); | ||
| 6669 | unlock_kernel(); | ||
| 6670 | return ret; | ||
| 6671 | } | ||
| 6672 | |||
| 6664 | static int ixj_fasync(int fd, struct file *file_p, int mode) | 6673 | static int ixj_fasync(int fd, struct file *file_p, int mode) |
| 6665 | { | 6674 | { |
| 6666 | IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); | 6675 | IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); |
| @@ -6674,7 +6683,7 @@ static const struct file_operations ixj_fops = | |||
| 6674 | .read = ixj_enhanced_read, | 6683 | .read = ixj_enhanced_read, |
| 6675 | .write = ixj_enhanced_write, | 6684 | .write = ixj_enhanced_write, |
| 6676 | .poll = ixj_poll, | 6685 | .poll = ixj_poll, |
| 6677 | .ioctl = ixj_ioctl, | 6686 | .unlocked_ioctl = ixj_ioctl, |
| 6678 | .release = ixj_release, | 6687 | .release = ixj_release, |
| 6679 | .fasync = ixj_fasync | 6688 | .fasync = ixj_fasync |
| 6680 | }; | 6689 | }; |
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index a973f2a50fb9..c65d62295890 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h | |||
| @@ -171,7 +171,7 @@ struct at91_request { | |||
| 171 | #endif | 171 | #endif |
| 172 | 172 | ||
| 173 | #define ERR(stuff...) pr_err("udc: " stuff) | 173 | #define ERR(stuff...) pr_err("udc: " stuff) |
| 174 | #define WARN(stuff...) pr_warning("udc: " stuff) | 174 | #define WARNING(stuff...) pr_warning("udc: " stuff) |
| 175 | #define INFO(stuff...) pr_info("udc: " stuff) | 175 | #define INFO(stuff...) pr_info("udc: " stuff) |
| 176 | #define DBG(stuff...) pr_debug("udc: " stuff) | 176 | #define DBG(stuff...) pr_debug("udc: " stuff) |
| 177 | 177 | ||
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index d490d0289507..a39a4b940c33 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c | |||
| @@ -170,7 +170,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) | |||
| 170 | * but if the controller isn't recognized at all then | 170 | * but if the controller isn't recognized at all then |
| 171 | * that assumption is a bit more likely to be wrong. | 171 | * that assumption is a bit more likely to be wrong. |
| 172 | */ | 172 | */ |
| 173 | WARN(cdev, "controller '%s' not recognized; trying %s\n", | 173 | WARNING(cdev, "controller '%s' not recognized; trying %s\n", |
| 174 | gadget->name, | 174 | gadget->name, |
| 175 | cdc_config_driver.label); | 175 | cdc_config_driver.label); |
| 176 | device_desc.bcdDevice = | 176 | device_desc.bcdDevice = |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index d7aaaa29b1e1..bcac2e68660d 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
| @@ -293,7 +293,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev) | |||
| 293 | * but if the controller isn't recognized at all then | 293 | * but if the controller isn't recognized at all then |
| 294 | * that assumption is a bit more likely to be wrong. | 294 | * that assumption is a bit more likely to be wrong. |
| 295 | */ | 295 | */ |
| 296 | WARN(cdev, "controller '%s' not recognized; trying %s\n", | 296 | WARNING(cdev, "controller '%s' not recognized; trying %s\n", |
| 297 | gadget->name, | 297 | gadget->name, |
| 298 | eth_config_driver.label); | 298 | eth_config_driver.label); |
| 299 | device_desc.bcdDevice = | 299 | device_desc.bcdDevice = |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 15c24edbb61a..ea2c31d18080 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
| @@ -308,7 +308,7 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
| 308 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) | 308 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) |
| 309 | #define ERROR(d, fmt, args...) \ | 309 | #define ERROR(d, fmt, args...) \ |
| 310 | dev_err(&(d)->gadget->dev , fmt , ## args) | 310 | dev_err(&(d)->gadget->dev , fmt , ## args) |
| 311 | #define WARN(d, fmt, args...) \ | 311 | #define WARNING(d, fmt, args...) \ |
| 312 | dev_warn(&(d)->gadget->dev , fmt , ## args) | 312 | dev_warn(&(d)->gadget->dev , fmt , ## args) |
| 313 | #define INFO(d, fmt, args...) \ | 313 | #define INFO(d, fmt, args...) \ |
| 314 | dev_info(&(d)->gadget->dev , fmt , ## args) | 314 | dev_info(&(d)->gadget->dev , fmt , ## args) |
| @@ -1091,7 +1091,7 @@ static int ep0_queue(struct fsg_dev *fsg) | |||
| 1091 | if (rc != 0 && rc != -ESHUTDOWN) { | 1091 | if (rc != 0 && rc != -ESHUTDOWN) { |
| 1092 | 1092 | ||
| 1093 | /* We can't do much more than wait for a reset */ | 1093 | /* We can't do much more than wait for a reset */ |
| 1094 | WARN(fsg, "error in submission: %s --> %d\n", | 1094 | WARNING(fsg, "error in submission: %s --> %d\n", |
| 1095 | fsg->ep0->name, rc); | 1095 | fsg->ep0->name, rc); |
| 1096 | } | 1096 | } |
| 1097 | return rc; | 1097 | return rc; |
| @@ -1227,7 +1227,7 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
| 1227 | 1227 | ||
| 1228 | /* Save the command for later */ | 1228 | /* Save the command for later */ |
| 1229 | if (fsg->cbbuf_cmnd_size) | 1229 | if (fsg->cbbuf_cmnd_size) |
| 1230 | WARN(fsg, "CB[I] overwriting previous command\n"); | 1230 | WARNING(fsg, "CB[I] overwriting previous command\n"); |
| 1231 | fsg->cbbuf_cmnd_size = req->actual; | 1231 | fsg->cbbuf_cmnd_size = req->actual; |
| 1232 | memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); | 1232 | memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); |
| 1233 | 1233 | ||
| @@ -1506,7 +1506,7 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, | |||
| 1506 | * submissions if DMA is enabled. */ | 1506 | * submissions if DMA is enabled. */ |
| 1507 | if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && | 1507 | if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && |
| 1508 | req->length == 0)) | 1508 | req->length == 0)) |
| 1509 | WARN(fsg, "error in submission: %s --> %d\n", | 1509 | WARNING(fsg, "error in submission: %s --> %d\n", |
| 1510 | ep->name, rc); | 1510 | ep->name, rc); |
| 1511 | } | 1511 | } |
| 1512 | } | 1512 | } |
| @@ -2294,7 +2294,7 @@ static int halt_bulk_in_endpoint(struct fsg_dev *fsg) | |||
| 2294 | VDBG(fsg, "delayed bulk-in endpoint halt\n"); | 2294 | VDBG(fsg, "delayed bulk-in endpoint halt\n"); |
| 2295 | while (rc != 0) { | 2295 | while (rc != 0) { |
| 2296 | if (rc != -EAGAIN) { | 2296 | if (rc != -EAGAIN) { |
| 2297 | WARN(fsg, "usb_ep_set_halt -> %d\n", rc); | 2297 | WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); |
| 2298 | rc = 0; | 2298 | rc = 0; |
| 2299 | break; | 2299 | break; |
| 2300 | } | 2300 | } |
| @@ -2317,7 +2317,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) | |||
| 2317 | VDBG(fsg, "delayed bulk-in endpoint wedge\n"); | 2317 | VDBG(fsg, "delayed bulk-in endpoint wedge\n"); |
| 2318 | while (rc != 0) { | 2318 | while (rc != 0) { |
| 2319 | if (rc != -EAGAIN) { | 2319 | if (rc != -EAGAIN) { |
| 2320 | WARN(fsg, "usb_ep_set_wedge -> %d\n", rc); | 2320 | WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); |
| 2321 | rc = 0; | 2321 | rc = 0; |
| 2322 | break; | 2322 | break; |
| 2323 | } | 2323 | } |
| @@ -3755,7 +3755,7 @@ static int __init check_parameters(struct fsg_dev *fsg) | |||
| 3755 | if (gcnum >= 0) | 3755 | if (gcnum >= 0) |
| 3756 | mod_data.release = 0x0300 + gcnum; | 3756 | mod_data.release = 0x0300 + gcnum; |
| 3757 | else { | 3757 | else { |
| 3758 | WARN(fsg, "controller '%s' not recognized\n", | 3758 | WARNING(fsg, "controller '%s' not recognized\n", |
| 3759 | fsg->gadget->name); | 3759 | fsg->gadget->name); |
| 3760 | mod_data.release = 0x0399; | 3760 | mod_data.release = 0x0399; |
| 3761 | } | 3761 | } |
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 1695382f30fe..1cfccf102a2d 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c | |||
| @@ -1538,7 +1538,7 @@ static void dtd_complete_irq(struct fsl_udc *udc) | |||
| 1538 | 1538 | ||
| 1539 | /* If the ep is configured */ | 1539 | /* If the ep is configured */ |
| 1540 | if (curr_ep->name == NULL) { | 1540 | if (curr_ep->name == NULL) { |
| 1541 | WARN("Invalid EP?"); | 1541 | WARNING("Invalid EP?"); |
| 1542 | continue; | 1542 | continue; |
| 1543 | } | 1543 | } |
| 1544 | 1544 | ||
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 98b1483ef6a5..6131752a38bc 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h | |||
| @@ -552,7 +552,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) | |||
| 552 | #endif | 552 | #endif |
| 553 | 553 | ||
| 554 | #define ERR(stuff...) pr_err("udc: " stuff) | 554 | #define ERR(stuff...) pr_err("udc: " stuff) |
| 555 | #define WARN(stuff...) pr_warning("udc: " stuff) | 555 | #define WARNING(stuff...) pr_warning("udc: " stuff) |
| 556 | #define INFO(stuff...) pr_info("udc: " stuff) | 556 | #define INFO(stuff...) pr_info("udc: " stuff) |
| 557 | 557 | ||
| 558 | /*-------------------------------------------------------------------------*/ | 558 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 7f4d4828e3aa..ea8651e3da1a 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c | |||
| @@ -138,8 +138,6 @@ static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req); | |||
| 138 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) | 138 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) |
| 139 | #define ERROR(d, fmt, args...) \ | 139 | #define ERROR(d, fmt, args...) \ |
| 140 | dev_err(&(d)->gadget->dev , fmt , ## args) | 140 | dev_err(&(d)->gadget->dev , fmt , ## args) |
| 141 | #define WARN(d, fmt, args...) \ | ||
| 142 | dev_warn(&(d)->gadget->dev , fmt , ## args) | ||
| 143 | #define INFO(d, fmt, args...) \ | 141 | #define INFO(d, fmt, args...) \ |
| 144 | dev_info(&(d)->gadget->dev , fmt , ## args) | 142 | dev_info(&(d)->gadget->dev , fmt , ## args) |
| 145 | 143 | ||
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 48f1c63b7013..60aa04847b18 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
| @@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1768 | * usb_gadget_driver_{register,unregister}() must change. | 1768 | * usb_gadget_driver_{register,unregister}() must change. |
| 1769 | */ | 1769 | */ |
| 1770 | if (the_controller) { | 1770 | if (the_controller) { |
| 1771 | WARN(dev, "ignoring %s\n", pci_name(pdev)); | 1771 | WARNING(dev, "ignoring %s\n", pci_name(pdev)); |
| 1772 | return -EBUSY; | 1772 | return -EBUSY; |
| 1773 | } | 1773 | } |
| 1774 | if (!pdev->irq) { | 1774 | if (!pdev->irq) { |
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index bc4eb1e0b507..566cb2319056 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h | |||
| @@ -285,7 +285,7 @@ struct goku_udc { | |||
| 285 | 285 | ||
| 286 | #define ERROR(dev,fmt,args...) \ | 286 | #define ERROR(dev,fmt,args...) \ |
| 287 | xprintk(dev , KERN_ERR , fmt , ## args) | 287 | xprintk(dev , KERN_ERR , fmt , ## args) |
| 288 | #define WARN(dev,fmt,args...) \ | 288 | #define WARNING(dev,fmt,args...) \ |
| 289 | xprintk(dev , KERN_WARNING , fmt , ## args) | 289 | xprintk(dev , KERN_WARNING , fmt , ## args) |
| 290 | #define INFO(dev,fmt,args...) \ | 290 | #define INFO(dev,fmt,args...) \ |
| 291 | xprintk(dev , KERN_INFO , fmt , ## args) | 291 | xprintk(dev , KERN_INFO , fmt , ## args) |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 04692d59fc1c..f4585d3e90d7 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
| @@ -262,8 +262,6 @@ static const char *CHIP; | |||
| 262 | 262 | ||
| 263 | #define ERROR(dev,fmt,args...) \ | 263 | #define ERROR(dev,fmt,args...) \ |
| 264 | xprintk(dev , KERN_ERR , fmt , ## args) | 264 | xprintk(dev , KERN_ERR , fmt , ## args) |
| 265 | #define WARN(dev,fmt,args...) \ | ||
| 266 | xprintk(dev , KERN_WARNING , fmt , ## args) | ||
| 267 | #define INFO(dev,fmt,args...) \ | 265 | #define INFO(dev,fmt,args...) \ |
| 268 | xprintk(dev , KERN_INFO , fmt , ## args) | 266 | xprintk(dev , KERN_INFO , fmt , ## args) |
| 269 | 267 | ||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index b67ab677af72..5cfb5ebf3881 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
| @@ -1007,7 +1007,7 @@ static void scan_dma_completions (struct net2280_ep *ep) | |||
| 1007 | * 0122, and 0124; not all cases trigger the warning. | 1007 | * 0122, and 0124; not all cases trigger the warning. |
| 1008 | */ | 1008 | */ |
| 1009 | if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) { | 1009 | if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) { |
| 1010 | WARN (ep->dev, "%s lost packet sync!\n", | 1010 | WARNING (ep->dev, "%s lost packet sync!\n", |
| 1011 | ep->ep.name); | 1011 | ep->ep.name); |
| 1012 | req->req.status = -EOVERFLOW; | 1012 | req->req.status = -EOVERFLOW; |
| 1013 | } else if ((tmp = readl (&ep->regs->ep_avail)) != 0) { | 1013 | } else if ((tmp = readl (&ep->regs->ep_avail)) != 0) { |
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h index 1f2af398a9a4..81a71dbdc2c6 100644 --- a/drivers/usb/gadget/net2280.h +++ b/drivers/usb/gadget/net2280.h | |||
| @@ -272,7 +272,7 @@ static inline void net2280_led_shutdown (struct net2280 *dev) | |||
| 272 | 272 | ||
| 273 | #define ERROR(dev,fmt,args...) \ | 273 | #define ERROR(dev,fmt,args...) \ |
| 274 | xprintk(dev , KERN_ERR , fmt , ## args) | 274 | xprintk(dev , KERN_ERR , fmt , ## args) |
| 275 | #define WARN(dev,fmt,args...) \ | 275 | #define WARNING(dev,fmt,args...) \ |
| 276 | xprintk(dev , KERN_WARNING , fmt , ## args) | 276 | xprintk(dev , KERN_WARNING , fmt , ## args) |
| 277 | #define INFO(dev,fmt,args...) \ | 277 | #define INFO(dev,fmt,args...) \ |
| 278 | xprintk(dev , KERN_INFO , fmt , ## args) | 278 | xprintk(dev , KERN_INFO , fmt , ## args) |
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 4b79a8509e84..395bd1844482 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
| @@ -1120,7 +1120,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) | |||
| 1120 | status = -EINVAL; | 1120 | status = -EINVAL; |
| 1121 | else if (value) { | 1121 | else if (value) { |
| 1122 | if (ep->udc->ep0_set_config) { | 1122 | if (ep->udc->ep0_set_config) { |
| 1123 | WARN("error changing config?\n"); | 1123 | WARNING("error changing config?\n"); |
| 1124 | omap_writew(UDC_CLR_CFG, UDC_SYSCON2); | 1124 | omap_writew(UDC_CLR_CFG, UDC_SYSCON2); |
| 1125 | } | 1125 | } |
| 1126 | omap_writew(UDC_STALL_CMD, UDC_SYSCON2); | 1126 | omap_writew(UDC_STALL_CMD, UDC_SYSCON2); |
| @@ -1764,7 +1764,7 @@ do_stall: | |||
| 1764 | u.r.bRequestType, u.r.bRequest, status); | 1764 | u.r.bRequestType, u.r.bRequest, status); |
| 1765 | if (udc->ep0_set_config) { | 1765 | if (udc->ep0_set_config) { |
| 1766 | if (udc->ep0_reset_config) | 1766 | if (udc->ep0_reset_config) |
| 1767 | WARN("error resetting config?\n"); | 1767 | WARNING("error resetting config?\n"); |
| 1768 | else | 1768 | else |
| 1769 | omap_writew(UDC_CLR_CFG, UDC_SYSCON2); | 1769 | omap_writew(UDC_CLR_CFG, UDC_SYSCON2); |
| 1770 | } | 1770 | } |
| @@ -3076,7 +3076,7 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message) | |||
| 3076 | * which would prevent entry to deep sleep... | 3076 | * which would prevent entry to deep sleep... |
| 3077 | */ | 3077 | */ |
| 3078 | if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) { | 3078 | if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) { |
| 3079 | WARN("session active; suspend requires disconnect\n"); | 3079 | WARNING("session active; suspend requires disconnect\n"); |
| 3080 | omap_pullup(&udc->gadget, 0); | 3080 | omap_pullup(&udc->gadget, 0); |
| 3081 | } | 3081 | } |
| 3082 | 3082 | ||
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index 8522bbb12278..29edc51b6b22 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h | |||
| @@ -188,7 +188,7 @@ struct omap_udc { | |||
| 188 | #endif | 188 | #endif |
| 189 | 189 | ||
| 190 | #define ERR(stuff...) pr_err("udc: " stuff) | 190 | #define ERR(stuff...) pr_err("udc: " stuff) |
| 191 | #define WARN(stuff...) pr_warning("udc: " stuff) | 191 | #define WARNING(stuff...) pr_warning("udc: " stuff) |
| 192 | #define INFO(stuff...) pr_info("udc: " stuff) | 192 | #define INFO(stuff...) pr_info("udc: " stuff) |
| 193 | #define DBG(stuff...) pr_debug("udc: " stuff) | 193 | #define DBG(stuff...) pr_debug("udc: " stuff) |
| 194 | 194 | ||
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 49cd9e145a9b..e0090085b78e 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c | |||
| @@ -179,7 +179,7 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); | |||
| 179 | 179 | ||
| 180 | #define ERROR(dev, fmt, args...) \ | 180 | #define ERROR(dev, fmt, args...) \ |
| 181 | xprintk(dev, KERN_ERR, fmt, ## args) | 181 | xprintk(dev, KERN_ERR, fmt, ## args) |
| 182 | #define WARN(dev, fmt, args...) \ | 182 | #define WARNING(dev, fmt, args...) \ |
| 183 | xprintk(dev, KERN_WARNING, fmt, ## args) | 183 | xprintk(dev, KERN_WARNING, fmt, ## args) |
| 184 | #define INFO(dev, fmt, args...) \ | 184 | #define INFO(dev, fmt, args...) \ |
| 185 | xprintk(dev, KERN_INFO, fmt, ## args) | 185 | xprintk(dev, KERN_INFO, fmt, ## args) |
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 8fb0066609bb..7e6725d89976 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c | |||
| @@ -342,7 +342,7 @@ pxa25x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req) | |||
| 342 | struct pxa25x_request *req; | 342 | struct pxa25x_request *req; |
| 343 | 343 | ||
| 344 | req = container_of (_req, struct pxa25x_request, req); | 344 | req = container_of (_req, struct pxa25x_request, req); |
| 345 | WARN_ON (!list_empty (&req->queue)); | 345 | WARN_ON(!list_empty (&req->queue)); |
| 346 | kfree(req); | 346 | kfree(req); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| @@ -1556,7 +1556,7 @@ config_change: | |||
| 1556 | * tell us about config change events, | 1556 | * tell us about config change events, |
| 1557 | * so later ones may fail... | 1557 | * so later ones may fail... |
| 1558 | */ | 1558 | */ |
| 1559 | WARN("config change %02x fail %d?\n", | 1559 | WARNING("config change %02x fail %d?\n", |
| 1560 | u.r.bRequest, i); | 1560 | u.r.bRequest, i); |
| 1561 | return; | 1561 | return; |
| 1562 | /* TODO experiment: if has_cfr, | 1562 | /* TODO experiment: if has_cfr, |
| @@ -2330,7 +2330,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state) | |||
| 2330 | unsigned long flags; | 2330 | unsigned long flags; |
| 2331 | 2331 | ||
| 2332 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | 2332 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) |
| 2333 | WARN("USB host won't detect disconnect!\n"); | 2333 | WARNING("USB host won't detect disconnect!\n"); |
| 2334 | udc->suspended = 1; | 2334 | udc->suspended = 1; |
| 2335 | 2335 | ||
| 2336 | local_irq_save(flags); | 2336 | local_irq_save(flags); |
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h index 4d11ece7c95f..c8a13215e02c 100644 --- a/drivers/usb/gadget/pxa25x_udc.h +++ b/drivers/usb/gadget/pxa25x_udc.h | |||
| @@ -259,7 +259,7 @@ dump_state(struct pxa25x_udc *dev) | |||
| 259 | #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0) | 259 | #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0) |
| 260 | 260 | ||
| 261 | #define ERR(stuff...) pr_err("udc: " stuff) | 261 | #define ERR(stuff...) pr_err("udc: " stuff) |
| 262 | #define WARN(stuff...) pr_warning("udc: " stuff) | 262 | #define WARNING(stuff...) pr_warning("udc: " stuff) |
| 263 | #define INFO(stuff...) pr_info("udc: " stuff) | 263 | #define INFO(stuff...) pr_info("udc: " stuff) |
| 264 | 264 | ||
| 265 | 265 | ||
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 5458f43a8668..3791e6271903 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c | |||
| @@ -116,7 +116,6 @@ static inline int qlen(struct usb_gadget *gadget) | |||
| 116 | #undef DBG | 116 | #undef DBG |
| 117 | #undef VDBG | 117 | #undef VDBG |
| 118 | #undef ERROR | 118 | #undef ERROR |
| 119 | #undef WARN | ||
| 120 | #undef INFO | 119 | #undef INFO |
| 121 | 120 | ||
| 122 | #define xprintk(d, level, fmt, args...) \ | 121 | #define xprintk(d, level, fmt, args...) \ |
| @@ -140,8 +139,6 @@ static inline int qlen(struct usb_gadget *gadget) | |||
| 140 | 139 | ||
| 141 | #define ERROR(dev, fmt, args...) \ | 140 | #define ERROR(dev, fmt, args...) \ |
| 142 | xprintk(dev , KERN_ERR , fmt , ## args) | 141 | xprintk(dev , KERN_ERR , fmt , ## args) |
| 143 | #define WARN(dev, fmt, args...) \ | ||
| 144 | xprintk(dev , KERN_WARNING , fmt , ## args) | ||
| 145 | #define INFO(dev, fmt, args...) \ | 142 | #define INFO(dev, fmt, args...) \ |
| 146 | xprintk(dev , KERN_INFO , fmt , ## args) | 143 | xprintk(dev , KERN_INFO , fmt , ## args) |
| 147 | 144 | ||
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 31178e10cbbe..ce1ca0ba0515 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
| @@ -882,7 +882,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd, | |||
| 882 | for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++) | 882 | for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++) |
| 883 | msleep(3); | 883 | msleep(3); |
| 884 | if (!list_empty(&hep->urb_list)) | 884 | if (!list_empty(&hep->urb_list)) |
| 885 | WARN("ep %p not empty?\n", ep); | 885 | WARNING("ep %p not empty?\n", ep); |
| 886 | 886 | ||
| 887 | kfree(ep); | 887 | kfree(ep); |
| 888 | hep->hcpriv = NULL; | 888 | hep->hcpriv = NULL; |
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index 595b90a99848..aa211bafcff9 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h | |||
| @@ -338,7 +338,7 @@ struct isp116x_ep { | |||
| 338 | #endif | 338 | #endif |
| 339 | 339 | ||
| 340 | #define ERR(stuff...) printk(KERN_ERR "116x: " stuff) | 340 | #define ERR(stuff...) printk(KERN_ERR "116x: " stuff) |
| 341 | #define WARN(stuff...) printk(KERN_WARNING "116x: " stuff) | 341 | #define WARNING(stuff...) printk(KERN_WARNING "116x: " stuff) |
| 342 | #define INFO(stuff...) printk(KERN_INFO "116x: " stuff) | 342 | #define INFO(stuff...) printk(KERN_INFO "116x: " stuff) |
| 343 | 343 | ||
| 344 | /* ------------------------------------------------- */ | 344 | /* ------------------------------------------------- */ |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 340d72da554a..8a74bbb57d08 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
| @@ -1026,7 +1026,7 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | |||
| 1026 | if (!list_empty(&hep->urb_list)) | 1026 | if (!list_empty(&hep->urb_list)) |
| 1027 | msleep(3); | 1027 | msleep(3); |
| 1028 | if (!list_empty(&hep->urb_list)) | 1028 | if (!list_empty(&hep->urb_list)) |
| 1029 | WARN("ep %p not empty?\n", ep); | 1029 | WARNING("ep %p not empty?\n", ep); |
| 1030 | 1030 | ||
| 1031 | kfree(ep); | 1031 | kfree(ep); |
| 1032 | hep->hcpriv = NULL; | 1032 | hep->hcpriv = NULL; |
diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h index 7690d98e42a7..b6b8c1f233dd 100644 --- a/drivers/usb/host/sl811.h +++ b/drivers/usb/host/sl811.h | |||
| @@ -261,6 +261,6 @@ sl811_read_buf(struct sl811 *sl811, int addr, void *buf, size_t count) | |||
| 261 | #endif | 261 | #endif |
| 262 | 262 | ||
| 263 | #define ERR(stuff...) printk(KERN_ERR "sl811: " stuff) | 263 | #define ERR(stuff...) printk(KERN_ERR "sl811: " stuff) |
| 264 | #define WARN(stuff...) printk(KERN_WARNING "sl811: " stuff) | 264 | #define WARNING(stuff...) printk(KERN_WARNING "sl811: " stuff) |
| 265 | #define INFO(stuff...) printk(KERN_INFO "sl811: " stuff) | 265 | #define INFO(stuff...) printk(KERN_INFO "sl811: " stuff) |
| 266 | 266 | ||
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 054dedd28127..b358c4e1cf21 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
| @@ -81,7 +81,7 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test) | |||
| 81 | 81 | ||
| 82 | #define ERROR(tdev, fmt, args...) \ | 82 | #define ERROR(tdev, fmt, args...) \ |
| 83 | dev_err(&(tdev)->intf->dev , fmt , ## args) | 83 | dev_err(&(tdev)->intf->dev , fmt , ## args) |
| 84 | #define WARN(tdev, fmt, args...) \ | 84 | #define WARNING(tdev, fmt, args...) \ |
| 85 | dev_warn(&(tdev)->intf->dev , fmt , ## args) | 85 | dev_warn(&(tdev)->intf->dev , fmt , ## args) |
| 86 | 86 | ||
| 87 | /*-------------------------------------------------------------------------*/ | 87 | /*-------------------------------------------------------------------------*/ |
| @@ -1946,7 +1946,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) | |||
| 1946 | 1946 | ||
| 1947 | status = get_endpoints (dev, intf); | 1947 | status = get_endpoints (dev, intf); |
| 1948 | if (status < 0) { | 1948 | if (status < 0) { |
| 1949 | WARN(dev, "couldn't get endpoints, %d\n", | 1949 | WARNING(dev, "couldn't get endpoints, %d\n", |
| 1950 | status); | 1950 | status); |
| 1951 | return status; | 1951 | return status; |
| 1952 | } | 1952 | } |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 7084e7e146c0..5b78fd0aff0a 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
| @@ -71,13 +71,6 @@ static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) | |||
| 71 | dev->id.device, dev->id.vendor); | 71 | dev->id.device, dev->id.vendor); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static struct bus_type virtio_bus = { | ||
| 75 | .name = "virtio", | ||
| 76 | .match = virtio_dev_match, | ||
| 77 | .dev_attrs = virtio_dev_attrs, | ||
| 78 | .uevent = virtio_uevent, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static void add_status(struct virtio_device *dev, unsigned status) | 74 | static void add_status(struct virtio_device *dev, unsigned status) |
| 82 | { | 75 | { |
| 83 | dev->config->set_status(dev, dev->config->get_status(dev) | status); | 76 | dev->config->set_status(dev, dev->config->get_status(dev) | status); |
| @@ -120,12 +113,16 @@ static int virtio_dev_probe(struct device *_d) | |||
| 120 | set_bit(f, dev->features); | 113 | set_bit(f, dev->features); |
| 121 | } | 114 | } |
| 122 | 115 | ||
| 116 | /* Transport features always preserved to pass to finalize_features. */ | ||
| 117 | for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) | ||
| 118 | if (device_features & (1 << i)) | ||
| 119 | set_bit(i, dev->features); | ||
| 120 | |||
| 123 | err = drv->probe(dev); | 121 | err = drv->probe(dev); |
| 124 | if (err) | 122 | if (err) |
| 125 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 123 | add_status(dev, VIRTIO_CONFIG_S_FAILED); |
| 126 | else { | 124 | else { |
| 127 | /* They should never have set feature bits beyond 32 */ | 125 | dev->config->finalize_features(dev); |
| 128 | dev->config->set_features(dev, dev->features[0]); | ||
| 129 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); | 126 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); |
| 130 | } | 127 | } |
| 131 | return err; | 128 | return err; |
| @@ -147,13 +144,20 @@ static int virtio_dev_remove(struct device *_d) | |||
| 147 | return 0; | 144 | return 0; |
| 148 | } | 145 | } |
| 149 | 146 | ||
| 147 | static struct bus_type virtio_bus = { | ||
| 148 | .name = "virtio", | ||
| 149 | .match = virtio_dev_match, | ||
| 150 | .dev_attrs = virtio_dev_attrs, | ||
| 151 | .uevent = virtio_uevent, | ||
| 152 | .probe = virtio_dev_probe, | ||
| 153 | .remove = virtio_dev_remove, | ||
| 154 | }; | ||
| 155 | |||
| 150 | int register_virtio_driver(struct virtio_driver *driver) | 156 | int register_virtio_driver(struct virtio_driver *driver) |
| 151 | { | 157 | { |
| 152 | /* Catch this early. */ | 158 | /* Catch this early. */ |
| 153 | BUG_ON(driver->feature_table_size && !driver->feature_table); | 159 | BUG_ON(driver->feature_table_size && !driver->feature_table); |
| 154 | driver->driver.bus = &virtio_bus; | 160 | driver->driver.bus = &virtio_bus; |
| 155 | driver->driver.probe = virtio_dev_probe; | ||
| 156 | driver->driver.remove = virtio_dev_remove; | ||
| 157 | return driver_register(&driver->driver); | 161 | return driver_register(&driver->driver); |
| 158 | } | 162 | } |
| 159 | EXPORT_SYMBOL_GPL(register_virtio_driver); | 163 | EXPORT_SYMBOL_GPL(register_virtio_driver); |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index eae7236310e4..c7dc37c7cce9 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -94,12 +94,17 @@ static u32 vp_get_features(struct virtio_device *vdev) | |||
| 94 | return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); | 94 | return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | /* virtio config->set_features() implementation */ | 97 | /* virtio config->finalize_features() implementation */ |
| 98 | static void vp_set_features(struct virtio_device *vdev, u32 features) | 98 | static void vp_finalize_features(struct virtio_device *vdev) |
| 99 | { | 99 | { |
| 100 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 100 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 101 | 101 | ||
| 102 | iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); | 102 | /* Give virtio_ring a chance to accept features. */ |
| 103 | vring_transport_features(vdev); | ||
| 104 | |||
| 105 | /* We only support 32 feature bits. */ | ||
| 106 | BUILD_BUG_ON(ARRAY_SIZE(vdev->features) != 1); | ||
| 107 | iowrite32(vdev->features[0], vp_dev->ioaddr+VIRTIO_PCI_GUEST_FEATURES); | ||
| 103 | } | 108 | } |
| 104 | 109 | ||
| 105 | /* virtio config->get() implementation */ | 110 | /* virtio config->get() implementation */ |
| @@ -297,7 +302,7 @@ static struct virtio_config_ops virtio_pci_config_ops = { | |||
| 297 | .find_vq = vp_find_vq, | 302 | .find_vq = vp_find_vq, |
| 298 | .del_vq = vp_del_vq, | 303 | .del_vq = vp_del_vq, |
| 299 | .get_features = vp_get_features, | 304 | .get_features = vp_get_features, |
| 300 | .set_features = vp_set_features, | 305 | .finalize_features = vp_finalize_features, |
| 301 | }; | 306 | }; |
| 302 | 307 | ||
| 303 | /* the PCI probing function */ | 308 | /* the PCI probing function */ |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 72bf8bc09014..6eb5303fed11 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | */ | 18 | */ |
| 19 | #include <linux/virtio.h> | 19 | #include <linux/virtio.h> |
| 20 | #include <linux/virtio_ring.h> | 20 | #include <linux/virtio_ring.h> |
| 21 | #include <linux/virtio_config.h> | ||
| 21 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 22 | 23 | ||
| 23 | #ifdef DEBUG | 24 | #ifdef DEBUG |
| @@ -87,8 +88,11 @@ static int vring_add_buf(struct virtqueue *_vq, | |||
| 87 | if (vq->num_free < out + in) { | 88 | if (vq->num_free < out + in) { |
| 88 | pr_debug("Can't add buf len %i - avail = %i\n", | 89 | pr_debug("Can't add buf len %i - avail = %i\n", |
| 89 | out + in, vq->num_free); | 90 | out + in, vq->num_free); |
| 90 | /* We notify *even if* VRING_USED_F_NO_NOTIFY is set here. */ | 91 | /* FIXME: for historical reasons, we force a notify here if |
| 91 | vq->notify(&vq->vq); | 92 | * there are outgoing parts to the buffer. Presumably the |
| 93 | * host should service the ring ASAP. */ | ||
| 94 | if (out) | ||
| 95 | vq->notify(&vq->vq); | ||
| 92 | END_USE(vq); | 96 | END_USE(vq); |
| 93 | return -ENOSPC; | 97 | return -ENOSPC; |
| 94 | } | 98 | } |
| @@ -320,4 +324,19 @@ void vring_del_virtqueue(struct virtqueue *vq) | |||
| 320 | } | 324 | } |
| 321 | EXPORT_SYMBOL_GPL(vring_del_virtqueue); | 325 | EXPORT_SYMBOL_GPL(vring_del_virtqueue); |
| 322 | 326 | ||
| 327 | /* Manipulates transport-specific feature bits. */ | ||
| 328 | void vring_transport_features(struct virtio_device *vdev) | ||
| 329 | { | ||
| 330 | unsigned int i; | ||
| 331 | |||
| 332 | for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) { | ||
| 333 | switch (i) { | ||
| 334 | default: | ||
| 335 | /* We don't understand this bit. */ | ||
| 336 | clear_bit(i, vdev->features); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | } | ||
| 340 | EXPORT_SYMBOL_GPL(vring_transport_features); | ||
| 341 | |||
| 323 | MODULE_LICENSE("GPL"); | 342 | MODULE_LICENSE("GPL"); |
diff --git a/fs/Kconfig b/fs/Kconfig index 37db79a2ff95..97e3bdedb1e6 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -902,65 +902,7 @@ endif # BLOCK | |||
| 902 | 902 | ||
| 903 | menu "Pseudo filesystems" | 903 | menu "Pseudo filesystems" |
| 904 | 904 | ||
| 905 | config PROC_FS | 905 | source "fs/proc/Kconfig" |
| 906 | bool "/proc file system support" if EMBEDDED | ||
| 907 | default y | ||
| 908 | help | ||
| 909 | This is a virtual file system providing information about the status | ||
| 910 | of the system. "Virtual" means that it doesn't take up any space on | ||
| 911 | your hard disk: the files are created on the fly by the kernel when | ||
| 912 | you try to access them. Also, you cannot read the files with older | ||
| 913 | version of the program less: you need to use more or cat. | ||
| 914 | |||
| 915 | It's totally cool; for example, "cat /proc/interrupts" gives | ||
| 916 | information about what the different IRQs are used for at the moment | ||
| 917 | (there is a small number of Interrupt ReQuest lines in your computer | ||
| 918 | that are used by the attached devices to gain the CPU's attention -- | ||
| 919 | often a source of trouble if two devices are mistakenly configured | ||
| 920 | to use the same IRQ). The program procinfo to display some | ||
| 921 | information about your system gathered from the /proc file system. | ||
| 922 | |||
| 923 | Before you can use the /proc file system, it has to be mounted, | ||
| 924 | meaning it has to be given a location in the directory hierarchy. | ||
| 925 | That location should be /proc. A command such as "mount -t proc proc | ||
| 926 | /proc" or the equivalent line in /etc/fstab does the job. | ||
| 927 | |||
| 928 | The /proc file system is explained in the file | ||
| 929 | <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage | ||
| 930 | ("man 5 proc"). | ||
| 931 | |||
| 932 | This option will enlarge your kernel by about 67 KB. Several | ||
| 933 | programs depend on this, so everyone should say Y here. | ||
| 934 | |||
| 935 | config PROC_KCORE | ||
| 936 | bool "/proc/kcore support" if !ARM | ||
| 937 | depends on PROC_FS && MMU | ||
| 938 | |||
| 939 | config PROC_VMCORE | ||
| 940 | bool "/proc/vmcore support (EXPERIMENTAL)" | ||
| 941 | depends on PROC_FS && CRASH_DUMP | ||
| 942 | default y | ||
| 943 | help | ||
| 944 | Exports the dump image of crashed kernel in ELF format. | ||
| 945 | |||
| 946 | config PROC_SYSCTL | ||
| 947 | bool "Sysctl support (/proc/sys)" if EMBEDDED | ||
| 948 | depends on PROC_FS | ||
| 949 | select SYSCTL | ||
| 950 | default y | ||
| 951 | ---help--- | ||
| 952 | The sysctl interface provides a means of dynamically changing | ||
| 953 | certain kernel parameters and variables on the fly without requiring | ||
| 954 | a recompile of the kernel or reboot of the system. The primary | ||
| 955 | interface is through /proc/sys. If you say Y here a tree of | ||
| 956 | modifiable sysctl entries will be generated beneath the | ||
| 957 | /proc/sys directory. They are explained in the files | ||
| 958 | in <file:Documentation/sysctl/>. Note that enabling this | ||
| 959 | option will enlarge the kernel by at least 8 KB. | ||
| 960 | |||
| 961 | As it is generally a good thing, you should say Y here unless | ||
| 962 | building a kernel for install/rescue disks or your system is very | ||
| 963 | limited in memory. | ||
| 964 | 906 | ||
| 965 | config SYSFS | 907 | config SYSFS |
| 966 | bool "sysfs file system support" if EMBEDDED | 908 | bool "sysfs file system support" if EMBEDDED |
| @@ -2093,20 +2035,6 @@ config CODA_FS | |||
| 2093 | To compile the coda client support as a module, choose M here: the | 2035 | To compile the coda client support as a module, choose M here: the |
| 2094 | module will be called coda. | 2036 | module will be called coda. |
| 2095 | 2037 | ||
| 2096 | config CODA_FS_OLD_API | ||
| 2097 | bool "Use 96-bit Coda file identifiers" | ||
| 2098 | depends on CODA_FS | ||
| 2099 | help | ||
| 2100 | A new kernel-userspace API had to be introduced for Coda v6.0 | ||
| 2101 | to support larger 128-bit file identifiers as needed by the | ||
| 2102 | new realms implementation. | ||
| 2103 | |||
| 2104 | However this new API is not backward compatible with older | ||
| 2105 | clients. If you really need to run the old Coda userspace | ||
| 2106 | cache manager then say Y. | ||
| 2107 | |||
| 2108 | For most cases you probably want to say N. | ||
| 2109 | |||
| 2110 | config AFS_FS | 2038 | config AFS_FS |
| 2111 | tristate "Andrew File System support (AFS) (EXPERIMENTAL)" | 2039 | tristate "Andrew File System support (AFS) (EXPERIMENTAL)" |
| 2112 | depends on INET && EXPERIMENTAL | 2040 | depends on INET && EXPERIMENTAL |
| @@ -586,7 +586,6 @@ static void use_mm(struct mm_struct *mm) | |||
| 586 | struct task_struct *tsk = current; | 586 | struct task_struct *tsk = current; |
| 587 | 587 | ||
| 588 | task_lock(tsk); | 588 | task_lock(tsk); |
| 589 | tsk->flags |= PF_BORROWED_MM; | ||
| 590 | active_mm = tsk->active_mm; | 589 | active_mm = tsk->active_mm; |
| 591 | atomic_inc(&mm->mm_count); | 590 | atomic_inc(&mm->mm_count); |
| 592 | tsk->mm = mm; | 591 | tsk->mm = mm; |
| @@ -610,7 +609,6 @@ static void unuse_mm(struct mm_struct *mm) | |||
| 610 | struct task_struct *tsk = current; | 609 | struct task_struct *tsk = current; |
| 611 | 610 | ||
| 612 | task_lock(tsk); | 611 | task_lock(tsk); |
| 613 | tsk->flags &= ~PF_BORROWED_MM; | ||
| 614 | tsk->mm = NULL; | 612 | tsk->mm = NULL; |
| 615 | /* active_mm is still 'mm' */ | 613 | /* active_mm is still 'mm' */ |
| 616 | enter_lazy_tlb(mm, tsk); | 614 | enter_lazy_tlb(mm, tsk); |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 639d2d8b5710..3b6ff854d983 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -131,6 +131,15 @@ static int padzero(unsigned long elf_bss) | |||
| 131 | #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; }) | 131 | #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; }) |
| 132 | #endif | 132 | #endif |
| 133 | 133 | ||
| 134 | #ifndef ELF_BASE_PLATFORM | ||
| 135 | /* | ||
| 136 | * AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture. | ||
| 137 | * If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value | ||
| 138 | * will be copied to the user stack in the same manner as AT_PLATFORM. | ||
| 139 | */ | ||
| 140 | #define ELF_BASE_PLATFORM NULL | ||
| 141 | #endif | ||
| 142 | |||
| 134 | static int | 143 | static int |
| 135 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | 144 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, |
| 136 | unsigned long load_addr, unsigned long interp_load_addr) | 145 | unsigned long load_addr, unsigned long interp_load_addr) |
| @@ -142,7 +151,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
| 142 | elf_addr_t __user *envp; | 151 | elf_addr_t __user *envp; |
| 143 | elf_addr_t __user *sp; | 152 | elf_addr_t __user *sp; |
| 144 | elf_addr_t __user *u_platform; | 153 | elf_addr_t __user *u_platform; |
| 154 | elf_addr_t __user *u_base_platform; | ||
| 145 | const char *k_platform = ELF_PLATFORM; | 155 | const char *k_platform = ELF_PLATFORM; |
| 156 | const char *k_base_platform = ELF_BASE_PLATFORM; | ||
| 146 | int items; | 157 | int items; |
| 147 | elf_addr_t *elf_info; | 158 | elf_addr_t *elf_info; |
| 148 | int ei_index = 0; | 159 | int ei_index = 0; |
| @@ -172,6 +183,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
| 172 | return -EFAULT; | 183 | return -EFAULT; |
| 173 | } | 184 | } |
| 174 | 185 | ||
| 186 | /* | ||
| 187 | * If this architecture has a "base" platform capability | ||
| 188 | * string, copy it to userspace. | ||
| 189 | */ | ||
| 190 | u_base_platform = NULL; | ||
| 191 | if (k_base_platform) { | ||
| 192 | size_t len = strlen(k_base_platform) + 1; | ||
| 193 | |||
| 194 | u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); | ||
| 195 | if (__copy_to_user(u_base_platform, k_base_platform, len)) | ||
| 196 | return -EFAULT; | ||
| 197 | } | ||
| 198 | |||
| 175 | /* Create the ELF interpreter info */ | 199 | /* Create the ELF interpreter info */ |
| 176 | elf_info = (elf_addr_t *)current->mm->saved_auxv; | 200 | elf_info = (elf_addr_t *)current->mm->saved_auxv; |
| 177 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ | 201 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ |
| @@ -209,6 +233,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
| 209 | NEW_AUX_ENT(AT_PLATFORM, | 233 | NEW_AUX_ENT(AT_PLATFORM, |
| 210 | (elf_addr_t)(unsigned long)u_platform); | 234 | (elf_addr_t)(unsigned long)u_platform); |
| 211 | } | 235 | } |
| 236 | if (k_base_platform) { | ||
| 237 | NEW_AUX_ENT(AT_BASE_PLATFORM, | ||
| 238 | (elf_addr_t)(unsigned long)u_base_platform); | ||
| 239 | } | ||
| 212 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { | 240 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { |
| 213 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); | 241 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); |
| 214 | } | 242 | } |
| @@ -1478,7 +1506,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1478 | const struct user_regset_view *view = task_user_regset_view(dump_task); | 1506 | const struct user_regset_view *view = task_user_regset_view(dump_task); |
| 1479 | struct elf_thread_core_info *t; | 1507 | struct elf_thread_core_info *t; |
| 1480 | struct elf_prpsinfo *psinfo; | 1508 | struct elf_prpsinfo *psinfo; |
| 1481 | struct task_struct *g, *p; | 1509 | struct core_thread *ct; |
| 1482 | unsigned int i; | 1510 | unsigned int i; |
| 1483 | 1511 | ||
| 1484 | info->size = 0; | 1512 | info->size = 0; |
| @@ -1517,31 +1545,26 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1517 | /* | 1545 | /* |
| 1518 | * Allocate a structure for each thread. | 1546 | * Allocate a structure for each thread. |
| 1519 | */ | 1547 | */ |
| 1520 | rcu_read_lock(); | 1548 | for (ct = &dump_task->mm->core_state->dumper; ct; ct = ct->next) { |
| 1521 | do_each_thread(g, p) | 1549 | t = kzalloc(offsetof(struct elf_thread_core_info, |
| 1522 | if (p->mm == dump_task->mm) { | 1550 | notes[info->thread_notes]), |
| 1523 | t = kzalloc(offsetof(struct elf_thread_core_info, | 1551 | GFP_KERNEL); |
| 1524 | notes[info->thread_notes]), | 1552 | if (unlikely(!t)) |
| 1525 | GFP_ATOMIC); | 1553 | return 0; |
| 1526 | if (unlikely(!t)) { | 1554 | |
| 1527 | rcu_read_unlock(); | 1555 | t->task = ct->task; |
| 1528 | return 0; | 1556 | if (ct->task == dump_task || !info->thread) { |
| 1529 | } | 1557 | t->next = info->thread; |
| 1530 | t->task = p; | 1558 | info->thread = t; |
| 1531 | if (p == dump_task || !info->thread) { | 1559 | } else { |
| 1532 | t->next = info->thread; | 1560 | /* |
| 1533 | info->thread = t; | 1561 | * Make sure to keep the original task at |
| 1534 | } else { | 1562 | * the head of the list. |
| 1535 | /* | 1563 | */ |
| 1536 | * Make sure to keep the original task at | 1564 | t->next = info->thread->next; |
| 1537 | * the head of the list. | 1565 | info->thread->next = t; |
| 1538 | */ | ||
| 1539 | t->next = info->thread->next; | ||
| 1540 | info->thread->next = t; | ||
| 1541 | } | ||
| 1542 | } | 1566 | } |
| 1543 | while_each_thread(g, p); | 1567 | } |
| 1544 | rcu_read_unlock(); | ||
| 1545 | 1568 | ||
| 1546 | /* | 1569 | /* |
| 1547 | * Now fill in each thread's information. | 1570 | * Now fill in each thread's information. |
| @@ -1688,7 +1711,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1688 | { | 1711 | { |
| 1689 | #define NUM_NOTES 6 | 1712 | #define NUM_NOTES 6 |
| 1690 | struct list_head *t; | 1713 | struct list_head *t; |
| 1691 | struct task_struct *g, *p; | ||
| 1692 | 1714 | ||
| 1693 | info->notes = NULL; | 1715 | info->notes = NULL; |
| 1694 | info->prstatus = NULL; | 1716 | info->prstatus = NULL; |
| @@ -1720,20 +1742,19 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1720 | 1742 | ||
| 1721 | info->thread_status_size = 0; | 1743 | info->thread_status_size = 0; |
| 1722 | if (signr) { | 1744 | if (signr) { |
| 1745 | struct core_thread *ct; | ||
| 1723 | struct elf_thread_status *ets; | 1746 | struct elf_thread_status *ets; |
| 1724 | rcu_read_lock(); | 1747 | |
| 1725 | do_each_thread(g, p) | 1748 | for (ct = current->mm->core_state->dumper.next; |
| 1726 | if (current->mm == p->mm && current != p) { | 1749 | ct; ct = ct->next) { |
| 1727 | ets = kzalloc(sizeof(*ets), GFP_ATOMIC); | 1750 | ets = kzalloc(sizeof(*ets), GFP_KERNEL); |
| 1728 | if (!ets) { | 1751 | if (!ets) |
| 1729 | rcu_read_unlock(); | 1752 | return 0; |
| 1730 | return 0; | 1753 | |
| 1731 | } | 1754 | ets->thread = ct->task; |
| 1732 | ets->thread = p; | 1755 | list_add(&ets->list, &info->thread_list); |
| 1733 | list_add(&ets->list, &info->thread_list); | 1756 | } |
| 1734 | } | 1757 | |
| 1735 | while_each_thread(g, p); | ||
| 1736 | rcu_read_unlock(); | ||
| 1737 | list_for_each(t, &info->thread_list) { | 1758 | list_for_each(t, &info->thread_list) { |
| 1738 | int sz; | 1759 | int sz; |
| 1739 | 1760 | ||
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index d051a32e6270..1b59b1edf26d 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
| @@ -1573,7 +1573,6 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
| 1573 | struct memelfnote *notes = NULL; | 1573 | struct memelfnote *notes = NULL; |
| 1574 | struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ | 1574 | struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ |
| 1575 | struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */ | 1575 | struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */ |
| 1576 | struct task_struct *g, *p; | ||
| 1577 | LIST_HEAD(thread_list); | 1576 | LIST_HEAD(thread_list); |
| 1578 | struct list_head *t; | 1577 | struct list_head *t; |
| 1579 | elf_fpregset_t *fpu = NULL; | 1578 | elf_fpregset_t *fpu = NULL; |
| @@ -1622,20 +1621,19 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
| 1622 | #endif | 1621 | #endif |
| 1623 | 1622 | ||
| 1624 | if (signr) { | 1623 | if (signr) { |
| 1624 | struct core_thread *ct; | ||
| 1625 | struct elf_thread_status *tmp; | 1625 | struct elf_thread_status *tmp; |
| 1626 | rcu_read_lock(); | 1626 | |
| 1627 | do_each_thread(g,p) | 1627 | for (ct = current->mm->core_state->dumper.next; |
| 1628 | if (current->mm == p->mm && current != p) { | 1628 | ct; ct = ct->next) { |
| 1629 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); | 1629 | tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); |
| 1630 | if (!tmp) { | 1630 | if (!tmp) |
| 1631 | rcu_read_unlock(); | 1631 | goto cleanup; |
| 1632 | goto cleanup; | 1632 | |
| 1633 | } | 1633 | tmp->thread = ct->task; |
| 1634 | tmp->thread = p; | 1634 | list_add(&tmp->list, &thread_list); |
| 1635 | list_add(&tmp->list, &thread_list); | 1635 | } |
| 1636 | } | 1636 | |
| 1637 | while_each_thread(g,p); | ||
| 1638 | rcu_read_unlock(); | ||
| 1639 | list_for_each(t, &thread_list) { | 1637 | list_for_each(t, &thread_list) { |
| 1640 | struct elf_thread_status *tmp; | 1638 | struct elf_thread_status *tmp; |
| 1641 | int sz; | 1639 | int sz; |
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c index e1c854890f94..bf4a3fd3c8e3 100644 --- a/fs/coda/coda_linux.c +++ b/fs/coda/coda_linux.c | |||
| @@ -28,11 +28,9 @@ int coda_fake_statfs; | |||
| 28 | char * coda_f2s(struct CodaFid *f) | 28 | char * coda_f2s(struct CodaFid *f) |
| 29 | { | 29 | { |
| 30 | static char s[60]; | 30 | static char s[60]; |
| 31 | #ifdef CONFIG_CODA_FS_OLD_API | 31 | |
| 32 | sprintf(s, "(%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2]); | ||
| 33 | #else | ||
| 34 | sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]); | 32 | sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]); |
| 35 | #endif | 33 | |
| 36 | return s; | 34 | return s; |
| 37 | } | 35 | } |
| 38 | 36 | ||
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 40c36f7352a6..0d9b80ec689c 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c | |||
| @@ -378,11 +378,7 @@ MODULE_AUTHOR("Jan Harkes, Peter J. Braam"); | |||
| 378 | MODULE_DESCRIPTION("Coda Distributed File System VFS interface"); | 378 | MODULE_DESCRIPTION("Coda Distributed File System VFS interface"); |
| 379 | MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR); | 379 | MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR); |
| 380 | MODULE_LICENSE("GPL"); | 380 | MODULE_LICENSE("GPL"); |
| 381 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 382 | MODULE_VERSION("5.3.21"); | ||
| 383 | #else | ||
| 384 | MODULE_VERSION("6.6"); | 381 | MODULE_VERSION("6.6"); |
| 385 | #endif | ||
| 386 | 382 | ||
| 387 | static int __init init_coda(void) | 383 | static int __init init_coda(void) |
| 388 | { | 384 | { |
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 359e531094dd..ce432bca95d1 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c | |||
| @@ -52,12 +52,8 @@ static void *alloc_upcall(int opcode, int size) | |||
| 52 | inp->ih.opcode = opcode; | 52 | inp->ih.opcode = opcode; |
| 53 | inp->ih.pid = current->pid; | 53 | inp->ih.pid = current->pid; |
| 54 | inp->ih.pgid = task_pgrp_nr(current); | 54 | inp->ih.pgid = task_pgrp_nr(current); |
| 55 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 56 | memset(&inp->ih.cred, 0, sizeof(struct coda_cred)); | ||
| 57 | inp->ih.cred.cr_fsuid = current->fsuid; | ||
| 58 | #else | ||
| 59 | inp->ih.uid = current->fsuid; | 55 | inp->ih.uid = current->fsuid; |
| 60 | #endif | 56 | |
| 61 | return (void*)inp; | 57 | return (void*)inp; |
| 62 | } | 58 | } |
| 63 | 59 | ||
| @@ -166,20 +162,11 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags, | |||
| 166 | union inputArgs *inp; | 162 | union inputArgs *inp; |
| 167 | union outputArgs *outp; | 163 | union outputArgs *outp; |
| 168 | int insize, outsize, error; | 164 | int insize, outsize, error; |
| 169 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 170 | struct coda_cred cred = { 0, }; | ||
| 171 | cred.cr_fsuid = uid; | ||
| 172 | #endif | ||
| 173 | 165 | ||
| 174 | insize = SIZE(release); | 166 | insize = SIZE(release); |
| 175 | UPARG(CODA_CLOSE); | 167 | UPARG(CODA_CLOSE); |
| 176 | 168 | ||
| 177 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 178 | memcpy(&(inp->ih.cred), &cred, sizeof(cred)); | ||
| 179 | #else | ||
| 180 | inp->ih.uid = uid; | 169 | inp->ih.uid = uid; |
| 181 | #endif | ||
| 182 | |||
| 183 | inp->coda_close.VFid = *fid; | 170 | inp->coda_close.VFid = *fid; |
| 184 | inp->coda_close.flags = flags; | 171 | inp->coda_close.flags = flags; |
| 185 | 172 | ||
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 18e2c548161d..5235c67e7594 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/raid/md.h> | 26 | #include <linux/raid/md.h> |
| 27 | #include <linux/kd.h> | 27 | #include <linux/kd.h> |
| 28 | #include <linux/dirent.h> | ||
| 29 | #include <linux/route.h> | 28 | #include <linux/route.h> |
| 30 | #include <linux/in6.h> | 29 | #include <linux/in6.h> |
| 31 | #include <linux/ipv6_route.h> | 30 | #include <linux/ipv6_route.h> |
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index 78878c5781ca..eba87ff3177b 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c | |||
| @@ -116,7 +116,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, | |||
| 116 | if (xop->callback == NULL) | 116 | if (xop->callback == NULL) |
| 117 | wait_event(recv_wq, (op->done != 0)); | 117 | wait_event(recv_wq, (op->done != 0)); |
| 118 | else { | 118 | else { |
| 119 | rv = -EINPROGRESS; | 119 | rv = FILE_LOCK_DEFERRED; |
| 120 | goto out; | 120 | goto out; |
| 121 | } | 121 | } |
| 122 | 122 | ||
diff --git a/fs/dquot.c b/fs/dquot.c index 5ac77da19959..1346eebe74ce 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
| @@ -562,6 +562,8 @@ static struct shrinker dqcache_shrinker = { | |||
| 562 | */ | 562 | */ |
| 563 | static void dqput(struct dquot *dquot) | 563 | static void dqput(struct dquot *dquot) |
| 564 | { | 564 | { |
| 565 | int ret; | ||
| 566 | |||
| 565 | if (!dquot) | 567 | if (!dquot) |
| 566 | return; | 568 | return; |
| 567 | #ifdef __DQUOT_PARANOIA | 569 | #ifdef __DQUOT_PARANOIA |
| @@ -594,7 +596,19 @@ we_slept: | |||
| 594 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) { | 596 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) { |
| 595 | spin_unlock(&dq_list_lock); | 597 | spin_unlock(&dq_list_lock); |
| 596 | /* Commit dquot before releasing */ | 598 | /* Commit dquot before releasing */ |
| 597 | dquot->dq_sb->dq_op->write_dquot(dquot); | 599 | ret = dquot->dq_sb->dq_op->write_dquot(dquot); |
| 600 | if (ret < 0) { | ||
| 601 | printk(KERN_ERR "VFS: cannot write quota structure on " | ||
| 602 | "device %s (error %d). Quota may get out of " | ||
| 603 | "sync!\n", dquot->dq_sb->s_id, ret); | ||
| 604 | /* | ||
| 605 | * We clear dirty bit anyway, so that we avoid | ||
| 606 | * infinite loop here | ||
| 607 | */ | ||
| 608 | spin_lock(&dq_list_lock); | ||
| 609 | clear_dquot_dirty(dquot); | ||
| 610 | spin_unlock(&dq_list_lock); | ||
| 611 | } | ||
| 598 | goto we_slept; | 612 | goto we_slept; |
| 599 | } | 613 | } |
| 600 | /* Clear flag in case dquot was inactive (something bad happened) */ | 614 | /* Clear flag in case dquot was inactive (something bad happened) */ |
| @@ -875,7 +889,10 @@ static void print_warning(struct dquot *dquot, const int warntype) | |||
| 875 | char *msg = NULL; | 889 | char *msg = NULL; |
| 876 | struct tty_struct *tty; | 890 | struct tty_struct *tty; |
| 877 | 891 | ||
| 878 | if (!need_print_warning(dquot)) | 892 | if (warntype == QUOTA_NL_IHARDBELOW || |
| 893 | warntype == QUOTA_NL_ISOFTBELOW || | ||
| 894 | warntype == QUOTA_NL_BHARDBELOW || | ||
| 895 | warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(dquot)) | ||
| 879 | return; | 896 | return; |
| 880 | 897 | ||
| 881 | mutex_lock(&tty_mutex); | 898 | mutex_lock(&tty_mutex); |
| @@ -1083,6 +1100,35 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war | |||
| 1083 | return QUOTA_OK; | 1100 | return QUOTA_OK; |
| 1084 | } | 1101 | } |
| 1085 | 1102 | ||
| 1103 | static int info_idq_free(struct dquot *dquot, ulong inodes) | ||
| 1104 | { | ||
| 1105 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || | ||
| 1106 | dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit) | ||
| 1107 | return QUOTA_NL_NOWARN; | ||
| 1108 | |||
| 1109 | if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit) | ||
| 1110 | return QUOTA_NL_ISOFTBELOW; | ||
| 1111 | if (dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_ihardlimit && | ||
| 1112 | dquot->dq_dqb.dqb_curinodes - inodes < dquot->dq_dqb.dqb_ihardlimit) | ||
| 1113 | return QUOTA_NL_IHARDBELOW; | ||
| 1114 | return QUOTA_NL_NOWARN; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | static int info_bdq_free(struct dquot *dquot, qsize_t space) | ||
| 1118 | { | ||
| 1119 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || | ||
| 1120 | toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit) | ||
| 1121 | return QUOTA_NL_NOWARN; | ||
| 1122 | |||
| 1123 | if (toqb(dquot->dq_dqb.dqb_curspace - space) <= | ||
| 1124 | dquot->dq_dqb.dqb_bsoftlimit) | ||
| 1125 | return QUOTA_NL_BSOFTBELOW; | ||
| 1126 | if (toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bhardlimit && | ||
| 1127 | toqb(dquot->dq_dqb.dqb_curspace - space) < | ||
| 1128 | dquot->dq_dqb.dqb_bhardlimit) | ||
| 1129 | return QUOTA_NL_BHARDBELOW; | ||
| 1130 | return QUOTA_NL_NOWARN; | ||
| 1131 | } | ||
| 1086 | /* | 1132 | /* |
| 1087 | * Initialize quota pointers in inode | 1133 | * Initialize quota pointers in inode |
| 1088 | * Transaction must be started at entry | 1134 | * Transaction must be started at entry |
| @@ -1139,6 +1185,28 @@ int dquot_drop(struct inode *inode) | |||
| 1139 | return 0; | 1185 | return 0; |
| 1140 | } | 1186 | } |
| 1141 | 1187 | ||
| 1188 | /* Wrapper to remove references to quota structures from inode */ | ||
| 1189 | void vfs_dq_drop(struct inode *inode) | ||
| 1190 | { | ||
| 1191 | /* Here we can get arbitrary inode from clear_inode() so we have | ||
| 1192 | * to be careful. OTOH we don't need locking as quota operations | ||
| 1193 | * are allowed to change only at mount time */ | ||
| 1194 | if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op | ||
| 1195 | && inode->i_sb->dq_op->drop) { | ||
| 1196 | int cnt; | ||
| 1197 | /* Test before calling to rule out calls from proc and such | ||
| 1198 | * where we are not allowed to block. Note that this is | ||
| 1199 | * actually reliable test even without the lock - the caller | ||
| 1200 | * must assure that nobody can come after the DQUOT_DROP and | ||
| 1201 | * add quota pointers back anyway */ | ||
| 1202 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | ||
| 1203 | if (inode->i_dquot[cnt] != NODQUOT) | ||
| 1204 | break; | ||
| 1205 | if (cnt < MAXQUOTAS) | ||
| 1206 | inode->i_sb->dq_op->drop(inode); | ||
| 1207 | } | ||
| 1208 | } | ||
| 1209 | |||
| 1142 | /* | 1210 | /* |
| 1143 | * Following four functions update i_blocks+i_bytes fields and | 1211 | * Following four functions update i_blocks+i_bytes fields and |
| 1144 | * quota information (together with appropriate checks) | 1212 | * quota information (together with appropriate checks) |
| @@ -1248,6 +1316,7 @@ warn_put_all: | |||
| 1248 | int dquot_free_space(struct inode *inode, qsize_t number) | 1316 | int dquot_free_space(struct inode *inode, qsize_t number) |
| 1249 | { | 1317 | { |
| 1250 | unsigned int cnt; | 1318 | unsigned int cnt; |
| 1319 | char warntype[MAXQUOTAS]; | ||
| 1251 | 1320 | ||
| 1252 | /* First test before acquiring mutex - solves deadlocks when we | 1321 | /* First test before acquiring mutex - solves deadlocks when we |
| 1253 | * re-enter the quota code and are already holding the mutex */ | 1322 | * re-enter the quota code and are already holding the mutex */ |
| @@ -1256,6 +1325,7 @@ out_sub: | |||
| 1256 | inode_sub_bytes(inode, number); | 1325 | inode_sub_bytes(inode, number); |
| 1257 | return QUOTA_OK; | 1326 | return QUOTA_OK; |
| 1258 | } | 1327 | } |
| 1328 | |||
| 1259 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1329 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
| 1260 | /* Now recheck reliably when holding dqptr_sem */ | 1330 | /* Now recheck reliably when holding dqptr_sem */ |
| 1261 | if (IS_NOQUOTA(inode)) { | 1331 | if (IS_NOQUOTA(inode)) { |
| @@ -1266,6 +1336,7 @@ out_sub: | |||
| 1266 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1336 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1267 | if (inode->i_dquot[cnt] == NODQUOT) | 1337 | if (inode->i_dquot[cnt] == NODQUOT) |
| 1268 | continue; | 1338 | continue; |
| 1339 | warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number); | ||
| 1269 | dquot_decr_space(inode->i_dquot[cnt], number); | 1340 | dquot_decr_space(inode->i_dquot[cnt], number); |
| 1270 | } | 1341 | } |
| 1271 | inode_sub_bytes(inode, number); | 1342 | inode_sub_bytes(inode, number); |
| @@ -1274,6 +1345,7 @@ out_sub: | |||
| 1274 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1345 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
| 1275 | if (inode->i_dquot[cnt]) | 1346 | if (inode->i_dquot[cnt]) |
| 1276 | mark_dquot_dirty(inode->i_dquot[cnt]); | 1347 | mark_dquot_dirty(inode->i_dquot[cnt]); |
| 1348 | flush_warnings(inode->i_dquot, warntype); | ||
| 1277 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1349 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
| 1278 | return QUOTA_OK; | 1350 | return QUOTA_OK; |
| 1279 | } | 1351 | } |
| @@ -1284,11 +1356,13 @@ out_sub: | |||
| 1284 | int dquot_free_inode(const struct inode *inode, unsigned long number) | 1356 | int dquot_free_inode(const struct inode *inode, unsigned long number) |
| 1285 | { | 1357 | { |
| 1286 | unsigned int cnt; | 1358 | unsigned int cnt; |
| 1359 | char warntype[MAXQUOTAS]; | ||
| 1287 | 1360 | ||
| 1288 | /* First test before acquiring mutex - solves deadlocks when we | 1361 | /* First test before acquiring mutex - solves deadlocks when we |
| 1289 | * re-enter the quota code and are already holding the mutex */ | 1362 | * re-enter the quota code and are already holding the mutex */ |
| 1290 | if (IS_NOQUOTA(inode)) | 1363 | if (IS_NOQUOTA(inode)) |
| 1291 | return QUOTA_OK; | 1364 | return QUOTA_OK; |
| 1365 | |||
| 1292 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1366 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
| 1293 | /* Now recheck reliably when holding dqptr_sem */ | 1367 | /* Now recheck reliably when holding dqptr_sem */ |
| 1294 | if (IS_NOQUOTA(inode)) { | 1368 | if (IS_NOQUOTA(inode)) { |
| @@ -1299,6 +1373,7 @@ int dquot_free_inode(const struct inode *inode, unsigned long number) | |||
| 1299 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1373 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1300 | if (inode->i_dquot[cnt] == NODQUOT) | 1374 | if (inode->i_dquot[cnt] == NODQUOT) |
| 1301 | continue; | 1375 | continue; |
| 1376 | warntype[cnt] = info_idq_free(inode->i_dquot[cnt], number); | ||
| 1302 | dquot_decr_inodes(inode->i_dquot[cnt], number); | 1377 | dquot_decr_inodes(inode->i_dquot[cnt], number); |
| 1303 | } | 1378 | } |
| 1304 | spin_unlock(&dq_data_lock); | 1379 | spin_unlock(&dq_data_lock); |
| @@ -1306,6 +1381,7 @@ int dquot_free_inode(const struct inode *inode, unsigned long number) | |||
| 1306 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1381 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
| 1307 | if (inode->i_dquot[cnt]) | 1382 | if (inode->i_dquot[cnt]) |
| 1308 | mark_dquot_dirty(inode->i_dquot[cnt]); | 1383 | mark_dquot_dirty(inode->i_dquot[cnt]); |
| 1384 | flush_warnings(inode->i_dquot, warntype); | ||
| 1309 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1385 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
| 1310 | return QUOTA_OK; | 1386 | return QUOTA_OK; |
| 1311 | } | 1387 | } |
| @@ -1323,7 +1399,8 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
| 1323 | struct dquot *transfer_to[MAXQUOTAS]; | 1399 | struct dquot *transfer_to[MAXQUOTAS]; |
| 1324 | int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid, | 1400 | int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid, |
| 1325 | chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid; | 1401 | chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid; |
| 1326 | char warntype[MAXQUOTAS]; | 1402 | char warntype_to[MAXQUOTAS]; |
| 1403 | char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS]; | ||
| 1327 | 1404 | ||
| 1328 | /* First test before acquiring mutex - solves deadlocks when we | 1405 | /* First test before acquiring mutex - solves deadlocks when we |
| 1329 | * re-enter the quota code and are already holding the mutex */ | 1406 | * re-enter the quota code and are already holding the mutex */ |
| @@ -1332,7 +1409,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
| 1332 | /* Clear the arrays */ | 1409 | /* Clear the arrays */ |
| 1333 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1410 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1334 | transfer_to[cnt] = transfer_from[cnt] = NODQUOT; | 1411 | transfer_to[cnt] = transfer_from[cnt] = NODQUOT; |
| 1335 | warntype[cnt] = QUOTA_NL_NOWARN; | 1412 | warntype_to[cnt] = QUOTA_NL_NOWARN; |
| 1336 | } | 1413 | } |
| 1337 | down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1414 | down_write(&sb_dqopt(inode->i_sb)->dqptr_sem); |
| 1338 | /* Now recheck reliably when holding dqptr_sem */ | 1415 | /* Now recheck reliably when holding dqptr_sem */ |
| @@ -1364,8 +1441,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
| 1364 | if (transfer_to[cnt] == NODQUOT) | 1441 | if (transfer_to[cnt] == NODQUOT) |
| 1365 | continue; | 1442 | continue; |
| 1366 | transfer_from[cnt] = inode->i_dquot[cnt]; | 1443 | transfer_from[cnt] = inode->i_dquot[cnt]; |
| 1367 | if (check_idq(transfer_to[cnt], 1, warntype+cnt) == NO_QUOTA || | 1444 | if (check_idq(transfer_to[cnt], 1, warntype_to + cnt) == |
| 1368 | check_bdq(transfer_to[cnt], space, 0, warntype+cnt) == NO_QUOTA) | 1445 | NO_QUOTA || check_bdq(transfer_to[cnt], space, 0, |
| 1446 | warntype_to + cnt) == NO_QUOTA) | ||
| 1369 | goto warn_put_all; | 1447 | goto warn_put_all; |
| 1370 | } | 1448 | } |
| 1371 | 1449 | ||
| @@ -1381,6 +1459,10 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
| 1381 | 1459 | ||
| 1382 | /* Due to IO error we might not have transfer_from[] structure */ | 1460 | /* Due to IO error we might not have transfer_from[] structure */ |
| 1383 | if (transfer_from[cnt]) { | 1461 | if (transfer_from[cnt]) { |
| 1462 | warntype_from_inodes[cnt] = | ||
| 1463 | info_idq_free(transfer_from[cnt], 1); | ||
| 1464 | warntype_from_space[cnt] = | ||
| 1465 | info_bdq_free(transfer_from[cnt], space); | ||
| 1384 | dquot_decr_inodes(transfer_from[cnt], 1); | 1466 | dquot_decr_inodes(transfer_from[cnt], 1); |
| 1385 | dquot_decr_space(transfer_from[cnt], space); | 1467 | dquot_decr_space(transfer_from[cnt], space); |
| 1386 | } | 1468 | } |
| @@ -1400,7 +1482,9 @@ warn_put_all: | |||
| 1400 | if (transfer_to[cnt]) | 1482 | if (transfer_to[cnt]) |
| 1401 | mark_dquot_dirty(transfer_to[cnt]); | 1483 | mark_dquot_dirty(transfer_to[cnt]); |
| 1402 | } | 1484 | } |
| 1403 | flush_warnings(transfer_to, warntype); | 1485 | flush_warnings(transfer_to, warntype_to); |
| 1486 | flush_warnings(transfer_from, warntype_from_inodes); | ||
| 1487 | flush_warnings(transfer_from, warntype_from_space); | ||
| 1404 | 1488 | ||
| 1405 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1489 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1406 | if (ret == QUOTA_OK && transfer_from[cnt] != NODQUOT) | 1490 | if (ret == QUOTA_OK && transfer_from[cnt] != NODQUOT) |
| @@ -1412,6 +1496,18 @@ warn_put_all: | |||
| 1412 | return ret; | 1496 | return ret; |
| 1413 | } | 1497 | } |
| 1414 | 1498 | ||
| 1499 | /* Wrapper for transferring ownership of an inode */ | ||
| 1500 | int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) | ||
| 1501 | { | ||
| 1502 | if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) { | ||
| 1503 | vfs_dq_init(inode); | ||
| 1504 | if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA) | ||
| 1505 | return 1; | ||
| 1506 | } | ||
| 1507 | return 0; | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | |||
| 1415 | /* | 1511 | /* |
| 1416 | * Write info of quota file to disk | 1512 | * Write info of quota file to disk |
| 1417 | */ | 1513 | */ |
| @@ -1752,6 +1848,22 @@ out: | |||
| 1752 | return error; | 1848 | return error; |
| 1753 | } | 1849 | } |
| 1754 | 1850 | ||
| 1851 | /* Wrapper to turn on quotas when remounting rw */ | ||
| 1852 | int vfs_dq_quota_on_remount(struct super_block *sb) | ||
| 1853 | { | ||
| 1854 | int cnt; | ||
| 1855 | int ret = 0, err; | ||
| 1856 | |||
| 1857 | if (!sb->s_qcop || !sb->s_qcop->quota_on) | ||
| 1858 | return -ENOSYS; | ||
| 1859 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
| 1860 | err = sb->s_qcop->quota_on(sb, cnt, 0, NULL, 1); | ||
| 1861 | if (err < 0 && !ret) | ||
| 1862 | ret = err; | ||
| 1863 | } | ||
| 1864 | return ret; | ||
| 1865 | } | ||
| 1866 | |||
| 1755 | /* Generic routine for getting common part of quota structure */ | 1867 | /* Generic routine for getting common part of quota structure */ |
| 1756 | static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di) | 1868 | static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di) |
| 1757 | { | 1869 | { |
| @@ -2087,8 +2199,11 @@ EXPORT_SYMBOL(dquot_release); | |||
| 2087 | EXPORT_SYMBOL(dquot_mark_dquot_dirty); | 2199 | EXPORT_SYMBOL(dquot_mark_dquot_dirty); |
| 2088 | EXPORT_SYMBOL(dquot_initialize); | 2200 | EXPORT_SYMBOL(dquot_initialize); |
| 2089 | EXPORT_SYMBOL(dquot_drop); | 2201 | EXPORT_SYMBOL(dquot_drop); |
| 2202 | EXPORT_SYMBOL(vfs_dq_drop); | ||
| 2090 | EXPORT_SYMBOL(dquot_alloc_space); | 2203 | EXPORT_SYMBOL(dquot_alloc_space); |
| 2091 | EXPORT_SYMBOL(dquot_alloc_inode); | 2204 | EXPORT_SYMBOL(dquot_alloc_inode); |
| 2092 | EXPORT_SYMBOL(dquot_free_space); | 2205 | EXPORT_SYMBOL(dquot_free_space); |
| 2093 | EXPORT_SYMBOL(dquot_free_inode); | 2206 | EXPORT_SYMBOL(dquot_free_inode); |
| 2094 | EXPORT_SYMBOL(dquot_transfer); | 2207 | EXPORT_SYMBOL(dquot_transfer); |
| 2208 | EXPORT_SYMBOL(vfs_dq_transfer); | ||
| 2209 | EXPORT_SYMBOL(vfs_dq_quota_on_remount); | ||
| @@ -25,19 +25,18 @@ | |||
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/file.h> | 26 | #include <linux/file.h> |
| 27 | #include <linux/fdtable.h> | 27 | #include <linux/fdtable.h> |
| 28 | #include <linux/mman.h> | 28 | #include <linux/mm.h> |
| 29 | #include <linux/stat.h> | 29 | #include <linux/stat.h> |
| 30 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
| 31 | #include <linux/smp_lock.h> | 31 | #include <linux/smp_lock.h> |
| 32 | #include <linux/swap.h> | ||
| 32 | #include <linux/string.h> | 33 | #include <linux/string.h> |
| 33 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 34 | #include <linux/pagemap.h> | ||
| 35 | #include <linux/highmem.h> | 35 | #include <linux/highmem.h> |
| 36 | #include <linux/spinlock.h> | 36 | #include <linux/spinlock.h> |
| 37 | #include <linux/key.h> | 37 | #include <linux/key.h> |
| 38 | #include <linux/personality.h> | 38 | #include <linux/personality.h> |
| 39 | #include <linux/binfmts.h> | 39 | #include <linux/binfmts.h> |
| 40 | #include <linux/swap.h> | ||
| 41 | #include <linux/utsname.h> | 40 | #include <linux/utsname.h> |
| 42 | #include <linux/pid_namespace.h> | 41 | #include <linux/pid_namespace.h> |
| 43 | #include <linux/module.h> | 42 | #include <linux/module.h> |
| @@ -47,7 +46,6 @@ | |||
| 47 | #include <linux/mount.h> | 46 | #include <linux/mount.h> |
| 48 | #include <linux/security.h> | 47 | #include <linux/security.h> |
| 49 | #include <linux/syscalls.h> | 48 | #include <linux/syscalls.h> |
| 50 | #include <linux/rmap.h> | ||
| 51 | #include <linux/tsacct_kern.h> | 49 | #include <linux/tsacct_kern.h> |
| 52 | #include <linux/cn_proc.h> | 50 | #include <linux/cn_proc.h> |
| 53 | #include <linux/audit.h> | 51 | #include <linux/audit.h> |
| @@ -724,12 +722,10 @@ static int exec_mmap(struct mm_struct *mm) | |||
| 724 | * Make sure that if there is a core dump in progress | 722 | * Make sure that if there is a core dump in progress |
| 725 | * for the old mm, we get out and die instead of going | 723 | * for the old mm, we get out and die instead of going |
| 726 | * through with the exec. We must hold mmap_sem around | 724 | * through with the exec. We must hold mmap_sem around |
| 727 | * checking core_waiters and changing tsk->mm. The | 725 | * checking core_state and changing tsk->mm. |
| 728 | * core-inducing thread will increment core_waiters for | ||
| 729 | * each thread whose ->mm == old_mm. | ||
| 730 | */ | 726 | */ |
| 731 | down_read(&old_mm->mmap_sem); | 727 | down_read(&old_mm->mmap_sem); |
| 732 | if (unlikely(old_mm->core_waiters)) { | 728 | if (unlikely(old_mm->core_state)) { |
| 733 | up_read(&old_mm->mmap_sem); | 729 | up_read(&old_mm->mmap_sem); |
| 734 | return -EINTR; | 730 | return -EINTR; |
| 735 | } | 731 | } |
| @@ -1328,6 +1324,7 @@ int do_execve(char * filename, | |||
| 1328 | if (retval < 0) | 1324 | if (retval < 0) |
| 1329 | goto out; | 1325 | goto out; |
| 1330 | 1326 | ||
| 1327 | current->flags &= ~PF_KTHREAD; | ||
| 1331 | retval = search_binary_handler(bprm,regs); | 1328 | retval = search_binary_handler(bprm,regs); |
| 1332 | if (retval >= 0) { | 1329 | if (retval >= 0) { |
| 1333 | /* execve success */ | 1330 | /* execve success */ |
| @@ -1382,17 +1379,14 @@ EXPORT_SYMBOL(set_binfmt); | |||
| 1382 | * name into corename, which must have space for at least | 1379 | * name into corename, which must have space for at least |
| 1383 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. | 1380 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. |
| 1384 | */ | 1381 | */ |
| 1385 | static int format_corename(char *corename, const char *pattern, long signr) | 1382 | static int format_corename(char *corename, int nr_threads, long signr) |
| 1386 | { | 1383 | { |
| 1387 | const char *pat_ptr = pattern; | 1384 | const char *pat_ptr = core_pattern; |
| 1385 | int ispipe = (*pat_ptr == '|'); | ||
| 1388 | char *out_ptr = corename; | 1386 | char *out_ptr = corename; |
| 1389 | char *const out_end = corename + CORENAME_MAX_SIZE; | 1387 | char *const out_end = corename + CORENAME_MAX_SIZE; |
| 1390 | int rc; | 1388 | int rc; |
| 1391 | int pid_in_pattern = 0; | 1389 | int pid_in_pattern = 0; |
| 1392 | int ispipe = 0; | ||
| 1393 | |||
| 1394 | if (*pattern == '|') | ||
| 1395 | ispipe = 1; | ||
| 1396 | 1390 | ||
| 1397 | /* Repeat as long as we have more pattern to process and more output | 1391 | /* Repeat as long as we have more pattern to process and more output |
| 1398 | space */ | 1392 | space */ |
| @@ -1493,7 +1487,7 @@ static int format_corename(char *corename, const char *pattern, long signr) | |||
| 1493 | * and core_uses_pid is set, then .%pid will be appended to | 1487 | * and core_uses_pid is set, then .%pid will be appended to |
| 1494 | * the filename. Do not do this for piped commands. */ | 1488 | * the filename. Do not do this for piped commands. */ |
| 1495 | if (!ispipe && !pid_in_pattern | 1489 | if (!ispipe && !pid_in_pattern |
| 1496 | && (core_uses_pid || atomic_read(¤t->mm->mm_users) != 1)) { | 1490 | && (core_uses_pid || nr_threads)) { |
| 1497 | rc = snprintf(out_ptr, out_end - out_ptr, | 1491 | rc = snprintf(out_ptr, out_end - out_ptr, |
| 1498 | ".%d", task_tgid_vnr(current)); | 1492 | ".%d", task_tgid_vnr(current)); |
| 1499 | if (rc > out_end - out_ptr) | 1493 | if (rc > out_end - out_ptr) |
| @@ -1505,9 +1499,10 @@ out: | |||
| 1505 | return ispipe; | 1499 | return ispipe; |
| 1506 | } | 1500 | } |
| 1507 | 1501 | ||
| 1508 | static void zap_process(struct task_struct *start) | 1502 | static int zap_process(struct task_struct *start) |
| 1509 | { | 1503 | { |
| 1510 | struct task_struct *t; | 1504 | struct task_struct *t; |
| 1505 | int nr = 0; | ||
| 1511 | 1506 | ||
| 1512 | start->signal->flags = SIGNAL_GROUP_EXIT; | 1507 | start->signal->flags = SIGNAL_GROUP_EXIT; |
| 1513 | start->signal->group_stop_count = 0; | 1508 | start->signal->group_stop_count = 0; |
| @@ -1515,72 +1510,99 @@ static void zap_process(struct task_struct *start) | |||
| 1515 | t = start; | 1510 | t = start; |
| 1516 | do { | 1511 | do { |
| 1517 | if (t != current && t->mm) { | 1512 | if (t != current && t->mm) { |
| 1518 | t->mm->core_waiters++; | ||
| 1519 | sigaddset(&t->pending.signal, SIGKILL); | 1513 | sigaddset(&t->pending.signal, SIGKILL); |
| 1520 | signal_wake_up(t, 1); | 1514 | signal_wake_up(t, 1); |
| 1515 | nr++; | ||
| 1521 | } | 1516 | } |
| 1522 | } while ((t = next_thread(t)) != start); | 1517 | } while_each_thread(start, t); |
| 1518 | |||
| 1519 | return nr; | ||
| 1523 | } | 1520 | } |
| 1524 | 1521 | ||
| 1525 | static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, | 1522 | static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, |
| 1526 | int exit_code) | 1523 | struct core_state *core_state, int exit_code) |
| 1527 | { | 1524 | { |
| 1528 | struct task_struct *g, *p; | 1525 | struct task_struct *g, *p; |
| 1529 | unsigned long flags; | 1526 | unsigned long flags; |
| 1530 | int err = -EAGAIN; | 1527 | int nr = -EAGAIN; |
| 1531 | 1528 | ||
| 1532 | spin_lock_irq(&tsk->sighand->siglock); | 1529 | spin_lock_irq(&tsk->sighand->siglock); |
| 1533 | if (!signal_group_exit(tsk->signal)) { | 1530 | if (!signal_group_exit(tsk->signal)) { |
| 1531 | mm->core_state = core_state; | ||
| 1534 | tsk->signal->group_exit_code = exit_code; | 1532 | tsk->signal->group_exit_code = exit_code; |
| 1535 | zap_process(tsk); | 1533 | nr = zap_process(tsk); |
| 1536 | err = 0; | ||
| 1537 | } | 1534 | } |
| 1538 | spin_unlock_irq(&tsk->sighand->siglock); | 1535 | spin_unlock_irq(&tsk->sighand->siglock); |
| 1539 | if (err) | 1536 | if (unlikely(nr < 0)) |
| 1540 | return err; | 1537 | return nr; |
| 1541 | 1538 | ||
| 1542 | if (atomic_read(&mm->mm_users) == mm->core_waiters + 1) | 1539 | if (atomic_read(&mm->mm_users) == nr + 1) |
| 1543 | goto done; | 1540 | goto done; |
| 1544 | 1541 | /* | |
| 1542 | * We should find and kill all tasks which use this mm, and we should | ||
| 1543 | * count them correctly into ->nr_threads. We don't take tasklist | ||
| 1544 | * lock, but this is safe wrt: | ||
| 1545 | * | ||
| 1546 | * fork: | ||
| 1547 | * None of sub-threads can fork after zap_process(leader). All | ||
| 1548 | * processes which were created before this point should be | ||
| 1549 | * visible to zap_threads() because copy_process() adds the new | ||
| 1550 | * process to the tail of init_task.tasks list, and lock/unlock | ||
| 1551 | * of ->siglock provides a memory barrier. | ||
| 1552 | * | ||
| 1553 | * do_exit: | ||
| 1554 | * The caller holds mm->mmap_sem. This means that the task which | ||
| 1555 | * uses this mm can't pass exit_mm(), so it can't exit or clear | ||
| 1556 | * its ->mm. | ||
| 1557 | * | ||
| 1558 | * de_thread: | ||
| 1559 | * It does list_replace_rcu(&leader->tasks, ¤t->tasks), | ||
| 1560 | * we must see either old or new leader, this does not matter. | ||
| 1561 | * However, it can change p->sighand, so lock_task_sighand(p) | ||
| 1562 | * must be used. Since p->mm != NULL and we hold ->mmap_sem | ||
| 1563 | * it can't fail. | ||
| 1564 | * | ||
| 1565 | * Note also that "g" can be the old leader with ->mm == NULL | ||
| 1566 | * and already unhashed and thus removed from ->thread_group. | ||
| 1567 | * This is OK, __unhash_process()->list_del_rcu() does not | ||
| 1568 | * clear the ->next pointer, we will find the new leader via | ||
| 1569 | * next_thread(). | ||
| 1570 | */ | ||
| 1545 | rcu_read_lock(); | 1571 | rcu_read_lock(); |
| 1546 | for_each_process(g) { | 1572 | for_each_process(g) { |
| 1547 | if (g == tsk->group_leader) | 1573 | if (g == tsk->group_leader) |
| 1548 | continue; | 1574 | continue; |
| 1549 | 1575 | if (g->flags & PF_KTHREAD) | |
| 1576 | continue; | ||
| 1550 | p = g; | 1577 | p = g; |
| 1551 | do { | 1578 | do { |
| 1552 | if (p->mm) { | 1579 | if (p->mm) { |
| 1553 | if (p->mm == mm) { | 1580 | if (unlikely(p->mm == mm)) { |
| 1554 | /* | ||
| 1555 | * p->sighand can't disappear, but | ||
| 1556 | * may be changed by de_thread() | ||
| 1557 | */ | ||
| 1558 | lock_task_sighand(p, &flags); | 1581 | lock_task_sighand(p, &flags); |
| 1559 | zap_process(p); | 1582 | nr += zap_process(p); |
| 1560 | unlock_task_sighand(p, &flags); | 1583 | unlock_task_sighand(p, &flags); |
| 1561 | } | 1584 | } |
| 1562 | break; | 1585 | break; |
| 1563 | } | 1586 | } |
| 1564 | } while ((p = next_thread(p)) != g); | 1587 | } while_each_thread(g, p); |
| 1565 | } | 1588 | } |
| 1566 | rcu_read_unlock(); | 1589 | rcu_read_unlock(); |
| 1567 | done: | 1590 | done: |
| 1568 | return mm->core_waiters; | 1591 | atomic_set(&core_state->nr_threads, nr); |
| 1592 | return nr; | ||
| 1569 | } | 1593 | } |
| 1570 | 1594 | ||
| 1571 | static int coredump_wait(int exit_code) | 1595 | static int coredump_wait(int exit_code, struct core_state *core_state) |
| 1572 | { | 1596 | { |
| 1573 | struct task_struct *tsk = current; | 1597 | struct task_struct *tsk = current; |
| 1574 | struct mm_struct *mm = tsk->mm; | 1598 | struct mm_struct *mm = tsk->mm; |
| 1575 | struct completion startup_done; | ||
| 1576 | struct completion *vfork_done; | 1599 | struct completion *vfork_done; |
| 1577 | int core_waiters; | 1600 | int core_waiters; |
| 1578 | 1601 | ||
| 1579 | init_completion(&mm->core_done); | 1602 | init_completion(&core_state->startup); |
| 1580 | init_completion(&startup_done); | 1603 | core_state->dumper.task = tsk; |
| 1581 | mm->core_startup_done = &startup_done; | 1604 | core_state->dumper.next = NULL; |
| 1582 | 1605 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); | |
| 1583 | core_waiters = zap_threads(tsk, mm, exit_code); | ||
| 1584 | up_write(&mm->mmap_sem); | 1606 | up_write(&mm->mmap_sem); |
| 1585 | 1607 | ||
| 1586 | if (unlikely(core_waiters < 0)) | 1608 | if (unlikely(core_waiters < 0)) |
| @@ -1597,12 +1619,32 @@ static int coredump_wait(int exit_code) | |||
| 1597 | } | 1619 | } |
| 1598 | 1620 | ||
| 1599 | if (core_waiters) | 1621 | if (core_waiters) |
| 1600 | wait_for_completion(&startup_done); | 1622 | wait_for_completion(&core_state->startup); |
| 1601 | fail: | 1623 | fail: |
| 1602 | BUG_ON(mm->core_waiters); | ||
| 1603 | return core_waiters; | 1624 | return core_waiters; |
| 1604 | } | 1625 | } |
| 1605 | 1626 | ||
| 1627 | static void coredump_finish(struct mm_struct *mm) | ||
| 1628 | { | ||
| 1629 | struct core_thread *curr, *next; | ||
| 1630 | struct task_struct *task; | ||
| 1631 | |||
| 1632 | next = mm->core_state->dumper.next; | ||
| 1633 | while ((curr = next) != NULL) { | ||
| 1634 | next = curr->next; | ||
| 1635 | task = curr->task; | ||
| 1636 | /* | ||
| 1637 | * see exit_mm(), curr->task must not see | ||
| 1638 | * ->task == NULL before we read ->next. | ||
| 1639 | */ | ||
| 1640 | smp_mb(); | ||
| 1641 | curr->task = NULL; | ||
| 1642 | wake_up_process(task); | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | mm->core_state = NULL; | ||
| 1646 | } | ||
| 1647 | |||
| 1606 | /* | 1648 | /* |
| 1607 | * set_dumpable converts traditional three-value dumpable to two flags and | 1649 | * set_dumpable converts traditional three-value dumpable to two flags and |
| 1608 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but | 1650 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but |
| @@ -1654,6 +1696,7 @@ int get_dumpable(struct mm_struct *mm) | |||
| 1654 | 1696 | ||
| 1655 | int do_coredump(long signr, int exit_code, struct pt_regs * regs) | 1697 | int do_coredump(long signr, int exit_code, struct pt_regs * regs) |
| 1656 | { | 1698 | { |
| 1699 | struct core_state core_state; | ||
| 1657 | char corename[CORENAME_MAX_SIZE + 1]; | 1700 | char corename[CORENAME_MAX_SIZE + 1]; |
| 1658 | struct mm_struct *mm = current->mm; | 1701 | struct mm_struct *mm = current->mm; |
| 1659 | struct linux_binfmt * binfmt; | 1702 | struct linux_binfmt * binfmt; |
| @@ -1677,7 +1720,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1677 | /* | 1720 | /* |
| 1678 | * If another thread got here first, or we are not dumpable, bail out. | 1721 | * If another thread got here first, or we are not dumpable, bail out. |
| 1679 | */ | 1722 | */ |
| 1680 | if (mm->core_waiters || !get_dumpable(mm)) { | 1723 | if (mm->core_state || !get_dumpable(mm)) { |
| 1681 | up_write(&mm->mmap_sem); | 1724 | up_write(&mm->mmap_sem); |
| 1682 | goto fail; | 1725 | goto fail; |
| 1683 | } | 1726 | } |
| @@ -1692,7 +1735,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1692 | current->fsuid = 0; /* Dump root private */ | 1735 | current->fsuid = 0; /* Dump root private */ |
| 1693 | } | 1736 | } |
| 1694 | 1737 | ||
| 1695 | retval = coredump_wait(exit_code); | 1738 | retval = coredump_wait(exit_code, &core_state); |
| 1696 | if (retval < 0) | 1739 | if (retval < 0) |
| 1697 | goto fail; | 1740 | goto fail; |
| 1698 | 1741 | ||
| @@ -1707,7 +1750,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1707 | * uses lock_kernel() | 1750 | * uses lock_kernel() |
| 1708 | */ | 1751 | */ |
| 1709 | lock_kernel(); | 1752 | lock_kernel(); |
| 1710 | ispipe = format_corename(corename, core_pattern, signr); | 1753 | ispipe = format_corename(corename, retval, signr); |
| 1711 | unlock_kernel(); | 1754 | unlock_kernel(); |
| 1712 | /* | 1755 | /* |
| 1713 | * Don't bother to check the RLIMIT_CORE value if core_pattern points | 1756 | * Don't bother to check the RLIMIT_CORE value if core_pattern points |
| @@ -1786,7 +1829,7 @@ fail_unlock: | |||
| 1786 | argv_free(helper_argv); | 1829 | argv_free(helper_argv); |
| 1787 | 1830 | ||
| 1788 | current->fsuid = fsuid; | 1831 | current->fsuid = fsuid; |
| 1789 | complete_all(&mm->core_done); | 1832 | coredump_finish(mm); |
| 1790 | fail: | 1833 | fail: |
| 1791 | return retval; | 1834 | return retval; |
| 1792 | } | 1835 | } |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index ef50cbc792db..31308a3b0b8b 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
| 32 | #include <linux/mount.h> | 32 | #include <linux/mount.h> |
| 33 | #include <linux/log2.h> | 33 | #include <linux/log2.h> |
| 34 | #include <linux/quotaops.h> | ||
| 34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
| 35 | #include "ext2.h" | 36 | #include "ext2.h" |
| 36 | #include "xattr.h" | 37 | #include "xattr.h" |
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index eaa23d2d5213..70c0dbdcdcb7 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c | |||
| @@ -14,7 +14,7 @@ static size_t | |||
| 14 | ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size, | 14 | ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size, |
| 15 | const char *name, size_t name_len) | 15 | const char *name, size_t name_len) |
| 16 | { | 16 | { |
| 17 | const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1; | 17 | const int prefix_len = XATTR_SECURITY_PREFIX_LEN; |
| 18 | const size_t total_len = prefix_len + name_len + 1; | 18 | const size_t total_len = prefix_len + name_len + 1; |
| 19 | 19 | ||
| 20 | if (list && total_len <= list_size) { | 20 | if (list && total_len <= list_size) { |
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c index 83ee149f353d..e8219f8eae9f 100644 --- a/fs/ext2/xattr_trusted.c +++ b/fs/ext2/xattr_trusted.c | |||
| @@ -12,13 +12,11 @@ | |||
| 12 | #include <linux/ext2_fs.h> | 12 | #include <linux/ext2_fs.h> |
| 13 | #include "xattr.h" | 13 | #include "xattr.h" |
| 14 | 14 | ||
| 15 | #define XATTR_TRUSTED_PREFIX "trusted." | ||
| 16 | |||
| 17 | static size_t | 15 | static size_t |
| 18 | ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size, | 16 | ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size, |
| 19 | const char *name, size_t name_len) | 17 | const char *name, size_t name_len) |
| 20 | { | 18 | { |
| 21 | const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1; | 19 | const int prefix_len = XATTR_TRUSTED_PREFIX_LEN; |
| 22 | const size_t total_len = prefix_len + name_len + 1; | 20 | const size_t total_len = prefix_len + name_len + 1; |
| 23 | 21 | ||
| 24 | if (!capable(CAP_SYS_ADMIN)) | 22 | if (!capable(CAP_SYS_ADMIN)) |
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c index f383e7c3a7b5..92495d28c62f 100644 --- a/fs/ext2/xattr_user.c +++ b/fs/ext2/xattr_user.c | |||
| @@ -11,13 +11,11 @@ | |||
| 11 | #include "ext2.h" | 11 | #include "ext2.h" |
| 12 | #include "xattr.h" | 12 | #include "xattr.h" |
| 13 | 13 | ||
| 14 | #define XATTR_USER_PREFIX "user." | ||
| 15 | |||
| 16 | static size_t | 14 | static size_t |
| 17 | ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size, | 15 | ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size, |
| 18 | const char *name, size_t name_len) | 16 | const char *name, size_t name_len) |
| 19 | { | 17 | { |
| 20 | const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1; | 18 | const size_t prefix_len = XATTR_USER_PREFIX_LEN; |
| 21 | const size_t total_len = prefix_len + name_len + 1; | 19 | const size_t total_len = prefix_len + name_len + 1; |
| 22 | 20 | ||
| 23 | if (!test_opt(inode->i_sb, XATTR_USER)) | 21 | if (!test_opt(inode->i_sb, XATTR_USER)) |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 8ca3bfd72427..2eea96ec78ed 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
| @@ -272,7 +272,7 @@ static void free_rb_tree_fname(struct rb_root *root) | |||
| 272 | 272 | ||
| 273 | while (n) { | 273 | while (n) { |
| 274 | /* Do the node's children first */ | 274 | /* Do the node's children first */ |
| 275 | if ((n)->rb_left) { | 275 | if (n->rb_left) { |
| 276 | n = n->rb_left; | 276 | n = n->rb_left; |
| 277 | continue; | 277 | continue; |
| 278 | } | 278 | } |
| @@ -301,24 +301,18 @@ static void free_rb_tree_fname(struct rb_root *root) | |||
| 301 | parent->rb_right = NULL; | 301 | parent->rb_right = NULL; |
| 302 | n = parent; | 302 | n = parent; |
| 303 | } | 303 | } |
| 304 | root->rb_node = NULL; | ||
| 305 | } | 304 | } |
| 306 | 305 | ||
| 307 | 306 | ||
| 308 | static struct dir_private_info *create_dir_info(loff_t pos) | 307 | static struct dir_private_info *ext3_htree_create_dir_info(loff_t pos) |
| 309 | { | 308 | { |
| 310 | struct dir_private_info *p; | 309 | struct dir_private_info *p; |
| 311 | 310 | ||
| 312 | p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL); | 311 | p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL); |
| 313 | if (!p) | 312 | if (!p) |
| 314 | return NULL; | 313 | return NULL; |
| 315 | p->root.rb_node = NULL; | ||
| 316 | p->curr_node = NULL; | ||
| 317 | p->extra_fname = NULL; | ||
| 318 | p->last_pos = 0; | ||
| 319 | p->curr_hash = pos2maj_hash(pos); | 314 | p->curr_hash = pos2maj_hash(pos); |
| 320 | p->curr_minor_hash = pos2min_hash(pos); | 315 | p->curr_minor_hash = pos2min_hash(pos); |
| 321 | p->next_hash = 0; | ||
| 322 | return p; | 316 | return p; |
| 323 | } | 317 | } |
| 324 | 318 | ||
| @@ -433,7 +427,7 @@ static int ext3_dx_readdir(struct file * filp, | |||
| 433 | int ret; | 427 | int ret; |
| 434 | 428 | ||
| 435 | if (!info) { | 429 | if (!info) { |
| 436 | info = create_dir_info(filp->f_pos); | 430 | info = ext3_htree_create_dir_info(filp->f_pos); |
| 437 | if (!info) | 431 | if (!info) |
| 438 | return -ENOMEM; | 432 | return -ENOMEM; |
| 439 | filp->private_data = info; | 433 | filp->private_data = info; |
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 77126821b2e9..47b678d73e7a 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
| @@ -669,6 +669,14 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino) | |||
| 669 | if (IS_ERR(inode)) | 669 | if (IS_ERR(inode)) |
| 670 | goto iget_failed; | 670 | goto iget_failed; |
| 671 | 671 | ||
| 672 | /* | ||
| 673 | * If the orphans has i_nlinks > 0 then it should be able to be | ||
| 674 | * truncated, otherwise it won't be removed from the orphan list | ||
| 675 | * during processing and an infinite loop will result. | ||
| 676 | */ | ||
| 677 | if (inode->i_nlink && !ext3_can_truncate(inode)) | ||
| 678 | goto bad_orphan; | ||
| 679 | |||
| 672 | if (NEXT_ORPHAN(inode) > max_ino) | 680 | if (NEXT_ORPHAN(inode) > max_ino) |
| 673 | goto bad_orphan; | 681 | goto bad_orphan; |
| 674 | brelse(bitmap_bh); | 682 | brelse(bitmap_bh); |
| @@ -690,6 +698,7 @@ bad_orphan: | |||
| 690 | printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", | 698 | printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", |
| 691 | NEXT_ORPHAN(inode)); | 699 | NEXT_ORPHAN(inode)); |
| 692 | printk(KERN_NOTICE "max_ino=%lu\n", max_ino); | 700 | printk(KERN_NOTICE "max_ino=%lu\n", max_ino); |
| 701 | printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink); | ||
| 693 | /* Avoid freeing blocks if we got a bad deleted inode */ | 702 | /* Avoid freeing blocks if we got a bad deleted inode */ |
| 694 | if (inode->i_nlink == 0) | 703 | if (inode->i_nlink == 0) |
| 695 | inode->i_blocks = 0; | 704 | inode->i_blocks = 0; |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 6ae4ecf3ce40..3bf07d70b914 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
| @@ -2127,7 +2127,21 @@ static void ext3_free_data(handle_t *handle, struct inode *inode, | |||
| 2127 | 2127 | ||
| 2128 | if (this_bh) { | 2128 | if (this_bh) { |
| 2129 | BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata"); | 2129 | BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata"); |
| 2130 | ext3_journal_dirty_metadata(handle, this_bh); | 2130 | |
| 2131 | /* | ||
| 2132 | * The buffer head should have an attached journal head at this | ||
| 2133 | * point. However, if the data is corrupted and an indirect | ||
| 2134 | * block pointed to itself, it would have been detached when | ||
| 2135 | * the block was cleared. Check for this instead of OOPSing. | ||
| 2136 | */ | ||
| 2137 | if (bh2jh(this_bh)) | ||
| 2138 | ext3_journal_dirty_metadata(handle, this_bh); | ||
| 2139 | else | ||
| 2140 | ext3_error(inode->i_sb, "ext3_free_data", | ||
| 2141 | "circular indirect block detected, " | ||
| 2142 | "inode=%lu, block=%llu", | ||
| 2143 | inode->i_ino, | ||
| 2144 | (unsigned long long)this_bh->b_blocknr); | ||
| 2131 | } | 2145 | } |
| 2132 | } | 2146 | } |
| 2133 | 2147 | ||
| @@ -2253,6 +2267,19 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode, | |||
| 2253 | } | 2267 | } |
| 2254 | } | 2268 | } |
| 2255 | 2269 | ||
| 2270 | int ext3_can_truncate(struct inode *inode) | ||
| 2271 | { | ||
| 2272 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
| 2273 | return 0; | ||
| 2274 | if (S_ISREG(inode->i_mode)) | ||
| 2275 | return 1; | ||
| 2276 | if (S_ISDIR(inode->i_mode)) | ||
| 2277 | return 1; | ||
| 2278 | if (S_ISLNK(inode->i_mode)) | ||
| 2279 | return !ext3_inode_is_fast_symlink(inode); | ||
| 2280 | return 0; | ||
| 2281 | } | ||
| 2282 | |||
| 2256 | /* | 2283 | /* |
| 2257 | * ext3_truncate() | 2284 | * ext3_truncate() |
| 2258 | * | 2285 | * |
| @@ -2297,12 +2324,7 @@ void ext3_truncate(struct inode *inode) | |||
| 2297 | unsigned blocksize = inode->i_sb->s_blocksize; | 2324 | unsigned blocksize = inode->i_sb->s_blocksize; |
| 2298 | struct page *page; | 2325 | struct page *page; |
| 2299 | 2326 | ||
| 2300 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 2327 | if (!ext3_can_truncate(inode)) |
| 2301 | S_ISLNK(inode->i_mode))) | ||
| 2302 | return; | ||
| 2303 | if (ext3_inode_is_fast_symlink(inode)) | ||
| 2304 | return; | ||
| 2305 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
| 2306 | return; | 2328 | return; |
| 2307 | 2329 | ||
| 2308 | /* | 2330 | /* |
| @@ -2513,6 +2535,16 @@ static int __ext3_get_inode_loc(struct inode *inode, | |||
| 2513 | } | 2535 | } |
| 2514 | if (!buffer_uptodate(bh)) { | 2536 | if (!buffer_uptodate(bh)) { |
| 2515 | lock_buffer(bh); | 2537 | lock_buffer(bh); |
| 2538 | |||
| 2539 | /* | ||
| 2540 | * If the buffer has the write error flag, we have failed | ||
| 2541 | * to write out another inode in the same block. In this | ||
| 2542 | * case, we don't have to read the block because we may | ||
| 2543 | * read the old inode data successfully. | ||
| 2544 | */ | ||
| 2545 | if (buffer_write_io_error(bh) && !buffer_uptodate(bh)) | ||
| 2546 | set_buffer_uptodate(bh); | ||
| 2547 | |||
| 2516 | if (buffer_uptodate(bh)) { | 2548 | if (buffer_uptodate(bh)) { |
| 2517 | /* someone brought it uptodate while we waited */ | 2549 | /* someone brought it uptodate while we waited */ |
| 2518 | unlock_buffer(bh); | 2550 | unlock_buffer(bh); |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 0b8cf80154f1..de13e919cd81 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
| @@ -240,13 +240,13 @@ static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize) | |||
| 240 | { | 240 | { |
| 241 | unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) - | 241 | unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) - |
| 242 | EXT3_DIR_REC_LEN(2) - infosize; | 242 | EXT3_DIR_REC_LEN(2) - infosize; |
| 243 | return 0? 20: entry_space / sizeof(struct dx_entry); | 243 | return entry_space / sizeof(struct dx_entry); |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static inline unsigned dx_node_limit (struct inode *dir) | 246 | static inline unsigned dx_node_limit (struct inode *dir) |
| 247 | { | 247 | { |
| 248 | unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0); | 248 | unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0); |
| 249 | return 0? 22: entry_space / sizeof(struct dx_entry); | 249 | return entry_space / sizeof(struct dx_entry); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | /* | 252 | /* |
| @@ -991,19 +991,21 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, | |||
| 991 | de = (struct ext3_dir_entry_2 *) bh->b_data; | 991 | de = (struct ext3_dir_entry_2 *) bh->b_data; |
| 992 | top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize - | 992 | top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize - |
| 993 | EXT3_DIR_REC_LEN(0)); | 993 | EXT3_DIR_REC_LEN(0)); |
| 994 | for (; de < top; de = ext3_next_entry(de)) | 994 | for (; de < top; de = ext3_next_entry(de)) { |
| 995 | if (ext3_match (namelen, name, de)) { | 995 | int off = (block << EXT3_BLOCK_SIZE_BITS(sb)) |
| 996 | if (!ext3_check_dir_entry("ext3_find_entry", | 996 | + ((char *) de - bh->b_data); |
| 997 | dir, de, bh, | 997 | |
| 998 | (block<<EXT3_BLOCK_SIZE_BITS(sb)) | 998 | if (!ext3_check_dir_entry(__func__, dir, de, bh, off)) { |
| 999 | +((char *)de - bh->b_data))) { | 999 | brelse(bh); |
| 1000 | brelse (bh); | ||
| 1001 | *err = ERR_BAD_DX_DIR; | 1000 | *err = ERR_BAD_DX_DIR; |
| 1002 | goto errout; | 1001 | goto errout; |
| 1003 | } | 1002 | } |
| 1004 | *res_dir = de; | 1003 | |
| 1005 | dx_release (frames); | 1004 | if (ext3_match(namelen, name, de)) { |
| 1006 | return bh; | 1005 | *res_dir = de; |
| 1006 | dx_release(frames); | ||
| 1007 | return bh; | ||
| 1008 | } | ||
| 1007 | } | 1009 | } |
| 1008 | brelse (bh); | 1010 | brelse (bh); |
| 1009 | /* Check to see if we should continue to search */ | 1011 | /* Check to see if we should continue to search */ |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 2845425077e8..615788c6843a 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -842,7 +842,7 @@ static int parse_options (char *options, struct super_block *sb, | |||
| 842 | int data_opt = 0; | 842 | int data_opt = 0; |
| 843 | int option; | 843 | int option; |
| 844 | #ifdef CONFIG_QUOTA | 844 | #ifdef CONFIG_QUOTA |
| 845 | int qtype; | 845 | int qtype, qfmt; |
| 846 | char *qname; | 846 | char *qname; |
| 847 | #endif | 847 | #endif |
| 848 | 848 | ||
| @@ -1018,9 +1018,11 @@ static int parse_options (char *options, struct super_block *sb, | |||
| 1018 | case Opt_grpjquota: | 1018 | case Opt_grpjquota: |
| 1019 | qtype = GRPQUOTA; | 1019 | qtype = GRPQUOTA; |
| 1020 | set_qf_name: | 1020 | set_qf_name: |
| 1021 | if (sb_any_quota_enabled(sb)) { | 1021 | if ((sb_any_quota_enabled(sb) || |
| 1022 | sb_any_quota_suspended(sb)) && | ||
| 1023 | !sbi->s_qf_names[qtype]) { | ||
| 1022 | printk(KERN_ERR | 1024 | printk(KERN_ERR |
| 1023 | "EXT3-fs: Cannot change journalled " | 1025 | "EXT3-fs: Cannot change journaled " |
| 1024 | "quota options when quota turned on.\n"); | 1026 | "quota options when quota turned on.\n"); |
| 1025 | return 0; | 1027 | return 0; |
| 1026 | } | 1028 | } |
| @@ -1056,9 +1058,11 @@ set_qf_name: | |||
| 1056 | case Opt_offgrpjquota: | 1058 | case Opt_offgrpjquota: |
| 1057 | qtype = GRPQUOTA; | 1059 | qtype = GRPQUOTA; |
| 1058 | clear_qf_name: | 1060 | clear_qf_name: |
| 1059 | if (sb_any_quota_enabled(sb)) { | 1061 | if ((sb_any_quota_enabled(sb) || |
| 1062 | sb_any_quota_suspended(sb)) && | ||
| 1063 | sbi->s_qf_names[qtype]) { | ||
| 1060 | printk(KERN_ERR "EXT3-fs: Cannot change " | 1064 | printk(KERN_ERR "EXT3-fs: Cannot change " |
| 1061 | "journalled quota options when " | 1065 | "journaled quota options when " |
| 1062 | "quota turned on.\n"); | 1066 | "quota turned on.\n"); |
| 1063 | return 0; | 1067 | return 0; |
| 1064 | } | 1068 | } |
| @@ -1069,10 +1073,20 @@ clear_qf_name: | |||
| 1069 | sbi->s_qf_names[qtype] = NULL; | 1073 | sbi->s_qf_names[qtype] = NULL; |
| 1070 | break; | 1074 | break; |
| 1071 | case Opt_jqfmt_vfsold: | 1075 | case Opt_jqfmt_vfsold: |
| 1072 | sbi->s_jquota_fmt = QFMT_VFS_OLD; | 1076 | qfmt = QFMT_VFS_OLD; |
| 1073 | break; | 1077 | goto set_qf_format; |
| 1074 | case Opt_jqfmt_vfsv0: | 1078 | case Opt_jqfmt_vfsv0: |
| 1075 | sbi->s_jquota_fmt = QFMT_VFS_V0; | 1079 | qfmt = QFMT_VFS_V0; |
| 1080 | set_qf_format: | ||
| 1081 | if ((sb_any_quota_enabled(sb) || | ||
| 1082 | sb_any_quota_suspended(sb)) && | ||
| 1083 | sbi->s_jquota_fmt != qfmt) { | ||
| 1084 | printk(KERN_ERR "EXT3-fs: Cannot change " | ||
| 1085 | "journaled quota options when " | ||
| 1086 | "quota turned on.\n"); | ||
| 1087 | return 0; | ||
| 1088 | } | ||
| 1089 | sbi->s_jquota_fmt = qfmt; | ||
| 1076 | break; | 1090 | break; |
| 1077 | case Opt_quota: | 1091 | case Opt_quota: |
| 1078 | case Opt_usrquota: | 1092 | case Opt_usrquota: |
| @@ -1084,7 +1098,8 @@ clear_qf_name: | |||
| 1084 | set_opt(sbi->s_mount_opt, GRPQUOTA); | 1098 | set_opt(sbi->s_mount_opt, GRPQUOTA); |
| 1085 | break; | 1099 | break; |
| 1086 | case Opt_noquota: | 1100 | case Opt_noquota: |
| 1087 | if (sb_any_quota_enabled(sb)) { | 1101 | if (sb_any_quota_enabled(sb) || |
| 1102 | sb_any_quota_suspended(sb)) { | ||
| 1088 | printk(KERN_ERR "EXT3-fs: Cannot change quota " | 1103 | printk(KERN_ERR "EXT3-fs: Cannot change quota " |
| 1089 | "options when quota turned on.\n"); | 1104 | "options when quota turned on.\n"); |
| 1090 | return 0; | 1105 | return 0; |
| @@ -1169,14 +1184,14 @@ clear_qf_name: | |||
| 1169 | } | 1184 | } |
| 1170 | 1185 | ||
| 1171 | if (!sbi->s_jquota_fmt) { | 1186 | if (!sbi->s_jquota_fmt) { |
| 1172 | printk(KERN_ERR "EXT3-fs: journalled quota format " | 1187 | printk(KERN_ERR "EXT3-fs: journaled quota format " |
| 1173 | "not specified.\n"); | 1188 | "not specified.\n"); |
| 1174 | return 0; | 1189 | return 0; |
| 1175 | } | 1190 | } |
| 1176 | } else { | 1191 | } else { |
| 1177 | if (sbi->s_jquota_fmt) { | 1192 | if (sbi->s_jquota_fmt) { |
| 1178 | printk(KERN_ERR "EXT3-fs: journalled quota format " | 1193 | printk(KERN_ERR "EXT3-fs: journaled quota format " |
| 1179 | "specified with no journalling " | 1194 | "specified with no journaling " |
| 1180 | "enabled.\n"); | 1195 | "enabled.\n"); |
| 1181 | return 0; | 1196 | return 0; |
| 1182 | } | 1197 | } |
| @@ -1370,7 +1385,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, | |||
| 1370 | int ret = ext3_quota_on_mount(sb, i); | 1385 | int ret = ext3_quota_on_mount(sb, i); |
| 1371 | if (ret < 0) | 1386 | if (ret < 0) |
| 1372 | printk(KERN_ERR | 1387 | printk(KERN_ERR |
| 1373 | "EXT3-fs: Cannot turn on journalled " | 1388 | "EXT3-fs: Cannot turn on journaled " |
| 1374 | "quota: error %d\n", ret); | 1389 | "quota: error %d\n", ret); |
| 1375 | } | 1390 | } |
| 1376 | } | 1391 | } |
| @@ -2712,7 +2727,7 @@ static int ext3_release_dquot(struct dquot *dquot) | |||
| 2712 | 2727 | ||
| 2713 | static int ext3_mark_dquot_dirty(struct dquot *dquot) | 2728 | static int ext3_mark_dquot_dirty(struct dquot *dquot) |
| 2714 | { | 2729 | { |
| 2715 | /* Are we journalling quotas? */ | 2730 | /* Are we journaling quotas? */ |
| 2716 | if (EXT3_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || | 2731 | if (EXT3_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || |
| 2717 | EXT3_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { | 2732 | EXT3_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { |
| 2718 | dquot_mark_dquot_dirty(dquot); | 2733 | dquot_mark_dquot_dirty(dquot); |
| @@ -2759,23 +2774,42 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, | |||
| 2759 | 2774 | ||
| 2760 | if (!test_opt(sb, QUOTA)) | 2775 | if (!test_opt(sb, QUOTA)) |
| 2761 | return -EINVAL; | 2776 | return -EINVAL; |
| 2762 | /* Not journalling quota or remount? */ | 2777 | /* When remounting, no checks are needed and in fact, path is NULL */ |
| 2763 | if ((!EXT3_SB(sb)->s_qf_names[USRQUOTA] && | 2778 | if (remount) |
| 2764 | !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) || remount) | ||
| 2765 | return vfs_quota_on(sb, type, format_id, path, remount); | 2779 | return vfs_quota_on(sb, type, format_id, path, remount); |
| 2780 | |||
| 2766 | err = path_lookup(path, LOOKUP_FOLLOW, &nd); | 2781 | err = path_lookup(path, LOOKUP_FOLLOW, &nd); |
| 2767 | if (err) | 2782 | if (err) |
| 2768 | return err; | 2783 | return err; |
| 2784 | |||
| 2769 | /* Quotafile not on the same filesystem? */ | 2785 | /* Quotafile not on the same filesystem? */ |
| 2770 | if (nd.path.mnt->mnt_sb != sb) { | 2786 | if (nd.path.mnt->mnt_sb != sb) { |
| 2771 | path_put(&nd.path); | 2787 | path_put(&nd.path); |
| 2772 | return -EXDEV; | 2788 | return -EXDEV; |
| 2773 | } | 2789 | } |
| 2774 | /* Quotafile not in fs root? */ | 2790 | /* Journaling quota? */ |
| 2775 | if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) | 2791 | if (EXT3_SB(sb)->s_qf_names[type]) { |
| 2776 | printk(KERN_WARNING | 2792 | /* Quotafile not of fs root? */ |
| 2777 | "EXT3-fs: Quota file not on filesystem root. " | 2793 | if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) |
| 2778 | "Journalled quota will not work.\n"); | 2794 | printk(KERN_WARNING |
| 2795 | "EXT3-fs: Quota file not on filesystem root. " | ||
| 2796 | "Journaled quota will not work.\n"); | ||
| 2797 | } | ||
| 2798 | |||
| 2799 | /* | ||
| 2800 | * When we journal data on quota file, we have to flush journal to see | ||
| 2801 | * all updates to the file when we bypass pagecache... | ||
| 2802 | */ | ||
| 2803 | if (ext3_should_journal_data(nd.path.dentry->d_inode)) { | ||
| 2804 | /* | ||
| 2805 | * We don't need to lock updates but journal_flush() could | ||
| 2806 | * otherwise be livelocked... | ||
| 2807 | */ | ||
| 2808 | journal_lock_updates(EXT3_SB(sb)->s_journal); | ||
| 2809 | journal_flush(EXT3_SB(sb)->s_journal); | ||
| 2810 | journal_unlock_updates(EXT3_SB(sb)->s_journal); | ||
| 2811 | } | ||
| 2812 | |||
| 2779 | path_put(&nd.path); | 2813 | path_put(&nd.path); |
| 2780 | return vfs_quota_on(sb, type, format_id, path, remount); | 2814 | return vfs_quota_on(sb, type, format_id, path, remount); |
| 2781 | } | 2815 | } |
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c index 821efaf2b94e..37b81097bdf2 100644 --- a/fs/ext3/xattr_security.c +++ b/fs/ext3/xattr_security.c | |||
| @@ -15,7 +15,7 @@ static size_t | |||
| 15 | ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size, | 15 | ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size, |
| 16 | const char *name, size_t name_len) | 16 | const char *name, size_t name_len) |
| 17 | { | 17 | { |
| 18 | const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1; | 18 | const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN; |
| 19 | const size_t total_len = prefix_len + name_len + 1; | 19 | const size_t total_len = prefix_len + name_len + 1; |
| 20 | 20 | ||
| 21 | 21 | ||
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c index 0327497a55ce..c7c41a410c4b 100644 --- a/fs/ext3/xattr_trusted.c +++ b/fs/ext3/xattr_trusted.c | |||
| @@ -13,13 +13,11 @@ | |||
| 13 | #include <linux/ext3_fs.h> | 13 | #include <linux/ext3_fs.h> |
| 14 | #include "xattr.h" | 14 | #include "xattr.h" |
| 15 | 15 | ||
| 16 | #define XATTR_TRUSTED_PREFIX "trusted." | ||
| 17 | |||
| 18 | static size_t | 16 | static size_t |
| 19 | ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size, | 17 | ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size, |
| 20 | const char *name, size_t name_len) | 18 | const char *name, size_t name_len) |
| 21 | { | 19 | { |
| 22 | const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1; | 20 | const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; |
| 23 | const size_t total_len = prefix_len + name_len + 1; | 21 | const size_t total_len = prefix_len + name_len + 1; |
| 24 | 22 | ||
| 25 | if (!capable(CAP_SYS_ADMIN)) | 23 | if (!capable(CAP_SYS_ADMIN)) |
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c index 1abd8f92c440..430fe63b31b3 100644 --- a/fs/ext3/xattr_user.c +++ b/fs/ext3/xattr_user.c | |||
| @@ -12,13 +12,11 @@ | |||
| 12 | #include <linux/ext3_fs.h> | 12 | #include <linux/ext3_fs.h> |
| 13 | #include "xattr.h" | 13 | #include "xattr.h" |
| 14 | 14 | ||
| 15 | #define XATTR_USER_PREFIX "user." | ||
| 16 | |||
| 17 | static size_t | 15 | static size_t |
| 18 | ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size, | 16 | ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size, |
| 19 | const char *name, size_t name_len) | 17 | const char *name, size_t name_len) |
| 20 | { | 18 | { |
| 21 | const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1; | 19 | const size_t prefix_len = XATTR_USER_PREFIX_LEN; |
| 22 | const size_t total_len = prefix_len + name_len + 1; | 20 | const size_t total_len = prefix_len + name_len + 1; |
| 23 | 21 | ||
| 24 | if (!test_opt(inode->i_sb, XATTR_USER)) | 22 | if (!test_opt(inode->i_sb, XATTR_USER)) |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 34541d06e626..cd4a0162e10d 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
| 19 | #include <linux/msdos_fs.h> | 19 | #include <linux/msdos_fs.h> |
| 20 | #include <linux/dirent.h> | ||
| 21 | #include <linux/smp_lock.h> | 20 | #include <linux/smp_lock.h> |
| 22 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
| 23 | #include <linux/compat.h> | 22 | #include <linux/compat.h> |
| @@ -124,10 +123,11 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos, | |||
| 124 | * but ignore that right now. | 123 | * but ignore that right now. |
| 125 | * Ahem... Stack smashing in ring 0 isn't fun. Fixed. | 124 | * Ahem... Stack smashing in ring 0 isn't fun. Fixed. |
| 126 | */ | 125 | */ |
| 127 | static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len, | 126 | static int uni16_to_x8(unsigned char *ascii, const wchar_t *uni, int len, |
| 128 | int uni_xlate, struct nls_table *nls) | 127 | int uni_xlate, struct nls_table *nls) |
| 129 | { | 128 | { |
| 130 | wchar_t *ip, ec; | 129 | const wchar_t *ip; |
| 130 | wchar_t ec; | ||
| 131 | unsigned char *op, nc; | 131 | unsigned char *op, nc; |
| 132 | int charlen; | 132 | int charlen; |
| 133 | int k; | 133 | int k; |
| @@ -167,6 +167,16 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len, | |||
| 167 | return (op - ascii); | 167 | return (op - ascii); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static inline int fat_uni_to_x8(struct msdos_sb_info *sbi, const wchar_t *uni, | ||
| 171 | unsigned char *buf, int size) | ||
| 172 | { | ||
| 173 | if (sbi->options.utf8) | ||
| 174 | return utf8_wcstombs(buf, uni, size); | ||
| 175 | else | ||
| 176 | return uni16_to_x8(buf, uni, size, sbi->options.unicode_xlate, | ||
| 177 | sbi->nls_io); | ||
| 178 | } | ||
| 179 | |||
| 170 | static inline int | 180 | static inline int |
| 171 | fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni) | 181 | fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni) |
| 172 | { | 182 | { |
| @@ -227,6 +237,19 @@ fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size, | |||
| 227 | return len; | 237 | return len; |
| 228 | } | 238 | } |
| 229 | 239 | ||
| 240 | static inline int fat_name_match(struct msdos_sb_info *sbi, | ||
| 241 | const unsigned char *a, int a_len, | ||
| 242 | const unsigned char *b, int b_len) | ||
| 243 | { | ||
| 244 | if (a_len != b_len) | ||
| 245 | return 0; | ||
| 246 | |||
| 247 | if (sbi->options.name_check != 's') | ||
| 248 | return !nls_strnicmp(sbi->nls_io, a, b, a_len); | ||
| 249 | else | ||
| 250 | return !memcmp(a, b, a_len); | ||
| 251 | } | ||
| 252 | |||
| 230 | enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, }; | 253 | enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, }; |
| 231 | 254 | ||
| 232 | /** | 255 | /** |
| @@ -302,6 +325,19 @@ parse_long: | |||
| 302 | } | 325 | } |
| 303 | 326 | ||
| 304 | /* | 327 | /* |
| 328 | * Maximum buffer size of short name. | ||
| 329 | * [(MSDOS_NAME + '.') * max one char + nul] | ||
| 330 | * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul] | ||
| 331 | */ | ||
| 332 | #define FAT_MAX_SHORT_SIZE ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1) | ||
| 333 | /* | ||
| 334 | * Maximum buffer size of unicode chars from slots. | ||
| 335 | * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)] | ||
| 336 | */ | ||
| 337 | #define FAT_MAX_UNI_CHARS ((MSDOS_SLOTS - 1) * 13 + 1) | ||
| 338 | #define FAT_MAX_UNI_SIZE (FAT_MAX_UNI_CHARS * sizeof(wchar_t)) | ||
| 339 | |||
| 340 | /* | ||
| 305 | * Return values: negative -> error, 0 -> not found, positive -> found, | 341 | * Return values: negative -> error, 0 -> not found, positive -> found, |
| 306 | * value is the total amount of slots, including the shortname entry. | 342 | * value is the total amount of slots, including the shortname entry. |
| 307 | */ | 343 | */ |
| @@ -312,29 +348,20 @@ int fat_search_long(struct inode *inode, const unsigned char *name, | |||
| 312 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 348 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
| 313 | struct buffer_head *bh = NULL; | 349 | struct buffer_head *bh = NULL; |
| 314 | struct msdos_dir_entry *de; | 350 | struct msdos_dir_entry *de; |
| 315 | struct nls_table *nls_io = sbi->nls_io; | ||
| 316 | struct nls_table *nls_disk = sbi->nls_disk; | 351 | struct nls_table *nls_disk = sbi->nls_disk; |
| 317 | wchar_t bufuname[14]; | ||
| 318 | unsigned char nr_slots; | 352 | unsigned char nr_slots; |
| 319 | int xlate_len; | 353 | wchar_t bufuname[14]; |
| 320 | wchar_t *unicode = NULL; | 354 | wchar_t *unicode = NULL; |
| 321 | unsigned char work[MSDOS_NAME]; | 355 | unsigned char work[MSDOS_NAME]; |
| 322 | unsigned char *bufname = NULL; | 356 | unsigned char bufname[FAT_MAX_SHORT_SIZE]; |
| 323 | int uni_xlate = sbi->options.unicode_xlate; | ||
| 324 | int utf8 = sbi->options.utf8; | ||
| 325 | int anycase = (sbi->options.name_check != 's'); | ||
| 326 | unsigned short opt_shortname = sbi->options.shortname; | 357 | unsigned short opt_shortname = sbi->options.shortname; |
| 327 | loff_t cpos = 0; | 358 | loff_t cpos = 0; |
| 328 | int chl, i, j, last_u, err; | 359 | int chl, i, j, last_u, err, len; |
| 329 | |||
| 330 | bufname = __getname(); | ||
| 331 | if (!bufname) | ||
| 332 | return -ENOMEM; | ||
| 333 | 360 | ||
| 334 | err = -ENOENT; | 361 | err = -ENOENT; |
| 335 | while(1) { | 362 | while (1) { |
| 336 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) | 363 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) |
| 337 | goto EODir; | 364 | goto end_of_dir; |
| 338 | parse_record: | 365 | parse_record: |
| 339 | nr_slots = 0; | 366 | nr_slots = 0; |
| 340 | if (de->name[0] == DELETED_FLAG) | 367 | if (de->name[0] == DELETED_FLAG) |
| @@ -353,7 +380,7 @@ parse_record: | |||
| 353 | else if (status == PARSE_NOT_LONGNAME) | 380 | else if (status == PARSE_NOT_LONGNAME) |
| 354 | goto parse_record; | 381 | goto parse_record; |
| 355 | else if (status == PARSE_EOF) | 382 | else if (status == PARSE_EOF) |
| 356 | goto EODir; | 383 | goto end_of_dir; |
| 357 | } | 384 | } |
| 358 | 385 | ||
| 359 | memcpy(work, de->name, sizeof(de->name)); | 386 | memcpy(work, de->name, sizeof(de->name)); |
| @@ -394,30 +421,24 @@ parse_record: | |||
| 394 | if (!last_u) | 421 | if (!last_u) |
| 395 | continue; | 422 | continue; |
| 396 | 423 | ||
| 424 | /* Compare shortname */ | ||
| 397 | bufuname[last_u] = 0x0000; | 425 | bufuname[last_u] = 0x0000; |
| 398 | xlate_len = utf8 | 426 | len = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); |
| 399 | ?utf8_wcstombs(bufname, bufuname, PATH_MAX) | 427 | if (fat_name_match(sbi, name, name_len, bufname, len)) |
| 400 | :uni16_to_x8(bufname, bufuname, PATH_MAX, uni_xlate, nls_io); | 428 | goto found; |
| 401 | if (xlate_len == name_len) | ||
| 402 | if ((!anycase && !memcmp(name, bufname, xlate_len)) || | ||
| 403 | (anycase && !nls_strnicmp(nls_io, name, bufname, | ||
| 404 | xlate_len))) | ||
| 405 | goto Found; | ||
| 406 | 429 | ||
| 407 | if (nr_slots) { | 430 | if (nr_slots) { |
| 408 | xlate_len = utf8 | 431 | void *longname = unicode + FAT_MAX_UNI_CHARS; |
| 409 | ?utf8_wcstombs(bufname, unicode, PATH_MAX) | 432 | int size = PATH_MAX - FAT_MAX_UNI_SIZE; |
| 410 | :uni16_to_x8(bufname, unicode, PATH_MAX, uni_xlate, nls_io); | 433 | |
| 411 | if (xlate_len != name_len) | 434 | /* Compare longname */ |
| 412 | continue; | 435 | len = fat_uni_to_x8(sbi, unicode, longname, size); |
| 413 | if ((!anycase && !memcmp(name, bufname, xlate_len)) || | 436 | if (fat_name_match(sbi, name, name_len, longname, len)) |
| 414 | (anycase && !nls_strnicmp(nls_io, name, bufname, | 437 | goto found; |
| 415 | xlate_len))) | ||
| 416 | goto Found; | ||
| 417 | } | 438 | } |
| 418 | } | 439 | } |
| 419 | 440 | ||
| 420 | Found: | 441 | found: |
| 421 | nr_slots++; /* include the de */ | 442 | nr_slots++; /* include the de */ |
| 422 | sinfo->slot_off = cpos - nr_slots * sizeof(*de); | 443 | sinfo->slot_off = cpos - nr_slots * sizeof(*de); |
| 423 | sinfo->nr_slots = nr_slots; | 444 | sinfo->nr_slots = nr_slots; |
| @@ -425,9 +446,7 @@ Found: | |||
| 425 | sinfo->bh = bh; | 446 | sinfo->bh = bh; |
| 426 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); | 447 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); |
| 427 | err = 0; | 448 | err = 0; |
| 428 | EODir: | 449 | end_of_dir: |
| 429 | if (bufname) | ||
| 430 | __putname(bufname); | ||
| 431 | if (unicode) | 450 | if (unicode) |
| 432 | __putname(unicode); | 451 | __putname(unicode); |
| 433 | 452 | ||
| @@ -453,23 +472,20 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | |||
| 453 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 472 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
| 454 | struct buffer_head *bh; | 473 | struct buffer_head *bh; |
| 455 | struct msdos_dir_entry *de; | 474 | struct msdos_dir_entry *de; |
| 456 | struct nls_table *nls_io = sbi->nls_io; | ||
| 457 | struct nls_table *nls_disk = sbi->nls_disk; | 475 | struct nls_table *nls_disk = sbi->nls_disk; |
| 458 | unsigned char long_slots; | 476 | unsigned char nr_slots; |
| 459 | const char *fill_name; | ||
| 460 | int fill_len; | ||
| 461 | wchar_t bufuname[14]; | 477 | wchar_t bufuname[14]; |
| 462 | wchar_t *unicode = NULL; | 478 | wchar_t *unicode = NULL; |
| 463 | unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname; | 479 | unsigned char c, work[MSDOS_NAME]; |
| 464 | unsigned long lpos, dummy, *furrfu = &lpos; | 480 | unsigned char bufname[FAT_MAX_SHORT_SIZE], *ptname = bufname; |
| 465 | int uni_xlate = sbi->options.unicode_xlate; | 481 | unsigned short opt_shortname = sbi->options.shortname; |
| 466 | int isvfat = sbi->options.isvfat; | 482 | int isvfat = sbi->options.isvfat; |
| 467 | int utf8 = sbi->options.utf8; | ||
| 468 | int nocase = sbi->options.nocase; | 483 | int nocase = sbi->options.nocase; |
| 469 | unsigned short opt_shortname = sbi->options.shortname; | 484 | const char *fill_name = NULL; |
| 470 | unsigned long inum; | 485 | unsigned long inum; |
| 471 | int chi, chl, i, i2, j, last, last_u, dotoffset = 0; | 486 | unsigned long lpos, dummy, *furrfu = &lpos; |
| 472 | loff_t cpos; | 487 | loff_t cpos; |
| 488 | int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0; | ||
| 473 | int ret = 0; | 489 | int ret = 0; |
| 474 | 490 | ||
| 475 | lock_super(sb); | 491 | lock_super(sb); |
| @@ -489,43 +505,58 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | |||
| 489 | cpos = 0; | 505 | cpos = 0; |
| 490 | } | 506 | } |
| 491 | } | 507 | } |
| 492 | if (cpos & (sizeof(struct msdos_dir_entry)-1)) { | 508 | if (cpos & (sizeof(struct msdos_dir_entry) - 1)) { |
| 493 | ret = -ENOENT; | 509 | ret = -ENOENT; |
| 494 | goto out; | 510 | goto out; |
| 495 | } | 511 | } |
| 496 | 512 | ||
| 497 | bh = NULL; | 513 | bh = NULL; |
| 498 | GetNew: | 514 | get_new: |
| 499 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) | 515 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) |
| 500 | goto EODir; | 516 | goto end_of_dir; |
| 501 | parse_record: | 517 | parse_record: |
| 502 | long_slots = 0; | 518 | nr_slots = 0; |
| 503 | /* Check for long filename entry */ | 519 | /* |
| 504 | if (isvfat) { | 520 | * Check for long filename entry, but if short_only, we don't |
| 521 | * need to parse long filename. | ||
| 522 | */ | ||
| 523 | if (isvfat && !short_only) { | ||
| 505 | if (de->name[0] == DELETED_FLAG) | 524 | if (de->name[0] == DELETED_FLAG) |
| 506 | goto RecEnd; | 525 | goto record_end; |
| 507 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) | 526 | if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME)) |
| 508 | goto RecEnd; | 527 | goto record_end; |
| 509 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) | 528 | if (de->attr != ATTR_EXT && IS_FREE(de->name)) |
| 510 | goto RecEnd; | 529 | goto record_end; |
| 511 | } else { | 530 | } else { |
| 512 | if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name)) | 531 | if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name)) |
| 513 | goto RecEnd; | 532 | goto record_end; |
| 514 | } | 533 | } |
| 515 | 534 | ||
| 516 | if (isvfat && de->attr == ATTR_EXT) { | 535 | if (isvfat && de->attr == ATTR_EXT) { |
| 517 | int status = fat_parse_long(inode, &cpos, &bh, &de, | 536 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
| 518 | &unicode, &long_slots); | 537 | &unicode, &nr_slots); |
| 519 | if (status < 0) { | 538 | if (status < 0) { |
| 520 | filp->f_pos = cpos; | 539 | filp->f_pos = cpos; |
| 521 | ret = status; | 540 | ret = status; |
| 522 | goto out; | 541 | goto out; |
| 523 | } else if (status == PARSE_INVALID) | 542 | } else if (status == PARSE_INVALID) |
| 524 | goto RecEnd; | 543 | goto record_end; |
| 525 | else if (status == PARSE_NOT_LONGNAME) | 544 | else if (status == PARSE_NOT_LONGNAME) |
| 526 | goto parse_record; | 545 | goto parse_record; |
| 527 | else if (status == PARSE_EOF) | 546 | else if (status == PARSE_EOF) |
| 528 | goto EODir; | 547 | goto end_of_dir; |
| 548 | |||
| 549 | if (nr_slots) { | ||
| 550 | void *longname = unicode + FAT_MAX_UNI_CHARS; | ||
| 551 | int size = PATH_MAX - FAT_MAX_UNI_SIZE; | ||
| 552 | int len = fat_uni_to_x8(sbi, unicode, longname, size); | ||
| 553 | |||
| 554 | fill_name = longname; | ||
| 555 | fill_len = len; | ||
| 556 | /* !both && !short_only, so we don't need shortname. */ | ||
| 557 | if (!both) | ||
| 558 | goto start_filldir; | ||
| 559 | } | ||
| 529 | } | 560 | } |
| 530 | 561 | ||
| 531 | if (sbi->options.dotsOK) { | 562 | if (sbi->options.dotsOK) { |
| @@ -587,12 +618,32 @@ parse_record: | |||
| 587 | } | 618 | } |
| 588 | } | 619 | } |
| 589 | if (!last) | 620 | if (!last) |
| 590 | goto RecEnd; | 621 | goto record_end; |
| 591 | 622 | ||
| 592 | i = last + dotoffset; | 623 | i = last + dotoffset; |
| 593 | j = last_u; | 624 | j = last_u; |
| 594 | 625 | ||
| 595 | lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry); | 626 | if (isvfat) { |
| 627 | bufuname[j] = 0x0000; | ||
| 628 | i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); | ||
| 629 | } | ||
| 630 | if (nr_slots) { | ||
| 631 | /* hack for fat_ioctl_filldir() */ | ||
| 632 | struct fat_ioctl_filldir_callback *p = dirent; | ||
| 633 | |||
| 634 | p->longname = fill_name; | ||
| 635 | p->long_len = fill_len; | ||
| 636 | p->shortname = bufname; | ||
| 637 | p->short_len = i; | ||
| 638 | fill_name = NULL; | ||
| 639 | fill_len = 0; | ||
| 640 | } else { | ||
| 641 | fill_name = bufname; | ||
| 642 | fill_len = i; | ||
| 643 | } | ||
| 644 | |||
| 645 | start_filldir: | ||
| 646 | lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry); | ||
| 596 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) | 647 | if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) |
| 597 | inum = inode->i_ino; | 648 | inum = inode->i_ino; |
| 598 | else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { | 649 | else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { |
| @@ -607,49 +658,17 @@ parse_record: | |||
| 607 | inum = iunique(sb, MSDOS_ROOT_INO); | 658 | inum = iunique(sb, MSDOS_ROOT_INO); |
| 608 | } | 659 | } |
| 609 | 660 | ||
| 610 | if (isvfat) { | ||
| 611 | bufuname[j] = 0x0000; | ||
| 612 | i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname)) | ||
| 613 | : uni16_to_x8(bufname, bufuname, sizeof(bufname), uni_xlate, nls_io); | ||
| 614 | } | ||
| 615 | |||
| 616 | fill_name = bufname; | ||
| 617 | fill_len = i; | ||
| 618 | if (!short_only && long_slots) { | ||
| 619 | /* convert the unicode long name. 261 is maximum size | ||
| 620 | * of unicode buffer. (13 * slots + nul) */ | ||
| 621 | void *longname = unicode + 261; | ||
| 622 | int buf_size = PATH_MAX - (261 * sizeof(unicode[0])); | ||
| 623 | int long_len = utf8 | ||
| 624 | ? utf8_wcstombs(longname, unicode, buf_size) | ||
| 625 | : uni16_to_x8(longname, unicode, buf_size, uni_xlate, nls_io); | ||
| 626 | |||
| 627 | if (!both) { | ||
| 628 | fill_name = longname; | ||
| 629 | fill_len = long_len; | ||
| 630 | } else { | ||
| 631 | /* hack for fat_ioctl_filldir() */ | ||
| 632 | struct fat_ioctl_filldir_callback *p = dirent; | ||
| 633 | |||
| 634 | p->longname = longname; | ||
| 635 | p->long_len = long_len; | ||
| 636 | p->shortname = bufname; | ||
| 637 | p->short_len = i; | ||
| 638 | fill_name = NULL; | ||
| 639 | fill_len = 0; | ||
| 640 | } | ||
| 641 | } | ||
| 642 | if (filldir(dirent, fill_name, fill_len, *furrfu, inum, | 661 | if (filldir(dirent, fill_name, fill_len, *furrfu, inum, |
| 643 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) | 662 | (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0) |
| 644 | goto FillFailed; | 663 | goto fill_failed; |
| 645 | 664 | ||
| 646 | RecEnd: | 665 | record_end: |
| 647 | furrfu = &lpos; | 666 | furrfu = &lpos; |
| 648 | filp->f_pos = cpos; | 667 | filp->f_pos = cpos; |
| 649 | goto GetNew; | 668 | goto get_new; |
| 650 | EODir: | 669 | end_of_dir: |
| 651 | filp->f_pos = cpos; | 670 | filp->f_pos = cpos; |
| 652 | FillFailed: | 671 | fill_failed: |
| 653 | brelse(bh); | 672 | brelse(bh); |
| 654 | if (unicode) | 673 | if (unicode) |
| 655 | __putname(unicode); | 674 | __putname(unicode); |
| @@ -715,7 +734,7 @@ efault: \ | |||
| 715 | return -EFAULT; \ | 734 | return -EFAULT; \ |
| 716 | } | 735 | } |
| 717 | 736 | ||
| 718 | FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, dirent) | 737 | FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent) |
| 719 | 738 | ||
| 720 | static int fat_ioctl_readdir(struct inode *inode, struct file *filp, | 739 | static int fat_ioctl_readdir(struct inode *inode, struct file *filp, |
| 721 | void __user *dirent, filldir_t filldir, | 740 | void __user *dirent, filldir_t filldir, |
| @@ -741,7 +760,7 @@ static int fat_ioctl_readdir(struct inode *inode, struct file *filp, | |||
| 741 | static int fat_dir_ioctl(struct inode *inode, struct file *filp, | 760 | static int fat_dir_ioctl(struct inode *inode, struct file *filp, |
| 742 | unsigned int cmd, unsigned long arg) | 761 | unsigned int cmd, unsigned long arg) |
| 743 | { | 762 | { |
| 744 | struct dirent __user *d1 = (struct dirent __user *)arg; | 763 | struct __fat_dirent __user *d1 = (struct __fat_dirent __user *)arg; |
| 745 | int short_only, both; | 764 | int short_only, both; |
| 746 | 765 | ||
| 747 | switch (cmd) { | 766 | switch (cmd) { |
| @@ -757,7 +776,7 @@ static int fat_dir_ioctl(struct inode *inode, struct file *filp, | |||
| 757 | return fat_generic_ioctl(inode, filp, cmd, arg); | 776 | return fat_generic_ioctl(inode, filp, cmd, arg); |
| 758 | } | 777 | } |
| 759 | 778 | ||
| 760 | if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2]))) | 779 | if (!access_ok(VERIFY_WRITE, d1, sizeof(struct __fat_dirent[2]))) |
| 761 | return -EFAULT; | 780 | return -EFAULT; |
| 762 | /* | 781 | /* |
| 763 | * Yes, we don't need this put_user() absolutely. However old | 782 | * Yes, we don't need this put_user() absolutely. However old |
| @@ -1082,7 +1101,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | |||
| 1082 | goto error_free; | 1101 | goto error_free; |
| 1083 | } | 1102 | } |
| 1084 | 1103 | ||
| 1085 | fat_date_unix2dos(ts->tv_sec, &time, &date); | 1104 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); |
| 1086 | 1105 | ||
| 1087 | de = (struct msdos_dir_entry *)bhs[0]->b_data; | 1106 | de = (struct msdos_dir_entry *)bhs[0]->b_data; |
| 1088 | /* filling the new directory slots ("." and ".." entries) */ | 1107 | /* filling the new directory slots ("." and ".." entries) */ |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 46a4508ffd2e..23676f9d79ce 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -382,17 +382,20 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
| 382 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 382 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
| 383 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 383 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
| 384 | inode->i_mtime.tv_sec = | 384 | inode->i_mtime.tv_sec = |
| 385 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date)); | 385 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date), |
| 386 | sbi->options.tz_utc); | ||
| 386 | inode->i_mtime.tv_nsec = 0; | 387 | inode->i_mtime.tv_nsec = 0; |
| 387 | if (sbi->options.isvfat) { | 388 | if (sbi->options.isvfat) { |
| 388 | int secs = de->ctime_cs / 100; | 389 | int secs = de->ctime_cs / 100; |
| 389 | int csecs = de->ctime_cs % 100; | 390 | int csecs = de->ctime_cs % 100; |
| 390 | inode->i_ctime.tv_sec = | 391 | inode->i_ctime.tv_sec = |
| 391 | date_dos2unix(le16_to_cpu(de->ctime), | 392 | date_dos2unix(le16_to_cpu(de->ctime), |
| 392 | le16_to_cpu(de->cdate)) + secs; | 393 | le16_to_cpu(de->cdate), |
| 394 | sbi->options.tz_utc) + secs; | ||
| 393 | inode->i_ctime.tv_nsec = csecs * 10000000; | 395 | inode->i_ctime.tv_nsec = csecs * 10000000; |
| 394 | inode->i_atime.tv_sec = | 396 | inode->i_atime.tv_sec = |
| 395 | date_dos2unix(0, le16_to_cpu(de->adate)); | 397 | date_dos2unix(0, le16_to_cpu(de->adate), |
| 398 | sbi->options.tz_utc); | ||
| 396 | inode->i_atime.tv_nsec = 0; | 399 | inode->i_atime.tv_nsec = 0; |
| 397 | } else | 400 | } else |
| 398 | inode->i_ctime = inode->i_atime = inode->i_mtime; | 401 | inode->i_ctime = inode->i_atime = inode->i_mtime; |
| @@ -591,11 +594,14 @@ retry: | |||
| 591 | raw_entry->attr = fat_attr(inode); | 594 | raw_entry->attr = fat_attr(inode); |
| 592 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); | 595 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); |
| 593 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); | 596 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); |
| 594 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); | 597 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, |
| 598 | &raw_entry->date, sbi->options.tz_utc); | ||
| 595 | if (sbi->options.isvfat) { | 599 | if (sbi->options.isvfat) { |
| 596 | __le16 atime; | 600 | __le16 atime; |
| 597 | fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); | 601 | fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime, |
| 598 | fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate); | 602 | &raw_entry->cdate, sbi->options.tz_utc); |
| 603 | fat_date_unix2dos(inode->i_atime.tv_sec, &atime, | ||
| 604 | &raw_entry->adate, sbi->options.tz_utc); | ||
| 599 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + | 605 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + |
| 600 | inode->i_ctime.tv_nsec / 10000000; | 606 | inode->i_ctime.tv_nsec / 10000000; |
| 601 | } | 607 | } |
| @@ -836,6 +842,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 836 | } | 842 | } |
| 837 | if (sbi->options.flush) | 843 | if (sbi->options.flush) |
| 838 | seq_puts(m, ",flush"); | 844 | seq_puts(m, ",flush"); |
| 845 | if (opts->tz_utc) | ||
| 846 | seq_puts(m, ",tz=UTC"); | ||
| 839 | 847 | ||
| 840 | return 0; | 848 | return 0; |
| 841 | } | 849 | } |
| @@ -848,7 +856,7 @@ enum { | |||
| 848 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, | 856 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |
| 849 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 857 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
| 850 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 858 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
| 851 | Opt_obsolate, Opt_flush, Opt_err, | 859 | Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err, |
| 852 | }; | 860 | }; |
| 853 | 861 | ||
| 854 | static match_table_t fat_tokens = { | 862 | static match_table_t fat_tokens = { |
| @@ -883,6 +891,7 @@ static match_table_t fat_tokens = { | |||
| 883 | {Opt_obsolate, "cvf_options=%100s"}, | 891 | {Opt_obsolate, "cvf_options=%100s"}, |
| 884 | {Opt_obsolate, "posix"}, | 892 | {Opt_obsolate, "posix"}, |
| 885 | {Opt_flush, "flush"}, | 893 | {Opt_flush, "flush"}, |
| 894 | {Opt_tz_utc, "tz=UTC"}, | ||
| 886 | {Opt_err, NULL}, | 895 | {Opt_err, NULL}, |
| 887 | }; | 896 | }; |
| 888 | static match_table_t msdos_tokens = { | 897 | static match_table_t msdos_tokens = { |
| @@ -947,10 +956,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
| 947 | opts->utf8 = opts->unicode_xlate = 0; | 956 | opts->utf8 = opts->unicode_xlate = 0; |
| 948 | opts->numtail = 1; | 957 | opts->numtail = 1; |
| 949 | opts->usefree = opts->nocase = 0; | 958 | opts->usefree = opts->nocase = 0; |
| 959 | opts->tz_utc = 0; | ||
| 950 | *debug = 0; | 960 | *debug = 0; |
| 951 | 961 | ||
| 952 | if (!options) | 962 | if (!options) |
| 953 | return 0; | 963 | goto out; |
| 954 | 964 | ||
| 955 | while ((p = strsep(&options, ",")) != NULL) { | 965 | while ((p = strsep(&options, ",")) != NULL) { |
| 956 | int token; | 966 | int token; |
| @@ -1036,6 +1046,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
| 1036 | case Opt_flush: | 1046 | case Opt_flush: |
| 1037 | opts->flush = 1; | 1047 | opts->flush = 1; |
| 1038 | break; | 1048 | break; |
| 1049 | case Opt_tz_utc: | ||
| 1050 | opts->tz_utc = 1; | ||
| 1051 | break; | ||
| 1039 | 1052 | ||
| 1040 | /* msdos specific */ | 1053 | /* msdos specific */ |
| 1041 | case Opt_dots: | 1054 | case Opt_dots: |
| @@ -1104,10 +1117,13 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
| 1104 | return -EINVAL; | 1117 | return -EINVAL; |
| 1105 | } | 1118 | } |
| 1106 | } | 1119 | } |
| 1120 | |||
| 1121 | out: | ||
| 1107 | /* UTF-8 doesn't provide FAT semantics */ | 1122 | /* UTF-8 doesn't provide FAT semantics */ |
| 1108 | if (!strcmp(opts->iocharset, "utf8")) { | 1123 | if (!strcmp(opts->iocharset, "utf8")) { |
| 1109 | printk(KERN_ERR "FAT: utf8 is not a recommended IO charset" | 1124 | printk(KERN_ERR "FAT: utf8 is not a recommended IO charset" |
| 1110 | " for FAT filesystems, filesystem will be case sensitive!\n"); | 1125 | " for FAT filesystems, filesystem will be " |
| 1126 | "case sensitive!\n"); | ||
| 1111 | } | 1127 | } |
| 1112 | 1128 | ||
| 1113 | /* If user doesn't specify allow_utime, it's initialized from dmask. */ | 1129 | /* If user doesn't specify allow_utime, it's initialized from dmask. */ |
diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 61f23511eacf..79fb98ad36d4 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c | |||
| @@ -142,7 +142,7 @@ static int day_n[] = { | |||
| 142 | }; | 142 | }; |
| 143 | 143 | ||
| 144 | /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ | 144 | /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ |
| 145 | int date_dos2unix(unsigned short time, unsigned short date) | 145 | int date_dos2unix(unsigned short time, unsigned short date, int tz_utc) |
| 146 | { | 146 | { |
| 147 | int month, year, secs; | 147 | int month, year, secs; |
| 148 | 148 | ||
| @@ -156,16 +156,18 @@ int date_dos2unix(unsigned short time, unsigned short date) | |||
| 156 | ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && | 156 | ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && |
| 157 | month < 2 ? 1 : 0)+3653); | 157 | month < 2 ? 1 : 0)+3653); |
| 158 | /* days since 1.1.70 plus 80's leap day */ | 158 | /* days since 1.1.70 plus 80's leap day */ |
| 159 | secs += sys_tz.tz_minuteswest*60; | 159 | if (!tz_utc) |
| 160 | secs += sys_tz.tz_minuteswest*60; | ||
| 160 | return secs; | 161 | return secs; |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | /* Convert linear UNIX date to a MS-DOS time/date pair. */ | 164 | /* Convert linear UNIX date to a MS-DOS time/date pair. */ |
| 164 | void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date) | 165 | void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int tz_utc) |
| 165 | { | 166 | { |
| 166 | int day, year, nl_day, month; | 167 | int day, year, nl_day, month; |
| 167 | 168 | ||
| 168 | unix_date -= sys_tz.tz_minuteswest*60; | 169 | if (!tz_utc) |
| 170 | unix_date -= sys_tz.tz_minuteswest*60; | ||
| 169 | 171 | ||
| 170 | /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ | 172 | /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ |
| 171 | if (unix_date < 315532800) | 173 | if (unix_date < 315532800) |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 2060bf06b906..51d0035ff07e 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -97,7 +97,7 @@ void fuse_invalidate_attr(struct inode *inode) | |||
| 97 | * timeout is unknown (unlink, rmdir, rename and in some cases | 97 | * timeout is unknown (unlink, rmdir, rename and in some cases |
| 98 | * lookup) | 98 | * lookup) |
| 99 | */ | 99 | */ |
| 100 | static void fuse_invalidate_entry_cache(struct dentry *entry) | 100 | void fuse_invalidate_entry_cache(struct dentry *entry) |
| 101 | { | 101 | { |
| 102 | fuse_dentry_settime(entry, 0); | 102 | fuse_dentry_settime(entry, 0); |
| 103 | } | 103 | } |
| @@ -112,18 +112,16 @@ static void fuse_invalidate_entry(struct dentry *entry) | |||
| 112 | fuse_invalidate_entry_cache(entry); | 112 | fuse_invalidate_entry_cache(entry); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, | 115 | static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req, |
| 116 | struct dentry *entry, | 116 | u64 nodeid, struct qstr *name, |
| 117 | struct fuse_entry_out *outarg) | 117 | struct fuse_entry_out *outarg) |
| 118 | { | 118 | { |
| 119 | struct fuse_conn *fc = get_fuse_conn(dir); | ||
| 120 | |||
| 121 | memset(outarg, 0, sizeof(struct fuse_entry_out)); | 119 | memset(outarg, 0, sizeof(struct fuse_entry_out)); |
| 122 | req->in.h.opcode = FUSE_LOOKUP; | 120 | req->in.h.opcode = FUSE_LOOKUP; |
| 123 | req->in.h.nodeid = get_node_id(dir); | 121 | req->in.h.nodeid = nodeid; |
| 124 | req->in.numargs = 1; | 122 | req->in.numargs = 1; |
| 125 | req->in.args[0].size = entry->d_name.len + 1; | 123 | req->in.args[0].size = name->len + 1; |
| 126 | req->in.args[0].value = entry->d_name.name; | 124 | req->in.args[0].value = name->name; |
| 127 | req->out.numargs = 1; | 125 | req->out.numargs = 1; |
| 128 | if (fc->minor < 9) | 126 | if (fc->minor < 9) |
| 129 | req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | 127 | req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; |
| @@ -189,7 +187,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
| 189 | attr_version = fuse_get_attr_version(fc); | 187 | attr_version = fuse_get_attr_version(fc); |
| 190 | 188 | ||
| 191 | parent = dget_parent(entry); | 189 | parent = dget_parent(entry); |
| 192 | fuse_lookup_init(req, parent->d_inode, entry, &outarg); | 190 | fuse_lookup_init(fc, req, get_node_id(parent->d_inode), |
| 191 | &entry->d_name, &outarg); | ||
| 193 | request_send(fc, req); | 192 | request_send(fc, req); |
| 194 | dput(parent); | 193 | dput(parent); |
| 195 | err = req->out.h.error; | 194 | err = req->out.h.error; |
| @@ -225,7 +224,7 @@ static int invalid_nodeid(u64 nodeid) | |||
| 225 | return !nodeid || nodeid == FUSE_ROOT_ID; | 224 | return !nodeid || nodeid == FUSE_ROOT_ID; |
| 226 | } | 225 | } |
| 227 | 226 | ||
| 228 | static struct dentry_operations fuse_dentry_operations = { | 227 | struct dentry_operations fuse_dentry_operations = { |
| 229 | .d_revalidate = fuse_dentry_revalidate, | 228 | .d_revalidate = fuse_dentry_revalidate, |
| 230 | }; | 229 | }; |
| 231 | 230 | ||
| @@ -239,85 +238,127 @@ int fuse_valid_type(int m) | |||
| 239 | * Add a directory inode to a dentry, ensuring that no other dentry | 238 | * Add a directory inode to a dentry, ensuring that no other dentry |
| 240 | * refers to this inode. Called with fc->inst_mutex. | 239 | * refers to this inode. Called with fc->inst_mutex. |
| 241 | */ | 240 | */ |
| 242 | static int fuse_d_add_directory(struct dentry *entry, struct inode *inode) | 241 | static struct dentry *fuse_d_add_directory(struct dentry *entry, |
| 242 | struct inode *inode) | ||
| 243 | { | 243 | { |
| 244 | struct dentry *alias = d_find_alias(inode); | 244 | struct dentry *alias = d_find_alias(inode); |
| 245 | if (alias) { | 245 | if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { |
| 246 | /* This tries to shrink the subtree below alias */ | 246 | /* This tries to shrink the subtree below alias */ |
| 247 | fuse_invalidate_entry(alias); | 247 | fuse_invalidate_entry(alias); |
| 248 | dput(alias); | 248 | dput(alias); |
| 249 | if (!list_empty(&inode->i_dentry)) | 249 | if (!list_empty(&inode->i_dentry)) |
| 250 | return -EBUSY; | 250 | return ERR_PTR(-EBUSY); |
| 251 | } else { | ||
| 252 | dput(alias); | ||
| 251 | } | 253 | } |
| 252 | d_add(entry, inode); | 254 | return d_splice_alias(inode, entry); |
| 253 | return 0; | ||
| 254 | } | 255 | } |
| 255 | 256 | ||
| 256 | static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | 257 | int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, |
| 257 | struct nameidata *nd) | 258 | struct fuse_entry_out *outarg, struct inode **inode) |
| 258 | { | 259 | { |
| 259 | int err; | 260 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
| 260 | struct fuse_entry_out outarg; | ||
| 261 | struct inode *inode = NULL; | ||
| 262 | struct fuse_conn *fc = get_fuse_conn(dir); | ||
| 263 | struct fuse_req *req; | 261 | struct fuse_req *req; |
| 264 | struct fuse_req *forget_req; | 262 | struct fuse_req *forget_req; |
| 265 | u64 attr_version; | 263 | u64 attr_version; |
| 264 | int err; | ||
| 266 | 265 | ||
| 267 | if (entry->d_name.len > FUSE_NAME_MAX) | 266 | *inode = NULL; |
| 268 | return ERR_PTR(-ENAMETOOLONG); | 267 | err = -ENAMETOOLONG; |
| 268 | if (name->len > FUSE_NAME_MAX) | ||
| 269 | goto out; | ||
| 269 | 270 | ||
| 270 | req = fuse_get_req(fc); | 271 | req = fuse_get_req(fc); |
| 272 | err = PTR_ERR(req); | ||
| 271 | if (IS_ERR(req)) | 273 | if (IS_ERR(req)) |
| 272 | return ERR_CAST(req); | 274 | goto out; |
| 273 | 275 | ||
| 274 | forget_req = fuse_get_req(fc); | 276 | forget_req = fuse_get_req(fc); |
| 277 | err = PTR_ERR(forget_req); | ||
| 275 | if (IS_ERR(forget_req)) { | 278 | if (IS_ERR(forget_req)) { |
| 276 | fuse_put_request(fc, req); | 279 | fuse_put_request(fc, req); |
| 277 | return ERR_CAST(forget_req); | 280 | goto out; |
| 278 | } | 281 | } |
| 279 | 282 | ||
| 280 | attr_version = fuse_get_attr_version(fc); | 283 | attr_version = fuse_get_attr_version(fc); |
| 281 | 284 | ||
| 282 | fuse_lookup_init(req, dir, entry, &outarg); | 285 | fuse_lookup_init(fc, req, nodeid, name, outarg); |
| 283 | request_send(fc, req); | 286 | request_send(fc, req); |
| 284 | err = req->out.h.error; | 287 | err = req->out.h.error; |
| 285 | fuse_put_request(fc, req); | 288 | fuse_put_request(fc, req); |
| 286 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ | 289 | /* Zero nodeid is same as -ENOENT, but with valid timeout */ |
| 287 | if (!err && outarg.nodeid && | 290 | if (err || !outarg->nodeid) |
| 288 | (invalid_nodeid(outarg.nodeid) || | 291 | goto out_put_forget; |
| 289 | !fuse_valid_type(outarg.attr.mode))) | 292 | |
| 290 | err = -EIO; | 293 | err = -EIO; |
| 291 | if (!err && outarg.nodeid) { | 294 | if (!outarg->nodeid) |
| 292 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 295 | goto out_put_forget; |
| 293 | &outarg.attr, entry_attr_timeout(&outarg), | 296 | if (!fuse_valid_type(outarg->attr.mode)) |
| 294 | attr_version); | 297 | goto out_put_forget; |
| 295 | if (!inode) { | 298 | |
| 296 | fuse_send_forget(fc, forget_req, outarg.nodeid, 1); | 299 | *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, |
| 297 | return ERR_PTR(-ENOMEM); | 300 | &outarg->attr, entry_attr_timeout(outarg), |
| 298 | } | 301 | attr_version); |
| 302 | err = -ENOMEM; | ||
| 303 | if (!*inode) { | ||
| 304 | fuse_send_forget(fc, forget_req, outarg->nodeid, 1); | ||
| 305 | goto out; | ||
| 299 | } | 306 | } |
| 307 | err = 0; | ||
| 308 | |||
| 309 | out_put_forget: | ||
| 300 | fuse_put_request(fc, forget_req); | 310 | fuse_put_request(fc, forget_req); |
| 301 | if (err && err != -ENOENT) | 311 | out: |
| 302 | return ERR_PTR(err); | 312 | return err; |
| 313 | } | ||
| 314 | |||
| 315 | static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | ||
| 316 | struct nameidata *nd) | ||
| 317 | { | ||
| 318 | int err; | ||
| 319 | struct fuse_entry_out outarg; | ||
| 320 | struct inode *inode; | ||
| 321 | struct dentry *newent; | ||
| 322 | struct fuse_conn *fc = get_fuse_conn(dir); | ||
| 323 | bool outarg_valid = true; | ||
| 324 | |||
| 325 | err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, | ||
| 326 | &outarg, &inode); | ||
| 327 | if (err == -ENOENT) { | ||
| 328 | outarg_valid = false; | ||
| 329 | err = 0; | ||
| 330 | } | ||
| 331 | if (err) | ||
| 332 | goto out_err; | ||
| 333 | |||
| 334 | err = -EIO; | ||
| 335 | if (inode && get_node_id(inode) == FUSE_ROOT_ID) | ||
| 336 | goto out_iput; | ||
| 303 | 337 | ||
| 304 | if (inode && S_ISDIR(inode->i_mode)) { | 338 | if (inode && S_ISDIR(inode->i_mode)) { |
| 305 | mutex_lock(&fc->inst_mutex); | 339 | mutex_lock(&fc->inst_mutex); |
| 306 | err = fuse_d_add_directory(entry, inode); | 340 | newent = fuse_d_add_directory(entry, inode); |
| 307 | mutex_unlock(&fc->inst_mutex); | 341 | mutex_unlock(&fc->inst_mutex); |
| 308 | if (err) { | 342 | err = PTR_ERR(newent); |
| 309 | iput(inode); | 343 | if (IS_ERR(newent)) |
| 310 | return ERR_PTR(err); | 344 | goto out_iput; |
| 311 | } | 345 | } else { |
| 312 | } else | 346 | newent = d_splice_alias(inode, entry); |
| 313 | d_add(entry, inode); | 347 | } |
| 314 | 348 | ||
| 349 | entry = newent ? newent : entry; | ||
| 315 | entry->d_op = &fuse_dentry_operations; | 350 | entry->d_op = &fuse_dentry_operations; |
| 316 | if (!err) | 351 | if (outarg_valid) |
| 317 | fuse_change_entry_timeout(entry, &outarg); | 352 | fuse_change_entry_timeout(entry, &outarg); |
| 318 | else | 353 | else |
| 319 | fuse_invalidate_entry_cache(entry); | 354 | fuse_invalidate_entry_cache(entry); |
| 320 | return NULL; | 355 | |
| 356 | return newent; | ||
| 357 | |||
| 358 | out_iput: | ||
| 359 | iput(inode); | ||
| 360 | out_err: | ||
| 361 | return ERR_PTR(err); | ||
| 321 | } | 362 | } |
| 322 | 363 | ||
| 323 | /* | 364 | /* |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 8092f0d9fd1f..67ff2c6a8f63 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -1341,6 +1341,11 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
| 1341 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; | 1341 | pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; |
| 1342 | int err; | 1342 | int err; |
| 1343 | 1343 | ||
| 1344 | if (fl->fl_lmops && fl->fl_lmops->fl_grant) { | ||
| 1345 | /* NLM needs asynchronous locks, which we don't support yet */ | ||
| 1346 | return -ENOLCK; | ||
| 1347 | } | ||
| 1348 | |||
| 1344 | /* Unlock on close is handled by the flush method */ | 1349 | /* Unlock on close is handled by the flush method */ |
| 1345 | if (fl->fl_flags & FL_CLOSE) | 1350 | if (fl->fl_flags & FL_CLOSE) |
| 1346 | return 0; | 1351 | return 0; |
| @@ -1365,7 +1370,9 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) | |||
| 1365 | struct fuse_conn *fc = get_fuse_conn(inode); | 1370 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 1366 | int err; | 1371 | int err; |
| 1367 | 1372 | ||
| 1368 | if (cmd == F_GETLK) { | 1373 | if (cmd == F_CANCELLK) { |
| 1374 | err = 0; | ||
| 1375 | } else if (cmd == F_GETLK) { | ||
| 1369 | if (fc->no_lock) { | 1376 | if (fc->no_lock) { |
| 1370 | posix_test_lock(file, fl); | 1377 | posix_test_lock(file, fl); |
| 1371 | err = 0; | 1378 | err = 0; |
| @@ -1373,7 +1380,7 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) | |||
| 1373 | err = fuse_getlk(file, fl); | 1380 | err = fuse_getlk(file, fl); |
| 1374 | } else { | 1381 | } else { |
| 1375 | if (fc->no_lock) | 1382 | if (fc->no_lock) |
| 1376 | err = posix_lock_file_wait(file, fl); | 1383 | err = posix_lock_file(file, fl, NULL); |
| 1377 | else | 1384 | else |
| 1378 | err = fuse_setlk(file, fl, 0); | 1385 | err = fuse_setlk(file, fl, 0); |
| 1379 | } | 1386 | } |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index bae948657c4f..3a876076bdd1 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -363,6 +363,9 @@ struct fuse_conn { | |||
| 363 | /** Do not send separate SETATTR request before open(O_TRUNC) */ | 363 | /** Do not send separate SETATTR request before open(O_TRUNC) */ |
| 364 | unsigned atomic_o_trunc : 1; | 364 | unsigned atomic_o_trunc : 1; |
| 365 | 365 | ||
| 366 | /** Filesystem supports NFS exporting. Only set in INIT */ | ||
| 367 | unsigned export_support : 1; | ||
| 368 | |||
| 366 | /* | 369 | /* |
| 367 | * The following bitfields are only for optimization purposes | 370 | * The following bitfields are only for optimization purposes |
| 368 | * and hence races in setting them will not cause malfunction | 371 | * and hence races in setting them will not cause malfunction |
| @@ -464,6 +467,8 @@ static inline u64 get_node_id(struct inode *inode) | |||
| 464 | /** Device operations */ | 467 | /** Device operations */ |
| 465 | extern const struct file_operations fuse_dev_operations; | 468 | extern const struct file_operations fuse_dev_operations; |
| 466 | 469 | ||
| 470 | extern struct dentry_operations fuse_dentry_operations; | ||
| 471 | |||
| 467 | /** | 472 | /** |
| 468 | * Get a filled in inode | 473 | * Get a filled in inode |
| 469 | */ | 474 | */ |
| @@ -471,6 +476,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, | |||
| 471 | int generation, struct fuse_attr *attr, | 476 | int generation, struct fuse_attr *attr, |
| 472 | u64 attr_valid, u64 attr_version); | 477 | u64 attr_valid, u64 attr_version); |
| 473 | 478 | ||
| 479 | int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | ||
| 480 | struct fuse_entry_out *outarg, struct inode **inode); | ||
| 481 | |||
| 474 | /** | 482 | /** |
| 475 | * Send FORGET command | 483 | * Send FORGET command |
| 476 | */ | 484 | */ |
| @@ -604,6 +612,8 @@ void fuse_abort_conn(struct fuse_conn *fc); | |||
| 604 | */ | 612 | */ |
| 605 | void fuse_invalidate_attr(struct inode *inode); | 613 | void fuse_invalidate_attr(struct inode *inode); |
| 606 | 614 | ||
| 615 | void fuse_invalidate_entry_cache(struct dentry *entry); | ||
| 616 | |||
| 607 | /** | 617 | /** |
| 608 | * Acquire reference to fuse_conn | 618 | * Acquire reference to fuse_conn |
| 609 | */ | 619 | */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 3141690558c8..7d2f7d6e22e2 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/statfs.h> | 18 | #include <linux/statfs.h> |
| 19 | #include <linux/random.h> | 19 | #include <linux/random.h> |
| 20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 21 | #include <linux/exportfs.h> | ||
| 21 | 22 | ||
| 22 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); | 23 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); |
| 23 | MODULE_DESCRIPTION("Filesystem in Userspace"); | 24 | MODULE_DESCRIPTION("Filesystem in Userspace"); |
| @@ -552,6 +553,174 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode) | |||
| 552 | return fuse_iget(sb, 1, 0, &attr, 0, 0); | 553 | return fuse_iget(sb, 1, 0, &attr, 0, 0); |
| 553 | } | 554 | } |
| 554 | 555 | ||
| 556 | struct fuse_inode_handle | ||
| 557 | { | ||
| 558 | u64 nodeid; | ||
| 559 | u32 generation; | ||
| 560 | }; | ||
| 561 | |||
| 562 | static struct dentry *fuse_get_dentry(struct super_block *sb, | ||
| 563 | struct fuse_inode_handle *handle) | ||
| 564 | { | ||
| 565 | struct fuse_conn *fc = get_fuse_conn_super(sb); | ||
| 566 | struct inode *inode; | ||
| 567 | struct dentry *entry; | ||
| 568 | int err = -ESTALE; | ||
| 569 | |||
| 570 | if (handle->nodeid == 0) | ||
| 571 | goto out_err; | ||
| 572 | |||
| 573 | inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); | ||
| 574 | if (!inode) { | ||
| 575 | struct fuse_entry_out outarg; | ||
| 576 | struct qstr name; | ||
| 577 | |||
| 578 | if (!fc->export_support) | ||
| 579 | goto out_err; | ||
| 580 | |||
| 581 | name.len = 1; | ||
| 582 | name.name = "."; | ||
| 583 | err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, | ||
| 584 | &inode); | ||
| 585 | if (err && err != -ENOENT) | ||
| 586 | goto out_err; | ||
| 587 | if (err || !inode) { | ||
| 588 | err = -ESTALE; | ||
| 589 | goto out_err; | ||
| 590 | } | ||
| 591 | err = -EIO; | ||
| 592 | if (get_node_id(inode) != handle->nodeid) | ||
| 593 | goto out_iput; | ||
| 594 | } | ||
| 595 | err = -ESTALE; | ||
| 596 | if (inode->i_generation != handle->generation) | ||
| 597 | goto out_iput; | ||
| 598 | |||
| 599 | entry = d_alloc_anon(inode); | ||
| 600 | err = -ENOMEM; | ||
| 601 | if (!entry) | ||
| 602 | goto out_iput; | ||
| 603 | |||
| 604 | if (get_node_id(inode) != FUSE_ROOT_ID) { | ||
| 605 | entry->d_op = &fuse_dentry_operations; | ||
| 606 | fuse_invalidate_entry_cache(entry); | ||
| 607 | } | ||
| 608 | |||
| 609 | return entry; | ||
| 610 | |||
| 611 | out_iput: | ||
| 612 | iput(inode); | ||
| 613 | out_err: | ||
| 614 | return ERR_PTR(err); | ||
| 615 | } | ||
| 616 | |||
| 617 | static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | ||
| 618 | int connectable) | ||
| 619 | { | ||
| 620 | struct inode *inode = dentry->d_inode; | ||
| 621 | bool encode_parent = connectable && !S_ISDIR(inode->i_mode); | ||
| 622 | int len = encode_parent ? 6 : 3; | ||
| 623 | u64 nodeid; | ||
| 624 | u32 generation; | ||
| 625 | |||
| 626 | if (*max_len < len) | ||
| 627 | return 255; | ||
| 628 | |||
| 629 | nodeid = get_fuse_inode(inode)->nodeid; | ||
| 630 | generation = inode->i_generation; | ||
| 631 | |||
| 632 | fh[0] = (u32)(nodeid >> 32); | ||
| 633 | fh[1] = (u32)(nodeid & 0xffffffff); | ||
| 634 | fh[2] = generation; | ||
| 635 | |||
| 636 | if (encode_parent) { | ||
| 637 | struct inode *parent; | ||
| 638 | |||
| 639 | spin_lock(&dentry->d_lock); | ||
| 640 | parent = dentry->d_parent->d_inode; | ||
| 641 | nodeid = get_fuse_inode(parent)->nodeid; | ||
| 642 | generation = parent->i_generation; | ||
| 643 | spin_unlock(&dentry->d_lock); | ||
| 644 | |||
| 645 | fh[3] = (u32)(nodeid >> 32); | ||
| 646 | fh[4] = (u32)(nodeid & 0xffffffff); | ||
| 647 | fh[5] = generation; | ||
| 648 | } | ||
| 649 | |||
| 650 | *max_len = len; | ||
| 651 | return encode_parent ? 0x82 : 0x81; | ||
| 652 | } | ||
| 653 | |||
| 654 | static struct dentry *fuse_fh_to_dentry(struct super_block *sb, | ||
| 655 | struct fid *fid, int fh_len, int fh_type) | ||
| 656 | { | ||
| 657 | struct fuse_inode_handle handle; | ||
| 658 | |||
| 659 | if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) | ||
| 660 | return NULL; | ||
| 661 | |||
| 662 | handle.nodeid = (u64) fid->raw[0] << 32; | ||
| 663 | handle.nodeid |= (u64) fid->raw[1]; | ||
| 664 | handle.generation = fid->raw[2]; | ||
| 665 | return fuse_get_dentry(sb, &handle); | ||
| 666 | } | ||
| 667 | |||
| 668 | static struct dentry *fuse_fh_to_parent(struct super_block *sb, | ||
| 669 | struct fid *fid, int fh_len, int fh_type) | ||
| 670 | { | ||
| 671 | struct fuse_inode_handle parent; | ||
| 672 | |||
| 673 | if (fh_type != 0x82 || fh_len < 6) | ||
| 674 | return NULL; | ||
| 675 | |||
| 676 | parent.nodeid = (u64) fid->raw[3] << 32; | ||
| 677 | parent.nodeid |= (u64) fid->raw[4]; | ||
| 678 | parent.generation = fid->raw[5]; | ||
| 679 | return fuse_get_dentry(sb, &parent); | ||
| 680 | } | ||
| 681 | |||
| 682 | static struct dentry *fuse_get_parent(struct dentry *child) | ||
| 683 | { | ||
| 684 | struct inode *child_inode = child->d_inode; | ||
| 685 | struct fuse_conn *fc = get_fuse_conn(child_inode); | ||
| 686 | struct inode *inode; | ||
| 687 | struct dentry *parent; | ||
| 688 | struct fuse_entry_out outarg; | ||
| 689 | struct qstr name; | ||
| 690 | int err; | ||
| 691 | |||
| 692 | if (!fc->export_support) | ||
| 693 | return ERR_PTR(-ESTALE); | ||
| 694 | |||
| 695 | name.len = 2; | ||
| 696 | name.name = ".."; | ||
| 697 | err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), | ||
| 698 | &name, &outarg, &inode); | ||
| 699 | if (err && err != -ENOENT) | ||
| 700 | return ERR_PTR(err); | ||
| 701 | if (err || !inode) | ||
| 702 | return ERR_PTR(-ESTALE); | ||
| 703 | |||
| 704 | parent = d_alloc_anon(inode); | ||
| 705 | if (!parent) { | ||
| 706 | iput(inode); | ||
| 707 | return ERR_PTR(-ENOMEM); | ||
| 708 | } | ||
| 709 | if (get_node_id(inode) != FUSE_ROOT_ID) { | ||
| 710 | parent->d_op = &fuse_dentry_operations; | ||
| 711 | fuse_invalidate_entry_cache(parent); | ||
| 712 | } | ||
| 713 | |||
| 714 | return parent; | ||
| 715 | } | ||
| 716 | |||
| 717 | static const struct export_operations fuse_export_operations = { | ||
| 718 | .fh_to_dentry = fuse_fh_to_dentry, | ||
| 719 | .fh_to_parent = fuse_fh_to_parent, | ||
| 720 | .encode_fh = fuse_encode_fh, | ||
| 721 | .get_parent = fuse_get_parent, | ||
| 722 | }; | ||
| 723 | |||
| 555 | static const struct super_operations fuse_super_operations = { | 724 | static const struct super_operations fuse_super_operations = { |
| 556 | .alloc_inode = fuse_alloc_inode, | 725 | .alloc_inode = fuse_alloc_inode, |
| 557 | .destroy_inode = fuse_destroy_inode, | 726 | .destroy_inode = fuse_destroy_inode, |
| @@ -581,6 +750,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
| 581 | fc->no_lock = 1; | 750 | fc->no_lock = 1; |
| 582 | if (arg->flags & FUSE_ATOMIC_O_TRUNC) | 751 | if (arg->flags & FUSE_ATOMIC_O_TRUNC) |
| 583 | fc->atomic_o_trunc = 1; | 752 | fc->atomic_o_trunc = 1; |
| 753 | if (arg->minor >= 9) { | ||
| 754 | /* LOOKUP has dependency on proto version */ | ||
| 755 | if (arg->flags & FUSE_EXPORT_SUPPORT) | ||
| 756 | fc->export_support = 1; | ||
| 757 | } | ||
| 584 | if (arg->flags & FUSE_BIG_WRITES) | 758 | if (arg->flags & FUSE_BIG_WRITES) |
| 585 | fc->big_writes = 1; | 759 | fc->big_writes = 1; |
| 586 | } else { | 760 | } else { |
| @@ -607,7 +781,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
| 607 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 781 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
| 608 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; | 782 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
| 609 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | | 783 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | |
| 610 | FUSE_BIG_WRITES; | 784 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES; |
| 611 | req->in.h.opcode = FUSE_INIT; | 785 | req->in.h.opcode = FUSE_INIT; |
| 612 | req->in.numargs = 1; | 786 | req->in.numargs = 1; |
| 613 | req->in.args[0].size = sizeof(*arg); | 787 | req->in.args[0].size = sizeof(*arg); |
| @@ -652,6 +826,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
| 652 | sb->s_magic = FUSE_SUPER_MAGIC; | 826 | sb->s_magic = FUSE_SUPER_MAGIC; |
| 653 | sb->s_op = &fuse_super_operations; | 827 | sb->s_op = &fuse_super_operations; |
| 654 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 828 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
| 829 | sb->s_export_op = &fuse_export_operations; | ||
| 655 | 830 | ||
| 656 | file = fget(d.fd); | 831 | file = fget(d.fd); |
| 657 | if (!file) | 832 | if (!file) |
diff --git a/fs/hfs/bitmap.c b/fs/hfs/bitmap.c index 24e75798ddf0..c6e97366e8ac 100644 --- a/fs/hfs/bitmap.c +++ b/fs/hfs/bitmap.c | |||
| @@ -145,7 +145,7 @@ u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits) | |||
| 145 | if (!*num_bits) | 145 | if (!*num_bits) |
| 146 | return 0; | 146 | return 0; |
| 147 | 147 | ||
| 148 | down(&HFS_SB(sb)->bitmap_lock); | 148 | mutex_lock(&HFS_SB(sb)->bitmap_lock); |
| 149 | bitmap = HFS_SB(sb)->bitmap; | 149 | bitmap = HFS_SB(sb)->bitmap; |
| 150 | 150 | ||
| 151 | pos = hfs_find_set_zero_bits(bitmap, HFS_SB(sb)->fs_ablocks, goal, num_bits); | 151 | pos = hfs_find_set_zero_bits(bitmap, HFS_SB(sb)->fs_ablocks, goal, num_bits); |
| @@ -162,7 +162,7 @@ u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits) | |||
| 162 | HFS_SB(sb)->free_ablocks -= *num_bits; | 162 | HFS_SB(sb)->free_ablocks -= *num_bits; |
| 163 | hfs_bitmap_dirty(sb); | 163 | hfs_bitmap_dirty(sb); |
| 164 | out: | 164 | out: |
| 165 | up(&HFS_SB(sb)->bitmap_lock); | 165 | mutex_unlock(&HFS_SB(sb)->bitmap_lock); |
| 166 | return pos; | 166 | return pos; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| @@ -205,7 +205,7 @@ int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count) | |||
| 205 | if ((start + count) > HFS_SB(sb)->fs_ablocks) | 205 | if ((start + count) > HFS_SB(sb)->fs_ablocks) |
| 206 | return -2; | 206 | return -2; |
| 207 | 207 | ||
| 208 | down(&HFS_SB(sb)->bitmap_lock); | 208 | mutex_lock(&HFS_SB(sb)->bitmap_lock); |
| 209 | /* bitmap is always on a 32-bit boundary */ | 209 | /* bitmap is always on a 32-bit boundary */ |
| 210 | curr = HFS_SB(sb)->bitmap + (start / 32); | 210 | curr = HFS_SB(sb)->bitmap + (start / 32); |
| 211 | len = count; | 211 | len = count; |
| @@ -236,7 +236,7 @@ int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count) | |||
| 236 | } | 236 | } |
| 237 | out: | 237 | out: |
| 238 | HFS_SB(sb)->free_ablocks += len; | 238 | HFS_SB(sb)->free_ablocks += len; |
| 239 | up(&HFS_SB(sb)->bitmap_lock); | 239 | mutex_unlock(&HFS_SB(sb)->bitmap_lock); |
| 240 | hfs_bitmap_dirty(sb); | 240 | hfs_bitmap_dirty(sb); |
| 241 | 241 | ||
| 242 | return 0; | 242 | return 0; |
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c index f6621a785202..9b9d6395bad3 100644 --- a/fs/hfs/btree.c +++ b/fs/hfs/btree.c | |||
| @@ -40,7 +40,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke | |||
| 40 | { | 40 | { |
| 41 | struct hfs_mdb *mdb = HFS_SB(sb)->mdb; | 41 | struct hfs_mdb *mdb = HFS_SB(sb)->mdb; |
| 42 | HFS_I(tree->inode)->flags = 0; | 42 | HFS_I(tree->inode)->flags = 0; |
| 43 | init_MUTEX(&HFS_I(tree->inode)->extents_lock); | 43 | mutex_init(&HFS_I(tree->inode)->extents_lock); |
| 44 | switch (id) { | 44 | switch (id) { |
| 45 | case HFS_EXT_CNID: | 45 | case HFS_EXT_CNID: |
| 46 | hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize, | 46 | hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize, |
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index c176f67ba0a5..2c16316d2917 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c | |||
| @@ -343,16 +343,16 @@ int hfs_get_block(struct inode *inode, sector_t block, | |||
| 343 | goto done; | 343 | goto done; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | down(&HFS_I(inode)->extents_lock); | 346 | mutex_lock(&HFS_I(inode)->extents_lock); |
| 347 | res = hfs_ext_read_extent(inode, ablock); | 347 | res = hfs_ext_read_extent(inode, ablock); |
| 348 | if (!res) | 348 | if (!res) |
| 349 | dblock = hfs_ext_find_block(HFS_I(inode)->cached_extents, | 349 | dblock = hfs_ext_find_block(HFS_I(inode)->cached_extents, |
| 350 | ablock - HFS_I(inode)->cached_start); | 350 | ablock - HFS_I(inode)->cached_start); |
| 351 | else { | 351 | else { |
| 352 | up(&HFS_I(inode)->extents_lock); | 352 | mutex_unlock(&HFS_I(inode)->extents_lock); |
| 353 | return -EIO; | 353 | return -EIO; |
| 354 | } | 354 | } |
| 355 | up(&HFS_I(inode)->extents_lock); | 355 | mutex_unlock(&HFS_I(inode)->extents_lock); |
| 356 | 356 | ||
| 357 | done: | 357 | done: |
| 358 | map_bh(bh_result, sb, HFS_SB(sb)->fs_start + | 358 | map_bh(bh_result, sb, HFS_SB(sb)->fs_start + |
| @@ -375,7 +375,7 @@ int hfs_extend_file(struct inode *inode) | |||
| 375 | u32 start, len, goal; | 375 | u32 start, len, goal; |
| 376 | int res; | 376 | int res; |
| 377 | 377 | ||
| 378 | down(&HFS_I(inode)->extents_lock); | 378 | mutex_lock(&HFS_I(inode)->extents_lock); |
| 379 | if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks) | 379 | if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks) |
| 380 | goal = hfs_ext_lastblock(HFS_I(inode)->first_extents); | 380 | goal = hfs_ext_lastblock(HFS_I(inode)->first_extents); |
| 381 | else { | 381 | else { |
| @@ -425,7 +425,7 @@ int hfs_extend_file(struct inode *inode) | |||
| 425 | goto insert_extent; | 425 | goto insert_extent; |
| 426 | } | 426 | } |
| 427 | out: | 427 | out: |
| 428 | up(&HFS_I(inode)->extents_lock); | 428 | mutex_unlock(&HFS_I(inode)->extents_lock); |
| 429 | if (!res) { | 429 | if (!res) { |
| 430 | HFS_I(inode)->alloc_blocks += len; | 430 | HFS_I(inode)->alloc_blocks += len; |
| 431 | mark_inode_dirty(inode); | 431 | mark_inode_dirty(inode); |
| @@ -487,7 +487,7 @@ void hfs_file_truncate(struct inode *inode) | |||
| 487 | if (blk_cnt == alloc_cnt) | 487 | if (blk_cnt == alloc_cnt) |
| 488 | goto out; | 488 | goto out; |
| 489 | 489 | ||
| 490 | down(&HFS_I(inode)->extents_lock); | 490 | mutex_lock(&HFS_I(inode)->extents_lock); |
| 491 | hfs_find_init(HFS_SB(sb)->ext_tree, &fd); | 491 | hfs_find_init(HFS_SB(sb)->ext_tree, &fd); |
| 492 | while (1) { | 492 | while (1) { |
| 493 | if (alloc_cnt == HFS_I(inode)->first_blocks) { | 493 | if (alloc_cnt == HFS_I(inode)->first_blocks) { |
| @@ -514,7 +514,7 @@ void hfs_file_truncate(struct inode *inode) | |||
| 514 | hfs_brec_remove(&fd); | 514 | hfs_brec_remove(&fd); |
| 515 | } | 515 | } |
| 516 | hfs_find_exit(&fd); | 516 | hfs_find_exit(&fd); |
| 517 | up(&HFS_I(inode)->extents_lock); | 517 | mutex_unlock(&HFS_I(inode)->extents_lock); |
| 518 | 518 | ||
| 519 | HFS_I(inode)->alloc_blocks = blk_cnt; | 519 | HFS_I(inode)->alloc_blocks = blk_cnt; |
| 520 | out: | 520 | out: |
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 147374b6f675..9955232fdf8c 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | #include <linux/mutex.h> | ||
| 14 | #include <linux/buffer_head.h> | 15 | #include <linux/buffer_head.h> |
| 15 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
| 16 | 17 | ||
| @@ -53,7 +54,7 @@ struct hfs_inode_info { | |||
| 53 | struct list_head open_dir_list; | 54 | struct list_head open_dir_list; |
| 54 | struct inode *rsrc_inode; | 55 | struct inode *rsrc_inode; |
| 55 | 56 | ||
| 56 | struct semaphore extents_lock; | 57 | struct mutex extents_lock; |
| 57 | 58 | ||
| 58 | u16 alloc_blocks, clump_blocks; | 59 | u16 alloc_blocks, clump_blocks; |
| 59 | sector_t fs_blocks; | 60 | sector_t fs_blocks; |
| @@ -139,7 +140,7 @@ struct hfs_sb_info { | |||
| 139 | 140 | ||
| 140 | struct nls_table *nls_io, *nls_disk; | 141 | struct nls_table *nls_io, *nls_disk; |
| 141 | 142 | ||
| 142 | struct semaphore bitmap_lock; | 143 | struct mutex bitmap_lock; |
| 143 | 144 | ||
| 144 | unsigned long flags; | 145 | unsigned long flags; |
| 145 | 146 | ||
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 97f8446c4ff4..dc4ec640e875 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
| @@ -150,7 +150,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode) | |||
| 150 | if (!inode) | 150 | if (!inode) |
| 151 | return NULL; | 151 | return NULL; |
| 152 | 152 | ||
| 153 | init_MUTEX(&HFS_I(inode)->extents_lock); | 153 | mutex_init(&HFS_I(inode)->extents_lock); |
| 154 | INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); | 154 | INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); |
| 155 | hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name); | 155 | hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name); |
| 156 | inode->i_ino = HFS_SB(sb)->next_id++; | 156 | inode->i_ino = HFS_SB(sb)->next_id++; |
| @@ -281,7 +281,7 @@ static int hfs_read_inode(struct inode *inode, void *data) | |||
| 281 | 281 | ||
| 282 | HFS_I(inode)->flags = 0; | 282 | HFS_I(inode)->flags = 0; |
| 283 | HFS_I(inode)->rsrc_inode = NULL; | 283 | HFS_I(inode)->rsrc_inode = NULL; |
| 284 | init_MUTEX(&HFS_I(inode)->extents_lock); | 284 | mutex_init(&HFS_I(inode)->extents_lock); |
| 285 | INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); | 285 | INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list); |
| 286 | 286 | ||
| 287 | /* Initialize the inode */ | 287 | /* Initialize the inode */ |
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 8cf67974adf6..ac2ec5ef66e4 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
| @@ -372,7 +372,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 372 | 372 | ||
| 373 | sb->s_op = &hfs_super_operations; | 373 | sb->s_op = &hfs_super_operations; |
| 374 | sb->s_flags |= MS_NODIRATIME; | 374 | sb->s_flags |= MS_NODIRATIME; |
| 375 | init_MUTEX(&sbi->bitmap_lock); | 375 | mutex_init(&sbi->bitmap_lock); |
| 376 | 376 | ||
| 377 | res = hfs_mdb_get(sb); | 377 | res = hfs_mdb_get(sb); |
| 378 | if (res) { | 378 | if (res) { |
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 12e899cd7886..fec8f61227ff 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c | |||
| @@ -199,16 +199,16 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock, | |||
| 199 | goto done; | 199 | goto done; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | down(&HFSPLUS_I(inode).extents_lock); | 202 | mutex_lock(&HFSPLUS_I(inode).extents_lock); |
| 203 | res = hfsplus_ext_read_extent(inode, ablock); | 203 | res = hfsplus_ext_read_extent(inode, ablock); |
| 204 | if (!res) { | 204 | if (!res) { |
| 205 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - | 205 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - |
| 206 | HFSPLUS_I(inode).cached_start); | 206 | HFSPLUS_I(inode).cached_start); |
| 207 | } else { | 207 | } else { |
| 208 | up(&HFSPLUS_I(inode).extents_lock); | 208 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); |
| 209 | return -EIO; | 209 | return -EIO; |
| 210 | } | 210 | } |
| 211 | up(&HFSPLUS_I(inode).extents_lock); | 211 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); |
| 212 | 212 | ||
| 213 | done: | 213 | done: |
| 214 | dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); | 214 | dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); |
| @@ -355,7 +355,7 @@ int hfsplus_file_extend(struct inode *inode) | |||
| 355 | return -ENOSPC; | 355 | return -ENOSPC; |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | down(&HFSPLUS_I(inode).extents_lock); | 358 | mutex_lock(&HFSPLUS_I(inode).extents_lock); |
| 359 | if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks) | 359 | if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks) |
| 360 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents); | 360 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents); |
| 361 | else { | 361 | else { |
| @@ -408,7 +408,7 @@ int hfsplus_file_extend(struct inode *inode) | |||
| 408 | goto insert_extent; | 408 | goto insert_extent; |
| 409 | } | 409 | } |
| 410 | out: | 410 | out: |
| 411 | up(&HFSPLUS_I(inode).extents_lock); | 411 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); |
| 412 | if (!res) { | 412 | if (!res) { |
| 413 | HFSPLUS_I(inode).alloc_blocks += len; | 413 | HFSPLUS_I(inode).alloc_blocks += len; |
| 414 | mark_inode_dirty(inode); | 414 | mark_inode_dirty(inode); |
| @@ -465,7 +465,7 @@ void hfsplus_file_truncate(struct inode *inode) | |||
| 465 | if (blk_cnt == alloc_cnt) | 465 | if (blk_cnt == alloc_cnt) |
| 466 | goto out; | 466 | goto out; |
| 467 | 467 | ||
| 468 | down(&HFSPLUS_I(inode).extents_lock); | 468 | mutex_lock(&HFSPLUS_I(inode).extents_lock); |
| 469 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); | 469 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); |
| 470 | while (1) { | 470 | while (1) { |
| 471 | if (alloc_cnt == HFSPLUS_I(inode).first_blocks) { | 471 | if (alloc_cnt == HFSPLUS_I(inode).first_blocks) { |
| @@ -492,7 +492,7 @@ void hfsplus_file_truncate(struct inode *inode) | |||
| 492 | hfs_brec_remove(&fd); | 492 | hfs_brec_remove(&fd); |
| 493 | } | 493 | } |
| 494 | hfs_find_exit(&fd); | 494 | hfs_find_exit(&fd); |
| 495 | up(&HFSPLUS_I(inode).extents_lock); | 495 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); |
| 496 | 496 | ||
| 497 | HFSPLUS_I(inode).alloc_blocks = blk_cnt; | 497 | HFSPLUS_I(inode).alloc_blocks = blk_cnt; |
| 498 | out: | 498 | out: |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 9e59537b43d5..f027a905225f 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #define _LINUX_HFSPLUS_FS_H | 11 | #define _LINUX_HFSPLUS_FS_H |
| 12 | 12 | ||
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/mutex.h> | ||
| 14 | #include <linux/buffer_head.h> | 15 | #include <linux/buffer_head.h> |
| 15 | #include "hfsplus_raw.h" | 16 | #include "hfsplus_raw.h" |
| 16 | 17 | ||
| @@ -154,7 +155,7 @@ struct hfsplus_sb_info { | |||
| 154 | 155 | ||
| 155 | 156 | ||
| 156 | struct hfsplus_inode_info { | 157 | struct hfsplus_inode_info { |
| 157 | struct semaphore extents_lock; | 158 | struct mutex extents_lock; |
| 158 | u32 clump_blocks, alloc_blocks; | 159 | u32 clump_blocks, alloc_blocks; |
| 159 | sector_t fs_blocks; | 160 | sector_t fs_blocks; |
| 160 | /* Allocation extents from catalog record or volume header */ | 161 | /* Allocation extents from catalog record or volume header */ |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 67e1c8b467c4..cc3b5e24339b 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
| @@ -163,7 +163,7 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
| 163 | 163 | ||
| 164 | inode->i_ino = dir->i_ino; | 164 | inode->i_ino = dir->i_ino; |
| 165 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 165 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); |
| 166 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | 166 | mutex_init(&HFSPLUS_I(inode).extents_lock); |
| 167 | HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; | 167 | HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; |
| 168 | 168 | ||
| 169 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 169 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); |
| @@ -316,7 +316,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode) | |||
| 316 | inode->i_nlink = 1; | 316 | inode->i_nlink = 1; |
| 317 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 317 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
| 318 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 318 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); |
| 319 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | 319 | mutex_init(&HFSPLUS_I(inode).extents_lock); |
| 320 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | 320 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); |
| 321 | HFSPLUS_I(inode).flags = 0; | 321 | HFSPLUS_I(inode).flags = 0; |
| 322 | memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec)); | 322 | memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec)); |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index ce97a54518d8..3859118531c7 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
| @@ -34,7 +34,7 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) | |||
| 34 | return inode; | 34 | return inode; |
| 35 | 35 | ||
| 36 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 36 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); |
| 37 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | 37 | mutex_init(&HFSPLUS_I(inode).extents_lock); |
| 38 | HFSPLUS_I(inode).flags = 0; | 38 | HFSPLUS_I(inode).flags = 0; |
| 39 | HFSPLUS_I(inode).rsrc_inode = NULL; | 39 | HFSPLUS_I(inode).rsrc_inode = NULL; |
| 40 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | 40 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); |
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 6bd48f0a7047..c2fb2dd0131f 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c | |||
| @@ -209,6 +209,11 @@ repeat: | |||
| 209 | 209 | ||
| 210 | while (rs.len > 2) { /* There may be one byte for padding somewhere */ | 210 | while (rs.len > 2) { /* There may be one byte for padding somewhere */ |
| 211 | rr = (struct rock_ridge *)rs.chr; | 211 | rr = (struct rock_ridge *)rs.chr; |
| 212 | /* | ||
| 213 | * Ignore rock ridge info if rr->len is out of range, but | ||
| 214 | * don't return -EIO because that would make the file | ||
| 215 | * invisible. | ||
| 216 | */ | ||
| 212 | if (rr->len < 3) | 217 | if (rr->len < 3) |
| 213 | goto out; /* Something got screwed up here */ | 218 | goto out; /* Something got screwed up here */ |
| 214 | sig = isonum_721(rs.chr); | 219 | sig = isonum_721(rs.chr); |
| @@ -216,8 +221,12 @@ repeat: | |||
| 216 | goto eio; | 221 | goto eio; |
| 217 | rs.chr += rr->len; | 222 | rs.chr += rr->len; |
| 218 | rs.len -= rr->len; | 223 | rs.len -= rr->len; |
| 224 | /* | ||
| 225 | * As above, just ignore the rock ridge info if rr->len | ||
| 226 | * is bogus. | ||
| 227 | */ | ||
| 219 | if (rs.len < 0) | 228 | if (rs.len < 0) |
| 220 | goto eio; /* corrupted isofs */ | 229 | goto out; /* Something got screwed up here */ |
| 221 | 230 | ||
| 222 | switch (sig) { | 231 | switch (sig) { |
| 223 | case SIG('R', 'R'): | 232 | case SIG('R', 'R'): |
| @@ -307,6 +316,11 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, | |||
| 307 | repeat: | 316 | repeat: |
| 308 | while (rs.len > 2) { /* There may be one byte for padding somewhere */ | 317 | while (rs.len > 2) { /* There may be one byte for padding somewhere */ |
| 309 | rr = (struct rock_ridge *)rs.chr; | 318 | rr = (struct rock_ridge *)rs.chr; |
| 319 | /* | ||
| 320 | * Ignore rock ridge info if rr->len is out of range, but | ||
| 321 | * don't return -EIO because that would make the file | ||
| 322 | * invisible. | ||
| 323 | */ | ||
| 310 | if (rr->len < 3) | 324 | if (rr->len < 3) |
| 311 | goto out; /* Something got screwed up here */ | 325 | goto out; /* Something got screwed up here */ |
| 312 | sig = isonum_721(rs.chr); | 326 | sig = isonum_721(rs.chr); |
| @@ -314,8 +328,12 @@ repeat: | |||
| 314 | goto eio; | 328 | goto eio; |
| 315 | rs.chr += rr->len; | 329 | rs.chr += rr->len; |
| 316 | rs.len -= rr->len; | 330 | rs.len -= rr->len; |
| 331 | /* | ||
| 332 | * As above, just ignore the rock ridge info if rr->len | ||
| 333 | * is bogus. | ||
| 334 | */ | ||
| 317 | if (rs.len < 0) | 335 | if (rs.len < 0) |
| 318 | goto eio; /* corrupted isofs */ | 336 | goto out; /* Something got screwed up here */ |
| 319 | 337 | ||
| 320 | switch (sig) { | 338 | switch (sig) { |
| 321 | #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ | 339 | #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 5a8ca61498ca..2eccbfaa1d48 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
| @@ -36,7 +36,7 @@ static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate) | |||
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * When an ext3-ordered file is truncated, it is possible that many pages are | 38 | * When an ext3-ordered file is truncated, it is possible that many pages are |
| 39 | * not sucessfully freed, because they are attached to a committing transaction. | 39 | * not successfully freed, because they are attached to a committing transaction. |
| 40 | * After the transaction commits, these pages are left on the LRU, with no | 40 | * After the transaction commits, these pages are left on the LRU, with no |
| 41 | * ->mapping, and with attached buffers. These pages are trivially reclaimable | 41 | * ->mapping, and with attached buffers. These pages are trivially reclaimable |
| 42 | * by the VM, but their apparent absence upsets the VM accounting, and it makes | 42 | * by the VM, but their apparent absence upsets the VM accounting, and it makes |
| @@ -45,8 +45,8 @@ static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate) | |||
| 45 | * So here, we have a buffer which has just come off the forget list. Look to | 45 | * So here, we have a buffer which has just come off the forget list. Look to |
| 46 | * see if we can strip all buffers from the backing page. | 46 | * see if we can strip all buffers from the backing page. |
| 47 | * | 47 | * |
| 48 | * Called under lock_journal(), and possibly under journal_datalist_lock. The | 48 | * Called under journal->j_list_lock. The caller provided us with a ref |
| 49 | * caller provided us with a ref against the buffer, and we drop that here. | 49 | * against the buffer, and we drop that here. |
| 50 | */ | 50 | */ |
| 51 | static void release_buffer_page(struct buffer_head *bh) | 51 | static void release_buffer_page(struct buffer_head *bh) |
| 52 | { | 52 | { |
| @@ -78,6 +78,19 @@ nope: | |||
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | /* | 80 | /* |
| 81 | * Decrement reference counter for data buffer. If it has been marked | ||
| 82 | * 'BH_Freed', release it and the page to which it belongs if possible. | ||
| 83 | */ | ||
| 84 | static void release_data_buffer(struct buffer_head *bh) | ||
| 85 | { | ||
| 86 | if (buffer_freed(bh)) { | ||
| 87 | clear_buffer_freed(bh); | ||
| 88 | release_buffer_page(bh); | ||
| 89 | } else | ||
| 90 | put_bh(bh); | ||
| 91 | } | ||
| 92 | |||
| 93 | /* | ||
| 81 | * Try to acquire jbd_lock_bh_state() against the buffer, when j_list_lock is | 94 | * Try to acquire jbd_lock_bh_state() against the buffer, when j_list_lock is |
| 82 | * held. For ranking reasons we must trylock. If we lose, schedule away and | 95 | * held. For ranking reasons we must trylock. If we lose, schedule away and |
| 83 | * return 0. j_list_lock is dropped in this case. | 96 | * return 0. j_list_lock is dropped in this case. |
| @@ -172,7 +185,7 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs) | |||
| 172 | /* | 185 | /* |
| 173 | * Submit all the data buffers to disk | 186 | * Submit all the data buffers to disk |
| 174 | */ | 187 | */ |
| 175 | static void journal_submit_data_buffers(journal_t *journal, | 188 | static int journal_submit_data_buffers(journal_t *journal, |
| 176 | transaction_t *commit_transaction) | 189 | transaction_t *commit_transaction) |
| 177 | { | 190 | { |
| 178 | struct journal_head *jh; | 191 | struct journal_head *jh; |
| @@ -180,6 +193,7 @@ static void journal_submit_data_buffers(journal_t *journal, | |||
| 180 | int locked; | 193 | int locked; |
| 181 | int bufs = 0; | 194 | int bufs = 0; |
| 182 | struct buffer_head **wbuf = journal->j_wbuf; | 195 | struct buffer_head **wbuf = journal->j_wbuf; |
| 196 | int err = 0; | ||
| 183 | 197 | ||
| 184 | /* | 198 | /* |
| 185 | * Whenever we unlock the journal and sleep, things can get added | 199 | * Whenever we unlock the journal and sleep, things can get added |
| @@ -231,7 +245,7 @@ write_out_data: | |||
| 231 | if (locked) | 245 | if (locked) |
| 232 | unlock_buffer(bh); | 246 | unlock_buffer(bh); |
| 233 | BUFFER_TRACE(bh, "already cleaned up"); | 247 | BUFFER_TRACE(bh, "already cleaned up"); |
| 234 | put_bh(bh); | 248 | release_data_buffer(bh); |
| 235 | continue; | 249 | continue; |
| 236 | } | 250 | } |
| 237 | if (locked && test_clear_buffer_dirty(bh)) { | 251 | if (locked && test_clear_buffer_dirty(bh)) { |
| @@ -253,15 +267,17 @@ write_out_data: | |||
| 253 | put_bh(bh); | 267 | put_bh(bh); |
| 254 | } else { | 268 | } else { |
| 255 | BUFFER_TRACE(bh, "writeout complete: unfile"); | 269 | BUFFER_TRACE(bh, "writeout complete: unfile"); |
| 270 | if (unlikely(!buffer_uptodate(bh))) | ||
| 271 | err = -EIO; | ||
| 256 | __journal_unfile_buffer(jh); | 272 | __journal_unfile_buffer(jh); |
| 257 | jbd_unlock_bh_state(bh); | 273 | jbd_unlock_bh_state(bh); |
| 258 | if (locked) | 274 | if (locked) |
| 259 | unlock_buffer(bh); | 275 | unlock_buffer(bh); |
| 260 | journal_remove_journal_head(bh); | 276 | journal_remove_journal_head(bh); |
| 261 | /* Once for our safety reference, once for | 277 | /* One for our safety reference, other for |
| 262 | * journal_remove_journal_head() */ | 278 | * journal_remove_journal_head() */ |
| 263 | put_bh(bh); | 279 | put_bh(bh); |
| 264 | put_bh(bh); | 280 | release_data_buffer(bh); |
| 265 | } | 281 | } |
| 266 | 282 | ||
| 267 | if (need_resched() || spin_needbreak(&journal->j_list_lock)) { | 283 | if (need_resched() || spin_needbreak(&journal->j_list_lock)) { |
| @@ -271,6 +287,8 @@ write_out_data: | |||
| 271 | } | 287 | } |
| 272 | spin_unlock(&journal->j_list_lock); | 288 | spin_unlock(&journal->j_list_lock); |
| 273 | journal_do_submit_data(wbuf, bufs); | 289 | journal_do_submit_data(wbuf, bufs); |
| 290 | |||
| 291 | return err; | ||
| 274 | } | 292 | } |
| 275 | 293 | ||
| 276 | /* | 294 | /* |
| @@ -410,8 +428,7 @@ void journal_commit_transaction(journal_t *journal) | |||
| 410 | * Now start flushing things to disk, in the order they appear | 428 | * Now start flushing things to disk, in the order they appear |
| 411 | * on the transaction lists. Data blocks go first. | 429 | * on the transaction lists. Data blocks go first. |
| 412 | */ | 430 | */ |
| 413 | err = 0; | 431 | err = journal_submit_data_buffers(journal, commit_transaction); |
| 414 | journal_submit_data_buffers(journal, commit_transaction); | ||
| 415 | 432 | ||
| 416 | /* | 433 | /* |
| 417 | * Wait for all previously submitted IO to complete. | 434 | * Wait for all previously submitted IO to complete. |
| @@ -426,10 +443,21 @@ void journal_commit_transaction(journal_t *journal) | |||
| 426 | if (buffer_locked(bh)) { | 443 | if (buffer_locked(bh)) { |
| 427 | spin_unlock(&journal->j_list_lock); | 444 | spin_unlock(&journal->j_list_lock); |
| 428 | wait_on_buffer(bh); | 445 | wait_on_buffer(bh); |
| 429 | if (unlikely(!buffer_uptodate(bh))) | ||
| 430 | err = -EIO; | ||
| 431 | spin_lock(&journal->j_list_lock); | 446 | spin_lock(&journal->j_list_lock); |
| 432 | } | 447 | } |
| 448 | if (unlikely(!buffer_uptodate(bh))) { | ||
| 449 | if (TestSetPageLocked(bh->b_page)) { | ||
| 450 | spin_unlock(&journal->j_list_lock); | ||
| 451 | lock_page(bh->b_page); | ||
| 452 | spin_lock(&journal->j_list_lock); | ||
| 453 | } | ||
| 454 | if (bh->b_page->mapping) | ||
| 455 | set_bit(AS_EIO, &bh->b_page->mapping->flags); | ||
| 456 | |||
| 457 | unlock_page(bh->b_page); | ||
| 458 | SetPageError(bh->b_page); | ||
| 459 | err = -EIO; | ||
| 460 | } | ||
| 433 | if (!inverted_lock(journal, bh)) { | 461 | if (!inverted_lock(journal, bh)) { |
| 434 | put_bh(bh); | 462 | put_bh(bh); |
| 435 | spin_lock(&journal->j_list_lock); | 463 | spin_lock(&journal->j_list_lock); |
| @@ -443,17 +471,21 @@ void journal_commit_transaction(journal_t *journal) | |||
| 443 | } else { | 471 | } else { |
| 444 | jbd_unlock_bh_state(bh); | 472 | jbd_unlock_bh_state(bh); |
| 445 | } | 473 | } |
| 446 | put_bh(bh); | 474 | release_data_buffer(bh); |
| 447 | cond_resched_lock(&journal->j_list_lock); | 475 | cond_resched_lock(&journal->j_list_lock); |
| 448 | } | 476 | } |
| 449 | spin_unlock(&journal->j_list_lock); | 477 | spin_unlock(&journal->j_list_lock); |
| 450 | 478 | ||
| 451 | if (err) | 479 | if (err) { |
| 452 | journal_abort(journal, err); | 480 | char b[BDEVNAME_SIZE]; |
| 453 | 481 | ||
| 454 | journal_write_revoke_records(journal, commit_transaction); | 482 | printk(KERN_WARNING |
| 483 | "JBD: Detected IO errors while flushing file data " | ||
| 484 | "on %s\n", bdevname(journal->j_fs_dev, b)); | ||
| 485 | err = 0; | ||
| 486 | } | ||
| 455 | 487 | ||
| 456 | jbd_debug(3, "JBD: commit phase 2\n"); | 488 | journal_write_revoke_records(journal, commit_transaction); |
| 457 | 489 | ||
| 458 | /* | 490 | /* |
| 459 | * If we found any dirty or locked buffers, then we should have | 491 | * If we found any dirty or locked buffers, then we should have |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index b99c3b3654c4..aa7143a8349b 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
| @@ -68,7 +68,6 @@ EXPORT_SYMBOL(journal_set_features); | |||
| 68 | EXPORT_SYMBOL(journal_create); | 68 | EXPORT_SYMBOL(journal_create); |
| 69 | EXPORT_SYMBOL(journal_load); | 69 | EXPORT_SYMBOL(journal_load); |
| 70 | EXPORT_SYMBOL(journal_destroy); | 70 | EXPORT_SYMBOL(journal_destroy); |
| 71 | EXPORT_SYMBOL(journal_update_superblock); | ||
| 72 | EXPORT_SYMBOL(journal_abort); | 71 | EXPORT_SYMBOL(journal_abort); |
| 73 | EXPORT_SYMBOL(journal_errno); | 72 | EXPORT_SYMBOL(journal_errno); |
| 74 | EXPORT_SYMBOL(journal_ack_err); | 73 | EXPORT_SYMBOL(journal_ack_err); |
| @@ -1636,9 +1635,10 @@ static int journal_init_journal_head_cache(void) | |||
| 1636 | 1635 | ||
| 1637 | static void journal_destroy_journal_head_cache(void) | 1636 | static void journal_destroy_journal_head_cache(void) |
| 1638 | { | 1637 | { |
| 1639 | J_ASSERT(journal_head_cache != NULL); | 1638 | if (journal_head_cache) { |
| 1640 | kmem_cache_destroy(journal_head_cache); | 1639 | kmem_cache_destroy(journal_head_cache); |
| 1641 | journal_head_cache = NULL; | 1640 | journal_head_cache = NULL; |
| 1641 | } | ||
| 1642 | } | 1642 | } |
| 1643 | 1643 | ||
| 1644 | /* | 1644 | /* |
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index 1bb43e987f4b..c7bd649bbbdc 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c | |||
| @@ -166,138 +166,123 @@ static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal, | |||
| 166 | return NULL; | 166 | return NULL; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | void journal_destroy_revoke_caches(void) | ||
| 170 | { | ||
| 171 | if (revoke_record_cache) { | ||
| 172 | kmem_cache_destroy(revoke_record_cache); | ||
| 173 | revoke_record_cache = NULL; | ||
| 174 | } | ||
| 175 | if (revoke_table_cache) { | ||
| 176 | kmem_cache_destroy(revoke_table_cache); | ||
| 177 | revoke_table_cache = NULL; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 169 | int __init journal_init_revoke_caches(void) | 181 | int __init journal_init_revoke_caches(void) |
| 170 | { | 182 | { |
| 183 | J_ASSERT(!revoke_record_cache); | ||
| 184 | J_ASSERT(!revoke_table_cache); | ||
| 185 | |||
| 171 | revoke_record_cache = kmem_cache_create("revoke_record", | 186 | revoke_record_cache = kmem_cache_create("revoke_record", |
| 172 | sizeof(struct jbd_revoke_record_s), | 187 | sizeof(struct jbd_revoke_record_s), |
| 173 | 0, | 188 | 0, |
| 174 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | 189 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, |
| 175 | NULL); | 190 | NULL); |
| 176 | if (!revoke_record_cache) | 191 | if (!revoke_record_cache) |
| 177 | return -ENOMEM; | 192 | goto record_cache_failure; |
| 178 | 193 | ||
| 179 | revoke_table_cache = kmem_cache_create("revoke_table", | 194 | revoke_table_cache = kmem_cache_create("revoke_table", |
| 180 | sizeof(struct jbd_revoke_table_s), | 195 | sizeof(struct jbd_revoke_table_s), |
| 181 | 0, SLAB_TEMPORARY, NULL); | 196 | 0, SLAB_TEMPORARY, NULL); |
| 182 | if (!revoke_table_cache) { | 197 | if (!revoke_table_cache) |
| 183 | kmem_cache_destroy(revoke_record_cache); | 198 | goto table_cache_failure; |
| 184 | revoke_record_cache = NULL; | 199 | |
| 185 | return -ENOMEM; | ||
| 186 | } | ||
| 187 | return 0; | 200 | return 0; |
| 188 | } | ||
| 189 | 201 | ||
| 190 | void journal_destroy_revoke_caches(void) | 202 | table_cache_failure: |
| 191 | { | 203 | journal_destroy_revoke_caches(); |
| 192 | kmem_cache_destroy(revoke_record_cache); | 204 | record_cache_failure: |
| 193 | revoke_record_cache = NULL; | 205 | return -ENOMEM; |
| 194 | kmem_cache_destroy(revoke_table_cache); | ||
| 195 | revoke_table_cache = NULL; | ||
| 196 | } | 206 | } |
| 197 | 207 | ||
| 198 | /* Initialise the revoke table for a given journal to a given size. */ | 208 | static struct jbd_revoke_table_s *journal_init_revoke_table(int hash_size) |
| 199 | |||
| 200 | int journal_init_revoke(journal_t *journal, int hash_size) | ||
| 201 | { | 209 | { |
| 202 | int shift, tmp; | 210 | int shift = 0; |
| 211 | int tmp = hash_size; | ||
| 212 | struct jbd_revoke_table_s *table; | ||
| 203 | 213 | ||
| 204 | J_ASSERT (journal->j_revoke_table[0] == NULL); | 214 | table = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL); |
| 215 | if (!table) | ||
| 216 | goto out; | ||
| 205 | 217 | ||
| 206 | shift = 0; | ||
| 207 | tmp = hash_size; | ||
| 208 | while((tmp >>= 1UL) != 0UL) | 218 | while((tmp >>= 1UL) != 0UL) |
| 209 | shift++; | 219 | shift++; |
| 210 | 220 | ||
| 211 | journal->j_revoke_table[0] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL); | 221 | table->hash_size = hash_size; |
| 212 | if (!journal->j_revoke_table[0]) | 222 | table->hash_shift = shift; |
| 213 | return -ENOMEM; | 223 | table->hash_table = |
| 214 | journal->j_revoke = journal->j_revoke_table[0]; | ||
| 215 | |||
| 216 | /* Check that the hash_size is a power of two */ | ||
| 217 | J_ASSERT(is_power_of_2(hash_size)); | ||
| 218 | |||
| 219 | journal->j_revoke->hash_size = hash_size; | ||
| 220 | |||
| 221 | journal->j_revoke->hash_shift = shift; | ||
| 222 | |||
| 223 | journal->j_revoke->hash_table = | ||
| 224 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | 224 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); |
| 225 | if (!journal->j_revoke->hash_table) { | 225 | if (!table->hash_table) { |
| 226 | kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]); | 226 | kmem_cache_free(revoke_table_cache, table); |
| 227 | journal->j_revoke = NULL; | 227 | table = NULL; |
| 228 | return -ENOMEM; | 228 | goto out; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | for (tmp = 0; tmp < hash_size; tmp++) | 231 | for (tmp = 0; tmp < hash_size; tmp++) |
| 232 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | 232 | INIT_LIST_HEAD(&table->hash_table[tmp]); |
| 233 | 233 | ||
| 234 | journal->j_revoke_table[1] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL); | 234 | out: |
| 235 | if (!journal->j_revoke_table[1]) { | 235 | return table; |
| 236 | kfree(journal->j_revoke_table[0]->hash_table); | 236 | } |
| 237 | kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]); | 237 | |
| 238 | return -ENOMEM; | 238 | static void journal_destroy_revoke_table(struct jbd_revoke_table_s *table) |
| 239 | { | ||
| 240 | int i; | ||
| 241 | struct list_head *hash_list; | ||
| 242 | |||
| 243 | for (i = 0; i < table->hash_size; i++) { | ||
| 244 | hash_list = &table->hash_table[i]; | ||
| 245 | J_ASSERT(list_empty(hash_list)); | ||
| 239 | } | 246 | } |
| 240 | 247 | ||
| 241 | journal->j_revoke = journal->j_revoke_table[1]; | 248 | kfree(table->hash_table); |
| 249 | kmem_cache_free(revoke_table_cache, table); | ||
| 250 | } | ||
| 242 | 251 | ||
| 243 | /* Check that the hash_size is a power of two */ | 252 | /* Initialise the revoke table for a given journal to a given size. */ |
| 253 | int journal_init_revoke(journal_t *journal, int hash_size) | ||
| 254 | { | ||
| 255 | J_ASSERT(journal->j_revoke_table[0] == NULL); | ||
| 244 | J_ASSERT(is_power_of_2(hash_size)); | 256 | J_ASSERT(is_power_of_2(hash_size)); |
| 245 | 257 | ||
| 246 | journal->j_revoke->hash_size = hash_size; | 258 | journal->j_revoke_table[0] = journal_init_revoke_table(hash_size); |
| 259 | if (!journal->j_revoke_table[0]) | ||
| 260 | goto fail0; | ||
| 247 | 261 | ||
| 248 | journal->j_revoke->hash_shift = shift; | 262 | journal->j_revoke_table[1] = journal_init_revoke_table(hash_size); |
| 263 | if (!journal->j_revoke_table[1]) | ||
| 264 | goto fail1; | ||
| 249 | 265 | ||
| 250 | journal->j_revoke->hash_table = | 266 | journal->j_revoke = journal->j_revoke_table[1]; |
| 251 | kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); | ||
| 252 | if (!journal->j_revoke->hash_table) { | ||
| 253 | kfree(journal->j_revoke_table[0]->hash_table); | ||
| 254 | kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]); | ||
| 255 | kmem_cache_free(revoke_table_cache, journal->j_revoke_table[1]); | ||
| 256 | journal->j_revoke = NULL; | ||
| 257 | return -ENOMEM; | ||
| 258 | } | ||
| 259 | |||
| 260 | for (tmp = 0; tmp < hash_size; tmp++) | ||
| 261 | INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); | ||
| 262 | 267 | ||
| 263 | spin_lock_init(&journal->j_revoke_lock); | 268 | spin_lock_init(&journal->j_revoke_lock); |
| 264 | 269 | ||
| 265 | return 0; | 270 | return 0; |
| 266 | } | ||
| 267 | 271 | ||
| 268 | /* Destoy a journal's revoke table. The table must already be empty! */ | 272 | fail1: |
| 273 | journal_destroy_revoke_table(journal->j_revoke_table[0]); | ||
| 274 | fail0: | ||
| 275 | return -ENOMEM; | ||
| 276 | } | ||
| 269 | 277 | ||
| 278 | /* Destroy a journal's revoke table. The table must already be empty! */ | ||
| 270 | void journal_destroy_revoke(journal_t *journal) | 279 | void journal_destroy_revoke(journal_t *journal) |
| 271 | { | 280 | { |
| 272 | struct jbd_revoke_table_s *table; | ||
| 273 | struct list_head *hash_list; | ||
| 274 | int i; | ||
| 275 | |||
| 276 | table = journal->j_revoke_table[0]; | ||
| 277 | if (!table) | ||
| 278 | return; | ||
| 279 | |||
| 280 | for (i=0; i<table->hash_size; i++) { | ||
| 281 | hash_list = &table->hash_table[i]; | ||
| 282 | J_ASSERT (list_empty(hash_list)); | ||
| 283 | } | ||
| 284 | |||
| 285 | kfree(table->hash_table); | ||
| 286 | kmem_cache_free(revoke_table_cache, table); | ||
| 287 | journal->j_revoke = NULL; | ||
| 288 | |||
| 289 | table = journal->j_revoke_table[1]; | ||
| 290 | if (!table) | ||
| 291 | return; | ||
| 292 | |||
| 293 | for (i=0; i<table->hash_size; i++) { | ||
| 294 | hash_list = &table->hash_table[i]; | ||
| 295 | J_ASSERT (list_empty(hash_list)); | ||
| 296 | } | ||
| 297 | |||
| 298 | kfree(table->hash_table); | ||
| 299 | kmem_cache_free(revoke_table_cache, table); | ||
| 300 | journal->j_revoke = NULL; | 281 | journal->j_revoke = NULL; |
| 282 | if (journal->j_revoke_table[0]) | ||
| 283 | journal_destroy_revoke_table(journal->j_revoke_table[0]); | ||
| 284 | if (journal->j_revoke_table[1]) | ||
| 285 | journal_destroy_revoke_table(journal->j_revoke_table[1]); | ||
| 301 | } | 286 | } |
| 302 | 287 | ||
| 303 | 288 | ||
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 67ff2024c23c..8dee32007500 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
| @@ -1648,12 +1648,42 @@ out: | |||
| 1648 | return; | 1648 | return; |
| 1649 | } | 1649 | } |
| 1650 | 1650 | ||
| 1651 | /* | ||
| 1652 | * journal_try_to_free_buffers() could race with journal_commit_transaction() | ||
| 1653 | * The latter might still hold the a count on buffers when inspecting | ||
| 1654 | * them on t_syncdata_list or t_locked_list. | ||
| 1655 | * | ||
| 1656 | * journal_try_to_free_buffers() will call this function to | ||
| 1657 | * wait for the current transaction to finish syncing data buffers, before | ||
| 1658 | * tryinf to free that buffer. | ||
| 1659 | * | ||
| 1660 | * Called with journal->j_state_lock held. | ||
| 1661 | */ | ||
| 1662 | static void journal_wait_for_transaction_sync_data(journal_t *journal) | ||
| 1663 | { | ||
| 1664 | transaction_t *transaction = NULL; | ||
| 1665 | tid_t tid; | ||
| 1666 | |||
| 1667 | spin_lock(&journal->j_state_lock); | ||
| 1668 | transaction = journal->j_committing_transaction; | ||
| 1669 | |||
| 1670 | if (!transaction) { | ||
| 1671 | spin_unlock(&journal->j_state_lock); | ||
| 1672 | return; | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | tid = transaction->t_tid; | ||
| 1676 | spin_unlock(&journal->j_state_lock); | ||
| 1677 | log_wait_commit(journal, tid); | ||
| 1678 | } | ||
| 1651 | 1679 | ||
| 1652 | /** | 1680 | /** |
| 1653 | * int journal_try_to_free_buffers() - try to free page buffers. | 1681 | * int journal_try_to_free_buffers() - try to free page buffers. |
| 1654 | * @journal: journal for operation | 1682 | * @journal: journal for operation |
| 1655 | * @page: to try and free | 1683 | * @page: to try and free |
| 1656 | * @unused_gfp_mask: unused | 1684 | * @gfp_mask: we use the mask to detect how hard should we try to release |
| 1685 | * buffers. If __GFP_WAIT and __GFP_FS is set, we wait for commit code to | ||
| 1686 | * release the buffers. | ||
| 1657 | * | 1687 | * |
| 1658 | * | 1688 | * |
| 1659 | * For all the buffers on this page, | 1689 | * For all the buffers on this page, |
| @@ -1682,9 +1712,11 @@ out: | |||
| 1682 | * journal_try_to_free_buffer() is changing its state. But that | 1712 | * journal_try_to_free_buffer() is changing its state. But that |
| 1683 | * cannot happen because we never reallocate freed data as metadata | 1713 | * cannot happen because we never reallocate freed data as metadata |
| 1684 | * while the data is part of a transaction. Yes? | 1714 | * while the data is part of a transaction. Yes? |
| 1715 | * | ||
| 1716 | * Return 0 on failure, 1 on success | ||
| 1685 | */ | 1717 | */ |
| 1686 | int journal_try_to_free_buffers(journal_t *journal, | 1718 | int journal_try_to_free_buffers(journal_t *journal, |
| 1687 | struct page *page, gfp_t unused_gfp_mask) | 1719 | struct page *page, gfp_t gfp_mask) |
| 1688 | { | 1720 | { |
| 1689 | struct buffer_head *head; | 1721 | struct buffer_head *head; |
| 1690 | struct buffer_head *bh; | 1722 | struct buffer_head *bh; |
| @@ -1713,7 +1745,28 @@ int journal_try_to_free_buffers(journal_t *journal, | |||
| 1713 | if (buffer_jbd(bh)) | 1745 | if (buffer_jbd(bh)) |
| 1714 | goto busy; | 1746 | goto busy; |
| 1715 | } while ((bh = bh->b_this_page) != head); | 1747 | } while ((bh = bh->b_this_page) != head); |
| 1748 | |||
| 1716 | ret = try_to_free_buffers(page); | 1749 | ret = try_to_free_buffers(page); |
| 1750 | |||
| 1751 | /* | ||
| 1752 | * There are a number of places where journal_try_to_free_buffers() | ||
| 1753 | * could race with journal_commit_transaction(), the later still | ||
| 1754 | * holds the reference to the buffers to free while processing them. | ||
| 1755 | * try_to_free_buffers() failed to free those buffers. Some of the | ||
| 1756 | * caller of releasepage() request page buffers to be dropped, otherwise | ||
| 1757 | * treat the fail-to-free as errors (such as generic_file_direct_IO()) | ||
| 1758 | * | ||
| 1759 | * So, if the caller of try_to_release_page() wants the synchronous | ||
| 1760 | * behaviour(i.e make sure buffers are dropped upon return), | ||
| 1761 | * let's wait for the current transaction to finish flush of | ||
| 1762 | * dirty data buffers, then try to free those buffers again, | ||
| 1763 | * with the journal locked. | ||
| 1764 | */ | ||
| 1765 | if (ret == 0 && (gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS)) { | ||
| 1766 | journal_wait_for_transaction_sync_data(journal); | ||
| 1767 | ret = try_to_free_buffers(page); | ||
| 1768 | } | ||
| 1769 | |||
| 1717 | busy: | 1770 | busy: |
| 1718 | return ret; | 1771 | return ret; |
| 1719 | } | 1772 | } |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 0288e6d7936a..359c091d8965 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/parser.h> | 22 | #include <linux/parser.h> |
| 23 | #include <linux/completion.h> | 23 | #include <linux/completion.h> |
| 24 | #include <linux/vfs.h> | 24 | #include <linux/vfs.h> |
| 25 | #include <linux/quotaops.h> | ||
| 25 | #include <linux/mount.h> | 26 | #include <linux/mount.h> |
| 26 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
| 27 | #include <linux/kthread.h> | 28 | #include <linux/kthread.h> |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 1f6dc518505c..31668b690e03 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
| @@ -582,7 +582,15 @@ again: | |||
| 582 | } | 582 | } |
| 583 | if (status < 0) | 583 | if (status < 0) |
| 584 | goto out_unlock; | 584 | goto out_unlock; |
| 585 | status = nlm_stat_to_errno(resp->status); | 585 | /* |
| 586 | * EAGAIN doesn't make sense for sleeping locks, and in some | ||
| 587 | * cases NLM_LCK_DENIED is returned for a permanent error. So | ||
| 588 | * turn it into an ENOLCK. | ||
| 589 | */ | ||
| 590 | if (resp->status == nlm_lck_denied && (fl_flags & FL_SLEEP)) | ||
| 591 | status = -ENOLCK; | ||
| 592 | else | ||
| 593 | status = nlm_stat_to_errno(resp->status); | ||
| 586 | out_unblock: | 594 | out_unblock: |
| 587 | nlmclnt_finish_block(block); | 595 | nlmclnt_finish_block(block); |
| 588 | out: | 596 | out: |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 821b9acdfb66..cf0d5c2c318d 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -418,8 +418,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 418 | goto out; | 418 | goto out; |
| 419 | case -EAGAIN: | 419 | case -EAGAIN: |
| 420 | ret = nlm_lck_denied; | 420 | ret = nlm_lck_denied; |
| 421 | break; | 421 | goto out; |
| 422 | case -EINPROGRESS: | 422 | case FILE_LOCK_DEFERRED: |
| 423 | if (wait) | 423 | if (wait) |
| 424 | break; | 424 | break; |
| 425 | /* Filesystem lock operation is in progress | 425 | /* Filesystem lock operation is in progress |
| @@ -434,10 +434,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 434 | goto out; | 434 | goto out; |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | ret = nlm_lck_denied; | ||
| 438 | if (!wait) | ||
| 439 | goto out; | ||
| 440 | |||
| 441 | ret = nlm_lck_blocked; | 437 | ret = nlm_lck_blocked; |
| 442 | 438 | ||
| 443 | /* Append to list of blocked */ | 439 | /* Append to list of blocked */ |
| @@ -507,7 +503,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 507 | } | 503 | } |
| 508 | 504 | ||
| 509 | error = vfs_test_lock(file->f_file, &lock->fl); | 505 | error = vfs_test_lock(file->f_file, &lock->fl); |
| 510 | if (error == -EINPROGRESS) { | 506 | if (error == FILE_LOCK_DEFERRED) { |
| 511 | ret = nlmsvc_defer_lock_rqst(rqstp, block); | 507 | ret = nlmsvc_defer_lock_rqst(rqstp, block); |
| 512 | goto out; | 508 | goto out; |
| 513 | } | 509 | } |
| @@ -731,8 +727,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
| 731 | switch (error) { | 727 | switch (error) { |
| 732 | case 0: | 728 | case 0: |
| 733 | break; | 729 | break; |
| 734 | case -EAGAIN: | 730 | case FILE_LOCK_DEFERRED: |
| 735 | case -EINPROGRESS: | ||
| 736 | dprintk("lockd: lock still blocked error %d\n", error); | 731 | dprintk("lockd: lock still blocked error %d\n", error); |
| 737 | nlmsvc_insert_block(block, NLM_NEVER); | 732 | nlmsvc_insert_block(block, NLM_NEVER); |
| 738 | nlmsvc_release_block(block); | 733 | nlmsvc_release_block(block); |
diff --git a/fs/locks.c b/fs/locks.c index dce8c747371c..01490300f7cb 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -779,8 +779,10 @@ find_conflict: | |||
| 779 | if (!flock_locks_conflict(request, fl)) | 779 | if (!flock_locks_conflict(request, fl)) |
| 780 | continue; | 780 | continue; |
| 781 | error = -EAGAIN; | 781 | error = -EAGAIN; |
| 782 | if (request->fl_flags & FL_SLEEP) | 782 | if (!(request->fl_flags & FL_SLEEP)) |
| 783 | locks_insert_block(fl, request); | 783 | goto out; |
| 784 | error = FILE_LOCK_DEFERRED; | ||
| 785 | locks_insert_block(fl, request); | ||
| 784 | goto out; | 786 | goto out; |
| 785 | } | 787 | } |
| 786 | if (request->fl_flags & FL_ACCESS) | 788 | if (request->fl_flags & FL_ACCESS) |
| @@ -836,7 +838,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 836 | error = -EDEADLK; | 838 | error = -EDEADLK; |
| 837 | if (posix_locks_deadlock(request, fl)) | 839 | if (posix_locks_deadlock(request, fl)) |
| 838 | goto out; | 840 | goto out; |
| 839 | error = -EAGAIN; | 841 | error = FILE_LOCK_DEFERRED; |
| 840 | locks_insert_block(fl, request); | 842 | locks_insert_block(fl, request); |
| 841 | goto out; | 843 | goto out; |
| 842 | } | 844 | } |
| @@ -1035,7 +1037,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl) | |||
| 1035 | might_sleep (); | 1037 | might_sleep (); |
| 1036 | for (;;) { | 1038 | for (;;) { |
| 1037 | error = posix_lock_file(filp, fl, NULL); | 1039 | error = posix_lock_file(filp, fl, NULL); |
| 1038 | if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) | 1040 | if (error != FILE_LOCK_DEFERRED) |
| 1039 | break; | 1041 | break; |
| 1040 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); | 1042 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); |
| 1041 | if (!error) | 1043 | if (!error) |
| @@ -1107,9 +1109,7 @@ int locks_mandatory_area(int read_write, struct inode *inode, | |||
| 1107 | 1109 | ||
| 1108 | for (;;) { | 1110 | for (;;) { |
| 1109 | error = __posix_lock_file(inode, &fl, NULL); | 1111 | error = __posix_lock_file(inode, &fl, NULL); |
| 1110 | if (error != -EAGAIN) | 1112 | if (error != FILE_LOCK_DEFERRED) |
| 1111 | break; | ||
| 1112 | if (!(fl.fl_flags & FL_SLEEP)) | ||
| 1113 | break; | 1113 | break; |
| 1114 | error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); | 1114 | error = wait_event_interruptible(fl.fl_wait, !fl.fl_next); |
| 1115 | if (!error) { | 1115 | if (!error) { |
| @@ -1531,7 +1531,7 @@ int flock_lock_file_wait(struct file *filp, struct file_lock *fl) | |||
| 1531 | might_sleep(); | 1531 | might_sleep(); |
| 1532 | for (;;) { | 1532 | for (;;) { |
| 1533 | error = flock_lock_file(filp, fl); | 1533 | error = flock_lock_file(filp, fl); |
| 1534 | if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP)) | 1534 | if (error != FILE_LOCK_DEFERRED) |
| 1535 | break; | 1535 | break; |
| 1536 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); | 1536 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); |
| 1537 | if (!error) | 1537 | if (!error) |
| @@ -1716,17 +1716,17 @@ out: | |||
| 1716 | * fl_grant is set. Callers expecting ->lock() to return asynchronously | 1716 | * fl_grant is set. Callers expecting ->lock() to return asynchronously |
| 1717 | * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) | 1717 | * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) |
| 1718 | * the request is for a blocking lock. When ->lock() does return asynchronously, | 1718 | * the request is for a blocking lock. When ->lock() does return asynchronously, |
| 1719 | * it must return -EINPROGRESS, and call ->fl_grant() when the lock | 1719 | * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock |
| 1720 | * request completes. | 1720 | * request completes. |
| 1721 | * If the request is for non-blocking lock the file system should return | 1721 | * If the request is for non-blocking lock the file system should return |
| 1722 | * -EINPROGRESS then try to get the lock and call the callback routine with | 1722 | * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine |
| 1723 | * the result. If the request timed out the callback routine will return a | 1723 | * with the result. If the request timed out the callback routine will return a |
| 1724 | * nonzero return code and the file system should release the lock. The file | 1724 | * nonzero return code and the file system should release the lock. The file |
| 1725 | * system is also responsible to keep a corresponding posix lock when it | 1725 | * system is also responsible to keep a corresponding posix lock when it |
| 1726 | * grants a lock so the VFS can find out which locks are locally held and do | 1726 | * grants a lock so the VFS can find out which locks are locally held and do |
| 1727 | * the correct lock cleanup when required. | 1727 | * the correct lock cleanup when required. |
| 1728 | * The underlying filesystem must not drop the kernel lock or call | 1728 | * The underlying filesystem must not drop the kernel lock or call |
| 1729 | * ->fl_grant() before returning to the caller with a -EINPROGRESS | 1729 | * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED |
| 1730 | * return code. | 1730 | * return code. |
| 1731 | */ | 1731 | */ |
| 1732 | int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) | 1732 | int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) |
| @@ -1738,6 +1738,30 @@ int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, str | |||
| 1738 | } | 1738 | } |
| 1739 | EXPORT_SYMBOL_GPL(vfs_lock_file); | 1739 | EXPORT_SYMBOL_GPL(vfs_lock_file); |
| 1740 | 1740 | ||
| 1741 | static int do_lock_file_wait(struct file *filp, unsigned int cmd, | ||
| 1742 | struct file_lock *fl) | ||
| 1743 | { | ||
| 1744 | int error; | ||
| 1745 | |||
| 1746 | error = security_file_lock(filp, fl->fl_type); | ||
| 1747 | if (error) | ||
| 1748 | return error; | ||
| 1749 | |||
| 1750 | for (;;) { | ||
| 1751 | error = vfs_lock_file(filp, cmd, fl, NULL); | ||
| 1752 | if (error != FILE_LOCK_DEFERRED) | ||
| 1753 | break; | ||
| 1754 | error = wait_event_interruptible(fl->fl_wait, !fl->fl_next); | ||
| 1755 | if (!error) | ||
| 1756 | continue; | ||
| 1757 | |||
| 1758 | locks_delete_block(fl); | ||
| 1759 | break; | ||
| 1760 | } | ||
| 1761 | |||
| 1762 | return error; | ||
| 1763 | } | ||
| 1764 | |||
| 1741 | /* Apply the lock described by l to an open file descriptor. | 1765 | /* Apply the lock described by l to an open file descriptor. |
| 1742 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). | 1766 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). |
| 1743 | */ | 1767 | */ |
| @@ -1795,26 +1819,7 @@ again: | |||
| 1795 | goto out; | 1819 | goto out; |
| 1796 | } | 1820 | } |
| 1797 | 1821 | ||
| 1798 | error = security_file_lock(filp, file_lock->fl_type); | 1822 | error = do_lock_file_wait(filp, cmd, file_lock); |
| 1799 | if (error) | ||
| 1800 | goto out; | ||
| 1801 | |||
| 1802 | if (filp->f_op && filp->f_op->lock != NULL) | ||
| 1803 | error = filp->f_op->lock(filp, cmd, file_lock); | ||
| 1804 | else { | ||
| 1805 | for (;;) { | ||
| 1806 | error = posix_lock_file(filp, file_lock, NULL); | ||
| 1807 | if (error != -EAGAIN || cmd == F_SETLK) | ||
| 1808 | break; | ||
| 1809 | error = wait_event_interruptible(file_lock->fl_wait, | ||
| 1810 | !file_lock->fl_next); | ||
| 1811 | if (!error) | ||
| 1812 | continue; | ||
| 1813 | |||
| 1814 | locks_delete_block(file_lock); | ||
| 1815 | break; | ||
| 1816 | } | ||
| 1817 | } | ||
| 1818 | 1823 | ||
| 1819 | /* | 1824 | /* |
| 1820 | * Attempt to detect a close/fcntl race and recover by | 1825 | * Attempt to detect a close/fcntl race and recover by |
| @@ -1932,26 +1937,7 @@ again: | |||
| 1932 | goto out; | 1937 | goto out; |
| 1933 | } | 1938 | } |
| 1934 | 1939 | ||
| 1935 | error = security_file_lock(filp, file_lock->fl_type); | 1940 | error = do_lock_file_wait(filp, cmd, file_lock); |
| 1936 | if (error) | ||
| 1937 | goto out; | ||
| 1938 | |||
| 1939 | if (filp->f_op && filp->f_op->lock != NULL) | ||
| 1940 | error = filp->f_op->lock(filp, cmd, file_lock); | ||
| 1941 | else { | ||
| 1942 | for (;;) { | ||
| 1943 | error = posix_lock_file(filp, file_lock, NULL); | ||
| 1944 | if (error != -EAGAIN || cmd == F_SETLK64) | ||
| 1945 | break; | ||
| 1946 | error = wait_event_interruptible(file_lock->fl_wait, | ||
| 1947 | !file_lock->fl_next); | ||
| 1948 | if (!error) | ||
| 1949 | continue; | ||
| 1950 | |||
| 1951 | locks_delete_block(file_lock); | ||
| 1952 | break; | ||
| 1953 | } | ||
| 1954 | } | ||
| 1955 | 1941 | ||
| 1956 | /* | 1942 | /* |
| 1957 | * Attempt to detect a close/fcntl race and recover by | 1943 | * Attempt to detect a close/fcntl race and recover by |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 84f6242ba6fc..523d73713418 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
| @@ -256,9 +256,6 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
| 256 | if (!s->s_root) | 256 | if (!s->s_root) |
| 257 | goto out_iput; | 257 | goto out_iput; |
| 258 | 258 | ||
| 259 | if (!NO_TRUNCATE) | ||
| 260 | s->s_root->d_op = &minix_dentry_operations; | ||
| 261 | |||
| 262 | if (!(s->s_flags & MS_RDONLY)) { | 259 | if (!(s->s_flags & MS_RDONLY)) { |
| 263 | if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ | 260 | if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ |
| 264 | ms->s_state &= ~MINIX_VALID_FS; | 261 | ms->s_state &= ~MINIX_VALID_FS; |
diff --git a/fs/minix/minix.h b/fs/minix/minix.h index 326edfe96108..e6a0b193bea4 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h | |||
| @@ -2,11 +2,6 @@ | |||
| 2 | #include <linux/pagemap.h> | 2 | #include <linux/pagemap.h> |
| 3 | #include <linux/minix_fs.h> | 3 | #include <linux/minix_fs.h> |
| 4 | 4 | ||
| 5 | /* | ||
| 6 | * change the define below to 0 if you want names > info->s_namelen chars to be | ||
| 7 | * truncated. Else they will be disallowed (ENAMETOOLONG). | ||
| 8 | */ | ||
| 9 | #define NO_TRUNCATE 1 | ||
| 10 | #define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version | 5 | #define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version |
| 11 | #define MINIX_V1 0x0001 /* original minix fs */ | 6 | #define MINIX_V1 0x0001 /* original minix fs */ |
| 12 | #define MINIX_V2 0x0002 /* minix V2 fs */ | 7 | #define MINIX_V2 0x0002 /* minix V2 fs */ |
| @@ -83,7 +78,6 @@ extern const struct inode_operations minix_file_inode_operations; | |||
| 83 | extern const struct inode_operations minix_dir_inode_operations; | 78 | extern const struct inode_operations minix_dir_inode_operations; |
| 84 | extern const struct file_operations minix_file_operations; | 79 | extern const struct file_operations minix_file_operations; |
| 85 | extern const struct file_operations minix_dir_operations; | 80 | extern const struct file_operations minix_dir_operations; |
| 86 | extern struct dentry_operations minix_dentry_operations; | ||
| 87 | 81 | ||
| 88 | static inline struct minix_sb_info *minix_sb(struct super_block *sb) | 82 | static inline struct minix_sb_info *minix_sb(struct super_block *sb) |
| 89 | { | 83 | { |
diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 102241bc9c79..32b131cd6121 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c | |||
| @@ -18,30 +18,6 @@ static int add_nondir(struct dentry *dentry, struct inode *inode) | |||
| 18 | return err; | 18 | return err; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | static int minix_hash(struct dentry *dentry, struct qstr *qstr) | ||
| 22 | { | ||
| 23 | unsigned long hash; | ||
| 24 | int i; | ||
| 25 | const unsigned char *name; | ||
| 26 | |||
| 27 | i = minix_sb(dentry->d_inode->i_sb)->s_namelen; | ||
| 28 | if (i >= qstr->len) | ||
| 29 | return 0; | ||
| 30 | /* Truncate the name in place, avoids having to define a compare | ||
| 31 | function. */ | ||
| 32 | qstr->len = i; | ||
| 33 | name = qstr->name; | ||
| 34 | hash = init_name_hash(); | ||
| 35 | while (i--) | ||
| 36 | hash = partial_name_hash(*name++, hash); | ||
| 37 | qstr->hash = end_name_hash(hash); | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | struct dentry_operations minix_dentry_operations = { | ||
| 42 | .d_hash = minix_hash, | ||
| 43 | }; | ||
| 44 | |||
| 45 | static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) | 21 | static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) |
| 46 | { | 22 | { |
| 47 | struct inode * inode = NULL; | 23 | struct inode * inode = NULL; |
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 1f7f2956412a..e844b9809d27 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c | |||
| @@ -14,12 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | /* Characters that are undesirable in an MS-DOS file name */ | 15 | /* Characters that are undesirable in an MS-DOS file name */ |
| 16 | static unsigned char bad_chars[] = "*?<>|\""; | 16 | static unsigned char bad_chars[] = "*?<>|\""; |
| 17 | static unsigned char bad_if_strict_pc[] = "+=,; "; | 17 | static unsigned char bad_if_strict[] = "+=,; "; |
| 18 | /* GEMDOS is less restrictive */ | ||
| 19 | static unsigned char bad_if_strict_atari[] = " "; | ||
| 20 | |||
| 21 | #define bad_if_strict(opts) \ | ||
| 22 | ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc) | ||
| 23 | 18 | ||
| 24 | /***** Formats an MS-DOS file name. Rejects invalid names. */ | 19 | /***** Formats an MS-DOS file name. Rejects invalid names. */ |
| 25 | static int msdos_format_name(const unsigned char *name, int len, | 20 | static int msdos_format_name(const unsigned char *name, int len, |
| @@ -40,21 +35,20 @@ static int msdos_format_name(const unsigned char *name, int len, | |||
| 40 | /* Get rid of dot - test for it elsewhere */ | 35 | /* Get rid of dot - test for it elsewhere */ |
| 41 | name++; | 36 | name++; |
| 42 | len--; | 37 | len--; |
| 43 | } else if (!opts->atari) | 38 | } else |
| 44 | return -EINVAL; | 39 | return -EINVAL; |
| 45 | } | 40 | } |
| 46 | /* | 41 | /* |
| 47 | * disallow names that _really_ start with a dot for MS-DOS, | 42 | * disallow names that _really_ start with a dot |
| 48 | * GEMDOS does not care | ||
| 49 | */ | 43 | */ |
| 50 | space = !opts->atari; | 44 | space = 1; |
| 51 | c = 0; | 45 | c = 0; |
| 52 | for (walk = res; len && walk - res < 8; walk++) { | 46 | for (walk = res; len && walk - res < 8; walk++) { |
| 53 | c = *name++; | 47 | c = *name++; |
| 54 | len--; | 48 | len--; |
| 55 | if (opts->name_check != 'r' && strchr(bad_chars, c)) | 49 | if (opts->name_check != 'r' && strchr(bad_chars, c)) |
| 56 | return -EINVAL; | 50 | return -EINVAL; |
| 57 | if (opts->name_check == 's' && strchr(bad_if_strict(opts), c)) | 51 | if (opts->name_check == 's' && strchr(bad_if_strict, c)) |
| 58 | return -EINVAL; | 52 | return -EINVAL; |
| 59 | if (c >= 'A' && c <= 'Z' && opts->name_check == 's') | 53 | if (c >= 'A' && c <= 'Z' && opts->name_check == 's') |
| 60 | return -EINVAL; | 54 | return -EINVAL; |
| @@ -94,7 +88,7 @@ static int msdos_format_name(const unsigned char *name, int len, | |||
| 94 | if (opts->name_check != 'r' && strchr(bad_chars, c)) | 88 | if (opts->name_check != 'r' && strchr(bad_chars, c)) |
| 95 | return -EINVAL; | 89 | return -EINVAL; |
| 96 | if (opts->name_check == 's' && | 90 | if (opts->name_check == 's' && |
| 97 | strchr(bad_if_strict(opts), c)) | 91 | strchr(bad_if_strict, c)) |
| 98 | return -EINVAL; | 92 | return -EINVAL; |
| 99 | if (c < ' ' || c == ':' || c == '\\') | 93 | if (c < ' ' || c == ':' || c == '\\') |
| 100 | return -EINVAL; | 94 | return -EINVAL; |
| @@ -243,6 +237,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, | |||
| 243 | int is_dir, int is_hid, int cluster, | 237 | int is_dir, int is_hid, int cluster, |
| 244 | struct timespec *ts, struct fat_slot_info *sinfo) | 238 | struct timespec *ts, struct fat_slot_info *sinfo) |
| 245 | { | 239 | { |
| 240 | struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb); | ||
| 246 | struct msdos_dir_entry de; | 241 | struct msdos_dir_entry de; |
| 247 | __le16 time, date; | 242 | __le16 time, date; |
| 248 | int err; | 243 | int err; |
| @@ -252,7 +247,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, | |||
| 252 | if (is_hid) | 247 | if (is_hid) |
| 253 | de.attr |= ATTR_HIDDEN; | 248 | de.attr |= ATTR_HIDDEN; |
| 254 | de.lcase = 0; | 249 | de.lcase = 0; |
| 255 | fat_date_unix2dos(ts->tv_sec, &time, &date); | 250 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); |
| 256 | de.cdate = de.adate = 0; | 251 | de.cdate = de.adate = 0; |
| 257 | de.ctime = 0; | 252 | de.ctime = 0; |
| 258 | de.ctime_cs = 0; | 253 | de.ctime_cs = 0; |
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 6b6225ac4926..15c6faeec77c 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c | |||
| @@ -19,6 +19,13 @@ | |||
| 19 | 19 | ||
| 20 | #define NFSDDBG_FACILITY NFSDDBG_LOCKD | 20 | #define NFSDDBG_FACILITY NFSDDBG_LOCKD |
| 21 | 21 | ||
| 22 | #ifdef CONFIG_LOCKD_V4 | ||
| 23 | #define nlm_stale_fh nlm4_stale_fh | ||
| 24 | #define nlm_failed nlm4_failed | ||
| 25 | #else | ||
| 26 | #define nlm_stale_fh nlm_lck_denied_nolocks | ||
| 27 | #define nlm_failed nlm_lck_denied_nolocks | ||
| 28 | #endif | ||
| 22 | /* | 29 | /* |
| 23 | * Note: we hold the dentry use count while the file is open. | 30 | * Note: we hold the dentry use count while the file is open. |
| 24 | */ | 31 | */ |
| @@ -47,12 +54,10 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) | |||
| 47 | return 0; | 54 | return 0; |
| 48 | case nfserr_dropit: | 55 | case nfserr_dropit: |
| 49 | return nlm_drop_reply; | 56 | return nlm_drop_reply; |
| 50 | #ifdef CONFIG_LOCKD_V4 | ||
| 51 | case nfserr_stale: | 57 | case nfserr_stale: |
| 52 | return nlm4_stale_fh; | 58 | return nlm_stale_fh; |
| 53 | #endif | ||
| 54 | default: | 59 | default: |
| 55 | return nlm_lck_denied; | 60 | return nlm_failed; |
| 56 | } | 61 | } |
| 57 | } | 62 | } |
| 58 | 63 | ||
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index efef715135d3..7d6b34e201db 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
| @@ -344,18 +344,18 @@ static ssize_t whole_disk_show(struct device *dev, | |||
| 344 | static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, | 344 | static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, |
| 345 | whole_disk_show, NULL); | 345 | whole_disk_show, NULL); |
| 346 | 346 | ||
| 347 | void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) | 347 | int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) |
| 348 | { | 348 | { |
| 349 | struct hd_struct *p; | 349 | struct hd_struct *p; |
| 350 | int err; | 350 | int err; |
| 351 | 351 | ||
| 352 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 352 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 353 | if (!p) | 353 | if (!p) |
| 354 | return; | 354 | return -ENOMEM; |
| 355 | 355 | ||
| 356 | if (!init_part_stats(p)) { | 356 | if (!init_part_stats(p)) { |
| 357 | kfree(p); | 357 | err = -ENOMEM; |
| 358 | return; | 358 | goto out0; |
| 359 | } | 359 | } |
| 360 | p->start_sect = start; | 360 | p->start_sect = start; |
| 361 | p->nr_sects = len; | 361 | p->nr_sects = len; |
| @@ -378,15 +378,31 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, | |||
| 378 | 378 | ||
| 379 | /* delay uevent until 'holders' subdir is created */ | 379 | /* delay uevent until 'holders' subdir is created */ |
| 380 | p->dev.uevent_suppress = 1; | 380 | p->dev.uevent_suppress = 1; |
| 381 | device_add(&p->dev); | 381 | err = device_add(&p->dev); |
| 382 | if (err) | ||
| 383 | goto out1; | ||
| 382 | partition_sysfs_add_subdir(p); | 384 | partition_sysfs_add_subdir(p); |
| 383 | p->dev.uevent_suppress = 0; | 385 | p->dev.uevent_suppress = 0; |
| 384 | if (flags & ADDPART_FLAG_WHOLEDISK) | 386 | if (flags & ADDPART_FLAG_WHOLEDISK) { |
| 385 | err = device_create_file(&p->dev, &dev_attr_whole_disk); | 387 | err = device_create_file(&p->dev, &dev_attr_whole_disk); |
| 388 | if (err) | ||
| 389 | goto out2; | ||
| 390 | } | ||
| 386 | 391 | ||
| 387 | /* suppress uevent if the disk supresses it */ | 392 | /* suppress uevent if the disk supresses it */ |
| 388 | if (!disk->dev.uevent_suppress) | 393 | if (!disk->dev.uevent_suppress) |
| 389 | kobject_uevent(&p->dev.kobj, KOBJ_ADD); | 394 | kobject_uevent(&p->dev.kobj, KOBJ_ADD); |
| 395 | |||
| 396 | return 0; | ||
| 397 | |||
| 398 | out2: | ||
| 399 | device_del(&p->dev); | ||
| 400 | out1: | ||
| 401 | put_device(&p->dev); | ||
| 402 | free_part_stats(p); | ||
| 403 | out0: | ||
| 404 | kfree(p); | ||
| 405 | return err; | ||
| 390 | } | 406 | } |
| 391 | 407 | ||
| 392 | /* Not exported, helper to add_disk(). */ | 408 | /* Not exported, helper to add_disk(). */ |
| @@ -483,10 +499,16 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
| 483 | if (!size) | 499 | if (!size) |
| 484 | continue; | 500 | continue; |
| 485 | if (from + size > get_capacity(disk)) { | 501 | if (from + size > get_capacity(disk)) { |
| 486 | printk(" %s: p%d exceeds device capacity\n", | 502 | printk(KERN_ERR " %s: p%d exceeds device capacity\n", |
| 487 | disk->disk_name, p); | 503 | disk->disk_name, p); |
| 504 | continue; | ||
| 505 | } | ||
| 506 | res = add_partition(disk, p, from, size, state->parts[p].flags); | ||
| 507 | if (res) { | ||
| 508 | printk(KERN_ERR " %s: p%d could not be added: %d\n", | ||
| 509 | disk->disk_name, p, -res); | ||
| 510 | continue; | ||
| 488 | } | 511 | } |
| 489 | add_partition(disk, p, from, size, state->parts[p].flags); | ||
| 490 | #ifdef CONFIG_BLK_DEV_MD | 512 | #ifdef CONFIG_BLK_DEV_MD |
| 491 | if (state->parts[p].flags & ADDPART_FLAG_RAID) | 513 | if (state->parts[p].flags & ADDPART_FLAG_RAID) |
| 492 | md_autodetect_dev(bdev->bd_dev+p); | 514 | md_autodetect_dev(bdev->bd_dev+p); |
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index e7b07006bc41..038a6022152f 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c | |||
| @@ -95,13 +95,6 @@ | |||
| 95 | #include "check.h" | 95 | #include "check.h" |
| 96 | #include "efi.h" | 96 | #include "efi.h" |
| 97 | 97 | ||
| 98 | #undef EFI_DEBUG | ||
| 99 | #ifdef EFI_DEBUG | ||
| 100 | #define Dprintk(x...) printk(KERN_DEBUG x) | ||
| 101 | #else | ||
| 102 | #define Dprintk(x...) | ||
| 103 | #endif | ||
| 104 | |||
| 105 | /* This allows a kernel command line option 'gpt' to override | 98 | /* This allows a kernel command line option 'gpt' to override |
| 106 | * the test for invalid PMBR. Not __initdata because reloading | 99 | * the test for invalid PMBR. Not __initdata because reloading |
| 107 | * the partition tables happens after init too. | 100 | * the partition tables happens after init too. |
| @@ -305,10 +298,10 @@ is_gpt_valid(struct block_device *bdev, u64 lba, | |||
| 305 | 298 | ||
| 306 | /* Check the GUID Partition Table signature */ | 299 | /* Check the GUID Partition Table signature */ |
| 307 | if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { | 300 | if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { |
| 308 | Dprintk("GUID Partition Table Header signature is wrong:" | 301 | pr_debug("GUID Partition Table Header signature is wrong:" |
| 309 | "%lld != %lld\n", | 302 | "%lld != %lld\n", |
| 310 | (unsigned long long)le64_to_cpu((*gpt)->signature), | 303 | (unsigned long long)le64_to_cpu((*gpt)->signature), |
| 311 | (unsigned long long)GPT_HEADER_SIGNATURE); | 304 | (unsigned long long)GPT_HEADER_SIGNATURE); |
| 312 | goto fail; | 305 | goto fail; |
| 313 | } | 306 | } |
| 314 | 307 | ||
| @@ -318,9 +311,8 @@ is_gpt_valid(struct block_device *bdev, u64 lba, | |||
| 318 | crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); | 311 | crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); |
| 319 | 312 | ||
| 320 | if (crc != origcrc) { | 313 | if (crc != origcrc) { |
| 321 | Dprintk | 314 | pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n", |
| 322 | ("GUID Partition Table Header CRC is wrong: %x != %x\n", | 315 | crc, origcrc); |
| 323 | crc, origcrc); | ||
| 324 | goto fail; | 316 | goto fail; |
| 325 | } | 317 | } |
| 326 | (*gpt)->header_crc32 = cpu_to_le32(origcrc); | 318 | (*gpt)->header_crc32 = cpu_to_le32(origcrc); |
| @@ -328,9 +320,9 @@ is_gpt_valid(struct block_device *bdev, u64 lba, | |||
| 328 | /* Check that the my_lba entry points to the LBA that contains | 320 | /* Check that the my_lba entry points to the LBA that contains |
| 329 | * the GUID Partition Table */ | 321 | * the GUID Partition Table */ |
| 330 | if (le64_to_cpu((*gpt)->my_lba) != lba) { | 322 | if (le64_to_cpu((*gpt)->my_lba) != lba) { |
| 331 | Dprintk("GPT my_lba incorrect: %lld != %lld\n", | 323 | pr_debug("GPT my_lba incorrect: %lld != %lld\n", |
| 332 | (unsigned long long)le64_to_cpu((*gpt)->my_lba), | 324 | (unsigned long long)le64_to_cpu((*gpt)->my_lba), |
| 333 | (unsigned long long)lba); | 325 | (unsigned long long)lba); |
| 334 | goto fail; | 326 | goto fail; |
| 335 | } | 327 | } |
| 336 | 328 | ||
| @@ -339,15 +331,15 @@ is_gpt_valid(struct block_device *bdev, u64 lba, | |||
| 339 | */ | 331 | */ |
| 340 | lastlba = last_lba(bdev); | 332 | lastlba = last_lba(bdev); |
| 341 | if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { | 333 | if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { |
| 342 | Dprintk("GPT: first_usable_lba incorrect: %lld > %lld\n", | 334 | pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n", |
| 343 | (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba), | 335 | (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba), |
| 344 | (unsigned long long)lastlba); | 336 | (unsigned long long)lastlba); |
| 345 | goto fail; | 337 | goto fail; |
| 346 | } | 338 | } |
| 347 | if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { | 339 | if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { |
| 348 | Dprintk("GPT: last_usable_lba incorrect: %lld > %lld\n", | 340 | pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n", |
| 349 | (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), | 341 | (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), |
| 350 | (unsigned long long)lastlba); | 342 | (unsigned long long)lastlba); |
| 351 | goto fail; | 343 | goto fail; |
| 352 | } | 344 | } |
| 353 | 345 | ||
| @@ -360,7 +352,7 @@ is_gpt_valid(struct block_device *bdev, u64 lba, | |||
| 360 | le32_to_cpu((*gpt)->sizeof_partition_entry)); | 352 | le32_to_cpu((*gpt)->sizeof_partition_entry)); |
| 361 | 353 | ||
| 362 | if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { | 354 | if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { |
| 363 | Dprintk("GUID Partitition Entry Array CRC check failed.\n"); | 355 | pr_debug("GUID Partitition Entry Array CRC check failed.\n"); |
| 364 | goto fail_ptes; | 356 | goto fail_ptes; |
| 365 | } | 357 | } |
| 366 | 358 | ||
| @@ -616,7 +608,7 @@ efi_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
| 616 | return 0; | 608 | return 0; |
| 617 | } | 609 | } |
| 618 | 610 | ||
| 619 | Dprintk("GUID Partition Table is valid! Yea!\n"); | 611 | pr_debug("GUID Partition Table is valid! Yea!\n"); |
| 620 | 612 | ||
| 621 | for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { | 613 | for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { |
| 622 | if (!is_pte_valid(&ptes[i], last_lba(bdev))) | 614 | if (!is_pte_valid(&ptes[i], last_lba(bdev))) |
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index 0fdda2e8a4cc..8652fb99e962 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c | |||
| @@ -133,17 +133,17 @@ static bool ldm_parse_privhead(const u8 *data, struct privhead *ph) | |||
| 133 | bool is_vista = false; | 133 | bool is_vista = false; |
| 134 | 134 | ||
| 135 | BUG_ON(!data || !ph); | 135 | BUG_ON(!data || !ph); |
| 136 | if (MAGIC_PRIVHEAD != BE64(data)) { | 136 | if (MAGIC_PRIVHEAD != get_unaligned_be64(data)) { |
| 137 | ldm_error("Cannot find PRIVHEAD structure. LDM database is" | 137 | ldm_error("Cannot find PRIVHEAD structure. LDM database is" |
| 138 | " corrupt. Aborting."); | 138 | " corrupt. Aborting."); |
| 139 | return false; | 139 | return false; |
| 140 | } | 140 | } |
| 141 | ph->ver_major = BE16(data + 0x000C); | 141 | ph->ver_major = get_unaligned_be16(data + 0x000C); |
| 142 | ph->ver_minor = BE16(data + 0x000E); | 142 | ph->ver_minor = get_unaligned_be16(data + 0x000E); |
| 143 | ph->logical_disk_start = BE64(data + 0x011B); | 143 | ph->logical_disk_start = get_unaligned_be64(data + 0x011B); |
| 144 | ph->logical_disk_size = BE64(data + 0x0123); | 144 | ph->logical_disk_size = get_unaligned_be64(data + 0x0123); |
| 145 | ph->config_start = BE64(data + 0x012B); | 145 | ph->config_start = get_unaligned_be64(data + 0x012B); |
| 146 | ph->config_size = BE64(data + 0x0133); | 146 | ph->config_size = get_unaligned_be64(data + 0x0133); |
| 147 | /* Version 2.11 is Win2k/XP and version 2.12 is Vista. */ | 147 | /* Version 2.11 is Win2k/XP and version 2.12 is Vista. */ |
| 148 | if (ph->ver_major == 2 && ph->ver_minor == 12) | 148 | if (ph->ver_major == 2 && ph->ver_minor == 12) |
| 149 | is_vista = true; | 149 | is_vista = true; |
| @@ -191,14 +191,14 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc) | |||
| 191 | { | 191 | { |
| 192 | BUG_ON (!data || !toc); | 192 | BUG_ON (!data || !toc); |
| 193 | 193 | ||
| 194 | if (MAGIC_TOCBLOCK != BE64 (data)) { | 194 | if (MAGIC_TOCBLOCK != get_unaligned_be64(data)) { |
| 195 | ldm_crit ("Cannot find TOCBLOCK, database may be corrupt."); | 195 | ldm_crit ("Cannot find TOCBLOCK, database may be corrupt."); |
| 196 | return false; | 196 | return false; |
| 197 | } | 197 | } |
| 198 | strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name)); | 198 | strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name)); |
| 199 | toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0; | 199 | toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0; |
| 200 | toc->bitmap1_start = BE64 (data + 0x2E); | 200 | toc->bitmap1_start = get_unaligned_be64(data + 0x2E); |
| 201 | toc->bitmap1_size = BE64 (data + 0x36); | 201 | toc->bitmap1_size = get_unaligned_be64(data + 0x36); |
| 202 | 202 | ||
| 203 | if (strncmp (toc->bitmap1_name, TOC_BITMAP1, | 203 | if (strncmp (toc->bitmap1_name, TOC_BITMAP1, |
| 204 | sizeof (toc->bitmap1_name)) != 0) { | 204 | sizeof (toc->bitmap1_name)) != 0) { |
| @@ -208,8 +208,8 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc) | |||
| 208 | } | 208 | } |
| 209 | strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name)); | 209 | strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name)); |
| 210 | toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0; | 210 | toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0; |
| 211 | toc->bitmap2_start = BE64 (data + 0x50); | 211 | toc->bitmap2_start = get_unaligned_be64(data + 0x50); |
| 212 | toc->bitmap2_size = BE64 (data + 0x58); | 212 | toc->bitmap2_size = get_unaligned_be64(data + 0x58); |
| 213 | if (strncmp (toc->bitmap2_name, TOC_BITMAP2, | 213 | if (strncmp (toc->bitmap2_name, TOC_BITMAP2, |
| 214 | sizeof (toc->bitmap2_name)) != 0) { | 214 | sizeof (toc->bitmap2_name)) != 0) { |
| 215 | ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.", | 215 | ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.", |
| @@ -237,22 +237,22 @@ static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm) | |||
| 237 | { | 237 | { |
| 238 | BUG_ON (!data || !vm); | 238 | BUG_ON (!data || !vm); |
| 239 | 239 | ||
| 240 | if (MAGIC_VMDB != BE32 (data)) { | 240 | if (MAGIC_VMDB != get_unaligned_be32(data)) { |
| 241 | ldm_crit ("Cannot find the VMDB, database may be corrupt."); | 241 | ldm_crit ("Cannot find the VMDB, database may be corrupt."); |
| 242 | return false; | 242 | return false; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | vm->ver_major = BE16 (data + 0x12); | 245 | vm->ver_major = get_unaligned_be16(data + 0x12); |
| 246 | vm->ver_minor = BE16 (data + 0x14); | 246 | vm->ver_minor = get_unaligned_be16(data + 0x14); |
| 247 | if ((vm->ver_major != 4) || (vm->ver_minor != 10)) { | 247 | if ((vm->ver_major != 4) || (vm->ver_minor != 10)) { |
| 248 | ldm_error ("Expected VMDB version %d.%d, got %d.%d. " | 248 | ldm_error ("Expected VMDB version %d.%d, got %d.%d. " |
| 249 | "Aborting.", 4, 10, vm->ver_major, vm->ver_minor); | 249 | "Aborting.", 4, 10, vm->ver_major, vm->ver_minor); |
| 250 | return false; | 250 | return false; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | vm->vblk_size = BE32 (data + 0x08); | 253 | vm->vblk_size = get_unaligned_be32(data + 0x08); |
| 254 | vm->vblk_offset = BE32 (data + 0x0C); | 254 | vm->vblk_offset = get_unaligned_be32(data + 0x0C); |
| 255 | vm->last_vblk_seq = BE32 (data + 0x04); | 255 | vm->last_vblk_seq = get_unaligned_be32(data + 0x04); |
| 256 | 256 | ||
| 257 | ldm_debug ("Parsed VMDB successfully."); | 257 | ldm_debug ("Parsed VMDB successfully."); |
| 258 | return true; | 258 | return true; |
| @@ -507,7 +507,7 @@ static bool ldm_validate_vmdb (struct block_device *bdev, unsigned long base, | |||
| 507 | goto out; /* Already logged */ | 507 | goto out; /* Already logged */ |
| 508 | 508 | ||
| 509 | /* Are there uncommitted transactions? */ | 509 | /* Are there uncommitted transactions? */ |
| 510 | if (BE16(data + 0x10) != 0x01) { | 510 | if (get_unaligned_be16(data + 0x10) != 0x01) { |
| 511 | ldm_crit ("Database is not in a consistent state. Aborting."); | 511 | ldm_crit ("Database is not in a consistent state. Aborting."); |
| 512 | goto out; | 512 | goto out; |
| 513 | } | 513 | } |
| @@ -802,7 +802,7 @@ static bool ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb) | |||
| 802 | return false; | 802 | return false; |
| 803 | 803 | ||
| 804 | len += VBLK_SIZE_CMP3; | 804 | len += VBLK_SIZE_CMP3; |
| 805 | if (len != BE32 (buffer + 0x14)) | 805 | if (len != get_unaligned_be32(buffer + 0x14)) |
| 806 | return false; | 806 | return false; |
| 807 | 807 | ||
| 808 | comp = &vb->vblk.comp; | 808 | comp = &vb->vblk.comp; |
| @@ -851,7 +851,7 @@ static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb) | |||
| 851 | return false; | 851 | return false; |
| 852 | 852 | ||
| 853 | len += VBLK_SIZE_DGR3; | 853 | len += VBLK_SIZE_DGR3; |
| 854 | if (len != BE32 (buffer + 0x14)) | 854 | if (len != get_unaligned_be32(buffer + 0x14)) |
| 855 | return false; | 855 | return false; |
| 856 | 856 | ||
| 857 | dgrp = &vb->vblk.dgrp; | 857 | dgrp = &vb->vblk.dgrp; |
| @@ -895,7 +895,7 @@ static bool ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb) | |||
| 895 | return false; | 895 | return false; |
| 896 | 896 | ||
| 897 | len += VBLK_SIZE_DGR4; | 897 | len += VBLK_SIZE_DGR4; |
| 898 | if (len != BE32 (buffer + 0x14)) | 898 | if (len != get_unaligned_be32(buffer + 0x14)) |
| 899 | return false; | 899 | return false; |
| 900 | 900 | ||
| 901 | dgrp = &vb->vblk.dgrp; | 901 | dgrp = &vb->vblk.dgrp; |
| @@ -931,7 +931,7 @@ static bool ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb) | |||
| 931 | return false; | 931 | return false; |
| 932 | 932 | ||
| 933 | len += VBLK_SIZE_DSK3; | 933 | len += VBLK_SIZE_DSK3; |
| 934 | if (len != BE32 (buffer + 0x14)) | 934 | if (len != get_unaligned_be32(buffer + 0x14)) |
| 935 | return false; | 935 | return false; |
| 936 | 936 | ||
| 937 | disk = &vb->vblk.disk; | 937 | disk = &vb->vblk.disk; |
| @@ -968,7 +968,7 @@ static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb) | |||
| 968 | return false; | 968 | return false; |
| 969 | 969 | ||
| 970 | len += VBLK_SIZE_DSK4; | 970 | len += VBLK_SIZE_DSK4; |
| 971 | if (len != BE32 (buffer + 0x14)) | 971 | if (len != get_unaligned_be32(buffer + 0x14)) |
| 972 | return false; | 972 | return false; |
| 973 | 973 | ||
| 974 | disk = &vb->vblk.disk; | 974 | disk = &vb->vblk.disk; |
| @@ -1034,14 +1034,14 @@ static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb) | |||
| 1034 | return false; | 1034 | return false; |
| 1035 | } | 1035 | } |
| 1036 | len += VBLK_SIZE_PRT3; | 1036 | len += VBLK_SIZE_PRT3; |
| 1037 | if (len > BE32(buffer + 0x14)) { | 1037 | if (len > get_unaligned_be32(buffer + 0x14)) { |
| 1038 | ldm_error("len %d > BE32(buffer + 0x14) %d", len, | 1038 | ldm_error("len %d > BE32(buffer + 0x14) %d", len, |
| 1039 | BE32(buffer + 0x14)); | 1039 | get_unaligned_be32(buffer + 0x14)); |
| 1040 | return false; | 1040 | return false; |
| 1041 | } | 1041 | } |
| 1042 | part = &vb->vblk.part; | 1042 | part = &vb->vblk.part; |
| 1043 | part->start = BE64(buffer + 0x24 + r_name); | 1043 | part->start = get_unaligned_be64(buffer + 0x24 + r_name); |
| 1044 | part->volume_offset = BE64(buffer + 0x2C + r_name); | 1044 | part->volume_offset = get_unaligned_be64(buffer + 0x2C + r_name); |
| 1045 | part->size = ldm_get_vnum(buffer + 0x34 + r_name); | 1045 | part->size = ldm_get_vnum(buffer + 0x34 + r_name); |
| 1046 | part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size); | 1046 | part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size); |
| 1047 | part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent); | 1047 | part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent); |
| @@ -1139,9 +1139,9 @@ static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb) | |||
| 1139 | return false; | 1139 | return false; |
| 1140 | } | 1140 | } |
| 1141 | len += VBLK_SIZE_VOL5; | 1141 | len += VBLK_SIZE_VOL5; |
| 1142 | if (len > BE32(buffer + 0x14)) { | 1142 | if (len > get_unaligned_be32(buffer + 0x14)) { |
| 1143 | ldm_error("len %d > BE32(buffer + 0x14) %d", len, | 1143 | ldm_error("len %d > BE32(buffer + 0x14) %d", len, |
| 1144 | BE32(buffer + 0x14)); | 1144 | get_unaligned_be32(buffer + 0x14)); |
| 1145 | return false; | 1145 | return false; |
| 1146 | } | 1146 | } |
| 1147 | volu = &vb->vblk.volu; | 1147 | volu = &vb->vblk.volu; |
| @@ -1294,9 +1294,9 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) | |||
| 1294 | 1294 | ||
| 1295 | BUG_ON (!data || !frags); | 1295 | BUG_ON (!data || !frags); |
| 1296 | 1296 | ||
| 1297 | group = BE32 (data + 0x08); | 1297 | group = get_unaligned_be32(data + 0x08); |
| 1298 | rec = BE16 (data + 0x0C); | 1298 | rec = get_unaligned_be16(data + 0x0C); |
| 1299 | num = BE16 (data + 0x0E); | 1299 | num = get_unaligned_be16(data + 0x0E); |
| 1300 | if ((num < 1) || (num > 4)) { | 1300 | if ((num < 1) || (num > 4)) { |
| 1301 | ldm_error ("A VBLK claims to have %d parts.", num); | 1301 | ldm_error ("A VBLK claims to have %d parts.", num); |
| 1302 | return false; | 1302 | return false; |
| @@ -1425,12 +1425,12 @@ static bool ldm_get_vblks (struct block_device *bdev, unsigned long base, | |||
| 1425 | } | 1425 | } |
| 1426 | 1426 | ||
| 1427 | for (v = 0; v < perbuf; v++, data+=size) { /* For each vblk */ | 1427 | for (v = 0; v < perbuf; v++, data+=size) { /* For each vblk */ |
| 1428 | if (MAGIC_VBLK != BE32 (data)) { | 1428 | if (MAGIC_VBLK != get_unaligned_be32(data)) { |
| 1429 | ldm_error ("Expected to find a VBLK."); | 1429 | ldm_error ("Expected to find a VBLK."); |
| 1430 | goto out; | 1430 | goto out; |
| 1431 | } | 1431 | } |
| 1432 | 1432 | ||
| 1433 | recs = BE16 (data + 0x0E); /* Number of records */ | 1433 | recs = get_unaligned_be16(data + 0x0E); /* Number of records */ |
| 1434 | if (recs == 1) { | 1434 | if (recs == 1) { |
| 1435 | if (!ldm_ldmdb_add (data, size, ldb)) | 1435 | if (!ldm_ldmdb_add (data, size, ldb)) |
| 1436 | goto out; /* Already logged */ | 1436 | goto out; /* Already logged */ |
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h index 80f63b5fdd9f..30e08e809c1d 100644 --- a/fs/partitions/ldm.h +++ b/fs/partitions/ldm.h | |||
| @@ -98,11 +98,6 @@ struct parsed_partitions; | |||
| 98 | #define TOC_BITMAP1 "config" /* Names of the two defined */ | 98 | #define TOC_BITMAP1 "config" /* Names of the two defined */ |
| 99 | #define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */ | 99 | #define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */ |
| 100 | 100 | ||
| 101 | /* Most numbers we deal with are big-endian and won't be aligned. */ | ||
| 102 | #define BE16(x) ((u16)be16_to_cpu(get_unaligned((__be16*)(x)))) | ||
| 103 | #define BE32(x) ((u32)be32_to_cpu(get_unaligned((__be32*)(x)))) | ||
| 104 | #define BE64(x) ((u64)be64_to_cpu(get_unaligned((__be64*)(x)))) | ||
| 105 | |||
| 106 | /* Borrowed from msdos.c */ | 101 | /* Borrowed from msdos.c */ |
| 107 | #define SYS_IND(p) (get_unaligned(&(p)->sys_ind)) | 102 | #define SYS_IND(p) (get_unaligned(&(p)->sys_ind)) |
| 108 | 103 | ||
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig new file mode 100644 index 000000000000..73cd7a418f06 --- /dev/null +++ b/fs/proc/Kconfig | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | config PROC_FS | ||
| 2 | bool "/proc file system support" if EMBEDDED | ||
| 3 | default y | ||
| 4 | help | ||
| 5 | This is a virtual file system providing information about the status | ||
| 6 | of the system. "Virtual" means that it doesn't take up any space on | ||
| 7 | your hard disk: the files are created on the fly by the kernel when | ||
| 8 | you try to access them. Also, you cannot read the files with older | ||
| 9 | version of the program less: you need to use more or cat. | ||
| 10 | |||
| 11 | It's totally cool; for example, "cat /proc/interrupts" gives | ||
| 12 | information about what the different IRQs are used for at the moment | ||
| 13 | (there is a small number of Interrupt ReQuest lines in your computer | ||
| 14 | that are used by the attached devices to gain the CPU's attention -- | ||
| 15 | often a source of trouble if two devices are mistakenly configured | ||
| 16 | to use the same IRQ). The program procinfo to display some | ||
| 17 | information about your system gathered from the /proc file system. | ||
| 18 | |||
| 19 | Before you can use the /proc file system, it has to be mounted, | ||
| 20 | meaning it has to be given a location in the directory hierarchy. | ||
| 21 | That location should be /proc. A command such as "mount -t proc proc | ||
| 22 | /proc" or the equivalent line in /etc/fstab does the job. | ||
| 23 | |||
| 24 | The /proc file system is explained in the file | ||
| 25 | <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage | ||
| 26 | ("man 5 proc"). | ||
| 27 | |||
| 28 | This option will enlarge your kernel by about 67 KB. Several | ||
| 29 | programs depend on this, so everyone should say Y here. | ||
| 30 | |||
| 31 | config PROC_KCORE | ||
| 32 | bool "/proc/kcore support" if !ARM | ||
| 33 | depends on PROC_FS && MMU | ||
| 34 | |||
| 35 | config PROC_VMCORE | ||
| 36 | bool "/proc/vmcore support (EXPERIMENTAL)" | ||
| 37 | depends on PROC_FS && CRASH_DUMP | ||
| 38 | default y | ||
| 39 | help | ||
| 40 | Exports the dump image of crashed kernel in ELF format. | ||
| 41 | |||
| 42 | config PROC_SYSCTL | ||
| 43 | bool "Sysctl support (/proc/sys)" if EMBEDDED | ||
| 44 | depends on PROC_FS | ||
| 45 | select SYSCTL | ||
| 46 | default y | ||
| 47 | ---help--- | ||
| 48 | The sysctl interface provides a means of dynamically changing | ||
| 49 | certain kernel parameters and variables on the fly without requiring | ||
| 50 | a recompile of the kernel or reboot of the system. The primary | ||
| 51 | interface is through /proc/sys. If you say Y here a tree of | ||
| 52 | modifiable sysctl entries will be generated beneath the | ||
| 53 | /proc/sys directory. They are explained in the files | ||
| 54 | in <file:Documentation/sysctl/>. Note that enabling this | ||
| 55 | option will enlarge the kernel by at least 8 KB. | ||
| 56 | |||
| 57 | As it is generally a good thing, you should say Y here unless | ||
| 58 | building a kernel for install/rescue disks or your system is very | ||
| 59 | limited in memory. | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index 58c3e6a8e15e..a891fe4cb43b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -2376,29 +2376,82 @@ static int proc_base_fill_cache(struct file *filp, void *dirent, | |||
| 2376 | } | 2376 | } |
| 2377 | 2377 | ||
| 2378 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2378 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2379 | static int proc_pid_io_accounting(struct task_struct *task, char *buffer) | 2379 | static int do_io_accounting(struct task_struct *task, char *buffer, int whole) |
| 2380 | { | 2380 | { |
| 2381 | u64 rchar, wchar, syscr, syscw; | ||
| 2382 | struct task_io_accounting ioac; | ||
| 2383 | |||
| 2384 | if (!whole) { | ||
| 2385 | rchar = task->rchar; | ||
| 2386 | wchar = task->wchar; | ||
| 2387 | syscr = task->syscr; | ||
| 2388 | syscw = task->syscw; | ||
| 2389 | memcpy(&ioac, &task->ioac, sizeof(ioac)); | ||
| 2390 | } else { | ||
| 2391 | unsigned long flags; | ||
| 2392 | struct task_struct *t = task; | ||
| 2393 | rchar = wchar = syscr = syscw = 0; | ||
| 2394 | memset(&ioac, 0, sizeof(ioac)); | ||
| 2395 | |||
| 2396 | rcu_read_lock(); | ||
| 2397 | do { | ||
| 2398 | rchar += t->rchar; | ||
| 2399 | wchar += t->wchar; | ||
| 2400 | syscr += t->syscr; | ||
| 2401 | syscw += t->syscw; | ||
| 2402 | |||
| 2403 | ioac.read_bytes += t->ioac.read_bytes; | ||
| 2404 | ioac.write_bytes += t->ioac.write_bytes; | ||
| 2405 | ioac.cancelled_write_bytes += | ||
| 2406 | t->ioac.cancelled_write_bytes; | ||
| 2407 | t = next_thread(t); | ||
| 2408 | } while (t != task); | ||
| 2409 | rcu_read_unlock(); | ||
| 2410 | |||
| 2411 | if (lock_task_sighand(task, &flags)) { | ||
| 2412 | struct signal_struct *sig = task->signal; | ||
| 2413 | |||
| 2414 | rchar += sig->rchar; | ||
| 2415 | wchar += sig->wchar; | ||
| 2416 | syscr += sig->syscr; | ||
| 2417 | syscw += sig->syscw; | ||
| 2418 | |||
| 2419 | ioac.read_bytes += sig->ioac.read_bytes; | ||
| 2420 | ioac.write_bytes += sig->ioac.write_bytes; | ||
| 2421 | ioac.cancelled_write_bytes += | ||
| 2422 | sig->ioac.cancelled_write_bytes; | ||
| 2423 | |||
| 2424 | unlock_task_sighand(task, &flags); | ||
| 2425 | } | ||
| 2426 | } | ||
| 2427 | |||
| 2381 | return sprintf(buffer, | 2428 | return sprintf(buffer, |
| 2382 | #ifdef CONFIG_TASK_XACCT | ||
| 2383 | "rchar: %llu\n" | 2429 | "rchar: %llu\n" |
| 2384 | "wchar: %llu\n" | 2430 | "wchar: %llu\n" |
| 2385 | "syscr: %llu\n" | 2431 | "syscr: %llu\n" |
| 2386 | "syscw: %llu\n" | 2432 | "syscw: %llu\n" |
| 2387 | #endif | ||
| 2388 | "read_bytes: %llu\n" | 2433 | "read_bytes: %llu\n" |
| 2389 | "write_bytes: %llu\n" | 2434 | "write_bytes: %llu\n" |
| 2390 | "cancelled_write_bytes: %llu\n", | 2435 | "cancelled_write_bytes: %llu\n", |
| 2391 | #ifdef CONFIG_TASK_XACCT | 2436 | (unsigned long long)rchar, |
| 2392 | (unsigned long long)task->rchar, | 2437 | (unsigned long long)wchar, |
| 2393 | (unsigned long long)task->wchar, | 2438 | (unsigned long long)syscr, |
| 2394 | (unsigned long long)task->syscr, | 2439 | (unsigned long long)syscw, |
| 2395 | (unsigned long long)task->syscw, | 2440 | (unsigned long long)ioac.read_bytes, |
| 2396 | #endif | 2441 | (unsigned long long)ioac.write_bytes, |
| 2397 | (unsigned long long)task->ioac.read_bytes, | 2442 | (unsigned long long)ioac.cancelled_write_bytes); |
| 2398 | (unsigned long long)task->ioac.write_bytes, | 2443 | } |
| 2399 | (unsigned long long)task->ioac.cancelled_write_bytes); | 2444 | |
| 2445 | static int proc_tid_io_accounting(struct task_struct *task, char *buffer) | ||
| 2446 | { | ||
| 2447 | return do_io_accounting(task, buffer, 0); | ||
| 2400 | } | 2448 | } |
| 2401 | #endif | 2449 | |
| 2450 | static int proc_tgid_io_accounting(struct task_struct *task, char *buffer) | ||
| 2451 | { | ||
| 2452 | return do_io_accounting(task, buffer, 1); | ||
| 2453 | } | ||
| 2454 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
| 2402 | 2455 | ||
| 2403 | /* | 2456 | /* |
| 2404 | * Thread groups | 2457 | * Thread groups |
| @@ -2470,7 +2523,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2470 | REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter), | 2523 | REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter), |
| 2471 | #endif | 2524 | #endif |
| 2472 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2525 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2473 | INF("io", S_IRUGO, pid_io_accounting), | 2526 | INF("io", S_IRUGO, tgid_io_accounting), |
| 2474 | #endif | 2527 | #endif |
| 2475 | }; | 2528 | }; |
| 2476 | 2529 | ||
| @@ -2797,6 +2850,9 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2797 | #ifdef CONFIG_FAULT_INJECTION | 2850 | #ifdef CONFIG_FAULT_INJECTION |
| 2798 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), | 2851 | REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), |
| 2799 | #endif | 2852 | #endif |
| 2853 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
| 2854 | INF("io", S_IRUGO, tid_io_accounting), | ||
| 2855 | #endif | ||
| 2800 | }; | 2856 | }; |
| 2801 | 2857 | ||
| 2802 | static int proc_tid_base_readdir(struct file * filp, | 2858 | static int proc_tid_base_readdir(struct file * filp, |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 43e54e86cefd..bc0a0dd2d844 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
| @@ -597,6 +597,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent, | |||
| 597 | ent->pde_users = 0; | 597 | ent->pde_users = 0; |
| 598 | spin_lock_init(&ent->pde_unload_lock); | 598 | spin_lock_init(&ent->pde_unload_lock); |
| 599 | ent->pde_unload_completion = NULL; | 599 | ent->pde_unload_completion = NULL; |
| 600 | INIT_LIST_HEAD(&ent->pde_openers); | ||
| 600 | out: | 601 | out: |
| 601 | return ent; | 602 | return ent; |
| 602 | } | 603 | } |
| @@ -789,6 +790,19 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
| 789 | spin_unlock(&de->pde_unload_lock); | 790 | spin_unlock(&de->pde_unload_lock); |
| 790 | 791 | ||
| 791 | continue_removing: | 792 | continue_removing: |
| 793 | spin_lock(&de->pde_unload_lock); | ||
| 794 | while (!list_empty(&de->pde_openers)) { | ||
| 795 | struct pde_opener *pdeo; | ||
| 796 | |||
| 797 | pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh); | ||
| 798 | list_del(&pdeo->lh); | ||
| 799 | spin_unlock(&de->pde_unload_lock); | ||
| 800 | pdeo->release(pdeo->inode, pdeo->file); | ||
| 801 | kfree(pdeo); | ||
| 802 | spin_lock(&de->pde_unload_lock); | ||
| 803 | } | ||
| 804 | spin_unlock(&de->pde_unload_lock); | ||
| 805 | |||
| 792 | if (S_ISDIR(de->mode)) | 806 | if (S_ISDIR(de->mode)) |
| 793 | parent->nlink--; | 807 | parent->nlink--; |
| 794 | de->nlink = 0; | 808 | de->nlink = 0; |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index b08d10017911..02eca2ed9dd7 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
| @@ -111,27 +111,25 @@ int __init proc_init_inodecache(void) | |||
| 111 | return 0; | 111 | return 0; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static int proc_remount(struct super_block *sb, int *flags, char *data) | ||
| 115 | { | ||
| 116 | *flags |= MS_NODIRATIME; | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static const struct super_operations proc_sops = { | 114 | static const struct super_operations proc_sops = { |
| 121 | .alloc_inode = proc_alloc_inode, | 115 | .alloc_inode = proc_alloc_inode, |
| 122 | .destroy_inode = proc_destroy_inode, | 116 | .destroy_inode = proc_destroy_inode, |
| 123 | .drop_inode = generic_delete_inode, | 117 | .drop_inode = generic_delete_inode, |
| 124 | .delete_inode = proc_delete_inode, | 118 | .delete_inode = proc_delete_inode, |
| 125 | .statfs = simple_statfs, | 119 | .statfs = simple_statfs, |
| 126 | .remount_fs = proc_remount, | ||
| 127 | }; | 120 | }; |
| 128 | 121 | ||
| 129 | static void pde_users_dec(struct proc_dir_entry *pde) | 122 | static void __pde_users_dec(struct proc_dir_entry *pde) |
| 130 | { | 123 | { |
| 131 | spin_lock(&pde->pde_unload_lock); | ||
| 132 | pde->pde_users--; | 124 | pde->pde_users--; |
| 133 | if (pde->pde_unload_completion && pde->pde_users == 0) | 125 | if (pde->pde_unload_completion && pde->pde_users == 0) |
| 134 | complete(pde->pde_unload_completion); | 126 | complete(pde->pde_unload_completion); |
| 127 | } | ||
| 128 | |||
| 129 | static void pde_users_dec(struct proc_dir_entry *pde) | ||
| 130 | { | ||
| 131 | spin_lock(&pde->pde_unload_lock); | ||
| 132 | __pde_users_dec(pde); | ||
| 135 | spin_unlock(&pde->pde_unload_lock); | 133 | spin_unlock(&pde->pde_unload_lock); |
| 136 | } | 134 | } |
| 137 | 135 | ||
| @@ -318,36 +316,97 @@ static int proc_reg_open(struct inode *inode, struct file *file) | |||
| 318 | struct proc_dir_entry *pde = PDE(inode); | 316 | struct proc_dir_entry *pde = PDE(inode); |
| 319 | int rv = 0; | 317 | int rv = 0; |
| 320 | int (*open)(struct inode *, struct file *); | 318 | int (*open)(struct inode *, struct file *); |
| 319 | int (*release)(struct inode *, struct file *); | ||
| 320 | struct pde_opener *pdeo; | ||
| 321 | |||
| 322 | /* | ||
| 323 | * What for, you ask? Well, we can have open, rmmod, remove_proc_entry | ||
| 324 | * sequence. ->release won't be called because ->proc_fops will be | ||
| 325 | * cleared. Depending on complexity of ->release, consequences vary. | ||
| 326 | * | ||
| 327 | * We can't wait for mercy when close will be done for real, it's | ||
| 328 | * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release | ||
| 329 | * by hand in remove_proc_entry(). For this, save opener's credentials | ||
| 330 | * for later. | ||
| 331 | */ | ||
| 332 | pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL); | ||
| 333 | if (!pdeo) | ||
| 334 | return -ENOMEM; | ||
| 321 | 335 | ||
| 322 | spin_lock(&pde->pde_unload_lock); | 336 | spin_lock(&pde->pde_unload_lock); |
| 323 | if (!pde->proc_fops) { | 337 | if (!pde->proc_fops) { |
| 324 | spin_unlock(&pde->pde_unload_lock); | 338 | spin_unlock(&pde->pde_unload_lock); |
| 339 | kfree(pdeo); | ||
| 325 | return rv; | 340 | return rv; |
| 326 | } | 341 | } |
| 327 | pde->pde_users++; | 342 | pde->pde_users++; |
| 328 | open = pde->proc_fops->open; | 343 | open = pde->proc_fops->open; |
| 344 | release = pde->proc_fops->release; | ||
| 329 | spin_unlock(&pde->pde_unload_lock); | 345 | spin_unlock(&pde->pde_unload_lock); |
| 330 | 346 | ||
| 331 | if (open) | 347 | if (open) |
| 332 | rv = open(inode, file); | 348 | rv = open(inode, file); |
| 333 | 349 | ||
| 334 | pde_users_dec(pde); | 350 | spin_lock(&pde->pde_unload_lock); |
| 351 | if (rv == 0 && release) { | ||
| 352 | /* To know what to release. */ | ||
| 353 | pdeo->inode = inode; | ||
| 354 | pdeo->file = file; | ||
| 355 | /* Strictly for "too late" ->release in proc_reg_release(). */ | ||
| 356 | pdeo->release = release; | ||
| 357 | list_add(&pdeo->lh, &pde->pde_openers); | ||
| 358 | } else | ||
| 359 | kfree(pdeo); | ||
| 360 | __pde_users_dec(pde); | ||
| 361 | spin_unlock(&pde->pde_unload_lock); | ||
| 335 | return rv; | 362 | return rv; |
| 336 | } | 363 | } |
| 337 | 364 | ||
| 365 | static struct pde_opener *find_pde_opener(struct proc_dir_entry *pde, | ||
| 366 | struct inode *inode, struct file *file) | ||
| 367 | { | ||
| 368 | struct pde_opener *pdeo; | ||
| 369 | |||
| 370 | list_for_each_entry(pdeo, &pde->pde_openers, lh) { | ||
| 371 | if (pdeo->inode == inode && pdeo->file == file) | ||
| 372 | return pdeo; | ||
| 373 | } | ||
| 374 | return NULL; | ||
| 375 | } | ||
| 376 | |||
| 338 | static int proc_reg_release(struct inode *inode, struct file *file) | 377 | static int proc_reg_release(struct inode *inode, struct file *file) |
| 339 | { | 378 | { |
| 340 | struct proc_dir_entry *pde = PDE(inode); | 379 | struct proc_dir_entry *pde = PDE(inode); |
| 341 | int rv = 0; | 380 | int rv = 0; |
| 342 | int (*release)(struct inode *, struct file *); | 381 | int (*release)(struct inode *, struct file *); |
| 382 | struct pde_opener *pdeo; | ||
| 343 | 383 | ||
| 344 | spin_lock(&pde->pde_unload_lock); | 384 | spin_lock(&pde->pde_unload_lock); |
| 385 | pdeo = find_pde_opener(pde, inode, file); | ||
| 345 | if (!pde->proc_fops) { | 386 | if (!pde->proc_fops) { |
| 346 | spin_unlock(&pde->pde_unload_lock); | 387 | /* |
| 388 | * Can't simply exit, __fput() will think that everything is OK, | ||
| 389 | * and move on to freeing struct file. remove_proc_entry() will | ||
| 390 | * find slacker in opener's list and will try to do non-trivial | ||
| 391 | * things with struct file. Therefore, remove opener from list. | ||
| 392 | * | ||
| 393 | * But if opener is removed from list, who will ->release it? | ||
| 394 | */ | ||
| 395 | if (pdeo) { | ||
| 396 | list_del(&pdeo->lh); | ||
| 397 | spin_unlock(&pde->pde_unload_lock); | ||
| 398 | rv = pdeo->release(inode, file); | ||
| 399 | kfree(pdeo); | ||
| 400 | } else | ||
| 401 | spin_unlock(&pde->pde_unload_lock); | ||
| 347 | return rv; | 402 | return rv; |
| 348 | } | 403 | } |
| 349 | pde->pde_users++; | 404 | pde->pde_users++; |
| 350 | release = pde->proc_fops->release; | 405 | release = pde->proc_fops->release; |
| 406 | if (pdeo) { | ||
| 407 | list_del(&pdeo->lh); | ||
| 408 | kfree(pdeo); | ||
| 409 | } | ||
| 351 | spin_unlock(&pde->pde_unload_lock); | 410 | spin_unlock(&pde->pde_unload_lock); |
| 352 | 411 | ||
| 353 | if (release) | 412 | if (release) |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 28cbca805905..442202314d53 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
| @@ -63,6 +63,7 @@ extern const struct file_operations proc_smaps_operations; | |||
| 63 | extern const struct file_operations proc_clear_refs_operations; | 63 | extern const struct file_operations proc_clear_refs_operations; |
| 64 | extern const struct file_operations proc_pagemap_operations; | 64 | extern const struct file_operations proc_pagemap_operations; |
| 65 | extern const struct file_operations proc_net_operations; | 65 | extern const struct file_operations proc_net_operations; |
| 66 | extern const struct file_operations proc_kmsg_operations; | ||
| 66 | extern const struct inode_operations proc_net_inode_operations; | 67 | extern const struct inode_operations proc_net_inode_operations; |
| 67 | 68 | ||
| 68 | void free_proc_entry(struct proc_dir_entry *de); | 69 | void free_proc_entry(struct proc_dir_entry *de); |
| @@ -88,3 +89,10 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino, | |||
| 88 | struct dentry *dentry); | 89 | struct dentry *dentry); |
| 89 | int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, | 90 | int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent, |
| 90 | filldir_t filldir); | 91 | filldir_t filldir); |
| 92 | |||
| 93 | struct pde_opener { | ||
| 94 | struct inode *inode; | ||
| 95 | struct file *file; | ||
| 96 | int (*release)(struct inode *, struct file *); | ||
| 97 | struct list_head lh; | ||
| 98 | }; | ||
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index e78c81fcf547..c2370c76fb71 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
| @@ -23,6 +23,10 @@ | |||
| 23 | 23 | ||
| 24 | #define CORE_STR "CORE" | 24 | #define CORE_STR "CORE" |
| 25 | 25 | ||
| 26 | #ifndef ELF_CORE_EFLAGS | ||
| 27 | #define ELF_CORE_EFLAGS 0 | ||
| 28 | #endif | ||
| 29 | |||
| 26 | static int open_kcore(struct inode * inode, struct file * filp) | 30 | static int open_kcore(struct inode * inode, struct file * filp) |
| 27 | { | 31 | { |
| 28 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; | 32 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; |
| @@ -164,11 +168,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff) | |||
| 164 | elf->e_entry = 0; | 168 | elf->e_entry = 0; |
| 165 | elf->e_phoff = sizeof(struct elfhdr); | 169 | elf->e_phoff = sizeof(struct elfhdr); |
| 166 | elf->e_shoff = 0; | 170 | elf->e_shoff = 0; |
| 167 | #if defined(CONFIG_H8300) | 171 | elf->e_flags = ELF_CORE_EFLAGS; |
| 168 | elf->e_flags = ELF_FLAGS; | ||
| 169 | #else | ||
| 170 | elf->e_flags = 0; | ||
| 171 | #endif | ||
| 172 | elf->e_ehsize = sizeof(struct elfhdr); | 172 | elf->e_ehsize = sizeof(struct elfhdr); |
| 173 | elf->e_phentsize= sizeof(struct elf_phdr); | 173 | elf->e_phentsize= sizeof(struct elf_phdr); |
| 174 | elf->e_phnum = nphdr; | 174 | elf->e_phnum = nphdr; |
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index ff3b90b56e9d..9fd5df3f40ce 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
| 16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
| 17 | 17 | ||
| 18 | #include "internal.h" | ||
| 19 | |||
| 18 | extern wait_queue_head_t log_wait; | 20 | extern wait_queue_head_t log_wait; |
| 19 | 21 | ||
| 20 | extern int do_syslog(int type, char __user *bug, int count); | 22 | extern int do_syslog(int type, char __user *bug, int count); |
diff --git a/fs/quota.c b/fs/quota.c index db1cc9f3c7aa..7f4386ebc23a 100644 --- a/fs/quota.c +++ b/fs/quota.c | |||
| @@ -186,7 +186,7 @@ static void quota_sync_sb(struct super_block *sb, int type) | |||
| 186 | 186 | ||
| 187 | void sync_dquots(struct super_block *sb, int type) | 187 | void sync_dquots(struct super_block *sb, int type) |
| 188 | { | 188 | { |
| 189 | int cnt, dirty; | 189 | int cnt; |
| 190 | 190 | ||
| 191 | if (sb) { | 191 | if (sb) { |
| 192 | if (sb->s_qcop->quota_sync) | 192 | if (sb->s_qcop->quota_sync) |
| @@ -198,11 +198,17 @@ void sync_dquots(struct super_block *sb, int type) | |||
| 198 | restart: | 198 | restart: |
| 199 | list_for_each_entry(sb, &super_blocks, s_list) { | 199 | list_for_each_entry(sb, &super_blocks, s_list) { |
| 200 | /* This test just improves performance so it needn't be reliable... */ | 200 | /* This test just improves performance so it needn't be reliable... */ |
| 201 | for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++) | 201 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 202 | if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt) | 202 | if (type != -1 && type != cnt) |
| 203 | && info_any_dirty(&sb_dqopt(sb)->info[cnt])) | 203 | continue; |
| 204 | dirty = 1; | 204 | if (!sb_has_quota_enabled(sb, cnt)) |
| 205 | if (!dirty) | 205 | continue; |
| 206 | if (!info_dirty(&sb_dqopt(sb)->info[cnt]) && | ||
| 207 | list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list)) | ||
| 208 | continue; | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | if (cnt == MAXQUOTAS) | ||
| 206 | continue; | 212 | continue; |
| 207 | sb->s_count++; | 213 | sb->s_count++; |
| 208 | spin_unlock(&sb_lock); | 214 | spin_unlock(&sb_lock); |
diff --git a/fs/quota_v1.c b/fs/quota_v1.c index a6cf9269105c..5ae15b13eeb0 100644 --- a/fs/quota_v1.c +++ b/fs/quota_v1.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/errno.h> | 1 | #include <linux/errno.h> |
| 2 | #include <linux/fs.h> | 2 | #include <linux/fs.h> |
| 3 | #include <linux/quota.h> | 3 | #include <linux/quota.h> |
| 4 | #include <linux/quotaops.h> | ||
| 4 | #include <linux/dqblk_v1.h> | 5 | #include <linux/dqblk_v1.h> |
| 5 | #include <linux/quotaio_v1.h> | 6 | #include <linux/quotaio_v1.h> |
| 6 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
diff --git a/fs/quota_v2.c b/fs/quota_v2.c index 234ada903633..b53827dc02d9 100644 --- a/fs/quota_v2.c +++ b/fs/quota_v2.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 14 | #include <linux/quotaops.h> | ||
| 14 | 15 | ||
| 15 | #include <asm/byteorder.h> | 16 | #include <asm/byteorder.h> |
| 16 | 17 | ||
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index e396b2fa4743..c8f60ee183b5 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
| @@ -34,15 +34,10 @@ | |||
| 34 | ** from within kupdate, it will ignore the immediate flag | 34 | ** from within kupdate, it will ignore the immediate flag |
| 35 | */ | 35 | */ |
| 36 | 36 | ||
| 37 | #include <asm/uaccess.h> | ||
| 38 | #include <asm/system.h> | ||
| 39 | |||
| 40 | #include <linux/time.h> | 37 | #include <linux/time.h> |
| 41 | #include <linux/semaphore.h> | 38 | #include <linux/semaphore.h> |
| 42 | |||
| 43 | #include <linux/vmalloc.h> | 39 | #include <linux/vmalloc.h> |
| 44 | #include <linux/reiserfs_fs.h> | 40 | #include <linux/reiserfs_fs.h> |
| 45 | |||
| 46 | #include <linux/kernel.h> | 41 | #include <linux/kernel.h> |
| 47 | #include <linux/errno.h> | 42 | #include <linux/errno.h> |
| 48 | #include <linux/fcntl.h> | 43 | #include <linux/fcntl.h> |
| @@ -54,6 +49,9 @@ | |||
| 54 | #include <linux/writeback.h> | 49 | #include <linux/writeback.h> |
| 55 | #include <linux/blkdev.h> | 50 | #include <linux/blkdev.h> |
| 56 | #include <linux/backing-dev.h> | 51 | #include <linux/backing-dev.h> |
| 52 | #include <linux/uaccess.h> | ||
| 53 | |||
| 54 | #include <asm/system.h> | ||
| 57 | 55 | ||
| 58 | /* gets a struct reiserfs_journal_list * from a list head */ | 56 | /* gets a struct reiserfs_journal_list * from a list head */ |
| 59 | #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \ | 57 | #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \ |
| @@ -558,13 +556,13 @@ static inline void insert_journal_hash(struct reiserfs_journal_cnode **table, | |||
| 558 | static inline void lock_journal(struct super_block *p_s_sb) | 556 | static inline void lock_journal(struct super_block *p_s_sb) |
| 559 | { | 557 | { |
| 560 | PROC_INFO_INC(p_s_sb, journal.lock_journal); | 558 | PROC_INFO_INC(p_s_sb, journal.lock_journal); |
| 561 | down(&SB_JOURNAL(p_s_sb)->j_lock); | 559 | mutex_lock(&SB_JOURNAL(p_s_sb)->j_mutex); |
| 562 | } | 560 | } |
| 563 | 561 | ||
| 564 | /* unlock the current transaction */ | 562 | /* unlock the current transaction */ |
| 565 | static inline void unlock_journal(struct super_block *p_s_sb) | 563 | static inline void unlock_journal(struct super_block *p_s_sb) |
| 566 | { | 564 | { |
| 567 | up(&SB_JOURNAL(p_s_sb)->j_lock); | 565 | mutex_unlock(&SB_JOURNAL(p_s_sb)->j_mutex); |
| 568 | } | 566 | } |
| 569 | 567 | ||
| 570 | static inline void get_journal_list(struct reiserfs_journal_list *jl) | 568 | static inline void get_journal_list(struct reiserfs_journal_list *jl) |
| @@ -1045,9 +1043,9 @@ static int flush_commit_list(struct super_block *s, | |||
| 1045 | } | 1043 | } |
| 1046 | 1044 | ||
| 1047 | /* make sure nobody is trying to flush this one at the same time */ | 1045 | /* make sure nobody is trying to flush this one at the same time */ |
| 1048 | down(&jl->j_commit_lock); | 1046 | mutex_lock(&jl->j_commit_mutex); |
| 1049 | if (!journal_list_still_alive(s, trans_id)) { | 1047 | if (!journal_list_still_alive(s, trans_id)) { |
| 1050 | up(&jl->j_commit_lock); | 1048 | mutex_unlock(&jl->j_commit_mutex); |
| 1051 | goto put_jl; | 1049 | goto put_jl; |
| 1052 | } | 1050 | } |
| 1053 | BUG_ON(jl->j_trans_id == 0); | 1051 | BUG_ON(jl->j_trans_id == 0); |
| @@ -1057,7 +1055,7 @@ static int flush_commit_list(struct super_block *s, | |||
| 1057 | if (flushall) { | 1055 | if (flushall) { |
| 1058 | atomic_set(&(jl->j_older_commits_done), 1); | 1056 | atomic_set(&(jl->j_older_commits_done), 1); |
| 1059 | } | 1057 | } |
| 1060 | up(&jl->j_commit_lock); | 1058 | mutex_unlock(&jl->j_commit_mutex); |
| 1061 | goto put_jl; | 1059 | goto put_jl; |
| 1062 | } | 1060 | } |
| 1063 | 1061 | ||
| @@ -1181,7 +1179,7 @@ static int flush_commit_list(struct super_block *s, | |||
| 1181 | if (flushall) { | 1179 | if (flushall) { |
| 1182 | atomic_set(&(jl->j_older_commits_done), 1); | 1180 | atomic_set(&(jl->j_older_commits_done), 1); |
| 1183 | } | 1181 | } |
| 1184 | up(&jl->j_commit_lock); | 1182 | mutex_unlock(&jl->j_commit_mutex); |
| 1185 | put_jl: | 1183 | put_jl: |
| 1186 | put_journal_list(s, jl); | 1184 | put_journal_list(s, jl); |
| 1187 | 1185 | ||
| @@ -1411,8 +1409,8 @@ static int flush_journal_list(struct super_block *s, | |||
| 1411 | 1409 | ||
| 1412 | /* if flushall == 0, the lock is already held */ | 1410 | /* if flushall == 0, the lock is already held */ |
| 1413 | if (flushall) { | 1411 | if (flushall) { |
| 1414 | down(&journal->j_flush_sem); | 1412 | mutex_lock(&journal->j_flush_mutex); |
| 1415 | } else if (!down_trylock(&journal->j_flush_sem)) { | 1413 | } else if (mutex_trylock(&journal->j_flush_mutex)) { |
| 1416 | BUG(); | 1414 | BUG(); |
| 1417 | } | 1415 | } |
| 1418 | 1416 | ||
| @@ -1642,7 +1640,7 @@ static int flush_journal_list(struct super_block *s, | |||
| 1642 | jl->j_state = 0; | 1640 | jl->j_state = 0; |
| 1643 | put_journal_list(s, jl); | 1641 | put_journal_list(s, jl); |
| 1644 | if (flushall) | 1642 | if (flushall) |
| 1645 | up(&journal->j_flush_sem); | 1643 | mutex_unlock(&journal->j_flush_mutex); |
| 1646 | put_fs_excl(); | 1644 | put_fs_excl(); |
| 1647 | return err; | 1645 | return err; |
| 1648 | } | 1646 | } |
| @@ -1772,12 +1770,12 @@ static int kupdate_transactions(struct super_block *s, | |||
| 1772 | struct reiserfs_journal *journal = SB_JOURNAL(s); | 1770 | struct reiserfs_journal *journal = SB_JOURNAL(s); |
| 1773 | chunk.nr = 0; | 1771 | chunk.nr = 0; |
| 1774 | 1772 | ||
| 1775 | down(&journal->j_flush_sem); | 1773 | mutex_lock(&journal->j_flush_mutex); |
| 1776 | if (!journal_list_still_alive(s, orig_trans_id)) { | 1774 | if (!journal_list_still_alive(s, orig_trans_id)) { |
| 1777 | goto done; | 1775 | goto done; |
| 1778 | } | 1776 | } |
| 1779 | 1777 | ||
| 1780 | /* we've got j_flush_sem held, nobody is going to delete any | 1778 | /* we've got j_flush_mutex held, nobody is going to delete any |
| 1781 | * of these lists out from underneath us | 1779 | * of these lists out from underneath us |
| 1782 | */ | 1780 | */ |
| 1783 | while ((num_trans && transactions_flushed < num_trans) || | 1781 | while ((num_trans && transactions_flushed < num_trans) || |
| @@ -1812,7 +1810,7 @@ static int kupdate_transactions(struct super_block *s, | |||
| 1812 | } | 1810 | } |
| 1813 | 1811 | ||
| 1814 | done: | 1812 | done: |
| 1815 | up(&journal->j_flush_sem); | 1813 | mutex_unlock(&journal->j_flush_mutex); |
| 1816 | return ret; | 1814 | return ret; |
| 1817 | } | 1815 | } |
| 1818 | 1816 | ||
| @@ -2556,7 +2554,7 @@ static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s) | |||
| 2556 | INIT_LIST_HEAD(&jl->j_working_list); | 2554 | INIT_LIST_HEAD(&jl->j_working_list); |
| 2557 | INIT_LIST_HEAD(&jl->j_tail_bh_list); | 2555 | INIT_LIST_HEAD(&jl->j_tail_bh_list); |
| 2558 | INIT_LIST_HEAD(&jl->j_bh_list); | 2556 | INIT_LIST_HEAD(&jl->j_bh_list); |
| 2559 | sema_init(&jl->j_commit_lock, 1); | 2557 | mutex_init(&jl->j_commit_mutex); |
| 2560 | SB_JOURNAL(s)->j_num_lists++; | 2558 | SB_JOURNAL(s)->j_num_lists++; |
| 2561 | get_journal_list(jl); | 2559 | get_journal_list(jl); |
| 2562 | return jl; | 2560 | return jl; |
| @@ -2837,8 +2835,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, | |||
| 2837 | journal->j_last = NULL; | 2835 | journal->j_last = NULL; |
| 2838 | journal->j_first = NULL; | 2836 | journal->j_first = NULL; |
| 2839 | init_waitqueue_head(&(journal->j_join_wait)); | 2837 | init_waitqueue_head(&(journal->j_join_wait)); |
| 2840 | sema_init(&journal->j_lock, 1); | 2838 | mutex_init(&journal->j_mutex); |
| 2841 | sema_init(&journal->j_flush_sem, 1); | 2839 | mutex_init(&journal->j_flush_mutex); |
| 2842 | 2840 | ||
| 2843 | journal->j_trans_id = 10; | 2841 | journal->j_trans_id = 10; |
| 2844 | journal->j_mount_id = 10; | 2842 | journal->j_mount_id = 10; |
| @@ -4030,7 +4028,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
| 4030 | * the new transaction is fully setup, and we've already flushed the | 4028 | * the new transaction is fully setup, and we've already flushed the |
| 4031 | * ordered bh list | 4029 | * ordered bh list |
| 4032 | */ | 4030 | */ |
| 4033 | down(&jl->j_commit_lock); | 4031 | mutex_lock(&jl->j_commit_mutex); |
| 4034 | 4032 | ||
| 4035 | /* save the transaction id in case we need to commit it later */ | 4033 | /* save the transaction id in case we need to commit it later */ |
| 4036 | commit_trans_id = jl->j_trans_id; | 4034 | commit_trans_id = jl->j_trans_id; |
| @@ -4196,7 +4194,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
| 4196 | lock_kernel(); | 4194 | lock_kernel(); |
| 4197 | } | 4195 | } |
| 4198 | BUG_ON(!list_empty(&jl->j_tail_bh_list)); | 4196 | BUG_ON(!list_empty(&jl->j_tail_bh_list)); |
| 4199 | up(&jl->j_commit_lock); | 4197 | mutex_unlock(&jl->j_commit_mutex); |
| 4200 | 4198 | ||
| 4201 | /* honor the flush wishes from the caller, simple commits can | 4199 | /* honor the flush wishes from the caller, simple commits can |
| 4202 | ** be done outside the journal lock, they are done below | 4200 | ** be done outside the journal lock, they are done below |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 1d40f2bd1970..2ec748ba0bd3 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
| 23 | #include <linux/buffer_head.h> | 23 | #include <linux/buffer_head.h> |
| 24 | #include <linux/exportfs.h> | 24 | #include <linux/exportfs.h> |
| 25 | #include <linux/quotaops.h> | ||
| 25 | #include <linux/vfs.h> | 26 | #include <linux/vfs.h> |
| 26 | #include <linux/mnt_namespace.h> | 27 | #include <linux/mnt_namespace.h> |
| 27 | #include <linux/mount.h> | 28 | #include <linux/mount.h> |
| @@ -182,7 +183,7 @@ static int finish_unfinished(struct super_block *s) | |||
| 182 | int ret = reiserfs_quota_on_mount(s, i); | 183 | int ret = reiserfs_quota_on_mount(s, i); |
| 183 | if (ret < 0) | 184 | if (ret < 0) |
| 184 | reiserfs_warning(s, | 185 | reiserfs_warning(s, |
| 185 | "reiserfs: cannot turn on journalled quota: error %d", | 186 | "reiserfs: cannot turn on journaled quota: error %d", |
| 186 | ret); | 187 | ret); |
| 187 | } | 188 | } |
| 188 | } | 189 | } |
| @@ -876,7 +877,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin | |||
| 876 | mount options were selected. */ | 877 | mount options were selected. */ |
| 877 | unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */ | 878 | unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */ |
| 878 | char **jdev_name, | 879 | char **jdev_name, |
| 879 | unsigned int *commit_max_age) | 880 | unsigned int *commit_max_age, |
| 881 | char **qf_names, | ||
| 882 | unsigned int *qfmt) | ||
| 880 | { | 883 | { |
| 881 | int c; | 884 | int c; |
| 882 | char *arg = NULL; | 885 | char *arg = NULL; |
| @@ -992,9 +995,11 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin | |||
| 992 | if (c == 'u' || c == 'g') { | 995 | if (c == 'u' || c == 'g') { |
| 993 | int qtype = c == 'u' ? USRQUOTA : GRPQUOTA; | 996 | int qtype = c == 'u' ? USRQUOTA : GRPQUOTA; |
| 994 | 997 | ||
| 995 | if (sb_any_quota_enabled(s)) { | 998 | if ((sb_any_quota_enabled(s) || |
| 999 | sb_any_quota_suspended(s)) && | ||
| 1000 | (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) { | ||
| 996 | reiserfs_warning(s, | 1001 | reiserfs_warning(s, |
| 997 | "reiserfs_parse_options: cannot change journalled quota options when quota turned on."); | 1002 | "reiserfs_parse_options: cannot change journaled quota options when quota turned on."); |
| 998 | return 0; | 1003 | return 0; |
| 999 | } | 1004 | } |
| 1000 | if (*arg) { /* Some filename specified? */ | 1005 | if (*arg) { /* Some filename specified? */ |
| @@ -1011,46 +1016,54 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin | |||
| 1011 | "reiserfs_parse_options: quotafile must be on filesystem root."); | 1016 | "reiserfs_parse_options: quotafile must be on filesystem root."); |
| 1012 | return 0; | 1017 | return 0; |
| 1013 | } | 1018 | } |
| 1014 | REISERFS_SB(s)->s_qf_names[qtype] = | 1019 | qf_names[qtype] = |
| 1015 | kmalloc(strlen(arg) + 1, GFP_KERNEL); | 1020 | kmalloc(strlen(arg) + 1, GFP_KERNEL); |
| 1016 | if (!REISERFS_SB(s)->s_qf_names[qtype]) { | 1021 | if (!qf_names[qtype]) { |
| 1017 | reiserfs_warning(s, | 1022 | reiserfs_warning(s, |
| 1018 | "reiserfs_parse_options: not enough memory for storing quotafile name."); | 1023 | "reiserfs_parse_options: not enough memory for storing quotafile name."); |
| 1019 | return 0; | 1024 | return 0; |
| 1020 | } | 1025 | } |
| 1021 | strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg); | 1026 | strcpy(qf_names[qtype], arg); |
| 1022 | *mount_options |= 1 << REISERFS_QUOTA; | 1027 | *mount_options |= 1 << REISERFS_QUOTA; |
| 1023 | } else { | 1028 | } else { |
| 1024 | kfree(REISERFS_SB(s)->s_qf_names[qtype]); | 1029 | if (qf_names[qtype] != |
| 1025 | REISERFS_SB(s)->s_qf_names[qtype] = NULL; | 1030 | REISERFS_SB(s)->s_qf_names[qtype]) |
| 1031 | kfree(qf_names[qtype]); | ||
| 1032 | qf_names[qtype] = NULL; | ||
| 1026 | } | 1033 | } |
| 1027 | } | 1034 | } |
| 1028 | if (c == 'f') { | 1035 | if (c == 'f') { |
| 1029 | if (!strcmp(arg, "vfsold")) | 1036 | if (!strcmp(arg, "vfsold")) |
| 1030 | REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_OLD; | 1037 | *qfmt = QFMT_VFS_OLD; |
| 1031 | else if (!strcmp(arg, "vfsv0")) | 1038 | else if (!strcmp(arg, "vfsv0")) |
| 1032 | REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_V0; | 1039 | *qfmt = QFMT_VFS_V0; |
| 1033 | else { | 1040 | else { |
| 1034 | reiserfs_warning(s, | 1041 | reiserfs_warning(s, |
| 1035 | "reiserfs_parse_options: unknown quota format specified."); | 1042 | "reiserfs_parse_options: unknown quota format specified."); |
| 1036 | return 0; | 1043 | return 0; |
| 1037 | } | 1044 | } |
| 1045 | if ((sb_any_quota_enabled(s) || | ||
| 1046 | sb_any_quota_suspended(s)) && | ||
| 1047 | *qfmt != REISERFS_SB(s)->s_jquota_fmt) { | ||
| 1048 | reiserfs_warning(s, | ||
| 1049 | "reiserfs_parse_options: cannot change journaled quota options when quota turned on."); | ||
| 1050 | return 0; | ||
| 1051 | } | ||
| 1038 | } | 1052 | } |
| 1039 | #else | 1053 | #else |
| 1040 | if (c == 'u' || c == 'g' || c == 'f') { | 1054 | if (c == 'u' || c == 'g' || c == 'f') { |
| 1041 | reiserfs_warning(s, | 1055 | reiserfs_warning(s, |
| 1042 | "reiserfs_parse_options: journalled quota options not supported."); | 1056 | "reiserfs_parse_options: journaled quota options not supported."); |
| 1043 | return 0; | 1057 | return 0; |
| 1044 | } | 1058 | } |
| 1045 | #endif | 1059 | #endif |
| 1046 | } | 1060 | } |
| 1047 | 1061 | ||
| 1048 | #ifdef CONFIG_QUOTA | 1062 | #ifdef CONFIG_QUOTA |
| 1049 | if (!REISERFS_SB(s)->s_jquota_fmt | 1063 | if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt |
| 1050 | && (REISERFS_SB(s)->s_qf_names[USRQUOTA] | 1064 | && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) { |
| 1051 | || REISERFS_SB(s)->s_qf_names[GRPQUOTA])) { | ||
| 1052 | reiserfs_warning(s, | 1065 | reiserfs_warning(s, |
| 1053 | "reiserfs_parse_options: journalled quota format not specified."); | 1066 | "reiserfs_parse_options: journaled quota format not specified."); |
| 1054 | return 0; | 1067 | return 0; |
| 1055 | } | 1068 | } |
| 1056 | /* This checking is not precise wrt the quota type but for our purposes it is sufficient */ | 1069 | /* This checking is not precise wrt the quota type but for our purposes it is sufficient */ |
| @@ -1130,6 +1143,21 @@ static void handle_attrs(struct super_block *s) | |||
| 1130 | } | 1143 | } |
| 1131 | } | 1144 | } |
| 1132 | 1145 | ||
| 1146 | #ifdef CONFIG_QUOTA | ||
| 1147 | static void handle_quota_files(struct super_block *s, char **qf_names, | ||
| 1148 | unsigned int *qfmt) | ||
| 1149 | { | ||
| 1150 | int i; | ||
| 1151 | |||
| 1152 | for (i = 0; i < MAXQUOTAS; i++) { | ||
| 1153 | if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i]) | ||
| 1154 | kfree(REISERFS_SB(s)->s_qf_names[i]); | ||
| 1155 | REISERFS_SB(s)->s_qf_names[i] = qf_names[i]; | ||
| 1156 | } | ||
| 1157 | REISERFS_SB(s)->s_jquota_fmt = *qfmt; | ||
| 1158 | } | ||
| 1159 | #endif | ||
| 1160 | |||
| 1133 | static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | 1161 | static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) |
| 1134 | { | 1162 | { |
| 1135 | struct reiserfs_super_block *rs; | 1163 | struct reiserfs_super_block *rs; |
| @@ -1141,23 +1169,30 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
| 1141 | struct reiserfs_journal *journal = SB_JOURNAL(s); | 1169 | struct reiserfs_journal *journal = SB_JOURNAL(s); |
| 1142 | char *new_opts = kstrdup(arg, GFP_KERNEL); | 1170 | char *new_opts = kstrdup(arg, GFP_KERNEL); |
| 1143 | int err; | 1171 | int err; |
| 1172 | char *qf_names[MAXQUOTAS]; | ||
| 1173 | unsigned int qfmt = 0; | ||
| 1144 | #ifdef CONFIG_QUOTA | 1174 | #ifdef CONFIG_QUOTA |
| 1145 | int i; | 1175 | int i; |
| 1176 | |||
| 1177 | memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names)); | ||
| 1146 | #endif | 1178 | #endif |
| 1147 | 1179 | ||
| 1148 | rs = SB_DISK_SUPER_BLOCK(s); | 1180 | rs = SB_DISK_SUPER_BLOCK(s); |
| 1149 | 1181 | ||
| 1150 | if (!reiserfs_parse_options | 1182 | if (!reiserfs_parse_options |
| 1151 | (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) { | 1183 | (s, arg, &mount_options, &blocks, NULL, &commit_max_age, |
| 1184 | qf_names, &qfmt)) { | ||
| 1152 | #ifdef CONFIG_QUOTA | 1185 | #ifdef CONFIG_QUOTA |
| 1153 | for (i = 0; i < MAXQUOTAS; i++) { | 1186 | for (i = 0; i < MAXQUOTAS; i++) |
| 1154 | kfree(REISERFS_SB(s)->s_qf_names[i]); | 1187 | if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i]) |
| 1155 | REISERFS_SB(s)->s_qf_names[i] = NULL; | 1188 | kfree(qf_names[i]); |
| 1156 | } | ||
| 1157 | #endif | 1189 | #endif |
| 1158 | err = -EINVAL; | 1190 | err = -EINVAL; |
| 1159 | goto out_err; | 1191 | goto out_err; |
| 1160 | } | 1192 | } |
| 1193 | #ifdef CONFIG_QUOTA | ||
| 1194 | handle_quota_files(s, qf_names, &qfmt); | ||
| 1195 | #endif | ||
| 1161 | 1196 | ||
| 1162 | handle_attrs(s); | 1197 | handle_attrs(s); |
| 1163 | 1198 | ||
| @@ -1570,6 +1605,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1570 | char *jdev_name; | 1605 | char *jdev_name; |
| 1571 | struct reiserfs_sb_info *sbi; | 1606 | struct reiserfs_sb_info *sbi; |
| 1572 | int errval = -EINVAL; | 1607 | int errval = -EINVAL; |
| 1608 | char *qf_names[MAXQUOTAS] = {}; | ||
| 1609 | unsigned int qfmt = 0; | ||
| 1573 | 1610 | ||
| 1574 | save_mount_options(s, data); | 1611 | save_mount_options(s, data); |
| 1575 | 1612 | ||
| @@ -1597,9 +1634,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1597 | jdev_name = NULL; | 1634 | jdev_name = NULL; |
| 1598 | if (reiserfs_parse_options | 1635 | if (reiserfs_parse_options |
| 1599 | (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, | 1636 | (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, |
| 1600 | &commit_max_age) == 0) { | 1637 | &commit_max_age, qf_names, &qfmt) == 0) { |
| 1601 | goto error; | 1638 | goto error; |
| 1602 | } | 1639 | } |
| 1640 | #ifdef CONFIG_QUOTA | ||
| 1641 | handle_quota_files(s, qf_names, &qfmt); | ||
| 1642 | #endif | ||
| 1603 | 1643 | ||
| 1604 | if (blocks) { | 1644 | if (blocks) { |
| 1605 | SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option " | 1645 | SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option " |
| @@ -1819,7 +1859,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1819 | 1859 | ||
| 1820 | return (0); | 1860 | return (0); |
| 1821 | 1861 | ||
| 1822 | error: | 1862 | error: |
| 1823 | if (jinit_done) { /* kill the commit thread, free journal ram */ | 1863 | if (jinit_done) { /* kill the commit thread, free journal ram */ |
| 1824 | journal_release_error(NULL, s); | 1864 | journal_release_error(NULL, s); |
| 1825 | } | 1865 | } |
| @@ -1830,10 +1870,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1830 | #ifdef CONFIG_QUOTA | 1870 | #ifdef CONFIG_QUOTA |
| 1831 | { | 1871 | { |
| 1832 | int j; | 1872 | int j; |
| 1833 | for (j = 0; j < MAXQUOTAS; j++) { | 1873 | for (j = 0; j < MAXQUOTAS; j++) |
| 1834 | kfree(sbi->s_qf_names[j]); | 1874 | kfree(qf_names[j]); |
| 1835 | sbi->s_qf_names[j] = NULL; | ||
| 1836 | } | ||
| 1837 | } | 1875 | } |
| 1838 | #endif | 1876 | #endif |
| 1839 | kfree(sbi); | 1877 | kfree(sbi); |
| @@ -1980,7 +2018,7 @@ static int reiserfs_release_dquot(struct dquot *dquot) | |||
| 1980 | 2018 | ||
| 1981 | static int reiserfs_mark_dquot_dirty(struct dquot *dquot) | 2019 | static int reiserfs_mark_dquot_dirty(struct dquot *dquot) |
| 1982 | { | 2020 | { |
| 1983 | /* Are we journalling quotas? */ | 2021 | /* Are we journaling quotas? */ |
| 1984 | if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || | 2022 | if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || |
| 1985 | REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { | 2023 | REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { |
| 1986 | dquot_mark_dquot_dirty(dquot); | 2024 | dquot_mark_dquot_dirty(dquot); |
| @@ -2026,6 +2064,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, | |||
| 2026 | int err; | 2064 | int err; |
| 2027 | struct nameidata nd; | 2065 | struct nameidata nd; |
| 2028 | struct inode *inode; | 2066 | struct inode *inode; |
| 2067 | struct reiserfs_transaction_handle th; | ||
| 2029 | 2068 | ||
| 2030 | if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA))) | 2069 | if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA))) |
| 2031 | return -EINVAL; | 2070 | return -EINVAL; |
| @@ -2053,17 +2092,28 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, | |||
| 2053 | } | 2092 | } |
| 2054 | mark_inode_dirty(inode); | 2093 | mark_inode_dirty(inode); |
| 2055 | } | 2094 | } |
| 2056 | /* Not journalling quota? No more tests needed... */ | 2095 | /* Journaling quota? */ |
| 2057 | if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] && | 2096 | if (REISERFS_SB(sb)->s_qf_names[type]) { |
| 2058 | !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) { | 2097 | /* Quotafile not of fs root? */ |
| 2059 | path_put(&nd.path); | 2098 | if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) |
| 2060 | return vfs_quota_on(sb, type, format_id, path, 0); | 2099 | reiserfs_warning(sb, |
| 2061 | } | ||
| 2062 | /* Quotafile not of fs root? */ | ||
| 2063 | if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) | ||
| 2064 | reiserfs_warning(sb, | ||
| 2065 | "reiserfs: Quota file not on filesystem root. " | 2100 | "reiserfs: Quota file not on filesystem root. " |
| 2066 | "Journalled quota will not work."); | 2101 | "Journalled quota will not work."); |
| 2102 | } | ||
| 2103 | |||
| 2104 | /* | ||
| 2105 | * When we journal data on quota file, we have to flush journal to see | ||
| 2106 | * all updates to the file when we bypass pagecache... | ||
| 2107 | */ | ||
| 2108 | if (reiserfs_file_data_log(inode)) { | ||
| 2109 | /* Just start temporary transaction and finish it */ | ||
| 2110 | err = journal_begin(&th, sb, 1); | ||
| 2111 | if (err) | ||
| 2112 | return err; | ||
| 2113 | err = journal_end_sync(&th, sb, 1); | ||
| 2114 | if (err) | ||
| 2115 | return err; | ||
| 2116 | } | ||
| 2067 | path_put(&nd.path); | 2117 | path_put(&nd.path); |
| 2068 | return vfs_quota_on(sb, type, format_id, path, 0); | 2118 | return vfs_quota_on(sb, type, format_id, path, 0); |
| 2069 | } | 2119 | } |
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index 5e90a95ad60b..056008db1377 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c | |||
| @@ -6,8 +6,6 @@ | |||
| 6 | #include <linux/reiserfs_xattr.h> | 6 | #include <linux/reiserfs_xattr.h> |
| 7 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
| 8 | 8 | ||
| 9 | #define XATTR_SECURITY_PREFIX "security." | ||
| 10 | |||
| 11 | static int | 9 | static int |
| 12 | security_get(struct inode *inode, const char *name, void *buffer, size_t size) | 10 | security_get(struct inode *inode, const char *name, void *buffer, size_t size) |
| 13 | { | 11 | { |
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c index 024a938ca60f..60abe2bb1f98 100644 --- a/fs/reiserfs/xattr_trusted.c +++ b/fs/reiserfs/xattr_trusted.c | |||
| @@ -7,8 +7,6 @@ | |||
| 7 | #include <linux/reiserfs_xattr.h> | 7 | #include <linux/reiserfs_xattr.h> |
| 8 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
| 9 | 9 | ||
| 10 | #define XATTR_TRUSTED_PREFIX "trusted." | ||
| 11 | |||
| 12 | static int | 10 | static int |
| 13 | trusted_get(struct inode *inode, const char *name, void *buffer, size_t size) | 11 | trusted_get(struct inode *inode, const char *name, void *buffer, size_t size) |
| 14 | { | 12 | { |
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c index 073f39364b11..1384efcb938e 100644 --- a/fs/reiserfs/xattr_user.c +++ b/fs/reiserfs/xattr_user.c | |||
| @@ -10,8 +10,6 @@ | |||
| 10 | # include <linux/reiserfs_acl.h> | 10 | # include <linux/reiserfs_acl.h> |
| 11 | #endif | 11 | #endif |
| 12 | 12 | ||
| 13 | #define XATTR_USER_PREFIX "user." | ||
| 14 | |||
| 15 | static int | 13 | static int |
| 16 | user_get(struct inode *inode, const char *name, void *buffer, size_t size) | 14 | user_get(struct inode *inode, const char *name, void *buffer, size_t size) |
| 17 | { | 15 | { |
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c index 8182f0542a21..8c177eb7e344 100644 --- a/fs/smbfs/cache.c +++ b/fs/smbfs/cache.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
| 16 | #include <linux/dirent.h> | ||
| 17 | #include <linux/smb_fs.h> | 16 | #include <linux/smb_fs.h> |
| 18 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
| 19 | #include <linux/net.h> | 18 | #include <linux/net.h> |
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index d517a27b7f4b..ee536e8a649a 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
| 17 | #include <linux/fcntl.h> | 17 | #include <linux/fcntl.h> |
| 18 | #include <linux/dcache.h> | 18 | #include <linux/dcache.h> |
| 19 | #include <linux/dirent.h> | ||
| 20 | #include <linux/nls.h> | 19 | #include <linux/nls.h> |
| 21 | #include <linux/smp_lock.h> | 20 | #include <linux/smp_lock.h> |
| 22 | #include <linux/net.h> | 21 | #include <linux/net.h> |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 506f724055c2..227c9d700040 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
| @@ -76,6 +76,7 @@ | |||
| 76 | 76 | ||
| 77 | #include <linux/errno.h> | 77 | #include <linux/errno.h> |
| 78 | #include <linux/fs.h> | 78 | #include <linux/fs.h> |
| 79 | #include <linux/quotaops.h> | ||
| 79 | #include <linux/slab.h> | 80 | #include <linux/slab.h> |
| 80 | #include <linux/time.h> | 81 | #include <linux/time.h> |
| 81 | #include <linux/stat.h> | 82 | #include <linux/stat.h> |
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index b546ba69be82..155c10b4adbd 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c | |||
| @@ -621,7 +621,7 @@ shortname: | |||
| 621 | memcpy(de->name, msdos_name, MSDOS_NAME); | 621 | memcpy(de->name, msdos_name, MSDOS_NAME); |
| 622 | de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; | 622 | de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; |
| 623 | de->lcase = lcase; | 623 | de->lcase = lcase; |
| 624 | fat_date_unix2dos(ts->tv_sec, &time, &date); | 624 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); |
| 625 | de->time = de->ctime = time; | 625 | de->time = de->ctime = time; |
| 626 | de->date = de->cdate = de->adate = date; | 626 | de->date = de->cdate = de->adate = date; |
| 627 | de->ctime_cs = 0; | 627 | de->ctime_cs = 0; |
diff --git a/include/asm-alpha/kvm.h b/include/asm-alpha/kvm.h deleted file mode 100644 index b9daec429689..000000000000 --- a/include/asm-alpha/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_ALPHA_H | ||
| 2 | #define __LINUX_KVM_ALPHA_H | ||
| 3 | |||
| 4 | /* alpha does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h index fb3185196298..15fda4344424 100644 --- a/include/asm-alpha/thread_info.h +++ b/include/asm-alpha/thread_info.h | |||
| @@ -50,10 +50,8 @@ register struct thread_info *__current_thread_info __asm__("$8"); | |||
| 50 | #define current_thread_info() __current_thread_info | 50 | #define current_thread_info() __current_thread_info |
| 51 | 51 | ||
| 52 | /* Thread information allocation. */ | 52 | /* Thread information allocation. */ |
| 53 | #define THREAD_SIZE_ORDER 1 | ||
| 53 | #define THREAD_SIZE (2*PAGE_SIZE) | 54 | #define THREAD_SIZE (2*PAGE_SIZE) |
| 54 | #define alloc_thread_info(tsk) \ | ||
| 55 | ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) | ||
| 56 | #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) | ||
| 57 | 55 | ||
| 58 | #endif /* __ASSEMBLY__ */ | 56 | #endif /* __ASSEMBLY__ */ |
| 59 | 57 | ||
diff --git a/include/asm-arm/kvm.h b/include/asm-arm/kvm.h deleted file mode 100644 index cb3c08cbcb9e..000000000000 --- a/include/asm-arm/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_ARM_H | ||
| 2 | #define __LINUX_KVM_ARM_H | ||
| 3 | |||
| 4 | /* arm does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index 7aaa206cb54e..8382b7510f94 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h | |||
| @@ -139,8 +139,6 @@ static inline int valid_user_regs(struct pt_regs *regs) | |||
| 139 | return 0; | 139 | return 0; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | #endif /* __KERNEL__ */ | ||
| 143 | |||
| 144 | #define pc_pointer(v) \ | 142 | #define pc_pointer(v) \ |
| 145 | ((v) & ~PCMASK) | 143 | ((v) & ~PCMASK) |
| 146 | 144 | ||
| @@ -153,10 +151,10 @@ extern unsigned long profile_pc(struct pt_regs *regs); | |||
| 153 | #define profile_pc(regs) instruction_pointer(regs) | 151 | #define profile_pc(regs) instruction_pointer(regs) |
| 154 | #endif | 152 | #endif |
| 155 | 153 | ||
| 156 | #ifdef __KERNEL__ | ||
| 157 | #define predicate(x) ((x) & 0xf0000000) | 154 | #define predicate(x) ((x) & 0xf0000000) |
| 158 | #define PREDICATE_ALWAYS 0xe0000000 | 155 | #define PREDICATE_ALWAYS 0xe0000000 |
| 159 | #endif | 156 | |
| 157 | #endif /* __KERNEL__ */ | ||
| 160 | 158 | ||
| 161 | #endif /* __ASSEMBLY__ */ | 159 | #endif /* __ASSEMBLY__ */ |
| 162 | 160 | ||
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index f5a664786311..d4be2d646160 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h | |||
| @@ -97,19 +97,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 97 | return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); | 97 | return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | /* thread information allocation */ | ||
| 101 | #ifdef CONFIG_DEBUG_STACK_USAGE | ||
| 102 | #define alloc_thread_info(tsk) \ | ||
| 103 | ((struct thread_info *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, \ | ||
| 104 | THREAD_SIZE_ORDER)) | ||
| 105 | #else | ||
| 106 | #define alloc_thread_info(tsk) \ | ||
| 107 | ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER)) | ||
| 108 | #endif | ||
| 109 | |||
| 110 | #define free_thread_info(info) \ | ||
| 111 | free_pages((unsigned long)info, THREAD_SIZE_ORDER); | ||
| 112 | |||
| 113 | #define thread_saved_pc(tsk) \ | 100 | #define thread_saved_pc(tsk) \ |
| 114 | ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc))) | 101 | ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc))) |
| 115 | #define thread_saved_fp(tsk) \ | 102 | #define thread_saved_fp(tsk) \ |
diff --git a/include/asm-avr32/kvm.h b/include/asm-avr32/kvm.h deleted file mode 100644 index 8c5777020e2c..000000000000 --- a/include/asm-avr32/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_AVR32_H | ||
| 2 | #define __LINUX_KVM_AVR32_H | ||
| 3 | |||
| 4 | /* avr32 does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-avr32/thread_info.h b/include/asm-avr32/thread_info.h index df68631b7b27..294b25f9323d 100644 --- a/include/asm-avr32/thread_info.h +++ b/include/asm-avr32/thread_info.h | |||
| @@ -61,10 +61,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 61 | return (struct thread_info *)addr; | 61 | return (struct thread_info *)addr; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | /* thread information allocation */ | ||
| 65 | #define alloc_thread_info(ti) \ | ||
| 66 | ((struct thread_info *) __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER)) | ||
| 67 | #define free_thread_info(ti) free_pages((unsigned long)(ti), 1) | ||
| 68 | #define get_thread_info(ti) get_task_struct((ti)->task) | 64 | #define get_thread_info(ti) get_task_struct((ti)->task) |
| 69 | #define put_thread_info(ti) put_task_struct((ti)->task) | 65 | #define put_thread_info(ti) put_task_struct((ti)->task) |
| 70 | 66 | ||
diff --git a/include/asm-blackfin/kvm.h b/include/asm-blackfin/kvm.h deleted file mode 100644 index e3477d77c014..000000000000 --- a/include/asm-blackfin/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_BLACKFIN_H | ||
| 2 | #define __LINUX_KVM_BLACKFIN_H | ||
| 3 | |||
| 4 | /* blackfin does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-blackfin/ptrace.h b/include/asm-blackfin/ptrace.h index b8346cd3a6f6..a45a80e54adc 100644 --- a/include/asm-blackfin/ptrace.h +++ b/include/asm-blackfin/ptrace.h | |||
| @@ -83,14 +83,14 @@ struct pt_regs { | |||
| 83 | #define PTRACE_GETREGS 12 | 83 | #define PTRACE_GETREGS 12 |
| 84 | #define PTRACE_SETREGS 13 /* ptrace signal */ | 84 | #define PTRACE_SETREGS 13 /* ptrace signal */ |
| 85 | 85 | ||
| 86 | #ifdef CONFIG_BINFMT_ELF_FDPIC | ||
| 87 | #define PTRACE_GETFDPIC 31 | 86 | #define PTRACE_GETFDPIC 31 |
| 88 | #define PTRACE_GETFDPIC_EXEC 0 | 87 | #define PTRACE_GETFDPIC_EXEC 0 |
| 89 | #define PTRACE_GETFDPIC_INTERP 1 | 88 | #define PTRACE_GETFDPIC_INTERP 1 |
| 90 | #endif | ||
| 91 | 89 | ||
| 92 | #define PS_S (0x0002) | 90 | #define PS_S (0x0002) |
| 93 | 91 | ||
| 92 | #ifdef __KERNEL__ | ||
| 93 | |||
| 94 | /* user_mode returns true if only one bit is set in IPEND, other than the | 94 | /* user_mode returns true if only one bit is set in IPEND, other than the |
| 95 | master interrupt enable. */ | 95 | master interrupt enable. */ |
| 96 | #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1))) | 96 | #define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1))) |
| @@ -98,6 +98,8 @@ struct pt_regs { | |||
| 98 | #define profile_pc(regs) instruction_pointer(regs) | 98 | #define profile_pc(regs) instruction_pointer(regs) |
| 99 | extern void show_regs(struct pt_regs *); | 99 | extern void show_regs(struct pt_regs *); |
| 100 | 100 | ||
| 101 | #endif /* __KERNEL__ */ | ||
| 102 | |||
| 101 | #endif /* __ASSEMBLY__ */ | 103 | #endif /* __ASSEMBLY__ */ |
| 102 | 104 | ||
| 103 | /* | 105 | /* |
diff --git a/include/asm-blackfin/thread_info.h b/include/asm-blackfin/thread_info.h index bc2fe5accf20..642769329d12 100644 --- a/include/asm-blackfin/thread_info.h +++ b/include/asm-blackfin/thread_info.h | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | /* | 42 | /* |
| 43 | * Size of kernel stack for each process. This must be a power of 2... | 43 | * Size of kernel stack for each process. This must be a power of 2... |
| 44 | */ | 44 | */ |
| 45 | #define THREAD_SIZE_ORDER 1 | ||
| 45 | #define THREAD_SIZE 8192 /* 2 pages */ | 46 | #define THREAD_SIZE 8192 /* 2 pages */ |
| 46 | 47 | ||
| 47 | #ifndef __ASSEMBLY__ | 48 | #ifndef __ASSEMBLY__ |
| @@ -94,10 +95,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 94 | return (struct thread_info *)((long)ti & ~((long)THREAD_SIZE-1)); | 95 | return (struct thread_info *)((long)ti & ~((long)THREAD_SIZE-1)); |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | /* thread information allocation */ | ||
| 98 | #define alloc_thread_info(tsk) ((struct thread_info *) \ | ||
| 99 | __get_free_pages(GFP_KERNEL, 1)) | ||
| 100 | #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) | ||
| 101 | #endif /* __ASSEMBLY__ */ | 98 | #endif /* __ASSEMBLY__ */ |
| 102 | 99 | ||
| 103 | /* | 100 | /* |
diff --git a/include/asm-cris/arch-v10/Kbuild b/include/asm-cris/arch-v10/Kbuild index 60e7e1b73cec..7a192e1290b1 100644 --- a/include/asm-cris/arch-v10/Kbuild +++ b/include/asm-cris/arch-v10/Kbuild | |||
| @@ -1,4 +1,3 @@ | |||
| 1 | header-y += ptrace.h | ||
| 2 | header-y += user.h | 1 | header-y += user.h |
| 3 | header-y += svinto.h | 2 | header-y += svinto.h |
| 4 | header-y += sv_addr_ag.h | 3 | header-y += sv_addr_ag.h |
diff --git a/include/asm-cris/arch-v10/ptrace.h b/include/asm-cris/arch-v10/ptrace.h index fb14c5ee37f9..2f464eab3a51 100644 --- a/include/asm-cris/arch-v10/ptrace.h +++ b/include/asm-cris/arch-v10/ptrace.h | |||
| @@ -106,10 +106,14 @@ struct switch_stack { | |||
| 106 | unsigned long return_ip; /* ip that _resume will return to */ | 106 | unsigned long return_ip; /* ip that _resume will return to */ |
| 107 | }; | 107 | }; |
| 108 | 108 | ||
| 109 | #ifdef __KERNEL__ | ||
| 110 | |||
| 109 | /* bit 8 is user-mode flag */ | 111 | /* bit 8 is user-mode flag */ |
| 110 | #define user_mode(regs) (((regs)->dccr & 0x100) != 0) | 112 | #define user_mode(regs) (((regs)->dccr & 0x100) != 0) |
| 111 | #define instruction_pointer(regs) ((regs)->irp) | 113 | #define instruction_pointer(regs) ((regs)->irp) |
| 112 | #define profile_pc(regs) instruction_pointer(regs) | 114 | #define profile_pc(regs) instruction_pointer(regs) |
| 113 | extern void show_regs(struct pt_regs *); | 115 | extern void show_regs(struct pt_regs *); |
| 114 | 116 | ||
| 117 | #endif /* __KERNEL__ */ | ||
| 118 | |||
| 115 | #endif | 119 | #endif |
diff --git a/include/asm-cris/arch-v32/Kbuild b/include/asm-cris/arch-v32/Kbuild index a0ec545e242e..35f2fc4f993e 100644 --- a/include/asm-cris/arch-v32/Kbuild +++ b/include/asm-cris/arch-v32/Kbuild | |||
| @@ -1,3 +1,2 @@ | |||
| 1 | header-y += ptrace.h | ||
| 2 | header-y += user.h | 1 | header-y += user.h |
| 3 | header-y += cryptocop.h | 2 | header-y += cryptocop.h |
diff --git a/include/asm-cris/arch-v32/ptrace.h b/include/asm-cris/arch-v32/ptrace.h index 516cc7062d94..41f4e8662bc2 100644 --- a/include/asm-cris/arch-v32/ptrace.h +++ b/include/asm-cris/arch-v32/ptrace.h | |||
| @@ -106,9 +106,13 @@ struct switch_stack { | |||
| 106 | unsigned long return_ip; /* ip that _resume will return to */ | 106 | unsigned long return_ip; /* ip that _resume will return to */ |
| 107 | }; | 107 | }; |
| 108 | 108 | ||
| 109 | #ifdef __KERNEL__ | ||
| 110 | |||
| 109 | #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0) | 111 | #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0) |
| 110 | #define instruction_pointer(regs) ((regs)->erp) | 112 | #define instruction_pointer(regs) ((regs)->erp) |
| 111 | extern void show_regs(struct pt_regs *); | 113 | extern void show_regs(struct pt_regs *); |
| 112 | #define profile_pc(regs) instruction_pointer(regs) | 114 | #define profile_pc(regs) instruction_pointer(regs) |
| 113 | 115 | ||
| 116 | #endif /* __KERNEL__ */ | ||
| 117 | |||
| 114 | #endif | 118 | #endif |
diff --git a/include/asm-cris/kvm.h b/include/asm-cris/kvm.h deleted file mode 100644 index c860f51149f0..000000000000 --- a/include/asm-cris/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_CRIS_H | ||
| 2 | #define __LINUX_KVM_CRIS_H | ||
| 3 | |||
| 4 | /* cris does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-cris/ptrace.h b/include/asm-cris/ptrace.h index 1ec69a7ea836..d910925e3174 100644 --- a/include/asm-cris/ptrace.h +++ b/include/asm-cris/ptrace.h | |||
| @@ -4,11 +4,13 @@ | |||
| 4 | #include <asm/arch/ptrace.h> | 4 | #include <asm/arch/ptrace.h> |
| 5 | 5 | ||
| 6 | #ifdef __KERNEL__ | 6 | #ifdef __KERNEL__ |
| 7 | |||
| 7 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ | 8 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ |
| 8 | #define PTRACE_GETREGS 12 | 9 | #define PTRACE_GETREGS 12 |
| 9 | #define PTRACE_SETREGS 13 | 10 | #define PTRACE_SETREGS 13 |
| 10 | #endif | ||
| 11 | 11 | ||
| 12 | #define profile_pc(regs) instruction_pointer(regs) | 12 | #define profile_pc(regs) instruction_pointer(regs) |
| 13 | 13 | ||
| 14 | #endif /* __KERNEL__ */ | ||
| 15 | |||
| 14 | #endif /* _CRIS_PTRACE_H */ | 16 | #endif /* _CRIS_PTRACE_H */ |
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h index 784668ab0fa2..7efe1000f99d 100644 --- a/include/asm-cris/thread_info.h +++ b/include/asm-cris/thread_info.h | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | #ifdef __KERNEL__ | 12 | #ifdef __KERNEL__ |
| 13 | 13 | ||
| 14 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 15 | |||
| 14 | #ifndef __ASSEMBLY__ | 16 | #ifndef __ASSEMBLY__ |
| 15 | #include <asm/types.h> | 17 | #include <asm/types.h> |
| 16 | #include <asm/processor.h> | 18 | #include <asm/processor.h> |
diff --git a/include/asm-frv/Kbuild b/include/asm-frv/Kbuild index bc3f12c5b7e0..0f8956def738 100644 --- a/include/asm-frv/Kbuild +++ b/include/asm-frv/Kbuild | |||
| @@ -3,4 +3,3 @@ include include/asm-generic/Kbuild.asm | |||
| 3 | header-y += registers.h | 3 | header-y += registers.h |
| 4 | 4 | ||
| 5 | unifdef-y += termios.h | 5 | unifdef-y += termios.h |
| 6 | unifdef-y += ptrace.h | ||
diff --git a/include/asm-frv/kvm.h b/include/asm-frv/kvm.h deleted file mode 100644 index 9c8a4f08d0a9..000000000000 --- a/include/asm-frv/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_FRV_H | ||
| 2 | #define __LINUX_KVM_FRV_H | ||
| 3 | |||
| 4 | /* frv does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h index 348b8f1df17e..b7ac6bf2844c 100644 --- a/include/asm-frv/thread_info.h +++ b/include/asm-frv/thread_info.h | |||
| @@ -82,6 +82,8 @@ register struct thread_info *__current_thread_info asm("gr15"); | |||
| 82 | 82 | ||
| 83 | #define current_thread_info() ({ __current_thread_info; }) | 83 | #define current_thread_info() ({ __current_thread_info; }) |
| 84 | 84 | ||
| 85 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 86 | |||
| 85 | /* thread information allocation */ | 87 | /* thread information allocation */ |
| 86 | #ifdef CONFIG_DEBUG_STACK_USAGE | 88 | #ifdef CONFIG_DEBUG_STACK_USAGE |
| 87 | #define alloc_thread_info(tsk) \ | 89 | #define alloc_thread_info(tsk) \ |
diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm index 7cd25b8e7c9a..1170dc60e638 100644 --- a/include/asm-generic/Kbuild.asm +++ b/include/asm-generic/Kbuild.asm | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),) | ||
| 1 | header-y += kvm.h | 2 | header-y += kvm.h |
| 3 | endif | ||
| 2 | 4 | ||
| 3 | ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),) | 5 | ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),) |
| 4 | unifdef-y += a.out.h | 6 | unifdef-y += a.out.h |
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 2632328d8646..a3f738cffdb6 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h | |||
| @@ -34,9 +34,14 @@ struct bug_entry { | |||
| 34 | #ifndef __WARN | 34 | #ifndef __WARN |
| 35 | #ifndef __ASSEMBLY__ | 35 | #ifndef __ASSEMBLY__ |
| 36 | extern void warn_on_slowpath(const char *file, const int line); | 36 | extern void warn_on_slowpath(const char *file, const int line); |
| 37 | extern void warn_slowpath(const char *file, const int line, | ||
| 38 | const char *fmt, ...) __attribute__((format(printf, 3, 4))); | ||
| 37 | #define WANT_WARN_ON_SLOWPATH | 39 | #define WANT_WARN_ON_SLOWPATH |
| 38 | #endif | 40 | #endif |
| 39 | #define __WARN() warn_on_slowpath(__FILE__, __LINE__) | 41 | #define __WARN() warn_on_slowpath(__FILE__, __LINE__) |
| 42 | #define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg) | ||
| 43 | #else | ||
| 44 | #define __WARN_printf(arg...) __WARN() | ||
| 40 | #endif | 45 | #endif |
| 41 | 46 | ||
| 42 | #ifndef WARN_ON | 47 | #ifndef WARN_ON |
| @@ -48,6 +53,15 @@ extern void warn_on_slowpath(const char *file, const int line); | |||
| 48 | }) | 53 | }) |
| 49 | #endif | 54 | #endif |
| 50 | 55 | ||
| 56 | #ifndef WARN | ||
| 57 | #define WARN(condition, format...) ({ \ | ||
| 58 | int __ret_warn_on = !!(condition); \ | ||
| 59 | if (unlikely(__ret_warn_on)) \ | ||
| 60 | __WARN_printf(format); \ | ||
| 61 | unlikely(__ret_warn_on); \ | ||
| 62 | }) | ||
| 63 | #endif | ||
| 64 | |||
| 51 | #else /* !CONFIG_BUG */ | 65 | #else /* !CONFIG_BUG */ |
| 52 | #ifndef HAVE_ARCH_BUG | 66 | #ifndef HAVE_ARCH_BUG |
| 53 | #define BUG() | 67 | #define BUG() |
| @@ -63,6 +77,14 @@ extern void warn_on_slowpath(const char *file, const int line); | |||
| 63 | unlikely(__ret_warn_on); \ | 77 | unlikely(__ret_warn_on); \ |
| 64 | }) | 78 | }) |
| 65 | #endif | 79 | #endif |
| 80 | |||
| 81 | #ifndef WARN | ||
| 82 | #define WARN(condition, format...) ({ \ | ||
| 83 | int __ret_warn_on = !!(condition); \ | ||
| 84 | unlikely(__ret_warn_on); \ | ||
| 85 | }) | ||
| 86 | #endif | ||
| 87 | |||
| 66 | #endif | 88 | #endif |
| 67 | 89 | ||
| 68 | #define WARN_ON_ONCE(condition) ({ \ | 90 | #define WARN_ON_ONCE(condition) ({ \ |
| @@ -75,6 +97,9 @@ extern void warn_on_slowpath(const char *file, const int line); | |||
| 75 | unlikely(__ret_warn_once); \ | 97 | unlikely(__ret_warn_once); \ |
| 76 | }) | 98 | }) |
| 77 | 99 | ||
| 100 | #define WARN_ON_RATELIMIT(condition, state) \ | ||
| 101 | WARN_ON((condition) && __ratelimit(state)) | ||
| 102 | |||
| 78 | #ifdef CONFIG_SMP | 103 | #ifdef CONFIG_SMP |
| 79 | # define WARN_ON_SMP(x) WARN_ON(x) | 104 | # define WARN_ON_SMP(x) WARN_ON(x) |
| 80 | #else | 105 | #else |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 6be061d09da9..a3034d20ebd5 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
| 5 | 5 | ||
| 6 | #ifdef CONFIG_HAVE_GPIO_LIB | 6 | #ifdef CONFIG_GPIOLIB |
| 7 | 7 | ||
| 8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
| 9 | 9 | ||
| @@ -32,6 +32,8 @@ struct module; | |||
| 32 | /** | 32 | /** |
| 33 | * struct gpio_chip - abstract a GPIO controller | 33 | * struct gpio_chip - abstract a GPIO controller |
| 34 | * @label: for diagnostics | 34 | * @label: for diagnostics |
| 35 | * @dev: optional device providing the GPIOs | ||
| 36 | * @owner: helps prevent removal of modules exporting active GPIOs | ||
| 35 | * @direction_input: configures signal "offset" as input, or returns error | 37 | * @direction_input: configures signal "offset" as input, or returns error |
| 36 | * @get: returns value for signal "offset"; for output signals this | 38 | * @get: returns value for signal "offset"; for output signals this |
| 37 | * returns either the value actually sensed, or zero | 39 | * returns either the value actually sensed, or zero |
| @@ -59,6 +61,7 @@ struct module; | |||
| 59 | */ | 61 | */ |
| 60 | struct gpio_chip { | 62 | struct gpio_chip { |
| 61 | char *label; | 63 | char *label; |
| 64 | struct device *dev; | ||
| 62 | struct module *owner; | 65 | struct module *owner; |
| 63 | 66 | ||
| 64 | int (*direction_input)(struct gpio_chip *chip, | 67 | int (*direction_input)(struct gpio_chip *chip, |
| @@ -74,6 +77,7 @@ struct gpio_chip { | |||
| 74 | int base; | 77 | int base; |
| 75 | u16 ngpio; | 78 | u16 ngpio; |
| 76 | unsigned can_sleep:1; | 79 | unsigned can_sleep:1; |
| 80 | unsigned exported:1; | ||
| 77 | }; | 81 | }; |
| 78 | 82 | ||
| 79 | extern const char *gpiochip_is_requested(struct gpio_chip *chip, | 83 | extern const char *gpiochip_is_requested(struct gpio_chip *chip, |
| @@ -108,7 +112,18 @@ extern void __gpio_set_value(unsigned gpio, int value); | |||
| 108 | extern int __gpio_cansleep(unsigned gpio); | 112 | extern int __gpio_cansleep(unsigned gpio); |
| 109 | 113 | ||
| 110 | 114 | ||
| 111 | #else | 115 | #ifdef CONFIG_GPIO_SYSFS |
| 116 | |||
| 117 | /* | ||
| 118 | * A sysfs interface can be exported by individual drivers if they want, | ||
| 119 | * but more typically is configured entirely from userspace. | ||
| 120 | */ | ||
| 121 | extern int gpio_export(unsigned gpio, bool direction_may_change); | ||
| 122 | extern void gpio_unexport(unsigned gpio); | ||
| 123 | |||
| 124 | #endif /* CONFIG_GPIO_SYSFS */ | ||
| 125 | |||
| 126 | #else /* !CONFIG_HAVE_GPIO_LIB */ | ||
| 112 | 127 | ||
| 113 | static inline int gpio_is_valid(int number) | 128 | static inline int gpio_is_valid(int number) |
| 114 | { | 129 | { |
| @@ -137,6 +152,20 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value) | |||
| 137 | gpio_set_value(gpio, value); | 152 | gpio_set_value(gpio, value); |
| 138 | } | 153 | } |
| 139 | 154 | ||
| 140 | #endif | 155 | #endif /* !CONFIG_HAVE_GPIO_LIB */ |
| 156 | |||
| 157 | #ifndef CONFIG_GPIO_SYSFS | ||
| 158 | |||
| 159 | /* sysfs support is only available with gpiolib, where it's optional */ | ||
| 160 | |||
| 161 | static inline int gpio_export(unsigned gpio, bool direction_may_change) | ||
| 162 | { | ||
| 163 | return -ENOSYS; | ||
| 164 | } | ||
| 165 | |||
| 166 | static inline void gpio_unexport(unsigned gpio) | ||
| 167 | { | ||
| 168 | } | ||
| 169 | #endif /* CONFIG_GPIO_SYSFS */ | ||
| 141 | 170 | ||
| 142 | #endif /* _ASM_GENERIC_GPIO_H */ | 171 | #endif /* _ASM_GENERIC_GPIO_H */ |
diff --git a/include/asm-generic/int-ll64.h b/include/asm-generic/int-ll64.h index 260948905e4e..f9bc9ac29b36 100644 --- a/include/asm-generic/int-ll64.h +++ b/include/asm-generic/int-ll64.h | |||
| @@ -26,7 +26,7 @@ typedef unsigned int __u32; | |||
| 26 | #ifdef __GNUC__ | 26 | #ifdef __GNUC__ |
| 27 | __extension__ typedef __signed__ long long __s64; | 27 | __extension__ typedef __signed__ long long __s64; |
| 28 | __extension__ typedef unsigned long long __u64; | 28 | __extension__ typedef unsigned long long __u64; |
| 29 | #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L | 29 | #else |
| 30 | typedef __signed__ long long __s64; | 30 | typedef __signed__ long long __s64; |
| 31 | typedef unsigned long long __u64; | 31 | typedef unsigned long long __u64; |
| 32 | #endif | 32 | #endif |
diff --git a/include/asm-h8300/elf.h b/include/asm-h8300/elf.h index 26bfc7e641da..a8b57d1f4128 100644 --- a/include/asm-h8300/elf.h +++ b/include/asm-h8300/elf.h | |||
| @@ -26,10 +26,10 @@ typedef unsigned long elf_fpregset_t; | |||
| 26 | #define ELF_DATA ELFDATA2MSB | 26 | #define ELF_DATA ELFDATA2MSB |
| 27 | #define ELF_ARCH EM_H8_300 | 27 | #define ELF_ARCH EM_H8_300 |
| 28 | #if defined(__H8300H__) | 28 | #if defined(__H8300H__) |
| 29 | #define ELF_FLAGS 0x810000 | 29 | #define ELF_CORE_EFLAGS 0x810000 |
| 30 | #endif | 30 | #endif |
| 31 | #if defined(__H8300S__) | 31 | #if defined(__H8300S__) |
| 32 | #define ELF_FLAGS 0x820000 | 32 | #define ELF_CORE_EFLAGS 0x820000 |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | #define ELF_PLAT_INIT(_r) _r->er1 = 0 | 35 | #define ELF_PLAT_INIT(_r) _r->er1 = 0 |
diff --git a/include/asm-h8300/kvm.h b/include/asm-h8300/kvm.h deleted file mode 100644 index bdbed7b987e1..000000000000 --- a/include/asm-h8300/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_H8300_H | ||
| 2 | #define __LINUX_KVM_H8300_H | ||
| 3 | |||
| 4 | /* h8300 does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h index 27bb95e2944c..aafd4d322ec3 100644 --- a/include/asm-h8300/thread_info.h +++ b/include/asm-h8300/thread_info.h | |||
| @@ -49,6 +49,7 @@ struct thread_info { | |||
| 49 | /* | 49 | /* |
| 50 | * Size of kernel stack for each process. This must be a power of 2... | 50 | * Size of kernel stack for each process. This must be a power of 2... |
| 51 | */ | 51 | */ |
| 52 | #define THREAD_SIZE_ORDER 1 | ||
| 52 | #define THREAD_SIZE 8192 /* 2 pages */ | 53 | #define THREAD_SIZE 8192 /* 2 pages */ |
| 53 | 54 | ||
| 54 | 55 | ||
| @@ -65,10 +66,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 65 | return ti; | 66 | return ti; |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | /* thread information allocation */ | ||
| 69 | #define alloc_thread_info(tsk) ((struct thread_info *) \ | ||
| 70 | __get_free_pages(GFP_KERNEL, 1)) | ||
| 71 | #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) | ||
| 72 | #endif /* __ASSEMBLY__ */ | 69 | #endif /* __ASSEMBLY__ */ |
| 73 | 70 | ||
| 74 | /* | 71 | /* |
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 2422ac61658a..7c60fcdd2efd 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h | |||
| @@ -54,6 +54,8 @@ struct thread_info { | |||
| 54 | }, \ | 54 | }, \ |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 58 | |||
| 57 | #ifndef ASM_OFFSETS_C | 59 | #ifndef ASM_OFFSETS_C |
| 58 | /* how to get the thread information struct from C */ | 60 | /* how to get the thread information struct from C */ |
| 59 | #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE)) | 61 | #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE)) |
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index e60314716122..d535833aab5e 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h | |||
| @@ -302,11 +302,17 @@ | |||
| 302 | #define __NR_timerfd_create 1310 | 302 | #define __NR_timerfd_create 1310 |
| 303 | #define __NR_timerfd_settime 1311 | 303 | #define __NR_timerfd_settime 1311 |
| 304 | #define __NR_timerfd_gettime 1312 | 304 | #define __NR_timerfd_gettime 1312 |
| 305 | #define __NR_signalfd4 1313 | ||
| 306 | #define __NR_eventfd2 1314 | ||
| 307 | #define __NR_epoll_create1 1315 | ||
| 308 | #define __NR_dup3 1316 | ||
| 309 | #define __NR_pipe2 1317 | ||
| 310 | #define __NR_inotify_init1 1318 | ||
| 305 | 311 | ||
| 306 | #ifdef __KERNEL__ | 312 | #ifdef __KERNEL__ |
| 307 | 313 | ||
| 308 | 314 | ||
| 309 | #define NR_syscalls 289 /* length of syscall table */ | 315 | #define NR_syscalls 295 /* length of syscall table */ |
| 310 | 316 | ||
| 311 | /* | 317 | /* |
| 312 | * The following defines stop scripts/checksyscalls.sh from complaining about | 318 | * The following defines stop scripts/checksyscalls.sh from complaining about |
diff --git a/include/asm-m32r/kvm.h b/include/asm-m32r/kvm.h deleted file mode 100644 index 99a40515b77e..000000000000 --- a/include/asm-m32r/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_M32R_H | ||
| 2 | #define __LINUX_KVM_M32R_H | ||
| 3 | |||
| 4 | /* m32r does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h index 1effcd0f5e63..8589d462df27 100644 --- a/include/asm-m32r/thread_info.h +++ b/include/asm-m32r/thread_info.h | |||
| @@ -94,6 +94,8 @@ static inline struct thread_info *current_thread_info(void) | |||
| 94 | return ti; | 94 | return ti; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 98 | |||
| 97 | /* thread information allocation */ | 99 | /* thread information allocation */ |
| 98 | #ifdef CONFIG_DEBUG_STACK_USAGE | 100 | #ifdef CONFIG_DEBUG_STACK_USAGE |
| 99 | #define alloc_thread_info(tsk) \ | 101 | #define alloc_thread_info(tsk) \ |
diff --git a/include/asm-m68k/kvm.h b/include/asm-m68k/kvm.h deleted file mode 100644 index 7ed27fce5240..000000000000 --- a/include/asm-m68k/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_M68K_H | ||
| 2 | #define __LINUX_KVM_M68K_H | ||
| 3 | |||
| 4 | /* m68k does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h index d635a3752488..abc002798a2b 100644 --- a/include/asm-m68k/thread_info.h +++ b/include/asm-m68k/thread_info.h | |||
| @@ -25,13 +25,7 @@ struct thread_info { | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | /* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */ | 27 | /* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */ |
| 28 | #if PAGE_SHIFT == 13 /* 8k machines */ | 28 | #define THREAD_SIZE_ORDER (13 - PAGE_SHIFT) |
| 29 | #define alloc_thread_info(tsk) ((struct thread_info *)__get_free_pages(GFP_KERNEL,0)) | ||
| 30 | #define free_thread_info(ti) free_pages((unsigned long)(ti),0) | ||
| 31 | #else /* otherwise assume 4k pages */ | ||
| 32 | #define alloc_thread_info(tsk) ((struct thread_info *)__get_free_pages(GFP_KERNEL,1)) | ||
| 33 | #define free_thread_info(ti) free_pages((unsigned long)(ti),1) | ||
| 34 | #endif /* PAGE_SHIFT == 13 */ | ||
| 35 | 29 | ||
| 36 | #define init_thread_info (init_task.thread.info) | 30 | #define init_thread_info (init_task.thread.info) |
| 37 | #define init_stack (init_thread_union.stack) | 31 | #define init_stack (init_thread_union.stack) |
diff --git a/include/asm-m68knommu/kvm.h b/include/asm-m68knommu/kvm.h deleted file mode 100644 index b49d4258dabb..000000000000 --- a/include/asm-m68knommu/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_M68KNOMMU_H | ||
| 2 | #define __LINUX_KVM_M68KNOMMU_H | ||
| 3 | |||
| 4 | /* m68knommu does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-m68knommu/ptrace.h b/include/asm-m68knommu/ptrace.h index 47258e86e8c4..8c9194b98548 100644 --- a/include/asm-m68knommu/ptrace.h +++ b/include/asm-m68knommu/ptrace.h | |||
| @@ -68,10 +68,8 @@ struct switch_stack { | |||
| 68 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ | 68 | /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ |
| 69 | #define PTRACE_GETREGS 12 | 69 | #define PTRACE_GETREGS 12 |
| 70 | #define PTRACE_SETREGS 13 | 70 | #define PTRACE_SETREGS 13 |
| 71 | #ifdef CONFIG_FPU | ||
| 72 | #define PTRACE_GETFPREGS 14 | 71 | #define PTRACE_GETFPREGS 14 |
| 73 | #define PTRACE_SETFPREGS 15 | 72 | #define PTRACE_SETFPREGS 15 |
| 74 | #endif | ||
| 75 | 73 | ||
| 76 | #ifdef __KERNEL__ | 74 | #ifdef __KERNEL__ |
| 77 | 75 | ||
diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h index 95996d978bed..0c9bc095f3f0 100644 --- a/include/asm-m68knommu/thread_info.h +++ b/include/asm-m68knommu/thread_info.h | |||
| @@ -71,10 +71,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 71 | return ti; | 71 | return ti; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /* thread information allocation */ | ||
| 75 | #define alloc_thread_info(tsk) ((struct thread_info *) \ | ||
| 76 | __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER)) | ||
| 77 | #define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_SIZE_ORDER) | ||
| 78 | #endif /* __ASSEMBLY__ */ | 74 | #endif /* __ASSEMBLY__ */ |
| 79 | 75 | ||
| 80 | #define PREEMPT_ACTIVE 0x4000000 | 76 | #define PREEMPT_ACTIVE 0x4000000 |
diff --git a/include/asm-mips/kvm.h b/include/asm-mips/kvm.h deleted file mode 100644 index 093a5b7f796b..000000000000 --- a/include/asm-mips/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_MIPS_H | ||
| 2 | #define __LINUX_KVM_MIPS_H | ||
| 3 | |||
| 4 | /* mips does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-mips/mach-generic/gpio.h b/include/asm-mips/mach-generic/gpio.h index e6b376bd9d06..b4e70208da64 100644 --- a/include/asm-mips/mach-generic/gpio.h +++ b/include/asm-mips/mach-generic/gpio.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #ifndef __ASM_MACH_GENERIC_GPIO_H | 1 | #ifndef __ASM_MACH_GENERIC_GPIO_H |
| 2 | #define __ASM_MACH_GENERIC_GPIO_H | 2 | #define __ASM_MACH_GENERIC_GPIO_H |
| 3 | 3 | ||
| 4 | #ifdef CONFIG_HAVE_GPIO_LIB | 4 | #ifdef CONFIG_GPIOLIB |
| 5 | #define gpio_get_value __gpio_get_value | 5 | #define gpio_get_value __gpio_get_value |
| 6 | #define gpio_set_value __gpio_set_value | 6 | #define gpio_set_value __gpio_set_value |
| 7 | #define gpio_cansleep __gpio_cansleep | 7 | #define gpio_cansleep __gpio_cansleep |
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h index b2772df1a1bd..bb3060699df2 100644 --- a/include/asm-mips/thread_info.h +++ b/include/asm-mips/thread_info.h | |||
| @@ -82,6 +82,8 @@ register struct thread_info *__current_thread_info __asm__("$28"); | |||
| 82 | #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) | 82 | #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) |
| 83 | #define THREAD_MASK (THREAD_SIZE - 1UL) | 83 | #define THREAD_MASK (THREAD_SIZE - 1UL) |
| 84 | 84 | ||
| 85 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 86 | |||
| 85 | #ifdef CONFIG_DEBUG_STACK_USAGE | 87 | #ifdef CONFIG_DEBUG_STACK_USAGE |
| 86 | #define alloc_thread_info(tsk) \ | 88 | #define alloc_thread_info(tsk) \ |
| 87 | ({ \ | 89 | ({ \ |
diff --git a/include/asm-mn10300/kvm.h b/include/asm-mn10300/kvm.h deleted file mode 100644 index f6b609ff4a57..000000000000 --- a/include/asm-mn10300/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_MN10300_H | ||
| 2 | #define __LINUX_KVM_MN10300_H | ||
| 3 | |||
| 4 | /* mn10300 does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-mn10300/ptrace.h b/include/asm-mn10300/ptrace.h index b3684689fcce..7b06cc623d8b 100644 --- a/include/asm-mn10300/ptrace.h +++ b/include/asm-mn10300/ptrace.h | |||
| @@ -88,12 +88,16 @@ extern struct pt_regs *__frame; /* current frame pointer */ | |||
| 88 | /* options set using PTRACE_SETOPTIONS */ | 88 | /* options set using PTRACE_SETOPTIONS */ |
| 89 | #define PTRACE_O_TRACESYSGOOD 0x00000001 | 89 | #define PTRACE_O_TRACESYSGOOD 0x00000001 |
| 90 | 90 | ||
| 91 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) | 91 | #if defined(__KERNEL__) |
| 92 | |||
| 93 | #if !defined(__ASSEMBLY__) | ||
| 92 | #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL) | 94 | #define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL) |
| 93 | #define instruction_pointer(regs) ((regs)->pc) | 95 | #define instruction_pointer(regs) ((regs)->pc) |
| 94 | extern void show_regs(struct pt_regs *); | 96 | extern void show_regs(struct pt_regs *); |
| 95 | #endif | 97 | #endif /* !__ASSEMBLY */ |
| 96 | 98 | ||
| 97 | #define profile_pc(regs) ((regs)->pc) | 99 | #define profile_pc(regs) ((regs)->pc) |
| 98 | 100 | ||
| 101 | #endif /* __KERNEL__ */ | ||
| 102 | |||
| 99 | #endif /* _ASM_PTRACE_H */ | 103 | #endif /* _ASM_PTRACE_H */ |
diff --git a/include/asm-mn10300/thread_info.h b/include/asm-mn10300/thread_info.h index e397e7192785..78a3881f3c12 100644 --- a/include/asm-mn10300/thread_info.h +++ b/include/asm-mn10300/thread_info.h | |||
| @@ -112,6 +112,8 @@ static inline unsigned long current_stack_pointer(void) | |||
| 112 | return sp; | 112 | return sp; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 116 | |||
| 115 | /* thread information allocation */ | 117 | /* thread information allocation */ |
| 116 | #ifdef CONFIG_DEBUG_STACK_USAGE | 118 | #ifdef CONFIG_DEBUG_STACK_USAGE |
| 117 | #define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL) | 119 | #define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL) |
diff --git a/include/asm-parisc/kvm.h b/include/asm-parisc/kvm.h deleted file mode 100644 index 00cc45812547..000000000000 --- a/include/asm-parisc/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_PARISC_H | ||
| 2 | #define __LINUX_KVM_PARISC_H | ||
| 3 | |||
| 4 | /* parisc does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-parisc/ptrace.h b/include/asm-parisc/ptrace.h index 93f990e418f1..3e94c5d85ff5 100644 --- a/include/asm-parisc/ptrace.h +++ b/include/asm-parisc/ptrace.h | |||
| @@ -33,7 +33,6 @@ struct pt_regs { | |||
| 33 | unsigned long ipsw; /* CR22 */ | 33 | unsigned long ipsw; /* CR22 */ |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) | ||
| 37 | /* | 36 | /* |
| 38 | * The numbers chosen here are somewhat arbitrary but absolutely MUST | 37 | * The numbers chosen here are somewhat arbitrary but absolutely MUST |
| 39 | * not overlap with any of the number assigned in <linux/ptrace.h>. | 38 | * not overlap with any of the number assigned in <linux/ptrace.h>. |
| @@ -43,8 +42,11 @@ struct pt_regs { | |||
| 43 | * since we have taken branch traps too) | 42 | * since we have taken branch traps too) |
| 44 | */ | 43 | */ |
| 45 | #define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */ | 44 | #define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */ |
| 45 | |||
| 46 | #ifdef __KERNEL__ | 46 | #ifdef __KERNEL__ |
| 47 | 47 | ||
| 48 | #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) | ||
| 49 | |||
| 48 | /* XXX should we use iaoq[1] or iaoq[0] ? */ | 50 | /* XXX should we use iaoq[1] or iaoq[0] ? */ |
| 49 | #define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0) | 51 | #define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0) |
| 50 | #define user_space(regs) (((regs)->iasq[1] != 0) ? 1 : 0) | 52 | #define user_space(regs) (((regs)->iasq[1] != 0) ? 1 : 0) |
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h index 2d9c7500867b..9f812741c355 100644 --- a/include/asm-parisc/thread_info.h +++ b/include/asm-parisc/thread_info.h | |||
| @@ -34,15 +34,11 @@ struct thread_info { | |||
| 34 | 34 | ||
| 35 | /* thread information allocation */ | 35 | /* thread information allocation */ |
| 36 | 36 | ||
| 37 | #define THREAD_ORDER 2 | 37 | #define THREAD_SIZE_ORDER 2 |
| 38 | /* Be sure to hunt all references to this down when you change the size of | 38 | /* Be sure to hunt all references to this down when you change the size of |
| 39 | * the kernel stack */ | 39 | * the kernel stack */ |
| 40 | #define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER) | 40 | #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) |
| 41 | #define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER) | 41 | #define THREAD_SHIFT (PAGE_SHIFT + THREAD_SIZE_ORDER) |
| 42 | |||
| 43 | #define alloc_thread_info(tsk) ((struct thread_info *) \ | ||
| 44 | __get_free_pages(GFP_KERNEL, THREAD_ORDER)) | ||
| 45 | #define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER) | ||
| 46 | 42 | ||
| 47 | /* how to get the thread information struct from C */ | 43 | /* how to get the thread information struct from C */ |
| 48 | #define current_thread_info() ((struct thread_info *)mfctl(30)) | 44 | #define current_thread_info() ((struct thread_info *)mfctl(30)) |
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild index 04ce8f8a2ee7..5ab7d7fe198c 100644 --- a/include/asm-powerpc/Kbuild +++ b/include/asm-powerpc/Kbuild | |||
| @@ -29,7 +29,6 @@ unifdef-y += elf.h | |||
| 29 | unifdef-y += nvram.h | 29 | unifdef-y += nvram.h |
| 30 | unifdef-y += param.h | 30 | unifdef-y += param.h |
| 31 | unifdef-y += posix_types.h | 31 | unifdef-y += posix_types.h |
| 32 | unifdef-y += ptrace.h | ||
| 33 | unifdef-y += seccomp.h | 32 | unifdef-y += seccomp.h |
| 34 | unifdef-y += signal.h | 33 | unifdef-y += signal.h |
| 35 | unifdef-y += spu_info.h | 34 | unifdef-y += spu_info.h |
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 2a3e9075a5a0..ef8a248dfd55 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h | |||
| @@ -127,6 +127,8 @@ extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr); | |||
| 127 | extern void do_feature_fixups(unsigned long value, void *fixup_start, | 127 | extern void do_feature_fixups(unsigned long value, void *fixup_start, |
| 128 | void *fixup_end); | 128 | void *fixup_end); |
| 129 | 129 | ||
| 130 | extern const char *powerpc_base_platform; | ||
| 131 | |||
| 130 | #endif /* __ASSEMBLY__ */ | 132 | #endif /* __ASSEMBLY__ */ |
| 131 | 133 | ||
| 132 | /* CPU kernel features */ | 134 | /* CPU kernel features */ |
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 89664675b469..80d1f399ee51 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h | |||
| @@ -217,6 +217,14 @@ typedef elf_vrregset_t elf_fpxregset_t; | |||
| 217 | 217 | ||
| 218 | #define ELF_PLATFORM (cur_cpu_spec->platform) | 218 | #define ELF_PLATFORM (cur_cpu_spec->platform) |
| 219 | 219 | ||
| 220 | /* While ELF_PLATFORM indicates the ISA supported by the platform, it | ||
| 221 | * may not accurately reflect the underlying behavior of the hardware | ||
| 222 | * (as in the case of running in Power5+ compatibility mode on a | ||
| 223 | * Power6 machine). ELF_BASE_PLATFORM allows ld.so to load libraries | ||
| 224 | * that are tuned for the real hardware. | ||
| 225 | */ | ||
| 226 | #define ELF_BASE_PLATFORM (powerpc_base_platform) | ||
| 227 | |||
| 220 | #ifdef __powerpc64__ | 228 | #ifdef __powerpc64__ |
| 221 | # define ELF_PLAT_INIT(_r, load_addr) do { \ | 229 | # define ELF_PLAT_INIT(_r, load_addr) do { \ |
| 222 | _r->gpr[2] = load_addr; \ | 230 | _r->gpr[2] = load_addr; \ |
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index ef328995ba9d..3a179827528d 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) | 46 | #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) |
| 47 | #define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000) | 47 | #define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000) |
| 48 | #define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000002000000) | 48 | #define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000002000000) |
| 49 | #define FW_FEATURE_CMO ASM_CONST(0x0000000004000000) | ||
| 49 | 50 | ||
| 50 | #ifndef __ASSEMBLY__ | 51 | #ifndef __ASSEMBLY__ |
| 51 | 52 | ||
| @@ -58,7 +59,7 @@ enum { | |||
| 58 | FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ | | 59 | FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ | |
| 59 | FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | | 60 | FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | |
| 60 | FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE | | 61 | FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE | |
| 61 | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR, | 62 | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_CMO, |
| 62 | FW_FEATURE_PSERIES_ALWAYS = 0, | 63 | FW_FEATURE_PSERIES_ALWAYS = 0, |
| 63 | FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, | 64 | FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
| 64 | FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, | 65 | FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
diff --git a/include/asm-powerpc/gpio.h b/include/asm-powerpc/gpio.h index 77ad3a890f30..ea04632399d8 100644 --- a/include/asm-powerpc/gpio.h +++ b/include/asm-powerpc/gpio.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
| 18 | #include <asm-generic/gpio.h> | 18 | #include <asm-generic/gpio.h> |
| 19 | 19 | ||
| 20 | #ifdef CONFIG_HAVE_GPIO_LIB | 20 | #ifdef CONFIG_GPIOLIB |
| 21 | 21 | ||
| 22 | /* | 22 | /* |
| 23 | * We don't (yet) implement inlined/rapid versions for on-chip gpios. | 23 | * We don't (yet) implement inlined/rapid versions for on-chip gpios. |
| @@ -51,6 +51,6 @@ static inline int irq_to_gpio(unsigned int irq) | |||
| 51 | return -EINVAL; | 51 | return -EINVAL; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | #endif /* CONFIG_HAVE_GPIO_LIB */ | 54 | #endif /* CONFIG_GPIOLIB */ |
| 55 | 55 | ||
| 56 | #endif /* __ASM_POWERPC_GPIO_H */ | 56 | #endif /* __ASM_POWERPC_GPIO_H */ |
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index bf6cd7cb996c..fbe2932fa9e9 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h | |||
| @@ -92,6 +92,11 @@ | |||
| 92 | #define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */ | 92 | #define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */ |
| 93 | #define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */ | 93 | #define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */ |
| 94 | #define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */ | 94 | #define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */ |
| 95 | #define H_PAGE_STATE_CHANGE (1UL<<(63-28)) | ||
| 96 | #define H_PAGE_UNUSED ((1UL<<(63-29)) | (1UL<<(63-30))) | ||
| 97 | #define H_PAGE_SET_UNUSED (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED) | ||
| 98 | #define H_PAGE_SET_LOANED (H_PAGE_SET_UNUSED | (1UL<<(63-31))) | ||
| 99 | #define H_PAGE_SET_ACTIVE H_PAGE_STATE_CHANGE | ||
| 95 | #define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */ | 100 | #define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */ |
| 96 | #define H_ANDCOND (1UL<<(63-33)) | 101 | #define H_ANDCOND (1UL<<(63-33)) |
| 97 | #define H_ICACHE_INVALIDATE (1UL<<(63-40)) /* icbi, etc. (ignored for IO pages) */ | 102 | #define H_ICACHE_INVALIDATE (1UL<<(63-40)) /* icbi, etc. (ignored for IO pages) */ |
| @@ -210,7 +215,9 @@ | |||
| 210 | #define H_JOIN 0x298 | 215 | #define H_JOIN 0x298 |
| 211 | #define H_VASI_STATE 0x2A4 | 216 | #define H_VASI_STATE 0x2A4 |
| 212 | #define H_ENABLE_CRQ 0x2B0 | 217 | #define H_ENABLE_CRQ 0x2B0 |
| 213 | #define MAX_HCALL_OPCODE H_ENABLE_CRQ | 218 | #define H_SET_MPP 0x2D0 |
| 219 | #define H_GET_MPP 0x2D4 | ||
| 220 | #define MAX_HCALL_OPCODE H_GET_MPP | ||
| 214 | 221 | ||
| 215 | #ifndef __ASSEMBLY__ | 222 | #ifndef __ASSEMBLY__ |
| 216 | 223 | ||
| @@ -270,6 +277,20 @@ struct hcall_stats { | |||
| 270 | }; | 277 | }; |
| 271 | #define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) | 278 | #define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) |
| 272 | 279 | ||
| 280 | struct hvcall_mpp_data { | ||
| 281 | unsigned long entitled_mem; | ||
| 282 | unsigned long mapped_mem; | ||
| 283 | unsigned short group_num; | ||
| 284 | unsigned short pool_num; | ||
| 285 | unsigned char mem_weight; | ||
| 286 | unsigned char unallocated_mem_weight; | ||
| 287 | unsigned long unallocated_entitlement; /* value in bytes */ | ||
| 288 | unsigned long pool_size; | ||
| 289 | signed long loan_request; | ||
| 290 | unsigned long backing_mem; | ||
| 291 | }; | ||
| 292 | |||
| 293 | int h_get_mpp(struct hvcall_mpp_data *); | ||
| 273 | #endif /* __ASSEMBLY__ */ | 294 | #endif /* __ASSEMBLY__ */ |
| 274 | #endif /* __KERNEL__ */ | 295 | #endif /* __KERNEL__ */ |
| 275 | #endif /* _ASM_POWERPC_HVCALL_H */ | 296 | #endif /* _ASM_POWERPC_HVCALL_H */ |
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h index 567ed92cd91f..2fe268b10333 100644 --- a/include/asm-powerpc/lppaca.h +++ b/include/asm-powerpc/lppaca.h | |||
| @@ -125,7 +125,10 @@ struct lppaca { | |||
| 125 | // NOTE: This value will ALWAYS be zero for dedicated processors and | 125 | // NOTE: This value will ALWAYS be zero for dedicated processors and |
| 126 | // will NEVER be zero for shared processors (ie, initialized to a 1). | 126 | // will NEVER be zero for shared processors (ie, initialized to a 1). |
| 127 | volatile u32 yield_count; // PLIC increments each dispatchx00-x03 | 127 | volatile u32 yield_count; // PLIC increments each dispatchx00-x03 |
| 128 | u8 reserved6[124]; // Reserved x04-x7F | 128 | u32 reserved6; |
| 129 | volatile u64 cmo_faults; // CMO page fault count x08-x0F | ||
| 130 | volatile u64 cmo_fault_time; // CMO page fault time x10-x17 | ||
| 131 | u8 reserved7[104]; // Reserved x18-x7F | ||
| 129 | 132 | ||
| 130 | //============================================================================= | 133 | //============================================================================= |
| 131 | // CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data | 134 | // CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data |
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 1233d735fd28..893aafd87fde 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
| @@ -76,7 +76,7 @@ struct machdep_calls { | |||
| 76 | * destroyed as well */ | 76 | * destroyed as well */ |
| 77 | void (*hpte_clear_all)(void); | 77 | void (*hpte_clear_all)(void); |
| 78 | 78 | ||
| 79 | void (*tce_build)(struct iommu_table * tbl, | 79 | int (*tce_build)(struct iommu_table *tbl, |
| 80 | long index, | 80 | long index, |
| 81 | long npages, | 81 | long npages, |
| 82 | unsigned long uaddr, | 82 | unsigned long uaddr, |
diff --git a/include/asm-powerpc/mpc52xx_psc.h b/include/asm-powerpc/mpc52xx_psc.h index 710c5d36efaa..8917ed630565 100644 --- a/include/asm-powerpc/mpc52xx_psc.h +++ b/include/asm-powerpc/mpc52xx_psc.h | |||
| @@ -60,10 +60,12 @@ | |||
| 60 | #define MPC52xx_PSC_RXTX_FIFO_ALARM 0x0002 | 60 | #define MPC52xx_PSC_RXTX_FIFO_ALARM 0x0002 |
| 61 | #define MPC52xx_PSC_RXTX_FIFO_EMPTY 0x0001 | 61 | #define MPC52xx_PSC_RXTX_FIFO_EMPTY 0x0001 |
| 62 | 62 | ||
| 63 | /* PSC interrupt mask bits */ | 63 | /* PSC interrupt status/mask bits */ |
| 64 | #define MPC52xx_PSC_IMR_TXRDY 0x0100 | 64 | #define MPC52xx_PSC_IMR_TXRDY 0x0100 |
| 65 | #define MPC52xx_PSC_IMR_RXRDY 0x0200 | 65 | #define MPC52xx_PSC_IMR_RXRDY 0x0200 |
| 66 | #define MPC52xx_PSC_IMR_DB 0x0400 | 66 | #define MPC52xx_PSC_IMR_DB 0x0400 |
| 67 | #define MPC52xx_PSC_IMR_TXEMP 0x0800 | ||
| 68 | #define MPC52xx_PSC_IMR_ORERR 0x1000 | ||
| 67 | #define MPC52xx_PSC_IMR_IPC 0x8000 | 69 | #define MPC52xx_PSC_IMR_IPC 0x8000 |
| 68 | 70 | ||
| 69 | /* PSC input port change bit */ | 71 | /* PSC input port change bit */ |
| @@ -92,6 +94,34 @@ | |||
| 92 | 94 | ||
| 93 | #define MPC52xx_PSC_RFNUM_MASK 0x01ff | 95 | #define MPC52xx_PSC_RFNUM_MASK 0x01ff |
| 94 | 96 | ||
| 97 | #define MPC52xx_PSC_SICR_DTS1 (1 << 29) | ||
| 98 | #define MPC52xx_PSC_SICR_SHDR (1 << 28) | ||
| 99 | #define MPC52xx_PSC_SICR_SIM_MASK (0xf << 24) | ||
| 100 | #define MPC52xx_PSC_SICR_SIM_UART (0x0 << 24) | ||
| 101 | #define MPC52xx_PSC_SICR_SIM_UART_DCD (0x8 << 24) | ||
| 102 | #define MPC52xx_PSC_SICR_SIM_CODEC_8 (0x1 << 24) | ||
| 103 | #define MPC52xx_PSC_SICR_SIM_CODEC_16 (0x2 << 24) | ||
| 104 | #define MPC52xx_PSC_SICR_SIM_AC97 (0x3 << 24) | ||
| 105 | #define MPC52xx_PSC_SICR_SIM_SIR (0x8 << 24) | ||
| 106 | #define MPC52xx_PSC_SICR_SIM_SIR_DCD (0xc << 24) | ||
| 107 | #define MPC52xx_PSC_SICR_SIM_MIR (0x5 << 24) | ||
| 108 | #define MPC52xx_PSC_SICR_SIM_FIR (0x6 << 24) | ||
| 109 | #define MPC52xx_PSC_SICR_SIM_CODEC_24 (0x7 << 24) | ||
| 110 | #define MPC52xx_PSC_SICR_SIM_CODEC_32 (0xf << 24) | ||
| 111 | #define MPC52xx_PSC_SICR_GENCLK (1 << 23) | ||
| 112 | #define MPC52xx_PSC_SICR_I2S (1 << 22) | ||
| 113 | #define MPC52xx_PSC_SICR_CLKPOL (1 << 21) | ||
| 114 | #define MPC52xx_PSC_SICR_SYNCPOL (1 << 20) | ||
| 115 | #define MPC52xx_PSC_SICR_CELLSLAVE (1 << 19) | ||
| 116 | #define MPC52xx_PSC_SICR_CELL2XCLK (1 << 18) | ||
| 117 | #define MPC52xx_PSC_SICR_ESAI (1 << 17) | ||
| 118 | #define MPC52xx_PSC_SICR_ENAC97 (1 << 16) | ||
| 119 | #define MPC52xx_PSC_SICR_SPI (1 << 15) | ||
| 120 | #define MPC52xx_PSC_SICR_MSTR (1 << 14) | ||
| 121 | #define MPC52xx_PSC_SICR_CPOL (1 << 13) | ||
| 122 | #define MPC52xx_PSC_SICR_CPHA (1 << 12) | ||
| 123 | #define MPC52xx_PSC_SICR_USEEOF (1 << 11) | ||
| 124 | #define MPC52xx_PSC_SICR_DISABLEEOF (1 << 10) | ||
| 95 | 125 | ||
| 96 | /* Structure of the hardware registers */ | 126 | /* Structure of the hardware registers */ |
| 97 | struct mpc52xx_psc { | 127 | struct mpc52xx_psc { |
| @@ -132,8 +162,12 @@ struct mpc52xx_psc { | |||
| 132 | u8 reserved5[3]; | 162 | u8 reserved5[3]; |
| 133 | u8 ctlr; /* PSC + 0x1c */ | 163 | u8 ctlr; /* PSC + 0x1c */ |
| 134 | u8 reserved6[3]; | 164 | u8 reserved6[3]; |
| 135 | u16 ccr; /* PSC + 0x20 */ | 165 | /* BitClkDiv field of CCR is byte swapped in |
| 136 | u8 reserved7[14]; | 166 | * the hardware for mpc5200/b compatibility */ |
| 167 | u32 ccr; /* PSC + 0x20 */ | ||
| 168 | u32 ac97_slots; /* PSC + 0x24 */ | ||
| 169 | u32 ac97_cmd; /* PSC + 0x28 */ | ||
| 170 | u32 ac97_data; /* PSC + 0x2c */ | ||
| 137 | u8 ivr; /* PSC + 0x30 */ | 171 | u8 ivr; /* PSC + 0x30 */ |
| 138 | u8 reserved8[3]; | 172 | u8 reserved8[3]; |
| 139 | u8 ip; /* PSC + 0x34 */ | 173 | u8 ip; /* PSC + 0x34 */ |
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index d18ffe7bc7c4..dbb8ca172e44 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h | |||
| @@ -38,6 +38,19 @@ extern void paging_init(void); | |||
| 38 | remap_pfn_range(vma, vaddr, pfn, size, prot) | 38 | remap_pfn_range(vma, vaddr, pfn, size, prot) |
| 39 | 39 | ||
| 40 | #include <asm-generic/pgtable.h> | 40 | #include <asm-generic/pgtable.h> |
| 41 | |||
| 42 | |||
| 43 | /* | ||
| 44 | * This gets called at the end of handling a page fault, when | ||
| 45 | * the kernel has put a new PTE into the page table for the process. | ||
| 46 | * We use it to ensure coherency between the i-cache and d-cache | ||
| 47 | * for the page which has just been mapped in. | ||
| 48 | * On machines which use an MMU hash table, we use this to put a | ||
| 49 | * corresponding HPTE into the hash table ahead of time, instead of | ||
| 50 | * waiting for the inevitable extra hash-table miss exception. | ||
| 51 | */ | ||
| 52 | extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); | ||
| 53 | |||
| 41 | #endif /* __ASSEMBLY__ */ | 54 | #endif /* __ASSEMBLY__ */ |
| 42 | 55 | ||
| 43 | #endif /* __KERNEL__ */ | 56 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h index 2b8a458f990a..eb8eb400c664 100644 --- a/include/asm-powerpc/syscalls.h +++ b/include/asm-powerpc/syscalls.h | |||
| @@ -31,6 +31,7 @@ asmlinkage int sys_vfork(unsigned long p1, unsigned long p2, | |||
| 31 | unsigned long p3, unsigned long p4, unsigned long p5, | 31 | unsigned long p3, unsigned long p4, unsigned long p5, |
| 32 | unsigned long p6, struct pt_regs *regs); | 32 | unsigned long p6, struct pt_regs *regs); |
| 33 | asmlinkage long sys_pipe(int __user *fildes); | 33 | asmlinkage long sys_pipe(int __user *fildes); |
| 34 | asmlinkage long sys_pipe2(int __user *fildes, int flags); | ||
| 34 | asmlinkage long sys_rt_sigaction(int sig, | 35 | asmlinkage long sys_rt_sigaction(int sig, |
| 35 | const struct sigaction __user *act, | 36 | const struct sigaction __user *act, |
| 36 | struct sigaction __user *oact, size_t sigsetsize); | 37 | struct sigaction __user *oact, size_t sigsetsize); |
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h index ae7085c65692..e084272ed1c2 100644 --- a/include/asm-powerpc/systbl.h +++ b/include/asm-powerpc/systbl.h | |||
| @@ -316,3 +316,9 @@ COMPAT_SYS(fallocate) | |||
| 316 | SYSCALL(subpage_prot) | 316 | SYSCALL(subpage_prot) |
| 317 | COMPAT_SYS_SPU(timerfd_settime) | 317 | COMPAT_SYS_SPU(timerfd_settime) |
| 318 | COMPAT_SYS_SPU(timerfd_gettime) | 318 | COMPAT_SYS_SPU(timerfd_gettime) |
| 319 | COMPAT_SYS_SPU(signalfd4) | ||
| 320 | SYSCALL_SPU(eventfd2) | ||
| 321 | SYSCALL_SPU(epoll_create1) | ||
| 322 | SYSCALL_SPU(dup3) | ||
| 323 | SYSCALL_SPU(pipe2) | ||
| 324 | SYSCALL(inotify_init1) | ||
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index e6e25e2364eb..d6648c143322 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
| @@ -110,6 +110,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } | |||
| 110 | #endif | 110 | #endif |
| 111 | 111 | ||
| 112 | extern int set_dabr(unsigned long dabr); | 112 | extern int set_dabr(unsigned long dabr); |
| 113 | extern void do_dabr(struct pt_regs *regs, unsigned long address, | ||
| 114 | unsigned long error_code); | ||
| 113 | extern void print_backtrace(unsigned long *); | 115 | extern void print_backtrace(unsigned long *); |
| 114 | extern void show_regs(struct pt_regs * regs); | 116 | extern void show_regs(struct pt_regs * regs); |
| 115 | extern void flush_instruction_cache(void); | 117 | extern void flush_instruction_cache(void); |
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index b705c2a7651a..a9db562df69a 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h | |||
| @@ -66,20 +66,12 @@ struct thread_info { | |||
| 66 | 66 | ||
| 67 | #if THREAD_SHIFT >= PAGE_SHIFT | 67 | #if THREAD_SHIFT >= PAGE_SHIFT |
| 68 | 68 | ||
| 69 | #define THREAD_ORDER (THREAD_SHIFT - PAGE_SHIFT) | 69 | #define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT) |
| 70 | |||
| 71 | #ifdef CONFIG_DEBUG_STACK_USAGE | ||
| 72 | #define alloc_thread_info(tsk) \ | ||
| 73 | ((struct thread_info *)__get_free_pages(GFP_KERNEL | \ | ||
| 74 | __GFP_ZERO, THREAD_ORDER)) | ||
| 75 | #else | ||
| 76 | #define alloc_thread_info(tsk) \ | ||
| 77 | ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_ORDER)) | ||
| 78 | #endif | ||
| 79 | #define free_thread_info(ti) free_pages((unsigned long)ti, THREAD_ORDER) | ||
| 80 | 70 | ||
| 81 | #else /* THREAD_SHIFT < PAGE_SHIFT */ | 71 | #else /* THREAD_SHIFT < PAGE_SHIFT */ |
| 82 | 72 | ||
| 73 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 74 | |||
| 83 | extern struct thread_info *alloc_thread_info(struct task_struct *tsk); | 75 | extern struct thread_info *alloc_thread_info(struct task_struct *tsk); |
| 84 | extern void free_thread_info(struct thread_info *ti); | 76 | extern void free_thread_info(struct thread_info *ti); |
| 85 | 77 | ||
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index 5c9108147644..361cd5c7a32b 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h | |||
| @@ -162,16 +162,5 @@ extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | |||
| 162 | 162 | ||
| 163 | #endif | 163 | #endif |
| 164 | 164 | ||
| 165 | /* | ||
| 166 | * This gets called at the end of handling a page fault, when | ||
| 167 | * the kernel has put a new PTE into the page table for the process. | ||
| 168 | * We use it to ensure coherency between the i-cache and d-cache | ||
| 169 | * for the page which has just been mapped in. | ||
| 170 | * On machines which use an MMU hash table, we use this to put a | ||
| 171 | * corresponding HPTE into the hash table ahead of time, instead of | ||
| 172 | * waiting for the inevitable extra hash-table miss exception. | ||
| 173 | */ | ||
| 174 | extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); | ||
| 175 | |||
| 176 | #endif /*__KERNEL__ */ | 165 | #endif /*__KERNEL__ */ |
| 177 | #endif /* _ASM_POWERPC_TLBFLUSH_H */ | 166 | #endif /* _ASM_POWERPC_TLBFLUSH_H */ |
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index ce91bb662063..e07d0c76ed77 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h | |||
| @@ -335,10 +335,16 @@ | |||
| 335 | #define __NR_subpage_prot 310 | 335 | #define __NR_subpage_prot 310 |
| 336 | #define __NR_timerfd_settime 311 | 336 | #define __NR_timerfd_settime 311 |
| 337 | #define __NR_timerfd_gettime 312 | 337 | #define __NR_timerfd_gettime 312 |
| 338 | #define __NR_signalfd4 313 | ||
| 339 | #define __NR_eventfd2 314 | ||
| 340 | #define __NR_epoll_create1 315 | ||
| 341 | #define __NR_dup3 316 | ||
| 342 | #define __NR_pipe2 317 | ||
| 343 | #define __NR_inotify_init1 318 | ||
| 338 | 344 | ||
| 339 | #ifdef __KERNEL__ | 345 | #ifdef __KERNEL__ |
| 340 | 346 | ||
| 341 | #define __NR_syscalls 313 | 347 | #define __NR_syscalls 319 |
| 342 | 348 | ||
| 343 | #define __NR__exit __NR_exit | 349 | #define __NR__exit __NR_exit |
| 344 | #define NR_syscalls __NR_syscalls | 350 | #define NR_syscalls __NR_syscalls |
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 56512a968dab..0a290a195946 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h | |||
| @@ -39,16 +39,32 @@ | |||
| 39 | #define VIO_IRQ_DISABLE 0UL | 39 | #define VIO_IRQ_DISABLE 0UL |
| 40 | #define VIO_IRQ_ENABLE 1UL | 40 | #define VIO_IRQ_ENABLE 1UL |
| 41 | 41 | ||
| 42 | /* | ||
| 43 | * VIO CMO minimum entitlement for all devices and spare entitlement | ||
| 44 | */ | ||
| 45 | #define VIO_CMO_MIN_ENT 1562624 | ||
| 46 | |||
| 42 | struct iommu_table; | 47 | struct iommu_table; |
| 43 | 48 | ||
| 44 | /* | 49 | /** |
| 45 | * The vio_dev structure is used to describe virtual I/O devices. | 50 | * vio_dev - This structure is used to describe virtual I/O devices. |
| 51 | * | ||
| 52 | * @desired: set from return of driver's get_desired_dma() function | ||
| 53 | * @entitled: bytes of IO data that has been reserved for this device. | ||
| 54 | * @allocated: bytes of IO data currently in use by the device. | ||
| 55 | * @allocs_failed: number of DMA failures due to insufficient entitlement. | ||
| 46 | */ | 56 | */ |
| 47 | struct vio_dev { | 57 | struct vio_dev { |
| 48 | const char *name; | 58 | const char *name; |
| 49 | const char *type; | 59 | const char *type; |
| 50 | uint32_t unit_address; | 60 | uint32_t unit_address; |
| 51 | unsigned int irq; | 61 | unsigned int irq; |
| 62 | struct { | ||
| 63 | size_t desired; | ||
| 64 | size_t entitled; | ||
| 65 | size_t allocated; | ||
| 66 | atomic_t allocs_failed; | ||
| 67 | } cmo; | ||
| 52 | struct device dev; | 68 | struct device dev; |
| 53 | }; | 69 | }; |
| 54 | 70 | ||
| @@ -56,12 +72,19 @@ struct vio_driver { | |||
| 56 | const struct vio_device_id *id_table; | 72 | const struct vio_device_id *id_table; |
| 57 | int (*probe)(struct vio_dev *dev, const struct vio_device_id *id); | 73 | int (*probe)(struct vio_dev *dev, const struct vio_device_id *id); |
| 58 | int (*remove)(struct vio_dev *dev); | 74 | int (*remove)(struct vio_dev *dev); |
| 75 | /* A driver must have a get_desired_dma() function to | ||
| 76 | * be loaded in a CMO environment if it uses DMA. | ||
| 77 | */ | ||
| 78 | unsigned long (*get_desired_dma)(struct vio_dev *dev); | ||
| 59 | struct device_driver driver; | 79 | struct device_driver driver; |
| 60 | }; | 80 | }; |
| 61 | 81 | ||
| 62 | extern int vio_register_driver(struct vio_driver *drv); | 82 | extern int vio_register_driver(struct vio_driver *drv); |
| 63 | extern void vio_unregister_driver(struct vio_driver *drv); | 83 | extern void vio_unregister_driver(struct vio_driver *drv); |
| 64 | 84 | ||
| 85 | extern int vio_cmo_entitlement_update(size_t); | ||
| 86 | extern void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired); | ||
| 87 | |||
| 65 | extern void __devinit vio_unregister_device(struct vio_dev *dev); | 88 | extern void __devinit vio_unregister_device(struct vio_dev *dev); |
| 66 | 89 | ||
| 67 | struct device_node; | 90 | struct device_node; |
diff --git a/include/asm-s390/Kbuild b/include/asm-s390/Kbuild index bb5e9edb9825..63a23415fba6 100644 --- a/include/asm-s390/Kbuild +++ b/include/asm-s390/Kbuild | |||
| @@ -7,7 +7,6 @@ header-y += tape390.h | |||
| 7 | header-y += ucontext.h | 7 | header-y += ucontext.h |
| 8 | header-y += vtoc.h | 8 | header-y += vtoc.h |
| 9 | header-y += zcrypt.h | 9 | header-y += zcrypt.h |
| 10 | header-y += kvm.h | ||
| 11 | header-y += chsc.h | 10 | header-y += chsc.h |
| 12 | 11 | ||
| 13 | unifdef-y += cmb.h | 12 | unifdef-y += cmb.h |
diff --git a/include/asm-s390/kvm_virtio.h b/include/asm-s390/kvm_virtio.h index 5c871a990c29..146100224def 100644 --- a/include/asm-s390/kvm_virtio.h +++ b/include/asm-s390/kvm_virtio.h | |||
| @@ -50,4 +50,14 @@ struct kvm_vqconfig { | |||
| 50 | #define KVM_S390_VIRTIO_RESET 1 | 50 | #define KVM_S390_VIRTIO_RESET 1 |
| 51 | #define KVM_S390_VIRTIO_SET_STATUS 2 | 51 | #define KVM_S390_VIRTIO_SET_STATUS 2 |
| 52 | 52 | ||
| 53 | #ifdef __KERNEL__ | ||
| 54 | /* early virtio console setup */ | ||
| 55 | #ifdef CONFIG_VIRTIO_CONSOLE | ||
| 56 | extern void s390_virtio_console_init(void); | ||
| 57 | #else | ||
| 58 | static inline void s390_virtio_console_init(void) | ||
| 59 | { | ||
| 60 | } | ||
| 61 | #endif /* CONFIG_VIRTIO_CONSOLE */ | ||
| 62 | #endif /* __KERNEL__ */ | ||
| 53 | #endif | 63 | #endif |
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h index 99bbed99a3b2..91a8f93ad355 100644 --- a/include/asm-s390/thread_info.h +++ b/include/asm-s390/thread_info.h | |||
| @@ -78,10 +78,7 @@ static inline struct thread_info *current_thread_info(void) | |||
| 78 | return (struct thread_info *)((*(unsigned long *) __LC_KERNEL_STACK)-THREAD_SIZE); | 78 | return (struct thread_info *)((*(unsigned long *) __LC_KERNEL_STACK)-THREAD_SIZE); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | /* thread information allocation */ | 81 | #define THREAD_SIZE_ORDER THREAD_ORDER |
| 82 | #define alloc_thread_info(tsk) ((struct thread_info *) \ | ||
| 83 | __get_free_pages(GFP_KERNEL,THREAD_ORDER)) | ||
| 84 | #define free_thread_info(ti) free_pages((unsigned long) (ti),THREAD_ORDER) | ||
| 85 | 82 | ||
| 86 | #endif | 83 | #endif |
| 87 | 84 | ||
diff --git a/include/asm-sh/kvm.h b/include/asm-sh/kvm.h deleted file mode 100644 index 6af51dbab2d0..000000000000 --- a/include/asm-sh/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_SH_H | ||
| 2 | #define __LINUX_KVM_SH_H | ||
| 3 | |||
| 4 | /* sh does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h index 8d6c92b3e770..7d36dc3bee69 100644 --- a/include/asm-sh/ptrace.h +++ b/include/asm-sh/ptrace.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * Copyright (C) 1999, 2000 Niibe Yutaka | 5 | * Copyright (C) 1999, 2000 Niibe Yutaka |
| 6 | * | 6 | * |
| 7 | */ | 7 | */ |
| 8 | #if defined(__SH5__) || defined(CONFIG_SUPERH64) | 8 | #if defined(__SH5__) |
| 9 | struct pt_regs { | 9 | struct pt_regs { |
| 10 | unsigned long long pc; | 10 | unsigned long long pc; |
| 11 | unsigned long long sr; | 11 | unsigned long long sr; |
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index c50e5d35fe84..5131e3907525 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h | |||
| @@ -92,6 +92,8 @@ static inline struct thread_info *current_thread_info(void) | |||
| 92 | return ti; | 92 | return ti; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 96 | |||
| 95 | /* thread information allocation */ | 97 | /* thread information allocation */ |
| 96 | #ifdef CONFIG_DEBUG_STACK_USAGE | 98 | #ifdef CONFIG_DEBUG_STACK_USAGE |
| 97 | #define alloc_thread_info(ti) kzalloc(THREAD_SIZE, GFP_KERNEL) | 99 | #define alloc_thread_info(ti) kzalloc(THREAD_SIZE, GFP_KERNEL) |
diff --git a/include/asm-sparc/kvm.h b/include/asm-sparc/kvm.h deleted file mode 100644 index 2e5478da3819..000000000000 --- a/include/asm-sparc/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_SPARC_H | ||
| 2 | #define __LINUX_KVM_SPARC_H | ||
| 3 | |||
| 4 | /* sparc does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-sparc/thread_info_32.h b/include/asm-sparc/thread_info_32.h index 91b9f5888c85..2cf9db044055 100644 --- a/include/asm-sparc/thread_info_32.h +++ b/include/asm-sparc/thread_info_32.h | |||
| @@ -86,6 +86,8 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
| 86 | #define THREAD_INFO_ORDER 1 | 86 | #define THREAD_INFO_ORDER 1 |
| 87 | #endif | 87 | #endif |
| 88 | 88 | ||
| 89 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 90 | |||
| 89 | BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void) | 91 | BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void) |
| 90 | #define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)() | 92 | #define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)() |
| 91 | 93 | ||
diff --git a/include/asm-sparc/thread_info_64.h b/include/asm-sparc/thread_info_64.h index c6d2e6c7f844..960969d5ad06 100644 --- a/include/asm-sparc/thread_info_64.h +++ b/include/asm-sparc/thread_info_64.h | |||
| @@ -155,6 +155,8 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
| 155 | #define __THREAD_INFO_ORDER 0 | 155 | #define __THREAD_INFO_ORDER 0 |
| 156 | #endif /* PAGE_SHIFT == 13 */ | 156 | #endif /* PAGE_SHIFT == 13 */ |
| 157 | 157 | ||
| 158 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 159 | |||
| 158 | #ifdef CONFIG_DEBUG_STACK_USAGE | 160 | #ifdef CONFIG_DEBUG_STACK_USAGE |
| 159 | #define alloc_thread_info(tsk) \ | 161 | #define alloc_thread_info(tsk) \ |
| 160 | ({ \ | 162 | ({ \ |
diff --git a/include/asm-sparc64/kvm.h b/include/asm-sparc64/kvm.h deleted file mode 100644 index 53564ad86b15..000000000000 --- a/include/asm-sparc64/kvm.h +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | #include <asm-sparc/kvm.h> | ||
diff --git a/include/asm-um/kvm.h b/include/asm-um/kvm.h deleted file mode 100644 index 66aa77094551..000000000000 --- a/include/asm-um/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_UM_H | ||
| 2 | #define __LINUX_KVM_UM_H | ||
| 3 | |||
| 4 | /* um does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h index 356b83e2c22e..e07e72846c7a 100644 --- a/include/asm-um/thread_info.h +++ b/include/asm-um/thread_info.h | |||
| @@ -53,21 +53,7 @@ static inline struct thread_info *current_thread_info(void) | |||
| 53 | return ti; | 53 | return ti; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | #ifdef CONFIG_DEBUG_STACK_USAGE | 56 | #define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER |
| 57 | |||
| 58 | #define alloc_thread_info(tsk) \ | ||
| 59 | ((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \ | ||
| 60 | CONFIG_KERNEL_STACK_ORDER)) | ||
| 61 | #else | ||
| 62 | |||
| 63 | /* thread information allocation */ | ||
| 64 | #define alloc_thread_info(tsk) \ | ||
| 65 | ((struct thread_info *) __get_free_pages(GFP_KERNEL, \ | ||
| 66 | CONFIG_KERNEL_STACK_ORDER)) | ||
| 67 | #endif | ||
| 68 | |||
| 69 | #define free_thread_info(ti) \ | ||
| 70 | free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER) | ||
| 71 | 57 | ||
| 72 | #endif | 58 | #endif |
| 73 | 59 | ||
diff --git a/include/asm-x86/Kbuild b/include/asm-x86/Kbuild index 1e3554596f72..4a8e80cdcfa5 100644 --- a/include/asm-x86/Kbuild +++ b/include/asm-x86/Kbuild | |||
| @@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm | |||
| 3 | header-y += boot.h | 3 | header-y += boot.h |
| 4 | header-y += bootparam.h | 4 | header-y += bootparam.h |
| 5 | header-y += debugreg.h | 5 | header-y += debugreg.h |
| 6 | header-y += kvm.h | ||
| 7 | header-y += ldt.h | 6 | header-y += ldt.h |
| 8 | header-y += msr-index.h | 7 | header-y += msr-index.h |
| 9 | header-y += prctl.h | 8 | header-y += prctl.h |
| @@ -19,7 +18,6 @@ unifdef-y += msr.h | |||
| 19 | unifdef-y += mtrr.h | 18 | unifdef-y += mtrr.h |
| 20 | unifdef-y += posix_types_32.h | 19 | unifdef-y += posix_types_32.h |
| 21 | unifdef-y += posix_types_64.h | 20 | unifdef-y += posix_types_64.h |
| 22 | unifdef-y += ptrace.h | ||
| 23 | unifdef-y += unistd_32.h | 21 | unifdef-y += unistd_32.h |
| 24 | unifdef-y += unistd_64.h | 22 | unifdef-y += unistd_64.h |
| 25 | unifdef-y += vm86.h | 23 | unifdef-y += vm86.h |
diff --git a/include/asm-x86/gpio.h b/include/asm-x86/gpio.h index ff87fca0caf9..116e9147fe66 100644 --- a/include/asm-x86/gpio.h +++ b/include/asm-x86/gpio.h | |||
| @@ -1,6 +1,62 @@ | |||
| 1 | /* | ||
| 2 | * Generic GPIO API implementation for x86. | ||
| 3 | * | ||
| 4 | * Derived from the generic GPIO API for powerpc: | ||
| 5 | * | ||
| 6 | * Copyright (c) 2007-2008 MontaVista Software, Inc. | ||
| 7 | * | ||
| 8 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 1 | #ifndef _ASM_I386_GPIO_H | 16 | #ifndef _ASM_I386_GPIO_H |
| 2 | #define _ASM_I386_GPIO_H | 17 | #define _ASM_I386_GPIO_H |
| 3 | 18 | ||
| 19 | #ifdef CONFIG_X86_RDC321X | ||
| 4 | #include <gpio.h> | 20 | #include <gpio.h> |
| 21 | #else /* CONFIG_X86_RDC321X */ | ||
| 22 | |||
| 23 | #include <asm-generic/gpio.h> | ||
| 24 | |||
| 25 | #ifdef CONFIG_GPIOLIB | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Just call gpiolib. | ||
| 29 | */ | ||
| 30 | static inline int gpio_get_value(unsigned int gpio) | ||
| 31 | { | ||
| 32 | return __gpio_get_value(gpio); | ||
| 33 | } | ||
| 34 | |||
| 35 | static inline void gpio_set_value(unsigned int gpio, int value) | ||
| 36 | { | ||
| 37 | __gpio_set_value(gpio, value); | ||
| 38 | } | ||
| 39 | |||
| 40 | static inline int gpio_cansleep(unsigned int gpio) | ||
| 41 | { | ||
| 42 | return __gpio_cansleep(gpio); | ||
| 43 | } | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Not implemented, yet. | ||
| 47 | */ | ||
| 48 | static inline int gpio_to_irq(unsigned int gpio) | ||
| 49 | { | ||
| 50 | return -ENOSYS; | ||
| 51 | } | ||
| 52 | |||
| 53 | static inline int irq_to_gpio(unsigned int irq) | ||
| 54 | { | ||
| 55 | return -EINVAL; | ||
| 56 | } | ||
| 57 | |||
| 58 | #endif /* CONFIG_GPIOLIB */ | ||
| 59 | |||
| 60 | #endif /* CONFIG_X86_RDC321X */ | ||
| 5 | 61 | ||
| 6 | #endif /* _ASM_I386_GPIO_H */ | 62 | #endif /* _ASM_I386_GPIO_H */ |
diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h index 3f2de1050988..da0a675adf94 100644 --- a/include/asm-x86/thread_info.h +++ b/include/asm-x86/thread_info.h | |||
| @@ -152,6 +152,8 @@ struct thread_info { | |||
| 152 | #define THREAD_FLAGS GFP_KERNEL | 152 | #define THREAD_FLAGS GFP_KERNEL |
| 153 | #endif | 153 | #endif |
| 154 | 154 | ||
| 155 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 156 | |||
| 155 | #define alloc_thread_info(tsk) \ | 157 | #define alloc_thread_info(tsk) \ |
| 156 | ((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER)) | 158 | ((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER)) |
| 157 | 159 | ||
diff --git a/include/asm-xtensa/kvm.h b/include/asm-xtensa/kvm.h deleted file mode 100644 index bda4e331e98c..000000000000 --- a/include/asm-xtensa/kvm.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __LINUX_KVM_XTENSA_H | ||
| 2 | #define __LINUX_KVM_XTENSA_H | ||
| 3 | |||
| 4 | /* xtensa does not support KVM */ | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h index 422c73e26937..089b0db44816 100644 --- a/include/asm-xtensa/ptrace.h +++ b/include/asm-xtensa/ptrace.h | |||
| @@ -73,10 +73,10 @@ | |||
| 73 | #define PTRACE_GETXTREGS 18 | 73 | #define PTRACE_GETXTREGS 18 |
| 74 | #define PTRACE_SETXTREGS 19 | 74 | #define PTRACE_SETXTREGS 19 |
| 75 | 75 | ||
| 76 | #ifndef __ASSEMBLY__ | ||
| 77 | |||
| 78 | #ifdef __KERNEL__ | 76 | #ifdef __KERNEL__ |
| 79 | 77 | ||
| 78 | #ifndef __ASSEMBLY__ | ||
| 79 | |||
| 80 | /* | 80 | /* |
| 81 | * This struct defines the way the registers are stored on the | 81 | * This struct defines the way the registers are stored on the |
| 82 | * kernel stack during a system call or other kernel entry. | 82 | * kernel stack during a system call or other kernel entry. |
| @@ -122,14 +122,14 @@ extern void show_regs(struct pt_regs *); | |||
| 122 | # ifndef CONFIG_SMP | 122 | # ifndef CONFIG_SMP |
| 123 | # define profile_pc(regs) instruction_pointer(regs) | 123 | # define profile_pc(regs) instruction_pointer(regs) |
| 124 | # endif | 124 | # endif |
| 125 | #endif /* __KERNEL__ */ | ||
| 126 | 125 | ||
| 127 | #else /* __ASSEMBLY__ */ | 126 | #else /* __ASSEMBLY__ */ |
| 128 | 127 | ||
| 129 | #ifdef __KERNEL__ | ||
| 130 | # include <asm/asm-offsets.h> | 128 | # include <asm/asm-offsets.h> |
| 131 | #define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE) | 129 | #define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE) |
| 132 | #endif | ||
| 133 | 130 | ||
| 134 | #endif /* !__ASSEMBLY__ */ | 131 | #endif /* !__ASSEMBLY__ */ |
| 132 | |||
| 133 | #endif /* __KERNEL__ */ | ||
| 134 | |||
| 135 | #endif /* _XTENSA_PTRACE_H */ | 135 | #endif /* _XTENSA_PTRACE_H */ |
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h index a2c640682ed9..7e4131dd546c 100644 --- a/include/asm-xtensa/thread_info.h +++ b/include/asm-xtensa/thread_info.h | |||
| @@ -111,10 +111,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 111 | return ti; | 111 | return ti; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | /* thread information allocation */ | ||
| 115 | #define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) | ||
| 116 | #define free_thread_info(ti) free_pages((unsigned long) (ti), 1) | ||
| 117 | |||
| 118 | #else /* !__ASSEMBLY__ */ | 114 | #else /* !__ASSEMBLY__ */ |
| 119 | 115 | ||
| 120 | /* how to get the thread information struct from ASM */ | 116 | /* how to get the thread information struct from ASM */ |
| @@ -160,6 +156,7 @@ static inline struct thread_info *current_thread_info(void) | |||
| 160 | #define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */ | 156 | #define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */ |
| 161 | 157 | ||
| 162 | #define THREAD_SIZE 8192 //(2*PAGE_SIZE) | 158 | #define THREAD_SIZE 8192 //(2*PAGE_SIZE) |
| 159 | #define THREAD_SIZE_ORDER 1 | ||
| 163 | 160 | ||
| 164 | #endif /* __KERNEL__ */ | 161 | #endif /* __KERNEL__ */ |
| 165 | #endif /* _XTENSA_THREAD_INFO */ | 162 | #endif /* _XTENSA_THREAD_INFO */ |
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 71d70d1fbce2..4c4142c5aa6e 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
| @@ -189,7 +189,6 @@ unifdef-y += connector.h | |||
| 189 | unifdef-y += cuda.h | 189 | unifdef-y += cuda.h |
| 190 | unifdef-y += cyclades.h | 190 | unifdef-y += cyclades.h |
| 191 | unifdef-y += dccp.h | 191 | unifdef-y += dccp.h |
| 192 | unifdef-y += dirent.h | ||
| 193 | unifdef-y += dlm.h | 192 | unifdef-y += dlm.h |
| 194 | unifdef-y += dlm_plock.h | 193 | unifdef-y += dlm_plock.h |
| 195 | unifdef-y += edd.h | 194 | unifdef-y += edd.h |
| @@ -256,7 +255,9 @@ unifdef-y += kd.h | |||
| 256 | unifdef-y += kernelcapi.h | 255 | unifdef-y += kernelcapi.h |
| 257 | unifdef-y += kernel.h | 256 | unifdef-y += kernel.h |
| 258 | unifdef-y += keyboard.h | 257 | unifdef-y += keyboard.h |
| 258 | ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),) | ||
| 259 | unifdef-y += kvm.h | 259 | unifdef-y += kvm.h |
| 260 | endif | ||
| 260 | unifdef-y += llc.h | 261 | unifdef-y += llc.h |
| 261 | unifdef-y += loop.h | 262 | unifdef-y += loop.h |
| 262 | unifdef-y += lp.h | 263 | unifdef-y += lp.h |
diff --git a/include/linux/acct.h b/include/linux/acct.h index e8cae54e8d88..882dc7248766 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h | |||
| @@ -120,17 +120,20 @@ struct acct_v3 | |||
| 120 | struct vfsmount; | 120 | struct vfsmount; |
| 121 | struct super_block; | 121 | struct super_block; |
| 122 | struct pacct_struct; | 122 | struct pacct_struct; |
| 123 | struct pid_namespace; | ||
| 123 | extern void acct_auto_close_mnt(struct vfsmount *m); | 124 | extern void acct_auto_close_mnt(struct vfsmount *m); |
| 124 | extern void acct_auto_close(struct super_block *sb); | 125 | extern void acct_auto_close(struct super_block *sb); |
| 125 | extern void acct_init_pacct(struct pacct_struct *pacct); | 126 | extern void acct_init_pacct(struct pacct_struct *pacct); |
| 126 | extern void acct_collect(long exitcode, int group_dead); | 127 | extern void acct_collect(long exitcode, int group_dead); |
| 127 | extern void acct_process(void); | 128 | extern void acct_process(void); |
| 129 | extern void acct_exit_ns(struct pid_namespace *); | ||
| 128 | #else | 130 | #else |
| 129 | #define acct_auto_close_mnt(x) do { } while (0) | 131 | #define acct_auto_close_mnt(x) do { } while (0) |
| 130 | #define acct_auto_close(x) do { } while (0) | 132 | #define acct_auto_close(x) do { } while (0) |
| 131 | #define acct_init_pacct(x) do { } while (0) | 133 | #define acct_init_pacct(x) do { } while (0) |
| 132 | #define acct_collect(x,y) do { } while (0) | 134 | #define acct_collect(x,y) do { } while (0) |
| 133 | #define acct_process() do { } while (0) | 135 | #define acct_process() do { } while (0) |
| 136 | #define acct_exit_ns(ns) do { } while (0) | ||
| 134 | #endif | 137 | #endif |
| 135 | 138 | ||
| 136 | /* | 139 | /* |
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h index 0da17d14fd13..d7afa9dd6635 100644 --- a/include/linux/auxvec.h +++ b/include/linux/auxvec.h | |||
| @@ -26,9 +26,13 @@ | |||
| 26 | 26 | ||
| 27 | #define AT_SECURE 23 /* secure mode boolean */ | 27 | #define AT_SECURE 23 /* secure mode boolean */ |
| 28 | 28 | ||
| 29 | #define AT_BASE_PLATFORM 24 /* string identifying real platform, may | ||
| 30 | * differ from AT_PLATFORM. */ | ||
| 31 | |||
| 29 | #define AT_EXECFN 31 /* filename of program */ | 32 | #define AT_EXECFN 31 /* filename of program */ |
| 33 | |||
| 30 | #ifdef __KERNEL__ | 34 | #ifdef __KERNEL__ |
| 31 | #define AT_VECTOR_SIZE_BASE 17 /* NEW_AUX_ENT entries in auxiliary table */ | 35 | #define AT_VECTOR_SIZE_BASE 18 /* NEW_AUX_ENT entries in auxiliary table */ |
| 32 | /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */ | 36 | /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */ |
| 33 | #endif | 37 | #endif |
| 34 | 38 | ||
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 4ddf2922fc8d..652470b687c9 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h | |||
| @@ -103,17 +103,16 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat, | |||
| 103 | __alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) | 103 | __alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) |
| 104 | #define alloc_bootmem_low_pages(x) \ | 104 | #define alloc_bootmem_low_pages(x) \ |
| 105 | __alloc_bootmem_low(x, PAGE_SIZE, 0) | 105 | __alloc_bootmem_low(x, PAGE_SIZE, 0) |
| 106 | #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ | ||
| 107 | |||
| 108 | extern int reserve_bootmem_generic(unsigned long addr, unsigned long size, | ||
| 109 | int flags); | ||
| 110 | |||
| 111 | #define alloc_bootmem_node(pgdat, x) \ | 106 | #define alloc_bootmem_node(pgdat, x) \ |
| 112 | __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) | 107 | __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) |
| 113 | #define alloc_bootmem_pages_node(pgdat, x) \ | 108 | #define alloc_bootmem_pages_node(pgdat, x) \ |
| 114 | __alloc_bootmem_node(pgdat, x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) | 109 | __alloc_bootmem_node(pgdat, x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) |
| 115 | #define alloc_bootmem_low_pages_node(pgdat, x) \ | 110 | #define alloc_bootmem_low_pages_node(pgdat, x) \ |
| 116 | __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0) | 111 | __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0) |
| 112 | #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ | ||
| 113 | |||
| 114 | extern int reserve_bootmem_generic(unsigned long addr, unsigned long size, | ||
| 115 | int flags); | ||
| 117 | 116 | ||
| 118 | extern void *alloc_bootmem_section(unsigned long size, | 117 | extern void *alloc_bootmem_section(unsigned long size, |
| 119 | unsigned long section_nr); | 118 | unsigned long section_nr); |
diff --git a/include/linux/byteorder/big_endian.h b/include/linux/byteorder/big_endian.h index 961ed4b48d8e..44f95b92393b 100644 --- a/include/linux/byteorder/big_endian.h +++ b/include/linux/byteorder/big_endian.h | |||
| @@ -94,12 +94,12 @@ static inline __u16 __be16_to_cpup(const __be16 *p) | |||
| 94 | #define __le32_to_cpus(x) __swab32s((x)) | 94 | #define __le32_to_cpus(x) __swab32s((x)) |
| 95 | #define __cpu_to_le16s(x) __swab16s((x)) | 95 | #define __cpu_to_le16s(x) __swab16s((x)) |
| 96 | #define __le16_to_cpus(x) __swab16s((x)) | 96 | #define __le16_to_cpus(x) __swab16s((x)) |
| 97 | #define __cpu_to_be64s(x) do {} while (0) | 97 | #define __cpu_to_be64s(x) do { (void)(x); } while (0) |
| 98 | #define __be64_to_cpus(x) do {} while (0) | 98 | #define __be64_to_cpus(x) do { (void)(x); } while (0) |
| 99 | #define __cpu_to_be32s(x) do {} while (0) | 99 | #define __cpu_to_be32s(x) do { (void)(x); } while (0) |
| 100 | #define __be32_to_cpus(x) do {} while (0) | 100 | #define __be32_to_cpus(x) do { (void)(x); } while (0) |
| 101 | #define __cpu_to_be16s(x) do {} while (0) | 101 | #define __cpu_to_be16s(x) do { (void)(x); } while (0) |
| 102 | #define __be16_to_cpus(x) do {} while (0) | 102 | #define __be16_to_cpus(x) do { (void)(x); } while (0) |
| 103 | 103 | ||
| 104 | #ifdef __KERNEL__ | 104 | #ifdef __KERNEL__ |
| 105 | #include <linux/byteorder/generic.h> | 105 | #include <linux/byteorder/generic.h> |
diff --git a/include/linux/byteorder/little_endian.h b/include/linux/byteorder/little_endian.h index 05dc7c35b3b2..4cc170a31762 100644 --- a/include/linux/byteorder/little_endian.h +++ b/include/linux/byteorder/little_endian.h | |||
| @@ -88,12 +88,12 @@ static inline __u16 __be16_to_cpup(const __be16 *p) | |||
| 88 | { | 88 | { |
| 89 | return __swab16p((__u16 *)p); | 89 | return __swab16p((__u16 *)p); |
| 90 | } | 90 | } |
| 91 | #define __cpu_to_le64s(x) do {} while (0) | 91 | #define __cpu_to_le64s(x) do { (void)(x); } while (0) |
| 92 | #define __le64_to_cpus(x) do {} while (0) | 92 | #define __le64_to_cpus(x) do { (void)(x); } while (0) |
| 93 | #define __cpu_to_le32s(x) do {} while (0) | 93 | #define __cpu_to_le32s(x) do { (void)(x); } while (0) |
| 94 | #define __le32_to_cpus(x) do {} while (0) | 94 | #define __le32_to_cpus(x) do { (void)(x); } while (0) |
| 95 | #define __cpu_to_le16s(x) do {} while (0) | 95 | #define __cpu_to_le16s(x) do { (void)(x); } while (0) |
| 96 | #define __le16_to_cpus(x) do {} while (0) | 96 | #define __le16_to_cpus(x) do { (void)(x); } while (0) |
| 97 | #define __cpu_to_be64s(x) __swab64s((x)) | 97 | #define __cpu_to_be64s(x) __swab64s((x)) |
| 98 | #define __be64_to_cpus(x) __swab64s((x)) | 98 | #define __be64_to_cpus(x) __swab64s((x)) |
| 99 | #define __cpu_to_be32s(x) __swab32s((x)) | 99 | #define __cpu_to_be32s(x) __swab32s((x)) |
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index e155aa78d859..c98dd7cb7076 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
| @@ -21,11 +21,13 @@ | |||
| 21 | struct cgroupfs_root; | 21 | struct cgroupfs_root; |
| 22 | struct cgroup_subsys; | 22 | struct cgroup_subsys; |
| 23 | struct inode; | 23 | struct inode; |
| 24 | struct cgroup; | ||
| 24 | 25 | ||
| 25 | extern int cgroup_init_early(void); | 26 | extern int cgroup_init_early(void); |
| 26 | extern int cgroup_init(void); | 27 | extern int cgroup_init(void); |
| 27 | extern void cgroup_init_smp(void); | 28 | extern void cgroup_init_smp(void); |
| 28 | extern void cgroup_lock(void); | 29 | extern void cgroup_lock(void); |
| 30 | extern bool cgroup_lock_live_group(struct cgroup *cgrp); | ||
| 29 | extern void cgroup_unlock(void); | 31 | extern void cgroup_unlock(void); |
| 30 | extern void cgroup_fork(struct task_struct *p); | 32 | extern void cgroup_fork(struct task_struct *p); |
| 31 | extern void cgroup_fork_callbacks(struct task_struct *p); | 33 | extern void cgroup_fork_callbacks(struct task_struct *p); |
| @@ -205,50 +207,64 @@ struct cftype { | |||
| 205 | * subsystem, followed by a period */ | 207 | * subsystem, followed by a period */ |
| 206 | char name[MAX_CFTYPE_NAME]; | 208 | char name[MAX_CFTYPE_NAME]; |
| 207 | int private; | 209 | int private; |
| 208 | int (*open) (struct inode *inode, struct file *file); | 210 | |
| 209 | ssize_t (*read) (struct cgroup *cgrp, struct cftype *cft, | 211 | /* |
| 210 | struct file *file, | 212 | * If non-zero, defines the maximum length of string that can |
| 211 | char __user *buf, size_t nbytes, loff_t *ppos); | 213 | * be passed to write_string; defaults to 64 |
| 214 | */ | ||
| 215 | size_t max_write_len; | ||
| 216 | |||
| 217 | int (*open)(struct inode *inode, struct file *file); | ||
| 218 | ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft, | ||
| 219 | struct file *file, | ||
| 220 | char __user *buf, size_t nbytes, loff_t *ppos); | ||
| 212 | /* | 221 | /* |
| 213 | * read_u64() is a shortcut for the common case of returning a | 222 | * read_u64() is a shortcut for the common case of returning a |
| 214 | * single integer. Use it in place of read() | 223 | * single integer. Use it in place of read() |
| 215 | */ | 224 | */ |
| 216 | u64 (*read_u64) (struct cgroup *cgrp, struct cftype *cft); | 225 | u64 (*read_u64)(struct cgroup *cgrp, struct cftype *cft); |
| 217 | /* | 226 | /* |
| 218 | * read_s64() is a signed version of read_u64() | 227 | * read_s64() is a signed version of read_u64() |
| 219 | */ | 228 | */ |
| 220 | s64 (*read_s64) (struct cgroup *cgrp, struct cftype *cft); | 229 | s64 (*read_s64)(struct cgroup *cgrp, struct cftype *cft); |
| 221 | /* | 230 | /* |
| 222 | * read_map() is used for defining a map of key/value | 231 | * read_map() is used for defining a map of key/value |
| 223 | * pairs. It should call cb->fill(cb, key, value) for each | 232 | * pairs. It should call cb->fill(cb, key, value) for each |
| 224 | * entry. The key/value pairs (and their ordering) should not | 233 | * entry. The key/value pairs (and their ordering) should not |
| 225 | * change between reboots. | 234 | * change between reboots. |
| 226 | */ | 235 | */ |
| 227 | int (*read_map) (struct cgroup *cont, struct cftype *cft, | 236 | int (*read_map)(struct cgroup *cont, struct cftype *cft, |
| 228 | struct cgroup_map_cb *cb); | 237 | struct cgroup_map_cb *cb); |
| 229 | /* | 238 | /* |
| 230 | * read_seq_string() is used for outputting a simple sequence | 239 | * read_seq_string() is used for outputting a simple sequence |
| 231 | * using seqfile. | 240 | * using seqfile. |
| 232 | */ | 241 | */ |
| 233 | int (*read_seq_string) (struct cgroup *cont, struct cftype *cft, | 242 | int (*read_seq_string)(struct cgroup *cont, struct cftype *cft, |
| 234 | struct seq_file *m); | 243 | struct seq_file *m); |
| 235 | 244 | ||
| 236 | ssize_t (*write) (struct cgroup *cgrp, struct cftype *cft, | 245 | ssize_t (*write)(struct cgroup *cgrp, struct cftype *cft, |
| 237 | struct file *file, | 246 | struct file *file, |
| 238 | const char __user *buf, size_t nbytes, loff_t *ppos); | 247 | const char __user *buf, size_t nbytes, loff_t *ppos); |
| 239 | 248 | ||
| 240 | /* | 249 | /* |
| 241 | * write_u64() is a shortcut for the common case of accepting | 250 | * write_u64() is a shortcut for the common case of accepting |
| 242 | * a single integer (as parsed by simple_strtoull) from | 251 | * a single integer (as parsed by simple_strtoull) from |
| 243 | * userspace. Use in place of write(); return 0 or error. | 252 | * userspace. Use in place of write(); return 0 or error. |
| 244 | */ | 253 | */ |
| 245 | int (*write_u64) (struct cgroup *cgrp, struct cftype *cft, u64 val); | 254 | int (*write_u64)(struct cgroup *cgrp, struct cftype *cft, u64 val); |
| 246 | /* | 255 | /* |
| 247 | * write_s64() is a signed version of write_u64() | 256 | * write_s64() is a signed version of write_u64() |
| 248 | */ | 257 | */ |
| 249 | int (*write_s64) (struct cgroup *cgrp, struct cftype *cft, s64 val); | 258 | int (*write_s64)(struct cgroup *cgrp, struct cftype *cft, s64 val); |
| 250 | 259 | ||
| 251 | /* | 260 | /* |
| 261 | * write_string() is passed a nul-terminated kernelspace | ||
| 262 | * buffer of maximum length determined by max_write_len. | ||
| 263 | * Returns 0 or -ve error code. | ||
| 264 | */ | ||
| 265 | int (*write_string)(struct cgroup *cgrp, struct cftype *cft, | ||
| 266 | const char *buffer); | ||
| 267 | /* | ||
| 252 | * trigger() callback can be used to get some kick from the | 268 | * trigger() callback can be used to get some kick from the |
| 253 | * userspace, when the actual string written is not important | 269 | * userspace, when the actual string written is not important |
| 254 | * at all. The private field can be used to determine the | 270 | * at all. The private field can be used to determine the |
| @@ -256,7 +272,7 @@ struct cftype { | |||
| 256 | */ | 272 | */ |
| 257 | int (*trigger)(struct cgroup *cgrp, unsigned int event); | 273 | int (*trigger)(struct cgroup *cgrp, unsigned int event); |
| 258 | 274 | ||
| 259 | int (*release) (struct inode *inode, struct file *file); | 275 | int (*release)(struct inode *inode, struct file *file); |
| 260 | }; | 276 | }; |
| 261 | 277 | ||
| 262 | struct cgroup_scanner { | 278 | struct cgroup_scanner { |
| @@ -348,7 +364,8 @@ static inline struct cgroup* task_cgroup(struct task_struct *task, | |||
| 348 | return task_subsys_state(task, subsys_id)->cgroup; | 364 | return task_subsys_state(task, subsys_id)->cgroup; |
| 349 | } | 365 | } |
| 350 | 366 | ||
| 351 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss); | 367 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss, |
| 368 | char *nodename); | ||
| 352 | 369 | ||
| 353 | /* A cgroup_iter should be treated as an opaque object */ | 370 | /* A cgroup_iter should be treated as an opaque object */ |
| 354 | struct cgroup_iter { | 371 | struct cgroup_iter { |
diff --git a/include/linux/coda.h b/include/linux/coda.h index b5cf0780c51a..96c87693800b 100644 --- a/include/linux/coda.h +++ b/include/linux/coda.h | |||
| @@ -199,28 +199,6 @@ typedef u_int32_t vuid_t; | |||
| 199 | typedef u_int32_t vgid_t; | 199 | typedef u_int32_t vgid_t; |
| 200 | #endif /*_VUID_T_ */ | 200 | #endif /*_VUID_T_ */ |
| 201 | 201 | ||
| 202 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 203 | struct CodaFid { | ||
| 204 | u_int32_t opaque[3]; | ||
| 205 | }; | ||
| 206 | |||
| 207 | static __inline__ ino_t coda_f2i(struct CodaFid *fid) | ||
| 208 | { | ||
| 209 | if ( ! fid ) | ||
| 210 | return 0; | ||
| 211 | if (fid->opaque[1] == 0xfffffffe || fid->opaque[1] == 0xffffffff) | ||
| 212 | return ((fid->opaque[0] << 20) | (fid->opaque[2] & 0xfffff)); | ||
| 213 | else | ||
| 214 | return (fid->opaque[2] + (fid->opaque[1]<<10) + (fid->opaque[0]<<20)); | ||
| 215 | } | ||
| 216 | |||
| 217 | struct coda_cred { | ||
| 218 | vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/ | ||
| 219 | vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */ | ||
| 220 | }; | ||
| 221 | |||
| 222 | #else /* not defined(CONFIG_CODA_FS_OLD_API) */ | ||
| 223 | |||
| 224 | struct CodaFid { | 202 | struct CodaFid { |
| 225 | u_int32_t opaque[4]; | 203 | u_int32_t opaque[4]; |
| 226 | }; | 204 | }; |
| @@ -228,8 +206,6 @@ struct CodaFid { | |||
| 228 | #define coda_f2i(fid)\ | 206 | #define coda_f2i(fid)\ |
| 229 | (fid ? (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]) : 0) | 207 | (fid ? (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]) : 0) |
| 230 | 208 | ||
| 231 | #endif | ||
| 232 | |||
| 233 | #ifndef _VENUS_VATTR_T_ | 209 | #ifndef _VENUS_VATTR_T_ |
| 234 | #define _VENUS_VATTR_T_ | 210 | #define _VENUS_VATTR_T_ |
| 235 | /* | 211 | /* |
| @@ -313,15 +289,7 @@ struct coda_statfs { | |||
| 313 | 289 | ||
| 314 | #define CIOC_KERNEL_VERSION _IOWR('c', 10, size_t) | 290 | #define CIOC_KERNEL_VERSION _IOWR('c', 10, size_t) |
| 315 | 291 | ||
| 316 | #if 0 | ||
| 317 | #define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */ | ||
| 318 | #define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */ | ||
| 319 | #endif | ||
| 320 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 321 | #define CODA_KERNEL_VERSION 2 /* venus_lookup got an extra parameter */ | ||
| 322 | #else | ||
| 323 | #define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */ | 292 | #define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */ |
| 324 | #endif | ||
| 325 | 293 | ||
| 326 | /* | 294 | /* |
| 327 | * Venus <-> Coda RPC arguments | 295 | * Venus <-> Coda RPC arguments |
| @@ -329,16 +297,9 @@ struct coda_statfs { | |||
| 329 | struct coda_in_hdr { | 297 | struct coda_in_hdr { |
| 330 | u_int32_t opcode; | 298 | u_int32_t opcode; |
| 331 | u_int32_t unique; /* Keep multiple outstanding msgs distinct */ | 299 | u_int32_t unique; /* Keep multiple outstanding msgs distinct */ |
| 332 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 333 | u_int16_t pid; /* Common to all */ | ||
| 334 | u_int16_t pgid; /* Common to all */ | ||
| 335 | u_int16_t sid; /* Common to all */ | ||
| 336 | struct coda_cred cred; /* Common to all */ | ||
| 337 | #else | ||
| 338 | pid_t pid; | 300 | pid_t pid; |
| 339 | pid_t pgid; | 301 | pid_t pgid; |
| 340 | vuid_t uid; | 302 | vuid_t uid; |
| 341 | #endif | ||
| 342 | }; | 303 | }; |
| 343 | 304 | ||
| 344 | /* Really important that opcode and unique are 1st two fields! */ | 305 | /* Really important that opcode and unique are 1st two fields! */ |
| @@ -613,11 +574,7 @@ struct coda_vget_out { | |||
| 613 | /* CODA_PURGEUSER is a venus->kernel call */ | 574 | /* CODA_PURGEUSER is a venus->kernel call */ |
| 614 | struct coda_purgeuser_out { | 575 | struct coda_purgeuser_out { |
| 615 | struct coda_out_hdr oh; | 576 | struct coda_out_hdr oh; |
| 616 | #ifdef CONFIG_CODA_FS_OLD_API | ||
| 617 | struct coda_cred cred; | ||
| 618 | #else | ||
| 619 | vuid_t uid; | 577 | vuid_t uid; |
| 620 | #endif | ||
| 621 | }; | 578 | }; |
| 622 | 579 | ||
| 623 | /* coda_zapfile: */ | 580 | /* coda_zapfile: */ |
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h index e2bf7e5db39a..c4811da1338b 100644 --- a/include/linux/consolemap.h +++ b/include/linux/consolemap.h | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | * | 3 | * |
| 4 | * Interface between console.c, selection.c and consolemap.c | 4 | * Interface between console.c, selection.c and consolemap.c |
| 5 | */ | 5 | */ |
| 6 | #ifndef __LINUX_CONSOLEMAP_H__ | ||
| 7 | #define __LINUX_CONSOLEMAP_H__ | ||
| 8 | |||
| 6 | #define LAT1_MAP 0 | 9 | #define LAT1_MAP 0 |
| 7 | #define GRAF_MAP 1 | 10 | #define GRAF_MAP 1 |
| 8 | #define IBMPC_MAP 2 | 11 | #define IBMPC_MAP 2 |
| @@ -10,6 +13,7 @@ | |||
| 10 | 13 | ||
| 11 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 12 | 15 | ||
| 16 | #ifdef CONFIG_CONSOLE_TRANSLATIONS | ||
| 13 | struct vc_data; | 17 | struct vc_data; |
| 14 | 18 | ||
| 15 | extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode); | 19 | extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode); |
| @@ -18,3 +22,13 @@ extern int conv_uni_to_pc(struct vc_data *conp, long ucs); | |||
| 18 | extern u32 conv_8bit_to_uni(unsigned char c); | 22 | extern u32 conv_8bit_to_uni(unsigned char c); |
| 19 | extern int conv_uni_to_8bit(u32 uni); | 23 | extern int conv_uni_to_8bit(u32 uni); |
| 20 | void console_map_init(void); | 24 | void console_map_init(void); |
| 25 | #else | ||
| 26 | #define inverse_translate(conp, glyph, uni) ((uint16_t)glyph) | ||
| 27 | #define set_translate(m, vc) ((unsigned short *)NULL) | ||
| 28 | #define conv_uni_to_pc(conp, ucs) ((int) (ucs > 0xff ? -1: ucs)) | ||
| 29 | #define conv_8bit_to_uni(c) ((uint32_t)(c)) | ||
| 30 | #define conv_uni_to_8bit(c) ((int) ((c) & 0xff)) | ||
| 31 | #define console_map_init(c) do { ; } while (0) | ||
| 32 | #endif /* CONFIG_CONSOLE_TRANSLATIONS */ | ||
| 33 | |||
| 34 | #endif /* __LINUX_CONSOLEMAP_H__ */ | ||
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 7464ba3b4333..d7faf8808497 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
| @@ -69,10 +69,11 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb) | |||
| 69 | #endif | 69 | #endif |
| 70 | 70 | ||
| 71 | int cpu_up(unsigned int cpu); | 71 | int cpu_up(unsigned int cpu); |
| 72 | |||
| 73 | extern void cpu_hotplug_init(void); | 72 | extern void cpu_hotplug_init(void); |
| 73 | extern void cpu_maps_update_begin(void); | ||
| 74 | extern void cpu_maps_update_done(void); | ||
| 74 | 75 | ||
| 75 | #else | 76 | #else /* CONFIG_SMP */ |
| 76 | 77 | ||
| 77 | static inline int register_cpu_notifier(struct notifier_block *nb) | 78 | static inline int register_cpu_notifier(struct notifier_block *nb) |
| 78 | { | 79 | { |
| @@ -87,10 +88,16 @@ static inline void cpu_hotplug_init(void) | |||
| 87 | { | 88 | { |
| 88 | } | 89 | } |
| 89 | 90 | ||
| 91 | static inline void cpu_maps_update_begin(void) | ||
| 92 | { | ||
| 93 | } | ||
| 94 | |||
| 95 | static inline void cpu_maps_update_done(void) | ||
| 96 | { | ||
| 97 | } | ||
| 98 | |||
| 90 | #endif /* CONFIG_SMP */ | 99 | #endif /* CONFIG_SMP */ |
| 91 | extern struct sysdev_class cpu_sysdev_class; | 100 | extern struct sysdev_class cpu_sysdev_class; |
| 92 | extern void cpu_maps_update_begin(void); | ||
| 93 | extern void cpu_maps_update_done(void); | ||
| 94 | 101 | ||
| 95 | #ifdef CONFIG_HOTPLUG_CPU | 102 | #ifdef CONFIG_HOTPLUG_CPU |
| 96 | /* Stop CPUs going up and down. */ | 103 | /* Stop CPUs going up and down. */ |
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index 22c7ac5cd80c..6cd39a927e1f 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h | |||
| @@ -22,5 +22,13 @@ extern struct proc_dir_entry *proc_vmcore; | |||
| 22 | 22 | ||
| 23 | #define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x)) | 23 | #define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x)) |
| 24 | 24 | ||
| 25 | static inline int is_kdump_kernel(void) | ||
| 26 | { | ||
| 27 | return (elfcorehdr_addr != ELFCORE_ADDR_MAX) ? 1 : 0; | ||
| 28 | } | ||
| 29 | #else /* !CONFIG_CRASH_DUMP */ | ||
| 30 | static inline int is_kdump_kernel(void) { return 0; } | ||
| 25 | #endif /* CONFIG_CRASH_DUMP */ | 31 | #endif /* CONFIG_CRASH_DUMP */ |
| 32 | |||
| 33 | extern unsigned long saved_max_pfn; | ||
| 26 | #endif /* LINUX_CRASHDUMP_H */ | 34 | #endif /* LINUX_CRASHDUMP_H */ |
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h index ab94bc083558..f352f06fa063 100644 --- a/include/linux/delayacct.h +++ b/include/linux/delayacct.h | |||
| @@ -39,6 +39,8 @@ extern void __delayacct_blkio_start(void); | |||
| 39 | extern void __delayacct_blkio_end(void); | 39 | extern void __delayacct_blkio_end(void); |
| 40 | extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *); | 40 | extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *); |
| 41 | extern __u64 __delayacct_blkio_ticks(struct task_struct *); | 41 | extern __u64 __delayacct_blkio_ticks(struct task_struct *); |
| 42 | extern void __delayacct_freepages_start(void); | ||
| 43 | extern void __delayacct_freepages_end(void); | ||
| 42 | 44 | ||
| 43 | static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) | 45 | static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) |
| 44 | { | 46 | { |
| @@ -107,6 +109,18 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) | |||
| 107 | return 0; | 109 | return 0; |
| 108 | } | 110 | } |
| 109 | 111 | ||
| 112 | static inline void delayacct_freepages_start(void) | ||
| 113 | { | ||
| 114 | if (current->delays) | ||
| 115 | __delayacct_freepages_start(); | ||
| 116 | } | ||
| 117 | |||
| 118 | static inline void delayacct_freepages_end(void) | ||
| 119 | { | ||
| 120 | if (current->delays) | ||
| 121 | __delayacct_freepages_end(); | ||
| 122 | } | ||
| 123 | |||
| 110 | #else | 124 | #else |
| 111 | static inline void delayacct_set_flag(int flag) | 125 | static inline void delayacct_set_flag(int flag) |
| 112 | {} | 126 | {} |
| @@ -129,6 +143,11 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) | |||
| 129 | { return 0; } | 143 | { return 0; } |
| 130 | static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) | 144 | static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) |
| 131 | { return 0; } | 145 | { return 0; } |
| 146 | static inline void delayacct_freepages_start(void) | ||
| 147 | {} | ||
| 148 | static inline void delayacct_freepages_end(void) | ||
| 149 | {} | ||
| 150 | |||
| 132 | #endif /* CONFIG_TASK_DELAY_ACCT */ | 151 | #endif /* CONFIG_TASK_DELAY_ACCT */ |
| 133 | 152 | ||
| 134 | #endif | 153 | #endif |
diff --git a/include/linux/dirent.h b/include/linux/dirent.h index 5d6023b87800..f072fb8d10a3 100644 --- a/include/linux/dirent.h +++ b/include/linux/dirent.h | |||
| @@ -1,23 +1,6 @@ | |||
| 1 | #ifndef _LINUX_DIRENT_H | 1 | #ifndef _LINUX_DIRENT_H |
| 2 | #define _LINUX_DIRENT_H | 2 | #define _LINUX_DIRENT_H |
| 3 | 3 | ||
| 4 | struct dirent { | ||
| 5 | long d_ino; | ||
| 6 | __kernel_off_t d_off; | ||
| 7 | unsigned short d_reclen; | ||
| 8 | char d_name[256]; /* We must not include limits.h! */ | ||
| 9 | }; | ||
| 10 | |||
| 11 | struct dirent64 { | ||
| 12 | __u64 d_ino; | ||
| 13 | __s64 d_off; | ||
| 14 | unsigned short d_reclen; | ||
| 15 | unsigned char d_type; | ||
| 16 | char d_name[256]; | ||
| 17 | }; | ||
| 18 | |||
| 19 | #ifdef __KERNEL__ | ||
| 20 | |||
| 21 | struct linux_dirent64 { | 4 | struct linux_dirent64 { |
| 22 | u64 d_ino; | 5 | u64 d_ino; |
| 23 | s64 d_off; | 6 | s64 d_off; |
| @@ -26,7 +9,4 @@ struct linux_dirent64 { | |||
| 26 | char d_name[0]; | 9 | char d_name[0]; |
| 27 | }; | 10 | }; |
| 28 | 11 | ||
| 29 | #endif /* __KERNEL__ */ | ||
| 30 | |||
| 31 | |||
| 32 | #endif | 12 | #endif |
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index 84cec2aa9f1e..2efe7b863cff 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h | |||
| @@ -284,8 +284,8 @@ struct ext2_inode { | |||
| 284 | 284 | ||
| 285 | #ifdef __hurd__ | 285 | #ifdef __hurd__ |
| 286 | #define i_translator osd1.hurd1.h_i_translator | 286 | #define i_translator osd1.hurd1.h_i_translator |
| 287 | #define i_frag osd2.hurd2.h_i_frag; | 287 | #define i_frag osd2.hurd2.h_i_frag |
| 288 | #define i_fsize osd2.hurd2.h_i_fsize; | 288 | #define i_fsize osd2.hurd2.h_i_fsize |
| 289 | #define i_uid_high osd2.hurd2.h_i_uid_high | 289 | #define i_uid_high osd2.hurd2.h_i_uid_high |
| 290 | #define i_gid_high osd2.hurd2.h_i_gid_high | 290 | #define i_gid_high osd2.hurd2.h_i_gid_high |
| 291 | #define i_author osd2.hurd2.h_i_author | 291 | #define i_author osd2.hurd2.h_i_author |
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 36c540396377..80171ee89a22 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h | |||
| @@ -832,6 +832,7 @@ extern void ext3_discard_reservation (struct inode *); | |||
| 832 | extern void ext3_dirty_inode(struct inode *); | 832 | extern void ext3_dirty_inode(struct inode *); |
| 833 | extern int ext3_change_inode_journal_flag(struct inode *, int); | 833 | extern int ext3_change_inode_journal_flag(struct inode *, int); |
| 834 | extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *); | 834 | extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *); |
| 835 | extern int ext3_can_truncate(struct inode *inode); | ||
| 835 | extern void ext3_truncate (struct inode *); | 836 | extern void ext3_truncate (struct inode *); |
| 836 | extern void ext3_set_inode_flags(struct inode *); | 837 | extern void ext3_set_inode_flags(struct inode *); |
| 837 | extern void ext3_get_inode_flags(struct ext3_inode_info *); | 838 | extern void ext3_get_inode_flags(struct ext3_inode_info *); |
diff --git a/include/linux/fd1772.h b/include/linux/fd1772.h deleted file mode 100644 index 871d6e4c677e..000000000000 --- a/include/linux/fd1772.h +++ /dev/null | |||
| @@ -1,80 +0,0 @@ | |||
| 1 | #ifndef _LINUX_FD1772REG_H | ||
| 2 | #define _LINUX_FD1772REG_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | ** WD1772 stuff - originally from the M68K Linux | ||
| 6 | * Modified for Archimedes by Dave Gilbert (gilbertd@cs.man.ac.uk) | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* register codes */ | ||
| 10 | |||
| 11 | #define FDC1772SELREG_STP (0x80) /* command/status register */ | ||
| 12 | #define FDC1772SELREG_TRA (0x82) /* track register */ | ||
| 13 | #define FDC1772SELREG_SEC (0x84) /* sector register */ | ||
| 14 | #define FDC1772SELREG_DTA (0x86) /* data register */ | ||
| 15 | |||
| 16 | /* register names for FDC1772_READ/WRITE macros */ | ||
| 17 | |||
| 18 | #define FDC1772REG_CMD 0 | ||
| 19 | #define FDC1772REG_STATUS 0 | ||
| 20 | #define FDC1772REG_TRACK 2 | ||
| 21 | #define FDC1772REG_SECTOR 4 | ||
| 22 | #define FDC1772REG_DATA 6 | ||
| 23 | |||
| 24 | /* command opcodes */ | ||
| 25 | |||
| 26 | #define FDC1772CMD_RESTORE (0x00) /* - */ | ||
| 27 | #define FDC1772CMD_SEEK (0x10) /* | */ | ||
| 28 | #define FDC1772CMD_STEP (0x20) /* | TYP 1 Commands */ | ||
| 29 | #define FDC1772CMD_STIN (0x40) /* | */ | ||
| 30 | #define FDC1772CMD_STOT (0x60) /* - */ | ||
| 31 | #define FDC1772CMD_RDSEC (0x80) /* - TYP 2 Commands */ | ||
| 32 | #define FDC1772CMD_WRSEC (0xa0) /* - " */ | ||
| 33 | #define FDC1772CMD_RDADR (0xc0) /* - */ | ||
| 34 | #define FDC1772CMD_RDTRA (0xe0) /* | TYP 3 Commands */ | ||
| 35 | #define FDC1772CMD_WRTRA (0xf0) /* - */ | ||
| 36 | #define FDC1772CMD_FORCI (0xd0) /* - TYP 4 Command */ | ||
| 37 | |||
| 38 | /* command modifier bits */ | ||
| 39 | |||
| 40 | #define FDC1772CMDADD_SR6 (0x00) /* step rate settings */ | ||
| 41 | #define FDC1772CMDADD_SR12 (0x01) | ||
| 42 | #define FDC1772CMDADD_SR2 (0x02) | ||
| 43 | #define FDC1772CMDADD_SR3 (0x03) | ||
| 44 | #define FDC1772CMDADD_V (0x04) /* verify */ | ||
| 45 | #define FDC1772CMDADD_H (0x08) /* wait for spin-up */ | ||
| 46 | #define FDC1772CMDADD_U (0x10) /* update track register */ | ||
| 47 | #define FDC1772CMDADD_M (0x10) /* multiple sector access */ | ||
| 48 | #define FDC1772CMDADD_E (0x04) /* head settling flag */ | ||
| 49 | #define FDC1772CMDADD_P (0x02) /* precompensation */ | ||
| 50 | #define FDC1772CMDADD_A0 (0x01) /* DAM flag */ | ||
| 51 | |||
| 52 | /* status register bits */ | ||
| 53 | |||
| 54 | #define FDC1772STAT_MOTORON (0x80) /* motor on */ | ||
| 55 | #define FDC1772STAT_WPROT (0x40) /* write protected (FDC1772CMD_WR*) */ | ||
| 56 | #define FDC1772STAT_SPINUP (0x20) /* motor speed stable (Type I) */ | ||
| 57 | #define FDC1772STAT_DELDAM (0x20) /* sector has deleted DAM (Type II+III) */ | ||
| 58 | #define FDC1772STAT_RECNF (0x10) /* record not found */ | ||
| 59 | #define FDC1772STAT_CRC (0x08) /* CRC error */ | ||
| 60 | #define FDC1772STAT_TR00 (0x04) /* Track 00 flag (Type I) */ | ||
| 61 | #define FDC1772STAT_LOST (0x04) /* Lost Data (Type II+III) */ | ||
| 62 | #define FDC1772STAT_IDX (0x02) /* Index status (Type I) */ | ||
| 63 | #define FDC1772STAT_DRQ (0x02) /* DRQ status (Type II+III) */ | ||
| 64 | #define FDC1772STAT_BUSY (0x01) /* FDC1772 is busy */ | ||
| 65 | |||
| 66 | |||
| 67 | /* PSG Port A Bit Nr 0 .. Side Sel .. 0 -> Side 1 1 -> Side 2 */ | ||
| 68 | #define DSKSIDE (0x01) | ||
| 69 | |||
| 70 | #define DSKDRVNONE (0x06) | ||
| 71 | #define DSKDRV0 (0x02) | ||
| 72 | #define DSKDRV1 (0x04) | ||
| 73 | |||
| 74 | /* step rates */ | ||
| 75 | #define FDC1772STEP_6 0x00 | ||
| 76 | #define FDC1772STEP_12 0x01 | ||
| 77 | #define FDC1772STEP_2 0x02 | ||
| 78 | #define FDC1772STEP_3 0x03 | ||
| 79 | |||
| 80 | #endif | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 4b86f806014c..49d8eb7a71be 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -886,6 +886,12 @@ static inline int file_check_writeable(struct file *filp) | |||
| 886 | #define FL_SLEEP 128 /* A blocking lock */ | 886 | #define FL_SLEEP 128 /* A blocking lock */ |
| 887 | 887 | ||
| 888 | /* | 888 | /* |
| 889 | * Special return value from posix_lock_file() and vfs_lock_file() for | ||
| 890 | * asynchronous locking. | ||
| 891 | */ | ||
| 892 | #define FILE_LOCK_DEFERRED 1 | ||
| 893 | |||
| 894 | /* | ||
| 889 | * The POSIX file lock owner is determined by | 895 | * The POSIX file lock owner is determined by |
| 890 | * the "struct files_struct" in the thread group | 896 | * the "struct files_struct" in the thread group |
| 891 | * (or NULL for no owner - BSD locks). | 897 | * (or NULL for no owner - BSD locks). |
diff --git a/include/linux/fuse.h b/include/linux/fuse.h index d48282197696..265635dc9908 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h | |||
| @@ -104,11 +104,14 @@ struct fuse_file_lock { | |||
| 104 | 104 | ||
| 105 | /** | 105 | /** |
| 106 | * INIT request/reply flags | 106 | * INIT request/reply flags |
| 107 | * | ||
| 108 | * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." | ||
| 107 | */ | 109 | */ |
| 108 | #define FUSE_ASYNC_READ (1 << 0) | 110 | #define FUSE_ASYNC_READ (1 << 0) |
| 109 | #define FUSE_POSIX_LOCKS (1 << 1) | 111 | #define FUSE_POSIX_LOCKS (1 << 1) |
| 110 | #define FUSE_FILE_OPS (1 << 2) | 112 | #define FUSE_FILE_OPS (1 << 2) |
| 111 | #define FUSE_ATOMIC_O_TRUNC (1 << 3) | 113 | #define FUSE_ATOMIC_O_TRUNC (1 << 3) |
| 114 | #define FUSE_EXPORT_SUPPORT (1 << 4) | ||
| 112 | #define FUSE_BIG_WRITES (1 << 5) | 115 | #define FUSE_BIG_WRITES (1 << 5) |
| 113 | 116 | ||
| 114 | /** | 117 | /** |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index e8787417f65a..118216f1bd3c 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
| @@ -541,7 +541,7 @@ extern dev_t blk_lookup_devt(const char *name, int part); | |||
| 541 | extern char *disk_name (struct gendisk *hd, int part, char *buf); | 541 | extern char *disk_name (struct gendisk *hd, int part, char *buf); |
| 542 | 542 | ||
| 543 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); | 543 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); |
| 544 | extern void add_partition(struct gendisk *, int, sector_t, sector_t, int); | 544 | extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int); |
| 545 | extern void delete_partition(struct gendisk *, int); | 545 | extern void delete_partition(struct gendisk *, int); |
| 546 | extern void printk_all_partitions(void); | 546 | extern void printk_all_partitions(void); |
| 547 | 547 | ||
diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 98be6c5762b9..730a20b83576 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h | |||
| @@ -79,6 +79,19 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value) | |||
| 79 | WARN_ON(1); | 79 | WARN_ON(1); |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static inline int gpio_export(unsigned gpio, bool direction_may_change) | ||
| 83 | { | ||
| 84 | /* GPIO can never have been requested or set as {in,out}put */ | ||
| 85 | WARN_ON(1); | ||
| 86 | return -EINVAL; | ||
| 87 | } | ||
| 88 | |||
| 89 | static inline void gpio_unexport(unsigned gpio) | ||
| 90 | { | ||
| 91 | /* GPIO can never have been exported */ | ||
| 92 | WARN_ON(1); | ||
| 93 | } | ||
| 94 | |||
| 82 | static inline int gpio_to_irq(unsigned gpio) | 95 | static inline int gpio_to_irq(unsigned gpio) |
| 83 | { | 96 | { |
| 84 | /* GPIO can never have been requested or set as input */ | 97 | /* GPIO can never have been requested or set as input */ |
diff --git a/include/linux/i2c/max732x.h b/include/linux/i2c/max732x.h new file mode 100644 index 000000000000..e10336631c62 --- /dev/null +++ b/include/linux/i2c/max732x.h | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | #ifndef __LINUX_I2C_MAX732X_H | ||
| 2 | #define __LINUX_I2C_MAX732X_H | ||
| 3 | |||
| 4 | /* platform data for the MAX732x 8/16-bit I/O expander driver */ | ||
| 5 | |||
| 6 | struct max732x_platform_data { | ||
| 7 | /* number of the first GPIO */ | ||
| 8 | unsigned gpio_base; | ||
| 9 | |||
| 10 | void *context; /* param to setup/teardown */ | ||
| 11 | |||
| 12 | int (*setup)(struct i2c_client *client, | ||
| 13 | unsigned gpio, unsigned ngpio, | ||
| 14 | void *context); | ||
| 15 | int (*teardown)(struct i2c_client *client, | ||
| 16 | unsigned gpio, unsigned ngpio, | ||
| 17 | void *context); | ||
| 18 | }; | ||
| 19 | #endif /* __LINUX_I2C_MAX732X_H */ | ||
diff --git a/include/linux/idr.h b/include/linux/idr.h index 9a2d762124de..fa035f96f2a3 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| 16 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/rcupdate.h> | ||
| 18 | 19 | ||
| 19 | #if BITS_PER_LONG == 32 | 20 | #if BITS_PER_LONG == 32 |
| 20 | # define IDR_BITS 5 | 21 | # define IDR_BITS 5 |
| @@ -51,6 +52,7 @@ struct idr_layer { | |||
| 51 | unsigned long bitmap; /* A zero bit means "space here" */ | 52 | unsigned long bitmap; /* A zero bit means "space here" */ |
| 52 | struct idr_layer *ary[1<<IDR_BITS]; | 53 | struct idr_layer *ary[1<<IDR_BITS]; |
| 53 | int count; /* When zero, we can release it */ | 54 | int count; /* When zero, we can release it */ |
| 55 | struct rcu_head rcu_head; | ||
| 54 | }; | 56 | }; |
| 55 | 57 | ||
| 56 | struct idr { | 58 | struct idr { |
| @@ -71,6 +73,28 @@ struct idr { | |||
| 71 | } | 73 | } |
| 72 | #define DEFINE_IDR(name) struct idr name = IDR_INIT(name) | 74 | #define DEFINE_IDR(name) struct idr name = IDR_INIT(name) |
| 73 | 75 | ||
| 76 | /* Actions to be taken after a call to _idr_sub_alloc */ | ||
| 77 | #define IDR_NEED_TO_GROW -2 | ||
| 78 | #define IDR_NOMORE_SPACE -3 | ||
| 79 | |||
| 80 | #define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC) | ||
| 81 | |||
| 82 | /** | ||
| 83 | * idr synchronization (stolen from radix-tree.h) | ||
| 84 | * | ||
| 85 | * idr_find() is able to be called locklessly, using RCU. The caller must | ||
| 86 | * ensure calls to this function are made within rcu_read_lock() regions. | ||
| 87 | * Other readers (lock-free or otherwise) and modifications may be running | ||
| 88 | * concurrently. | ||
| 89 | * | ||
| 90 | * It is still required that the caller manage the synchronization and | ||
| 91 | * lifetimes of the items. So if RCU lock-free lookups are used, typically | ||
| 92 | * this would mean that the items have their own locks, or are amenable to | ||
| 93 | * lock-free access; and that the items are freed by RCU (or only freed after | ||
| 94 | * having been deleted from the idr tree *and* a synchronize_rcu() grace | ||
| 95 | * period). | ||
| 96 | */ | ||
| 97 | |||
| 74 | /* | 98 | /* |
| 75 | * This is what we export. | 99 | * This is what we export. |
| 76 | */ | 100 | */ |
diff --git a/include/linux/init.h b/include/linux/init.h index 21d658cdfa27..42ae95411a93 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
| @@ -275,13 +275,7 @@ void __init parse_early_param(void); | |||
| 275 | 275 | ||
| 276 | #define security_initcall(fn) module_init(fn) | 276 | #define security_initcall(fn) module_init(fn) |
| 277 | 277 | ||
| 278 | /* These macros create a dummy inline: gcc 2.9x does not count alias | 278 | /* Each module must use one module_init(). */ |
| 279 | as usage, hence the `unused function' warning when __init functions | ||
| 280 | are declared static. We use the dummy __*_module_inline functions | ||
| 281 | both to kill the warning and check the type of the init/cleanup | ||
| 282 | function. */ | ||
| 283 | |||
| 284 | /* Each module must use one module_init(), or one no_module_init */ | ||
| 285 | #define module_init(initfn) \ | 279 | #define module_init(initfn) \ |
| 286 | static inline initcall_t __inittest(void) \ | 280 | static inline initcall_t __inittest(void) \ |
| 287 | { return initfn; } \ | 281 | { return initfn; } \ |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 93c45acf249a..021d8e720c79 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
| @@ -122,7 +122,7 @@ extern struct group_info init_groups; | |||
| 122 | .state = 0, \ | 122 | .state = 0, \ |
| 123 | .stack = &init_thread_info, \ | 123 | .stack = &init_thread_info, \ |
| 124 | .usage = ATOMIC_INIT(2), \ | 124 | .usage = ATOMIC_INIT(2), \ |
| 125 | .flags = 0, \ | 125 | .flags = PF_KTHREAD, \ |
| 126 | .lock_depth = -1, \ | 126 | .lock_depth = -1, \ |
| 127 | .prio = MAX_PRIO-20, \ | 127 | .prio = MAX_PRIO-20, \ |
| 128 | .static_prio = MAX_PRIO-20, \ | 128 | .static_prio = MAX_PRIO-20, \ |
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index ea6c18a8b0d4..ea330f9e7100 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h | |||
| @@ -36,6 +36,7 @@ struct ipc_namespace { | |||
| 36 | int msg_ctlmni; | 36 | int msg_ctlmni; |
| 37 | atomic_t msg_bytes; | 37 | atomic_t msg_bytes; |
| 38 | atomic_t msg_hdrs; | 38 | atomic_t msg_hdrs; |
| 39 | int auto_msgmni; | ||
| 39 | 40 | ||
| 40 | size_t shm_ctlmax; | 41 | size_t shm_ctlmax; |
| 41 | size_t shm_ctlall; | 42 | size_t shm_ctlall; |
| @@ -53,7 +54,7 @@ extern atomic_t nr_ipc_ns; | |||
| 53 | 54 | ||
| 54 | extern int register_ipcns_notifier(struct ipc_namespace *); | 55 | extern int register_ipcns_notifier(struct ipc_namespace *); |
| 55 | extern int cond_register_ipcns_notifier(struct ipc_namespace *); | 56 | extern int cond_register_ipcns_notifier(struct ipc_namespace *); |
| 56 | extern int unregister_ipcns_notifier(struct ipc_namespace *); | 57 | extern void unregister_ipcns_notifier(struct ipc_namespace *); |
| 57 | extern int ipcns_notify(unsigned long); | 58 | extern int ipcns_notify(unsigned long); |
| 58 | 59 | ||
| 59 | #else /* CONFIG_SYSVIPC */ | 60 | #else /* CONFIG_SYSVIPC */ |
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index 2b1c2e58566e..74bde13224c9 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #ifndef _LINUX_TRACE_IRQFLAGS_H | 11 | #ifndef _LINUX_TRACE_IRQFLAGS_H |
| 12 | #define _LINUX_TRACE_IRQFLAGS_H | 12 | #define _LINUX_TRACE_IRQFLAGS_H |
| 13 | 13 | ||
| 14 | #include <linux/typecheck.h> | ||
| 15 | |||
| 14 | #ifdef CONFIG_TRACE_IRQFLAGS | 16 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 15 | extern void trace_softirqs_on(unsigned long ip); | 17 | extern void trace_softirqs_on(unsigned long ip); |
| 16 | extern void trace_softirqs_off(unsigned long ip); | 18 | extern void trace_softirqs_off(unsigned long ip); |
| @@ -58,18 +60,24 @@ | |||
| 58 | do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0) | 60 | do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0) |
| 59 | #define local_irq_disable() \ | 61 | #define local_irq_disable() \ |
| 60 | do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) | 62 | do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) |
| 61 | #define local_irq_save(flags) \ | 63 | #define local_irq_save(flags) \ |
| 62 | do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0) | 64 | do { \ |
| 65 | typecheck(unsigned long, flags); \ | ||
| 66 | raw_local_irq_save(flags); \ | ||
| 67 | trace_hardirqs_off(); \ | ||
| 68 | } while (0) | ||
| 63 | 69 | ||
| 64 | #define local_irq_restore(flags) \ | 70 | |
| 65 | do { \ | 71 | #define local_irq_restore(flags) \ |
| 66 | if (raw_irqs_disabled_flags(flags)) { \ | 72 | do { \ |
| 67 | raw_local_irq_restore(flags); \ | 73 | typecheck(unsigned long, flags); \ |
| 68 | trace_hardirqs_off(); \ | 74 | if (raw_irqs_disabled_flags(flags)) { \ |
| 69 | } else { \ | 75 | raw_local_irq_restore(flags); \ |
| 70 | trace_hardirqs_on(); \ | 76 | trace_hardirqs_off(); \ |
| 71 | raw_local_irq_restore(flags); \ | 77 | } else { \ |
| 72 | } \ | 78 | trace_hardirqs_on(); \ |
| 79 | raw_local_irq_restore(flags); \ | ||
| 80 | } \ | ||
| 73 | } while (0) | 81 | } while (0) |
| 74 | #else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */ | 82 | #else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */ |
| 75 | /* | 83 | /* |
| @@ -78,8 +86,16 @@ | |||
| 78 | */ | 86 | */ |
| 79 | # define raw_local_irq_disable() local_irq_disable() | 87 | # define raw_local_irq_disable() local_irq_disable() |
| 80 | # define raw_local_irq_enable() local_irq_enable() | 88 | # define raw_local_irq_enable() local_irq_enable() |
| 81 | # define raw_local_irq_save(flags) local_irq_save(flags) | 89 | # define raw_local_irq_save(flags) \ |
| 82 | # define raw_local_irq_restore(flags) local_irq_restore(flags) | 90 | do { \ |
| 91 | typecheck(unsigned long, flags); \ | ||
| 92 | local_irq_save(flags); \ | ||
| 93 | } while (0) | ||
| 94 | # define raw_local_irq_restore(flags) \ | ||
| 95 | do { \ | ||
| 96 | typecheck(unsigned long, flags); \ | ||
| 97 | local_irq_restore(flags); \ | ||
| 98 | } while (0) | ||
| 83 | #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ | 99 | #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ |
| 84 | 100 | ||
| 85 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | 101 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT |
| @@ -89,7 +105,11 @@ | |||
| 89 | raw_safe_halt(); \ | 105 | raw_safe_halt(); \ |
| 90 | } while (0) | 106 | } while (0) |
| 91 | 107 | ||
| 92 | #define local_save_flags(flags) raw_local_save_flags(flags) | 108 | #define local_save_flags(flags) \ |
| 109 | do { \ | ||
| 110 | typecheck(unsigned long, flags); \ | ||
| 111 | raw_local_save_flags(flags); \ | ||
| 112 | } while (0) | ||
| 93 | 113 | ||
| 94 | #define irqs_disabled() \ | 114 | #define irqs_disabled() \ |
| 95 | ({ \ | 115 | ({ \ |
| @@ -99,7 +119,11 @@ | |||
| 99 | raw_irqs_disabled_flags(_flags); \ | 119 | raw_irqs_disabled_flags(_flags); \ |
| 100 | }) | 120 | }) |
| 101 | 121 | ||
| 102 | #define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) | 122 | #define irqs_disabled_flags(flags) \ |
| 123 | ({ \ | ||
| 124 | typecheck(unsigned long, flags); \ | ||
| 125 | raw_irqs_disabled_flags(flags); \ | ||
| 126 | }) | ||
| 103 | #endif /* CONFIG_X86 */ | 127 | #endif /* CONFIG_X86 */ |
| 104 | 128 | ||
| 105 | #endif | 129 | #endif |
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 00c1801099fa..57aefa160a92 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #define _LINUX_KALLSYMS_H | 6 | #define _LINUX_KALLSYMS_H |
| 7 | 7 | ||
| 8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
| 9 | #include <linux/kernel.h> | ||
| 9 | #include <linux/stddef.h> | 10 | #include <linux/stddef.h> |
| 10 | 11 | ||
| 11 | #define KSYM_NAME_LEN 128 | 12 | #define KSYM_NAME_LEN 128 |
| @@ -105,18 +106,10 @@ static inline void print_fn_descriptor_symbol(const char *fmt, void *addr) | |||
| 105 | print_symbol(fmt, (unsigned long)addr); | 106 | print_symbol(fmt, (unsigned long)addr); |
| 106 | } | 107 | } |
| 107 | 108 | ||
| 108 | #ifndef CONFIG_64BIT | 109 | static inline void print_ip_sym(unsigned long ip) |
| 109 | #define print_ip_sym(ip) \ | 110 | { |
| 110 | do { \ | 111 | printk("[<%p>]", (void *) ip); |
| 111 | printk("[<%08lx>]", ip); \ | 112 | print_symbol(" %s\n", ip); |
| 112 | print_symbol(" %s\n", ip); \ | 113 | } |
| 113 | } while(0) | ||
| 114 | #else | ||
| 115 | #define print_ip_sym(ip) \ | ||
| 116 | do { \ | ||
| 117 | printk("[<%016lx>]", ip); \ | ||
| 118 | print_symbol(" %s\n", ip); \ | ||
| 119 | } while(0) | ||
| 120 | #endif | ||
| 121 | 114 | ||
| 122 | #endif /*_LINUX_KALLSYMS_H*/ | 115 | #endif /*_LINUX_KALLSYMS_H*/ |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f9cd7a513f9c..fdbbf72ca2eb 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include <linux/compiler.h> | 14 | #include <linux/compiler.h> |
| 15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
| 16 | #include <linux/log2.h> | 16 | #include <linux/log2.h> |
| 17 | #include <linux/typecheck.h> | ||
| 18 | #include <linux/ratelimit.h> | ||
| 17 | #include <asm/byteorder.h> | 19 | #include <asm/byteorder.h> |
| 18 | #include <asm/bug.h> | 20 | #include <asm/bug.h> |
| 19 | 21 | ||
| @@ -188,11 +190,8 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
| 188 | asmlinkage int printk(const char * fmt, ...) | 190 | asmlinkage int printk(const char * fmt, ...) |
| 189 | __attribute__ ((format (printf, 1, 2))) __cold; | 191 | __attribute__ ((format (printf, 1, 2))) __cold; |
| 190 | 192 | ||
| 191 | extern int printk_ratelimit_jiffies; | 193 | extern struct ratelimit_state printk_ratelimit_state; |
| 192 | extern int printk_ratelimit_burst; | ||
| 193 | extern int printk_ratelimit(void); | 194 | extern int printk_ratelimit(void); |
| 194 | extern int __ratelimit(int ratelimit_jiffies, int ratelimit_burst); | ||
| 195 | extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst); | ||
| 196 | extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, | 195 | extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, |
| 197 | unsigned int interval_msec); | 196 | unsigned int interval_msec); |
| 198 | #else | 197 | #else |
| @@ -203,8 +202,6 @@ static inline int printk(const char *s, ...) | |||
| 203 | __attribute__ ((format (printf, 1, 2))); | 202 | __attribute__ ((format (printf, 1, 2))); |
| 204 | static inline int __cold printk(const char *s, ...) { return 0; } | 203 | static inline int __cold printk(const char *s, ...) { return 0; } |
| 205 | static inline int printk_ratelimit(void) { return 0; } | 204 | static inline int printk_ratelimit(void) { return 0; } |
| 206 | static inline int __printk_ratelimit(int ratelimit_jiffies, \ | ||
| 207 | int ratelimit_burst) { return 0; } | ||
| 208 | static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \ | 205 | static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \ |
| 209 | unsigned int interval_msec) \ | 206 | unsigned int interval_msec) \ |
| 210 | { return false; } | 207 | { return false; } |
| @@ -441,26 +438,6 @@ static inline char *pack_hex_byte(char *buf, u8 byte) | |||
| 441 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ | 438 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
| 442 | (type *)( (char *)__mptr - offsetof(type,member) );}) | 439 | (type *)( (char *)__mptr - offsetof(type,member) );}) |
| 443 | 440 | ||
| 444 | /* | ||
| 445 | * Check at compile time that something is of a particular type. | ||
| 446 | * Always evaluates to 1 so you may use it easily in comparisons. | ||
| 447 | */ | ||
| 448 | #define typecheck(type,x) \ | ||
| 449 | ({ type __dummy; \ | ||
| 450 | typeof(x) __dummy2; \ | ||
| 451 | (void)(&__dummy == &__dummy2); \ | ||
| 452 | 1; \ | ||
| 453 | }) | ||
| 454 | |||
| 455 | /* | ||
| 456 | * Check at compile time that 'function' is a certain type, or is a pointer | ||
| 457 | * to that type (needs to use typedef for the function type.) | ||
| 458 | */ | ||
| 459 | #define typecheck_fn(type,function) \ | ||
| 460 | ({ typeof(type) __tmp = function; \ | ||
| 461 | (void)__tmp; \ | ||
| 462 | }) | ||
| 463 | |||
| 464 | struct sysinfo; | 441 | struct sysinfo; |
| 465 | extern int do_sysinfo(struct sysinfo *info); | 442 | extern int do_sysinfo(struct sysinfo *info); |
| 466 | 443 | ||
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 0509c4ce4857..a1a91577813c 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/gfp.h> | ||
| 22 | #include <linux/stddef.h> | 23 | #include <linux/stddef.h> |
| 23 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 24 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
| @@ -41,8 +42,8 @@ struct file; | |||
| 41 | struct subprocess_info; | 42 | struct subprocess_info; |
| 42 | 43 | ||
| 43 | /* Allocate a subprocess_info structure */ | 44 | /* Allocate a subprocess_info structure */ |
| 44 | struct subprocess_info *call_usermodehelper_setup(char *path, | 45 | struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, |
| 45 | char **argv, char **envp); | 46 | char **envp, gfp_t gfp_mask); |
| 46 | 47 | ||
| 47 | /* Set various pieces of state into the subprocess_info structure */ | 48 | /* Set various pieces of state into the subprocess_info structure */ |
| 48 | void call_usermodehelper_setkeys(struct subprocess_info *info, | 49 | void call_usermodehelper_setkeys(struct subprocess_info *info, |
| @@ -69,8 +70,9 @@ static inline int | |||
| 69 | call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait) | 70 | call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait) |
| 70 | { | 71 | { |
| 71 | struct subprocess_info *info; | 72 | struct subprocess_info *info; |
| 73 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; | ||
| 72 | 74 | ||
| 73 | info = call_usermodehelper_setup(path, argv, envp); | 75 | info = call_usermodehelper_setup(path, argv, envp, gfp_mask); |
| 74 | if (info == NULL) | 76 | if (info == NULL) |
| 75 | return -ENOMEM; | 77 | return -ENOMEM; |
| 76 | return call_usermodehelper_exec(info, wait); | 78 | return call_usermodehelper_exec(info, wait); |
| @@ -81,8 +83,9 @@ call_usermodehelper_keys(char *path, char **argv, char **envp, | |||
| 81 | struct key *session_keyring, enum umh_wait wait) | 83 | struct key *session_keyring, enum umh_wait wait) |
| 82 | { | 84 | { |
| 83 | struct subprocess_info *info; | 85 | struct subprocess_info *info; |
| 86 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; | ||
| 84 | 87 | ||
| 85 | info = call_usermodehelper_setup(path, argv, envp); | 88 | info = call_usermodehelper_setup(path, argv, envp, gfp_mask); |
| 86 | if (info == NULL) | 89 | if (info == NULL) |
| 87 | return -ENOMEM; | 90 | return -ENOMEM; |
| 88 | 91 | ||
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 04a3556bdea6..0be7795655fa 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
| @@ -157,11 +157,10 @@ struct kretprobe { | |||
| 157 | int nmissed; | 157 | int nmissed; |
| 158 | size_t data_size; | 158 | size_t data_size; |
| 159 | struct hlist_head free_instances; | 159 | struct hlist_head free_instances; |
| 160 | struct hlist_head used_instances; | 160 | spinlock_t lock; |
| 161 | }; | 161 | }; |
| 162 | 162 | ||
| 163 | struct kretprobe_instance { | 163 | struct kretprobe_instance { |
| 164 | struct hlist_node uflist; /* either on free list or used list */ | ||
| 165 | struct hlist_node hlist; | 164 | struct hlist_node hlist; |
| 166 | struct kretprobe *rp; | 165 | struct kretprobe *rp; |
| 167 | kprobe_opcode_t *ret_addr; | 166 | kprobe_opcode_t *ret_addr; |
| @@ -201,7 +200,6 @@ static inline int init_test_probes(void) | |||
| 201 | } | 200 | } |
| 202 | #endif /* CONFIG_KPROBES_SANITY_TEST */ | 201 | #endif /* CONFIG_KPROBES_SANITY_TEST */ |
| 203 | 202 | ||
| 204 | extern spinlock_t kretprobe_lock; | ||
| 205 | extern struct mutex kprobe_mutex; | 203 | extern struct mutex kprobe_mutex; |
| 206 | extern int arch_prepare_kprobe(struct kprobe *p); | 204 | extern int arch_prepare_kprobe(struct kprobe *p); |
| 207 | extern void arch_arm_kprobe(struct kprobe *p); | 205 | extern void arch_arm_kprobe(struct kprobe *p); |
| @@ -214,6 +212,9 @@ extern void kprobes_inc_nmissed_count(struct kprobe *p); | |||
| 214 | 212 | ||
| 215 | /* Get the kprobe at this addr (if any) - called with preemption disabled */ | 213 | /* Get the kprobe at this addr (if any) - called with preemption disabled */ |
| 216 | struct kprobe *get_kprobe(void *addr); | 214 | struct kprobe *get_kprobe(void *addr); |
| 215 | void kretprobe_hash_lock(struct task_struct *tsk, | ||
| 216 | struct hlist_head **head, unsigned long *flags); | ||
| 217 | void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags); | ||
| 217 | struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); | 218 | struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); |
| 218 | 219 | ||
| 219 | /* kprobe_running() will just return the current_kprobe on this CPU */ | 220 | /* kprobe_running() will just return the current_kprobe on this CPU */ |
diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 00dd957e245b..aabc8a13ba71 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h | |||
| @@ -6,7 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | struct task_struct *kthread_create(int (*threadfn)(void *data), | 7 | struct task_struct *kthread_create(int (*threadfn)(void *data), |
| 8 | void *data, | 8 | void *data, |
| 9 | const char namefmt[], ...); | 9 | const char namefmt[], ...) |
| 10 | __attribute__((format(printf, 3, 4))); | ||
| 10 | 11 | ||
| 11 | /** | 12 | /** |
| 12 | * kthread_run - create and wake a thread. | 13 | * kthread_run - create and wake a thread. |
diff --git a/include/linux/list.h b/include/linux/list.h index 139ec41d9c2e..453916bc0412 100644 --- a/include/linux/list.h +++ b/include/linux/list.h | |||
| @@ -61,14 +61,10 @@ extern void __list_add(struct list_head *new, | |||
| 61 | * Insert a new entry after the specified head. | 61 | * Insert a new entry after the specified head. |
| 62 | * This is good for implementing stacks. | 62 | * This is good for implementing stacks. |
| 63 | */ | 63 | */ |
| 64 | #ifndef CONFIG_DEBUG_LIST | ||
| 65 | static inline void list_add(struct list_head *new, struct list_head *head) | 64 | static inline void list_add(struct list_head *new, struct list_head *head) |
| 66 | { | 65 | { |
| 67 | __list_add(new, head, head->next); | 66 | __list_add(new, head, head->next); |
| 68 | } | 67 | } |
| 69 | #else | ||
| 70 | extern void list_add(struct list_head *new, struct list_head *head); | ||
| 71 | #endif | ||
| 72 | 68 | ||
| 73 | 69 | ||
| 74 | /** | 70 | /** |
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index e6608776bc96..fdf3967e1397 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h | |||
| @@ -35,7 +35,10 @@ extern int mem_cgroup_charge(struct page *page, struct mm_struct *mm, | |||
| 35 | extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, | 35 | extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, |
| 36 | gfp_t gfp_mask); | 36 | gfp_t gfp_mask); |
| 37 | extern void mem_cgroup_uncharge_page(struct page *page); | 37 | extern void mem_cgroup_uncharge_page(struct page *page); |
| 38 | extern void mem_cgroup_uncharge_cache_page(struct page *page); | ||
| 38 | extern void mem_cgroup_move_lists(struct page *page, bool active); | 39 | extern void mem_cgroup_move_lists(struct page *page, bool active); |
| 40 | extern int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask); | ||
| 41 | |||
| 39 | extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, | 42 | extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, |
| 40 | struct list_head *dst, | 43 | struct list_head *dst, |
| 41 | unsigned long *scanned, int order, | 44 | unsigned long *scanned, int order, |
| @@ -50,9 +53,9 @@ extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); | |||
| 50 | #define mm_match_cgroup(mm, cgroup) \ | 53 | #define mm_match_cgroup(mm, cgroup) \ |
| 51 | ((cgroup) == mem_cgroup_from_task((mm)->owner)) | 54 | ((cgroup) == mem_cgroup_from_task((mm)->owner)) |
| 52 | 55 | ||
| 53 | extern int mem_cgroup_prepare_migration(struct page *page); | 56 | extern int |
| 57 | mem_cgroup_prepare_migration(struct page *page, struct page *newpage); | ||
| 54 | extern void mem_cgroup_end_migration(struct page *page); | 58 | extern void mem_cgroup_end_migration(struct page *page); |
| 55 | extern void mem_cgroup_page_migration(struct page *page, struct page *newpage); | ||
| 56 | 59 | ||
| 57 | /* | 60 | /* |
| 58 | * For memory reclaim. | 61 | * For memory reclaim. |
| @@ -97,6 +100,15 @@ static inline void mem_cgroup_uncharge_page(struct page *page) | |||
| 97 | { | 100 | { |
| 98 | } | 101 | } |
| 99 | 102 | ||
| 103 | static inline void mem_cgroup_uncharge_cache_page(struct page *page) | ||
| 104 | { | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask) | ||
| 108 | { | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 100 | static inline void mem_cgroup_move_lists(struct page *page, bool active) | 112 | static inline void mem_cgroup_move_lists(struct page *page, bool active) |
| 101 | { | 113 | { |
| 102 | } | 114 | } |
| @@ -112,7 +124,8 @@ static inline int task_in_mem_cgroup(struct task_struct *task, | |||
| 112 | return 1; | 124 | return 1; |
| 113 | } | 125 | } |
| 114 | 126 | ||
| 115 | static inline int mem_cgroup_prepare_migration(struct page *page) | 127 | static inline int |
| 128 | mem_cgroup_prepare_migration(struct page *page, struct page *newpage) | ||
| 116 | { | 129 | { |
| 117 | return 0; | 130 | return 0; |
| 118 | } | 131 | } |
| @@ -121,11 +134,6 @@ static inline void mem_cgroup_end_migration(struct page *page) | |||
| 121 | { | 134 | { |
| 122 | } | 135 | } |
| 123 | 136 | ||
| 124 | static inline void | ||
| 125 | mem_cgroup_page_migration(struct page *page, struct page *newpage) | ||
| 126 | { | ||
| 127 | } | ||
| 128 | |||
| 129 | static inline int mem_cgroup_calc_mapped_ratio(struct mem_cgroup *mem) | 137 | static inline int mem_cgroup_calc_mapped_ratio(struct mem_cgroup *mem) |
| 130 | { | 138 | { |
| 131 | return 0; | 139 | return 0; |
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 02a27ae78539..746f975b58ef 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h | |||
| @@ -159,6 +159,17 @@ struct vm_area_struct { | |||
| 159 | #endif | 159 | #endif |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | struct core_thread { | ||
| 163 | struct task_struct *task; | ||
| 164 | struct core_thread *next; | ||
| 165 | }; | ||
| 166 | |||
| 167 | struct core_state { | ||
| 168 | atomic_t nr_threads; | ||
| 169 | struct core_thread dumper; | ||
| 170 | struct completion startup; | ||
| 171 | }; | ||
| 172 | |||
| 162 | struct mm_struct { | 173 | struct mm_struct { |
| 163 | struct vm_area_struct * mmap; /* list of VMAs */ | 174 | struct vm_area_struct * mmap; /* list of VMAs */ |
| 164 | struct rb_root mm_rb; | 175 | struct rb_root mm_rb; |
| @@ -175,7 +186,6 @@ struct mm_struct { | |||
| 175 | atomic_t mm_users; /* How many users with user space? */ | 186 | atomic_t mm_users; /* How many users with user space? */ |
| 176 | atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */ | 187 | atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */ |
| 177 | int map_count; /* number of VMAs */ | 188 | int map_count; /* number of VMAs */ |
| 178 | int core_waiters; | ||
| 179 | struct rw_semaphore mmap_sem; | 189 | struct rw_semaphore mmap_sem; |
| 180 | spinlock_t page_table_lock; /* Protects page tables and some counters */ | 190 | spinlock_t page_table_lock; /* Protects page tables and some counters */ |
| 181 | 191 | ||
| @@ -219,8 +229,7 @@ struct mm_struct { | |||
| 219 | 229 | ||
| 220 | unsigned long flags; /* Must use atomic bitops to access the bits */ | 230 | unsigned long flags; /* Must use atomic bitops to access the bits */ |
| 221 | 231 | ||
| 222 | /* coredumping support */ | 232 | struct core_state *core_state; /* coredumping support */ |
| 223 | struct completion *core_startup_done, core_done; | ||
| 224 | 233 | ||
| 225 | /* aio bits */ | 234 | /* aio bits */ |
| 226 | rwlock_t ioctx_list_lock; /* aio lock */ | 235 | rwlock_t ioctx_list_lock; /* aio lock */ |
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 81cd36b735b0..ba63858056c7 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h | |||
| @@ -2,11 +2,11 @@ | |||
| 2 | #define _LINUX_MSDOS_FS_H | 2 | #define _LINUX_MSDOS_FS_H |
| 3 | 3 | ||
| 4 | #include <linux/magic.h> | 4 | #include <linux/magic.h> |
| 5 | #include <asm/byteorder.h> | ||
| 5 | 6 | ||
| 6 | /* | 7 | /* |
| 7 | * The MS-DOS filesystem constants/structures | 8 | * The MS-DOS filesystem constants/structures |
| 8 | */ | 9 | */ |
| 9 | #include <asm/byteorder.h> | ||
| 10 | 10 | ||
| 11 | #define SECTOR_SIZE 512 /* sector size (bytes) */ | 11 | #define SECTOR_SIZE 512 /* sector size (bytes) */ |
| 12 | #define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ | 12 | #define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ |
| @@ -89,24 +89,22 @@ | |||
| 89 | #define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ | 89 | #define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ |
| 90 | && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) | 90 | && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) |
| 91 | 91 | ||
| 92 | struct __fat_dirent { | ||
| 93 | long d_ino; | ||
| 94 | __kernel_off_t d_off; | ||
| 95 | unsigned short d_reclen; | ||
| 96 | char d_name[256]; /* We must not include limits.h! */ | ||
| 97 | }; | ||
| 98 | |||
| 92 | /* | 99 | /* |
| 93 | * ioctl commands | 100 | * ioctl commands |
| 94 | */ | 101 | */ |
| 95 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) | 102 | #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct __fat_dirent[2]) |
| 96 | #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) | 103 | #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct __fat_dirent[2]) |
| 97 | /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */ | 104 | /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */ |
| 98 | #define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) | 105 | #define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) |
| 99 | #define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) | 106 | #define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) |
| 100 | 107 | ||
| 101 | /* | ||
| 102 | * vfat shortname flags | ||
| 103 | */ | ||
| 104 | #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ | ||
| 105 | #define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ | ||
| 106 | #define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ | ||
| 107 | #define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ | ||
| 108 | #define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ | ||
| 109 | |||
| 110 | struct fat_boot_sector { | 108 | struct fat_boot_sector { |
| 111 | __u8 ignored[3]; /* Boot strap short or near jump */ | 109 | __u8 ignored[3]; /* Boot strap short or near jump */ |
| 112 | __u8 system_id[8]; /* Name - can be used to special case | 110 | __u8 system_id[8]; /* Name - can be used to special case |
| @@ -168,14 +166,6 @@ struct msdos_dir_slot { | |||
| 168 | __u8 name11_12[4]; /* last 2 characters in name */ | 166 | __u8 name11_12[4]; /* last 2 characters in name */ |
| 169 | }; | 167 | }; |
| 170 | 168 | ||
| 171 | struct fat_slot_info { | ||
| 172 | loff_t i_pos; /* on-disk position of directory entry */ | ||
| 173 | loff_t slot_off; /* offset for slot or de start */ | ||
| 174 | int nr_slots; /* number of slots + 1(de) in filename */ | ||
| 175 | struct msdos_dir_entry *de; | ||
| 176 | struct buffer_head *bh; | ||
| 177 | }; | ||
| 178 | |||
| 179 | #ifdef __KERNEL__ | 169 | #ifdef __KERNEL__ |
| 180 | 170 | ||
| 181 | #include <linux/buffer_head.h> | 171 | #include <linux/buffer_head.h> |
| @@ -184,6 +174,15 @@ struct fat_slot_info { | |||
| 184 | #include <linux/fs.h> | 174 | #include <linux/fs.h> |
| 185 | #include <linux/mutex.h> | 175 | #include <linux/mutex.h> |
| 186 | 176 | ||
| 177 | /* | ||
| 178 | * vfat shortname flags | ||
| 179 | */ | ||
| 180 | #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ | ||
| 181 | #define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ | ||
| 182 | #define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ | ||
| 183 | #define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ | ||
| 184 | #define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ | ||
| 185 | |||
| 187 | struct fat_mount_options { | 186 | struct fat_mount_options { |
| 188 | uid_t fs_uid; | 187 | uid_t fs_uid; |
| 189 | gid_t fs_gid; | 188 | gid_t fs_gid; |
| @@ -202,10 +201,10 @@ struct fat_mount_options { | |||
| 202 | utf8:1, /* Use of UTF-8 character set (Default) */ | 201 | utf8:1, /* Use of UTF-8 character set (Default) */ |
| 203 | unicode_xlate:1, /* create escape sequences for unhandled Unicode */ | 202 | unicode_xlate:1, /* create escape sequences for unhandled Unicode */ |
| 204 | numtail:1, /* Does first alias have a numeric '~1' type tail? */ | 203 | numtail:1, /* Does first alias have a numeric '~1' type tail? */ |
| 205 | atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */ | ||
| 206 | flush:1, /* write things quickly */ | 204 | flush:1, /* write things quickly */ |
| 207 | nocase:1, /* Does this need case conversion? 0=need case conversion*/ | 205 | nocase:1, /* Does this need case conversion? 0=need case conversion*/ |
| 208 | usefree:1; /* Use free_clusters for FAT32 */ | 206 | usefree:1, /* Use free_clusters for FAT32 */ |
| 207 | tz_utc:1; /* Filesystem timestamps are in UTC */ | ||
| 209 | }; | 208 | }; |
| 210 | 209 | ||
| 211 | #define FAT_HASH_BITS 8 | 210 | #define FAT_HASH_BITS 8 |
| @@ -267,6 +266,14 @@ struct msdos_inode_info { | |||
| 267 | struct inode vfs_inode; | 266 | struct inode vfs_inode; |
| 268 | }; | 267 | }; |
| 269 | 268 | ||
| 269 | struct fat_slot_info { | ||
| 270 | loff_t i_pos; /* on-disk position of directory entry */ | ||
| 271 | loff_t slot_off; /* offset for slot or de start */ | ||
| 272 | int nr_slots; /* number of slots + 1(de) in filename */ | ||
| 273 | struct msdos_dir_entry *de; | ||
| 274 | struct buffer_head *bh; | ||
| 275 | }; | ||
| 276 | |||
| 270 | static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) | 277 | static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) |
| 271 | { | 278 | { |
| 272 | return sb->s_fs_info; | 279 | return sb->s_fs_info; |
| @@ -428,8 +435,9 @@ extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | |||
| 428 | extern void fat_fs_panic(struct super_block *s, const char *fmt, ...); | 435 | extern void fat_fs_panic(struct super_block *s, const char *fmt, ...); |
| 429 | extern void fat_clusters_flush(struct super_block *sb); | 436 | extern void fat_clusters_flush(struct super_block *sb); |
| 430 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); | 437 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); |
| 431 | extern int date_dos2unix(unsigned short time, unsigned short date); | 438 | extern int date_dos2unix(unsigned short time, unsigned short date, int tz_utc); |
| 432 | extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date); | 439 | extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, |
| 440 | int tz_utc); | ||
| 433 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); | 441 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); |
| 434 | 442 | ||
| 435 | int fat_cache_init(void); | 443 | int fat_cache_init(void); |
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h index f71201d0f3e7..6316fafe5c2a 100644 --- a/include/linux/mtd/ubi.h +++ b/include/linux/mtd/ubi.h | |||
| @@ -45,13 +45,13 @@ enum { | |||
| 45 | * @size: how many physical eraseblocks are reserved for this volume | 45 | * @size: how many physical eraseblocks are reserved for this volume |
| 46 | * @used_bytes: how many bytes of data this volume contains | 46 | * @used_bytes: how many bytes of data this volume contains |
| 47 | * @used_ebs: how many physical eraseblocks of this volume actually contain any | 47 | * @used_ebs: how many physical eraseblocks of this volume actually contain any |
| 48 | * data | 48 | * data |
| 49 | * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) | 49 | * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) |
| 50 | * @corrupted: non-zero if the volume is corrupted (static volumes only) | 50 | * @corrupted: non-zero if the volume is corrupted (static volumes only) |
| 51 | * @upd_marker: non-zero if the volume has update marker set | 51 | * @upd_marker: non-zero if the volume has update marker set |
| 52 | * @alignment: volume alignment | 52 | * @alignment: volume alignment |
| 53 | * @usable_leb_size: how many bytes are available in logical eraseblocks of | 53 | * @usable_leb_size: how many bytes are available in logical eraseblocks of |
| 54 | * this volume | 54 | * this volume |
| 55 | * @name_len: volume name length | 55 | * @name_len: volume name length |
| 56 | * @name: volume name | 56 | * @name: volume name |
| 57 | * @cdev: UBI volume character device major and minor numbers | 57 | * @cdev: UBI volume character device major and minor numbers |
| @@ -152,6 +152,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum); | |||
| 152 | int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum); | 152 | int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum); |
| 153 | int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype); | 153 | int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype); |
| 154 | int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); | 154 | int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); |
| 155 | int ubi_sync(int ubi_num); | ||
| 155 | 156 | ||
| 156 | /* | 157 | /* |
| 157 | * This function is the same as the 'ubi_leb_read()' function, but it does not | 158 | * This function is the same as the 'ubi_leb_read()' function, but it does not |
diff --git a/include/linux/net.h b/include/linux/net.h index 2f999fbb188d..4a9a30f2d68f 100644 --- a/include/linux/net.h +++ b/include/linux/net.h | |||
| @@ -351,8 +351,7 @@ static const struct proto_ops name##_ops = { \ | |||
| 351 | 351 | ||
| 352 | #ifdef CONFIG_SYSCTL | 352 | #ifdef CONFIG_SYSCTL |
| 353 | #include <linux/sysctl.h> | 353 | #include <linux/sysctl.h> |
| 354 | extern int net_msg_cost; | 354 | extern struct ratelimit_state net_ratelimit_state; |
| 355 | extern int net_msg_burst; | ||
| 356 | #endif | 355 | #endif |
| 357 | 356 | ||
| 358 | #endif /* __KERNEL__ */ | 357 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index a2861d95ecc3..108f47e5fd95 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | #include <linux/unistd.h> | 14 | #include <linux/unistd.h> |
| 15 | #include <linux/dirent.h> | ||
| 16 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
| 17 | #include <linux/posix_acl.h> | 16 | #include <linux/posix_acl.h> |
| 18 | #include <linux/mount.h> | 17 | #include <linux/mount.h> |
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index bd3d72ddf333..da2698b0fdd1 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
| @@ -214,6 +214,8 @@ static inline int notifier_to_errno(int ret) | |||
| 214 | #define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ | 214 | #define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ |
| 215 | #define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task, | 215 | #define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task, |
| 216 | * not handling interrupts, soon dead */ | 216 | * not handling interrupts, soon dead */ |
| 217 | #define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug | ||
| 218 | * lock is dropped */ | ||
| 217 | 219 | ||
| 218 | /* Used for CPU hotplug events occuring while tasks are frozen due to a suspend | 220 | /* Used for CPU hotplug events occuring while tasks are frozen due to a suspend |
| 219 | * operation in progress | 221 | * operation in progress |
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h index 0e66b57631fc..c8a768e59640 100644 --- a/include/linux/nsproxy.h +++ b/include/linux/nsproxy.h | |||
| @@ -82,9 +82,12 @@ static inline void get_nsproxy(struct nsproxy *ns) | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | #ifdef CONFIG_CGROUP_NS | 84 | #ifdef CONFIG_CGROUP_NS |
| 85 | int ns_cgroup_clone(struct task_struct *tsk); | 85 | int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid); |
| 86 | #else | 86 | #else |
| 87 | static inline int ns_cgroup_clone(struct task_struct *tsk) { return 0; } | 87 | static inline int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid) |
| 88 | { | ||
| 89 | return 0; | ||
| 90 | } | ||
| 88 | #endif | 91 | #endif |
| 89 | 92 | ||
| 90 | #endif | 93 | #endif |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 119ae7b8f028..c3b1761aba26 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2400,6 +2400,9 @@ | |||
| 2400 | #define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 | 2400 | #define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 |
| 2401 | #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 | 2401 | #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 |
| 2402 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f | 2402 | #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f |
| 2403 | #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 | ||
| 2404 | #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 | ||
| 2405 | #define PCI_DEVICE_ID_INTEL_5100_22 0x65f6 | ||
| 2403 | #define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 | 2406 | #define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 |
| 2404 | #define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 | 2407 | #define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 |
| 2405 | #define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 | 2408 | #define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 |
diff --git a/include/linux/pid.h b/include/linux/pid.h index c21c7e8124a7..22921ac4cfd9 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h | |||
| @@ -48,7 +48,7 @@ enum pid_type | |||
| 48 | */ | 48 | */ |
| 49 | 49 | ||
| 50 | struct upid { | 50 | struct upid { |
| 51 | /* Try to keep pid_chain in the same cacheline as nr for find_pid */ | 51 | /* Try to keep pid_chain in the same cacheline as nr for find_vpid */ |
| 52 | int nr; | 52 | int nr; |
| 53 | struct pid_namespace *ns; | 53 | struct pid_namespace *ns; |
| 54 | struct hlist_node pid_chain; | 54 | struct hlist_node pid_chain; |
| @@ -57,10 +57,10 @@ struct upid { | |||
| 57 | struct pid | 57 | struct pid |
| 58 | { | 58 | { |
| 59 | atomic_t count; | 59 | atomic_t count; |
| 60 | unsigned int level; | ||
| 60 | /* lists of tasks that use this pid */ | 61 | /* lists of tasks that use this pid */ |
| 61 | struct hlist_head tasks[PIDTYPE_MAX]; | 62 | struct hlist_head tasks[PIDTYPE_MAX]; |
| 62 | struct rcu_head rcu; | 63 | struct rcu_head rcu; |
| 63 | unsigned int level; | ||
| 64 | struct upid numbers[1]; | 64 | struct upid numbers[1]; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| @@ -105,14 +105,12 @@ extern struct pid_namespace init_pid_ns; | |||
| 105 | * or rcu_read_lock() held. | 105 | * or rcu_read_lock() held. |
| 106 | * | 106 | * |
| 107 | * find_pid_ns() finds the pid in the namespace specified | 107 | * find_pid_ns() finds the pid in the namespace specified |
| 108 | * find_pid() find the pid by its global id, i.e. in the init namespace | ||
| 109 | * find_vpid() finr the pid by its virtual id, i.e. in the current namespace | 108 | * find_vpid() finr the pid by its virtual id, i.e. in the current namespace |
| 110 | * | 109 | * |
| 111 | * see also find_task_by_pid() set in include/linux/sched.h | 110 | * see also find_task_by_vpid() set in include/linux/sched.h |
| 112 | */ | 111 | */ |
| 113 | extern struct pid *find_pid_ns(int nr, struct pid_namespace *ns); | 112 | extern struct pid *find_pid_ns(int nr, struct pid_namespace *ns); |
| 114 | extern struct pid *find_vpid(int nr); | 113 | extern struct pid *find_vpid(int nr); |
| 115 | extern struct pid *find_pid(int nr); | ||
| 116 | 114 | ||
| 117 | /* | 115 | /* |
| 118 | * Lookup a PID in the hash table, and return with it's count elevated. | 116 | * Lookup a PID in the hash table, and return with it's count elevated. |
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index caff5283d15c..1af82c4e17d4 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h | |||
| @@ -14,6 +14,8 @@ struct pidmap { | |||
| 14 | 14 | ||
| 15 | #define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8) | 15 | #define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8) |
| 16 | 16 | ||
| 17 | struct bsd_acct_struct; | ||
| 18 | |||
| 17 | struct pid_namespace { | 19 | struct pid_namespace { |
| 18 | struct kref kref; | 20 | struct kref kref; |
| 19 | struct pidmap pidmap[PIDMAP_ENTRIES]; | 21 | struct pidmap pidmap[PIDMAP_ENTRIES]; |
| @@ -25,6 +27,9 @@ struct pid_namespace { | |||
| 25 | #ifdef CONFIG_PROC_FS | 27 | #ifdef CONFIG_PROC_FS |
| 26 | struct vfsmount *proc_mnt; | 28 | struct vfsmount *proc_mnt; |
| 27 | #endif | 29 | #endif |
| 30 | #ifdef CONFIG_BSD_PROCESS_ACCT | ||
| 31 | struct bsd_acct_struct *bacct; | ||
| 32 | #endif | ||
| 28 | }; | 33 | }; |
| 29 | 34 | ||
| 30 | extern struct pid_namespace init_pid_ns; | 35 | extern struct pid_namespace init_pid_ns; |
| @@ -85,4 +90,7 @@ static inline struct task_struct *task_child_reaper(struct task_struct *tsk) | |||
| 85 | return tsk->nsproxy->pid_ns->child_reaper; | 90 | return tsk->nsproxy->pid_ns->child_reaper; |
| 86 | } | 91 | } |
| 87 | 92 | ||
| 93 | void pidhash_init(void); | ||
| 94 | void pidmap_init(void); | ||
| 95 | |||
| 88 | #endif /* _LINUX_PID_NS_H */ | 96 | #endif /* _LINUX_PID_NS_H */ |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 15a9eaf4a802..f560d1705afe 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
| @@ -79,6 +79,7 @@ struct proc_dir_entry { | |||
| 79 | int pde_users; /* number of callers into module in progress */ | 79 | int pde_users; /* number of callers into module in progress */ |
| 80 | spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ | 80 | spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ |
| 81 | struct completion *pde_unload_completion; | 81 | struct completion *pde_unload_completion; |
| 82 | struct list_head pde_openers; /* who did ->open, but not ->release */ | ||
| 82 | }; | 83 | }; |
| 83 | 84 | ||
| 84 | struct kcore_list { | 85 | struct kcore_list { |
| @@ -138,7 +139,6 @@ extern int proc_readdir(struct file *, void *, filldir_t); | |||
| 138 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *); | 139 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *); |
| 139 | 140 | ||
| 140 | extern const struct file_operations proc_kcore_operations; | 141 | extern const struct file_operations proc_kcore_operations; |
| 141 | extern const struct file_operations proc_kmsg_operations; | ||
| 142 | extern const struct file_operations ppc_htab_operations; | 142 | extern const struct file_operations ppc_htab_operations; |
| 143 | 143 | ||
| 144 | extern int pid_ns_prepare_proc(struct pid_namespace *ns); | 144 | extern int pid_ns_prepare_proc(struct pid_namespace *ns); |
diff --git a/include/linux/profile.h b/include/linux/profile.h index 05c1cc736937..7e7087239af5 100644 --- a/include/linux/profile.h +++ b/include/linux/profile.h | |||
| @@ -8,8 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | #include <asm/errno.h> | 9 | #include <asm/errno.h> |
| 10 | 10 | ||
| 11 | extern int prof_on __read_mostly; | ||
| 12 | |||
| 13 | #define CPU_PROFILING 1 | 11 | #define CPU_PROFILING 1 |
| 14 | #define SCHED_PROFILING 2 | 12 | #define SCHED_PROFILING 2 |
| 15 | #define SLEEP_PROFILING 3 | 13 | #define SLEEP_PROFILING 3 |
| @@ -19,14 +17,31 @@ struct proc_dir_entry; | |||
| 19 | struct pt_regs; | 17 | struct pt_regs; |
| 20 | struct notifier_block; | 18 | struct notifier_block; |
| 21 | 19 | ||
| 20 | #if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS) | ||
| 21 | void create_prof_cpu_mask(struct proc_dir_entry *de); | ||
| 22 | #else | ||
| 23 | static inline void create_prof_cpu_mask(struct proc_dir_entry *de) | ||
| 24 | { | ||
| 25 | } | ||
| 26 | #endif | ||
| 27 | |||
| 28 | enum profile_type { | ||
| 29 | PROFILE_TASK_EXIT, | ||
| 30 | PROFILE_MUNMAP | ||
| 31 | }; | ||
| 32 | |||
| 33 | #ifdef CONFIG_PROFILING | ||
| 34 | |||
| 35 | extern int prof_on __read_mostly; | ||
| 36 | |||
| 22 | /* init basic kernel profiler */ | 37 | /* init basic kernel profiler */ |
| 23 | void __init profile_init(void); | 38 | void __init profile_init(void); |
| 24 | void profile_tick(int); | 39 | void profile_tick(int type); |
| 25 | 40 | ||
| 26 | /* | 41 | /* |
| 27 | * Add multiple profiler hits to a given address: | 42 | * Add multiple profiler hits to a given address: |
| 28 | */ | 43 | */ |
| 29 | void profile_hits(int, void *ip, unsigned int nr_hits); | 44 | void profile_hits(int type, void *ip, unsigned int nr_hits); |
| 30 | 45 | ||
| 31 | /* | 46 | /* |
| 32 | * Single profiler hit: | 47 | * Single profiler hit: |
| @@ -40,19 +55,6 @@ static inline void profile_hit(int type, void *ip) | |||
| 40 | profile_hits(type, ip, 1); | 55 | profile_hits(type, ip, 1); |
| 41 | } | 56 | } |
| 42 | 57 | ||
| 43 | #ifdef CONFIG_PROC_FS | ||
| 44 | void create_prof_cpu_mask(struct proc_dir_entry *); | ||
| 45 | #else | ||
| 46 | #define create_prof_cpu_mask(x) do { (void)(x); } while (0) | ||
| 47 | #endif | ||
| 48 | |||
| 49 | enum profile_type { | ||
| 50 | PROFILE_TASK_EXIT, | ||
| 51 | PROFILE_MUNMAP | ||
| 52 | }; | ||
| 53 | |||
| 54 | #ifdef CONFIG_PROFILING | ||
| 55 | |||
| 56 | struct task_struct; | 58 | struct task_struct; |
| 57 | struct mm_struct; | 59 | struct mm_struct; |
| 58 | 60 | ||
| @@ -80,6 +82,28 @@ struct pt_regs; | |||
| 80 | 82 | ||
| 81 | #else | 83 | #else |
| 82 | 84 | ||
| 85 | #define prof_on 0 | ||
| 86 | |||
| 87 | static inline void profile_init(void) | ||
| 88 | { | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | static inline void profile_tick(int type) | ||
| 93 | { | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | |||
| 97 | static inline void profile_hits(int type, void *ip, unsigned int nr_hits) | ||
| 98 | { | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | |||
| 102 | static inline void profile_hit(int type, void *ip) | ||
| 103 | { | ||
| 104 | return; | ||
| 105 | } | ||
| 106 | |||
| 83 | static inline int task_handoff_register(struct notifier_block * n) | 107 | static inline int task_handoff_register(struct notifier_block * n) |
| 84 | { | 108 | { |
| 85 | return -ENOSYS; | 109 | return -ENOSYS; |
diff --git a/include/linux/quota.h b/include/linux/quota.h index dcddfb200947..376a05048bc5 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
| @@ -41,9 +41,6 @@ | |||
| 41 | #define __DQUOT_VERSION__ "dquot_6.5.1" | 41 | #define __DQUOT_VERSION__ "dquot_6.5.1" |
| 42 | #define __DQUOT_NUM_VERSION__ 6*10000+5*100+1 | 42 | #define __DQUOT_NUM_VERSION__ 6*10000+5*100+1 |
| 43 | 43 | ||
| 44 | typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */ | ||
| 45 | typedef __u64 qsize_t; /* Type in which we store sizes */ | ||
| 46 | |||
| 47 | /* Size of blocks in which are counted size limits */ | 44 | /* Size of blocks in which are counted size limits */ |
| 48 | #define QUOTABLOCK_BITS 10 | 45 | #define QUOTABLOCK_BITS 10 |
| 49 | #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS) | 46 | #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS) |
| @@ -138,6 +135,10 @@ struct if_dqinfo { | |||
| 138 | #define QUOTA_NL_BHARDWARN 4 /* Block hardlimit reached */ | 135 | #define QUOTA_NL_BHARDWARN 4 /* Block hardlimit reached */ |
| 139 | #define QUOTA_NL_BSOFTLONGWARN 5 /* Block grace time expired */ | 136 | #define QUOTA_NL_BSOFTLONGWARN 5 /* Block grace time expired */ |
| 140 | #define QUOTA_NL_BSOFTWARN 6 /* Block softlimit reached */ | 137 | #define QUOTA_NL_BSOFTWARN 6 /* Block softlimit reached */ |
| 138 | #define QUOTA_NL_IHARDBELOW 7 /* Usage got below inode hardlimit */ | ||
| 139 | #define QUOTA_NL_ISOFTBELOW 8 /* Usage got below inode softlimit */ | ||
| 140 | #define QUOTA_NL_BHARDBELOW 9 /* Usage got below block hardlimit */ | ||
| 141 | #define QUOTA_NL_BSOFTBELOW 10 /* Usage got below block softlimit */ | ||
| 141 | 142 | ||
| 142 | enum { | 143 | enum { |
| 143 | QUOTA_NL_C_UNSPEC, | 144 | QUOTA_NL_C_UNSPEC, |
| @@ -172,6 +173,9 @@ enum { | |||
| 172 | 173 | ||
| 173 | #include <asm/atomic.h> | 174 | #include <asm/atomic.h> |
| 174 | 175 | ||
| 176 | typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */ | ||
| 177 | typedef __u64 qsize_t; /* Type in which we store sizes */ | ||
| 178 | |||
| 175 | extern spinlock_t dq_data_lock; | 179 | extern spinlock_t dq_data_lock; |
| 176 | 180 | ||
| 177 | /* Maximal numbers of writes for quota operation (insert/delete/update) | 181 | /* Maximal numbers of writes for quota operation (insert/delete/update) |
| @@ -223,12 +227,10 @@ struct super_block; | |||
| 223 | #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */ | 227 | #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */ |
| 224 | 228 | ||
| 225 | extern void mark_info_dirty(struct super_block *sb, int type); | 229 | extern void mark_info_dirty(struct super_block *sb, int type); |
| 226 | #define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags) | 230 | static inline int info_dirty(struct mem_dqinfo *info) |
| 227 | #define info_any_dquot_dirty(info) (!list_empty(&(info)->dqi_dirty_list)) | 231 | { |
| 228 | #define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info)) | 232 | return test_bit(DQF_INFO_DIRTY_B, &info->dqi_flags); |
| 229 | 233 | } | |
| 230 | #define sb_dqopt(sb) (&(sb)->s_dquot) | ||
| 231 | #define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type)) | ||
| 232 | 234 | ||
| 233 | struct dqstats { | 235 | struct dqstats { |
| 234 | int lookups; | 236 | int lookups; |
| @@ -337,19 +339,6 @@ struct quota_info { | |||
| 337 | struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ | 339 | struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ |
| 338 | }; | 340 | }; |
| 339 | 341 | ||
| 340 | #define sb_has_quota_enabled(sb, type) ((type)==USRQUOTA ? \ | ||
| 341 | (sb_dqopt(sb)->flags & DQUOT_USR_ENABLED) : (sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED)) | ||
| 342 | |||
| 343 | #define sb_any_quota_enabled(sb) (sb_has_quota_enabled(sb, USRQUOTA) | \ | ||
| 344 | sb_has_quota_enabled(sb, GRPQUOTA)) | ||
| 345 | |||
| 346 | #define sb_has_quota_suspended(sb, type) \ | ||
| 347 | ((type) == USRQUOTA ? (sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED) : \ | ||
| 348 | (sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED)) | ||
| 349 | |||
| 350 | #define sb_any_quota_suspended(sb) (sb_has_quota_suspended(sb, USRQUOTA) | \ | ||
| 351 | sb_has_quota_suspended(sb, GRPQUOTA)) | ||
| 352 | |||
| 353 | int register_quota_format(struct quota_format_type *fmt); | 342 | int register_quota_format(struct quota_format_type *fmt); |
| 354 | void unregister_quota_format(struct quota_format_type *fmt); | 343 | void unregister_quota_format(struct quota_format_type *fmt); |
| 355 | 344 | ||
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index f86702053853..742187f7a05c 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
| @@ -11,42 +11,85 @@ | |||
| 11 | #define _LINUX_QUOTAOPS_ | 11 | #define _LINUX_QUOTAOPS_ |
| 12 | 12 | ||
| 13 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
| 14 | |||
| 15 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
| 16 | 15 | ||
| 16 | static inline struct quota_info *sb_dqopt(struct super_block *sb) | ||
| 17 | { | ||
| 18 | return &sb->s_dquot; | ||
| 19 | } | ||
| 20 | |||
| 17 | #if defined(CONFIG_QUOTA) | 21 | #if defined(CONFIG_QUOTA) |
| 18 | 22 | ||
| 19 | /* | 23 | /* |
| 20 | * declaration of quota_function calls in kernel. | 24 | * declaration of quota_function calls in kernel. |
| 21 | */ | 25 | */ |
| 22 | extern void sync_dquots(struct super_block *sb, int type); | 26 | void sync_dquots(struct super_block *sb, int type); |
| 23 | 27 | ||
| 24 | extern int dquot_initialize(struct inode *inode, int type); | 28 | int dquot_initialize(struct inode *inode, int type); |
| 25 | extern int dquot_drop(struct inode *inode); | 29 | int dquot_drop(struct inode *inode); |
| 26 | 30 | ||
| 27 | extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); | 31 | int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); |
| 28 | extern int dquot_alloc_inode(const struct inode *inode, unsigned long number); | 32 | int dquot_alloc_inode(const struct inode *inode, unsigned long number); |
| 29 | 33 | ||
| 30 | extern int dquot_free_space(struct inode *inode, qsize_t number); | 34 | int dquot_free_space(struct inode *inode, qsize_t number); |
| 31 | extern int dquot_free_inode(const struct inode *inode, unsigned long number); | 35 | int dquot_free_inode(const struct inode *inode, unsigned long number); |
| 32 | 36 | ||
| 33 | extern int dquot_transfer(struct inode *inode, struct iattr *iattr); | 37 | int dquot_transfer(struct inode *inode, struct iattr *iattr); |
| 34 | extern int dquot_commit(struct dquot *dquot); | 38 | int dquot_commit(struct dquot *dquot); |
| 35 | extern int dquot_acquire(struct dquot *dquot); | 39 | int dquot_acquire(struct dquot *dquot); |
| 36 | extern int dquot_release(struct dquot *dquot); | 40 | int dquot_release(struct dquot *dquot); |
| 37 | extern int dquot_commit_info(struct super_block *sb, int type); | 41 | int dquot_commit_info(struct super_block *sb, int type); |
| 38 | extern int dquot_mark_dquot_dirty(struct dquot *dquot); | 42 | int dquot_mark_dquot_dirty(struct dquot *dquot); |
| 39 | 43 | ||
| 40 | extern int vfs_quota_on(struct super_block *sb, int type, int format_id, | 44 | int vfs_quota_on(struct super_block *sb, int type, int format_id, |
| 41 | char *path, int remount); | 45 | char *path, int remount); |
| 42 | extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name, | 46 | int vfs_quota_on_mount(struct super_block *sb, char *qf_name, |
| 43 | int format_id, int type); | 47 | int format_id, int type); |
| 44 | extern int vfs_quota_off(struct super_block *sb, int type, int remount); | 48 | int vfs_quota_off(struct super_block *sb, int type, int remount); |
| 45 | extern int vfs_quota_sync(struct super_block *sb, int type); | 49 | int vfs_quota_sync(struct super_block *sb, int type); |
| 46 | extern int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); | 50 | int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); |
| 47 | extern int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); | 51 | int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); |
| 48 | extern int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di); | 52 | int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di); |
| 49 | extern int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di); | 53 | int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di); |
| 54 | |||
| 55 | void vfs_dq_drop(struct inode *inode); | ||
| 56 | int vfs_dq_transfer(struct inode *inode, struct iattr *iattr); | ||
| 57 | int vfs_dq_quota_on_remount(struct super_block *sb); | ||
| 58 | |||
| 59 | static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type) | ||
| 60 | { | ||
| 61 | return sb_dqopt(sb)->info + type; | ||
| 62 | } | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Functions for checking status of quota | ||
| 66 | */ | ||
| 67 | |||
| 68 | static inline int sb_has_quota_enabled(struct super_block *sb, int type) | ||
| 69 | { | ||
| 70 | if (type == USRQUOTA) | ||
| 71 | return sb_dqopt(sb)->flags & DQUOT_USR_ENABLED; | ||
| 72 | return sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED; | ||
| 73 | } | ||
| 74 | |||
| 75 | static inline int sb_any_quota_enabled(struct super_block *sb) | ||
| 76 | { | ||
| 77 | return sb_has_quota_enabled(sb, USRQUOTA) || | ||
| 78 | sb_has_quota_enabled(sb, GRPQUOTA); | ||
| 79 | } | ||
| 80 | |||
| 81 | static inline int sb_has_quota_suspended(struct super_block *sb, int type) | ||
| 82 | { | ||
| 83 | if (type == USRQUOTA) | ||
| 84 | return sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED; | ||
| 85 | return sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED; | ||
| 86 | } | ||
| 87 | |||
| 88 | static inline int sb_any_quota_suspended(struct super_block *sb) | ||
| 89 | { | ||
| 90 | return sb_has_quota_suspended(sb, USRQUOTA) || | ||
| 91 | sb_has_quota_suspended(sb, GRPQUOTA); | ||
| 92 | } | ||
| 50 | 93 | ||
| 51 | /* | 94 | /* |
| 52 | * Operations supported for diskquotas. | 95 | * Operations supported for diskquotas. |
| @@ -59,38 +102,16 @@ extern struct quotactl_ops vfs_quotactl_ops; | |||
| 59 | 102 | ||
| 60 | /* It is better to call this function outside of any transaction as it might | 103 | /* It is better to call this function outside of any transaction as it might |
| 61 | * need a lot of space in journal for dquot structure allocation. */ | 104 | * need a lot of space in journal for dquot structure allocation. */ |
| 62 | static inline void DQUOT_INIT(struct inode *inode) | 105 | static inline void vfs_dq_init(struct inode *inode) |
| 63 | { | 106 | { |
| 64 | BUG_ON(!inode->i_sb); | 107 | BUG_ON(!inode->i_sb); |
| 65 | if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) | 108 | if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) |
| 66 | inode->i_sb->dq_op->initialize(inode, -1); | 109 | inode->i_sb->dq_op->initialize(inode, -1); |
| 67 | } | 110 | } |
| 68 | 111 | ||
| 69 | /* The same as with DQUOT_INIT */ | ||
| 70 | static inline void DQUOT_DROP(struct inode *inode) | ||
| 71 | { | ||
| 72 | /* Here we can get arbitrary inode from clear_inode() so we have | ||
| 73 | * to be careful. OTOH we don't need locking as quota operations | ||
| 74 | * are allowed to change only at mount time */ | ||
| 75 | if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op | ||
| 76 | && inode->i_sb->dq_op->drop) { | ||
| 77 | int cnt; | ||
| 78 | /* Test before calling to rule out calls from proc and such | ||
| 79 | * where we are not allowed to block. Note that this is | ||
| 80 | * actually reliable test even without the lock - the caller | ||
| 81 | * must assure that nobody can come after the DQUOT_DROP and | ||
| 82 | * add quota pointers back anyway */ | ||
| 83 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | ||
| 84 | if (inode->i_dquot[cnt] != NODQUOT) | ||
| 85 | break; | ||
| 86 | if (cnt < MAXQUOTAS) | ||
| 87 | inode->i_sb->dq_op->drop(inode); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | /* The following allocation/freeing/transfer functions *must* be called inside | 112 | /* The following allocation/freeing/transfer functions *must* be called inside |
| 92 | * a transaction (deadlocks possible otherwise) */ | 113 | * a transaction (deadlocks possible otherwise) */ |
| 93 | static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | 114 | static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr) |
| 94 | { | 115 | { |
| 95 | if (sb_any_quota_enabled(inode->i_sb)) { | 116 | if (sb_any_quota_enabled(inode->i_sb)) { |
| 96 | /* Used space is updated in alloc_space() */ | 117 | /* Used space is updated in alloc_space() */ |
| @@ -102,15 +123,15 @@ static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | |||
| 102 | return 0; | 123 | return 0; |
| 103 | } | 124 | } |
| 104 | 125 | ||
| 105 | static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) | 126 | static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr) |
| 106 | { | 127 | { |
| 107 | int ret; | 128 | int ret; |
| 108 | if (!(ret = DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr))) | 129 | if (!(ret = vfs_dq_prealloc_space_nodirty(inode, nr))) |
| 109 | mark_inode_dirty(inode); | 130 | mark_inode_dirty(inode); |
| 110 | return ret; | 131 | return ret; |
| 111 | } | 132 | } |
| 112 | 133 | ||
| 113 | static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | 134 | static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr) |
| 114 | { | 135 | { |
| 115 | if (sb_any_quota_enabled(inode->i_sb)) { | 136 | if (sb_any_quota_enabled(inode->i_sb)) { |
| 116 | /* Used space is updated in alloc_space() */ | 137 | /* Used space is updated in alloc_space() */ |
| @@ -122,25 +143,25 @@ static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | |||
| 122 | return 0; | 143 | return 0; |
| 123 | } | 144 | } |
| 124 | 145 | ||
| 125 | static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) | 146 | static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) |
| 126 | { | 147 | { |
| 127 | int ret; | 148 | int ret; |
| 128 | if (!(ret = DQUOT_ALLOC_SPACE_NODIRTY(inode, nr))) | 149 | if (!(ret = vfs_dq_alloc_space_nodirty(inode, nr))) |
| 129 | mark_inode_dirty(inode); | 150 | mark_inode_dirty(inode); |
| 130 | return ret; | 151 | return ret; |
| 131 | } | 152 | } |
| 132 | 153 | ||
| 133 | static inline int DQUOT_ALLOC_INODE(struct inode *inode) | 154 | static inline int vfs_dq_alloc_inode(struct inode *inode) |
| 134 | { | 155 | { |
| 135 | if (sb_any_quota_enabled(inode->i_sb)) { | 156 | if (sb_any_quota_enabled(inode->i_sb)) { |
| 136 | DQUOT_INIT(inode); | 157 | vfs_dq_init(inode); |
| 137 | if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) | 158 | if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) |
| 138 | return 1; | 159 | return 1; |
| 139 | } | 160 | } |
| 140 | return 0; | 161 | return 0; |
| 141 | } | 162 | } |
| 142 | 163 | ||
| 143 | static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | 164 | static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) |
| 144 | { | 165 | { |
| 145 | if (sb_any_quota_enabled(inode->i_sb)) | 166 | if (sb_any_quota_enabled(inode->i_sb)) |
| 146 | inode->i_sb->dq_op->free_space(inode, nr); | 167 | inode->i_sb->dq_op->free_space(inode, nr); |
| @@ -148,35 +169,25 @@ static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | |||
| 148 | inode_sub_bytes(inode, nr); | 169 | inode_sub_bytes(inode, nr); |
| 149 | } | 170 | } |
| 150 | 171 | ||
| 151 | static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) | 172 | static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr) |
| 152 | { | 173 | { |
| 153 | DQUOT_FREE_SPACE_NODIRTY(inode, nr); | 174 | vfs_dq_free_space_nodirty(inode, nr); |
| 154 | mark_inode_dirty(inode); | 175 | mark_inode_dirty(inode); |
| 155 | } | 176 | } |
| 156 | 177 | ||
| 157 | static inline void DQUOT_FREE_INODE(struct inode *inode) | 178 | static inline void vfs_dq_free_inode(struct inode *inode) |
| 158 | { | 179 | { |
| 159 | if (sb_any_quota_enabled(inode->i_sb)) | 180 | if (sb_any_quota_enabled(inode->i_sb)) |
| 160 | inode->i_sb->dq_op->free_inode(inode, 1); | 181 | inode->i_sb->dq_op->free_inode(inode, 1); |
| 161 | } | 182 | } |
| 162 | 183 | ||
| 163 | static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr) | ||
| 164 | { | ||
| 165 | if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) { | ||
| 166 | DQUOT_INIT(inode); | ||
| 167 | if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA) | ||
| 168 | return 1; | ||
| 169 | } | ||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | /* The following two functions cannot be called inside a transaction */ | 184 | /* The following two functions cannot be called inside a transaction */ |
| 174 | static inline void DQUOT_SYNC(struct super_block *sb) | 185 | static inline void vfs_dq_sync(struct super_block *sb) |
| 175 | { | 186 | { |
| 176 | sync_dquots(sb, -1); | 187 | sync_dquots(sb, -1); |
| 177 | } | 188 | } |
| 178 | 189 | ||
| 179 | static inline int DQUOT_OFF(struct super_block *sb, int remount) | 190 | static inline int vfs_dq_off(struct super_block *sb, int remount) |
| 180 | { | 191 | { |
| 181 | int ret = -ENOSYS; | 192 | int ret = -ENOSYS; |
| 182 | 193 | ||
| @@ -185,22 +196,27 @@ static inline int DQUOT_OFF(struct super_block *sb, int remount) | |||
| 185 | return ret; | 196 | return ret; |
| 186 | } | 197 | } |
| 187 | 198 | ||
| 188 | static inline int DQUOT_ON_REMOUNT(struct super_block *sb) | 199 | #else |
| 200 | |||
| 201 | static inline int sb_has_quota_enabled(struct super_block *sb, int type) | ||
| 189 | { | 202 | { |
| 190 | int cnt; | 203 | return 0; |
| 191 | int ret = 0, err; | 204 | } |
| 192 | 205 | ||
| 193 | if (!sb->s_qcop || !sb->s_qcop->quota_on) | 206 | static inline int sb_any_quota_enabled(struct super_block *sb) |
| 194 | return -ENOSYS; | 207 | { |
| 195 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 208 | return 0; |
| 196 | err = sb->s_qcop->quota_on(sb, cnt, 0, NULL, 1); | ||
| 197 | if (err < 0 && !ret) | ||
| 198 | ret = err; | ||
| 199 | } | ||
| 200 | return ret; | ||
| 201 | } | 209 | } |
| 202 | 210 | ||
| 203 | #else | 211 | static inline int sb_has_quota_suspended(struct super_block *sb, int type) |
| 212 | { | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static inline int sb_any_quota_suspended(struct super_block *sb) | ||
| 217 | { | ||
| 218 | return 0; | ||
| 219 | } | ||
| 204 | 220 | ||
| 205 | /* | 221 | /* |
| 206 | * NO-OP when quota not configured. | 222 | * NO-OP when quota not configured. |
| @@ -208,113 +224,144 @@ static inline int DQUOT_ON_REMOUNT(struct super_block *sb) | |||
| 208 | #define sb_dquot_ops (NULL) | 224 | #define sb_dquot_ops (NULL) |
| 209 | #define sb_quotactl_ops (NULL) | 225 | #define sb_quotactl_ops (NULL) |
| 210 | 226 | ||
| 211 | static inline void DQUOT_INIT(struct inode *inode) | 227 | static inline void vfs_dq_init(struct inode *inode) |
| 212 | { | 228 | { |
| 213 | } | 229 | } |
| 214 | 230 | ||
| 215 | static inline void DQUOT_DROP(struct inode *inode) | 231 | static inline void vfs_dq_drop(struct inode *inode) |
| 216 | { | 232 | { |
| 217 | } | 233 | } |
| 218 | 234 | ||
| 219 | static inline int DQUOT_ALLOC_INODE(struct inode *inode) | 235 | static inline int vfs_dq_alloc_inode(struct inode *inode) |
| 220 | { | 236 | { |
| 221 | return 0; | 237 | return 0; |
| 222 | } | 238 | } |
| 223 | 239 | ||
| 224 | static inline void DQUOT_FREE_INODE(struct inode *inode) | 240 | static inline void vfs_dq_free_inode(struct inode *inode) |
| 225 | { | 241 | { |
| 226 | } | 242 | } |
| 227 | 243 | ||
| 228 | static inline void DQUOT_SYNC(struct super_block *sb) | 244 | static inline void vfs_dq_sync(struct super_block *sb) |
| 229 | { | 245 | { |
| 230 | } | 246 | } |
| 231 | 247 | ||
| 232 | static inline int DQUOT_OFF(struct super_block *sb, int remount) | 248 | static inline int vfs_dq_off(struct super_block *sb, int remount) |
| 233 | { | 249 | { |
| 234 | return 0; | 250 | return 0; |
| 235 | } | 251 | } |
| 236 | 252 | ||
| 237 | static inline int DQUOT_ON_REMOUNT(struct super_block *sb) | 253 | static inline int vfs_dq_quota_on_remount(struct super_block *sb) |
| 238 | { | 254 | { |
| 239 | return 0; | 255 | return 0; |
| 240 | } | 256 | } |
| 241 | 257 | ||
| 242 | static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr) | 258 | static inline int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) |
| 243 | { | 259 | { |
| 244 | return 0; | 260 | return 0; |
| 245 | } | 261 | } |
| 246 | 262 | ||
| 247 | static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | 263 | static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr) |
| 248 | { | 264 | { |
| 249 | inode_add_bytes(inode, nr); | 265 | inode_add_bytes(inode, nr); |
| 250 | return 0; | 266 | return 0; |
| 251 | } | 267 | } |
| 252 | 268 | ||
| 253 | static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) | 269 | static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr) |
| 254 | { | 270 | { |
| 255 | DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr); | 271 | vfs_dq_prealloc_space_nodirty(inode, nr); |
| 256 | mark_inode_dirty(inode); | 272 | mark_inode_dirty(inode); |
| 257 | return 0; | 273 | return 0; |
| 258 | } | 274 | } |
| 259 | 275 | ||
| 260 | static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | 276 | static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr) |
| 261 | { | 277 | { |
| 262 | inode_add_bytes(inode, nr); | 278 | inode_add_bytes(inode, nr); |
| 263 | return 0; | 279 | return 0; |
| 264 | } | 280 | } |
| 265 | 281 | ||
| 266 | static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) | 282 | static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) |
| 267 | { | 283 | { |
| 268 | DQUOT_ALLOC_SPACE_NODIRTY(inode, nr); | 284 | vfs_dq_alloc_space_nodirty(inode, nr); |
| 269 | mark_inode_dirty(inode); | 285 | mark_inode_dirty(inode); |
| 270 | return 0; | 286 | return 0; |
| 271 | } | 287 | } |
| 272 | 288 | ||
| 273 | static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) | 289 | static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) |
| 274 | { | 290 | { |
| 275 | inode_sub_bytes(inode, nr); | 291 | inode_sub_bytes(inode, nr); |
| 276 | } | 292 | } |
| 277 | 293 | ||
| 278 | static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) | 294 | static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr) |
| 279 | { | 295 | { |
| 280 | DQUOT_FREE_SPACE_NODIRTY(inode, nr); | 296 | vfs_dq_free_space_nodirty(inode, nr); |
| 281 | mark_inode_dirty(inode); | 297 | mark_inode_dirty(inode); |
| 282 | } | 298 | } |
| 283 | 299 | ||
| 284 | #endif /* CONFIG_QUOTA */ | 300 | #endif /* CONFIG_QUOTA */ |
| 285 | 301 | ||
| 286 | static inline int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr) | 302 | static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr) |
| 287 | { | 303 | { |
| 288 | return DQUOT_PREALLOC_SPACE_NODIRTY(inode, | 304 | return vfs_dq_prealloc_space_nodirty(inode, |
| 289 | nr << inode->i_sb->s_blocksize_bits); | 305 | nr << inode->i_sb->s_blocksize_bits); |
| 290 | } | 306 | } |
| 291 | 307 | ||
| 292 | static inline int DQUOT_PREALLOC_BLOCK(struct inode *inode, qsize_t nr) | 308 | static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr) |
| 293 | { | 309 | { |
| 294 | return DQUOT_PREALLOC_SPACE(inode, | 310 | return vfs_dq_prealloc_space(inode, |
| 295 | nr << inode->i_sb->s_blocksize_bits); | 311 | nr << inode->i_sb->s_blocksize_bits); |
| 296 | } | 312 | } |
| 297 | 313 | ||
| 298 | static inline int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr) | 314 | static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr) |
| 299 | { | 315 | { |
| 300 | return DQUOT_ALLOC_SPACE_NODIRTY(inode, | 316 | return vfs_dq_alloc_space_nodirty(inode, |
| 301 | nr << inode->i_sb->s_blocksize_bits); | 317 | nr << inode->i_sb->s_blocksize_bits); |
| 302 | } | 318 | } |
| 303 | 319 | ||
| 304 | static inline int DQUOT_ALLOC_BLOCK(struct inode *inode, qsize_t nr) | 320 | static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr) |
| 305 | { | 321 | { |
| 306 | return DQUOT_ALLOC_SPACE(inode, | 322 | return vfs_dq_alloc_space(inode, |
| 307 | nr << inode->i_sb->s_blocksize_bits); | 323 | nr << inode->i_sb->s_blocksize_bits); |
| 308 | } | 324 | } |
| 309 | 325 | ||
| 310 | static inline void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, qsize_t nr) | 326 | static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) |
| 311 | { | 327 | { |
| 312 | DQUOT_FREE_SPACE_NODIRTY(inode, nr << inode->i_sb->s_blocksize_bits); | 328 | vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); |
| 313 | } | 329 | } |
| 314 | 330 | ||
| 315 | static inline void DQUOT_FREE_BLOCK(struct inode *inode, qsize_t nr) | 331 | static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr) |
| 316 | { | 332 | { |
| 317 | DQUOT_FREE_SPACE(inode, nr << inode->i_sb->s_blocksize_bits); | 333 | vfs_dq_free_space(inode, nr << inode->i_sb->s_blocksize_bits); |
| 318 | } | 334 | } |
| 319 | 335 | ||
| 336 | /* | ||
| 337 | * Define uppercase equivalents for compatibility with old function names | ||
| 338 | * Can go away when we think all users have been converted (15/04/2008) | ||
| 339 | */ | ||
| 340 | #define DQUOT_INIT(inode) vfs_dq_init(inode) | ||
| 341 | #define DQUOT_DROP(inode) vfs_dq_drop(inode) | ||
| 342 | #define DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr) \ | ||
| 343 | vfs_dq_prealloc_space_nodirty(inode, nr) | ||
| 344 | #define DQUOT_PREALLOC_SPACE(inode, nr) vfs_dq_prealloc_space(inode, nr) | ||
| 345 | #define DQUOT_ALLOC_SPACE_NODIRTY(inode, nr) \ | ||
| 346 | vfs_dq_alloc_space_nodirty(inode, nr) | ||
| 347 | #define DQUOT_ALLOC_SPACE(inode, nr) vfs_dq_alloc_space(inode, nr) | ||
| 348 | #define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) \ | ||
| 349 | vfs_dq_prealloc_block_nodirty(inode, nr) | ||
| 350 | #define DQUOT_PREALLOC_BLOCK(inode, nr) vfs_dq_prealloc_block(inode, nr) | ||
| 351 | #define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) \ | ||
| 352 | vfs_dq_alloc_block_nodirty(inode, nr) | ||
| 353 | #define DQUOT_ALLOC_BLOCK(inode, nr) vfs_dq_alloc_block(inode, nr) | ||
| 354 | #define DQUOT_ALLOC_INODE(inode) vfs_dq_alloc_inode(inode) | ||
| 355 | #define DQUOT_FREE_SPACE_NODIRTY(inode, nr) \ | ||
| 356 | vfs_dq_free_space_nodirty(inode, nr) | ||
| 357 | #define DQUOT_FREE_SPACE(inode, nr) vfs_dq_free_space(inode, nr) | ||
| 358 | #define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) \ | ||
| 359 | vfs_dq_free_block_nodirty(inode, nr) | ||
| 360 | #define DQUOT_FREE_BLOCK(inode, nr) vfs_dq_free_block(inode, nr) | ||
| 361 | #define DQUOT_FREE_INODE(inode) vfs_dq_free_inode(inode) | ||
| 362 | #define DQUOT_TRANSFER(inode, iattr) vfs_dq_transfer(inode, iattr) | ||
| 363 | #define DQUOT_SYNC(sb) vfs_dq_sync(sb) | ||
| 364 | #define DQUOT_OFF(sb, remount) vfs_dq_off(sb, remount) | ||
| 365 | #define DQUOT_ON_REMOUNT(sb) vfs_dq_quota_on_remount(sb) | ||
| 366 | |||
| 320 | #endif /* _LINUX_QUOTAOPS_ */ | 367 | #endif /* _LINUX_QUOTAOPS_ */ |
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h new file mode 100644 index 000000000000..18a5b9ba9d40 --- /dev/null +++ b/include/linux/ratelimit.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef _LINUX_RATELIMIT_H | ||
| 2 | #define _LINUX_RATELIMIT_H | ||
| 3 | #include <linux/param.h> | ||
| 4 | |||
| 5 | #define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) | ||
| 6 | #define DEFAULT_RATELIMIT_BURST 10 | ||
| 7 | |||
| 8 | struct ratelimit_state { | ||
| 9 | int interval; | ||
| 10 | int burst; | ||
| 11 | int printed; | ||
| 12 | int missed; | ||
| 13 | unsigned long begin; | ||
| 14 | }; | ||
| 15 | |||
| 16 | #define DEFINE_RATELIMIT_STATE(name, interval, burst) \ | ||
| 17 | struct ratelimit_state name = {interval, burst,} | ||
| 18 | |||
| 19 | extern int __ratelimit(struct ratelimit_state *rs); | ||
| 20 | |||
| 21 | static inline int ratelimit(void) | ||
| 22 | { | ||
| 23 | static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, | ||
| 24 | DEFAULT_RATELIMIT_BURST); | ||
| 25 | return __ratelimit(&rs); | ||
| 26 | } | ||
| 27 | #endif | ||
diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h index f04b64eca636..0967f03b0705 100644 --- a/include/linux/rcupreempt.h +++ b/include/linux/rcupreempt.h | |||
| @@ -115,16 +115,21 @@ DECLARE_PER_CPU(struct rcu_dyntick_sched, rcu_dyntick_sched); | |||
| 115 | 115 | ||
| 116 | static inline void rcu_enter_nohz(void) | 116 | static inline void rcu_enter_nohz(void) |
| 117 | { | 117 | { |
| 118 | static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1); | ||
| 119 | |||
| 118 | smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */ | 120 | smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */ |
| 119 | __get_cpu_var(rcu_dyntick_sched).dynticks++; | 121 | __get_cpu_var(rcu_dyntick_sched).dynticks++; |
| 120 | WARN_ON(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1); | 122 | WARN_ON_RATELIMIT(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1, &rs); |
| 121 | } | 123 | } |
| 122 | 124 | ||
| 123 | static inline void rcu_exit_nohz(void) | 125 | static inline void rcu_exit_nohz(void) |
| 124 | { | 126 | { |
| 127 | static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1); | ||
| 128 | |||
| 125 | smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ | 129 | smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ |
| 126 | __get_cpu_var(rcu_dyntick_sched).dynticks++; | 130 | __get_cpu_var(rcu_dyntick_sched).dynticks++; |
| 127 | WARN_ON(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1)); | 131 | WARN_ON_RATELIMIT(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1), |
| 132 | &rs); | ||
| 128 | } | 133 | } |
| 129 | 134 | ||
| 130 | #else /* CONFIG_NO_HZ */ | 135 | #else /* CONFIG_NO_HZ */ |
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 4aacaeecb56f..e9963af16cda 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h | |||
| @@ -526,8 +526,8 @@ struct item_head { | |||
| 526 | ** p is the array of __u32, i is the index into the array, v is the value | 526 | ** p is the array of __u32, i is the index into the array, v is the value |
| 527 | ** to store there. | 527 | ** to store there. |
| 528 | */ | 528 | */ |
| 529 | #define get_block_num(p, i) le32_to_cpu(get_unaligned((p) + (i))) | 529 | #define get_block_num(p, i) get_unaligned_le32((p) + (i)) |
| 530 | #define put_block_num(p, i, v) put_unaligned(cpu_to_le32(v), (p) + (i)) | 530 | #define put_block_num(p, i, v) put_unaligned_le32((v), (p) + (i)) |
| 531 | 531 | ||
| 532 | // | 532 | // |
| 533 | // in old version uniqueness field shows key type | 533 | // in old version uniqueness field shows key type |
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 336ee43ed7d8..315517e8bfa1 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h | |||
| @@ -152,7 +152,7 @@ struct reiserfs_journal_list { | |||
| 152 | atomic_t j_nonzerolen; | 152 | atomic_t j_nonzerolen; |
| 153 | atomic_t j_commit_left; | 153 | atomic_t j_commit_left; |
| 154 | atomic_t j_older_commits_done; /* all commits older than this on disk */ | 154 | atomic_t j_older_commits_done; /* all commits older than this on disk */ |
| 155 | struct semaphore j_commit_lock; | 155 | struct mutex j_commit_mutex; |
| 156 | unsigned long j_trans_id; | 156 | unsigned long j_trans_id; |
| 157 | time_t j_timestamp; | 157 | time_t j_timestamp; |
| 158 | struct reiserfs_list_bitmap *j_list_bitmap; | 158 | struct reiserfs_list_bitmap *j_list_bitmap; |
| @@ -193,8 +193,8 @@ struct reiserfs_journal { | |||
| 193 | struct buffer_head *j_header_bh; | 193 | struct buffer_head *j_header_bh; |
| 194 | 194 | ||
| 195 | time_t j_trans_start_time; /* time this transaction started */ | 195 | time_t j_trans_start_time; /* time this transaction started */ |
| 196 | struct semaphore j_lock; | 196 | struct mutex j_mutex; |
| 197 | struct semaphore j_flush_sem; | 197 | struct mutex j_flush_mutex; |
| 198 | wait_queue_head_t j_join_wait; /* wait for current transaction to finish before starting new one */ | 198 | wait_queue_head_t j_join_wait; /* wait for current transaction to finish before starting new one */ |
| 199 | atomic_t j_jlock; /* lock for j_join_wait */ | 199 | atomic_t j_jlock; /* lock for j_join_wait */ |
| 200 | int j_list_bitmap_index; /* number of next list bitmap to use */ | 200 | int j_list_bitmap_index; /* number of next list bitmap to use */ |
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h index 6d9e1fca098c..fdeadd9740dc 100644 --- a/include/linux/res_counter.h +++ b/include/linux/res_counter.h | |||
| @@ -63,9 +63,14 @@ u64 res_counter_read_u64(struct res_counter *counter, int member); | |||
| 63 | ssize_t res_counter_read(struct res_counter *counter, int member, | 63 | ssize_t res_counter_read(struct res_counter *counter, int member, |
| 64 | const char __user *buf, size_t nbytes, loff_t *pos, | 64 | const char __user *buf, size_t nbytes, loff_t *pos, |
| 65 | int (*read_strategy)(unsigned long long val, char *s)); | 65 | int (*read_strategy)(unsigned long long val, char *s)); |
| 66 | ssize_t res_counter_write(struct res_counter *counter, int member, | 66 | |
| 67 | const char __user *buf, size_t nbytes, loff_t *pos, | 67 | typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val); |
| 68 | int (*write_strategy)(char *buf, unsigned long long *val)); | 68 | |
| 69 | int res_counter_memparse_write_strategy(const char *buf, | ||
| 70 | unsigned long long *res); | ||
| 71 | |||
| 72 | int res_counter_write(struct res_counter *counter, int member, | ||
| 73 | const char *buffer, write_strategy_fn write_strategy); | ||
| 69 | 74 | ||
| 70 | /* | 75 | /* |
| 71 | * the field descriptors. one for each member of res_counter | 76 | * the field descriptors. one for each member of res_counter |
| @@ -95,8 +100,10 @@ void res_counter_init(struct res_counter *counter); | |||
| 95 | * counter->limit _locked call expects the counter->lock to be taken | 100 | * counter->limit _locked call expects the counter->lock to be taken |
| 96 | */ | 101 | */ |
| 97 | 102 | ||
| 98 | int res_counter_charge_locked(struct res_counter *counter, unsigned long val); | 103 | int __must_check res_counter_charge_locked(struct res_counter *counter, |
| 99 | int res_counter_charge(struct res_counter *counter, unsigned long val); | 104 | unsigned long val); |
| 105 | int __must_check res_counter_charge(struct res_counter *counter, | ||
| 106 | unsigned long val); | ||
| 100 | 107 | ||
| 101 | /* | 108 | /* |
| 102 | * uncharge - tell that some portion of the resource is released | 109 | * uncharge - tell that some portion of the resource is released |
| @@ -151,4 +158,20 @@ static inline void res_counter_reset_failcnt(struct res_counter *cnt) | |||
| 151 | cnt->failcnt = 0; | 158 | cnt->failcnt = 0; |
| 152 | spin_unlock_irqrestore(&cnt->lock, flags); | 159 | spin_unlock_irqrestore(&cnt->lock, flags); |
| 153 | } | 160 | } |
| 161 | |||
| 162 | static inline int res_counter_set_limit(struct res_counter *cnt, | ||
| 163 | unsigned long long limit) | ||
| 164 | { | ||
| 165 | unsigned long flags; | ||
| 166 | int ret = -EBUSY; | ||
| 167 | |||
| 168 | spin_lock_irqsave(&cnt->lock, flags); | ||
| 169 | if (cnt->usage < limit) { | ||
| 170 | cnt->limit = limit; | ||
| 171 | ret = 0; | ||
| 172 | } | ||
| 173 | spin_unlock_irqrestore(&cnt->lock, flags); | ||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 154 | #endif | 177 | #endif |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 6aca4a16e377..42036ffe6b00 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -506,6 +506,10 @@ struct signal_struct { | |||
| 506 | unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; | 506 | unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; |
| 507 | unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; | 507 | unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; |
| 508 | unsigned long inblock, oublock, cinblock, coublock; | 508 | unsigned long inblock, oublock, cinblock, coublock; |
| 509 | #ifdef CONFIG_TASK_XACCT | ||
| 510 | u64 rchar, wchar, syscr, syscw; | ||
| 511 | #endif | ||
| 512 | struct task_io_accounting ioac; | ||
| 509 | 513 | ||
| 510 | /* | 514 | /* |
| 511 | * Cumulative ns of scheduled CPU time for dead threads in the | 515 | * Cumulative ns of scheduled CPU time for dead threads in the |
| @@ -668,6 +672,10 @@ struct task_delay_info { | |||
| 668 | /* io operations performed */ | 672 | /* io operations performed */ |
| 669 | u32 swapin_count; /* total count of the number of swapin block */ | 673 | u32 swapin_count; /* total count of the number of swapin block */ |
| 670 | /* io operations performed */ | 674 | /* io operations performed */ |
| 675 | |||
| 676 | struct timespec freepages_start, freepages_end; | ||
| 677 | u64 freepages_delay; /* wait for memory reclaim */ | ||
| 678 | u32 freepages_count; /* total count of memory reclaim */ | ||
| 671 | }; | 679 | }; |
| 672 | #endif /* CONFIG_TASK_DELAY_ACCT */ | 680 | #endif /* CONFIG_TASK_DELAY_ACCT */ |
| 673 | 681 | ||
| @@ -1257,7 +1265,7 @@ struct task_struct { | |||
| 1257 | #if defined(CONFIG_TASK_XACCT) | 1265 | #if defined(CONFIG_TASK_XACCT) |
| 1258 | u64 acct_rss_mem1; /* accumulated rss usage */ | 1266 | u64 acct_rss_mem1; /* accumulated rss usage */ |
| 1259 | u64 acct_vm_mem1; /* accumulated virtual memory usage */ | 1267 | u64 acct_vm_mem1; /* accumulated virtual memory usage */ |
| 1260 | cputime_t acct_stimexpd;/* stime since last update */ | 1268 | cputime_t acct_timexpd; /* stime + utime since last update */ |
| 1261 | #endif | 1269 | #endif |
| 1262 | #ifdef CONFIG_CPUSETS | 1270 | #ifdef CONFIG_CPUSETS |
| 1263 | nodemask_t mems_allowed; | 1271 | nodemask_t mems_allowed; |
| @@ -1496,7 +1504,7 @@ static inline void put_task_struct(struct task_struct *t) | |||
| 1496 | #define PF_KSWAPD 0x00040000 /* I am kswapd */ | 1504 | #define PF_KSWAPD 0x00040000 /* I am kswapd */ |
| 1497 | #define PF_SWAPOFF 0x00080000 /* I am in swapoff */ | 1505 | #define PF_SWAPOFF 0x00080000 /* I am in swapoff */ |
| 1498 | #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ | 1506 | #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ |
| 1499 | #define PF_BORROWED_MM 0x00200000 /* I am a kthread doing use_mm */ | 1507 | #define PF_KTHREAD 0x00200000 /* I am a kernel thread */ |
| 1500 | #define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */ | 1508 | #define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */ |
| 1501 | #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ | 1509 | #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ |
| 1502 | #define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */ | 1510 | #define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */ |
| @@ -1715,19 +1723,13 @@ extern struct pid_namespace init_pid_ns; | |||
| 1715 | * finds a task by its pid in the specified namespace | 1723 | * finds a task by its pid in the specified namespace |
| 1716 | * find_task_by_vpid(): | 1724 | * find_task_by_vpid(): |
| 1717 | * finds a task by its virtual pid | 1725 | * finds a task by its virtual pid |
| 1718 | * find_task_by_pid(): | ||
| 1719 | * finds a task by its global pid | ||
| 1720 | * | 1726 | * |
| 1721 | * see also find_pid() etc in include/linux/pid.h | 1727 | * see also find_vpid() etc in include/linux/pid.h |
| 1722 | */ | 1728 | */ |
| 1723 | 1729 | ||
| 1724 | extern struct task_struct *find_task_by_pid_type_ns(int type, int pid, | 1730 | extern struct task_struct *find_task_by_pid_type_ns(int type, int pid, |
| 1725 | struct pid_namespace *ns); | 1731 | struct pid_namespace *ns); |
| 1726 | 1732 | ||
| 1727 | static inline struct task_struct *__deprecated find_task_by_pid(pid_t nr) | ||
| 1728 | { | ||
| 1729 | return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns); | ||
| 1730 | } | ||
| 1731 | extern struct task_struct *find_task_by_vpid(pid_t nr); | 1733 | extern struct task_struct *find_task_by_vpid(pid_t nr); |
| 1732 | extern struct task_struct *find_task_by_pid_ns(pid_t nr, | 1734 | extern struct task_struct *find_task_by_pid_ns(pid_t nr, |
| 1733 | struct pid_namespace *ns); | 1735 | struct pid_namespace *ns); |
| @@ -1800,7 +1802,6 @@ extern void force_sig(int, struct task_struct *); | |||
| 1800 | extern void force_sig_specific(int, struct task_struct *); | 1802 | extern void force_sig_specific(int, struct task_struct *); |
| 1801 | extern int send_sig(int, struct task_struct *, int); | 1803 | extern int send_sig(int, struct task_struct *, int); |
| 1802 | extern void zap_other_threads(struct task_struct *p); | 1804 | extern void zap_other_threads(struct task_struct *p); |
| 1803 | extern int kill_proc(pid_t, int, int); | ||
| 1804 | extern struct sigqueue *sigqueue_alloc(void); | 1805 | extern struct sigqueue *sigqueue_alloc(void); |
| 1805 | extern void sigqueue_free(struct sigqueue *); | 1806 | extern void sigqueue_free(struct sigqueue *); |
| 1806 | extern int send_sigqueue(struct sigqueue *, struct task_struct *, int group); | 1807 | extern int send_sigqueue(struct sigqueue *, struct task_struct *, int group); |
| @@ -2054,9 +2055,6 @@ static inline int signal_pending_state(long state, struct task_struct *p) | |||
| 2054 | if (!signal_pending(p)) | 2055 | if (!signal_pending(p)) |
| 2055 | return 0; | 2056 | return 0; |
| 2056 | 2057 | ||
| 2057 | if (state & (__TASK_STOPPED | __TASK_TRACED)) | ||
| 2058 | return 0; | ||
| 2059 | |||
| 2060 | return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p); | 2058 | return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p); |
| 2061 | } | 2059 | } |
| 2062 | 2060 | ||
diff --git a/include/linux/sem.h b/include/linux/sem.h index c8eaad9e4b72..1b191c176bcd 100644 --- a/include/linux/sem.h +++ b/include/linux/sem.h | |||
| @@ -78,6 +78,7 @@ struct seminfo { | |||
| 78 | 78 | ||
| 79 | #ifdef __KERNEL__ | 79 | #ifdef __KERNEL__ |
| 80 | #include <asm/atomic.h> | 80 | #include <asm/atomic.h> |
| 81 | #include <linux/rcupdate.h> | ||
| 81 | 82 | ||
| 82 | struct task_struct; | 83 | struct task_struct; |
| 83 | 84 | ||
| @@ -93,23 +94,19 @@ struct sem_array { | |||
| 93 | time_t sem_otime; /* last semop time */ | 94 | time_t sem_otime; /* last semop time */ |
| 94 | time_t sem_ctime; /* last change time */ | 95 | time_t sem_ctime; /* last change time */ |
| 95 | struct sem *sem_base; /* ptr to first semaphore in array */ | 96 | struct sem *sem_base; /* ptr to first semaphore in array */ |
| 96 | struct sem_queue *sem_pending; /* pending operations to be processed */ | 97 | struct list_head sem_pending; /* pending operations to be processed */ |
| 97 | struct sem_queue **sem_pending_last; /* last pending operation */ | 98 | struct list_head list_id; /* undo requests on this array */ |
| 98 | struct sem_undo *undo; /* undo requests on this array */ | ||
| 99 | unsigned long sem_nsems; /* no. of semaphores in array */ | 99 | unsigned long sem_nsems; /* no. of semaphores in array */ |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| 102 | /* One queue for each sleeping process in the system. */ | 102 | /* One queue for each sleeping process in the system. */ |
| 103 | struct sem_queue { | 103 | struct sem_queue { |
| 104 | struct sem_queue * next; /* next entry in the queue */ | 104 | struct list_head list; /* queue of pending operations */ |
| 105 | struct sem_queue ** prev; /* previous entry in the queue, *(q->prev) == q */ | 105 | struct task_struct *sleeper; /* this process */ |
| 106 | struct task_struct* sleeper; /* this process */ | 106 | struct sem_undo *undo; /* undo structure */ |
| 107 | struct sem_undo * undo; /* undo structure */ | ||
| 108 | int pid; /* process id of requesting process */ | 107 | int pid; /* process id of requesting process */ |
| 109 | int status; /* completion status of operation */ | 108 | int status; /* completion status of operation */ |
| 110 | struct sem_array * sma; /* semaphore array for operations */ | 109 | struct sembuf *sops; /* array of pending operations */ |
| 111 | int id; /* internal sem id */ | ||
| 112 | struct sembuf * sops; /* array of pending operations */ | ||
| 113 | int nsops; /* number of operations */ | 110 | int nsops; /* number of operations */ |
| 114 | int alter; /* does the operation alter the array? */ | 111 | int alter; /* does the operation alter the array? */ |
| 115 | }; | 112 | }; |
| @@ -118,8 +115,11 @@ struct sem_queue { | |||
| 118 | * when the process exits. | 115 | * when the process exits. |
| 119 | */ | 116 | */ |
| 120 | struct sem_undo { | 117 | struct sem_undo { |
| 121 | struct sem_undo * proc_next; /* next entry on this process */ | 118 | struct list_head list_proc; /* per-process list: all undos from one process. */ |
| 122 | struct sem_undo * id_next; /* next entry on this semaphore set */ | 119 | /* rcu protected */ |
| 120 | struct rcu_head rcu; /* rcu struct for sem_undo() */ | ||
| 121 | struct sem_undo_list *ulp; /* sem_undo_list for the process */ | ||
| 122 | struct list_head list_id; /* per semaphore array list: all undos for one array */ | ||
| 123 | int semid; /* semaphore set identifier */ | 123 | int semid; /* semaphore set identifier */ |
| 124 | short * semadj; /* array of adjustments, one per semaphore */ | 124 | short * semadj; /* array of adjustments, one per semaphore */ |
| 125 | }; | 125 | }; |
| @@ -128,9 +128,9 @@ struct sem_undo { | |||
| 128 | * that may be shared among all a CLONE_SYSVSEM task group. | 128 | * that may be shared among all a CLONE_SYSVSEM task group. |
| 129 | */ | 129 | */ |
| 130 | struct sem_undo_list { | 130 | struct sem_undo_list { |
| 131 | atomic_t refcnt; | 131 | atomic_t refcnt; |
| 132 | spinlock_t lock; | 132 | spinlock_t lock; |
| 133 | struct sem_undo *proc_list; | 133 | struct list_head list_proc; |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | struct sysv_sem { | 136 | struct sysv_sem { |
diff --git a/include/linux/sm501.h b/include/linux/sm501.h index b530fa6a1d34..214f93209b8c 100644 --- a/include/linux/sm501.h +++ b/include/linux/sm501.h | |||
| @@ -46,24 +46,6 @@ extern unsigned long sm501_modify_reg(struct device *dev, | |||
| 46 | unsigned long set, | 46 | unsigned long set, |
| 47 | unsigned long clear); | 47 | unsigned long clear); |
| 48 | 48 | ||
| 49 | /* sm501_gpio_set | ||
| 50 | * | ||
| 51 | * set the state of the given GPIO line | ||
| 52 | */ | ||
| 53 | |||
| 54 | extern void sm501_gpio_set(struct device *dev, | ||
| 55 | unsigned long gpio, | ||
| 56 | unsigned int to, | ||
| 57 | unsigned int dir); | ||
| 58 | |||
| 59 | /* sm501_gpio_get | ||
| 60 | * | ||
| 61 | * get the state of the given GPIO line | ||
| 62 | */ | ||
| 63 | |||
| 64 | extern unsigned long sm501_gpio_get(struct device *dev, | ||
| 65 | unsigned long gpio); | ||
| 66 | |||
| 67 | 49 | ||
| 68 | /* Platform data definitions */ | 50 | /* Platform data definitions */ |
| 69 | 51 | ||
| @@ -104,11 +86,19 @@ struct sm501_platdata_fb { | |||
| 104 | struct sm501_platdata_fbsub *fb_pnl; | 86 | struct sm501_platdata_fbsub *fb_pnl; |
| 105 | }; | 87 | }; |
| 106 | 88 | ||
| 107 | /* gpio i2c */ | 89 | /* gpio i2c |
| 90 | * | ||
| 91 | * Note, we have to pass in the bus number, as the number used will be | ||
| 92 | * passed to the i2c-gpio driver's platform_device.id, subsequently used | ||
| 93 | * to register the i2c bus. | ||
| 94 | */ | ||
| 108 | 95 | ||
| 109 | struct sm501_platdata_gpio_i2c { | 96 | struct sm501_platdata_gpio_i2c { |
| 97 | unsigned int bus_num; | ||
| 110 | unsigned int pin_sda; | 98 | unsigned int pin_sda; |
| 111 | unsigned int pin_scl; | 99 | unsigned int pin_scl; |
| 100 | int udelay; | ||
| 101 | int timeout; | ||
| 112 | }; | 102 | }; |
| 113 | 103 | ||
| 114 | /* sm501_initdata | 104 | /* sm501_initdata |
| @@ -131,6 +121,7 @@ struct sm501_reg_init { | |||
| 131 | #define SM501_USE_FBACCEL (1<<6) | 121 | #define SM501_USE_FBACCEL (1<<6) |
| 132 | #define SM501_USE_AC97 (1<<7) | 122 | #define SM501_USE_AC97 (1<<7) |
| 133 | #define SM501_USE_I2S (1<<8) | 123 | #define SM501_USE_I2S (1<<8) |
| 124 | #define SM501_USE_GPIO (1<<9) | ||
| 134 | 125 | ||
| 135 | #define SM501_USE_ALL (0xffffffff) | 126 | #define SM501_USE_ALL (0xffffffff) |
| 136 | 127 | ||
| @@ -157,6 +148,8 @@ struct sm501_init_gpio { | |||
| 157 | struct sm501_reg_init gpio_ddr_high; | 148 | struct sm501_reg_init gpio_ddr_high; |
| 158 | }; | 149 | }; |
| 159 | 150 | ||
| 151 | #define SM501_FLAG_SUSPEND_OFF (1<<4) | ||
| 152 | |||
| 160 | /* sm501_platdata | 153 | /* sm501_platdata |
| 161 | * | 154 | * |
| 162 | * This is passed with the platform device to allow the board | 155 | * This is passed with the platform device to allow the board |
| @@ -170,6 +163,12 @@ struct sm501_platdata { | |||
| 170 | struct sm501_init_gpio *init_gpiop; | 163 | struct sm501_init_gpio *init_gpiop; |
| 171 | struct sm501_platdata_fb *fb; | 164 | struct sm501_platdata_fb *fb; |
| 172 | 165 | ||
| 166 | int flags; | ||
| 167 | int gpio_base; | ||
| 168 | |||
| 169 | int (*get_power)(struct device *dev); | ||
| 170 | int (*set_power)(struct device *dev, unsigned int on); | ||
| 171 | |||
| 173 | struct sm501_platdata_gpio_i2c *gpio_i2c; | 172 | struct sm501_platdata_gpio_i2c *gpio_i2c; |
| 174 | unsigned int gpio_i2c_nr; | 173 | unsigned int gpio_i2c_nr; |
| 175 | }; | 174 | }; |
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h index 2c5cd55f44ff..923cd8a247b1 100644 --- a/include/linux/smb_fs.h +++ b/include/linux/smb_fs.h | |||
| @@ -43,18 +43,13 @@ static inline struct smb_inode_info *SMB_I(struct inode *inode) | |||
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | /* macro names are short for word, double-word, long value (?) */ | 45 | /* macro names are short for word, double-word, long value (?) */ |
| 46 | #define WVAL(buf,pos) \ | 46 | #define WVAL(buf, pos) (get_unaligned_le16((u8 *)(buf) + (pos))) |
| 47 | (le16_to_cpu(get_unaligned((__le16 *)((u8 *)(buf) + (pos))))) | 47 | #define DVAL(buf, pos) (get_unaligned_le32((u8 *)(buf) + (pos))) |
| 48 | #define DVAL(buf,pos) \ | 48 | #define LVAL(buf, pos) (get_unaligned_le64((u8 *)(buf) + (pos))) |
| 49 | (le32_to_cpu(get_unaligned((__le32 *)((u8 *)(buf) + (pos))))) | 49 | |
| 50 | #define LVAL(buf,pos) \ | 50 | #define WSET(buf, pos, val) put_unaligned_le16((val), (u8 *)(buf) + (pos)) |
| 51 | (le64_to_cpu(get_unaligned((__le64 *)((u8 *)(buf) + (pos))))) | 51 | #define DSET(buf, pos, val) put_unaligned_le32((val), (u8 *)(buf) + (pos)) |
| 52 | #define WSET(buf,pos,val) \ | 52 | #define LSET(buf, pos, val) put_unaligned_le64((val), (u8 *)(buf) + (pos)) |
| 53 | put_unaligned(cpu_to_le16((u16)(val)), (__le16 *)((u8 *)(buf) + (pos))) | ||
| 54 | #define DSET(buf,pos,val) \ | ||
| 55 | put_unaligned(cpu_to_le32((u32)(val)), (__le32 *)((u8 *)(buf) + (pos))) | ||
| 56 | #define LSET(buf,pos,val) \ | ||
| 57 | put_unaligned(cpu_to_le64((u64)(val)), (__le64 *)((u8 *)(buf) + (pos))) | ||
| 58 | 53 | ||
| 59 | /* where to find the base of the SMB packet proper */ | 54 | /* where to find the base of the SMB packet proper */ |
| 60 | #define smb_base(buf) ((u8 *)(((u8 *)(buf))+4)) | 55 | #define smb_base(buf) ((u8 *)(((u8 *)(buf))+4)) |
diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h index 835ddf47d45c..22ef107d7704 100644 --- a/include/linux/spi/mcp23s08.h +++ b/include/linux/spi/mcp23s08.h | |||
| @@ -1,18 +1,25 @@ | |||
| 1 | 1 | ||
| 2 | /* FIXME driver should be able to handle all four slaves that | 2 | /* FIXME driver should be able to handle IRQs... */ |
| 3 | * can be hooked up to each chipselect, as well as IRQs... | 3 | |
| 4 | */ | 4 | struct mcp23s08_chip_info { |
| 5 | bool is_present; /* true iff populated */ | ||
| 6 | u8 pullups; /* BIT(x) means enable pullup x */ | ||
| 7 | }; | ||
| 5 | 8 | ||
| 6 | struct mcp23s08_platform_data { | 9 | struct mcp23s08_platform_data { |
| 7 | /* four slaves can share one SPI chipselect */ | 10 | /* Four slaves (numbered 0..3) can share one SPI chipselect, and |
| 8 | u8 slave; | 11 | * will provide 8..32 GPIOs using 1..4 gpio_chip instances. |
| 12 | */ | ||
| 13 | struct mcp23s08_chip_info chip[4]; | ||
| 9 | 14 | ||
| 10 | /* number assigned to the first GPIO */ | 15 | /* "base" is the number of the first GPIO. Dynamic assignment is |
| 16 | * not currently supported, and even if there are gaps in chip | ||
| 17 | * addressing the GPIO numbers are sequential .. so for example | ||
| 18 | * if only slaves 0 and 3 are present, their GPIOs range from | ||
| 19 | * base to base+15. | ||
| 20 | */ | ||
| 11 | unsigned base; | 21 | unsigned base; |
| 12 | 22 | ||
| 13 | /* pins with pullups */ | ||
| 14 | u8 pullups; | ||
| 15 | |||
| 16 | void *context; /* param to setup/teardown */ | 23 | void *context; /* param to setup/teardown */ |
| 17 | 24 | ||
| 18 | int (*setup)(struct spi_device *spi, | 25 | int (*setup)(struct spi_device *spi, |
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index d311a090fae7..61e5610ad165 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | * linux/spinlock.h: builds the final spin_*() APIs. | 46 | * linux/spinlock.h: builds the final spin_*() APIs. |
| 47 | */ | 47 | */ |
| 48 | 48 | ||
| 49 | #include <linux/typecheck.h> | ||
| 49 | #include <linux/preempt.h> | 50 | #include <linux/preempt.h> |
| 50 | #include <linux/linkage.h> | 51 | #include <linux/linkage.h> |
| 51 | #include <linux/compiler.h> | 52 | #include <linux/compiler.h> |
| @@ -191,23 +192,53 @@ do { \ | |||
| 191 | 192 | ||
| 192 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) | 193 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) |
| 193 | 194 | ||
| 194 | #define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock) | 195 | #define spin_lock_irqsave(lock, flags) \ |
| 195 | #define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock) | 196 | do { \ |
| 196 | #define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock) | 197 | typecheck(unsigned long, flags); \ |
| 198 | flags = _spin_lock_irqsave(lock); \ | ||
| 199 | } while (0) | ||
| 200 | #define read_lock_irqsave(lock, flags) \ | ||
| 201 | do { \ | ||
| 202 | typecheck(unsigned long, flags); \ | ||
| 203 | flags = _read_lock_irqsave(lock); \ | ||
| 204 | } while (0) | ||
| 205 | #define write_lock_irqsave(lock, flags) \ | ||
| 206 | do { \ | ||
| 207 | typecheck(unsigned long, flags); \ | ||
| 208 | flags = _write_lock_irqsave(lock); \ | ||
| 209 | } while (0) | ||
| 197 | 210 | ||
| 198 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 211 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 199 | #define spin_lock_irqsave_nested(lock, flags, subclass) \ | 212 | #define spin_lock_irqsave_nested(lock, flags, subclass) \ |
| 200 | flags = _spin_lock_irqsave_nested(lock, subclass) | 213 | do { \ |
| 214 | typecheck(unsigned long, flags); \ | ||
| 215 | flags = _spin_lock_irqsave_nested(lock, subclass); \ | ||
| 216 | } while (0) | ||
| 201 | #else | 217 | #else |
| 202 | #define spin_lock_irqsave_nested(lock, flags, subclass) \ | 218 | #define spin_lock_irqsave_nested(lock, flags, subclass) \ |
| 203 | flags = _spin_lock_irqsave(lock) | 219 | do { \ |
| 220 | typecheck(unsigned long, flags); \ | ||
| 221 | flags = _spin_lock_irqsave(lock); \ | ||
| 222 | } while (0) | ||
| 204 | #endif | 223 | #endif |
| 205 | 224 | ||
| 206 | #else | 225 | #else |
| 207 | 226 | ||
| 208 | #define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags) | 227 | #define spin_lock_irqsave(lock, flags) \ |
| 209 | #define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags) | 228 | do { \ |
| 210 | #define write_lock_irqsave(lock, flags) _write_lock_irqsave(lock, flags) | 229 | typecheck(unsigned long, flags); \ |
| 230 | _spin_lock_irqsave(lock, flags); \ | ||
| 231 | } while (0) | ||
| 232 | #define read_lock_irqsave(lock, flags) \ | ||
| 233 | do { \ | ||
| 234 | typecheck(unsigned long, flags); \ | ||
| 235 | _read_lock_irqsave(lock, flags); \ | ||
| 236 | } while (0) | ||
| 237 | #define write_lock_irqsave(lock, flags) \ | ||
| 238 | do { \ | ||
| 239 | typecheck(unsigned long, flags); \ | ||
| 240 | _write_lock_irqsave(lock, flags); \ | ||
| 241 | } while (0) | ||
| 211 | #define spin_lock_irqsave_nested(lock, flags, subclass) \ | 242 | #define spin_lock_irqsave_nested(lock, flags, subclass) \ |
| 212 | spin_lock_irqsave(lock, flags) | 243 | spin_lock_irqsave(lock, flags) |
| 213 | 244 | ||
| @@ -260,16 +291,25 @@ do { \ | |||
| 260 | } while (0) | 291 | } while (0) |
| 261 | #endif | 292 | #endif |
| 262 | 293 | ||
| 263 | #define spin_unlock_irqrestore(lock, flags) \ | 294 | #define spin_unlock_irqrestore(lock, flags) \ |
| 264 | _spin_unlock_irqrestore(lock, flags) | 295 | do { \ |
| 296 | typecheck(unsigned long, flags); \ | ||
| 297 | _spin_unlock_irqrestore(lock, flags); \ | ||
| 298 | } while (0) | ||
| 265 | #define spin_unlock_bh(lock) _spin_unlock_bh(lock) | 299 | #define spin_unlock_bh(lock) _spin_unlock_bh(lock) |
| 266 | 300 | ||
| 267 | #define read_unlock_irqrestore(lock, flags) \ | 301 | #define read_unlock_irqrestore(lock, flags) \ |
| 268 | _read_unlock_irqrestore(lock, flags) | 302 | do { \ |
| 303 | typecheck(unsigned long, flags); \ | ||
| 304 | _read_unlock_irqrestore(lock, flags); \ | ||
| 305 | } while (0) | ||
| 269 | #define read_unlock_bh(lock) _read_unlock_bh(lock) | 306 | #define read_unlock_bh(lock) _read_unlock_bh(lock) |
| 270 | 307 | ||
| 271 | #define write_unlock_irqrestore(lock, flags) \ | 308 | #define write_unlock_irqrestore(lock, flags) \ |
| 272 | _write_unlock_irqrestore(lock, flags) | 309 | do { \ |
| 310 | typecheck(unsigned long, flags); \ | ||
| 311 | _write_unlock_irqrestore(lock, flags); \ | ||
| 312 | } while (0) | ||
| 273 | #define write_unlock_bh(lock) _write_unlock_bh(lock) | 313 | #define write_unlock_bh(lock) _write_unlock_bh(lock) |
| 274 | 314 | ||
| 275 | #define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock)) | 315 | #define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock)) |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 06f2bf76c030..d6ff145919ca 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
| @@ -411,7 +411,7 @@ asmlinkage long sys_bind(int, struct sockaddr __user *, int); | |||
| 411 | asmlinkage long sys_connect(int, struct sockaddr __user *, int); | 411 | asmlinkage long sys_connect(int, struct sockaddr __user *, int); |
| 412 | asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); | 412 | asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); |
| 413 | asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *, | 413 | asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *, |
| 414 | const sigset_t *, size_t, int); | 414 | const __user sigset_t *, size_t, int); |
| 415 | asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); | 415 | asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); |
| 416 | asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); | 416 | asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); |
| 417 | asmlinkage long sys_send(int, void __user *, size_t, unsigned); | 417 | asmlinkage long sys_send(int, void __user *, size_t, unsigned); |
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h index 5d69c0744fff..18269e956a71 100644 --- a/include/linux/taskstats.h +++ b/include/linux/taskstats.h | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | #define TASKSTATS_VERSION 6 | 34 | #define TASKSTATS_VERSION 7 |
| 35 | #define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN | 35 | #define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN |
| 36 | * in linux/sched.h */ | 36 | * in linux/sched.h */ |
| 37 | 37 | ||
| @@ -157,6 +157,10 @@ struct taskstats { | |||
| 157 | __u64 ac_utimescaled; /* utime scaled on frequency etc */ | 157 | __u64 ac_utimescaled; /* utime scaled on frequency etc */ |
| 158 | __u64 ac_stimescaled; /* stime scaled on frequency etc */ | 158 | __u64 ac_stimescaled; /* stime scaled on frequency etc */ |
| 159 | __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */ | 159 | __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */ |
| 160 | |||
| 161 | /* Delay waiting for memory reclaim */ | ||
| 162 | __u64 freepages_count; | ||
| 163 | __u64 freepages_delay_total; | ||
| 160 | }; | 164 | }; |
| 161 | 165 | ||
| 162 | 166 | ||
diff --git a/include/linux/typecheck.h b/include/linux/typecheck.h new file mode 100644 index 000000000000..eb5b74a575be --- /dev/null +++ b/include/linux/typecheck.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef TYPECHECK_H_INCLUDED | ||
| 2 | #define TYPECHECK_H_INCLUDED | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Check at compile time that something is of a particular type. | ||
| 6 | * Always evaluates to 1 so you may use it easily in comparisons. | ||
| 7 | */ | ||
| 8 | #define typecheck(type,x) \ | ||
| 9 | ({ type __dummy; \ | ||
| 10 | typeof(x) __dummy2; \ | ||
| 11 | (void)(&__dummy == &__dummy2); \ | ||
| 12 | 1; \ | ||
| 13 | }) | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Check at compile time that 'function' is a certain type, or is a pointer | ||
| 17 | * to that type (needs to use typedef for the function type.) | ||
| 18 | */ | ||
| 19 | #define typecheck_fn(type,function) \ | ||
| 20 | ({ typeof(type) __tmp = function; \ | ||
| 21 | (void)__tmp; \ | ||
| 22 | }) | ||
| 23 | |||
| 24 | #endif /* TYPECHECK_H_INCLUDED */ | ||
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 747c3a49cdc9..c932390c6da0 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h | |||
| @@ -330,7 +330,7 @@ extern int usb_string_id(struct usb_composite_dev *c); | |||
| 330 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) | 330 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) |
| 331 | #define ERROR(d, fmt, args...) \ | 331 | #define ERROR(d, fmt, args...) \ |
| 332 | dev_err(&(d)->gadget->dev , fmt , ## args) | 332 | dev_err(&(d)->gadget->dev , fmt , ## args) |
| 333 | #define WARN(d, fmt, args...) \ | 333 | #define WARNING(d, fmt, args...) \ |
| 334 | dev_warn(&(d)->gadget->dev , fmt , ## args) | 334 | dev_warn(&(d)->gadget->dev , fmt , ## args) |
| 335 | #define INFO(d, fmt, args...) \ | 335 | #define INFO(d, fmt, args...) \ |
| 336 | dev_info(&(d)->gadget->dev , fmt , ## args) | 336 | dev_info(&(d)->gadget->dev , fmt , ## args) |
diff --git a/include/linux/virtio_9p.h b/include/linux/virtio_9p.h index 8eff0b53910b..b3c4a60ceeb3 100644 --- a/include/linux/virtio_9p.h +++ b/include/linux/virtio_9p.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #ifndef _LINUX_VIRTIO_9P_H | 1 | #ifndef _LINUX_VIRTIO_9P_H |
| 2 | #define _LINUX_VIRTIO_9P_H | 2 | #define _LINUX_VIRTIO_9P_H |
| 3 | /* This header is BSD licensed so anyone can use the definitions to implement | ||
| 4 | * compatible drivers/servers. */ | ||
| 3 | #include <linux/virtio_config.h> | 5 | #include <linux/virtio_config.h> |
| 4 | 6 | ||
| 5 | /* The ID for virtio console */ | 7 | /* The ID for virtio console */ |
diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h index 979524ee75b7..c30c7bfbf39b 100644 --- a/include/linux/virtio_balloon.h +++ b/include/linux/virtio_balloon.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #ifndef _LINUX_VIRTIO_BALLOON_H | 1 | #ifndef _LINUX_VIRTIO_BALLOON_H |
| 2 | #define _LINUX_VIRTIO_BALLOON_H | 2 | #define _LINUX_VIRTIO_BALLOON_H |
| 3 | /* This header is BSD licensed so anyone can use the definitions to implement | ||
| 4 | * compatible drivers/servers. */ | ||
| 3 | #include <linux/virtio_config.h> | 5 | #include <linux/virtio_config.h> |
| 4 | 6 | ||
| 5 | /* The ID for virtio_balloon */ | 7 | /* The ID for virtio_balloon */ |
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h index 5f79a5f9de79..c1aef85243bf 100644 --- a/include/linux/virtio_blk.h +++ b/include/linux/virtio_blk.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #ifndef _LINUX_VIRTIO_BLK_H | 1 | #ifndef _LINUX_VIRTIO_BLK_H |
| 2 | #define _LINUX_VIRTIO_BLK_H | 2 | #define _LINUX_VIRTIO_BLK_H |
| 3 | /* This header is BSD licensed so anyone can use the definitions to implement | ||
| 4 | * compatible drivers/servers. */ | ||
| 3 | #include <linux/virtio_config.h> | 5 | #include <linux/virtio_config.h> |
| 4 | 6 | ||
| 5 | /* The ID for virtio_block */ | 7 | /* The ID for virtio_block */ |
| @@ -11,6 +13,7 @@ | |||
| 11 | #define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ | 13 | #define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ |
| 12 | #define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */ | 14 | #define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */ |
| 13 | #define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ | 15 | #define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ |
| 16 | #define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ | ||
| 14 | 17 | ||
| 15 | struct virtio_blk_config | 18 | struct virtio_blk_config |
| 16 | { | 19 | { |
| @@ -26,6 +29,8 @@ struct virtio_blk_config | |||
| 26 | __u8 heads; | 29 | __u8 heads; |
| 27 | __u8 sectors; | 30 | __u8 sectors; |
| 28 | } geometry; | 31 | } geometry; |
| 32 | /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ | ||
| 33 | __u32 blk_size; | ||
| 29 | } __attribute__((packed)); | 34 | } __attribute__((packed)); |
| 30 | 35 | ||
| 31 | /* These two define direction. */ | 36 | /* These two define direction. */ |
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index f364bbf63c34..bf8ec283b232 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
| @@ -1,5 +1,8 @@ | |||
| 1 | #ifndef _LINUX_VIRTIO_CONFIG_H | 1 | #ifndef _LINUX_VIRTIO_CONFIG_H |
| 2 | #define _LINUX_VIRTIO_CONFIG_H | 2 | #define _LINUX_VIRTIO_CONFIG_H |
| 3 | /* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so | ||
| 4 | * anyone can use the definitions to implement compatible drivers/servers. */ | ||
| 5 | |||
| 3 | /* Virtio devices use a standardized configuration space to define their | 6 | /* Virtio devices use a standardized configuration space to define their |
| 4 | * features and pass configuration information, but each implementation can | 7 | * features and pass configuration information, but each implementation can |
| 5 | * store and access that space differently. */ | 8 | * store and access that space differently. */ |
| @@ -15,6 +18,12 @@ | |||
| 15 | /* We've given up on this device. */ | 18 | /* We've given up on this device. */ |
| 16 | #define VIRTIO_CONFIG_S_FAILED 0x80 | 19 | #define VIRTIO_CONFIG_S_FAILED 0x80 |
| 17 | 20 | ||
| 21 | /* Some virtio feature bits (currently bits 28 through 31) are reserved for the | ||
| 22 | * transport being used (eg. virtio_ring), the rest are per-device feature | ||
| 23 | * bits. */ | ||
| 24 | #define VIRTIO_TRANSPORT_F_START 28 | ||
| 25 | #define VIRTIO_TRANSPORT_F_END 32 | ||
| 26 | |||
| 18 | /* Do we get callbacks when the ring is completely used, even if we've | 27 | /* Do we get callbacks when the ring is completely used, even if we've |
| 19 | * suppressed them? */ | 28 | * suppressed them? */ |
| 20 | #define VIRTIO_F_NOTIFY_ON_EMPTY 24 | 29 | #define VIRTIO_F_NOTIFY_ON_EMPTY 24 |
| @@ -52,9 +61,10 @@ | |||
| 52 | * @get_features: get the array of feature bits for this device. | 61 | * @get_features: get the array of feature bits for this device. |
| 53 | * vdev: the virtio_device | 62 | * vdev: the virtio_device |
| 54 | * Returns the first 32 feature bits (all we currently need). | 63 | * Returns the first 32 feature bits (all we currently need). |
| 55 | * @set_features: confirm what device features we'll be using. | 64 | * @finalize_features: confirm what device features we'll be using. |
| 56 | * vdev: the virtio_device | 65 | * vdev: the virtio_device |
| 57 | * feature: the first 32 feature bits | 66 | * This gives the final feature bits for the device: it can change |
| 67 | * the dev->feature bits if it wants. | ||
| 58 | */ | 68 | */ |
| 59 | struct virtio_config_ops | 69 | struct virtio_config_ops |
| 60 | { | 70 | { |
| @@ -70,7 +80,7 @@ struct virtio_config_ops | |||
| 70 | void (*callback)(struct virtqueue *)); | 80 | void (*callback)(struct virtqueue *)); |
| 71 | void (*del_vq)(struct virtqueue *vq); | 81 | void (*del_vq)(struct virtqueue *vq); |
| 72 | u32 (*get_features)(struct virtio_device *vdev); | 82 | u32 (*get_features)(struct virtio_device *vdev); |
| 73 | void (*set_features)(struct virtio_device *vdev, u32 features); | 83 | void (*finalize_features)(struct virtio_device *vdev); |
| 74 | }; | 84 | }; |
| 75 | 85 | ||
| 76 | /* If driver didn't advertise the feature, it will never appear. */ | 86 | /* If driver didn't advertise the feature, it will never appear. */ |
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index ed2d4ead7eb7..19a0da0dba41 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #ifndef _LINUX_VIRTIO_CONSOLE_H | 1 | #ifndef _LINUX_VIRTIO_CONSOLE_H |
| 2 | #define _LINUX_VIRTIO_CONSOLE_H | 2 | #define _LINUX_VIRTIO_CONSOLE_H |
| 3 | #include <linux/virtio_config.h> | 3 | #include <linux/virtio_config.h> |
| 4 | /* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so | ||
| 5 | * anyone can use the definitions to implement compatible drivers/servers. */ | ||
| 4 | 6 | ||
| 5 | /* The ID for virtio console */ | 7 | /* The ID for virtio console */ |
| 6 | #define VIRTIO_ID_CONSOLE 3 | 8 | #define VIRTIO_ID_CONSOLE 3 |
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 38c0571820fb..5e33761b9b8a 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #ifndef _LINUX_VIRTIO_NET_H | 1 | #ifndef _LINUX_VIRTIO_NET_H |
| 2 | #define _LINUX_VIRTIO_NET_H | 2 | #define _LINUX_VIRTIO_NET_H |
| 3 | /* This header is BSD licensed so anyone can use the definitions to implement | ||
| 4 | * compatible drivers/servers. */ | ||
| 3 | #include <linux/virtio_config.h> | 5 | #include <linux/virtio_config.h> |
| 4 | 6 | ||
| 5 | /* The ID for virtio_net */ | 7 | /* The ID for virtio_net */ |
diff --git a/include/linux/virtio_pci.h b/include/linux/virtio_pci.h index b3151659cf49..cdef35742932 100644 --- a/include/linux/virtio_pci.h +++ b/include/linux/virtio_pci.h | |||
| @@ -9,9 +9,8 @@ | |||
| 9 | * Authors: | 9 | * Authors: |
| 10 | * Anthony Liguori <aliguori@us.ibm.com> | 10 | * Anthony Liguori <aliguori@us.ibm.com> |
| 11 | * | 11 | * |
| 12 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | 12 | * This header is BSD licensed so anyone can use the definitions to implement |
| 13 | * See the COPYING file in the top-level directory. | 13 | * compatible drivers/servers. |
| 14 | * | ||
| 15 | */ | 14 | */ |
| 16 | 15 | ||
| 17 | #ifndef _LINUX_VIRTIO_PCI_H | 16 | #ifndef _LINUX_VIRTIO_PCI_H |
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index abe481ed990e..c4a598fb3826 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h | |||
| @@ -120,6 +120,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, | |||
| 120 | void (*notify)(struct virtqueue *vq), | 120 | void (*notify)(struct virtqueue *vq), |
| 121 | void (*callback)(struct virtqueue *vq)); | 121 | void (*callback)(struct virtqueue *vq)); |
| 122 | void vring_del_virtqueue(struct virtqueue *vq); | 122 | void vring_del_virtqueue(struct virtqueue *vq); |
| 123 | /* Filter out transport-specific feature bits. */ | ||
| 124 | void vring_transport_features(struct virtio_device *vdev); | ||
| 123 | 125 | ||
| 124 | irqreturn_t vring_interrupt(int irq, void *_vq); | 126 | irqreturn_t vring_interrupt(int irq, void *_vq); |
| 125 | #endif /* __KERNEL__ */ | 127 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/virtio_rng.h b/include/linux/virtio_rng.h index 331afb6c9f62..1a85dab8a940 100644 --- a/include/linux/virtio_rng.h +++ b/include/linux/virtio_rng.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #ifndef _LINUX_VIRTIO_RNG_H | 1 | #ifndef _LINUX_VIRTIO_RNG_H |
| 2 | #define _LINUX_VIRTIO_RNG_H | 2 | #define _LINUX_VIRTIO_RNG_H |
| 3 | /* This header is BSD licensed so anyone can use the definitions to implement | ||
| 4 | * compatible drivers/servers. */ | ||
| 3 | #include <linux/virtio_config.h> | 5 | #include <linux/virtio_config.h> |
| 4 | 6 | ||
| 5 | /* The ID for virtio_rng */ | 7 | /* The ID for virtio_rng */ |
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 9448ffbdcbf6..14c0e91be9b5 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/mutex.h> | 12 | #include <linux/mutex.h> |
| 13 | #include <linux/console_struct.h> | 13 | #include <linux/console_struct.h> |
| 14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
| 15 | #include <linux/consolemap.h> | ||
| 15 | 16 | ||
| 16 | /* | 17 | /* |
| 17 | * Presently, a lot of graphics programs do not restore the contents of | 18 | * Presently, a lot of graphics programs do not restore the contents of |
| @@ -54,6 +55,7 @@ void redraw_screen(struct vc_data *vc, int is_switch); | |||
| 54 | struct tty_struct; | 55 | struct tty_struct; |
| 55 | int tioclinux(struct tty_struct *tty, unsigned long arg); | 56 | int tioclinux(struct tty_struct *tty, unsigned long arg); |
| 56 | 57 | ||
| 58 | #ifdef CONFIG_CONSOLE_TRANSLATIONS | ||
| 57 | /* consolemap.c */ | 59 | /* consolemap.c */ |
| 58 | 60 | ||
| 59 | struct unimapinit; | 61 | struct unimapinit; |
| @@ -71,6 +73,23 @@ void con_free_unimap(struct vc_data *vc); | |||
| 71 | void con_protect_unimap(struct vc_data *vc, int rdonly); | 73 | void con_protect_unimap(struct vc_data *vc, int rdonly); |
| 72 | int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); | 74 | int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); |
| 73 | 75 | ||
| 76 | #define vc_translate(vc, c) ((vc)->vc_translate[(c) | \ | ||
| 77 | (vc)->vc_toggle_meta ? 0x80 : 0]) | ||
| 78 | #else | ||
| 79 | #define con_set_trans_old(arg) (0) | ||
| 80 | #define con_get_trans_old(arg) (-EINVAL) | ||
| 81 | #define con_set_trans_new(arg) (0) | ||
| 82 | #define con_get_trans_new(arg) (-EINVAL) | ||
| 83 | #define con_clear_unimap(vc, ui) (0) | ||
| 84 | #define con_set_unimap(vc, ct, list) (0) | ||
| 85 | #define con_set_default_unimap(vc) (0) | ||
| 86 | #define con_copy_unimap(d, s) (0) | ||
| 87 | #define con_get_unimap(vc, ct, uct, list) (-EINVAL) | ||
| 88 | #define con_free_unimap(vc) do { ; } while (0) | ||
| 89 | |||
| 90 | #define vc_translate(vc, c) (c) | ||
| 91 | #endif | ||
| 92 | |||
| 74 | /* vt.c */ | 93 | /* vt.c */ |
| 75 | int vt_waitactive(int vt); | 94 | int vt_waitactive(int vt); |
| 76 | void change_console(struct vc_data *new_vc); | 95 | void change_console(struct vc_data *new_vc); |
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 14d47120682b..5c158c477ac7 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
| @@ -201,6 +201,8 @@ extern int keventd_up(void); | |||
| 201 | extern void init_workqueues(void); | 201 | extern void init_workqueues(void); |
| 202 | int execute_in_process_context(work_func_t fn, struct execute_work *); | 202 | int execute_in_process_context(work_func_t fn, struct execute_work *); |
| 203 | 203 | ||
| 204 | extern int flush_work(struct work_struct *work); | ||
| 205 | |||
| 204 | extern int cancel_work_sync(struct work_struct *work); | 206 | extern int cancel_work_sync(struct work_struct *work); |
| 205 | 207 | ||
| 206 | /* | 208 | /* |
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index a7421f130cc0..ccdc562e444e 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h | |||
| @@ -58,6 +58,13 @@ | |||
| 58 | * device should be used. A &struct ubi_rsvol_req object has to be properly | 58 | * device should be used. A &struct ubi_rsvol_req object has to be properly |
| 59 | * filled and a pointer to it has to be passed to the IOCTL. | 59 | * filled and a pointer to it has to be passed to the IOCTL. |
| 60 | * | 60 | * |
| 61 | * UBI volumes re-name | ||
| 62 | * ~~~~~~~~~~~~~~~~~~~ | ||
| 63 | * | ||
| 64 | * To re-name several volumes atomically at one go, the %UBI_IOCRNVOL command | ||
| 65 | * of the UBI character device should be used. A &struct ubi_rnvol_req object | ||
| 66 | * has to be properly filled and a pointer to it has to be passed to the IOCTL. | ||
| 67 | * | ||
| 61 | * UBI volume update | 68 | * UBI volume update |
| 62 | * ~~~~~~~~~~~~~~~~~ | 69 | * ~~~~~~~~~~~~~~~~~ |
| 63 | * | 70 | * |
| @@ -104,6 +111,8 @@ | |||
| 104 | #define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t) | 111 | #define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t) |
| 105 | /* Re-size an UBI volume */ | 112 | /* Re-size an UBI volume */ |
| 106 | #define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req) | 113 | #define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req) |
| 114 | /* Re-name volumes */ | ||
| 115 | #define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req) | ||
| 107 | 116 | ||
| 108 | /* IOCTL commands of the UBI control character device */ | 117 | /* IOCTL commands of the UBI control character device */ |
| 109 | 118 | ||
| @@ -128,6 +137,9 @@ | |||
| 128 | /* Maximum MTD device name length supported by UBI */ | 137 | /* Maximum MTD device name length supported by UBI */ |
| 129 | #define MAX_UBI_MTD_NAME_LEN 127 | 138 | #define MAX_UBI_MTD_NAME_LEN 127 |
| 130 | 139 | ||
| 140 | /* Maximum amount of UBI volumes that can be re-named at one go */ | ||
| 141 | #define UBI_MAX_RNVOL 32 | ||
| 142 | |||
| 131 | /* | 143 | /* |
| 132 | * UBI data type hint constants. | 144 | * UBI data type hint constants. |
| 133 | * | 145 | * |
| @@ -176,20 +188,20 @@ enum { | |||
| 176 | * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages. | 188 | * it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages. |
| 177 | * | 189 | * |
| 178 | * But in rare cases, if this optimizes things, the VID header may be placed to | 190 | * But in rare cases, if this optimizes things, the VID header may be placed to |
| 179 | * a different offset. For example, the boot-loader might do things faster if the | 191 | * a different offset. For example, the boot-loader might do things faster if |
| 180 | * VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As | 192 | * the VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. |
| 181 | * the boot-loader would not normally need to read EC headers (unless it needs | 193 | * As the boot-loader would not normally need to read EC headers (unless it |
| 182 | * UBI in RW mode), it might be faster to calculate ECC. This is weird example, | 194 | * needs UBI in RW mode), it might be faster to calculate ECC. This is weird |
| 183 | * but it real-life example. So, in this example, @vid_hdr_offer would be | 195 | * example, but it real-life example. So, in this example, @vid_hdr_offer would |
| 184 | * 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes | 196 | * be 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes |
| 185 | * aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page | 197 | * aligned, which is OK, as UBI is clever enough to realize this is 4th |
| 186 | * of the first page and add needed padding. | 198 | * sub-page of the first page and add needed padding. |
| 187 | */ | 199 | */ |
| 188 | struct ubi_attach_req { | 200 | struct ubi_attach_req { |
| 189 | int32_t ubi_num; | 201 | int32_t ubi_num; |
| 190 | int32_t mtd_num; | 202 | int32_t mtd_num; |
| 191 | int32_t vid_hdr_offset; | 203 | int32_t vid_hdr_offset; |
| 192 | uint8_t padding[12]; | 204 | int8_t padding[12]; |
| 193 | }; | 205 | }; |
| 194 | 206 | ||
| 195 | /** | 207 | /** |
| @@ -251,6 +263,48 @@ struct ubi_rsvol_req { | |||
| 251 | } __attribute__ ((packed)); | 263 | } __attribute__ ((packed)); |
| 252 | 264 | ||
| 253 | /** | 265 | /** |
| 266 | * struct ubi_rnvol_req - volumes re-name request. | ||
| 267 | * @count: count of volumes to re-name | ||
| 268 | * @padding1: reserved for future, not used, has to be zeroed | ||
| 269 | * @vol_id: ID of the volume to re-name | ||
| 270 | * @name_len: name length | ||
| 271 | * @padding2: reserved for future, not used, has to be zeroed | ||
| 272 | * @name: new volume name | ||
| 273 | * | ||
| 274 | * UBI allows to re-name up to %32 volumes at one go. The count of volumes to | ||
| 275 | * re-name is specified in the @count field. The ID of the volumes to re-name | ||
| 276 | * and the new names are specified in the @vol_id and @name fields. | ||
| 277 | * | ||
| 278 | * The UBI volume re-name operation is atomic, which means that should power cut | ||
| 279 | * happen, the volumes will have either old name or new name. So the possible | ||
| 280 | * use-cases of this command is atomic upgrade. Indeed, to upgrade, say, volumes | ||
| 281 | * A and B one may create temporary volumes %A1 and %B1 with the new contents, | ||
| 282 | * then atomically re-name A1->A and B1->B, in which case old %A and %B will | ||
| 283 | * be removed. | ||
| 284 | * | ||
| 285 | * If it is not desirable to remove old A and B, the re-name request has to | ||
| 286 | * contain 4 entries: A1->A, A->A1, B1->B, B->B1, in which case old A1 and B1 | ||
| 287 | * become A and B, and old A and B will become A1 and B1. | ||
| 288 | * | ||
| 289 | * It is also OK to request: A1->A, A1->X, B1->B, B->Y, in which case old A1 | ||
| 290 | * and B1 become A and B, and old A and B become X and Y. | ||
| 291 | * | ||
| 292 | * In other words, in case of re-naming into an existing volume name, the | ||
| 293 | * existing volume is removed, unless it is re-named as well at the same | ||
| 294 | * re-name request. | ||
| 295 | */ | ||
| 296 | struct ubi_rnvol_req { | ||
| 297 | int32_t count; | ||
| 298 | int8_t padding1[12]; | ||
| 299 | struct { | ||
| 300 | int32_t vol_id; | ||
| 301 | int16_t name_len; | ||
| 302 | int8_t padding2[2]; | ||
| 303 | char name[UBI_MAX_VOLUME_NAME + 1]; | ||
| 304 | } ents[UBI_MAX_RNVOL]; | ||
| 305 | } __attribute__ ((packed)); | ||
| 306 | |||
| 307 | /** | ||
| 254 | * struct ubi_leb_change_req - a data structure used in atomic logical | 308 | * struct ubi_leb_change_req - a data structure used in atomic logical |
| 255 | * eraseblock change requests. | 309 | * eraseblock change requests. |
| 256 | * @lnum: logical eraseblock number to change | 310 | * @lnum: logical eraseblock number to change |
| @@ -261,8 +315,8 @@ struct ubi_rsvol_req { | |||
| 261 | struct ubi_leb_change_req { | 315 | struct ubi_leb_change_req { |
| 262 | int32_t lnum; | 316 | int32_t lnum; |
| 263 | int32_t bytes; | 317 | int32_t bytes; |
| 264 | uint8_t dtype; | 318 | int8_t dtype; |
| 265 | uint8_t padding[7]; | 319 | int8_t padding[7]; |
| 266 | } __attribute__ ((packed)); | 320 | } __attribute__ ((packed)); |
| 267 | 321 | ||
| 268 | #endif /* __UBI_USER_H__ */ | 322 | #endif /* __UBI_USER_H__ */ |
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index dfd8bf66ce27..d364fd594ea4 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h | |||
| @@ -262,7 +262,7 @@ static inline int ieee80211_get_radiotap_len(unsigned char *data) | |||
| 262 | struct ieee80211_radiotap_header *hdr = | 262 | struct ieee80211_radiotap_header *hdr = |
| 263 | (struct ieee80211_radiotap_header *)data; | 263 | (struct ieee80211_radiotap_header *)data; |
| 264 | 264 | ||
| 265 | return le16_to_cpu(get_unaligned(&hdr->it_len)); | 265 | return get_unaligned_le16(&hdr->it_len); |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | #endif /* IEEE80211_RADIOTAP_H */ | 268 | #endif /* IEEE80211_RADIOTAP_H */ |
diff --git a/init/do_mounts.c b/init/do_mounts.c index a1de1bf3d6b9..f769fac4f4c0 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
| 15 | #include <linux/initrd.h> | ||
| 15 | 16 | ||
| 16 | #include <linux/nfs_fs.h> | 17 | #include <linux/nfs_fs.h> |
| 17 | #include <linux/nfs_fs_sb.h> | 18 | #include <linux/nfs_fs_sb.h> |
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 46dfd64ae8fb..fedef93b586f 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c | |||
| @@ -10,8 +10,6 @@ | |||
| 10 | 10 | ||
| 11 | #include "do_mounts.h" | 11 | #include "do_mounts.h" |
| 12 | 12 | ||
| 13 | #define BUILD_CRAMDISK | ||
| 14 | |||
| 15 | int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ | 13 | int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ |
| 16 | 14 | ||
| 17 | static int __init prompt_ramdisk(char *str) | 15 | static int __init prompt_ramdisk(char *str) |
| @@ -162,14 +160,8 @@ int __init rd_load_image(char *from) | |||
| 162 | goto done; | 160 | goto done; |
| 163 | 161 | ||
| 164 | if (nblocks == 0) { | 162 | if (nblocks == 0) { |
| 165 | #ifdef BUILD_CRAMDISK | ||
| 166 | if (crd_load(in_fd, out_fd) == 0) | 163 | if (crd_load(in_fd, out_fd) == 0) |
| 167 | goto successful_load; | 164 | goto successful_load; |
| 168 | #else | ||
| 169 | printk(KERN_NOTICE | ||
| 170 | "RAMDISK: Kernel does not support compressed " | ||
| 171 | "RAM disk images\n"); | ||
| 172 | #endif | ||
| 173 | goto done; | 165 | goto done; |
| 174 | } | 166 | } |
| 175 | 167 | ||
| @@ -267,8 +259,6 @@ int __init rd_load_disk(int n) | |||
| 267 | return rd_load_image("/dev/root"); | 259 | return rd_load_image("/dev/root"); |
| 268 | } | 260 | } |
| 269 | 261 | ||
| 270 | #ifdef BUILD_CRAMDISK | ||
| 271 | |||
| 272 | /* | 262 | /* |
| 273 | * gzip declarations | 263 | * gzip declarations |
| 274 | */ | 264 | */ |
| @@ -313,32 +303,11 @@ static int crd_infd, crd_outfd; | |||
| 313 | 303 | ||
| 314 | static int __init fill_inbuf(void); | 304 | static int __init fill_inbuf(void); |
| 315 | static void __init flush_window(void); | 305 | static void __init flush_window(void); |
| 316 | static void __init *malloc(size_t size); | ||
| 317 | static void __init free(void *where); | ||
| 318 | static void __init error(char *m); | 306 | static void __init error(char *m); |
| 319 | static void __init gzip_mark(void **); | ||
| 320 | static void __init gzip_release(void **); | ||
| 321 | |||
| 322 | #include "../lib/inflate.c" | ||
| 323 | 307 | ||
| 324 | static void __init *malloc(size_t size) | 308 | #define NO_INFLATE_MALLOC |
| 325 | { | ||
| 326 | return kmalloc(size, GFP_KERNEL); | ||
| 327 | } | ||
| 328 | |||
| 329 | static void __init free(void *where) | ||
| 330 | { | ||
| 331 | kfree(where); | ||
| 332 | } | ||
| 333 | |||
| 334 | static void __init gzip_mark(void **ptr) | ||
| 335 | { | ||
| 336 | } | ||
| 337 | |||
| 338 | static void __init gzip_release(void **ptr) | ||
| 339 | { | ||
| 340 | } | ||
| 341 | 309 | ||
| 310 | #include "../lib/inflate.c" | ||
| 342 | 311 | ||
| 343 | /* =========================================================================== | 312 | /* =========================================================================== |
| 344 | * Fill the input buffer. This is called only when the buffer is empty | 313 | * Fill the input buffer. This is called only when the buffer is empty |
| @@ -425,5 +394,3 @@ static int __init crd_load(int in_fd, int out_fd) | |||
| 425 | kfree(window); | 394 | kfree(window); |
| 426 | return result; | 395 | return result; |
| 427 | } | 396 | } |
| 428 | |||
| 429 | #endif /* BUILD_CRAMDISK */ | ||
diff --git a/init/initramfs.c b/init/initramfs.c index 8eeeccb328c9..644fc01ad5f0 100644 --- a/init/initramfs.c +++ b/init/initramfs.c | |||
| @@ -14,16 +14,6 @@ static void __init error(char *x) | |||
| 14 | message = x; | 14 | message = x; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | static void __init *malloc(size_t size) | ||
| 18 | { | ||
| 19 | return kmalloc(size, GFP_KERNEL); | ||
| 20 | } | ||
| 21 | |||
| 22 | static void __init free(void *where) | ||
| 23 | { | ||
| 24 | kfree(where); | ||
| 25 | } | ||
| 26 | |||
| 27 | /* link hash */ | 17 | /* link hash */ |
| 28 | 18 | ||
| 29 | #define N_ALIGN(len) ((((len) + 1) & ~3) + 2) | 19 | #define N_ALIGN(len) ((((len) + 1) & ~3) + 2) |
| @@ -407,18 +397,10 @@ static long bytes_out; | |||
| 407 | 397 | ||
| 408 | static void __init flush_window(void); | 398 | static void __init flush_window(void); |
| 409 | static void __init error(char *m); | 399 | static void __init error(char *m); |
| 410 | static void __init gzip_mark(void **); | ||
| 411 | static void __init gzip_release(void **); | ||
| 412 | 400 | ||
| 413 | #include "../lib/inflate.c" | 401 | #define NO_INFLATE_MALLOC |
| 414 | 402 | ||
| 415 | static void __init gzip_mark(void **ptr) | 403 | #include "../lib/inflate.c" |
| 416 | { | ||
| 417 | } | ||
| 418 | |||
| 419 | static void __init gzip_release(void **ptr) | ||
| 420 | { | ||
| 421 | } | ||
| 422 | 404 | ||
| 423 | /* =========================================================================== | 405 | /* =========================================================================== |
| 424 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | 406 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. |
diff --git a/init/main.c b/init/main.c index 2769dc031c62..0604cbcaf1e4 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -87,8 +87,6 @@ extern void init_IRQ(void); | |||
| 87 | extern void fork_init(unsigned long); | 87 | extern void fork_init(unsigned long); |
| 88 | extern void mca_init(void); | 88 | extern void mca_init(void); |
| 89 | extern void sbus_init(void); | 89 | extern void sbus_init(void); |
| 90 | extern void pidhash_init(void); | ||
| 91 | extern void pidmap_init(void); | ||
| 92 | extern void prio_tree_init(void); | 90 | extern void prio_tree_init(void); |
| 93 | extern void radix_tree_init(void); | 91 | extern void radix_tree_init(void); |
| 94 | extern void free_initmem(void); | 92 | extern void free_initmem(void); |
diff --git a/init/version.c b/init/version.c index 9d17d70ee02d..52a8b98642b8 100644 --- a/init/version.c +++ b/init/version.c | |||
| @@ -13,10 +13,13 @@ | |||
| 13 | #include <linux/utsrelease.h> | 13 | #include <linux/utsrelease.h> |
| 14 | #include <linux/version.h> | 14 | #include <linux/version.h> |
| 15 | 15 | ||
| 16 | #ifndef CONFIG_KALLSYMS | ||
| 16 | #define version(a) Version_ ## a | 17 | #define version(a) Version_ ## a |
| 17 | #define version_string(a) version(a) | 18 | #define version_string(a) version(a) |
| 18 | 19 | ||
| 20 | extern int version_string(LINUX_VERSION_CODE); | ||
| 19 | int version_string(LINUX_VERSION_CODE); | 21 | int version_string(LINUX_VERSION_CODE); |
| 22 | #endif | ||
| 20 | 23 | ||
| 21 | struct uts_namespace init_uts_ns = { | 24 | struct uts_namespace init_uts_ns = { |
| 22 | .kref = { | 25 | .kref = { |
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index d3497465cc0a..69bc85978ba0 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c | |||
| @@ -27,15 +27,17 @@ static void *get_ipc(ctl_table *table) | |||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | /* | 29 | /* |
| 30 | * Routine that is called when a tunable has successfully been changed by | 30 | * Routine that is called when the file "auto_msgmni" has successfully been |
| 31 | * hand and it has a callback routine registered on the ipc namespace notifier | 31 | * written. |
| 32 | * chain: we don't want such tunables to be recomputed anymore upon memory | 32 | * Two values are allowed: |
| 33 | * add/remove or ipc namespace creation/removal. | 33 | * 0: unregister msgmni's callback routine from the ipc namespace notifier |
| 34 | * They can come back to a recomputable state by being set to a <0 value. | 34 | * chain. This means that msgmni won't be recomputed anymore upon memory |
| 35 | * add/remove or ipc namespace creation/removal. | ||
| 36 | * 1: register back the callback routine. | ||
| 35 | */ | 37 | */ |
| 36 | static void tunable_set_callback(int val) | 38 | static void ipc_auto_callback(int val) |
| 37 | { | 39 | { |
| 38 | if (val >= 0) | 40 | if (!val) |
| 39 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | 41 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); |
| 40 | else { | 42 | else { |
| 41 | /* | 43 | /* |
| @@ -71,7 +73,12 @@ static int proc_ipc_callback_dointvec(ctl_table *table, int write, | |||
| 71 | rc = proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos); | 73 | rc = proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos); |
| 72 | 74 | ||
| 73 | if (write && !rc && lenp_bef == *lenp) | 75 | if (write && !rc && lenp_bef == *lenp) |
| 74 | tunable_set_callback(*((int *)(ipc_table.data))); | 76 | /* |
| 77 | * Tunable has successfully been changed by hand. Disable its | ||
| 78 | * automatic adjustment. This simply requires unregistering | ||
| 79 | * the notifiers that trigger recalculation. | ||
| 80 | */ | ||
| 81 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | ||
| 75 | 82 | ||
| 76 | return rc; | 83 | return rc; |
| 77 | } | 84 | } |
| @@ -87,10 +94,39 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, | |||
| 87 | lenp, ppos); | 94 | lenp, ppos); |
| 88 | } | 95 | } |
| 89 | 96 | ||
| 97 | static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, | ||
| 98 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) | ||
| 99 | { | ||
| 100 | struct ctl_table ipc_table; | ||
| 101 | size_t lenp_bef = *lenp; | ||
| 102 | int oldval; | ||
| 103 | int rc; | ||
| 104 | |||
| 105 | memcpy(&ipc_table, table, sizeof(ipc_table)); | ||
| 106 | ipc_table.data = get_ipc(table); | ||
| 107 | oldval = *((int *)(ipc_table.data)); | ||
| 108 | |||
| 109 | rc = proc_dointvec_minmax(&ipc_table, write, filp, buffer, lenp, ppos); | ||
| 110 | |||
| 111 | if (write && !rc && lenp_bef == *lenp) { | ||
| 112 | int newval = *((int *)(ipc_table.data)); | ||
| 113 | /* | ||
| 114 | * The file "auto_msgmni" has correctly been set. | ||
| 115 | * React by (un)registering the corresponding tunable, if the | ||
| 116 | * value has changed. | ||
| 117 | */ | ||
| 118 | if (newval != oldval) | ||
| 119 | ipc_auto_callback(newval); | ||
| 120 | } | ||
| 121 | |||
| 122 | return rc; | ||
| 123 | } | ||
| 124 | |||
| 90 | #else | 125 | #else |
| 91 | #define proc_ipc_doulongvec_minmax NULL | 126 | #define proc_ipc_doulongvec_minmax NULL |
| 92 | #define proc_ipc_dointvec NULL | 127 | #define proc_ipc_dointvec NULL |
| 93 | #define proc_ipc_callback_dointvec NULL | 128 | #define proc_ipc_callback_dointvec NULL |
| 129 | #define proc_ipcauto_dointvec_minmax NULL | ||
| 94 | #endif | 130 | #endif |
| 95 | 131 | ||
| 96 | #ifdef CONFIG_SYSCTL_SYSCALL | 132 | #ifdef CONFIG_SYSCTL_SYSCALL |
| @@ -142,14 +178,11 @@ static int sysctl_ipc_registered_data(ctl_table *table, int __user *name, | |||
| 142 | rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval, | 178 | rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval, |
| 143 | newlen); | 179 | newlen); |
| 144 | 180 | ||
| 145 | if (newval && newlen && rc > 0) { | 181 | if (newval && newlen && rc > 0) |
| 146 | /* | 182 | /* |
| 147 | * Tunable has successfully been changed from userland | 183 | * Tunable has successfully been changed from userland |
| 148 | */ | 184 | */ |
| 149 | int *data = get_ipc(table); | 185 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); |
| 150 | |||
| 151 | tunable_set_callback(*data); | ||
| 152 | } | ||
| 153 | 186 | ||
| 154 | return rc; | 187 | return rc; |
| 155 | } | 188 | } |
| @@ -158,6 +191,9 @@ static int sysctl_ipc_registered_data(ctl_table *table, int __user *name, | |||
| 158 | #define sysctl_ipc_registered_data NULL | 191 | #define sysctl_ipc_registered_data NULL |
| 159 | #endif | 192 | #endif |
| 160 | 193 | ||
| 194 | static int zero; | ||
| 195 | static int one = 1; | ||
| 196 | |||
| 161 | static struct ctl_table ipc_kern_table[] = { | 197 | static struct ctl_table ipc_kern_table[] = { |
| 162 | { | 198 | { |
| 163 | .ctl_name = KERN_SHMMAX, | 199 | .ctl_name = KERN_SHMMAX, |
| @@ -222,6 +258,16 @@ static struct ctl_table ipc_kern_table[] = { | |||
| 222 | .proc_handler = proc_ipc_dointvec, | 258 | .proc_handler = proc_ipc_dointvec, |
| 223 | .strategy = sysctl_ipc_data, | 259 | .strategy = sysctl_ipc_data, |
| 224 | }, | 260 | }, |
| 261 | { | ||
| 262 | .ctl_name = CTL_UNNUMBERED, | ||
| 263 | .procname = "auto_msgmni", | ||
| 264 | .data = &init_ipc_ns.auto_msgmni, | ||
| 265 | .maxlen = sizeof(int), | ||
| 266 | .mode = 0644, | ||
| 267 | .proc_handler = proc_ipcauto_dointvec_minmax, | ||
| 268 | .extra1 = &zero, | ||
| 269 | .extra2 = &one, | ||
| 270 | }, | ||
| 225 | {} | 271 | {} |
| 226 | }; | 272 | }; |
| 227 | 273 | ||
diff --git a/ipc/ipcns_notifier.c b/ipc/ipcns_notifier.c index 70ff09183f7b..b9b31a4f77e1 100644 --- a/ipc/ipcns_notifier.c +++ b/ipc/ipcns_notifier.c | |||
| @@ -55,25 +55,35 @@ static int ipcns_callback(struct notifier_block *self, | |||
| 55 | 55 | ||
| 56 | int register_ipcns_notifier(struct ipc_namespace *ns) | 56 | int register_ipcns_notifier(struct ipc_namespace *ns) |
| 57 | { | 57 | { |
| 58 | int rc; | ||
| 59 | |||
| 58 | memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb)); | 60 | memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb)); |
| 59 | ns->ipcns_nb.notifier_call = ipcns_callback; | 61 | ns->ipcns_nb.notifier_call = ipcns_callback; |
| 60 | ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI; | 62 | ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI; |
| 61 | return blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb); | 63 | rc = blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb); |
| 64 | if (!rc) | ||
| 65 | ns->auto_msgmni = 1; | ||
| 66 | return rc; | ||
| 62 | } | 67 | } |
| 63 | 68 | ||
| 64 | int cond_register_ipcns_notifier(struct ipc_namespace *ns) | 69 | int cond_register_ipcns_notifier(struct ipc_namespace *ns) |
| 65 | { | 70 | { |
| 71 | int rc; | ||
| 72 | |||
| 66 | memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb)); | 73 | memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb)); |
| 67 | ns->ipcns_nb.notifier_call = ipcns_callback; | 74 | ns->ipcns_nb.notifier_call = ipcns_callback; |
| 68 | ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI; | 75 | ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI; |
| 69 | return blocking_notifier_chain_cond_register(&ipcns_chain, | 76 | rc = blocking_notifier_chain_cond_register(&ipcns_chain, |
| 70 | &ns->ipcns_nb); | 77 | &ns->ipcns_nb); |
| 78 | if (!rc) | ||
| 79 | ns->auto_msgmni = 1; | ||
| 80 | return rc; | ||
| 71 | } | 81 | } |
| 72 | 82 | ||
| 73 | int unregister_ipcns_notifier(struct ipc_namespace *ns) | 83 | void unregister_ipcns_notifier(struct ipc_namespace *ns) |
| 74 | { | 84 | { |
| 75 | return blocking_notifier_chain_unregister(&ipcns_chain, | 85 | blocking_notifier_chain_unregister(&ipcns_chain, &ns->ipcns_nb); |
| 76 | &ns->ipcns_nb); | 86 | ns->auto_msgmni = 0; |
| 77 | } | 87 | } |
| 78 | 88 | ||
| 79 | int ipcns_notify(unsigned long val) | 89 | int ipcns_notify(unsigned long val) |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 3e84b958186b..1fdc2eb2f6d8 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
| @@ -314,15 +314,11 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry) | |||
| 314 | * through std routines) | 314 | * through std routines) |
| 315 | */ | 315 | */ |
| 316 | static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, | 316 | static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, |
| 317 | size_t count, loff_t * off) | 317 | size_t count, loff_t *off) |
| 318 | { | 318 | { |
| 319 | struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode); | 319 | struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode); |
| 320 | char buffer[FILENT_SIZE]; | 320 | char buffer[FILENT_SIZE]; |
| 321 | size_t slen; | 321 | ssize_t ret; |
| 322 | loff_t o; | ||
| 323 | |||
| 324 | if (!count) | ||
| 325 | return 0; | ||
| 326 | 322 | ||
| 327 | spin_lock(&info->lock); | 323 | spin_lock(&info->lock); |
| 328 | snprintf(buffer, sizeof(buffer), | 324 | snprintf(buffer, sizeof(buffer), |
| @@ -335,21 +331,14 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data, | |||
| 335 | pid_vnr(info->notify_owner)); | 331 | pid_vnr(info->notify_owner)); |
| 336 | spin_unlock(&info->lock); | 332 | spin_unlock(&info->lock); |
| 337 | buffer[sizeof(buffer)-1] = '\0'; | 333 | buffer[sizeof(buffer)-1] = '\0'; |
| 338 | slen = strlen(buffer)+1; | ||
| 339 | |||
| 340 | o = *off; | ||
| 341 | if (o > slen) | ||
| 342 | return 0; | ||
| 343 | |||
| 344 | if (o + count > slen) | ||
| 345 | count = slen - o; | ||
| 346 | 334 | ||
| 347 | if (copy_to_user(u_data, buffer + o, count)) | 335 | ret = simple_read_from_buffer(u_data, count, off, buffer, |
| 348 | return -EFAULT; | 336 | strlen(buffer)); |
| 337 | if (ret <= 0) | ||
| 338 | return ret; | ||
| 349 | 339 | ||
| 350 | *off = o + count; | ||
| 351 | filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME; | 340 | filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME; |
| 352 | return count; | 341 | return ret; |
| 353 | } | 342 | } |
| 354 | 343 | ||
| 355 | static int mqueue_flush_file(struct file *filp, fl_owner_t id) | 344 | static int mqueue_flush_file(struct file *filp, fl_owner_t id) |
| @@ -272,9 +272,8 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) | |||
| 272 | ns->used_sems += nsems; | 272 | ns->used_sems += nsems; |
| 273 | 273 | ||
| 274 | sma->sem_base = (struct sem *) &sma[1]; | 274 | sma->sem_base = (struct sem *) &sma[1]; |
| 275 | /* sma->sem_pending = NULL; */ | 275 | INIT_LIST_HEAD(&sma->sem_pending); |
| 276 | sma->sem_pending_last = &sma->sem_pending; | 276 | INIT_LIST_HEAD(&sma->list_id); |
| 277 | /* sma->undo = NULL; */ | ||
| 278 | sma->sem_nsems = nsems; | 277 | sma->sem_nsems = nsems; |
| 279 | sma->sem_ctime = get_seconds(); | 278 | sma->sem_ctime = get_seconds(); |
| 280 | sem_unlock(sma); | 279 | sem_unlock(sma); |
| @@ -331,38 +330,6 @@ asmlinkage long sys_semget(key_t key, int nsems, int semflg) | |||
| 331 | return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); | 330 | return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); |
| 332 | } | 331 | } |
| 333 | 332 | ||
| 334 | /* Manage the doubly linked list sma->sem_pending as a FIFO: | ||
| 335 | * insert new queue elements at the tail sma->sem_pending_last. | ||
| 336 | */ | ||
| 337 | static inline void append_to_queue (struct sem_array * sma, | ||
| 338 | struct sem_queue * q) | ||
| 339 | { | ||
| 340 | *(q->prev = sma->sem_pending_last) = q; | ||
| 341 | *(sma->sem_pending_last = &q->next) = NULL; | ||
| 342 | } | ||
| 343 | |||
| 344 | static inline void prepend_to_queue (struct sem_array * sma, | ||
| 345 | struct sem_queue * q) | ||
| 346 | { | ||
| 347 | q->next = sma->sem_pending; | ||
| 348 | *(q->prev = &sma->sem_pending) = q; | ||
| 349 | if (q->next) | ||
| 350 | q->next->prev = &q->next; | ||
| 351 | else /* sma->sem_pending_last == &sma->sem_pending */ | ||
| 352 | sma->sem_pending_last = &q->next; | ||
| 353 | } | ||
| 354 | |||
| 355 | static inline void remove_from_queue (struct sem_array * sma, | ||
| 356 | struct sem_queue * q) | ||
| 357 | { | ||
| 358 | *(q->prev) = q->next; | ||
| 359 | if (q->next) | ||
| 360 | q->next->prev = q->prev; | ||
| 361 | else /* sma->sem_pending_last == &q->next */ | ||
| 362 | sma->sem_pending_last = q->prev; | ||
| 363 | q->prev = NULL; /* mark as removed */ | ||
| 364 | } | ||
| 365 | |||
| 366 | /* | 333 | /* |
| 367 | * Determine whether a sequence of semaphore operations would succeed | 334 | * Determine whether a sequence of semaphore operations would succeed |
| 368 | * all at once. Return 0 if yes, 1 if need to sleep, else return error code. | 335 | * all at once. Return 0 if yes, 1 if need to sleep, else return error code. |
| @@ -438,16 +405,15 @@ static void update_queue (struct sem_array * sma) | |||
| 438 | int error; | 405 | int error; |
| 439 | struct sem_queue * q; | 406 | struct sem_queue * q; |
| 440 | 407 | ||
| 441 | q = sma->sem_pending; | 408 | q = list_entry(sma->sem_pending.next, struct sem_queue, list); |
| 442 | while(q) { | 409 | while (&q->list != &sma->sem_pending) { |
| 443 | error = try_atomic_semop(sma, q->sops, q->nsops, | 410 | error = try_atomic_semop(sma, q->sops, q->nsops, |
| 444 | q->undo, q->pid); | 411 | q->undo, q->pid); |
| 445 | 412 | ||
| 446 | /* Does q->sleeper still need to sleep? */ | 413 | /* Does q->sleeper still need to sleep? */ |
| 447 | if (error <= 0) { | 414 | if (error <= 0) { |
| 448 | struct sem_queue *n; | 415 | struct sem_queue *n; |
| 449 | remove_from_queue(sma,q); | 416 | |
| 450 | q->status = IN_WAKEUP; | ||
| 451 | /* | 417 | /* |
| 452 | * Continue scanning. The next operation | 418 | * Continue scanning. The next operation |
| 453 | * that must be checked depends on the type of the | 419 | * that must be checked depends on the type of the |
| @@ -458,11 +424,26 @@ static void update_queue (struct sem_array * sma) | |||
| 458 | * for semaphore values to become 0. | 424 | * for semaphore values to become 0. |
| 459 | * - if the operation didn't modify the array, | 425 | * - if the operation didn't modify the array, |
| 460 | * then just continue. | 426 | * then just continue. |
| 427 | * The order of list_del() and reading ->next | ||
| 428 | * is crucial: In the former case, the list_del() | ||
| 429 | * must be done first [because we might be the | ||
| 430 | * first entry in ->sem_pending], in the latter | ||
| 431 | * case the list_del() must be done last | ||
| 432 | * [because the list is invalid after the list_del()] | ||
| 461 | */ | 433 | */ |
| 462 | if (q->alter) | 434 | if (q->alter) { |
| 463 | n = sma->sem_pending; | 435 | list_del(&q->list); |
| 464 | else | 436 | n = list_entry(sma->sem_pending.next, |
| 465 | n = q->next; | 437 | struct sem_queue, list); |
| 438 | } else { | ||
| 439 | n = list_entry(q->list.next, struct sem_queue, | ||
| 440 | list); | ||
| 441 | list_del(&q->list); | ||
| 442 | } | ||
| 443 | |||
| 444 | /* wake up the waiting thread */ | ||
| 445 | q->status = IN_WAKEUP; | ||
| 446 | |||
| 466 | wake_up_process(q->sleeper); | 447 | wake_up_process(q->sleeper); |
| 467 | /* hands-off: q will disappear immediately after | 448 | /* hands-off: q will disappear immediately after |
| 468 | * writing q->status. | 449 | * writing q->status. |
| @@ -471,7 +452,7 @@ static void update_queue (struct sem_array * sma) | |||
| 471 | q->status = error; | 452 | q->status = error; |
| 472 | q = n; | 453 | q = n; |
| 473 | } else { | 454 | } else { |
| 474 | q = q->next; | 455 | q = list_entry(q->list.next, struct sem_queue, list); |
| 475 | } | 456 | } |
| 476 | } | 457 | } |
| 477 | } | 458 | } |
| @@ -491,7 +472,7 @@ static int count_semncnt (struct sem_array * sma, ushort semnum) | |||
| 491 | struct sem_queue * q; | 472 | struct sem_queue * q; |
| 492 | 473 | ||
| 493 | semncnt = 0; | 474 | semncnt = 0; |
| 494 | for (q = sma->sem_pending; q; q = q->next) { | 475 | list_for_each_entry(q, &sma->sem_pending, list) { |
| 495 | struct sembuf * sops = q->sops; | 476 | struct sembuf * sops = q->sops; |
| 496 | int nsops = q->nsops; | 477 | int nsops = q->nsops; |
| 497 | int i; | 478 | int i; |
| @@ -503,13 +484,14 @@ static int count_semncnt (struct sem_array * sma, ushort semnum) | |||
| 503 | } | 484 | } |
| 504 | return semncnt; | 485 | return semncnt; |
| 505 | } | 486 | } |
| 487 | |||
| 506 | static int count_semzcnt (struct sem_array * sma, ushort semnum) | 488 | static int count_semzcnt (struct sem_array * sma, ushort semnum) |
| 507 | { | 489 | { |
| 508 | int semzcnt; | 490 | int semzcnt; |
| 509 | struct sem_queue * q; | 491 | struct sem_queue * q; |
| 510 | 492 | ||
| 511 | semzcnt = 0; | 493 | semzcnt = 0; |
| 512 | for (q = sma->sem_pending; q; q = q->next) { | 494 | list_for_each_entry(q, &sma->sem_pending, list) { |
| 513 | struct sembuf * sops = q->sops; | 495 | struct sembuf * sops = q->sops; |
| 514 | int nsops = q->nsops; | 496 | int nsops = q->nsops; |
| 515 | int i; | 497 | int i; |
| @@ -522,35 +504,41 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum) | |||
| 522 | return semzcnt; | 504 | return semzcnt; |
| 523 | } | 505 | } |
| 524 | 506 | ||
| 507 | void free_un(struct rcu_head *head) | ||
| 508 | { | ||
| 509 | struct sem_undo *un = container_of(head, struct sem_undo, rcu); | ||
| 510 | kfree(un); | ||
| 511 | } | ||
| 512 | |||
| 525 | /* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked | 513 | /* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked |
| 526 | * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex | 514 | * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex |
| 527 | * remains locked on exit. | 515 | * remains locked on exit. |
| 528 | */ | 516 | */ |
| 529 | static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | 517 | static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) |
| 530 | { | 518 | { |
| 531 | struct sem_undo *un; | 519 | struct sem_undo *un, *tu; |
| 532 | struct sem_queue *q; | 520 | struct sem_queue *q, *tq; |
| 533 | struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm); | 521 | struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm); |
| 534 | 522 | ||
| 535 | /* Invalidate the existing undo structures for this semaphore set. | 523 | /* Free the existing undo structures for this semaphore set. */ |
| 536 | * (They will be freed without any further action in exit_sem() | 524 | assert_spin_locked(&sma->sem_perm.lock); |
| 537 | * or during the next semop.) | 525 | list_for_each_entry_safe(un, tu, &sma->list_id, list_id) { |
| 538 | */ | 526 | list_del(&un->list_id); |
| 539 | for (un = sma->undo; un; un = un->id_next) | 527 | spin_lock(&un->ulp->lock); |
| 540 | un->semid = -1; | 528 | un->semid = -1; |
| 529 | list_del_rcu(&un->list_proc); | ||
| 530 | spin_unlock(&un->ulp->lock); | ||
| 531 | call_rcu(&un->rcu, free_un); | ||
| 532 | } | ||
| 541 | 533 | ||
| 542 | /* Wake up all pending processes and let them fail with EIDRM. */ | 534 | /* Wake up all pending processes and let them fail with EIDRM. */ |
| 543 | q = sma->sem_pending; | 535 | list_for_each_entry_safe(q, tq, &sma->sem_pending, list) { |
| 544 | while(q) { | 536 | list_del(&q->list); |
| 545 | struct sem_queue *n; | 537 | |
| 546 | /* lazy remove_from_queue: we are killing the whole queue */ | ||
| 547 | q->prev = NULL; | ||
| 548 | n = q->next; | ||
| 549 | q->status = IN_WAKEUP; | 538 | q->status = IN_WAKEUP; |
| 550 | wake_up_process(q->sleeper); /* doesn't sleep */ | 539 | wake_up_process(q->sleeper); /* doesn't sleep */ |
| 551 | smp_wmb(); | 540 | smp_wmb(); |
| 552 | q->status = -EIDRM; /* hands-off q */ | 541 | q->status = -EIDRM; /* hands-off q */ |
| 553 | q = n; | ||
| 554 | } | 542 | } |
| 555 | 543 | ||
| 556 | /* Remove the semaphore set from the IDR */ | 544 | /* Remove the semaphore set from the IDR */ |
| @@ -763,9 +751,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
| 763 | 751 | ||
| 764 | for (i = 0; i < nsems; i++) | 752 | for (i = 0; i < nsems; i++) |
| 765 | sma->sem_base[i].semval = sem_io[i]; | 753 | sma->sem_base[i].semval = sem_io[i]; |
| 766 | for (un = sma->undo; un; un = un->id_next) | 754 | |
| 755 | assert_spin_locked(&sma->sem_perm.lock); | ||
| 756 | list_for_each_entry(un, &sma->list_id, list_id) { | ||
| 767 | for (i = 0; i < nsems; i++) | 757 | for (i = 0; i < nsems; i++) |
| 768 | un->semadj[i] = 0; | 758 | un->semadj[i] = 0; |
| 759 | } | ||
| 769 | sma->sem_ctime = get_seconds(); | 760 | sma->sem_ctime = get_seconds(); |
| 770 | /* maybe some queued-up processes were waiting for this */ | 761 | /* maybe some queued-up processes were waiting for this */ |
| 771 | update_queue(sma); | 762 | update_queue(sma); |
| @@ -797,12 +788,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
| 797 | { | 788 | { |
| 798 | int val = arg.val; | 789 | int val = arg.val; |
| 799 | struct sem_undo *un; | 790 | struct sem_undo *un; |
| 791 | |||
| 800 | err = -ERANGE; | 792 | err = -ERANGE; |
| 801 | if (val > SEMVMX || val < 0) | 793 | if (val > SEMVMX || val < 0) |
| 802 | goto out_unlock; | 794 | goto out_unlock; |
| 803 | 795 | ||
| 804 | for (un = sma->undo; un; un = un->id_next) | 796 | assert_spin_locked(&sma->sem_perm.lock); |
| 797 | list_for_each_entry(un, &sma->list_id, list_id) | ||
| 805 | un->semadj[semnum] = 0; | 798 | un->semadj[semnum] = 0; |
| 799 | |||
| 806 | curr->semval = val; | 800 | curr->semval = val; |
| 807 | curr->sempid = task_tgid_vnr(current); | 801 | curr->sempid = task_tgid_vnr(current); |
| 808 | sma->sem_ctime = get_seconds(); | 802 | sma->sem_ctime = get_seconds(); |
| @@ -952,6 +946,8 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp) | |||
| 952 | return -ENOMEM; | 946 | return -ENOMEM; |
| 953 | spin_lock_init(&undo_list->lock); | 947 | spin_lock_init(&undo_list->lock); |
| 954 | atomic_set(&undo_list->refcnt, 1); | 948 | atomic_set(&undo_list->refcnt, 1); |
| 949 | INIT_LIST_HEAD(&undo_list->list_proc); | ||
| 950 | |||
| 955 | current->sysvsem.undo_list = undo_list; | 951 | current->sysvsem.undo_list = undo_list; |
| 956 | } | 952 | } |
| 957 | *undo_listp = undo_list; | 953 | *undo_listp = undo_list; |
| @@ -960,25 +956,27 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp) | |||
| 960 | 956 | ||
| 961 | static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid) | 957 | static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid) |
| 962 | { | 958 | { |
| 963 | struct sem_undo **last, *un; | 959 | struct sem_undo *walk; |
| 964 | 960 | ||
| 965 | last = &ulp->proc_list; | 961 | list_for_each_entry_rcu(walk, &ulp->list_proc, list_proc) { |
| 966 | un = *last; | 962 | if (walk->semid == semid) |
| 967 | while(un != NULL) { | 963 | return walk; |
| 968 | if(un->semid==semid) | ||
| 969 | break; | ||
| 970 | if(un->semid==-1) { | ||
| 971 | *last=un->proc_next; | ||
| 972 | kfree(un); | ||
| 973 | } else { | ||
| 974 | last=&un->proc_next; | ||
| 975 | } | ||
| 976 | un=*last; | ||
| 977 | } | 964 | } |
| 978 | return un; | 965 | return NULL; |
| 979 | } | 966 | } |
| 980 | 967 | ||
| 981 | static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid) | 968 | /** |
| 969 | * find_alloc_undo - Lookup (and if not present create) undo array | ||
| 970 | * @ns: namespace | ||
| 971 | * @semid: semaphore array id | ||
| 972 | * | ||
| 973 | * The function looks up (and if not present creates) the undo structure. | ||
| 974 | * The size of the undo structure depends on the size of the semaphore | ||
| 975 | * array, thus the alloc path is not that straightforward. | ||
| 976 | * Lifetime-rules: sem_undo is rcu-protected, on success, the function | ||
| 977 | * performs a rcu_read_lock(). | ||
| 978 | */ | ||
| 979 | static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) | ||
| 982 | { | 980 | { |
| 983 | struct sem_array *sma; | 981 | struct sem_array *sma; |
| 984 | struct sem_undo_list *ulp; | 982 | struct sem_undo_list *ulp; |
| @@ -990,13 +988,16 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid) | |||
| 990 | if (error) | 988 | if (error) |
| 991 | return ERR_PTR(error); | 989 | return ERR_PTR(error); |
| 992 | 990 | ||
| 991 | rcu_read_lock(); | ||
| 993 | spin_lock(&ulp->lock); | 992 | spin_lock(&ulp->lock); |
| 994 | un = lookup_undo(ulp, semid); | 993 | un = lookup_undo(ulp, semid); |
| 995 | spin_unlock(&ulp->lock); | 994 | spin_unlock(&ulp->lock); |
| 996 | if (likely(un!=NULL)) | 995 | if (likely(un!=NULL)) |
| 997 | goto out; | 996 | goto out; |
| 997 | rcu_read_unlock(); | ||
| 998 | 998 | ||
| 999 | /* no undo structure around - allocate one. */ | 999 | /* no undo structure around - allocate one. */ |
| 1000 | /* step 1: figure out the size of the semaphore array */ | ||
| 1000 | sma = sem_lock_check(ns, semid); | 1001 | sma = sem_lock_check(ns, semid); |
| 1001 | if (IS_ERR(sma)) | 1002 | if (IS_ERR(sma)) |
| 1002 | return ERR_PTR(PTR_ERR(sma)); | 1003 | return ERR_PTR(PTR_ERR(sma)); |
| @@ -1004,37 +1005,45 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid) | |||
| 1004 | nsems = sma->sem_nsems; | 1005 | nsems = sma->sem_nsems; |
| 1005 | sem_getref_and_unlock(sma); | 1006 | sem_getref_and_unlock(sma); |
| 1006 | 1007 | ||
| 1008 | /* step 2: allocate new undo structure */ | ||
| 1007 | new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL); | 1009 | new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL); |
| 1008 | if (!new) { | 1010 | if (!new) { |
| 1009 | sem_putref(sma); | 1011 | sem_putref(sma); |
| 1010 | return ERR_PTR(-ENOMEM); | 1012 | return ERR_PTR(-ENOMEM); |
| 1011 | } | 1013 | } |
| 1012 | new->semadj = (short *) &new[1]; | ||
| 1013 | new->semid = semid; | ||
| 1014 | 1014 | ||
| 1015 | spin_lock(&ulp->lock); | 1015 | /* step 3: Acquire the lock on semaphore array */ |
| 1016 | un = lookup_undo(ulp, semid); | ||
| 1017 | if (un) { | ||
| 1018 | spin_unlock(&ulp->lock); | ||
| 1019 | kfree(new); | ||
| 1020 | sem_putref(sma); | ||
| 1021 | goto out; | ||
| 1022 | } | ||
| 1023 | sem_lock_and_putref(sma); | 1016 | sem_lock_and_putref(sma); |
| 1024 | if (sma->sem_perm.deleted) { | 1017 | if (sma->sem_perm.deleted) { |
| 1025 | sem_unlock(sma); | 1018 | sem_unlock(sma); |
| 1026 | spin_unlock(&ulp->lock); | ||
| 1027 | kfree(new); | 1019 | kfree(new); |
| 1028 | un = ERR_PTR(-EIDRM); | 1020 | un = ERR_PTR(-EIDRM); |
| 1029 | goto out; | 1021 | goto out; |
| 1030 | } | 1022 | } |
| 1031 | new->proc_next = ulp->proc_list; | 1023 | spin_lock(&ulp->lock); |
| 1032 | ulp->proc_list = new; | 1024 | |
| 1033 | new->id_next = sma->undo; | 1025 | /* |
| 1034 | sma->undo = new; | 1026 | * step 4: check for races: did someone else allocate the undo struct? |
| 1035 | sem_unlock(sma); | 1027 | */ |
| 1028 | un = lookup_undo(ulp, semid); | ||
| 1029 | if (un) { | ||
| 1030 | kfree(new); | ||
| 1031 | goto success; | ||
| 1032 | } | ||
| 1033 | /* step 5: initialize & link new undo structure */ | ||
| 1034 | new->semadj = (short *) &new[1]; | ||
| 1035 | new->ulp = ulp; | ||
| 1036 | new->semid = semid; | ||
| 1037 | assert_spin_locked(&ulp->lock); | ||
| 1038 | list_add_rcu(&new->list_proc, &ulp->list_proc); | ||
| 1039 | assert_spin_locked(&sma->sem_perm.lock); | ||
| 1040 | list_add(&new->list_id, &sma->list_id); | ||
| 1036 | un = new; | 1041 | un = new; |
| 1042 | |||
| 1043 | success: | ||
| 1037 | spin_unlock(&ulp->lock); | 1044 | spin_unlock(&ulp->lock); |
| 1045 | rcu_read_lock(); | ||
| 1046 | sem_unlock(sma); | ||
| 1038 | out: | 1047 | out: |
| 1039 | return un; | 1048 | return un; |
| 1040 | } | 1049 | } |
| @@ -1090,9 +1099,8 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, | |||
| 1090 | alter = 1; | 1099 | alter = 1; |
| 1091 | } | 1100 | } |
| 1092 | 1101 | ||
| 1093 | retry_undos: | ||
| 1094 | if (undos) { | 1102 | if (undos) { |
| 1095 | un = find_undo(ns, semid); | 1103 | un = find_alloc_undo(ns, semid); |
| 1096 | if (IS_ERR(un)) { | 1104 | if (IS_ERR(un)) { |
| 1097 | error = PTR_ERR(un); | 1105 | error = PTR_ERR(un); |
| 1098 | goto out_free; | 1106 | goto out_free; |
| @@ -1102,19 +1110,37 @@ retry_undos: | |||
| 1102 | 1110 | ||
| 1103 | sma = sem_lock_check(ns, semid); | 1111 | sma = sem_lock_check(ns, semid); |
| 1104 | if (IS_ERR(sma)) { | 1112 | if (IS_ERR(sma)) { |
| 1113 | if (un) | ||
| 1114 | rcu_read_unlock(); | ||
| 1105 | error = PTR_ERR(sma); | 1115 | error = PTR_ERR(sma); |
| 1106 | goto out_free; | 1116 | goto out_free; |
| 1107 | } | 1117 | } |
| 1108 | 1118 | ||
| 1109 | /* | 1119 | /* |
| 1110 | * semid identifiers are not unique - find_undo may have | 1120 | * semid identifiers are not unique - find_alloc_undo may have |
| 1111 | * allocated an undo structure, it was invalidated by an RMID | 1121 | * allocated an undo structure, it was invalidated by an RMID |
| 1112 | * and now a new array with received the same id. Check and retry. | 1122 | * and now a new array with received the same id. Check and fail. |
| 1123 | * This case can be detected checking un->semid. The existance of | ||
| 1124 | * "un" itself is guaranteed by rcu. | ||
| 1113 | */ | 1125 | */ |
| 1114 | if (un && un->semid == -1) { | 1126 | error = -EIDRM; |
| 1115 | sem_unlock(sma); | 1127 | if (un) { |
| 1116 | goto retry_undos; | 1128 | if (un->semid == -1) { |
| 1129 | rcu_read_unlock(); | ||
| 1130 | goto out_unlock_free; | ||
| 1131 | } else { | ||
| 1132 | /* | ||
| 1133 | * rcu lock can be released, "un" cannot disappear: | ||
| 1134 | * - sem_lock is acquired, thus IPC_RMID is | ||
| 1135 | * impossible. | ||
| 1136 | * - exit_sem is impossible, it always operates on | ||
| 1137 | * current (or a dead task). | ||
| 1138 | */ | ||
| 1139 | |||
| 1140 | rcu_read_unlock(); | ||
| 1141 | } | ||
| 1117 | } | 1142 | } |
| 1143 | |||
| 1118 | error = -EFBIG; | 1144 | error = -EFBIG; |
| 1119 | if (max >= sma->sem_nsems) | 1145 | if (max >= sma->sem_nsems) |
| 1120 | goto out_unlock_free; | 1146 | goto out_unlock_free; |
| @@ -1138,17 +1164,15 @@ retry_undos: | |||
| 1138 | * task into the pending queue and go to sleep. | 1164 | * task into the pending queue and go to sleep. |
| 1139 | */ | 1165 | */ |
| 1140 | 1166 | ||
| 1141 | queue.sma = sma; | ||
| 1142 | queue.sops = sops; | 1167 | queue.sops = sops; |
| 1143 | queue.nsops = nsops; | 1168 | queue.nsops = nsops; |
| 1144 | queue.undo = un; | 1169 | queue.undo = un; |
| 1145 | queue.pid = task_tgid_vnr(current); | 1170 | queue.pid = task_tgid_vnr(current); |
| 1146 | queue.id = semid; | ||
| 1147 | queue.alter = alter; | 1171 | queue.alter = alter; |
| 1148 | if (alter) | 1172 | if (alter) |
| 1149 | append_to_queue(sma ,&queue); | 1173 | list_add_tail(&queue.list, &sma->sem_pending); |
| 1150 | else | 1174 | else |
| 1151 | prepend_to_queue(sma ,&queue); | 1175 | list_add(&queue.list, &sma->sem_pending); |
| 1152 | 1176 | ||
| 1153 | queue.status = -EINTR; | 1177 | queue.status = -EINTR; |
| 1154 | queue.sleeper = current; | 1178 | queue.sleeper = current; |
| @@ -1174,7 +1198,6 @@ retry_undos: | |||
| 1174 | 1198 | ||
| 1175 | sma = sem_lock(ns, semid); | 1199 | sma = sem_lock(ns, semid); |
| 1176 | if (IS_ERR(sma)) { | 1200 | if (IS_ERR(sma)) { |
| 1177 | BUG_ON(queue.prev != NULL); | ||
| 1178 | error = -EIDRM; | 1201 | error = -EIDRM; |
| 1179 | goto out_free; | 1202 | goto out_free; |
| 1180 | } | 1203 | } |
| @@ -1192,7 +1215,7 @@ retry_undos: | |||
| 1192 | */ | 1215 | */ |
| 1193 | if (timeout && jiffies_left == 0) | 1216 | if (timeout && jiffies_left == 0) |
| 1194 | error = -EAGAIN; | 1217 | error = -EAGAIN; |
| 1195 | remove_from_queue(sma,&queue); | 1218 | list_del(&queue.list); |
| 1196 | goto out_unlock_free; | 1219 | goto out_unlock_free; |
| 1197 | 1220 | ||
| 1198 | out_unlock_free: | 1221 | out_unlock_free: |
| @@ -1243,56 +1266,62 @@ int copy_semundo(unsigned long clone_flags, struct task_struct *tsk) | |||
| 1243 | */ | 1266 | */ |
| 1244 | void exit_sem(struct task_struct *tsk) | 1267 | void exit_sem(struct task_struct *tsk) |
| 1245 | { | 1268 | { |
| 1246 | struct sem_undo_list *undo_list; | 1269 | struct sem_undo_list *ulp; |
| 1247 | struct sem_undo *u, **up; | ||
| 1248 | struct ipc_namespace *ns; | ||
| 1249 | 1270 | ||
| 1250 | undo_list = tsk->sysvsem.undo_list; | 1271 | ulp = tsk->sysvsem.undo_list; |
| 1251 | if (!undo_list) | 1272 | if (!ulp) |
| 1252 | return; | 1273 | return; |
| 1253 | tsk->sysvsem.undo_list = NULL; | 1274 | tsk->sysvsem.undo_list = NULL; |
| 1254 | 1275 | ||
| 1255 | if (!atomic_dec_and_test(&undo_list->refcnt)) | 1276 | if (!atomic_dec_and_test(&ulp->refcnt)) |
| 1256 | return; | 1277 | return; |
| 1257 | 1278 | ||
| 1258 | ns = tsk->nsproxy->ipc_ns; | 1279 | for (;;) { |
| 1259 | /* There's no need to hold the semundo list lock, as current | ||
| 1260 | * is the last task exiting for this undo list. | ||
| 1261 | */ | ||
| 1262 | for (up = &undo_list->proc_list; (u = *up); *up = u->proc_next, kfree(u)) { | ||
| 1263 | struct sem_array *sma; | 1280 | struct sem_array *sma; |
| 1264 | int nsems, i; | 1281 | struct sem_undo *un; |
| 1265 | struct sem_undo *un, **unp; | ||
| 1266 | int semid; | 1282 | int semid; |
| 1267 | 1283 | int i; | |
| 1268 | semid = u->semid; | ||
| 1269 | 1284 | ||
| 1270 | if(semid == -1) | 1285 | rcu_read_lock(); |
| 1271 | continue; | 1286 | un = list_entry(rcu_dereference(ulp->list_proc.next), |
| 1272 | sma = sem_lock(ns, semid); | 1287 | struct sem_undo, list_proc); |
| 1288 | if (&un->list_proc == &ulp->list_proc) | ||
| 1289 | semid = -1; | ||
| 1290 | else | ||
| 1291 | semid = un->semid; | ||
| 1292 | rcu_read_unlock(); | ||
| 1293 | |||
| 1294 | if (semid == -1) | ||
| 1295 | break; | ||
| 1296 | |||
| 1297 | sma = sem_lock_check(tsk->nsproxy->ipc_ns, un->semid); | ||
| 1298 | |||
| 1299 | /* exit_sem raced with IPC_RMID, nothing to do */ | ||
| 1273 | if (IS_ERR(sma)) | 1300 | if (IS_ERR(sma)) |
| 1274 | continue; | 1301 | continue; |
| 1275 | 1302 | ||
| 1276 | if (u->semid == -1) | 1303 | un = lookup_undo(ulp, semid); |
| 1277 | goto next_entry; | 1304 | if (un == NULL) { |
| 1305 | /* exit_sem raced with IPC_RMID+semget() that created | ||
| 1306 | * exactly the same semid. Nothing to do. | ||
| 1307 | */ | ||
| 1308 | sem_unlock(sma); | ||
| 1309 | continue; | ||
| 1310 | } | ||
| 1278 | 1311 | ||
| 1279 | BUG_ON(sem_checkid(sma, u->semid)); | 1312 | /* remove un from the linked lists */ |
| 1313 | assert_spin_locked(&sma->sem_perm.lock); | ||
| 1314 | list_del(&un->list_id); | ||
| 1280 | 1315 | ||
| 1281 | /* remove u from the sma->undo list */ | 1316 | spin_lock(&ulp->lock); |
| 1282 | for (unp = &sma->undo; (un = *unp); unp = &un->id_next) { | 1317 | list_del_rcu(&un->list_proc); |
| 1283 | if (u == un) | 1318 | spin_unlock(&ulp->lock); |
| 1284 | goto found; | 1319 | |
| 1285 | } | 1320 | /* perform adjustments registered in un */ |
| 1286 | printk ("exit_sem undo list error id=%d\n", u->semid); | 1321 | for (i = 0; i < sma->sem_nsems; i++) { |
| 1287 | goto next_entry; | ||
| 1288 | found: | ||
| 1289 | *unp = un->id_next; | ||
| 1290 | /* perform adjustments registered in u */ | ||
| 1291 | nsems = sma->sem_nsems; | ||
| 1292 | for (i = 0; i < nsems; i++) { | ||
| 1293 | struct sem * semaphore = &sma->sem_base[i]; | 1322 | struct sem * semaphore = &sma->sem_base[i]; |
| 1294 | if (u->semadj[i]) { | 1323 | if (un->semadj[i]) { |
| 1295 | semaphore->semval += u->semadj[i]; | 1324 | semaphore->semval += un->semadj[i]; |
| 1296 | /* | 1325 | /* |
| 1297 | * Range checks of the new semaphore value, | 1326 | * Range checks of the new semaphore value, |
| 1298 | * not defined by sus: | 1327 | * not defined by sus: |
| @@ -1316,10 +1345,11 @@ found: | |||
| 1316 | sma->sem_otime = get_seconds(); | 1345 | sma->sem_otime = get_seconds(); |
| 1317 | /* maybe some queued-up processes were waiting for this */ | 1346 | /* maybe some queued-up processes were waiting for this */ |
| 1318 | update_queue(sma); | 1347 | update_queue(sma); |
| 1319 | next_entry: | ||
| 1320 | sem_unlock(sma); | 1348 | sem_unlock(sma); |
| 1349 | |||
| 1350 | call_rcu(&un->rcu, free_un); | ||
| 1321 | } | 1351 | } |
| 1322 | kfree(undo_list); | 1352 | kfree(ulp); |
| 1323 | } | 1353 | } |
| 1324 | 1354 | ||
| 1325 | #ifdef CONFIG_PROC_FS | 1355 | #ifdef CONFIG_PROC_FS |
| @@ -112,23 +112,8 @@ void __init shm_init (void) | |||
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | /* | 114 | /* |
| 115 | * shm_lock_(check_)down routines are called in the paths where the rw_mutex | ||
| 116 | * is held to protect access to the idr tree. | ||
| 117 | */ | ||
| 118 | static inline struct shmid_kernel *shm_lock_down(struct ipc_namespace *ns, | ||
| 119 | int id) | ||
| 120 | { | ||
| 121 | struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id); | ||
| 122 | |||
| 123 | if (IS_ERR(ipcp)) | ||
| 124 | return (struct shmid_kernel *)ipcp; | ||
| 125 | |||
| 126 | return container_of(ipcp, struct shmid_kernel, shm_perm); | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | ||
| 130 | * shm_lock_(check_) routines are called in the paths where the rw_mutex | 115 | * shm_lock_(check_) routines are called in the paths where the rw_mutex |
| 131 | * is not held. | 116 | * is not necessarily held. |
| 132 | */ | 117 | */ |
| 133 | static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id) | 118 | static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id) |
| 134 | { | 119 | { |
| @@ -211,7 +196,7 @@ static void shm_close(struct vm_area_struct *vma) | |||
| 211 | 196 | ||
| 212 | down_write(&shm_ids(ns).rw_mutex); | 197 | down_write(&shm_ids(ns).rw_mutex); |
| 213 | /* remove from the list of attaches of the shm segment */ | 198 | /* remove from the list of attaches of the shm segment */ |
| 214 | shp = shm_lock_down(ns, sfd->id); | 199 | shp = shm_lock(ns, sfd->id); |
| 215 | BUG_ON(IS_ERR(shp)); | 200 | BUG_ON(IS_ERR(shp)); |
| 216 | shp->shm_lprid = task_tgid_vnr(current); | 201 | shp->shm_lprid = task_tgid_vnr(current); |
| 217 | shp->shm_dtim = get_seconds(); | 202 | shp->shm_dtim = get_seconds(); |
| @@ -932,7 +917,7 @@ invalid: | |||
| 932 | 917 | ||
| 933 | out_nattch: | 918 | out_nattch: |
| 934 | down_write(&shm_ids(ns).rw_mutex); | 919 | down_write(&shm_ids(ns).rw_mutex); |
| 935 | shp = shm_lock_down(ns, shmid); | 920 | shp = shm_lock(ns, shmid); |
| 936 | BUG_ON(IS_ERR(shp)); | 921 | BUG_ON(IS_ERR(shp)); |
| 937 | shp->shm_nattch--; | 922 | shp->shm_nattch--; |
| 938 | if(shp->shm_nattch == 0 && | 923 | if(shp->shm_nattch == 0 && |
diff --git a/ipc/util.c b/ipc/util.c index 3339177b336c..49b3ea615dc5 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
| @@ -688,10 +688,6 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out) | |||
| 688 | * Look for an id in the ipc ids idr and lock the associated ipc object. | 688 | * Look for an id in the ipc ids idr and lock the associated ipc object. |
| 689 | * | 689 | * |
| 690 | * The ipc object is locked on exit. | 690 | * The ipc object is locked on exit. |
| 691 | * | ||
| 692 | * This is the routine that should be called when the rw_mutex is not already | ||
| 693 | * held, i.e. idr tree not protected: it protects the idr tree in read mode | ||
| 694 | * during the idr_find(). | ||
| 695 | */ | 691 | */ |
| 696 | 692 | ||
| 697 | struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id) | 693 | struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id) |
| @@ -699,18 +695,13 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id) | |||
| 699 | struct kern_ipc_perm *out; | 695 | struct kern_ipc_perm *out; |
| 700 | int lid = ipcid_to_idx(id); | 696 | int lid = ipcid_to_idx(id); |
| 701 | 697 | ||
| 702 | down_read(&ids->rw_mutex); | ||
| 703 | |||
| 704 | rcu_read_lock(); | 698 | rcu_read_lock(); |
| 705 | out = idr_find(&ids->ipcs_idr, lid); | 699 | out = idr_find(&ids->ipcs_idr, lid); |
| 706 | if (out == NULL) { | 700 | if (out == NULL) { |
| 707 | rcu_read_unlock(); | 701 | rcu_read_unlock(); |
| 708 | up_read(&ids->rw_mutex); | ||
| 709 | return ERR_PTR(-EINVAL); | 702 | return ERR_PTR(-EINVAL); |
| 710 | } | 703 | } |
| 711 | 704 | ||
| 712 | up_read(&ids->rw_mutex); | ||
| 713 | |||
| 714 | spin_lock(&out->lock); | 705 | spin_lock(&out->lock); |
| 715 | 706 | ||
| 716 | /* ipc_rmid() may have already freed the ID while ipc_lock | 707 | /* ipc_rmid() may have already freed the ID while ipc_lock |
| @@ -725,56 +716,6 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id) | |||
| 725 | return out; | 716 | return out; |
| 726 | } | 717 | } |
| 727 | 718 | ||
| 728 | /** | ||
| 729 | * ipc_lock_down - Lock an ipc structure with rw_sem held | ||
| 730 | * @ids: IPC identifier set | ||
| 731 | * @id: ipc id to look for | ||
| 732 | * | ||
| 733 | * Look for an id in the ipc ids idr and lock the associated ipc object. | ||
| 734 | * | ||
| 735 | * The ipc object is locked on exit. | ||
| 736 | * | ||
| 737 | * This is the routine that should be called when the rw_mutex is already | ||
| 738 | * held, i.e. idr tree protected. | ||
| 739 | */ | ||
| 740 | |||
| 741 | struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *ids, int id) | ||
| 742 | { | ||
| 743 | struct kern_ipc_perm *out; | ||
| 744 | int lid = ipcid_to_idx(id); | ||
| 745 | |||
| 746 | rcu_read_lock(); | ||
| 747 | out = idr_find(&ids->ipcs_idr, lid); | ||
| 748 | if (out == NULL) { | ||
| 749 | rcu_read_unlock(); | ||
| 750 | return ERR_PTR(-EINVAL); | ||
| 751 | } | ||
| 752 | |||
| 753 | spin_lock(&out->lock); | ||
| 754 | |||
| 755 | /* | ||
| 756 | * No need to verify that the structure is still valid since the | ||
| 757 | * rw_mutex is held. | ||
| 758 | */ | ||
| 759 | return out; | ||
| 760 | } | ||
| 761 | |||
| 762 | struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id) | ||
| 763 | { | ||
| 764 | struct kern_ipc_perm *out; | ||
| 765 | |||
| 766 | out = ipc_lock_down(ids, id); | ||
| 767 | if (IS_ERR(out)) | ||
| 768 | return out; | ||
| 769 | |||
| 770 | if (ipc_checkid(out, id)) { | ||
| 771 | ipc_unlock(out); | ||
| 772 | return ERR_PTR(-EIDRM); | ||
| 773 | } | ||
| 774 | |||
| 775 | return out; | ||
| 776 | } | ||
| 777 | |||
| 778 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id) | 719 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id) |
| 779 | { | 720 | { |
| 780 | struct kern_ipc_perm *out; | 721 | struct kern_ipc_perm *out; |
| @@ -846,7 +787,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
| 846 | int err; | 787 | int err; |
| 847 | 788 | ||
| 848 | down_write(&ids->rw_mutex); | 789 | down_write(&ids->rw_mutex); |
| 849 | ipcp = ipc_lock_check_down(ids, id); | 790 | ipcp = ipc_lock_check(ids, id); |
| 850 | if (IS_ERR(ipcp)) { | 791 | if (IS_ERR(ipcp)) { |
| 851 | err = PTR_ERR(ipcp); | 792 | err = PTR_ERR(ipcp); |
| 852 | goto out_up; | 793 | goto out_up; |
diff --git a/ipc/util.h b/ipc/util.h index cdb966aebe07..3646b45a03c9 100644 --- a/ipc/util.h +++ b/ipc/util.h | |||
| @@ -102,11 +102,6 @@ void* ipc_rcu_alloc(int size); | |||
| 102 | void ipc_rcu_getref(void *ptr); | 102 | void ipc_rcu_getref(void *ptr); |
| 103 | void ipc_rcu_putref(void *ptr); | 103 | void ipc_rcu_putref(void *ptr); |
| 104 | 104 | ||
| 105 | /* | ||
| 106 | * ipc_lock_down: called with rw_mutex held | ||
| 107 | * ipc_lock: called without that lock held | ||
| 108 | */ | ||
| 109 | struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *, int); | ||
| 110 | struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int); | 105 | struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int); |
| 111 | 106 | ||
| 112 | void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out); | 107 | void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out); |
| @@ -155,7 +150,6 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm) | |||
| 155 | rcu_read_unlock(); | 150 | rcu_read_unlock(); |
| 156 | } | 151 | } |
| 157 | 152 | ||
| 158 | struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id); | ||
| 159 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id); | 153 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id); |
| 160 | int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, | 154 | int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, |
| 161 | struct ipc_ops *ops, struct ipc_params *params); | 155 | struct ipc_ops *ops, struct ipc_params *params); |
diff --git a/kernel/Makefile b/kernel/Makefile index 15ab63ffe64d..54f69837d35a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ | 5 | obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ |
| 6 | cpu.o exit.o itimer.o time.o softirq.o resource.o \ | 6 | cpu.o exit.o itimer.o time.o softirq.o resource.o \ |
| 7 | sysctl.o capability.o ptrace.o timer.o user.o \ | 7 | sysctl.o capability.o ptrace.o timer.o user.o \ |
| 8 | signal.o sys.o kmod.o workqueue.o pid.o \ | 8 | signal.o sys.o kmod.o workqueue.o pid.o \ |
| @@ -24,6 +24,7 @@ CFLAGS_REMOVE_sched_clock.o = -pg | |||
| 24 | CFLAGS_REMOVE_sched.o = -mno-spe -pg | 24 | CFLAGS_REMOVE_sched.o = -mno-spe -pg |
| 25 | endif | 25 | endif |
| 26 | 26 | ||
| 27 | obj-$(CONFIG_PROFILING) += profile.o | ||
| 27 | obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o | 28 | obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o |
| 28 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 29 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
| 29 | obj-y += time/ | 30 | obj-y += time/ |
diff --git a/kernel/acct.c b/kernel/acct.c index 91e1cfd734d2..dd68b9059418 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
| @@ -75,37 +75,39 @@ int acct_parm[3] = {4, 2, 30}; | |||
| 75 | /* | 75 | /* |
| 76 | * External references and all of the globals. | 76 | * External references and all of the globals. |
| 77 | */ | 77 | */ |
| 78 | static void do_acct_process(struct pid_namespace *ns, struct file *); | 78 | static void do_acct_process(struct bsd_acct_struct *acct, |
| 79 | struct pid_namespace *ns, struct file *); | ||
| 79 | 80 | ||
| 80 | /* | 81 | /* |
| 81 | * This structure is used so that all the data protected by lock | 82 | * This structure is used so that all the data protected by lock |
| 82 | * can be placed in the same cache line as the lock. This primes | 83 | * can be placed in the same cache line as the lock. This primes |
| 83 | * the cache line to have the data after getting the lock. | 84 | * the cache line to have the data after getting the lock. |
| 84 | */ | 85 | */ |
| 85 | struct acct_glbs { | 86 | struct bsd_acct_struct { |
| 86 | spinlock_t lock; | ||
| 87 | volatile int active; | 87 | volatile int active; |
| 88 | volatile int needcheck; | 88 | volatile int needcheck; |
| 89 | struct file *file; | 89 | struct file *file; |
| 90 | struct pid_namespace *ns; | 90 | struct pid_namespace *ns; |
| 91 | struct timer_list timer; | 91 | struct timer_list timer; |
| 92 | struct list_head list; | ||
| 92 | }; | 93 | }; |
| 93 | 94 | ||
| 94 | static struct acct_glbs acct_globals __cacheline_aligned = | 95 | static DEFINE_SPINLOCK(acct_lock); |
| 95 | {__SPIN_LOCK_UNLOCKED(acct_globals.lock)}; | 96 | static LIST_HEAD(acct_list); |
| 96 | 97 | ||
| 97 | /* | 98 | /* |
| 98 | * Called whenever the timer says to check the free space. | 99 | * Called whenever the timer says to check the free space. |
| 99 | */ | 100 | */ |
| 100 | static void acct_timeout(unsigned long unused) | 101 | static void acct_timeout(unsigned long x) |
| 101 | { | 102 | { |
| 102 | acct_globals.needcheck = 1; | 103 | struct bsd_acct_struct *acct = (struct bsd_acct_struct *)x; |
| 104 | acct->needcheck = 1; | ||
| 103 | } | 105 | } |
| 104 | 106 | ||
| 105 | /* | 107 | /* |
| 106 | * Check the amount of free space and suspend/resume accordingly. | 108 | * Check the amount of free space and suspend/resume accordingly. |
| 107 | */ | 109 | */ |
| 108 | static int check_free_space(struct file *file) | 110 | static int check_free_space(struct bsd_acct_struct *acct, struct file *file) |
| 109 | { | 111 | { |
| 110 | struct kstatfs sbuf; | 112 | struct kstatfs sbuf; |
| 111 | int res; | 113 | int res; |
| @@ -113,11 +115,11 @@ static int check_free_space(struct file *file) | |||
| 113 | sector_t resume; | 115 | sector_t resume; |
| 114 | sector_t suspend; | 116 | sector_t suspend; |
| 115 | 117 | ||
| 116 | spin_lock(&acct_globals.lock); | 118 | spin_lock(&acct_lock); |
| 117 | res = acct_globals.active; | 119 | res = acct->active; |
| 118 | if (!file || !acct_globals.needcheck) | 120 | if (!file || !acct->needcheck) |
| 119 | goto out; | 121 | goto out; |
| 120 | spin_unlock(&acct_globals.lock); | 122 | spin_unlock(&acct_lock); |
| 121 | 123 | ||
| 122 | /* May block */ | 124 | /* May block */ |
| 123 | if (vfs_statfs(file->f_path.dentry, &sbuf)) | 125 | if (vfs_statfs(file->f_path.dentry, &sbuf)) |
| @@ -136,35 +138,35 @@ static int check_free_space(struct file *file) | |||
| 136 | act = 0; | 138 | act = 0; |
| 137 | 139 | ||
| 138 | /* | 140 | /* |
| 139 | * If some joker switched acct_globals.file under us we'ld better be | 141 | * If some joker switched acct->file under us we'ld better be |
| 140 | * silent and _not_ touch anything. | 142 | * silent and _not_ touch anything. |
| 141 | */ | 143 | */ |
| 142 | spin_lock(&acct_globals.lock); | 144 | spin_lock(&acct_lock); |
| 143 | if (file != acct_globals.file) { | 145 | if (file != acct->file) { |
| 144 | if (act) | 146 | if (act) |
| 145 | res = act>0; | 147 | res = act>0; |
| 146 | goto out; | 148 | goto out; |
| 147 | } | 149 | } |
| 148 | 150 | ||
| 149 | if (acct_globals.active) { | 151 | if (acct->active) { |
| 150 | if (act < 0) { | 152 | if (act < 0) { |
| 151 | acct_globals.active = 0; | 153 | acct->active = 0; |
| 152 | printk(KERN_INFO "Process accounting paused\n"); | 154 | printk(KERN_INFO "Process accounting paused\n"); |
| 153 | } | 155 | } |
| 154 | } else { | 156 | } else { |
| 155 | if (act > 0) { | 157 | if (act > 0) { |
| 156 | acct_globals.active = 1; | 158 | acct->active = 1; |
| 157 | printk(KERN_INFO "Process accounting resumed\n"); | 159 | printk(KERN_INFO "Process accounting resumed\n"); |
| 158 | } | 160 | } |
| 159 | } | 161 | } |
| 160 | 162 | ||
| 161 | del_timer(&acct_globals.timer); | 163 | del_timer(&acct->timer); |
| 162 | acct_globals.needcheck = 0; | 164 | acct->needcheck = 0; |
| 163 | acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ; | 165 | acct->timer.expires = jiffies + ACCT_TIMEOUT*HZ; |
| 164 | add_timer(&acct_globals.timer); | 166 | add_timer(&acct->timer); |
| 165 | res = acct_globals.active; | 167 | res = acct->active; |
| 166 | out: | 168 | out: |
| 167 | spin_unlock(&acct_globals.lock); | 169 | spin_unlock(&acct_lock); |
| 168 | return res; | 170 | return res; |
| 169 | } | 171 | } |
| 170 | 172 | ||
| @@ -172,39 +174,41 @@ out: | |||
| 172 | * Close the old accounting file (if currently open) and then replace | 174 | * Close the old accounting file (if currently open) and then replace |
| 173 | * it with file (if non-NULL). | 175 | * it with file (if non-NULL). |
| 174 | * | 176 | * |
| 175 | * NOTE: acct_globals.lock MUST be held on entry and exit. | 177 | * NOTE: acct_lock MUST be held on entry and exit. |
| 176 | */ | 178 | */ |
| 177 | static void acct_file_reopen(struct file *file) | 179 | static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file, |
| 180 | struct pid_namespace *ns) | ||
| 178 | { | 181 | { |
| 179 | struct file *old_acct = NULL; | 182 | struct file *old_acct = NULL; |
| 180 | struct pid_namespace *old_ns = NULL; | 183 | struct pid_namespace *old_ns = NULL; |
| 181 | 184 | ||
| 182 | if (acct_globals.file) { | 185 | if (acct->file) { |
| 183 | old_acct = acct_globals.file; | 186 | old_acct = acct->file; |
| 184 | old_ns = acct_globals.ns; | 187 | old_ns = acct->ns; |
| 185 | del_timer(&acct_globals.timer); | 188 | del_timer(&acct->timer); |
| 186 | acct_globals.active = 0; | 189 | acct->active = 0; |
| 187 | acct_globals.needcheck = 0; | 190 | acct->needcheck = 0; |
| 188 | acct_globals.file = NULL; | 191 | acct->file = NULL; |
| 192 | acct->ns = NULL; | ||
| 193 | list_del(&acct->list); | ||
| 189 | } | 194 | } |
| 190 | if (file) { | 195 | if (file) { |
| 191 | acct_globals.file = file; | 196 | acct->file = file; |
| 192 | acct_globals.ns = get_pid_ns(task_active_pid_ns(current)); | 197 | acct->ns = ns; |
| 193 | acct_globals.needcheck = 0; | 198 | acct->needcheck = 0; |
| 194 | acct_globals.active = 1; | 199 | acct->active = 1; |
| 200 | list_add(&acct->list, &acct_list); | ||
| 195 | /* It's been deleted if it was used before so this is safe */ | 201 | /* It's been deleted if it was used before so this is safe */ |
| 196 | init_timer(&acct_globals.timer); | 202 | setup_timer(&acct->timer, acct_timeout, (unsigned long)acct); |
| 197 | acct_globals.timer.function = acct_timeout; | 203 | acct->timer.expires = jiffies + ACCT_TIMEOUT*HZ; |
| 198 | acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ; | 204 | add_timer(&acct->timer); |
| 199 | add_timer(&acct_globals.timer); | ||
| 200 | } | 205 | } |
| 201 | if (old_acct) { | 206 | if (old_acct) { |
| 202 | mnt_unpin(old_acct->f_path.mnt); | 207 | mnt_unpin(old_acct->f_path.mnt); |
| 203 | spin_unlock(&acct_globals.lock); | 208 | spin_unlock(&acct_lock); |
| 204 | do_acct_process(old_ns, old_acct); | 209 | do_acct_process(acct, old_ns, old_acct); |
| 205 | filp_close(old_acct, NULL); | 210 | filp_close(old_acct, NULL); |
| 206 | put_pid_ns(old_ns); | 211 | spin_lock(&acct_lock); |
| 207 | spin_lock(&acct_globals.lock); | ||
| 208 | } | 212 | } |
| 209 | } | 213 | } |
| 210 | 214 | ||
| @@ -212,6 +216,8 @@ static int acct_on(char *name) | |||
| 212 | { | 216 | { |
| 213 | struct file *file; | 217 | struct file *file; |
| 214 | int error; | 218 | int error; |
| 219 | struct pid_namespace *ns; | ||
| 220 | struct bsd_acct_struct *acct = NULL; | ||
| 215 | 221 | ||
| 216 | /* Difference from BSD - they don't do O_APPEND */ | 222 | /* Difference from BSD - they don't do O_APPEND */ |
| 217 | file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); | 223 | file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); |
| @@ -228,18 +234,34 @@ static int acct_on(char *name) | |||
| 228 | return -EIO; | 234 | return -EIO; |
| 229 | } | 235 | } |
| 230 | 236 | ||
| 237 | ns = task_active_pid_ns(current); | ||
| 238 | if (ns->bacct == NULL) { | ||
| 239 | acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL); | ||
| 240 | if (acct == NULL) { | ||
| 241 | filp_close(file, NULL); | ||
| 242 | return -ENOMEM; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 231 | error = security_acct(file); | 246 | error = security_acct(file); |
| 232 | if (error) { | 247 | if (error) { |
| 248 | kfree(acct); | ||
| 233 | filp_close(file, NULL); | 249 | filp_close(file, NULL); |
| 234 | return error; | 250 | return error; |
| 235 | } | 251 | } |
| 236 | 252 | ||
| 237 | spin_lock(&acct_globals.lock); | 253 | spin_lock(&acct_lock); |
| 254 | if (ns->bacct == NULL) { | ||
| 255 | ns->bacct = acct; | ||
| 256 | acct = NULL; | ||
| 257 | } | ||
| 258 | |||
| 238 | mnt_pin(file->f_path.mnt); | 259 | mnt_pin(file->f_path.mnt); |
| 239 | acct_file_reopen(file); | 260 | acct_file_reopen(ns->bacct, file, ns); |
| 240 | spin_unlock(&acct_globals.lock); | 261 | spin_unlock(&acct_lock); |
| 241 | 262 | ||
| 242 | mntput(file->f_path.mnt); /* it's pinned, now give up active reference */ | 263 | mntput(file->f_path.mnt); /* it's pinned, now give up active reference */ |
| 264 | kfree(acct); | ||
| 243 | 265 | ||
| 244 | return 0; | 266 | return 0; |
| 245 | } | 267 | } |
| @@ -269,11 +291,17 @@ asmlinkage long sys_acct(const char __user *name) | |||
| 269 | error = acct_on(tmp); | 291 | error = acct_on(tmp); |
| 270 | putname(tmp); | 292 | putname(tmp); |
| 271 | } else { | 293 | } else { |
| 294 | struct bsd_acct_struct *acct; | ||
| 295 | |||
| 296 | acct = task_active_pid_ns(current)->bacct; | ||
| 297 | if (acct == NULL) | ||
| 298 | return 0; | ||
| 299 | |||
| 272 | error = security_acct(NULL); | 300 | error = security_acct(NULL); |
| 273 | if (!error) { | 301 | if (!error) { |
| 274 | spin_lock(&acct_globals.lock); | 302 | spin_lock(&acct_lock); |
| 275 | acct_file_reopen(NULL); | 303 | acct_file_reopen(acct, NULL, NULL); |
| 276 | spin_unlock(&acct_globals.lock); | 304 | spin_unlock(&acct_lock); |
| 277 | } | 305 | } |
| 278 | } | 306 | } |
| 279 | return error; | 307 | return error; |
| @@ -288,10 +316,16 @@ asmlinkage long sys_acct(const char __user *name) | |||
| 288 | */ | 316 | */ |
| 289 | void acct_auto_close_mnt(struct vfsmount *m) | 317 | void acct_auto_close_mnt(struct vfsmount *m) |
| 290 | { | 318 | { |
| 291 | spin_lock(&acct_globals.lock); | 319 | struct bsd_acct_struct *acct; |
| 292 | if (acct_globals.file && acct_globals.file->f_path.mnt == m) | 320 | |
| 293 | acct_file_reopen(NULL); | 321 | spin_lock(&acct_lock); |
| 294 | spin_unlock(&acct_globals.lock); | 322 | restart: |
| 323 | list_for_each_entry(acct, &acct_list, list) | ||
| 324 | if (acct->file && acct->file->f_path.mnt == m) { | ||
| 325 | acct_file_reopen(acct, NULL, NULL); | ||
| 326 | goto restart; | ||
| 327 | } | ||
| 328 | spin_unlock(&acct_lock); | ||
| 295 | } | 329 | } |
| 296 | 330 | ||
| 297 | /** | 331 | /** |
| @@ -303,12 +337,31 @@ void acct_auto_close_mnt(struct vfsmount *m) | |||
| 303 | */ | 337 | */ |
| 304 | void acct_auto_close(struct super_block *sb) | 338 | void acct_auto_close(struct super_block *sb) |
| 305 | { | 339 | { |
| 306 | spin_lock(&acct_globals.lock); | 340 | struct bsd_acct_struct *acct; |
| 307 | if (acct_globals.file && | 341 | |
| 308 | acct_globals.file->f_path.mnt->mnt_sb == sb) { | 342 | spin_lock(&acct_lock); |
| 309 | acct_file_reopen(NULL); | 343 | restart: |
| 344 | list_for_each_entry(acct, &acct_list, list) | ||
| 345 | if (acct->file && acct->file->f_path.mnt->mnt_sb == sb) { | ||
| 346 | acct_file_reopen(acct, NULL, NULL); | ||
| 347 | goto restart; | ||
| 348 | } | ||
| 349 | spin_unlock(&acct_lock); | ||
| 350 | } | ||
| 351 | |||
| 352 | void acct_exit_ns(struct pid_namespace *ns) | ||
| 353 | { | ||
| 354 | struct bsd_acct_struct *acct; | ||
| 355 | |||
| 356 | spin_lock(&acct_lock); | ||
| 357 | acct = ns->bacct; | ||
| 358 | if (acct != NULL) { | ||
| 359 | if (acct->file != NULL) | ||
| 360 | acct_file_reopen(acct, NULL, NULL); | ||
| 361 | |||
| 362 | kfree(acct); | ||
| 310 | } | 363 | } |
| 311 | spin_unlock(&acct_globals.lock); | 364 | spin_unlock(&acct_lock); |
| 312 | } | 365 | } |
| 313 | 366 | ||
| 314 | /* | 367 | /* |
| @@ -425,7 +478,8 @@ static u32 encode_float(u64 value) | |||
| 425 | /* | 478 | /* |
| 426 | * do_acct_process does all actual work. Caller holds the reference to file. | 479 | * do_acct_process does all actual work. Caller holds the reference to file. |
| 427 | */ | 480 | */ |
| 428 | static void do_acct_process(struct pid_namespace *ns, struct file *file) | 481 | static void do_acct_process(struct bsd_acct_struct *acct, |
| 482 | struct pid_namespace *ns, struct file *file) | ||
| 429 | { | 483 | { |
| 430 | struct pacct_struct *pacct = ¤t->signal->pacct; | 484 | struct pacct_struct *pacct = ¤t->signal->pacct; |
| 431 | acct_t ac; | 485 | acct_t ac; |
| @@ -440,7 +494,7 @@ static void do_acct_process(struct pid_namespace *ns, struct file *file) | |||
| 440 | * First check to see if there is enough free_space to continue | 494 | * First check to see if there is enough free_space to continue |
| 441 | * the process accounting system. | 495 | * the process accounting system. |
| 442 | */ | 496 | */ |
| 443 | if (!check_free_space(file)) | 497 | if (!check_free_space(acct, file)) |
| 444 | return; | 498 | return; |
| 445 | 499 | ||
| 446 | /* | 500 | /* |
| @@ -577,34 +631,46 @@ void acct_collect(long exitcode, int group_dead) | |||
| 577 | spin_unlock_irq(¤t->sighand->siglock); | 631 | spin_unlock_irq(¤t->sighand->siglock); |
| 578 | } | 632 | } |
| 579 | 633 | ||
| 580 | /** | 634 | static void acct_process_in_ns(struct pid_namespace *ns) |
| 581 | * acct_process - now just a wrapper around do_acct_process | ||
| 582 | * @exitcode: task exit code | ||
| 583 | * | ||
| 584 | * handles process accounting for an exiting task | ||
| 585 | */ | ||
| 586 | void acct_process(void) | ||
| 587 | { | 635 | { |
| 588 | struct file *file = NULL; | 636 | struct file *file = NULL; |
| 589 | struct pid_namespace *ns; | 637 | struct bsd_acct_struct *acct; |
| 590 | 638 | ||
| 639 | acct = ns->bacct; | ||
| 591 | /* | 640 | /* |
| 592 | * accelerate the common fastpath: | 641 | * accelerate the common fastpath: |
| 593 | */ | 642 | */ |
| 594 | if (!acct_globals.file) | 643 | if (!acct || !acct->file) |
| 595 | return; | 644 | return; |
| 596 | 645 | ||
| 597 | spin_lock(&acct_globals.lock); | 646 | spin_lock(&acct_lock); |
| 598 | file = acct_globals.file; | 647 | file = acct->file; |
| 599 | if (unlikely(!file)) { | 648 | if (unlikely(!file)) { |
| 600 | spin_unlock(&acct_globals.lock); | 649 | spin_unlock(&acct_lock); |
| 601 | return; | 650 | return; |
| 602 | } | 651 | } |
| 603 | get_file(file); | 652 | get_file(file); |
| 604 | ns = get_pid_ns(acct_globals.ns); | 653 | spin_unlock(&acct_lock); |
| 605 | spin_unlock(&acct_globals.lock); | ||
| 606 | 654 | ||
| 607 | do_acct_process(ns, file); | 655 | do_acct_process(acct, ns, file); |
| 608 | fput(file); | 656 | fput(file); |
| 609 | put_pid_ns(ns); | 657 | } |
| 658 | |||
| 659 | /** | ||
| 660 | * acct_process - now just a wrapper around acct_process_in_ns, | ||
| 661 | * which in turn is a wrapper around do_acct_process. | ||
| 662 | * | ||
| 663 | * handles process accounting for an exiting task | ||
| 664 | */ | ||
| 665 | void acct_process(void) | ||
| 666 | { | ||
| 667 | struct pid_namespace *ns; | ||
| 668 | |||
| 669 | /* | ||
| 670 | * This loop is safe lockless, since current is still | ||
| 671 | * alive and holds its namespace, which in turn holds | ||
| 672 | * its parent. | ||
| 673 | */ | ||
| 674 | for (ns = task_active_pid_ns(current); ns != NULL; ns = ns->parent) | ||
| 675 | acct_process_in_ns(ns); | ||
| 610 | } | 676 | } |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 15ac0e1e4f4d..66ec9fd21e0c 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -89,11 +89,7 @@ struct cgroupfs_root { | |||
| 89 | /* Hierarchy-specific flags */ | 89 | /* Hierarchy-specific flags */ |
| 90 | unsigned long flags; | 90 | unsigned long flags; |
| 91 | 91 | ||
| 92 | /* The path to use for release notifications. No locking | 92 | /* The path to use for release notifications. */ |
| 93 | * between setting and use - so if userspace updates this | ||
| 94 | * while child cgroups exist, you could miss a | ||
| 95 | * notification. We ensure that it's always a valid | ||
| 96 | * NUL-terminated string */ | ||
| 97 | char release_agent_path[PATH_MAX]; | 93 | char release_agent_path[PATH_MAX]; |
| 98 | }; | 94 | }; |
| 99 | 95 | ||
| @@ -118,7 +114,7 @@ static int root_count; | |||
| 118 | * extra work in the fork/exit path if none of the subsystems need to | 114 | * extra work in the fork/exit path if none of the subsystems need to |
| 119 | * be called. | 115 | * be called. |
| 120 | */ | 116 | */ |
| 121 | static int need_forkexit_callback; | 117 | static int need_forkexit_callback __read_mostly; |
| 122 | static int need_mm_owner_callback __read_mostly; | 118 | static int need_mm_owner_callback __read_mostly; |
| 123 | 119 | ||
| 124 | /* convenient tests for these bits */ | 120 | /* convenient tests for these bits */ |
| @@ -220,7 +216,7 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[]) | |||
| 220 | * task until after the first call to cgroup_iter_start(). This | 216 | * task until after the first call to cgroup_iter_start(). This |
| 221 | * reduces the fork()/exit() overhead for people who have cgroups | 217 | * reduces the fork()/exit() overhead for people who have cgroups |
| 222 | * compiled into their kernel but not actually in use */ | 218 | * compiled into their kernel but not actually in use */ |
| 223 | static int use_task_css_set_links; | 219 | static int use_task_css_set_links __read_mostly; |
| 224 | 220 | ||
| 225 | /* When we create or destroy a css_set, the operation simply | 221 | /* When we create or destroy a css_set, the operation simply |
| 226 | * takes/releases a reference count on all the cgroups referenced | 222 | * takes/releases a reference count on all the cgroups referenced |
| @@ -241,17 +237,20 @@ static int use_task_css_set_links; | |||
| 241 | */ | 237 | */ |
| 242 | static void unlink_css_set(struct css_set *cg) | 238 | static void unlink_css_set(struct css_set *cg) |
| 243 | { | 239 | { |
| 240 | struct cg_cgroup_link *link; | ||
| 241 | struct cg_cgroup_link *saved_link; | ||
| 242 | |||
| 244 | write_lock(&css_set_lock); | 243 | write_lock(&css_set_lock); |
| 245 | hlist_del(&cg->hlist); | 244 | hlist_del(&cg->hlist); |
| 246 | css_set_count--; | 245 | css_set_count--; |
| 247 | while (!list_empty(&cg->cg_links)) { | 246 | |
| 248 | struct cg_cgroup_link *link; | 247 | list_for_each_entry_safe(link, saved_link, &cg->cg_links, |
| 249 | link = list_entry(cg->cg_links.next, | 248 | cg_link_list) { |
| 250 | struct cg_cgroup_link, cg_link_list); | ||
| 251 | list_del(&link->cg_link_list); | 249 | list_del(&link->cg_link_list); |
| 252 | list_del(&link->cgrp_link_list); | 250 | list_del(&link->cgrp_link_list); |
| 253 | kfree(link); | 251 | kfree(link); |
| 254 | } | 252 | } |
| 253 | |||
| 255 | write_unlock(&css_set_lock); | 254 | write_unlock(&css_set_lock); |
| 256 | } | 255 | } |
| 257 | 256 | ||
| @@ -363,15 +362,14 @@ static struct css_set *find_existing_css_set( | |||
| 363 | static int allocate_cg_links(int count, struct list_head *tmp) | 362 | static int allocate_cg_links(int count, struct list_head *tmp) |
| 364 | { | 363 | { |
| 365 | struct cg_cgroup_link *link; | 364 | struct cg_cgroup_link *link; |
| 365 | struct cg_cgroup_link *saved_link; | ||
| 366 | int i; | 366 | int i; |
| 367 | INIT_LIST_HEAD(tmp); | 367 | INIT_LIST_HEAD(tmp); |
| 368 | for (i = 0; i < count; i++) { | 368 | for (i = 0; i < count; i++) { |
| 369 | link = kmalloc(sizeof(*link), GFP_KERNEL); | 369 | link = kmalloc(sizeof(*link), GFP_KERNEL); |
| 370 | if (!link) { | 370 | if (!link) { |
| 371 | while (!list_empty(tmp)) { | 371 | list_for_each_entry_safe(link, saved_link, tmp, |
| 372 | link = list_entry(tmp->next, | 372 | cgrp_link_list) { |
| 373 | struct cg_cgroup_link, | ||
| 374 | cgrp_link_list); | ||
| 375 | list_del(&link->cgrp_link_list); | 373 | list_del(&link->cgrp_link_list); |
| 376 | kfree(link); | 374 | kfree(link); |
| 377 | } | 375 | } |
| @@ -384,11 +382,10 @@ static int allocate_cg_links(int count, struct list_head *tmp) | |||
| 384 | 382 | ||
| 385 | static void free_cg_links(struct list_head *tmp) | 383 | static void free_cg_links(struct list_head *tmp) |
| 386 | { | 384 | { |
| 387 | while (!list_empty(tmp)) { | 385 | struct cg_cgroup_link *link; |
| 388 | struct cg_cgroup_link *link; | 386 | struct cg_cgroup_link *saved_link; |
| 389 | link = list_entry(tmp->next, | 387 | |
| 390 | struct cg_cgroup_link, | 388 | list_for_each_entry_safe(link, saved_link, tmp, cgrp_link_list) { |
| 391 | cgrp_link_list); | ||
| 392 | list_del(&link->cgrp_link_list); | 389 | list_del(&link->cgrp_link_list); |
| 393 | kfree(link); | 390 | kfree(link); |
| 394 | } | 391 | } |
| @@ -415,11 +412,11 @@ static struct css_set *find_css_set( | |||
| 415 | 412 | ||
| 416 | /* First see if we already have a cgroup group that matches | 413 | /* First see if we already have a cgroup group that matches |
| 417 | * the desired set */ | 414 | * the desired set */ |
| 418 | write_lock(&css_set_lock); | 415 | read_lock(&css_set_lock); |
| 419 | res = find_existing_css_set(oldcg, cgrp, template); | 416 | res = find_existing_css_set(oldcg, cgrp, template); |
| 420 | if (res) | 417 | if (res) |
| 421 | get_css_set(res); | 418 | get_css_set(res); |
| 422 | write_unlock(&css_set_lock); | 419 | read_unlock(&css_set_lock); |
| 423 | 420 | ||
| 424 | if (res) | 421 | if (res) |
| 425 | return res; | 422 | return res; |
| @@ -507,10 +504,6 @@ static struct css_set *find_css_set( | |||
| 507 | * knows that the cgroup won't be removed, as cgroup_rmdir() | 504 | * knows that the cgroup won't be removed, as cgroup_rmdir() |
| 508 | * needs that mutex. | 505 | * needs that mutex. |
| 509 | * | 506 | * |
| 510 | * The cgroup_common_file_write handler for operations that modify | ||
| 511 | * the cgroup hierarchy holds cgroup_mutex across the entire operation, | ||
| 512 | * single threading all such cgroup modifications across the system. | ||
| 513 | * | ||
| 514 | * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't | 507 | * The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't |
| 515 | * (usually) take cgroup_mutex. These are the two most performance | 508 | * (usually) take cgroup_mutex. These are the two most performance |
| 516 | * critical pieces of code here. The exception occurs on cgroup_exit(), | 509 | * critical pieces of code here. The exception occurs on cgroup_exit(), |
| @@ -1093,6 +1086,8 @@ static void cgroup_kill_sb(struct super_block *sb) { | |||
| 1093 | struct cgroupfs_root *root = sb->s_fs_info; | 1086 | struct cgroupfs_root *root = sb->s_fs_info; |
| 1094 | struct cgroup *cgrp = &root->top_cgroup; | 1087 | struct cgroup *cgrp = &root->top_cgroup; |
| 1095 | int ret; | 1088 | int ret; |
| 1089 | struct cg_cgroup_link *link; | ||
| 1090 | struct cg_cgroup_link *saved_link; | ||
| 1096 | 1091 | ||
| 1097 | BUG_ON(!root); | 1092 | BUG_ON(!root); |
| 1098 | 1093 | ||
| @@ -1112,10 +1107,9 @@ static void cgroup_kill_sb(struct super_block *sb) { | |||
| 1112 | * root cgroup | 1107 | * root cgroup |
| 1113 | */ | 1108 | */ |
| 1114 | write_lock(&css_set_lock); | 1109 | write_lock(&css_set_lock); |
| 1115 | while (!list_empty(&cgrp->css_sets)) { | 1110 | |
| 1116 | struct cg_cgroup_link *link; | 1111 | list_for_each_entry_safe(link, saved_link, &cgrp->css_sets, |
| 1117 | link = list_entry(cgrp->css_sets.next, | 1112 | cgrp_link_list) { |
| 1118 | struct cg_cgroup_link, cgrp_link_list); | ||
| 1119 | list_del(&link->cg_link_list); | 1113 | list_del(&link->cg_link_list); |
| 1120 | list_del(&link->cgrp_link_list); | 1114 | list_del(&link->cgrp_link_list); |
| 1121 | kfree(link); | 1115 | kfree(link); |
| @@ -1281,18 +1275,14 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | |||
| 1281 | } | 1275 | } |
| 1282 | 1276 | ||
| 1283 | /* | 1277 | /* |
| 1284 | * Attach task with pid 'pid' to cgroup 'cgrp'. Call with | 1278 | * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex |
| 1285 | * cgroup_mutex, may take task_lock of task | 1279 | * held. May take task_lock of task |
| 1286 | */ | 1280 | */ |
| 1287 | static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf) | 1281 | static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) |
| 1288 | { | 1282 | { |
| 1289 | pid_t pid; | ||
| 1290 | struct task_struct *tsk; | 1283 | struct task_struct *tsk; |
| 1291 | int ret; | 1284 | int ret; |
| 1292 | 1285 | ||
| 1293 | if (sscanf(pidbuf, "%d", &pid) != 1) | ||
| 1294 | return -EIO; | ||
| 1295 | |||
| 1296 | if (pid) { | 1286 | if (pid) { |
| 1297 | rcu_read_lock(); | 1287 | rcu_read_lock(); |
| 1298 | tsk = find_task_by_vpid(pid); | 1288 | tsk = find_task_by_vpid(pid); |
| @@ -1318,6 +1308,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf) | |||
| 1318 | return ret; | 1308 | return ret; |
| 1319 | } | 1309 | } |
| 1320 | 1310 | ||
| 1311 | static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid) | ||
| 1312 | { | ||
| 1313 | int ret; | ||
| 1314 | if (!cgroup_lock_live_group(cgrp)) | ||
| 1315 | return -ENODEV; | ||
| 1316 | ret = attach_task_by_pid(cgrp, pid); | ||
| 1317 | cgroup_unlock(); | ||
| 1318 | return ret; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | /* The various types of files and directories in a cgroup file system */ | 1321 | /* The various types of files and directories in a cgroup file system */ |
| 1322 | enum cgroup_filetype { | 1322 | enum cgroup_filetype { |
| 1323 | FILE_ROOT, | 1323 | FILE_ROOT, |
| @@ -1327,12 +1327,54 @@ enum cgroup_filetype { | |||
| 1327 | FILE_RELEASE_AGENT, | 1327 | FILE_RELEASE_AGENT, |
| 1328 | }; | 1328 | }; |
| 1329 | 1329 | ||
| 1330 | /** | ||
| 1331 | * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive. | ||
| 1332 | * @cgrp: the cgroup to be checked for liveness | ||
| 1333 | * | ||
| 1334 | * On success, returns true; the lock should be later released with | ||
| 1335 | * cgroup_unlock(). On failure returns false with no lock held. | ||
| 1336 | */ | ||
| 1337 | bool cgroup_lock_live_group(struct cgroup *cgrp) | ||
| 1338 | { | ||
| 1339 | mutex_lock(&cgroup_mutex); | ||
| 1340 | if (cgroup_is_removed(cgrp)) { | ||
| 1341 | mutex_unlock(&cgroup_mutex); | ||
| 1342 | return false; | ||
| 1343 | } | ||
| 1344 | return true; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft, | ||
| 1348 | const char *buffer) | ||
| 1349 | { | ||
| 1350 | BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX); | ||
| 1351 | if (!cgroup_lock_live_group(cgrp)) | ||
| 1352 | return -ENODEV; | ||
| 1353 | strcpy(cgrp->root->release_agent_path, buffer); | ||
| 1354 | cgroup_unlock(); | ||
| 1355 | return 0; | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | static int cgroup_release_agent_show(struct cgroup *cgrp, struct cftype *cft, | ||
| 1359 | struct seq_file *seq) | ||
| 1360 | { | ||
| 1361 | if (!cgroup_lock_live_group(cgrp)) | ||
| 1362 | return -ENODEV; | ||
| 1363 | seq_puts(seq, cgrp->root->release_agent_path); | ||
| 1364 | seq_putc(seq, '\n'); | ||
| 1365 | cgroup_unlock(); | ||
| 1366 | return 0; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | /* A buffer size big enough for numbers or short strings */ | ||
| 1370 | #define CGROUP_LOCAL_BUFFER_SIZE 64 | ||
| 1371 | |||
| 1330 | static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, | 1372 | static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, |
| 1331 | struct file *file, | 1373 | struct file *file, |
| 1332 | const char __user *userbuf, | 1374 | const char __user *userbuf, |
| 1333 | size_t nbytes, loff_t *unused_ppos) | 1375 | size_t nbytes, loff_t *unused_ppos) |
| 1334 | { | 1376 | { |
| 1335 | char buffer[64]; | 1377 | char buffer[CGROUP_LOCAL_BUFFER_SIZE]; |
| 1336 | int retval = 0; | 1378 | int retval = 0; |
| 1337 | char *end; | 1379 | char *end; |
| 1338 | 1380 | ||
| @@ -1361,68 +1403,36 @@ static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, | |||
| 1361 | return retval; | 1403 | return retval; |
| 1362 | } | 1404 | } |
| 1363 | 1405 | ||
| 1364 | static ssize_t cgroup_common_file_write(struct cgroup *cgrp, | 1406 | static ssize_t cgroup_write_string(struct cgroup *cgrp, struct cftype *cft, |
| 1365 | struct cftype *cft, | 1407 | struct file *file, |
| 1366 | struct file *file, | 1408 | const char __user *userbuf, |
| 1367 | const char __user *userbuf, | 1409 | size_t nbytes, loff_t *unused_ppos) |
| 1368 | size_t nbytes, loff_t *unused_ppos) | ||
| 1369 | { | 1410 | { |
| 1370 | enum cgroup_filetype type = cft->private; | 1411 | char local_buffer[CGROUP_LOCAL_BUFFER_SIZE]; |
| 1371 | char *buffer; | ||
| 1372 | int retval = 0; | 1412 | int retval = 0; |
| 1413 | size_t max_bytes = cft->max_write_len; | ||
| 1414 | char *buffer = local_buffer; | ||
| 1373 | 1415 | ||
| 1374 | if (nbytes >= PATH_MAX) | 1416 | if (!max_bytes) |
| 1417 | max_bytes = sizeof(local_buffer) - 1; | ||
| 1418 | if (nbytes >= max_bytes) | ||
| 1375 | return -E2BIG; | 1419 | return -E2BIG; |
| 1376 | 1420 | /* Allocate a dynamic buffer if we need one */ | |
| 1377 | /* +1 for nul-terminator */ | 1421 | if (nbytes >= sizeof(local_buffer)) { |
| 1378 | buffer = kmalloc(nbytes + 1, GFP_KERNEL); | 1422 | buffer = kmalloc(nbytes + 1, GFP_KERNEL); |
| 1379 | if (buffer == NULL) | 1423 | if (buffer == NULL) |
| 1380 | return -ENOMEM; | 1424 | return -ENOMEM; |
| 1381 | |||
| 1382 | if (copy_from_user(buffer, userbuf, nbytes)) { | ||
| 1383 | retval = -EFAULT; | ||
| 1384 | goto out1; | ||
| 1385 | } | 1425 | } |
| 1386 | buffer[nbytes] = 0; /* nul-terminate */ | 1426 | if (nbytes && copy_from_user(buffer, userbuf, nbytes)) |
| 1387 | strstrip(buffer); /* strip -just- trailing whitespace */ | 1427 | return -EFAULT; |
| 1388 | |||
| 1389 | mutex_lock(&cgroup_mutex); | ||
| 1390 | 1428 | ||
| 1391 | /* | 1429 | buffer[nbytes] = 0; /* nul-terminate */ |
| 1392 | * This was already checked for in cgroup_file_write(), but | 1430 | strstrip(buffer); |
| 1393 | * check again now we're holding cgroup_mutex. | 1431 | retval = cft->write_string(cgrp, cft, buffer); |
| 1394 | */ | 1432 | if (!retval) |
| 1395 | if (cgroup_is_removed(cgrp)) { | ||
| 1396 | retval = -ENODEV; | ||
| 1397 | goto out2; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | switch (type) { | ||
| 1401 | case FILE_TASKLIST: | ||
| 1402 | retval = attach_task_by_pid(cgrp, buffer); | ||
| 1403 | break; | ||
| 1404 | case FILE_NOTIFY_ON_RELEASE: | ||
| 1405 | clear_bit(CGRP_RELEASABLE, &cgrp->flags); | ||
| 1406 | if (simple_strtoul(buffer, NULL, 10) != 0) | ||
| 1407 | set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
| 1408 | else | ||
| 1409 | clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
| 1410 | break; | ||
| 1411 | case FILE_RELEASE_AGENT: | ||
| 1412 | BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX); | ||
| 1413 | strcpy(cgrp->root->release_agent_path, buffer); | ||
| 1414 | break; | ||
| 1415 | default: | ||
| 1416 | retval = -EINVAL; | ||
| 1417 | goto out2; | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | if (retval == 0) | ||
| 1421 | retval = nbytes; | 1433 | retval = nbytes; |
| 1422 | out2: | 1434 | if (buffer != local_buffer) |
| 1423 | mutex_unlock(&cgroup_mutex); | 1435 | kfree(buffer); |
| 1424 | out1: | ||
| 1425 | kfree(buffer); | ||
| 1426 | return retval; | 1436 | return retval; |
| 1427 | } | 1437 | } |
| 1428 | 1438 | ||
| @@ -1438,6 +1448,8 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf, | |||
| 1438 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); | 1448 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); |
| 1439 | if (cft->write_u64 || cft->write_s64) | 1449 | if (cft->write_u64 || cft->write_s64) |
| 1440 | return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos); | 1450 | return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos); |
| 1451 | if (cft->write_string) | ||
| 1452 | return cgroup_write_string(cgrp, cft, file, buf, nbytes, ppos); | ||
| 1441 | if (cft->trigger) { | 1453 | if (cft->trigger) { |
| 1442 | int ret = cft->trigger(cgrp, (unsigned int)cft->private); | 1454 | int ret = cft->trigger(cgrp, (unsigned int)cft->private); |
| 1443 | return ret ? ret : nbytes; | 1455 | return ret ? ret : nbytes; |
| @@ -1450,7 +1462,7 @@ static ssize_t cgroup_read_u64(struct cgroup *cgrp, struct cftype *cft, | |||
| 1450 | char __user *buf, size_t nbytes, | 1462 | char __user *buf, size_t nbytes, |
| 1451 | loff_t *ppos) | 1463 | loff_t *ppos) |
| 1452 | { | 1464 | { |
| 1453 | char tmp[64]; | 1465 | char tmp[CGROUP_LOCAL_BUFFER_SIZE]; |
| 1454 | u64 val = cft->read_u64(cgrp, cft); | 1466 | u64 val = cft->read_u64(cgrp, cft); |
| 1455 | int len = sprintf(tmp, "%llu\n", (unsigned long long) val); | 1467 | int len = sprintf(tmp, "%llu\n", (unsigned long long) val); |
| 1456 | 1468 | ||
| @@ -1462,56 +1474,13 @@ static ssize_t cgroup_read_s64(struct cgroup *cgrp, struct cftype *cft, | |||
| 1462 | char __user *buf, size_t nbytes, | 1474 | char __user *buf, size_t nbytes, |
| 1463 | loff_t *ppos) | 1475 | loff_t *ppos) |
| 1464 | { | 1476 | { |
| 1465 | char tmp[64]; | 1477 | char tmp[CGROUP_LOCAL_BUFFER_SIZE]; |
| 1466 | s64 val = cft->read_s64(cgrp, cft); | 1478 | s64 val = cft->read_s64(cgrp, cft); |
| 1467 | int len = sprintf(tmp, "%lld\n", (long long) val); | 1479 | int len = sprintf(tmp, "%lld\n", (long long) val); |
| 1468 | 1480 | ||
| 1469 | return simple_read_from_buffer(buf, nbytes, ppos, tmp, len); | 1481 | return simple_read_from_buffer(buf, nbytes, ppos, tmp, len); |
| 1470 | } | 1482 | } |
| 1471 | 1483 | ||
| 1472 | static ssize_t cgroup_common_file_read(struct cgroup *cgrp, | ||
| 1473 | struct cftype *cft, | ||
| 1474 | struct file *file, | ||
| 1475 | char __user *buf, | ||
| 1476 | size_t nbytes, loff_t *ppos) | ||
| 1477 | { | ||
| 1478 | enum cgroup_filetype type = cft->private; | ||
| 1479 | char *page; | ||
| 1480 | ssize_t retval = 0; | ||
| 1481 | char *s; | ||
| 1482 | |||
| 1483 | if (!(page = (char *)__get_free_page(GFP_KERNEL))) | ||
| 1484 | return -ENOMEM; | ||
| 1485 | |||
| 1486 | s = page; | ||
| 1487 | |||
| 1488 | switch (type) { | ||
| 1489 | case FILE_RELEASE_AGENT: | ||
| 1490 | { | ||
| 1491 | struct cgroupfs_root *root; | ||
| 1492 | size_t n; | ||
| 1493 | mutex_lock(&cgroup_mutex); | ||
| 1494 | root = cgrp->root; | ||
| 1495 | n = strnlen(root->release_agent_path, | ||
| 1496 | sizeof(root->release_agent_path)); | ||
| 1497 | n = min(n, (size_t) PAGE_SIZE); | ||
| 1498 | strncpy(s, root->release_agent_path, n); | ||
| 1499 | mutex_unlock(&cgroup_mutex); | ||
| 1500 | s += n; | ||
| 1501 | break; | ||
| 1502 | } | ||
| 1503 | default: | ||
| 1504 | retval = -EINVAL; | ||
| 1505 | goto out; | ||
| 1506 | } | ||
| 1507 | *s++ = '\n'; | ||
| 1508 | |||
| 1509 | retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page); | ||
| 1510 | out: | ||
| 1511 | free_page((unsigned long)page); | ||
| 1512 | return retval; | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | static ssize_t cgroup_file_read(struct file *file, char __user *buf, | 1484 | static ssize_t cgroup_file_read(struct file *file, char __user *buf, |
| 1516 | size_t nbytes, loff_t *ppos) | 1485 | size_t nbytes, loff_t *ppos) |
| 1517 | { | 1486 | { |
| @@ -1569,6 +1538,7 @@ int cgroup_seqfile_release(struct inode *inode, struct file *file) | |||
| 1569 | 1538 | ||
| 1570 | static struct file_operations cgroup_seqfile_operations = { | 1539 | static struct file_operations cgroup_seqfile_operations = { |
| 1571 | .read = seq_read, | 1540 | .read = seq_read, |
| 1541 | .write = cgroup_file_write, | ||
| 1572 | .llseek = seq_lseek, | 1542 | .llseek = seq_lseek, |
| 1573 | .release = cgroup_seqfile_release, | 1543 | .release = cgroup_seqfile_release, |
| 1574 | }; | 1544 | }; |
| @@ -1756,15 +1726,11 @@ int cgroup_add_files(struct cgroup *cgrp, | |||
| 1756 | int cgroup_task_count(const struct cgroup *cgrp) | 1726 | int cgroup_task_count(const struct cgroup *cgrp) |
| 1757 | { | 1727 | { |
| 1758 | int count = 0; | 1728 | int count = 0; |
| 1759 | struct list_head *l; | 1729 | struct cg_cgroup_link *link; |
| 1760 | 1730 | ||
| 1761 | read_lock(&css_set_lock); | 1731 | read_lock(&css_set_lock); |
| 1762 | l = cgrp->css_sets.next; | 1732 | list_for_each_entry(link, &cgrp->css_sets, cgrp_link_list) { |
| 1763 | while (l != &cgrp->css_sets) { | ||
| 1764 | struct cg_cgroup_link *link = | ||
| 1765 | list_entry(l, struct cg_cgroup_link, cgrp_link_list); | ||
| 1766 | count += atomic_read(&link->cg->ref.refcount); | 1733 | count += atomic_read(&link->cg->ref.refcount); |
| 1767 | l = l->next; | ||
| 1768 | } | 1734 | } |
| 1769 | read_unlock(&css_set_lock); | 1735 | read_unlock(&css_set_lock); |
| 1770 | return count; | 1736 | return count; |
| @@ -2227,6 +2193,18 @@ static u64 cgroup_read_notify_on_release(struct cgroup *cgrp, | |||
| 2227 | return notify_on_release(cgrp); | 2193 | return notify_on_release(cgrp); |
| 2228 | } | 2194 | } |
| 2229 | 2195 | ||
| 2196 | static int cgroup_write_notify_on_release(struct cgroup *cgrp, | ||
| 2197 | struct cftype *cft, | ||
| 2198 | u64 val) | ||
| 2199 | { | ||
| 2200 | clear_bit(CGRP_RELEASABLE, &cgrp->flags); | ||
| 2201 | if (val) | ||
| 2202 | set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
| 2203 | else | ||
| 2204 | clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags); | ||
| 2205 | return 0; | ||
| 2206 | } | ||
| 2207 | |||
| 2230 | /* | 2208 | /* |
| 2231 | * for the common functions, 'private' gives the type of file | 2209 | * for the common functions, 'private' gives the type of file |
| 2232 | */ | 2210 | */ |
| @@ -2235,7 +2213,7 @@ static struct cftype files[] = { | |||
| 2235 | .name = "tasks", | 2213 | .name = "tasks", |
| 2236 | .open = cgroup_tasks_open, | 2214 | .open = cgroup_tasks_open, |
| 2237 | .read = cgroup_tasks_read, | 2215 | .read = cgroup_tasks_read, |
| 2238 | .write = cgroup_common_file_write, | 2216 | .write_u64 = cgroup_tasks_write, |
| 2239 | .release = cgroup_tasks_release, | 2217 | .release = cgroup_tasks_release, |
| 2240 | .private = FILE_TASKLIST, | 2218 | .private = FILE_TASKLIST, |
| 2241 | }, | 2219 | }, |
| @@ -2243,15 +2221,16 @@ static struct cftype files[] = { | |||
| 2243 | { | 2221 | { |
| 2244 | .name = "notify_on_release", | 2222 | .name = "notify_on_release", |
| 2245 | .read_u64 = cgroup_read_notify_on_release, | 2223 | .read_u64 = cgroup_read_notify_on_release, |
| 2246 | .write = cgroup_common_file_write, | 2224 | .write_u64 = cgroup_write_notify_on_release, |
| 2247 | .private = FILE_NOTIFY_ON_RELEASE, | 2225 | .private = FILE_NOTIFY_ON_RELEASE, |
| 2248 | }, | 2226 | }, |
| 2249 | }; | 2227 | }; |
| 2250 | 2228 | ||
| 2251 | static struct cftype cft_release_agent = { | 2229 | static struct cftype cft_release_agent = { |
| 2252 | .name = "release_agent", | 2230 | .name = "release_agent", |
| 2253 | .read = cgroup_common_file_read, | 2231 | .read_seq_string = cgroup_release_agent_show, |
| 2254 | .write = cgroup_common_file_write, | 2232 | .write_string = cgroup_release_agent_write, |
| 2233 | .max_write_len = PATH_MAX, | ||
| 2255 | .private = FILE_RELEASE_AGENT, | 2234 | .private = FILE_RELEASE_AGENT, |
| 2256 | }; | 2235 | }; |
| 2257 | 2236 | ||
| @@ -2869,16 +2848,17 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks) | |||
| 2869 | * cgroup_clone - clone the cgroup the given subsystem is attached to | 2848 | * cgroup_clone - clone the cgroup the given subsystem is attached to |
| 2870 | * @tsk: the task to be moved | 2849 | * @tsk: the task to be moved |
| 2871 | * @subsys: the given subsystem | 2850 | * @subsys: the given subsystem |
| 2851 | * @nodename: the name for the new cgroup | ||
| 2872 | * | 2852 | * |
| 2873 | * Duplicate the current cgroup in the hierarchy that the given | 2853 | * Duplicate the current cgroup in the hierarchy that the given |
| 2874 | * subsystem is attached to, and move this task into the new | 2854 | * subsystem is attached to, and move this task into the new |
| 2875 | * child. | 2855 | * child. |
| 2876 | */ | 2856 | */ |
| 2877 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) | 2857 | int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, |
| 2858 | char *nodename) | ||
| 2878 | { | 2859 | { |
| 2879 | struct dentry *dentry; | 2860 | struct dentry *dentry; |
| 2880 | int ret = 0; | 2861 | int ret = 0; |
| 2881 | char nodename[MAX_CGROUP_TYPE_NAMELEN]; | ||
| 2882 | struct cgroup *parent, *child; | 2862 | struct cgroup *parent, *child; |
| 2883 | struct inode *inode; | 2863 | struct inode *inode; |
| 2884 | struct css_set *cg; | 2864 | struct css_set *cg; |
| @@ -2903,8 +2883,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) | |||
| 2903 | cg = tsk->cgroups; | 2883 | cg = tsk->cgroups; |
| 2904 | parent = task_cgroup(tsk, subsys->subsys_id); | 2884 | parent = task_cgroup(tsk, subsys->subsys_id); |
| 2905 | 2885 | ||
| 2906 | snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "%d", tsk->pid); | ||
| 2907 | |||
| 2908 | /* Pin the hierarchy */ | 2886 | /* Pin the hierarchy */ |
| 2909 | atomic_inc(&parent->root->sb->s_active); | 2887 | atomic_inc(&parent->root->sb->s_active); |
| 2910 | 2888 | ||
| @@ -3078,27 +3056,24 @@ static void cgroup_release_agent(struct work_struct *work) | |||
| 3078 | while (!list_empty(&release_list)) { | 3056 | while (!list_empty(&release_list)) { |
| 3079 | char *argv[3], *envp[3]; | 3057 | char *argv[3], *envp[3]; |
| 3080 | int i; | 3058 | int i; |
| 3081 | char *pathbuf; | 3059 | char *pathbuf = NULL, *agentbuf = NULL; |
| 3082 | struct cgroup *cgrp = list_entry(release_list.next, | 3060 | struct cgroup *cgrp = list_entry(release_list.next, |
| 3083 | struct cgroup, | 3061 | struct cgroup, |
| 3084 | release_list); | 3062 | release_list); |
| 3085 | list_del_init(&cgrp->release_list); | 3063 | list_del_init(&cgrp->release_list); |
| 3086 | spin_unlock(&release_list_lock); | 3064 | spin_unlock(&release_list_lock); |
| 3087 | pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 3065 | pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| 3088 | if (!pathbuf) { | 3066 | if (!pathbuf) |
| 3089 | spin_lock(&release_list_lock); | 3067 | goto continue_free; |
| 3090 | continue; | 3068 | if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) |
| 3091 | } | 3069 | goto continue_free; |
| 3092 | 3070 | agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL); | |
| 3093 | if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) { | 3071 | if (!agentbuf) |
| 3094 | kfree(pathbuf); | 3072 | goto continue_free; |
| 3095 | spin_lock(&release_list_lock); | ||
| 3096 | continue; | ||
| 3097 | } | ||
| 3098 | 3073 | ||
| 3099 | i = 0; | 3074 | i = 0; |
| 3100 | argv[i++] = cgrp->root->release_agent_path; | 3075 | argv[i++] = agentbuf; |
| 3101 | argv[i++] = (char *)pathbuf; | 3076 | argv[i++] = pathbuf; |
| 3102 | argv[i] = NULL; | 3077 | argv[i] = NULL; |
| 3103 | 3078 | ||
| 3104 | i = 0; | 3079 | i = 0; |
| @@ -3112,8 +3087,10 @@ static void cgroup_release_agent(struct work_struct *work) | |||
| 3112 | * be a slow process */ | 3087 | * be a slow process */ |
| 3113 | mutex_unlock(&cgroup_mutex); | 3088 | mutex_unlock(&cgroup_mutex); |
| 3114 | call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); | 3089 | call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); |
| 3115 | kfree(pathbuf); | ||
| 3116 | mutex_lock(&cgroup_mutex); | 3090 | mutex_lock(&cgroup_mutex); |
| 3091 | continue_free: | ||
| 3092 | kfree(pathbuf); | ||
| 3093 | kfree(agentbuf); | ||
| 3117 | spin_lock(&release_list_lock); | 3094 | spin_lock(&release_list_lock); |
| 3118 | } | 3095 | } |
| 3119 | spin_unlock(&release_list_lock); | 3096 | spin_unlock(&release_list_lock); |
diff --git a/kernel/cpu.c b/kernel/cpu.c index 2cc409ce0a8f..10ba5f1004a5 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
| @@ -285,6 +285,11 @@ out_allowed: | |||
| 285 | set_cpus_allowed_ptr(current, &old_allowed); | 285 | set_cpus_allowed_ptr(current, &old_allowed); |
| 286 | out_release: | 286 | out_release: |
| 287 | cpu_hotplug_done(); | 287 | cpu_hotplug_done(); |
| 288 | if (!err) { | ||
| 289 | if (raw_notifier_call_chain(&cpu_chain, CPU_POST_DEAD | mod, | ||
| 290 | hcpu) == NOTIFY_BAD) | ||
| 291 | BUG(); | ||
| 292 | } | ||
| 288 | return err; | 293 | return err; |
| 289 | } | 294 | } |
| 290 | 295 | ||
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d5738910c34c..91cf85b36dd5 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -227,10 +227,6 @@ static struct cpuset top_cpuset = { | |||
| 227 | * The task_struct fields mems_allowed and mems_generation may only | 227 | * The task_struct fields mems_allowed and mems_generation may only |
| 228 | * be accessed in the context of that task, so require no locks. | 228 | * be accessed in the context of that task, so require no locks. |
| 229 | * | 229 | * |
| 230 | * The cpuset_common_file_write handler for operations that modify | ||
| 231 | * the cpuset hierarchy holds cgroup_mutex across the entire operation, | ||
| 232 | * single threading all such cpuset modifications across the system. | ||
| 233 | * | ||
| 234 | * The cpuset_common_file_read() handlers only hold callback_mutex across | 230 | * The cpuset_common_file_read() handlers only hold callback_mutex across |
| 235 | * small pieces of code, such as when reading out possibly multi-word | 231 | * small pieces of code, such as when reading out possibly multi-word |
| 236 | * cpumasks and nodemasks. | 232 | * cpumasks and nodemasks. |
| @@ -369,7 +365,7 @@ void cpuset_update_task_memory_state(void) | |||
| 369 | my_cpusets_mem_gen = top_cpuset.mems_generation; | 365 | my_cpusets_mem_gen = top_cpuset.mems_generation; |
| 370 | } else { | 366 | } else { |
| 371 | rcu_read_lock(); | 367 | rcu_read_lock(); |
| 372 | my_cpusets_mem_gen = task_cs(current)->mems_generation; | 368 | my_cpusets_mem_gen = task_cs(tsk)->mems_generation; |
| 373 | rcu_read_unlock(); | 369 | rcu_read_unlock(); |
| 374 | } | 370 | } |
| 375 | 371 | ||
| @@ -500,11 +496,16 @@ update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c) | |||
| 500 | /* | 496 | /* |
| 501 | * rebuild_sched_domains() | 497 | * rebuild_sched_domains() |
| 502 | * | 498 | * |
| 503 | * If the flag 'sched_load_balance' of any cpuset with non-empty | 499 | * This routine will be called to rebuild the scheduler's dynamic |
| 504 | * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset | 500 | * sched domains: |
| 505 | * which has that flag enabled, or if any cpuset with a non-empty | 501 | * - if the flag 'sched_load_balance' of any cpuset with non-empty |
| 506 | * 'cpus' is removed, then call this routine to rebuild the | 502 | * 'cpus' changes, |
| 507 | * scheduler's dynamic sched domains. | 503 | * - or if the 'cpus' allowed changes in any cpuset which has that |
| 504 | * flag enabled, | ||
| 505 | * - or if the 'sched_relax_domain_level' of any cpuset which has | ||
| 506 | * that flag enabled and with non-empty 'cpus' changes, | ||
| 507 | * - or if any cpuset with non-empty 'cpus' is removed, | ||
| 508 | * - or if a cpu gets offlined. | ||
| 508 | * | 509 | * |
| 509 | * This routine builds a partial partition of the systems CPUs | 510 | * This routine builds a partial partition of the systems CPUs |
| 510 | * (the set of non-overlappping cpumask_t's in the array 'part' | 511 | * (the set of non-overlappping cpumask_t's in the array 'part' |
| @@ -609,8 +610,13 @@ void rebuild_sched_domains(void) | |||
| 609 | while (__kfifo_get(q, (void *)&cp, sizeof(cp))) { | 610 | while (__kfifo_get(q, (void *)&cp, sizeof(cp))) { |
| 610 | struct cgroup *cont; | 611 | struct cgroup *cont; |
| 611 | struct cpuset *child; /* scans child cpusets of cp */ | 612 | struct cpuset *child; /* scans child cpusets of cp */ |
| 613 | |||
| 614 | if (cpus_empty(cp->cpus_allowed)) | ||
| 615 | continue; | ||
| 616 | |||
| 612 | if (is_sched_load_balance(cp)) | 617 | if (is_sched_load_balance(cp)) |
| 613 | csa[csn++] = cp; | 618 | csa[csn++] = cp; |
| 619 | |||
| 614 | list_for_each_entry(cont, &cp->css.cgroup->children, sibling) { | 620 | list_for_each_entry(cont, &cp->css.cgroup->children, sibling) { |
| 615 | child = cgroup_cs(cont); | 621 | child = cgroup_cs(cont); |
| 616 | __kfifo_put(q, (void *)&child, sizeof(cp)); | 622 | __kfifo_put(q, (void *)&child, sizeof(cp)); |
| @@ -703,36 +709,6 @@ done: | |||
| 703 | /* Don't kfree(dattr) -- partition_sched_domains() does that. */ | 709 | /* Don't kfree(dattr) -- partition_sched_domains() does that. */ |
| 704 | } | 710 | } |
| 705 | 711 | ||
| 706 | static inline int started_after_time(struct task_struct *t1, | ||
| 707 | struct timespec *time, | ||
| 708 | struct task_struct *t2) | ||
| 709 | { | ||
| 710 | int start_diff = timespec_compare(&t1->start_time, time); | ||
| 711 | if (start_diff > 0) { | ||
| 712 | return 1; | ||
| 713 | } else if (start_diff < 0) { | ||
| 714 | return 0; | ||
| 715 | } else { | ||
| 716 | /* | ||
| 717 | * Arbitrarily, if two processes started at the same | ||
| 718 | * time, we'll say that the lower pointer value | ||
| 719 | * started first. Note that t2 may have exited by now | ||
| 720 | * so this may not be a valid pointer any longer, but | ||
| 721 | * that's fine - it still serves to distinguish | ||
| 722 | * between two tasks started (effectively) | ||
| 723 | * simultaneously. | ||
| 724 | */ | ||
| 725 | return t1 > t2; | ||
| 726 | } | ||
| 727 | } | ||
| 728 | |||
| 729 | static inline int started_after(void *p1, void *p2) | ||
| 730 | { | ||
| 731 | struct task_struct *t1 = p1; | ||
| 732 | struct task_struct *t2 = p2; | ||
| 733 | return started_after_time(t1, &t2->start_time, t2); | ||
| 734 | } | ||
| 735 | |||
| 736 | /** | 712 | /** |
| 737 | * cpuset_test_cpumask - test a task's cpus_allowed versus its cpuset's | 713 | * cpuset_test_cpumask - test a task's cpus_allowed versus its cpuset's |
| 738 | * @tsk: task to test | 714 | * @tsk: task to test |
| @@ -768,15 +744,49 @@ static void cpuset_change_cpumask(struct task_struct *tsk, | |||
| 768 | } | 744 | } |
| 769 | 745 | ||
| 770 | /** | 746 | /** |
| 747 | * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. | ||
| 748 | * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed | ||
| 749 | * | ||
| 750 | * Called with cgroup_mutex held | ||
| 751 | * | ||
| 752 | * The cgroup_scan_tasks() function will scan all the tasks in a cgroup, | ||
| 753 | * calling callback functions for each. | ||
| 754 | * | ||
| 755 | * Return 0 if successful, -errno if not. | ||
| 756 | */ | ||
| 757 | static int update_tasks_cpumask(struct cpuset *cs) | ||
| 758 | { | ||
| 759 | struct cgroup_scanner scan; | ||
| 760 | struct ptr_heap heap; | ||
| 761 | int retval; | ||
| 762 | |||
| 763 | /* | ||
| 764 | * cgroup_scan_tasks() will initialize heap->gt for us. | ||
| 765 | * heap_init() is still needed here for we should not change | ||
| 766 | * cs->cpus_allowed when heap_init() fails. | ||
| 767 | */ | ||
| 768 | retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL); | ||
| 769 | if (retval) | ||
| 770 | return retval; | ||
| 771 | |||
| 772 | scan.cg = cs->css.cgroup; | ||
| 773 | scan.test_task = cpuset_test_cpumask; | ||
| 774 | scan.process_task = cpuset_change_cpumask; | ||
| 775 | scan.heap = &heap; | ||
| 776 | retval = cgroup_scan_tasks(&scan); | ||
| 777 | |||
| 778 | heap_free(&heap); | ||
| 779 | return retval; | ||
| 780 | } | ||
| 781 | |||
| 782 | /** | ||
| 771 | * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it | 783 | * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it |
| 772 | * @cs: the cpuset to consider | 784 | * @cs: the cpuset to consider |
| 773 | * @buf: buffer of cpu numbers written to this cpuset | 785 | * @buf: buffer of cpu numbers written to this cpuset |
| 774 | */ | 786 | */ |
| 775 | static int update_cpumask(struct cpuset *cs, char *buf) | 787 | static int update_cpumask(struct cpuset *cs, const char *buf) |
| 776 | { | 788 | { |
| 777 | struct cpuset trialcs; | 789 | struct cpuset trialcs; |
| 778 | struct cgroup_scanner scan; | ||
| 779 | struct ptr_heap heap; | ||
| 780 | int retval; | 790 | int retval; |
| 781 | int is_load_balanced; | 791 | int is_load_balanced; |
| 782 | 792 | ||
| @@ -792,7 +802,6 @@ static int update_cpumask(struct cpuset *cs, char *buf) | |||
| 792 | * that parsing. The validate_change() call ensures that cpusets | 802 | * that parsing. The validate_change() call ensures that cpusets |
| 793 | * with tasks have cpus. | 803 | * with tasks have cpus. |
| 794 | */ | 804 | */ |
| 795 | buf = strstrip(buf); | ||
| 796 | if (!*buf) { | 805 | if (!*buf) { |
| 797 | cpus_clear(trialcs.cpus_allowed); | 806 | cpus_clear(trialcs.cpus_allowed); |
| 798 | } else { | 807 | } else { |
| @@ -811,10 +820,6 @@ static int update_cpumask(struct cpuset *cs, char *buf) | |||
| 811 | if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed)) | 820 | if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed)) |
| 812 | return 0; | 821 | return 0; |
| 813 | 822 | ||
| 814 | retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, &started_after); | ||
| 815 | if (retval) | ||
| 816 | return retval; | ||
| 817 | |||
| 818 | is_load_balanced = is_sched_load_balance(&trialcs); | 823 | is_load_balanced = is_sched_load_balance(&trialcs); |
| 819 | 824 | ||
| 820 | mutex_lock(&callback_mutex); | 825 | mutex_lock(&callback_mutex); |
| @@ -825,12 +830,9 @@ static int update_cpumask(struct cpuset *cs, char *buf) | |||
| 825 | * Scan tasks in the cpuset, and update the cpumasks of any | 830 | * Scan tasks in the cpuset, and update the cpumasks of any |
| 826 | * that need an update. | 831 | * that need an update. |
| 827 | */ | 832 | */ |
| 828 | scan.cg = cs->css.cgroup; | 833 | retval = update_tasks_cpumask(cs); |
| 829 | scan.test_task = cpuset_test_cpumask; | 834 | if (retval < 0) |
| 830 | scan.process_task = cpuset_change_cpumask; | 835 | return retval; |
| 831 | scan.heap = &heap; | ||
| 832 | cgroup_scan_tasks(&scan); | ||
| 833 | heap_free(&heap); | ||
| 834 | 836 | ||
| 835 | if (is_load_balanced) | 837 | if (is_load_balanced) |
| 836 | rebuild_sched_domains(); | 838 | rebuild_sched_domains(); |
| @@ -886,74 +888,25 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from, | |||
| 886 | mutex_unlock(&callback_mutex); | 888 | mutex_unlock(&callback_mutex); |
| 887 | } | 889 | } |
| 888 | 890 | ||
| 889 | /* | ||
| 890 | * Handle user request to change the 'mems' memory placement | ||
| 891 | * of a cpuset. Needs to validate the request, update the | ||
| 892 | * cpusets mems_allowed and mems_generation, and for each | ||
| 893 | * task in the cpuset, rebind any vma mempolicies and if | ||
| 894 | * the cpuset is marked 'memory_migrate', migrate the tasks | ||
| 895 | * pages to the new memory. | ||
| 896 | * | ||
| 897 | * Call with cgroup_mutex held. May take callback_mutex during call. | ||
| 898 | * Will take tasklist_lock, scan tasklist for tasks in cpuset cs, | ||
| 899 | * lock each such tasks mm->mmap_sem, scan its vma's and rebind | ||
| 900 | * their mempolicies to the cpusets new mems_allowed. | ||
| 901 | */ | ||
| 902 | |||
| 903 | static void *cpuset_being_rebound; | 891 | static void *cpuset_being_rebound; |
| 904 | 892 | ||
| 905 | static int update_nodemask(struct cpuset *cs, char *buf) | 893 | /** |
| 894 | * update_tasks_nodemask - Update the nodemasks of tasks in the cpuset. | ||
| 895 | * @cs: the cpuset in which each task's mems_allowed mask needs to be changed | ||
| 896 | * @oldmem: old mems_allowed of cpuset cs | ||
| 897 | * | ||
| 898 | * Called with cgroup_mutex held | ||
| 899 | * Return 0 if successful, -errno if not. | ||
| 900 | */ | ||
| 901 | static int update_tasks_nodemask(struct cpuset *cs, const nodemask_t *oldmem) | ||
| 906 | { | 902 | { |
| 907 | struct cpuset trialcs; | ||
| 908 | nodemask_t oldmem; | ||
| 909 | struct task_struct *p; | 903 | struct task_struct *p; |
| 910 | struct mm_struct **mmarray; | 904 | struct mm_struct **mmarray; |
| 911 | int i, n, ntasks; | 905 | int i, n, ntasks; |
| 912 | int migrate; | 906 | int migrate; |
| 913 | int fudge; | 907 | int fudge; |
| 914 | int retval; | ||
| 915 | struct cgroup_iter it; | 908 | struct cgroup_iter it; |
| 916 | 909 | int retval; | |
| 917 | /* | ||
| 918 | * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY]; | ||
| 919 | * it's read-only | ||
| 920 | */ | ||
| 921 | if (cs == &top_cpuset) | ||
| 922 | return -EACCES; | ||
| 923 | |||
| 924 | trialcs = *cs; | ||
| 925 | |||
| 926 | /* | ||
| 927 | * An empty mems_allowed is ok iff there are no tasks in the cpuset. | ||
| 928 | * Since nodelist_parse() fails on an empty mask, we special case | ||
| 929 | * that parsing. The validate_change() call ensures that cpusets | ||
| 930 | * with tasks have memory. | ||
| 931 | */ | ||
| 932 | buf = strstrip(buf); | ||
| 933 | if (!*buf) { | ||
| 934 | nodes_clear(trialcs.mems_allowed); | ||
| 935 | } else { | ||
| 936 | retval = nodelist_parse(buf, trialcs.mems_allowed); | ||
| 937 | if (retval < 0) | ||
| 938 | goto done; | ||
| 939 | |||
| 940 | if (!nodes_subset(trialcs.mems_allowed, | ||
| 941 | node_states[N_HIGH_MEMORY])) | ||
| 942 | return -EINVAL; | ||
| 943 | } | ||
| 944 | oldmem = cs->mems_allowed; | ||
| 945 | if (nodes_equal(oldmem, trialcs.mems_allowed)) { | ||
| 946 | retval = 0; /* Too easy - nothing to do */ | ||
| 947 | goto done; | ||
| 948 | } | ||
| 949 | retval = validate_change(cs, &trialcs); | ||
| 950 | if (retval < 0) | ||
| 951 | goto done; | ||
| 952 | |||
| 953 | mutex_lock(&callback_mutex); | ||
| 954 | cs->mems_allowed = trialcs.mems_allowed; | ||
| 955 | cs->mems_generation = cpuset_mems_generation++; | ||
| 956 | mutex_unlock(&callback_mutex); | ||
| 957 | 910 | ||
| 958 | cpuset_being_rebound = cs; /* causes mpol_dup() rebind */ | 911 | cpuset_being_rebound = cs; /* causes mpol_dup() rebind */ |
| 959 | 912 | ||
| @@ -1020,7 +973,7 @@ static int update_nodemask(struct cpuset *cs, char *buf) | |||
| 1020 | 973 | ||
| 1021 | mpol_rebind_mm(mm, &cs->mems_allowed); | 974 | mpol_rebind_mm(mm, &cs->mems_allowed); |
| 1022 | if (migrate) | 975 | if (migrate) |
| 1023 | cpuset_migrate_mm(mm, &oldmem, &cs->mems_allowed); | 976 | cpuset_migrate_mm(mm, oldmem, &cs->mems_allowed); |
| 1024 | mmput(mm); | 977 | mmput(mm); |
| 1025 | } | 978 | } |
| 1026 | 979 | ||
| @@ -1032,6 +985,70 @@ done: | |||
| 1032 | return retval; | 985 | return retval; |
| 1033 | } | 986 | } |
| 1034 | 987 | ||
| 988 | /* | ||
| 989 | * Handle user request to change the 'mems' memory placement | ||
| 990 | * of a cpuset. Needs to validate the request, update the | ||
| 991 | * cpusets mems_allowed and mems_generation, and for each | ||
| 992 | * task in the cpuset, rebind any vma mempolicies and if | ||
| 993 | * the cpuset is marked 'memory_migrate', migrate the tasks | ||
| 994 | * pages to the new memory. | ||
| 995 | * | ||
| 996 | * Call with cgroup_mutex held. May take callback_mutex during call. | ||
| 997 | * Will take tasklist_lock, scan tasklist for tasks in cpuset cs, | ||
| 998 | * lock each such tasks mm->mmap_sem, scan its vma's and rebind | ||
| 999 | * their mempolicies to the cpusets new mems_allowed. | ||
| 1000 | */ | ||
| 1001 | static int update_nodemask(struct cpuset *cs, const char *buf) | ||
| 1002 | { | ||
| 1003 | struct cpuset trialcs; | ||
| 1004 | nodemask_t oldmem; | ||
| 1005 | int retval; | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY]; | ||
| 1009 | * it's read-only | ||
| 1010 | */ | ||
| 1011 | if (cs == &top_cpuset) | ||
| 1012 | return -EACCES; | ||
| 1013 | |||
| 1014 | trialcs = *cs; | ||
| 1015 | |||
| 1016 | /* | ||
| 1017 | * An empty mems_allowed is ok iff there are no tasks in the cpuset. | ||
| 1018 | * Since nodelist_parse() fails on an empty mask, we special case | ||
| 1019 | * that parsing. The validate_change() call ensures that cpusets | ||
| 1020 | * with tasks have memory. | ||
| 1021 | */ | ||
| 1022 | if (!*buf) { | ||
| 1023 | nodes_clear(trialcs.mems_allowed); | ||
| 1024 | } else { | ||
| 1025 | retval = nodelist_parse(buf, trialcs.mems_allowed); | ||
| 1026 | if (retval < 0) | ||
| 1027 | goto done; | ||
| 1028 | |||
| 1029 | if (!nodes_subset(trialcs.mems_allowed, | ||
| 1030 | node_states[N_HIGH_MEMORY])) | ||
| 1031 | return -EINVAL; | ||
| 1032 | } | ||
| 1033 | oldmem = cs->mems_allowed; | ||
| 1034 | if (nodes_equal(oldmem, trialcs.mems_allowed)) { | ||
| 1035 | retval = 0; /* Too easy - nothing to do */ | ||
| 1036 | goto done; | ||
| 1037 | } | ||
| 1038 | retval = validate_change(cs, &trialcs); | ||
| 1039 | if (retval < 0) | ||
| 1040 | goto done; | ||
| 1041 | |||
| 1042 | mutex_lock(&callback_mutex); | ||
| 1043 | cs->mems_allowed = trialcs.mems_allowed; | ||
| 1044 | cs->mems_generation = cpuset_mems_generation++; | ||
| 1045 | mutex_unlock(&callback_mutex); | ||
| 1046 | |||
| 1047 | retval = update_tasks_nodemask(cs, &oldmem); | ||
| 1048 | done: | ||
| 1049 | return retval; | ||
| 1050 | } | ||
| 1051 | |||
| 1035 | int current_cpuset_is_being_rebound(void) | 1052 | int current_cpuset_is_being_rebound(void) |
| 1036 | { | 1053 | { |
| 1037 | return task_cs(current) == cpuset_being_rebound; | 1054 | return task_cs(current) == cpuset_being_rebound; |
| @@ -1044,7 +1061,8 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val) | |||
| 1044 | 1061 | ||
| 1045 | if (val != cs->relax_domain_level) { | 1062 | if (val != cs->relax_domain_level) { |
| 1046 | cs->relax_domain_level = val; | 1063 | cs->relax_domain_level = val; |
| 1047 | rebuild_sched_domains(); | 1064 | if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs)) |
| 1065 | rebuild_sched_domains(); | ||
| 1048 | } | 1066 | } |
| 1049 | 1067 | ||
| 1050 | return 0; | 1068 | return 0; |
| @@ -1256,72 +1274,14 @@ typedef enum { | |||
| 1256 | FILE_SPREAD_SLAB, | 1274 | FILE_SPREAD_SLAB, |
| 1257 | } cpuset_filetype_t; | 1275 | } cpuset_filetype_t; |
| 1258 | 1276 | ||
| 1259 | static ssize_t cpuset_common_file_write(struct cgroup *cont, | ||
| 1260 | struct cftype *cft, | ||
| 1261 | struct file *file, | ||
| 1262 | const char __user *userbuf, | ||
| 1263 | size_t nbytes, loff_t *unused_ppos) | ||
| 1264 | { | ||
| 1265 | struct cpuset *cs = cgroup_cs(cont); | ||
| 1266 | cpuset_filetype_t type = cft->private; | ||
| 1267 | char *buffer; | ||
| 1268 | int retval = 0; | ||
| 1269 | |||
| 1270 | /* Crude upper limit on largest legitimate cpulist user might write. */ | ||
| 1271 | if (nbytes > 100U + 6 * max(NR_CPUS, MAX_NUMNODES)) | ||
| 1272 | return -E2BIG; | ||
| 1273 | |||
| 1274 | /* +1 for nul-terminator */ | ||
| 1275 | buffer = kmalloc(nbytes + 1, GFP_KERNEL); | ||
| 1276 | if (!buffer) | ||
| 1277 | return -ENOMEM; | ||
| 1278 | |||
| 1279 | if (copy_from_user(buffer, userbuf, nbytes)) { | ||
| 1280 | retval = -EFAULT; | ||
| 1281 | goto out1; | ||
| 1282 | } | ||
| 1283 | buffer[nbytes] = 0; /* nul-terminate */ | ||
| 1284 | |||
| 1285 | cgroup_lock(); | ||
| 1286 | |||
| 1287 | if (cgroup_is_removed(cont)) { | ||
| 1288 | retval = -ENODEV; | ||
| 1289 | goto out2; | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | switch (type) { | ||
| 1293 | case FILE_CPULIST: | ||
| 1294 | retval = update_cpumask(cs, buffer); | ||
| 1295 | break; | ||
| 1296 | case FILE_MEMLIST: | ||
| 1297 | retval = update_nodemask(cs, buffer); | ||
| 1298 | break; | ||
| 1299 | default: | ||
| 1300 | retval = -EINVAL; | ||
| 1301 | goto out2; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | if (retval == 0) | ||
| 1305 | retval = nbytes; | ||
| 1306 | out2: | ||
| 1307 | cgroup_unlock(); | ||
| 1308 | out1: | ||
| 1309 | kfree(buffer); | ||
| 1310 | return retval; | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val) | 1277 | static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val) |
| 1314 | { | 1278 | { |
| 1315 | int retval = 0; | 1279 | int retval = 0; |
| 1316 | struct cpuset *cs = cgroup_cs(cgrp); | 1280 | struct cpuset *cs = cgroup_cs(cgrp); |
| 1317 | cpuset_filetype_t type = cft->private; | 1281 | cpuset_filetype_t type = cft->private; |
| 1318 | 1282 | ||
| 1319 | cgroup_lock(); | 1283 | if (!cgroup_lock_live_group(cgrp)) |
| 1320 | |||
| 1321 | if (cgroup_is_removed(cgrp)) { | ||
| 1322 | cgroup_unlock(); | ||
| 1323 | return -ENODEV; | 1284 | return -ENODEV; |
| 1324 | } | ||
| 1325 | 1285 | ||
| 1326 | switch (type) { | 1286 | switch (type) { |
| 1327 | case FILE_CPU_EXCLUSIVE: | 1287 | case FILE_CPU_EXCLUSIVE: |
| @@ -1367,12 +1327,9 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val) | |||
| 1367 | struct cpuset *cs = cgroup_cs(cgrp); | 1327 | struct cpuset *cs = cgroup_cs(cgrp); |
| 1368 | cpuset_filetype_t type = cft->private; | 1328 | cpuset_filetype_t type = cft->private; |
| 1369 | 1329 | ||
| 1370 | cgroup_lock(); | 1330 | if (!cgroup_lock_live_group(cgrp)) |
| 1371 | |||
| 1372 | if (cgroup_is_removed(cgrp)) { | ||
| 1373 | cgroup_unlock(); | ||
| 1374 | return -ENODEV; | 1331 | return -ENODEV; |
| 1375 | } | 1332 | |
| 1376 | switch (type) { | 1333 | switch (type) { |
| 1377 | case FILE_SCHED_RELAX_DOMAIN_LEVEL: | 1334 | case FILE_SCHED_RELAX_DOMAIN_LEVEL: |
| 1378 | retval = update_relax_domain_level(cs, val); | 1335 | retval = update_relax_domain_level(cs, val); |
| @@ -1386,6 +1343,32 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val) | |||
| 1386 | } | 1343 | } |
| 1387 | 1344 | ||
| 1388 | /* | 1345 | /* |
| 1346 | * Common handling for a write to a "cpus" or "mems" file. | ||
| 1347 | */ | ||
| 1348 | static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft, | ||
| 1349 | const char *buf) | ||
| 1350 | { | ||
| 1351 | int retval = 0; | ||
| 1352 | |||
| 1353 | if (!cgroup_lock_live_group(cgrp)) | ||
| 1354 | return -ENODEV; | ||
| 1355 | |||
| 1356 | switch (cft->private) { | ||
| 1357 | case FILE_CPULIST: | ||
| 1358 | retval = update_cpumask(cgroup_cs(cgrp), buf); | ||
| 1359 | break; | ||
| 1360 | case FILE_MEMLIST: | ||
| 1361 | retval = update_nodemask(cgroup_cs(cgrp), buf); | ||
| 1362 | break; | ||
| 1363 | default: | ||
| 1364 | retval = -EINVAL; | ||
| 1365 | break; | ||
| 1366 | } | ||
| 1367 | cgroup_unlock(); | ||
| 1368 | return retval; | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | /* | ||
| 1389 | * These ascii lists should be read in a single call, by using a user | 1372 | * These ascii lists should be read in a single call, by using a user |
| 1390 | * buffer large enough to hold the entire map. If read in smaller | 1373 | * buffer large enough to hold the entire map. If read in smaller |
| 1391 | * chunks, there is no guarantee of atomicity. Since the display format | 1374 | * chunks, there is no guarantee of atomicity. Since the display format |
| @@ -1504,14 +1487,16 @@ static struct cftype files[] = { | |||
| 1504 | { | 1487 | { |
| 1505 | .name = "cpus", | 1488 | .name = "cpus", |
| 1506 | .read = cpuset_common_file_read, | 1489 | .read = cpuset_common_file_read, |
| 1507 | .write = cpuset_common_file_write, | 1490 | .write_string = cpuset_write_resmask, |
| 1491 | .max_write_len = (100U + 6 * NR_CPUS), | ||
| 1508 | .private = FILE_CPULIST, | 1492 | .private = FILE_CPULIST, |
| 1509 | }, | 1493 | }, |
| 1510 | 1494 | ||
| 1511 | { | 1495 | { |
| 1512 | .name = "mems", | 1496 | .name = "mems", |
| 1513 | .read = cpuset_common_file_read, | 1497 | .read = cpuset_common_file_read, |
| 1514 | .write = cpuset_common_file_write, | 1498 | .write_string = cpuset_write_resmask, |
| 1499 | .max_write_len = (100U + 6 * MAX_NUMNODES), | ||
| 1515 | .private = FILE_MEMLIST, | 1500 | .private = FILE_MEMLIST, |
| 1516 | }, | 1501 | }, |
| 1517 | 1502 | ||
| @@ -1792,7 +1777,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to) | |||
| 1792 | scan.scan.heap = NULL; | 1777 | scan.scan.heap = NULL; |
| 1793 | scan.to = to->css.cgroup; | 1778 | scan.to = to->css.cgroup; |
| 1794 | 1779 | ||
| 1795 | if (cgroup_scan_tasks((struct cgroup_scanner *)&scan)) | 1780 | if (cgroup_scan_tasks(&scan.scan)) |
| 1796 | printk(KERN_ERR "move_member_tasks_to_cpuset: " | 1781 | printk(KERN_ERR "move_member_tasks_to_cpuset: " |
| 1797 | "cgroup_scan_tasks failed\n"); | 1782 | "cgroup_scan_tasks failed\n"); |
| 1798 | } | 1783 | } |
| @@ -1852,6 +1837,7 @@ static void scan_for_empty_cpusets(const struct cpuset *root) | |||
| 1852 | struct cpuset *child; /* scans child cpusets of cp */ | 1837 | struct cpuset *child; /* scans child cpusets of cp */ |
| 1853 | struct list_head queue; | 1838 | struct list_head queue; |
| 1854 | struct cgroup *cont; | 1839 | struct cgroup *cont; |
| 1840 | nodemask_t oldmems; | ||
| 1855 | 1841 | ||
| 1856 | INIT_LIST_HEAD(&queue); | 1842 | INIT_LIST_HEAD(&queue); |
| 1857 | 1843 | ||
| @@ -1871,6 +1857,8 @@ static void scan_for_empty_cpusets(const struct cpuset *root) | |||
| 1871 | nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY])) | 1857 | nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY])) |
| 1872 | continue; | 1858 | continue; |
| 1873 | 1859 | ||
| 1860 | oldmems = cp->mems_allowed; | ||
| 1861 | |||
| 1874 | /* Remove offline cpus and mems from this cpuset. */ | 1862 | /* Remove offline cpus and mems from this cpuset. */ |
| 1875 | mutex_lock(&callback_mutex); | 1863 | mutex_lock(&callback_mutex); |
| 1876 | cpus_and(cp->cpus_allowed, cp->cpus_allowed, cpu_online_map); | 1864 | cpus_and(cp->cpus_allowed, cp->cpus_allowed, cpu_online_map); |
| @@ -1882,6 +1870,10 @@ static void scan_for_empty_cpusets(const struct cpuset *root) | |||
| 1882 | if (cpus_empty(cp->cpus_allowed) || | 1870 | if (cpus_empty(cp->cpus_allowed) || |
| 1883 | nodes_empty(cp->mems_allowed)) | 1871 | nodes_empty(cp->mems_allowed)) |
| 1884 | remove_tasks_in_empty_cpuset(cp); | 1872 | remove_tasks_in_empty_cpuset(cp); |
| 1873 | else { | ||
| 1874 | update_tasks_cpumask(cp); | ||
| 1875 | update_tasks_nodemask(cp, &oldmems); | ||
| 1876 | } | ||
| 1885 | } | 1877 | } |
| 1886 | } | 1878 | } |
| 1887 | 1879 | ||
| @@ -1974,7 +1966,6 @@ void __init cpuset_init_smp(void) | |||
| 1974 | } | 1966 | } |
| 1975 | 1967 | ||
| 1976 | /** | 1968 | /** |
| 1977 | |||
| 1978 | * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset. | 1969 | * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset. |
| 1979 | * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed. | 1970 | * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed. |
| 1980 | * @pmask: pointer to cpumask_t variable to receive cpus_allowed set. | 1971 | * @pmask: pointer to cpumask_t variable to receive cpus_allowed set. |
diff --git a/kernel/delayacct.c b/kernel/delayacct.c index 10e43fd8b721..b3179dad71be 100644 --- a/kernel/delayacct.c +++ b/kernel/delayacct.c | |||
| @@ -145,8 +145,11 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) | |||
| 145 | d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp; | 145 | d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp; |
| 146 | tmp = d->swapin_delay_total + tsk->delays->swapin_delay; | 146 | tmp = d->swapin_delay_total + tsk->delays->swapin_delay; |
| 147 | d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp; | 147 | d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp; |
| 148 | tmp = d->freepages_delay_total + tsk->delays->freepages_delay; | ||
| 149 | d->freepages_delay_total = (tmp < d->freepages_delay_total) ? 0 : tmp; | ||
| 148 | d->blkio_count += tsk->delays->blkio_count; | 150 | d->blkio_count += tsk->delays->blkio_count; |
| 149 | d->swapin_count += tsk->delays->swapin_count; | 151 | d->swapin_count += tsk->delays->swapin_count; |
| 152 | d->freepages_count += tsk->delays->freepages_count; | ||
| 150 | spin_unlock_irqrestore(&tsk->delays->lock, flags); | 153 | spin_unlock_irqrestore(&tsk->delays->lock, flags); |
| 151 | 154 | ||
| 152 | done: | 155 | done: |
| @@ -165,3 +168,16 @@ __u64 __delayacct_blkio_ticks(struct task_struct *tsk) | |||
| 165 | return ret; | 168 | return ret; |
| 166 | } | 169 | } |
| 167 | 170 | ||
| 171 | void __delayacct_freepages_start(void) | ||
| 172 | { | ||
| 173 | delayacct_start(¤t->delays->freepages_start); | ||
| 174 | } | ||
| 175 | |||
| 176 | void __delayacct_freepages_end(void) | ||
| 177 | { | ||
| 178 | delayacct_end(¤t->delays->freepages_start, | ||
| 179 | ¤t->delays->freepages_end, | ||
| 180 | ¤t->delays->freepages_delay, | ||
| 181 | ¤t->delays->freepages_count); | ||
| 182 | } | ||
| 183 | |||
diff --git a/kernel/exit.c b/kernel/exit.c index 93d2711b9381..ad933bb29ec7 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -85,7 +85,6 @@ static void __exit_signal(struct task_struct *tsk) | |||
| 85 | BUG_ON(!sig); | 85 | BUG_ON(!sig); |
| 86 | BUG_ON(!atomic_read(&sig->count)); | 86 | BUG_ON(!atomic_read(&sig->count)); |
| 87 | 87 | ||
| 88 | rcu_read_lock(); | ||
| 89 | sighand = rcu_dereference(tsk->sighand); | 88 | sighand = rcu_dereference(tsk->sighand); |
| 90 | spin_lock(&sighand->siglock); | 89 | spin_lock(&sighand->siglock); |
| 91 | 90 | ||
| @@ -121,6 +120,18 @@ static void __exit_signal(struct task_struct *tsk) | |||
| 121 | sig->nivcsw += tsk->nivcsw; | 120 | sig->nivcsw += tsk->nivcsw; |
| 122 | sig->inblock += task_io_get_inblock(tsk); | 121 | sig->inblock += task_io_get_inblock(tsk); |
| 123 | sig->oublock += task_io_get_oublock(tsk); | 122 | sig->oublock += task_io_get_oublock(tsk); |
| 123 | #ifdef CONFIG_TASK_XACCT | ||
| 124 | sig->rchar += tsk->rchar; | ||
| 125 | sig->wchar += tsk->wchar; | ||
| 126 | sig->syscr += tsk->syscr; | ||
| 127 | sig->syscw += tsk->syscw; | ||
| 128 | #endif /* CONFIG_TASK_XACCT */ | ||
| 129 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
| 130 | sig->ioac.read_bytes += tsk->ioac.read_bytes; | ||
| 131 | sig->ioac.write_bytes += tsk->ioac.write_bytes; | ||
| 132 | sig->ioac.cancelled_write_bytes += | ||
| 133 | tsk->ioac.cancelled_write_bytes; | ||
| 134 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
| 124 | sig->sum_sched_runtime += tsk->se.sum_exec_runtime; | 135 | sig->sum_sched_runtime += tsk->se.sum_exec_runtime; |
| 125 | sig = NULL; /* Marker for below. */ | 136 | sig = NULL; /* Marker for below. */ |
| 126 | } | 137 | } |
| @@ -136,7 +147,6 @@ static void __exit_signal(struct task_struct *tsk) | |||
| 136 | tsk->signal = NULL; | 147 | tsk->signal = NULL; |
| 137 | tsk->sighand = NULL; | 148 | tsk->sighand = NULL; |
| 138 | spin_unlock(&sighand->siglock); | 149 | spin_unlock(&sighand->siglock); |
| 139 | rcu_read_unlock(); | ||
| 140 | 150 | ||
| 141 | __cleanup_sighand(sighand); | 151 | __cleanup_sighand(sighand); |
| 142 | clear_tsk_thread_flag(tsk,TIF_SIGPENDING); | 152 | clear_tsk_thread_flag(tsk,TIF_SIGPENDING); |
| @@ -432,7 +442,7 @@ void daemonize(const char *name, ...) | |||
| 432 | * We don't want to have TIF_FREEZE set if the system-wide hibernation | 442 | * We don't want to have TIF_FREEZE set if the system-wide hibernation |
| 433 | * or suspend transition begins right now. | 443 | * or suspend transition begins right now. |
| 434 | */ | 444 | */ |
| 435 | current->flags |= PF_NOFREEZE; | 445 | current->flags |= (PF_NOFREEZE | PF_KTHREAD); |
| 436 | 446 | ||
| 437 | if (current->nsproxy != &init_nsproxy) { | 447 | if (current->nsproxy != &init_nsproxy) { |
| 438 | get_nsproxy(&init_nsproxy); | 448 | get_nsproxy(&init_nsproxy); |
| @@ -666,26 +676,40 @@ assign_new_owner: | |||
| 666 | static void exit_mm(struct task_struct * tsk) | 676 | static void exit_mm(struct task_struct * tsk) |
| 667 | { | 677 | { |
| 668 | struct mm_struct *mm = tsk->mm; | 678 | struct mm_struct *mm = tsk->mm; |
| 679 | struct core_state *core_state; | ||
| 669 | 680 | ||
| 670 | mm_release(tsk, mm); | 681 | mm_release(tsk, mm); |
| 671 | if (!mm) | 682 | if (!mm) |
| 672 | return; | 683 | return; |
| 673 | /* | 684 | /* |
| 674 | * Serialize with any possible pending coredump. | 685 | * Serialize with any possible pending coredump. |
| 675 | * We must hold mmap_sem around checking core_waiters | 686 | * We must hold mmap_sem around checking core_state |
| 676 | * and clearing tsk->mm. The core-inducing thread | 687 | * and clearing tsk->mm. The core-inducing thread |
| 677 | * will increment core_waiters for each thread in the | 688 | * will increment ->nr_threads for each thread in the |
| 678 | * group with ->mm != NULL. | 689 | * group with ->mm != NULL. |
| 679 | */ | 690 | */ |
| 680 | down_read(&mm->mmap_sem); | 691 | down_read(&mm->mmap_sem); |
| 681 | if (mm->core_waiters) { | 692 | core_state = mm->core_state; |
| 693 | if (core_state) { | ||
| 694 | struct core_thread self; | ||
| 682 | up_read(&mm->mmap_sem); | 695 | up_read(&mm->mmap_sem); |
| 683 | down_write(&mm->mmap_sem); | ||
| 684 | if (!--mm->core_waiters) | ||
| 685 | complete(mm->core_startup_done); | ||
| 686 | up_write(&mm->mmap_sem); | ||
| 687 | 696 | ||
| 688 | wait_for_completion(&mm->core_done); | 697 | self.task = tsk; |
| 698 | self.next = xchg(&core_state->dumper.next, &self); | ||
| 699 | /* | ||
| 700 | * Implies mb(), the result of xchg() must be visible | ||
| 701 | * to core_state->dumper. | ||
| 702 | */ | ||
| 703 | if (atomic_dec_and_test(&core_state->nr_threads)) | ||
| 704 | complete(&core_state->startup); | ||
| 705 | |||
| 706 | for (;;) { | ||
| 707 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
| 708 | if (!self.task) /* see coredump_finish() */ | ||
| 709 | break; | ||
| 710 | schedule(); | ||
| 711 | } | ||
| 712 | __set_task_state(tsk, TASK_RUNNING); | ||
| 689 | down_read(&mm->mmap_sem); | 713 | down_read(&mm->mmap_sem); |
| 690 | } | 714 | } |
| 691 | atomic_inc(&mm->mm_count); | 715 | atomic_inc(&mm->mm_count); |
| @@ -1354,6 +1378,21 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
| 1354 | psig->coublock += | 1378 | psig->coublock += |
| 1355 | task_io_get_oublock(p) + | 1379 | task_io_get_oublock(p) + |
| 1356 | sig->oublock + sig->coublock; | 1380 | sig->oublock + sig->coublock; |
| 1381 | #ifdef CONFIG_TASK_XACCT | ||
| 1382 | psig->rchar += p->rchar + sig->rchar; | ||
| 1383 | psig->wchar += p->wchar + sig->wchar; | ||
| 1384 | psig->syscr += p->syscr + sig->syscr; | ||
| 1385 | psig->syscw += p->syscw + sig->syscw; | ||
| 1386 | #endif /* CONFIG_TASK_XACCT */ | ||
| 1387 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
| 1388 | psig->ioac.read_bytes += | ||
| 1389 | p->ioac.read_bytes + sig->ioac.read_bytes; | ||
| 1390 | psig->ioac.write_bytes += | ||
| 1391 | p->ioac.write_bytes + sig->ioac.write_bytes; | ||
| 1392 | psig->ioac.cancelled_write_bytes += | ||
| 1393 | p->ioac.cancelled_write_bytes + | ||
| 1394 | sig->ioac.cancelled_write_bytes; | ||
| 1395 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | ||
| 1357 | spin_unlock_irq(&p->parent->sighand->siglock); | 1396 | spin_unlock_irq(&p->parent->sighand->siglock); |
| 1358 | } | 1397 | } |
| 1359 | 1398 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index 552c8d8e77ad..b99d73e971a4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -93,6 +93,23 @@ int nr_processes(void) | |||
| 93 | static struct kmem_cache *task_struct_cachep; | 93 | static struct kmem_cache *task_struct_cachep; |
| 94 | #endif | 94 | #endif |
| 95 | 95 | ||
| 96 | #ifndef __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
| 97 | static inline struct thread_info *alloc_thread_info(struct task_struct *tsk) | ||
| 98 | { | ||
| 99 | #ifdef CONFIG_DEBUG_STACK_USAGE | ||
| 100 | gfp_t mask = GFP_KERNEL | __GFP_ZERO; | ||
| 101 | #else | ||
| 102 | gfp_t mask = GFP_KERNEL; | ||
| 103 | #endif | ||
| 104 | return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER); | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void free_thread_info(struct thread_info *ti) | ||
| 108 | { | ||
| 109 | free_pages((unsigned long)ti, THREAD_SIZE_ORDER); | ||
| 110 | } | ||
| 111 | #endif | ||
| 112 | |||
| 96 | /* SLAB cache for signal_struct structures (tsk->signal) */ | 113 | /* SLAB cache for signal_struct structures (tsk->signal) */ |
| 97 | static struct kmem_cache *signal_cachep; | 114 | static struct kmem_cache *signal_cachep; |
| 98 | 115 | ||
| @@ -383,7 +400,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | |||
| 383 | INIT_LIST_HEAD(&mm->mmlist); | 400 | INIT_LIST_HEAD(&mm->mmlist); |
| 384 | mm->flags = (current->mm) ? current->mm->flags | 401 | mm->flags = (current->mm) ? current->mm->flags |
| 385 | : MMF_DUMP_FILTER_DEFAULT; | 402 | : MMF_DUMP_FILTER_DEFAULT; |
| 386 | mm->core_waiters = 0; | 403 | mm->core_state = NULL; |
| 387 | mm->nr_ptes = 0; | 404 | mm->nr_ptes = 0; |
| 388 | set_mm_counter(mm, file_rss, 0); | 405 | set_mm_counter(mm, file_rss, 0); |
| 389 | set_mm_counter(mm, anon_rss, 0); | 406 | set_mm_counter(mm, anon_rss, 0); |
| @@ -457,7 +474,7 @@ EXPORT_SYMBOL_GPL(mmput); | |||
| 457 | /** | 474 | /** |
| 458 | * get_task_mm - acquire a reference to the task's mm | 475 | * get_task_mm - acquire a reference to the task's mm |
| 459 | * | 476 | * |
| 460 | * Returns %NULL if the task has no mm. Checks PF_BORROWED_MM (meaning | 477 | * Returns %NULL if the task has no mm. Checks PF_KTHREAD (meaning |
| 461 | * this kernel workthread has transiently adopted a user mm with use_mm, | 478 | * this kernel workthread has transiently adopted a user mm with use_mm, |
| 462 | * to do its AIO) is not set and if so returns a reference to it, after | 479 | * to do its AIO) is not set and if so returns a reference to it, after |
| 463 | * bumping up the use count. User must release the mm via mmput() | 480 | * bumping up the use count. User must release the mm via mmput() |
| @@ -470,7 +487,7 @@ struct mm_struct *get_task_mm(struct task_struct *task) | |||
| 470 | task_lock(task); | 487 | task_lock(task); |
| 471 | mm = task->mm; | 488 | mm = task->mm; |
| 472 | if (mm) { | 489 | if (mm) { |
| 473 | if (task->flags & PF_BORROWED_MM) | 490 | if (task->flags & PF_KTHREAD) |
| 474 | mm = NULL; | 491 | mm = NULL; |
| 475 | else | 492 | else |
| 476 | atomic_inc(&mm->mm_users); | 493 | atomic_inc(&mm->mm_users); |
| @@ -795,6 +812,12 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
| 795 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; | 812 | sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; |
| 796 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; | 813 | sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; |
| 797 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; | 814 | sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; |
| 815 | #ifdef CONFIG_TASK_XACCT | ||
| 816 | sig->rchar = sig->wchar = sig->syscr = sig->syscw = 0; | ||
| 817 | #endif | ||
| 818 | #ifdef CONFIG_TASK_IO_ACCOUNTING | ||
| 819 | memset(&sig->ioac, 0, sizeof(sig->ioac)); | ||
| 820 | #endif | ||
| 798 | sig->sum_sched_runtime = 0; | 821 | sig->sum_sched_runtime = 0; |
| 799 | INIT_LIST_HEAD(&sig->cpu_timers[0]); | 822 | INIT_LIST_HEAD(&sig->cpu_timers[0]); |
| 800 | INIT_LIST_HEAD(&sig->cpu_timers[1]); | 823 | INIT_LIST_HEAD(&sig->cpu_timers[1]); |
| @@ -1090,6 +1113,12 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1090 | if (clone_flags & CLONE_THREAD) | 1113 | if (clone_flags & CLONE_THREAD) |
| 1091 | p->tgid = current->tgid; | 1114 | p->tgid = current->tgid; |
| 1092 | 1115 | ||
| 1116 | if (current->nsproxy != p->nsproxy) { | ||
| 1117 | retval = ns_cgroup_clone(p, pid); | ||
| 1118 | if (retval) | ||
| 1119 | goto bad_fork_free_pid; | ||
| 1120 | } | ||
| 1121 | |||
| 1093 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | 1122 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; |
| 1094 | /* | 1123 | /* |
| 1095 | * Clear TID on mm_release()? | 1124 | * Clear TID on mm_release()? |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 5bc6e5ecc493..f8914b92b664 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -260,9 +260,7 @@ int set_irq_wake(unsigned int irq, unsigned int on) | |||
| 260 | } | 260 | } |
| 261 | } else { | 261 | } else { |
| 262 | if (desc->wake_depth == 0) { | 262 | if (desc->wake_depth == 0) { |
| 263 | printk(KERN_WARNING "Unbalanced IRQ %d " | 263 | WARN(1, "Unbalanced IRQ %d wake disable\n", irq); |
| 264 | "wake disable\n", irq); | ||
| 265 | WARN_ON(1); | ||
| 266 | } else if (--desc->wake_depth == 0) { | 264 | } else if (--desc->wake_depth == 0) { |
| 267 | ret = set_irq_wake_real(irq, on); | 265 | ret = set_irq_wake_real(irq, on); |
| 268 | if (ret) | 266 | if (ret) |
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 6fc0040f3e3a..38fc10ac7541 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
| @@ -176,7 +176,7 @@ static unsigned long get_symbol_pos(unsigned long addr, | |||
| 176 | high = kallsyms_num_syms; | 176 | high = kallsyms_num_syms; |
| 177 | 177 | ||
| 178 | while (high - low > 1) { | 178 | while (high - low > 1) { |
| 179 | mid = (low + high) / 2; | 179 | mid = low + (high - low) / 2; |
| 180 | if (kallsyms_addresses[mid] <= addr) | 180 | if (kallsyms_addresses[mid] <= addr) |
| 181 | low = mid; | 181 | low = mid; |
| 182 | else | 182 | else |
diff --git a/kernel/kmod.c b/kernel/kmod.c index 2989f67c4446..2456d1a0befb 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
| @@ -352,16 +352,17 @@ static inline void register_pm_notifier_callback(void) {} | |||
| 352 | * @path: path to usermode executable | 352 | * @path: path to usermode executable |
| 353 | * @argv: arg vector for process | 353 | * @argv: arg vector for process |
| 354 | * @envp: environment for process | 354 | * @envp: environment for process |
| 355 | * @gfp_mask: gfp mask for memory allocation | ||
| 355 | * | 356 | * |
| 356 | * Returns either %NULL on allocation failure, or a subprocess_info | 357 | * Returns either %NULL on allocation failure, or a subprocess_info |
| 357 | * structure. This should be passed to call_usermodehelper_exec to | 358 | * structure. This should be passed to call_usermodehelper_exec to |
| 358 | * exec the process and free the structure. | 359 | * exec the process and free the structure. |
| 359 | */ | 360 | */ |
| 360 | struct subprocess_info *call_usermodehelper_setup(char *path, | 361 | struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, |
| 361 | char **argv, char **envp) | 362 | char **envp, gfp_t gfp_mask) |
| 362 | { | 363 | { |
| 363 | struct subprocess_info *sub_info; | 364 | struct subprocess_info *sub_info; |
| 364 | sub_info = kzalloc(sizeof(struct subprocess_info), GFP_ATOMIC); | 365 | sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask); |
| 365 | if (!sub_info) | 366 | if (!sub_info) |
| 366 | goto out; | 367 | goto out; |
| 367 | 368 | ||
| @@ -494,7 +495,7 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp, | |||
| 494 | struct subprocess_info *sub_info; | 495 | struct subprocess_info *sub_info; |
| 495 | int ret; | 496 | int ret; |
| 496 | 497 | ||
| 497 | sub_info = call_usermodehelper_setup(path, argv, envp); | 498 | sub_info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL); |
| 498 | if (sub_info == NULL) | 499 | if (sub_info == NULL) |
| 499 | return -ENOMEM; | 500 | return -ENOMEM; |
| 500 | 501 | ||
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 1485ca8d0e00..75bc2cd9ebc6 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name))) | 62 | addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name))) |
| 63 | #endif | 63 | #endif |
| 64 | 64 | ||
| 65 | static int kprobes_initialized; | ||
| 65 | static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; | 66 | static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; |
| 66 | static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; | 67 | static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; |
| 67 | 68 | ||
| @@ -69,8 +70,15 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; | |||
| 69 | static bool kprobe_enabled; | 70 | static bool kprobe_enabled; |
| 70 | 71 | ||
| 71 | DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ | 72 | DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ |
| 72 | DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ | ||
| 73 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; | 73 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; |
| 74 | static struct { | ||
| 75 | spinlock_t lock ____cacheline_aligned; | ||
| 76 | } kretprobe_table_locks[KPROBE_TABLE_SIZE]; | ||
| 77 | |||
| 78 | static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash) | ||
| 79 | { | ||
| 80 | return &(kretprobe_table_locks[hash].lock); | ||
| 81 | } | ||
| 74 | 82 | ||
| 75 | /* | 83 | /* |
| 76 | * Normally, functions that we'd want to prohibit kprobes in, are marked | 84 | * Normally, functions that we'd want to prohibit kprobes in, are marked |
| @@ -368,26 +376,53 @@ void __kprobes kprobes_inc_nmissed_count(struct kprobe *p) | |||
| 368 | return; | 376 | return; |
| 369 | } | 377 | } |
| 370 | 378 | ||
| 371 | /* Called with kretprobe_lock held */ | ||
| 372 | void __kprobes recycle_rp_inst(struct kretprobe_instance *ri, | 379 | void __kprobes recycle_rp_inst(struct kretprobe_instance *ri, |
| 373 | struct hlist_head *head) | 380 | struct hlist_head *head) |
| 374 | { | 381 | { |
| 382 | struct kretprobe *rp = ri->rp; | ||
| 383 | |||
| 375 | /* remove rp inst off the rprobe_inst_table */ | 384 | /* remove rp inst off the rprobe_inst_table */ |
| 376 | hlist_del(&ri->hlist); | 385 | hlist_del(&ri->hlist); |
| 377 | if (ri->rp) { | 386 | INIT_HLIST_NODE(&ri->hlist); |
| 378 | /* remove rp inst off the used list */ | 387 | if (likely(rp)) { |
| 379 | hlist_del(&ri->uflist); | 388 | spin_lock(&rp->lock); |
| 380 | /* put rp inst back onto the free list */ | 389 | hlist_add_head(&ri->hlist, &rp->free_instances); |
| 381 | INIT_HLIST_NODE(&ri->uflist); | 390 | spin_unlock(&rp->lock); |
| 382 | hlist_add_head(&ri->uflist, &ri->rp->free_instances); | ||
| 383 | } else | 391 | } else |
| 384 | /* Unregistering */ | 392 | /* Unregistering */ |
| 385 | hlist_add_head(&ri->hlist, head); | 393 | hlist_add_head(&ri->hlist, head); |
| 386 | } | 394 | } |
| 387 | 395 | ||
| 388 | struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk) | 396 | void kretprobe_hash_lock(struct task_struct *tsk, |
| 397 | struct hlist_head **head, unsigned long *flags) | ||
| 389 | { | 398 | { |
| 390 | return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; | 399 | unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS); |
| 400 | spinlock_t *hlist_lock; | ||
| 401 | |||
| 402 | *head = &kretprobe_inst_table[hash]; | ||
| 403 | hlist_lock = kretprobe_table_lock_ptr(hash); | ||
| 404 | spin_lock_irqsave(hlist_lock, *flags); | ||
| 405 | } | ||
| 406 | |||
| 407 | void kretprobe_table_lock(unsigned long hash, unsigned long *flags) | ||
| 408 | { | ||
| 409 | spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash); | ||
| 410 | spin_lock_irqsave(hlist_lock, *flags); | ||
| 411 | } | ||
| 412 | |||
| 413 | void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags) | ||
| 414 | { | ||
| 415 | unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS); | ||
| 416 | spinlock_t *hlist_lock; | ||
| 417 | |||
| 418 | hlist_lock = kretprobe_table_lock_ptr(hash); | ||
| 419 | spin_unlock_irqrestore(hlist_lock, *flags); | ||
| 420 | } | ||
| 421 | |||
| 422 | void kretprobe_table_unlock(unsigned long hash, unsigned long *flags) | ||
| 423 | { | ||
| 424 | spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash); | ||
| 425 | spin_unlock_irqrestore(hlist_lock, *flags); | ||
| 391 | } | 426 | } |
| 392 | 427 | ||
| 393 | /* | 428 | /* |
| @@ -401,17 +436,21 @@ void __kprobes kprobe_flush_task(struct task_struct *tk) | |||
| 401 | struct kretprobe_instance *ri; | 436 | struct kretprobe_instance *ri; |
| 402 | struct hlist_head *head, empty_rp; | 437 | struct hlist_head *head, empty_rp; |
| 403 | struct hlist_node *node, *tmp; | 438 | struct hlist_node *node, *tmp; |
| 404 | unsigned long flags = 0; | 439 | unsigned long hash, flags = 0; |
| 405 | 440 | ||
| 406 | INIT_HLIST_HEAD(&empty_rp); | 441 | if (unlikely(!kprobes_initialized)) |
| 407 | spin_lock_irqsave(&kretprobe_lock, flags); | 442 | /* Early boot. kretprobe_table_locks not yet initialized. */ |
| 408 | head = kretprobe_inst_table_head(tk); | 443 | return; |
| 444 | |||
| 445 | hash = hash_ptr(tk, KPROBE_HASH_BITS); | ||
| 446 | head = &kretprobe_inst_table[hash]; | ||
| 447 | kretprobe_table_lock(hash, &flags); | ||
| 409 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | 448 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { |
| 410 | if (ri->task == tk) | 449 | if (ri->task == tk) |
| 411 | recycle_rp_inst(ri, &empty_rp); | 450 | recycle_rp_inst(ri, &empty_rp); |
| 412 | } | 451 | } |
| 413 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 452 | kretprobe_table_unlock(hash, &flags); |
| 414 | 453 | INIT_HLIST_HEAD(&empty_rp); | |
| 415 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 454 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { |
| 416 | hlist_del(&ri->hlist); | 455 | hlist_del(&ri->hlist); |
| 417 | kfree(ri); | 456 | kfree(ri); |
| @@ -423,24 +462,29 @@ static inline void free_rp_inst(struct kretprobe *rp) | |||
| 423 | struct kretprobe_instance *ri; | 462 | struct kretprobe_instance *ri; |
| 424 | struct hlist_node *pos, *next; | 463 | struct hlist_node *pos, *next; |
| 425 | 464 | ||
| 426 | hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, uflist) { | 465 | hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, hlist) { |
| 427 | hlist_del(&ri->uflist); | 466 | hlist_del(&ri->hlist); |
| 428 | kfree(ri); | 467 | kfree(ri); |
| 429 | } | 468 | } |
| 430 | } | 469 | } |
| 431 | 470 | ||
| 432 | static void __kprobes cleanup_rp_inst(struct kretprobe *rp) | 471 | static void __kprobes cleanup_rp_inst(struct kretprobe *rp) |
| 433 | { | 472 | { |
| 434 | unsigned long flags; | 473 | unsigned long flags, hash; |
| 435 | struct kretprobe_instance *ri; | 474 | struct kretprobe_instance *ri; |
| 436 | struct hlist_node *pos, *next; | 475 | struct hlist_node *pos, *next; |
| 476 | struct hlist_head *head; | ||
| 477 | |||
| 437 | /* No race here */ | 478 | /* No race here */ |
| 438 | spin_lock_irqsave(&kretprobe_lock, flags); | 479 | for (hash = 0; hash < KPROBE_TABLE_SIZE; hash++) { |
| 439 | hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) { | 480 | kretprobe_table_lock(hash, &flags); |
| 440 | ri->rp = NULL; | 481 | head = &kretprobe_inst_table[hash]; |
| 441 | hlist_del(&ri->uflist); | 482 | hlist_for_each_entry_safe(ri, pos, next, head, hlist) { |
| 483 | if (ri->rp == rp) | ||
| 484 | ri->rp = NULL; | ||
| 485 | } | ||
| 486 | kretprobe_table_unlock(hash, &flags); | ||
| 442 | } | 487 | } |
| 443 | spin_unlock_irqrestore(&kretprobe_lock, flags); | ||
| 444 | free_rp_inst(rp); | 488 | free_rp_inst(rp); |
| 445 | } | 489 | } |
| 446 | 490 | ||
| @@ -831,32 +875,37 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, | |||
| 831 | struct pt_regs *regs) | 875 | struct pt_regs *regs) |
| 832 | { | 876 | { |
| 833 | struct kretprobe *rp = container_of(p, struct kretprobe, kp); | 877 | struct kretprobe *rp = container_of(p, struct kretprobe, kp); |
| 834 | unsigned long flags = 0; | 878 | unsigned long hash, flags = 0; |
| 879 | struct kretprobe_instance *ri; | ||
| 835 | 880 | ||
| 836 | /*TODO: consider to only swap the RA after the last pre_handler fired */ | 881 | /*TODO: consider to only swap the RA after the last pre_handler fired */ |
| 837 | spin_lock_irqsave(&kretprobe_lock, flags); | 882 | hash = hash_ptr(current, KPROBE_HASH_BITS); |
| 883 | spin_lock_irqsave(&rp->lock, flags); | ||
| 838 | if (!hlist_empty(&rp->free_instances)) { | 884 | if (!hlist_empty(&rp->free_instances)) { |
| 839 | struct kretprobe_instance *ri; | ||
| 840 | |||
| 841 | ri = hlist_entry(rp->free_instances.first, | 885 | ri = hlist_entry(rp->free_instances.first, |
| 842 | struct kretprobe_instance, uflist); | 886 | struct kretprobe_instance, hlist); |
| 887 | hlist_del(&ri->hlist); | ||
| 888 | spin_unlock_irqrestore(&rp->lock, flags); | ||
| 889 | |||
| 843 | ri->rp = rp; | 890 | ri->rp = rp; |
| 844 | ri->task = current; | 891 | ri->task = current; |
| 845 | 892 | ||
| 846 | if (rp->entry_handler && rp->entry_handler(ri, regs)) { | 893 | if (rp->entry_handler && rp->entry_handler(ri, regs)) { |
| 847 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 894 | spin_unlock_irqrestore(&rp->lock, flags); |
| 848 | return 0; | 895 | return 0; |
| 849 | } | 896 | } |
| 850 | 897 | ||
| 851 | arch_prepare_kretprobe(ri, regs); | 898 | arch_prepare_kretprobe(ri, regs); |
| 852 | 899 | ||
| 853 | /* XXX(hch): why is there no hlist_move_head? */ | 900 | /* XXX(hch): why is there no hlist_move_head? */ |
| 854 | hlist_del(&ri->uflist); | 901 | INIT_HLIST_NODE(&ri->hlist); |
| 855 | hlist_add_head(&ri->uflist, &ri->rp->used_instances); | 902 | kretprobe_table_lock(hash, &flags); |
| 856 | hlist_add_head(&ri->hlist, kretprobe_inst_table_head(ri->task)); | 903 | hlist_add_head(&ri->hlist, &kretprobe_inst_table[hash]); |
| 857 | } else | 904 | kretprobe_table_unlock(hash, &flags); |
| 905 | } else { | ||
| 858 | rp->nmissed++; | 906 | rp->nmissed++; |
| 859 | spin_unlock_irqrestore(&kretprobe_lock, flags); | 907 | spin_unlock_irqrestore(&rp->lock, flags); |
| 908 | } | ||
| 860 | return 0; | 909 | return 0; |
| 861 | } | 910 | } |
| 862 | 911 | ||
| @@ -892,7 +941,7 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp, | |||
| 892 | rp->maxactive = NR_CPUS; | 941 | rp->maxactive = NR_CPUS; |
| 893 | #endif | 942 | #endif |
| 894 | } | 943 | } |
| 895 | INIT_HLIST_HEAD(&rp->used_instances); | 944 | spin_lock_init(&rp->lock); |
| 896 | INIT_HLIST_HEAD(&rp->free_instances); | 945 | INIT_HLIST_HEAD(&rp->free_instances); |
| 897 | for (i = 0; i < rp->maxactive; i++) { | 946 | for (i = 0; i < rp->maxactive; i++) { |
| 898 | inst = kmalloc(sizeof(struct kretprobe_instance) + | 947 | inst = kmalloc(sizeof(struct kretprobe_instance) + |
| @@ -901,8 +950,8 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp, | |||
| 901 | free_rp_inst(rp); | 950 | free_rp_inst(rp); |
| 902 | return -ENOMEM; | 951 | return -ENOMEM; |
| 903 | } | 952 | } |
| 904 | INIT_HLIST_NODE(&inst->uflist); | 953 | INIT_HLIST_NODE(&inst->hlist); |
| 905 | hlist_add_head(&inst->uflist, &rp->free_instances); | 954 | hlist_add_head(&inst->hlist, &rp->free_instances); |
| 906 | } | 955 | } |
| 907 | 956 | ||
| 908 | rp->nmissed = 0; | 957 | rp->nmissed = 0; |
| @@ -1009,6 +1058,7 @@ static int __init init_kprobes(void) | |||
| 1009 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1058 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
| 1010 | INIT_HLIST_HEAD(&kprobe_table[i]); | 1059 | INIT_HLIST_HEAD(&kprobe_table[i]); |
| 1011 | INIT_HLIST_HEAD(&kretprobe_inst_table[i]); | 1060 | INIT_HLIST_HEAD(&kretprobe_inst_table[i]); |
| 1061 | spin_lock_init(&(kretprobe_table_locks[i].lock)); | ||
| 1012 | } | 1062 | } |
| 1013 | 1063 | ||
| 1014 | /* | 1064 | /* |
| @@ -1050,6 +1100,7 @@ static int __init init_kprobes(void) | |||
| 1050 | err = arch_init_kprobes(); | 1100 | err = arch_init_kprobes(); |
| 1051 | if (!err) | 1101 | if (!err) |
| 1052 | err = register_die_notifier(&kprobe_exceptions_nb); | 1102 | err = register_die_notifier(&kprobe_exceptions_nb); |
| 1103 | kprobes_initialized = (err == 0); | ||
| 1053 | 1104 | ||
| 1054 | if (!err) | 1105 | if (!err) |
| 1055 | init_test_probes(); | 1106 | init_test_probes(); |
| @@ -1286,13 +1337,8 @@ EXPORT_SYMBOL_GPL(register_jprobe); | |||
| 1286 | EXPORT_SYMBOL_GPL(unregister_jprobe); | 1337 | EXPORT_SYMBOL_GPL(unregister_jprobe); |
| 1287 | EXPORT_SYMBOL_GPL(register_jprobes); | 1338 | EXPORT_SYMBOL_GPL(register_jprobes); |
| 1288 | EXPORT_SYMBOL_GPL(unregister_jprobes); | 1339 | EXPORT_SYMBOL_GPL(unregister_jprobes); |
| 1289 | #ifdef CONFIG_KPROBES | ||
| 1290 | EXPORT_SYMBOL_GPL(jprobe_return); | 1340 | EXPORT_SYMBOL_GPL(jprobe_return); |
| 1291 | #endif | ||
| 1292 | |||
| 1293 | #ifdef CONFIG_KPROBES | ||
| 1294 | EXPORT_SYMBOL_GPL(register_kretprobe); | 1341 | EXPORT_SYMBOL_GPL(register_kretprobe); |
| 1295 | EXPORT_SYMBOL_GPL(unregister_kretprobe); | 1342 | EXPORT_SYMBOL_GPL(unregister_kretprobe); |
| 1296 | EXPORT_SYMBOL_GPL(register_kretprobes); | 1343 | EXPORT_SYMBOL_GPL(register_kretprobes); |
| 1297 | EXPORT_SYMBOL_GPL(unregister_kretprobes); | 1344 | EXPORT_SYMBOL_GPL(unregister_kretprobes); |
| 1298 | #endif | ||
diff --git a/kernel/marker.c b/kernel/marker.c index 1abfb923b761..971da5317903 100644 --- a/kernel/marker.c +++ b/kernel/marker.c | |||
| @@ -441,7 +441,7 @@ static int remove_marker(const char *name) | |||
| 441 | hlist_del(&e->hlist); | 441 | hlist_del(&e->hlist); |
| 442 | /* Make sure the call_rcu has been executed */ | 442 | /* Make sure the call_rcu has been executed */ |
| 443 | if (e->rcu_pending) | 443 | if (e->rcu_pending) |
| 444 | rcu_barrier(); | 444 | rcu_barrier_sched(); |
| 445 | kfree(e); | 445 | kfree(e); |
| 446 | return 0; | 446 | return 0; |
| 447 | } | 447 | } |
| @@ -476,7 +476,7 @@ static int marker_set_format(struct marker_entry **entry, const char *format) | |||
| 476 | hlist_del(&(*entry)->hlist); | 476 | hlist_del(&(*entry)->hlist); |
| 477 | /* Make sure the call_rcu has been executed */ | 477 | /* Make sure the call_rcu has been executed */ |
| 478 | if ((*entry)->rcu_pending) | 478 | if ((*entry)->rcu_pending) |
| 479 | rcu_barrier(); | 479 | rcu_barrier_sched(); |
| 480 | kfree(*entry); | 480 | kfree(*entry); |
| 481 | *entry = e; | 481 | *entry = e; |
| 482 | trace_mark(core_marker_format, "name %s format %s", | 482 | trace_mark(core_marker_format, "name %s format %s", |
| @@ -655,7 +655,7 @@ int marker_probe_register(const char *name, const char *format, | |||
| 655 | * make sure it's executed now. | 655 | * make sure it's executed now. |
| 656 | */ | 656 | */ |
| 657 | if (entry->rcu_pending) | 657 | if (entry->rcu_pending) |
| 658 | rcu_barrier(); | 658 | rcu_barrier_sched(); |
| 659 | old = marker_entry_add_probe(entry, probe, probe_private); | 659 | old = marker_entry_add_probe(entry, probe, probe_private); |
| 660 | if (IS_ERR(old)) { | 660 | if (IS_ERR(old)) { |
| 661 | ret = PTR_ERR(old); | 661 | ret = PTR_ERR(old); |
| @@ -670,10 +670,7 @@ int marker_probe_register(const char *name, const char *format, | |||
| 670 | entry->rcu_pending = 1; | 670 | entry->rcu_pending = 1; |
| 671 | /* write rcu_pending before calling the RCU callback */ | 671 | /* write rcu_pending before calling the RCU callback */ |
| 672 | smp_wmb(); | 672 | smp_wmb(); |
| 673 | #ifdef CONFIG_PREEMPT_RCU | 673 | call_rcu_sched(&entry->rcu, free_old_closure); |
| 674 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
| 675 | #endif | ||
| 676 | call_rcu(&entry->rcu, free_old_closure); | ||
| 677 | end: | 674 | end: |
| 678 | mutex_unlock(&markers_mutex); | 675 | mutex_unlock(&markers_mutex); |
| 679 | return ret; | 676 | return ret; |
| @@ -704,7 +701,7 @@ int marker_probe_unregister(const char *name, | |||
| 704 | if (!entry) | 701 | if (!entry) |
| 705 | goto end; | 702 | goto end; |
| 706 | if (entry->rcu_pending) | 703 | if (entry->rcu_pending) |
| 707 | rcu_barrier(); | 704 | rcu_barrier_sched(); |
| 708 | old = marker_entry_remove_probe(entry, probe, probe_private); | 705 | old = marker_entry_remove_probe(entry, probe, probe_private); |
| 709 | mutex_unlock(&markers_mutex); | 706 | mutex_unlock(&markers_mutex); |
| 710 | marker_update_probes(); /* may update entry */ | 707 | marker_update_probes(); /* may update entry */ |
| @@ -716,10 +713,7 @@ int marker_probe_unregister(const char *name, | |||
| 716 | entry->rcu_pending = 1; | 713 | entry->rcu_pending = 1; |
| 717 | /* write rcu_pending before calling the RCU callback */ | 714 | /* write rcu_pending before calling the RCU callback */ |
| 718 | smp_wmb(); | 715 | smp_wmb(); |
| 719 | #ifdef CONFIG_PREEMPT_RCU | 716 | call_rcu_sched(&entry->rcu, free_old_closure); |
| 720 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
| 721 | #endif | ||
| 722 | call_rcu(&entry->rcu, free_old_closure); | ||
| 723 | remove_marker(name); /* Ignore busy error message */ | 717 | remove_marker(name); /* Ignore busy error message */ |
| 724 | ret = 0; | 718 | ret = 0; |
| 725 | end: | 719 | end: |
| @@ -786,7 +780,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
| 786 | goto end; | 780 | goto end; |
| 787 | } | 781 | } |
| 788 | if (entry->rcu_pending) | 782 | if (entry->rcu_pending) |
| 789 | rcu_barrier(); | 783 | rcu_barrier_sched(); |
| 790 | old = marker_entry_remove_probe(entry, NULL, probe_private); | 784 | old = marker_entry_remove_probe(entry, NULL, probe_private); |
| 791 | mutex_unlock(&markers_mutex); | 785 | mutex_unlock(&markers_mutex); |
| 792 | marker_update_probes(); /* may update entry */ | 786 | marker_update_probes(); /* may update entry */ |
| @@ -797,10 +791,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, | |||
| 797 | entry->rcu_pending = 1; | 791 | entry->rcu_pending = 1; |
| 798 | /* write rcu_pending before calling the RCU callback */ | 792 | /* write rcu_pending before calling the RCU callback */ |
| 799 | smp_wmb(); | 793 | smp_wmb(); |
| 800 | #ifdef CONFIG_PREEMPT_RCU | 794 | call_rcu_sched(&entry->rcu, free_old_closure); |
| 801 | synchronize_sched(); /* Until we have the call_rcu_sched() */ | ||
| 802 | #endif | ||
| 803 | call_rcu(&entry->rcu, free_old_closure); | ||
| 804 | remove_marker(entry->name); /* Ignore busy error message */ | 795 | remove_marker(entry->name); /* Ignore busy error message */ |
| 805 | end: | 796 | end: |
| 806 | mutex_unlock(&markers_mutex); | 797 | mutex_unlock(&markers_mutex); |
diff --git a/kernel/ns_cgroup.c b/kernel/ns_cgroup.c index 48d7ed6fc3a4..43c2111cd54d 100644 --- a/kernel/ns_cgroup.c +++ b/kernel/ns_cgroup.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 8 | #include <linux/cgroup.h> | 8 | #include <linux/cgroup.h> |
| 9 | #include <linux/fs.h> | 9 | #include <linux/fs.h> |
| 10 | #include <linux/proc_fs.h> | ||
| 10 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 11 | #include <linux/nsproxy.h> | 12 | #include <linux/nsproxy.h> |
| 12 | 13 | ||
| @@ -24,9 +25,12 @@ static inline struct ns_cgroup *cgroup_to_ns( | |||
| 24 | struct ns_cgroup, css); | 25 | struct ns_cgroup, css); |
| 25 | } | 26 | } |
| 26 | 27 | ||
| 27 | int ns_cgroup_clone(struct task_struct *task) | 28 | int ns_cgroup_clone(struct task_struct *task, struct pid *pid) |
| 28 | { | 29 | { |
| 29 | return cgroup_clone(task, &ns_subsys); | 30 | char name[PROC_NUMBUF]; |
| 31 | |||
| 32 | snprintf(name, PROC_NUMBUF, "%d", pid_vnr(pid)); | ||
| 33 | return cgroup_clone(task, &ns_subsys, name); | ||
| 30 | } | 34 | } |
| 31 | 35 | ||
| 32 | /* | 36 | /* |
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index adc785146a1c..21575fc46d05 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
| @@ -157,12 +157,6 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk) | |||
| 157 | goto out; | 157 | goto out; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | err = ns_cgroup_clone(tsk); | ||
| 161 | if (err) { | ||
| 162 | put_nsproxy(new_ns); | ||
| 163 | goto out; | ||
| 164 | } | ||
| 165 | |||
| 166 | tsk->nsproxy = new_ns; | 160 | tsk->nsproxy = new_ns; |
| 167 | 161 | ||
| 168 | out: | 162 | out: |
| @@ -209,7 +203,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags, | |||
| 209 | goto out; | 203 | goto out; |
| 210 | } | 204 | } |
| 211 | 205 | ||
| 212 | err = ns_cgroup_clone(current); | 206 | err = ns_cgroup_clone(current, task_pid(current)); |
| 213 | if (err) | 207 | if (err) |
| 214 | put_nsproxy(*new_nsp); | 208 | put_nsproxy(*new_nsp); |
| 215 | 209 | ||
diff --git a/kernel/panic.c b/kernel/panic.c index 425567f45b9f..12c5a0a6c89b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
| @@ -318,6 +318,28 @@ void warn_on_slowpath(const char *file, int line) | |||
| 318 | add_taint(TAINT_WARN); | 318 | add_taint(TAINT_WARN); |
| 319 | } | 319 | } |
| 320 | EXPORT_SYMBOL(warn_on_slowpath); | 320 | EXPORT_SYMBOL(warn_on_slowpath); |
| 321 | |||
| 322 | |||
| 323 | void warn_slowpath(const char *file, int line, const char *fmt, ...) | ||
| 324 | { | ||
| 325 | va_list args; | ||
| 326 | char function[KSYM_SYMBOL_LEN]; | ||
| 327 | unsigned long caller = (unsigned long)__builtin_return_address(0); | ||
| 328 | sprint_symbol(function, caller); | ||
| 329 | |||
| 330 | printk(KERN_WARNING "------------[ cut here ]------------\n"); | ||
| 331 | printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, | ||
| 332 | line, function); | ||
| 333 | va_start(args, fmt); | ||
| 334 | vprintk(fmt, args); | ||
| 335 | va_end(args); | ||
| 336 | |||
| 337 | print_modules(); | ||
| 338 | dump_stack(); | ||
| 339 | print_oops_end_marker(); | ||
| 340 | add_taint(TAINT_WARN); | ||
| 341 | } | ||
| 342 | EXPORT_SYMBOL(warn_slowpath); | ||
| 321 | #endif | 343 | #endif |
| 322 | 344 | ||
| 323 | #ifdef CONFIG_CC_STACKPROTECTOR | 345 | #ifdef CONFIG_CC_STACKPROTECTOR |
diff --git a/kernel/pid.c b/kernel/pid.c index 30bd5d4b2ac7..064e76afa507 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
| @@ -309,12 +309,6 @@ struct pid *find_vpid(int nr) | |||
| 309 | } | 309 | } |
| 310 | EXPORT_SYMBOL_GPL(find_vpid); | 310 | EXPORT_SYMBOL_GPL(find_vpid); |
| 311 | 311 | ||
| 312 | struct pid *find_pid(int nr) | ||
| 313 | { | ||
| 314 | return find_pid_ns(nr, &init_pid_ns); | ||
| 315 | } | ||
| 316 | EXPORT_SYMBOL_GPL(find_pid); | ||
| 317 | |||
| 318 | /* | 312 | /* |
| 319 | * attach_pid() must be called with the tasklist_lock write-held. | 313 | * attach_pid() must be called with the tasklist_lock write-held. |
| 320 | */ | 314 | */ |
| @@ -435,6 +429,7 @@ struct pid *find_get_pid(pid_t nr) | |||
| 435 | 429 | ||
| 436 | return pid; | 430 | return pid; |
| 437 | } | 431 | } |
| 432 | EXPORT_SYMBOL_GPL(find_get_pid); | ||
| 438 | 433 | ||
| 439 | pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns) | 434 | pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns) |
| 440 | { | 435 | { |
| @@ -482,7 +477,7 @@ EXPORT_SYMBOL(task_session_nr_ns); | |||
| 482 | /* | 477 | /* |
| 483 | * Used by proc to find the first pid that is greater then or equal to nr. | 478 | * Used by proc to find the first pid that is greater then or equal to nr. |
| 484 | * | 479 | * |
| 485 | * If there is a pid at nr this function is exactly the same as find_pid. | 480 | * If there is a pid at nr this function is exactly the same as find_pid_ns. |
| 486 | */ | 481 | */ |
| 487 | struct pid *find_ge_pid(int nr, struct pid_namespace *ns) | 482 | struct pid *find_ge_pid(int nr, struct pid_namespace *ns) |
| 488 | { | 483 | { |
| @@ -497,7 +492,6 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns) | |||
| 497 | 492 | ||
| 498 | return pid; | 493 | return pid; |
| 499 | } | 494 | } |
| 500 | EXPORT_SYMBOL_GPL(find_get_pid); | ||
| 501 | 495 | ||
| 502 | /* | 496 | /* |
| 503 | * The pid hash table is scaled according to the amount of memory in the | 497 | * The pid hash table is scaled according to the amount of memory in the |
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 98702b4b8851..ea567b78d1aa 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/pid_namespace.h> | 12 | #include <linux/pid_namespace.h> |
| 13 | #include <linux/syscalls.h> | 13 | #include <linux/syscalls.h> |
| 14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
| 15 | #include <linux/acct.h> | ||
| 15 | 16 | ||
| 16 | #define BITS_PER_PAGE (PAGE_SIZE*8) | 17 | #define BITS_PER_PAGE (PAGE_SIZE*8) |
| 17 | 18 | ||
| @@ -71,7 +72,7 @@ static struct pid_namespace *create_pid_namespace(unsigned int level) | |||
| 71 | struct pid_namespace *ns; | 72 | struct pid_namespace *ns; |
| 72 | int i; | 73 | int i; |
| 73 | 74 | ||
| 74 | ns = kmem_cache_alloc(pid_ns_cachep, GFP_KERNEL); | 75 | ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL); |
| 75 | if (ns == NULL) | 76 | if (ns == NULL) |
| 76 | goto out; | 77 | goto out; |
| 77 | 78 | ||
| @@ -84,17 +85,13 @@ static struct pid_namespace *create_pid_namespace(unsigned int level) | |||
| 84 | goto out_free_map; | 85 | goto out_free_map; |
| 85 | 86 | ||
| 86 | kref_init(&ns->kref); | 87 | kref_init(&ns->kref); |
| 87 | ns->last_pid = 0; | ||
| 88 | ns->child_reaper = NULL; | ||
| 89 | ns->level = level; | 88 | ns->level = level; |
| 90 | 89 | ||
| 91 | set_bit(0, ns->pidmap[0].page); | 90 | set_bit(0, ns->pidmap[0].page); |
| 92 | atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1); | 91 | atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1); |
| 93 | 92 | ||
| 94 | for (i = 1; i < PIDMAP_ENTRIES; i++) { | 93 | for (i = 1; i < PIDMAP_ENTRIES; i++) |
| 95 | ns->pidmap[i].page = NULL; | ||
| 96 | atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE); | 94 | atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE); |
| 97 | } | ||
| 98 | 95 | ||
| 99 | return ns; | 96 | return ns; |
| 100 | 97 | ||
| @@ -185,6 +182,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
| 185 | 182 | ||
| 186 | /* Child reaper for the pid namespace is going away */ | 183 | /* Child reaper for the pid namespace is going away */ |
| 187 | pid_ns->child_reaper = NULL; | 184 | pid_ns->child_reaper = NULL; |
| 185 | acct_exit_ns(pid_ns); | ||
| 188 | return; | 186 | return; |
| 189 | } | 187 | } |
| 190 | 188 | ||
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index dbd8398ddb0b..9a21681aa80f 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
| @@ -449,9 +449,6 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set) | |||
| 449 | spin_unlock_irqrestore(&idr_lock, flags); | 449 | spin_unlock_irqrestore(&idr_lock, flags); |
| 450 | } | 450 | } |
| 451 | sigqueue_free(tmr->sigq); | 451 | sigqueue_free(tmr->sigq); |
| 452 | if (unlikely(tmr->it_process) && | ||
| 453 | tmr->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) | ||
| 454 | put_task_struct(tmr->it_process); | ||
| 455 | kmem_cache_free(posix_timers_cache, tmr); | 452 | kmem_cache_free(posix_timers_cache, tmr); |
| 456 | } | 453 | } |
| 457 | 454 | ||
| @@ -856,11 +853,10 @@ retry_delete: | |||
| 856 | * This keeps any tasks waiting on the spin lock from thinking | 853 | * This keeps any tasks waiting on the spin lock from thinking |
| 857 | * they got something (see the lock code above). | 854 | * they got something (see the lock code above). |
| 858 | */ | 855 | */ |
| 859 | if (timer->it_process) { | 856 | if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) |
| 860 | if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) | 857 | put_task_struct(timer->it_process); |
| 861 | put_task_struct(timer->it_process); | 858 | timer->it_process = NULL; |
| 862 | timer->it_process = NULL; | 859 | |
| 863 | } | ||
| 864 | unlock_timer(timer, flags); | 860 | unlock_timer(timer, flags); |
| 865 | release_posix_timer(timer, IT_ID_SET); | 861 | release_posix_timer(timer, IT_ID_SET); |
| 866 | return 0; | 862 | return 0; |
| @@ -885,11 +881,10 @@ retry_delete: | |||
| 885 | * This keeps any tasks waiting on the spin lock from thinking | 881 | * This keeps any tasks waiting on the spin lock from thinking |
| 886 | * they got something (see the lock code above). | 882 | * they got something (see the lock code above). |
| 887 | */ | 883 | */ |
| 888 | if (timer->it_process) { | 884 | if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) |
| 889 | if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) | 885 | put_task_struct(timer->it_process); |
| 890 | put_task_struct(timer->it_process); | 886 | timer->it_process = NULL; |
| 891 | timer->it_process = NULL; | 887 | |
| 892 | } | ||
| 893 | unlock_timer(timer, flags); | 888 | unlock_timer(timer, flags); |
| 894 | release_posix_timer(timer, IT_ID_SET); | 889 | release_posix_timer(timer, IT_ID_SET); |
| 895 | } | 890 | } |
diff --git a/kernel/printk.c b/kernel/printk.c index 3f7a2a94583b..a7f7559c5f6c 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -1308,6 +1308,8 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
| 1308 | } | 1308 | } |
| 1309 | 1309 | ||
| 1310 | #if defined CONFIG_PRINTK | 1310 | #if defined CONFIG_PRINTK |
| 1311 | |||
| 1312 | DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10); | ||
| 1311 | /* | 1313 | /* |
| 1312 | * printk rate limiting, lifted from the networking subsystem. | 1314 | * printk rate limiting, lifted from the networking subsystem. |
| 1313 | * | 1315 | * |
| @@ -1315,22 +1317,9 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
| 1315 | * every printk_ratelimit_jiffies to make a denial-of-service | 1317 | * every printk_ratelimit_jiffies to make a denial-of-service |
| 1316 | * attack impossible. | 1318 | * attack impossible. |
| 1317 | */ | 1319 | */ |
| 1318 | int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst) | ||
| 1319 | { | ||
| 1320 | return __ratelimit(ratelimit_jiffies, ratelimit_burst); | ||
| 1321 | } | ||
| 1322 | EXPORT_SYMBOL(__printk_ratelimit); | ||
| 1323 | |||
| 1324 | /* minimum time in jiffies between messages */ | ||
| 1325 | int printk_ratelimit_jiffies = 5 * HZ; | ||
| 1326 | |||
| 1327 | /* number of messages we send before ratelimiting */ | ||
| 1328 | int printk_ratelimit_burst = 10; | ||
| 1329 | |||
| 1330 | int printk_ratelimit(void) | 1320 | int printk_ratelimit(void) |
| 1331 | { | 1321 | { |
| 1332 | return __printk_ratelimit(printk_ratelimit_jiffies, | 1322 | return __ratelimit(&printk_ratelimit_state); |
| 1333 | printk_ratelimit_burst); | ||
| 1334 | } | 1323 | } |
| 1335 | EXPORT_SYMBOL(printk_ratelimit); | 1324 | EXPORT_SYMBOL(printk_ratelimit); |
| 1336 | 1325 | ||
diff --git a/kernel/profile.c b/kernel/profile.c index 58926411eb2a..cd26bed4cc26 100644 --- a/kernel/profile.c +++ b/kernel/profile.c | |||
| @@ -112,8 +112,6 @@ void __init profile_init(void) | |||
| 112 | 112 | ||
| 113 | /* Profile event notifications */ | 113 | /* Profile event notifications */ |
| 114 | 114 | ||
| 115 | #ifdef CONFIG_PROFILING | ||
| 116 | |||
| 117 | static BLOCKING_NOTIFIER_HEAD(task_exit_notifier); | 115 | static BLOCKING_NOTIFIER_HEAD(task_exit_notifier); |
| 118 | static ATOMIC_NOTIFIER_HEAD(task_free_notifier); | 116 | static ATOMIC_NOTIFIER_HEAD(task_free_notifier); |
| 119 | static BLOCKING_NOTIFIER_HEAD(munmap_notifier); | 117 | static BLOCKING_NOTIFIER_HEAD(munmap_notifier); |
| @@ -203,8 +201,6 @@ void unregister_timer_hook(int (*hook)(struct pt_regs *)) | |||
| 203 | } | 201 | } |
| 204 | EXPORT_SYMBOL_GPL(unregister_timer_hook); | 202 | EXPORT_SYMBOL_GPL(unregister_timer_hook); |
| 205 | 203 | ||
| 206 | #endif /* CONFIG_PROFILING */ | ||
| 207 | |||
| 208 | 204 | ||
| 209 | #ifdef CONFIG_SMP | 205 | #ifdef CONFIG_SMP |
| 210 | /* | 206 | /* |
diff --git a/kernel/res_counter.c b/kernel/res_counter.c index d3c61b4ebef2..f275c8eca772 100644 --- a/kernel/res_counter.c +++ b/kernel/res_counter.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 14 | #include <linux/res_counter.h> | 14 | #include <linux/res_counter.h> |
| 15 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
| 16 | #include <linux/mm.h> | ||
| 16 | 17 | ||
| 17 | void res_counter_init(struct res_counter *counter) | 18 | void res_counter_init(struct res_counter *counter) |
| 18 | { | 19 | { |
| @@ -102,44 +103,37 @@ u64 res_counter_read_u64(struct res_counter *counter, int member) | |||
| 102 | return *res_counter_member(counter, member); | 103 | return *res_counter_member(counter, member); |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | ssize_t res_counter_write(struct res_counter *counter, int member, | 106 | int res_counter_memparse_write_strategy(const char *buf, |
| 106 | const char __user *userbuf, size_t nbytes, loff_t *pos, | 107 | unsigned long long *res) |
| 107 | int (*write_strategy)(char *st_buf, unsigned long long *val)) | ||
| 108 | { | 108 | { |
| 109 | int ret; | 109 | char *end; |
| 110 | char *buf, *end; | 110 | /* FIXME - make memparse() take const char* args */ |
| 111 | unsigned long flags; | 111 | *res = memparse((char *)buf, &end); |
| 112 | unsigned long long tmp, *val; | 112 | if (*end != '\0') |
| 113 | 113 | return -EINVAL; | |
| 114 | buf = kmalloc(nbytes + 1, GFP_KERNEL); | ||
| 115 | ret = -ENOMEM; | ||
| 116 | if (buf == NULL) | ||
| 117 | goto out; | ||
| 118 | 114 | ||
| 119 | buf[nbytes] = '\0'; | 115 | *res = PAGE_ALIGN(*res); |
| 120 | ret = -EFAULT; | 116 | return 0; |
| 121 | if (copy_from_user(buf, userbuf, nbytes)) | 117 | } |
| 122 | goto out_free; | ||
| 123 | 118 | ||
| 124 | ret = -EINVAL; | 119 | int res_counter_write(struct res_counter *counter, int member, |
| 120 | const char *buf, write_strategy_fn write_strategy) | ||
| 121 | { | ||
| 122 | char *end; | ||
| 123 | unsigned long flags; | ||
| 124 | unsigned long long tmp, *val; | ||
| 125 | 125 | ||
| 126 | strstrip(buf); | ||
| 127 | if (write_strategy) { | 126 | if (write_strategy) { |
| 128 | if (write_strategy(buf, &tmp)) { | 127 | if (write_strategy(buf, &tmp)) |
| 129 | goto out_free; | 128 | return -EINVAL; |
| 130 | } | ||
| 131 | } else { | 129 | } else { |
| 132 | tmp = simple_strtoull(buf, &end, 10); | 130 | tmp = simple_strtoull(buf, &end, 10); |
| 133 | if (*end != '\0') | 131 | if (*end != '\0') |
| 134 | goto out_free; | 132 | return -EINVAL; |
| 135 | } | 133 | } |
| 136 | spin_lock_irqsave(&counter->lock, flags); | 134 | spin_lock_irqsave(&counter->lock, flags); |
| 137 | val = res_counter_member(counter, member); | 135 | val = res_counter_member(counter, member); |
| 138 | *val = tmp; | 136 | *val = tmp; |
| 139 | spin_unlock_irqrestore(&counter->lock, flags); | 137 | spin_unlock_irqrestore(&counter->lock, flags); |
| 140 | ret = nbytes; | 138 | return 0; |
| 141 | out_free: | ||
| 142 | kfree(buf); | ||
| 143 | out: | ||
| 144 | return ret; | ||
| 145 | } | 139 | } |
diff --git a/kernel/sched.c b/kernel/sched.c index 6acf749d3336..0047bd9b96aa 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -4046,6 +4046,8 @@ void account_user_time(struct task_struct *p, cputime_t cputime) | |||
| 4046 | cpustat->nice = cputime64_add(cpustat->nice, tmp); | 4046 | cpustat->nice = cputime64_add(cpustat->nice, tmp); |
| 4047 | else | 4047 | else |
| 4048 | cpustat->user = cputime64_add(cpustat->user, tmp); | 4048 | cpustat->user = cputime64_add(cpustat->user, tmp); |
| 4049 | /* Account for user time used */ | ||
| 4050 | acct_update_integrals(p); | ||
| 4049 | } | 4051 | } |
| 4050 | 4052 | ||
| 4051 | /* | 4053 | /* |
diff --git a/kernel/signal.c b/kernel/signal.c index 6c0958e52ea7..82c3545596c5 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -338,13 +338,9 @@ unblock_all_signals(void) | |||
| 338 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | 338 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) | 341 | static void collect_signal(int sig, struct sigpending *list, siginfo_t *info) |
| 342 | { | 342 | { |
| 343 | struct sigqueue *q, *first = NULL; | 343 | struct sigqueue *q, *first = NULL; |
| 344 | int still_pending = 0; | ||
| 345 | |||
| 346 | if (unlikely(!sigismember(&list->signal, sig))) | ||
| 347 | return 0; | ||
| 348 | 344 | ||
| 349 | /* | 345 | /* |
| 350 | * Collect the siginfo appropriate to this signal. Check if | 346 | * Collect the siginfo appropriate to this signal. Check if |
| @@ -352,33 +348,30 @@ static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) | |||
| 352 | */ | 348 | */ |
| 353 | list_for_each_entry(q, &list->list, list) { | 349 | list_for_each_entry(q, &list->list, list) { |
| 354 | if (q->info.si_signo == sig) { | 350 | if (q->info.si_signo == sig) { |
| 355 | if (first) { | 351 | if (first) |
| 356 | still_pending = 1; | 352 | goto still_pending; |
| 357 | break; | ||
| 358 | } | ||
| 359 | first = q; | 353 | first = q; |
| 360 | } | 354 | } |
| 361 | } | 355 | } |
| 356 | |||
| 357 | sigdelset(&list->signal, sig); | ||
| 358 | |||
| 362 | if (first) { | 359 | if (first) { |
| 360 | still_pending: | ||
| 363 | list_del_init(&first->list); | 361 | list_del_init(&first->list); |
| 364 | copy_siginfo(info, &first->info); | 362 | copy_siginfo(info, &first->info); |
| 365 | __sigqueue_free(first); | 363 | __sigqueue_free(first); |
| 366 | if (!still_pending) | ||
| 367 | sigdelset(&list->signal, sig); | ||
| 368 | } else { | 364 | } else { |
| 369 | |||
| 370 | /* Ok, it wasn't in the queue. This must be | 365 | /* Ok, it wasn't in the queue. This must be |
| 371 | a fast-pathed signal or we must have been | 366 | a fast-pathed signal or we must have been |
| 372 | out of queue space. So zero out the info. | 367 | out of queue space. So zero out the info. |
| 373 | */ | 368 | */ |
| 374 | sigdelset(&list->signal, sig); | ||
| 375 | info->si_signo = sig; | 369 | info->si_signo = sig; |
| 376 | info->si_errno = 0; | 370 | info->si_errno = 0; |
| 377 | info->si_code = 0; | 371 | info->si_code = 0; |
| 378 | info->si_pid = 0; | 372 | info->si_pid = 0; |
| 379 | info->si_uid = 0; | 373 | info->si_uid = 0; |
| 380 | } | 374 | } |
| 381 | return 1; | ||
| 382 | } | 375 | } |
| 383 | 376 | ||
| 384 | static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, | 377 | static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, |
| @@ -396,8 +389,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, | |||
| 396 | } | 389 | } |
| 397 | } | 390 | } |
| 398 | 391 | ||
| 399 | if (!collect_signal(sig, pending, info)) | 392 | collect_signal(sig, pending, info); |
| 400 | sig = 0; | ||
| 401 | } | 393 | } |
| 402 | 394 | ||
| 403 | return sig; | 395 | return sig; |
| @@ -462,8 +454,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) | |||
| 462 | * is to alert stop-signal processing code when another | 454 | * is to alert stop-signal processing code when another |
| 463 | * processor has come along and cleared the flag. | 455 | * processor has come along and cleared the flag. |
| 464 | */ | 456 | */ |
| 465 | if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) | 457 | tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; |
| 466 | tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; | ||
| 467 | } | 458 | } |
| 468 | if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { | 459 | if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { |
| 469 | /* | 460 | /* |
| @@ -1125,7 +1116,7 @@ EXPORT_SYMBOL_GPL(kill_pid_info_as_uid); | |||
| 1125 | * is probably wrong. Should make it like BSD or SYSV. | 1116 | * is probably wrong. Should make it like BSD or SYSV. |
| 1126 | */ | 1117 | */ |
| 1127 | 1118 | ||
| 1128 | static int kill_something_info(int sig, struct siginfo *info, int pid) | 1119 | static int kill_something_info(int sig, struct siginfo *info, pid_t pid) |
| 1129 | { | 1120 | { |
| 1130 | int ret; | 1121 | int ret; |
| 1131 | 1122 | ||
| @@ -1237,17 +1228,6 @@ int kill_pid(struct pid *pid, int sig, int priv) | |||
| 1237 | } | 1228 | } |
| 1238 | EXPORT_SYMBOL(kill_pid); | 1229 | EXPORT_SYMBOL(kill_pid); |
| 1239 | 1230 | ||
| 1240 | int | ||
| 1241 | kill_proc(pid_t pid, int sig, int priv) | ||
| 1242 | { | ||
| 1243 | int ret; | ||
| 1244 | |||
| 1245 | rcu_read_lock(); | ||
| 1246 | ret = kill_pid_info(sig, __si_special(priv), find_pid(pid)); | ||
| 1247 | rcu_read_unlock(); | ||
| 1248 | return ret; | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | /* | 1231 | /* |
| 1252 | * These functions support sending signals using preallocated sigqueue | 1232 | * These functions support sending signals using preallocated sigqueue |
| 1253 | * structures. This is needed "because realtime applications cannot | 1233 | * structures. This is needed "because realtime applications cannot |
| @@ -1379,10 +1359,9 @@ void do_notify_parent(struct task_struct *tsk, int sig) | |||
| 1379 | 1359 | ||
| 1380 | info.si_uid = tsk->uid; | 1360 | info.si_uid = tsk->uid; |
| 1381 | 1361 | ||
| 1382 | /* FIXME: find out whether or not this is supposed to be c*time. */ | 1362 | info.si_utime = cputime_to_clock_t(cputime_add(tsk->utime, |
| 1383 | info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime, | ||
| 1384 | tsk->signal->utime)); | 1363 | tsk->signal->utime)); |
| 1385 | info.si_stime = cputime_to_jiffies(cputime_add(tsk->stime, | 1364 | info.si_stime = cputime_to_clock_t(cputime_add(tsk->stime, |
| 1386 | tsk->signal->stime)); | 1365 | tsk->signal->stime)); |
| 1387 | 1366 | ||
| 1388 | info.si_status = tsk->exit_code & 0x7f; | 1367 | info.si_status = tsk->exit_code & 0x7f; |
| @@ -1450,9 +1429,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why) | |||
| 1450 | 1429 | ||
| 1451 | info.si_uid = tsk->uid; | 1430 | info.si_uid = tsk->uid; |
| 1452 | 1431 | ||
| 1453 | /* FIXME: find out whether or not this is supposed to be c*time. */ | 1432 | info.si_utime = cputime_to_clock_t(tsk->utime); |
| 1454 | info.si_utime = cputime_to_jiffies(tsk->utime); | 1433 | info.si_stime = cputime_to_clock_t(tsk->stime); |
| 1455 | info.si_stime = cputime_to_jiffies(tsk->stime); | ||
| 1456 | 1434 | ||
| 1457 | info.si_code = why; | 1435 | info.si_code = why; |
| 1458 | switch (why) { | 1436 | switch (why) { |
| @@ -1491,10 +1469,10 @@ static inline int may_ptrace_stop(void) | |||
| 1491 | * is a deadlock situation, and pointless because our tracer | 1469 | * is a deadlock situation, and pointless because our tracer |
| 1492 | * is dead so don't allow us to stop. | 1470 | * is dead so don't allow us to stop. |
| 1493 | * If SIGKILL was already sent before the caller unlocked | 1471 | * If SIGKILL was already sent before the caller unlocked |
| 1494 | * ->siglock we must see ->core_waiters != 0. Otherwise it | 1472 | * ->siglock we must see ->core_state != NULL. Otherwise it |
| 1495 | * is safe to enter schedule(). | 1473 | * is safe to enter schedule(). |
| 1496 | */ | 1474 | */ |
| 1497 | if (unlikely(current->mm->core_waiters) && | 1475 | if (unlikely(current->mm->core_state) && |
| 1498 | unlikely(current->mm == current->parent->mm)) | 1476 | unlikely(current->mm == current->parent->mm)) |
| 1499 | return 0; | 1477 | return 0; |
| 1500 | 1478 | ||
| @@ -1507,9 +1485,8 @@ static inline int may_ptrace_stop(void) | |||
| 1507 | */ | 1485 | */ |
| 1508 | static int sigkill_pending(struct task_struct *tsk) | 1486 | static int sigkill_pending(struct task_struct *tsk) |
| 1509 | { | 1487 | { |
| 1510 | return ((sigismember(&tsk->pending.signal, SIGKILL) || | 1488 | return sigismember(&tsk->pending.signal, SIGKILL) || |
| 1511 | sigismember(&tsk->signal->shared_pending.signal, SIGKILL)) && | 1489 | sigismember(&tsk->signal->shared_pending.signal, SIGKILL); |
| 1512 | !unlikely(sigismember(&tsk->blocked, SIGKILL))); | ||
| 1513 | } | 1490 | } |
| 1514 | 1491 | ||
| 1515 | /* | 1492 | /* |
| @@ -1525,8 +1502,6 @@ static int sigkill_pending(struct task_struct *tsk) | |||
| 1525 | */ | 1502 | */ |
| 1526 | static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | 1503 | static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) |
| 1527 | { | 1504 | { |
| 1528 | int killed = 0; | ||
| 1529 | |||
| 1530 | if (arch_ptrace_stop_needed(exit_code, info)) { | 1505 | if (arch_ptrace_stop_needed(exit_code, info)) { |
| 1531 | /* | 1506 | /* |
| 1532 | * The arch code has something special to do before a | 1507 | * The arch code has something special to do before a |
| @@ -1542,7 +1517,8 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | |||
| 1542 | spin_unlock_irq(¤t->sighand->siglock); | 1517 | spin_unlock_irq(¤t->sighand->siglock); |
| 1543 | arch_ptrace_stop(exit_code, info); | 1518 | arch_ptrace_stop(exit_code, info); |
| 1544 | spin_lock_irq(¤t->sighand->siglock); | 1519 | spin_lock_irq(¤t->sighand->siglock); |
| 1545 | killed = sigkill_pending(current); | 1520 | if (sigkill_pending(current)) |
| 1521 | return; | ||
| 1546 | } | 1522 | } |
| 1547 | 1523 | ||
| 1548 | /* | 1524 | /* |
| @@ -1559,7 +1535,7 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | |||
| 1559 | __set_current_state(TASK_TRACED); | 1535 | __set_current_state(TASK_TRACED); |
| 1560 | spin_unlock_irq(¤t->sighand->siglock); | 1536 | spin_unlock_irq(¤t->sighand->siglock); |
| 1561 | read_lock(&tasklist_lock); | 1537 | read_lock(&tasklist_lock); |
| 1562 | if (!unlikely(killed) && may_ptrace_stop()) { | 1538 | if (may_ptrace_stop()) { |
| 1563 | do_notify_parent_cldstop(current, CLD_TRAPPED); | 1539 | do_notify_parent_cldstop(current, CLD_TRAPPED); |
| 1564 | read_unlock(&tasklist_lock); | 1540 | read_unlock(&tasklist_lock); |
| 1565 | schedule(); | 1541 | schedule(); |
| @@ -1658,8 +1634,7 @@ static int do_signal_stop(int signr) | |||
| 1658 | } else { | 1634 | } else { |
| 1659 | struct task_struct *t; | 1635 | struct task_struct *t; |
| 1660 | 1636 | ||
| 1661 | if (unlikely((sig->flags & (SIGNAL_STOP_DEQUEUED | SIGNAL_UNKILLABLE)) | 1637 | if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || |
| 1662 | != SIGNAL_STOP_DEQUEUED) || | ||
| 1663 | unlikely(signal_group_exit(sig))) | 1638 | unlikely(signal_group_exit(sig))) |
| 1664 | return 0; | 1639 | return 0; |
| 1665 | /* | 1640 | /* |
| @@ -1920,7 +1895,6 @@ EXPORT_SYMBOL(recalc_sigpending); | |||
| 1920 | EXPORT_SYMBOL_GPL(dequeue_signal); | 1895 | EXPORT_SYMBOL_GPL(dequeue_signal); |
| 1921 | EXPORT_SYMBOL(flush_signals); | 1896 | EXPORT_SYMBOL(flush_signals); |
| 1922 | EXPORT_SYMBOL(force_sig); | 1897 | EXPORT_SYMBOL(force_sig); |
| 1923 | EXPORT_SYMBOL(kill_proc); | ||
| 1924 | EXPORT_SYMBOL(ptrace_notify); | 1898 | EXPORT_SYMBOL(ptrace_notify); |
| 1925 | EXPORT_SYMBOL(send_sig); | 1899 | EXPORT_SYMBOL(send_sig); |
| 1926 | EXPORT_SYMBOL(send_sig_info); | 1900 | EXPORT_SYMBOL(send_sig_info); |
| @@ -2196,7 +2170,7 @@ sys_rt_sigtimedwait(const sigset_t __user *uthese, | |||
| 2196 | } | 2170 | } |
| 2197 | 2171 | ||
| 2198 | asmlinkage long | 2172 | asmlinkage long |
| 2199 | sys_kill(int pid, int sig) | 2173 | sys_kill(pid_t pid, int sig) |
| 2200 | { | 2174 | { |
| 2201 | struct siginfo info; | 2175 | struct siginfo info; |
| 2202 | 2176 | ||
| @@ -2209,7 +2183,7 @@ sys_kill(int pid, int sig) | |||
| 2209 | return kill_something_info(sig, &info, pid); | 2183 | return kill_something_info(sig, &info, pid); |
| 2210 | } | 2184 | } |
| 2211 | 2185 | ||
| 2212 | static int do_tkill(int tgid, int pid, int sig) | 2186 | static int do_tkill(pid_t tgid, pid_t pid, int sig) |
| 2213 | { | 2187 | { |
| 2214 | int error; | 2188 | int error; |
| 2215 | struct siginfo info; | 2189 | struct siginfo info; |
| @@ -2255,7 +2229,7 @@ static int do_tkill(int tgid, int pid, int sig) | |||
| 2255 | * exists but it's not belonging to the target process anymore. This | 2229 | * exists but it's not belonging to the target process anymore. This |
| 2256 | * method solves the problem of threads exiting and PIDs getting reused. | 2230 | * method solves the problem of threads exiting and PIDs getting reused. |
| 2257 | */ | 2231 | */ |
| 2258 | asmlinkage long sys_tgkill(int tgid, int pid, int sig) | 2232 | asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig) |
| 2259 | { | 2233 | { |
| 2260 | /* This is only valid for single tasks */ | 2234 | /* This is only valid for single tasks */ |
| 2261 | if (pid <= 0 || tgid <= 0) | 2235 | if (pid <= 0 || tgid <= 0) |
| @@ -2268,7 +2242,7 @@ asmlinkage long sys_tgkill(int tgid, int pid, int sig) | |||
| 2268 | * Send a signal to only one task, even if it's a CLONE_THREAD task. | 2242 | * Send a signal to only one task, even if it's a CLONE_THREAD task. |
| 2269 | */ | 2243 | */ |
| 2270 | asmlinkage long | 2244 | asmlinkage long |
| 2271 | sys_tkill(int pid, int sig) | 2245 | sys_tkill(pid_t pid, int sig) |
| 2272 | { | 2246 | { |
| 2273 | /* This is only valid for single tasks */ | 2247 | /* This is only valid for single tasks */ |
| 2274 | if (pid <= 0) | 2248 | if (pid <= 0) |
| @@ -2278,7 +2252,7 @@ sys_tkill(int pid, int sig) | |||
| 2278 | } | 2252 | } |
| 2279 | 2253 | ||
| 2280 | asmlinkage long | 2254 | asmlinkage long |
| 2281 | sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo) | 2255 | sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo) |
| 2282 | { | 2256 | { |
| 2283 | siginfo_t info; | 2257 | siginfo_t info; |
| 2284 | 2258 | ||
diff --git a/kernel/sys.c b/kernel/sys.c index 14e97282eb6c..0c9d3fa1f5ff 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -1343,8 +1343,6 @@ EXPORT_SYMBOL(in_egroup_p); | |||
| 1343 | 1343 | ||
| 1344 | DECLARE_RWSEM(uts_sem); | 1344 | DECLARE_RWSEM(uts_sem); |
| 1345 | 1345 | ||
| 1346 | EXPORT_SYMBOL(uts_sem); | ||
| 1347 | |||
| 1348 | asmlinkage long sys_newuname(struct new_utsname __user * name) | 1346 | asmlinkage long sys_newuname(struct new_utsname __user * name) |
| 1349 | { | 1347 | { |
| 1350 | int errno = 0; | 1348 | int errno = 0; |
| @@ -1795,7 +1793,7 @@ int orderly_poweroff(bool force) | |||
| 1795 | goto out; | 1793 | goto out; |
| 1796 | } | 1794 | } |
| 1797 | 1795 | ||
| 1798 | info = call_usermodehelper_setup(argv[0], argv, envp); | 1796 | info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC); |
| 1799 | if (info == NULL) { | 1797 | if (info == NULL) { |
| 1800 | argv_free(argv); | 1798 | argv_free(argv); |
| 1801 | goto out; | 1799 | goto out; |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index bd66ac5406f3..08d6e1bb99ac 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -57,6 +57,7 @@ cond_syscall(compat_sys_set_robust_list); | |||
| 57 | cond_syscall(sys_get_robust_list); | 57 | cond_syscall(sys_get_robust_list); |
| 58 | cond_syscall(compat_sys_get_robust_list); | 58 | cond_syscall(compat_sys_get_robust_list); |
| 59 | cond_syscall(sys_epoll_create); | 59 | cond_syscall(sys_epoll_create); |
| 60 | cond_syscall(sys_epoll_create1); | ||
| 60 | cond_syscall(sys_epoll_ctl); | 61 | cond_syscall(sys_epoll_ctl); |
| 61 | cond_syscall(sys_epoll_wait); | 62 | cond_syscall(sys_epoll_wait); |
| 62 | cond_syscall(sys_epoll_pwait); | 63 | cond_syscall(sys_epoll_pwait); |
| @@ -159,6 +160,7 @@ cond_syscall(sys_ioprio_get); | |||
| 159 | cond_syscall(sys_signalfd); | 160 | cond_syscall(sys_signalfd); |
| 160 | cond_syscall(sys_signalfd4); | 161 | cond_syscall(sys_signalfd4); |
| 161 | cond_syscall(compat_sys_signalfd); | 162 | cond_syscall(compat_sys_signalfd); |
| 163 | cond_syscall(compat_sys_signalfd4); | ||
| 162 | cond_syscall(sys_timerfd_create); | 164 | cond_syscall(sys_timerfd_create); |
| 163 | cond_syscall(sys_timerfd_settime); | 165 | cond_syscall(sys_timerfd_settime); |
| 164 | cond_syscall(sys_timerfd_gettime); | 166 | cond_syscall(sys_timerfd_gettime); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 1a8299d1fe59..35a50db9b6ce 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -624,7 +624,7 @@ static struct ctl_table kern_table[] = { | |||
| 624 | { | 624 | { |
| 625 | .ctl_name = KERN_PRINTK_RATELIMIT, | 625 | .ctl_name = KERN_PRINTK_RATELIMIT, |
| 626 | .procname = "printk_ratelimit", | 626 | .procname = "printk_ratelimit", |
| 627 | .data = &printk_ratelimit_jiffies, | 627 | .data = &printk_ratelimit_state.interval, |
| 628 | .maxlen = sizeof(int), | 628 | .maxlen = sizeof(int), |
| 629 | .mode = 0644, | 629 | .mode = 0644, |
| 630 | .proc_handler = &proc_dointvec_jiffies, | 630 | .proc_handler = &proc_dointvec_jiffies, |
| @@ -633,7 +633,7 @@ static struct ctl_table kern_table[] = { | |||
| 633 | { | 633 | { |
| 634 | .ctl_name = KERN_PRINTK_RATELIMIT_BURST, | 634 | .ctl_name = KERN_PRINTK_RATELIMIT_BURST, |
| 635 | .procname = "printk_ratelimit_burst", | 635 | .procname = "printk_ratelimit_burst", |
| 636 | .data = &printk_ratelimit_burst, | 636 | .data = &printk_ratelimit_state.burst, |
| 637 | .maxlen = sizeof(int), | 637 | .maxlen = sizeof(int), |
| 638 | .mode = 0644, | 638 | .mode = 0644, |
| 639 | .proc_handler = &proc_dointvec, | 639 | .proc_handler = &proc_dointvec, |
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index c09350d564f2..c35da23ab8fb 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c | |||
| @@ -1532,6 +1532,8 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table) | |||
| 1532 | sysctl_check_leaf(namespaces, table, &fail); | 1532 | sysctl_check_leaf(namespaces, table, &fail); |
| 1533 | } | 1533 | } |
| 1534 | sysctl_check_bin_path(table, &fail); | 1534 | sysctl_check_bin_path(table, &fail); |
| 1535 | if (table->mode > 0777) | ||
| 1536 | set_fail(&fail, table, "bogus .mode"); | ||
| 1535 | if (fail) { | 1537 | if (fail) { |
| 1536 | set_fail(&fail, table, NULL); | 1538 | set_fail(&fail, table, NULL); |
| 1537 | error = -EINVAL; | 1539 | error = -EINVAL; |
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 06b17547f4e7..bd6be76303cf 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | */ | 35 | */ |
| 36 | #define TASKSTATS_CPUMASK_MAXLEN (100+6*NR_CPUS) | 36 | #define TASKSTATS_CPUMASK_MAXLEN (100+6*NR_CPUS) |
| 37 | 37 | ||
| 38 | static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 }; | 38 | static DEFINE_PER_CPU(__u32, taskstats_seqnum); |
| 39 | static int family_registered; | 39 | static int family_registered; |
| 40 | struct kmem_cache *taskstats_cache; | 40 | struct kmem_cache *taskstats_cache; |
| 41 | 41 | ||
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index 63528086337c..ce2d723c10e1 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c | |||
| @@ -161,7 +161,7 @@ static void timer_notify(struct pt_regs *regs, int cpu) | |||
| 161 | __trace_special(tr, data, 2, regs->ip, 0); | 161 | __trace_special(tr, data, 2, regs->ip, 0); |
| 162 | 162 | ||
| 163 | while (i < sample_max_depth) { | 163 | while (i < sample_max_depth) { |
| 164 | frame.next_fp = 0; | 164 | frame.next_fp = NULL; |
| 165 | frame.return_address = 0; | 165 | frame.return_address = 0; |
| 166 | if (!copy_stack_frame(fp, &frame)) | 166 | if (!copy_stack_frame(fp, &frame)) |
| 167 | break; | 167 | break; |
diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 4ab1b584961b..3da47ccdc5e5 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c | |||
| @@ -28,14 +28,14 @@ | |||
| 28 | void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) | 28 | void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) |
| 29 | { | 29 | { |
| 30 | struct timespec uptime, ts; | 30 | struct timespec uptime, ts; |
| 31 | s64 ac_etime; | 31 | u64 ac_etime; |
| 32 | 32 | ||
| 33 | BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN); | 33 | BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN); |
| 34 | 34 | ||
| 35 | /* calculate task elapsed time in timespec */ | 35 | /* calculate task elapsed time in timespec */ |
| 36 | do_posix_clock_monotonic_gettime(&uptime); | 36 | do_posix_clock_monotonic_gettime(&uptime); |
| 37 | ts = timespec_sub(uptime, tsk->start_time); | 37 | ts = timespec_sub(uptime, tsk->start_time); |
| 38 | /* rebase elapsed time to usec */ | 38 | /* rebase elapsed time to usec (should never be negative) */ |
| 39 | ac_etime = timespec_to_ns(&ts); | 39 | ac_etime = timespec_to_ns(&ts); |
| 40 | do_div(ac_etime, NSEC_PER_USEC); | 40 | do_div(ac_etime, NSEC_PER_USEC); |
| 41 | stats->ac_etime = ac_etime; | 41 | stats->ac_etime = ac_etime; |
| @@ -84,9 +84,9 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p) | |||
| 84 | { | 84 | { |
| 85 | struct mm_struct *mm; | 85 | struct mm_struct *mm; |
| 86 | 86 | ||
| 87 | /* convert pages-jiffies to Mbyte-usec */ | 87 | /* convert pages-usec to Mbyte-usec */ |
| 88 | stats->coremem = jiffies_to_usecs(p->acct_rss_mem1) * PAGE_SIZE / MB; | 88 | stats->coremem = p->acct_rss_mem1 * PAGE_SIZE / MB; |
| 89 | stats->virtmem = jiffies_to_usecs(p->acct_vm_mem1) * PAGE_SIZE / MB; | 89 | stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE / MB; |
| 90 | mm = get_task_mm(p); | 90 | mm = get_task_mm(p); |
| 91 | if (mm) { | 91 | if (mm) { |
| 92 | /* adjust to KB unit */ | 92 | /* adjust to KB unit */ |
| @@ -118,12 +118,19 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p) | |||
| 118 | void acct_update_integrals(struct task_struct *tsk) | 118 | void acct_update_integrals(struct task_struct *tsk) |
| 119 | { | 119 | { |
| 120 | if (likely(tsk->mm)) { | 120 | if (likely(tsk->mm)) { |
| 121 | long delta = cputime_to_jiffies( | 121 | cputime_t time, dtime; |
| 122 | cputime_sub(tsk->stime, tsk->acct_stimexpd)); | 122 | struct timeval value; |
| 123 | u64 delta; | ||
| 124 | |||
| 125 | time = tsk->stime + tsk->utime; | ||
| 126 | dtime = cputime_sub(time, tsk->acct_timexpd); | ||
| 127 | jiffies_to_timeval(cputime_to_jiffies(dtime), &value); | ||
| 128 | delta = value.tv_sec; | ||
| 129 | delta = delta * USEC_PER_SEC + value.tv_usec; | ||
| 123 | 130 | ||
| 124 | if (delta == 0) | 131 | if (delta == 0) |
| 125 | return; | 132 | return; |
| 126 | tsk->acct_stimexpd = tsk->stime; | 133 | tsk->acct_timexpd = time; |
| 127 | tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm); | 134 | tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm); |
| 128 | tsk->acct_vm_mem1 += delta * tsk->mm->total_vm; | 135 | tsk->acct_vm_mem1 += delta * tsk->mm->total_vm; |
| 129 | } | 136 | } |
| @@ -135,7 +142,7 @@ void acct_update_integrals(struct task_struct *tsk) | |||
| 135 | */ | 142 | */ |
| 136 | void acct_clear_integrals(struct task_struct *tsk) | 143 | void acct_clear_integrals(struct task_struct *tsk) |
| 137 | { | 144 | { |
| 138 | tsk->acct_stimexpd = 0; | 145 | tsk->acct_timexpd = 0; |
| 139 | tsk->acct_rss_mem1 = 0; | 146 | tsk->acct_rss_mem1 = 0; |
| 140 | tsk->acct_vm_mem1 = 0; | 147 | tsk->acct_vm_mem1 = 0; |
| 141 | } | 148 | } |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 6fd158b21026..ec7e4f62aaff 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -125,7 +125,7 @@ struct cpu_workqueue_struct *get_wq_data(struct work_struct *work) | |||
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static void insert_work(struct cpu_workqueue_struct *cwq, | 127 | static void insert_work(struct cpu_workqueue_struct *cwq, |
| 128 | struct work_struct *work, int tail) | 128 | struct work_struct *work, struct list_head *head) |
| 129 | { | 129 | { |
| 130 | set_wq_data(work, cwq); | 130 | set_wq_data(work, cwq); |
| 131 | /* | 131 | /* |
| @@ -133,10 +133,7 @@ static void insert_work(struct cpu_workqueue_struct *cwq, | |||
| 133 | * result of list_add() below, see try_to_grab_pending(). | 133 | * result of list_add() below, see try_to_grab_pending(). |
| 134 | */ | 134 | */ |
| 135 | smp_wmb(); | 135 | smp_wmb(); |
| 136 | if (tail) | 136 | list_add_tail(&work->entry, head); |
| 137 | list_add_tail(&work->entry, &cwq->worklist); | ||
| 138 | else | ||
| 139 | list_add(&work->entry, &cwq->worklist); | ||
| 140 | wake_up(&cwq->more_work); | 137 | wake_up(&cwq->more_work); |
| 141 | } | 138 | } |
| 142 | 139 | ||
| @@ -146,7 +143,7 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, | |||
| 146 | unsigned long flags; | 143 | unsigned long flags; |
| 147 | 144 | ||
| 148 | spin_lock_irqsave(&cwq->lock, flags); | 145 | spin_lock_irqsave(&cwq->lock, flags); |
| 149 | insert_work(cwq, work, 1); | 146 | insert_work(cwq, work, &cwq->worklist); |
| 150 | spin_unlock_irqrestore(&cwq->lock, flags); | 147 | spin_unlock_irqrestore(&cwq->lock, flags); |
| 151 | } | 148 | } |
| 152 | 149 | ||
| @@ -162,14 +159,11 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, | |||
| 162 | */ | 159 | */ |
| 163 | int queue_work(struct workqueue_struct *wq, struct work_struct *work) | 160 | int queue_work(struct workqueue_struct *wq, struct work_struct *work) |
| 164 | { | 161 | { |
| 165 | int ret = 0; | 162 | int ret; |
| 163 | |||
| 164 | ret = queue_work_on(get_cpu(), wq, work); | ||
| 165 | put_cpu(); | ||
| 166 | 166 | ||
| 167 | if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) { | ||
| 168 | BUG_ON(!list_empty(&work->entry)); | ||
| 169 | __queue_work(wq_per_cpu(wq, get_cpu()), work); | ||
| 170 | put_cpu(); | ||
| 171 | ret = 1; | ||
| 172 | } | ||
| 173 | return ret; | 167 | return ret; |
| 174 | } | 168 | } |
| 175 | EXPORT_SYMBOL_GPL(queue_work); | 169 | EXPORT_SYMBOL_GPL(queue_work); |
| @@ -361,14 +355,14 @@ static void wq_barrier_func(struct work_struct *work) | |||
| 361 | } | 355 | } |
| 362 | 356 | ||
| 363 | static void insert_wq_barrier(struct cpu_workqueue_struct *cwq, | 357 | static void insert_wq_barrier(struct cpu_workqueue_struct *cwq, |
| 364 | struct wq_barrier *barr, int tail) | 358 | struct wq_barrier *barr, struct list_head *head) |
| 365 | { | 359 | { |
| 366 | INIT_WORK(&barr->work, wq_barrier_func); | 360 | INIT_WORK(&barr->work, wq_barrier_func); |
| 367 | __set_bit(WORK_STRUCT_PENDING, work_data_bits(&barr->work)); | 361 | __set_bit(WORK_STRUCT_PENDING, work_data_bits(&barr->work)); |
| 368 | 362 | ||
| 369 | init_completion(&barr->done); | 363 | init_completion(&barr->done); |
| 370 | 364 | ||
| 371 | insert_work(cwq, &barr->work, tail); | 365 | insert_work(cwq, &barr->work, head); |
| 372 | } | 366 | } |
| 373 | 367 | ||
| 374 | static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) | 368 | static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) |
| @@ -388,7 +382,7 @@ static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) | |||
| 388 | active = 0; | 382 | active = 0; |
| 389 | spin_lock_irq(&cwq->lock); | 383 | spin_lock_irq(&cwq->lock); |
| 390 | if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) { | 384 | if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) { |
| 391 | insert_wq_barrier(cwq, &barr, 1); | 385 | insert_wq_barrier(cwq, &barr, &cwq->worklist); |
| 392 | active = 1; | 386 | active = 1; |
| 393 | } | 387 | } |
| 394 | spin_unlock_irq(&cwq->lock); | 388 | spin_unlock_irq(&cwq->lock); |
| @@ -426,6 +420,57 @@ void flush_workqueue(struct workqueue_struct *wq) | |||
| 426 | } | 420 | } |
| 427 | EXPORT_SYMBOL_GPL(flush_workqueue); | 421 | EXPORT_SYMBOL_GPL(flush_workqueue); |
| 428 | 422 | ||
| 423 | /** | ||
| 424 | * flush_work - block until a work_struct's callback has terminated | ||
| 425 | * @work: the work which is to be flushed | ||
| 426 | * | ||
| 427 | * Returns false if @work has already terminated. | ||
| 428 | * | ||
| 429 | * It is expected that, prior to calling flush_work(), the caller has | ||
| 430 | * arranged for the work to not be requeued, otherwise it doesn't make | ||
| 431 | * sense to use this function. | ||
| 432 | */ | ||
| 433 | int flush_work(struct work_struct *work) | ||
| 434 | { | ||
| 435 | struct cpu_workqueue_struct *cwq; | ||
| 436 | struct list_head *prev; | ||
| 437 | struct wq_barrier barr; | ||
| 438 | |||
| 439 | might_sleep(); | ||
| 440 | cwq = get_wq_data(work); | ||
| 441 | if (!cwq) | ||
| 442 | return 0; | ||
| 443 | |||
| 444 | lock_acquire(&cwq->wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_); | ||
| 445 | lock_release(&cwq->wq->lockdep_map, 1, _THIS_IP_); | ||
| 446 | |||
| 447 | prev = NULL; | ||
| 448 | spin_lock_irq(&cwq->lock); | ||
| 449 | if (!list_empty(&work->entry)) { | ||
| 450 | /* | ||
| 451 | * See the comment near try_to_grab_pending()->smp_rmb(). | ||
| 452 | * If it was re-queued under us we are not going to wait. | ||
| 453 | */ | ||
| 454 | smp_rmb(); | ||
| 455 | if (unlikely(cwq != get_wq_data(work))) | ||
| 456 | goto out; | ||
| 457 | prev = &work->entry; | ||
| 458 | } else { | ||
| 459 | if (cwq->current_work != work) | ||
| 460 | goto out; | ||
| 461 | prev = &cwq->worklist; | ||
| 462 | } | ||
| 463 | insert_wq_barrier(cwq, &barr, prev->next); | ||
| 464 | out: | ||
| 465 | spin_unlock_irq(&cwq->lock); | ||
| 466 | if (!prev) | ||
| 467 | return 0; | ||
| 468 | |||
| 469 | wait_for_completion(&barr.done); | ||
| 470 | return 1; | ||
| 471 | } | ||
| 472 | EXPORT_SYMBOL_GPL(flush_work); | ||
| 473 | |||
| 429 | /* | 474 | /* |
| 430 | * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit, | 475 | * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit, |
| 431 | * so this work can't be re-armed in any way. | 476 | * so this work can't be re-armed in any way. |
| @@ -473,7 +518,7 @@ static void wait_on_cpu_work(struct cpu_workqueue_struct *cwq, | |||
| 473 | 518 | ||
| 474 | spin_lock_irq(&cwq->lock); | 519 | spin_lock_irq(&cwq->lock); |
| 475 | if (unlikely(cwq->current_work == work)) { | 520 | if (unlikely(cwq->current_work == work)) { |
| 476 | insert_wq_barrier(cwq, &barr, 0); | 521 | insert_wq_barrier(cwq, &barr, cwq->worklist.next); |
| 477 | running = 1; | 522 | running = 1; |
| 478 | } | 523 | } |
| 479 | spin_unlock_irq(&cwq->lock); | 524 | spin_unlock_irq(&cwq->lock); |
| @@ -644,10 +689,10 @@ int schedule_on_each_cpu(work_func_t func) | |||
| 644 | struct work_struct *work = per_cpu_ptr(works, cpu); | 689 | struct work_struct *work = per_cpu_ptr(works, cpu); |
| 645 | 690 | ||
| 646 | INIT_WORK(work, func); | 691 | INIT_WORK(work, func); |
| 647 | set_bit(WORK_STRUCT_PENDING, work_data_bits(work)); | 692 | schedule_work_on(cpu, work); |
| 648 | __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), work); | ||
| 649 | } | 693 | } |
| 650 | flush_workqueue(keventd_wq); | 694 | for_each_online_cpu(cpu) |
| 695 | flush_work(per_cpu_ptr(works, cpu)); | ||
| 651 | put_online_cpus(); | 696 | put_online_cpus(); |
| 652 | free_percpu(works); | 697 | free_percpu(works); |
| 653 | return 0; | 698 | return 0; |
| @@ -784,7 +829,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name, | |||
| 784 | err = create_workqueue_thread(cwq, singlethread_cpu); | 829 | err = create_workqueue_thread(cwq, singlethread_cpu); |
| 785 | start_workqueue_thread(cwq, -1); | 830 | start_workqueue_thread(cwq, -1); |
| 786 | } else { | 831 | } else { |
| 787 | get_online_cpus(); | 832 | cpu_maps_update_begin(); |
| 788 | spin_lock(&workqueue_lock); | 833 | spin_lock(&workqueue_lock); |
| 789 | list_add(&wq->list, &workqueues); | 834 | list_add(&wq->list, &workqueues); |
| 790 | spin_unlock(&workqueue_lock); | 835 | spin_unlock(&workqueue_lock); |
| @@ -796,7 +841,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name, | |||
| 796 | err = create_workqueue_thread(cwq, cpu); | 841 | err = create_workqueue_thread(cwq, cpu); |
| 797 | start_workqueue_thread(cwq, cpu); | 842 | start_workqueue_thread(cwq, cpu); |
| 798 | } | 843 | } |
| 799 | put_online_cpus(); | 844 | cpu_maps_update_done(); |
| 800 | } | 845 | } |
| 801 | 846 | ||
| 802 | if (err) { | 847 | if (err) { |
| @@ -810,8 +855,8 @@ EXPORT_SYMBOL_GPL(__create_workqueue_key); | |||
| 810 | static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq) | 855 | static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq) |
| 811 | { | 856 | { |
| 812 | /* | 857 | /* |
| 813 | * Our caller is either destroy_workqueue() or CPU_DEAD, | 858 | * Our caller is either destroy_workqueue() or CPU_POST_DEAD, |
| 814 | * get_online_cpus() protects cwq->thread. | 859 | * cpu_add_remove_lock protects cwq->thread. |
| 815 | */ | 860 | */ |
| 816 | if (cwq->thread == NULL) | 861 | if (cwq->thread == NULL) |
| 817 | return; | 862 | return; |
| @@ -821,7 +866,7 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq) | |||
| 821 | 866 | ||
| 822 | flush_cpu_workqueue(cwq); | 867 | flush_cpu_workqueue(cwq); |
| 823 | /* | 868 | /* |
| 824 | * If the caller is CPU_DEAD and cwq->worklist was not empty, | 869 | * If the caller is CPU_POST_DEAD and cwq->worklist was not empty, |
| 825 | * a concurrent flush_workqueue() can insert a barrier after us. | 870 | * a concurrent flush_workqueue() can insert a barrier after us. |
| 826 | * However, in that case run_workqueue() won't return and check | 871 | * However, in that case run_workqueue() won't return and check |
| 827 | * kthread_should_stop() until it flushes all work_struct's. | 872 | * kthread_should_stop() until it flushes all work_struct's. |
| @@ -845,14 +890,14 @@ void destroy_workqueue(struct workqueue_struct *wq) | |||
| 845 | const cpumask_t *cpu_map = wq_cpu_map(wq); | 890 | const cpumask_t *cpu_map = wq_cpu_map(wq); |
| 846 | int cpu; | 891 | int cpu; |
| 847 | 892 | ||
| 848 | get_online_cpus(); | 893 | cpu_maps_update_begin(); |
| 849 | spin_lock(&workqueue_lock); | 894 | spin_lock(&workqueue_lock); |
| 850 | list_del(&wq->list); | 895 | list_del(&wq->list); |
| 851 | spin_unlock(&workqueue_lock); | 896 | spin_unlock(&workqueue_lock); |
| 852 | 897 | ||
| 853 | for_each_cpu_mask_nr(cpu, *cpu_map) | 898 | for_each_cpu_mask_nr(cpu, *cpu_map) |
| 854 | cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu)); | 899 | cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu)); |
| 855 | put_online_cpus(); | 900 | cpu_maps_update_done(); |
| 856 | 901 | ||
| 857 | free_percpu(wq->cpu_wq); | 902 | free_percpu(wq->cpu_wq); |
| 858 | kfree(wq); | 903 | kfree(wq); |
| @@ -866,6 +911,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 866 | unsigned int cpu = (unsigned long)hcpu; | 911 | unsigned int cpu = (unsigned long)hcpu; |
| 867 | struct cpu_workqueue_struct *cwq; | 912 | struct cpu_workqueue_struct *cwq; |
| 868 | struct workqueue_struct *wq; | 913 | struct workqueue_struct *wq; |
| 914 | int ret = NOTIFY_OK; | ||
| 869 | 915 | ||
| 870 | action &= ~CPU_TASKS_FROZEN; | 916 | action &= ~CPU_TASKS_FROZEN; |
| 871 | 917 | ||
| @@ -873,7 +919,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 873 | case CPU_UP_PREPARE: | 919 | case CPU_UP_PREPARE: |
| 874 | cpu_set(cpu, cpu_populated_map); | 920 | cpu_set(cpu, cpu_populated_map); |
| 875 | } | 921 | } |
| 876 | 922 | undo: | |
| 877 | list_for_each_entry(wq, &workqueues, list) { | 923 | list_for_each_entry(wq, &workqueues, list) { |
| 878 | cwq = per_cpu_ptr(wq->cpu_wq, cpu); | 924 | cwq = per_cpu_ptr(wq->cpu_wq, cpu); |
| 879 | 925 | ||
| @@ -883,7 +929,9 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 883 | break; | 929 | break; |
| 884 | printk(KERN_ERR "workqueue [%s] for %i failed\n", | 930 | printk(KERN_ERR "workqueue [%s] for %i failed\n", |
| 885 | wq->name, cpu); | 931 | wq->name, cpu); |
| 886 | return NOTIFY_BAD; | 932 | action = CPU_UP_CANCELED; |
| 933 | ret = NOTIFY_BAD; | ||
| 934 | goto undo; | ||
| 887 | 935 | ||
| 888 | case CPU_ONLINE: | 936 | case CPU_ONLINE: |
| 889 | start_workqueue_thread(cwq, cpu); | 937 | start_workqueue_thread(cwq, cpu); |
| @@ -891,7 +939,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 891 | 939 | ||
| 892 | case CPU_UP_CANCELED: | 940 | case CPU_UP_CANCELED: |
| 893 | start_workqueue_thread(cwq, -1); | 941 | start_workqueue_thread(cwq, -1); |
| 894 | case CPU_DEAD: | 942 | case CPU_POST_DEAD: |
| 895 | cleanup_workqueue_thread(cwq); | 943 | cleanup_workqueue_thread(cwq); |
| 896 | break; | 944 | break; |
| 897 | } | 945 | } |
| @@ -899,11 +947,11 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
| 899 | 947 | ||
| 900 | switch (action) { | 948 | switch (action) { |
| 901 | case CPU_UP_CANCELED: | 949 | case CPU_UP_CANCELED: |
| 902 | case CPU_DEAD: | 950 | case CPU_POST_DEAD: |
| 903 | cpu_clear(cpu, cpu_populated_map); | 951 | cpu_clear(cpu, cpu_populated_map); |
| 904 | } | 952 | } |
| 905 | 953 | ||
| 906 | return NOTIFY_OK; | 954 | return ret; |
| 907 | } | 955 | } |
| 908 | 956 | ||
| 909 | void __init init_workqueues(void) | 957 | void __init init_workqueues(void) |
diff --git a/lib/cmdline.c b/lib/cmdline.c index f596c08d213a..5ba8a942a478 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c | |||
| @@ -116,7 +116,7 @@ char *get_options(const char *str, int nints, int *ints) | |||
| 116 | /** | 116 | /** |
| 117 | * memparse - parse a string with mem suffixes into a number | 117 | * memparse - parse a string with mem suffixes into a number |
| 118 | * @ptr: Where parse begins | 118 | * @ptr: Where parse begins |
| 119 | * @retptr: (output) Pointer to next char after parse completes | 119 | * @retptr: (output) Optional pointer to next char after parse completes |
| 120 | * | 120 | * |
| 121 | * Parses a string into a number. The number stored at @ptr is | 121 | * Parses a string into a number. The number stored at @ptr is |
| 122 | * potentially suffixed with %K (for kilobytes, or 1024 bytes), | 122 | * potentially suffixed with %K (for kilobytes, or 1024 bytes), |
| @@ -126,11 +126,13 @@ char *get_options(const char *str, int nints, int *ints) | |||
| 126 | * megabyte, or one gigabyte, respectively. | 126 | * megabyte, or one gigabyte, respectively. |
| 127 | */ | 127 | */ |
| 128 | 128 | ||
| 129 | unsigned long long memparse (char *ptr, char **retptr) | 129 | unsigned long long memparse(char *ptr, char **retptr) |
| 130 | { | 130 | { |
| 131 | unsigned long long ret = simple_strtoull (ptr, retptr, 0); | 131 | char *endptr; /* local pointer to end of parsed string */ |
| 132 | 132 | ||
| 133 | switch (**retptr) { | 133 | unsigned long long ret = simple_strtoull(ptr, &endptr, 0); |
| 134 | |||
| 135 | switch (*endptr) { | ||
| 134 | case 'G': | 136 | case 'G': |
| 135 | case 'g': | 137 | case 'g': |
| 136 | ret <<= 10; | 138 | ret <<= 10; |
| @@ -140,10 +142,14 @@ unsigned long long memparse (char *ptr, char **retptr) | |||
| 140 | case 'K': | 142 | case 'K': |
| 141 | case 'k': | 143 | case 'k': |
| 142 | ret <<= 10; | 144 | ret <<= 10; |
| 143 | (*retptr)++; | 145 | endptr++; |
| 144 | default: | 146 | default: |
| 145 | break; | 147 | break; |
| 146 | } | 148 | } |
| 149 | |||
| 150 | if (retptr) | ||
| 151 | *retptr = endptr; | ||
| 152 | |||
| 147 | return ret; | 153 | return ret; |
| 148 | } | 154 | } |
| 149 | 155 | ||
| @@ -6,6 +6,8 @@ | |||
| 6 | * Modified by George Anzinger to reuse immediately and to use | 6 | * Modified by George Anzinger to reuse immediately and to use |
| 7 | * find bit instructions. Also removed _irq on spinlocks. | 7 | * find bit instructions. Also removed _irq on spinlocks. |
| 8 | * | 8 | * |
| 9 | * Modified by Nadia Derbey to make it RCU safe. | ||
| 10 | * | ||
| 9 | * Small id to pointer translation service. | 11 | * Small id to pointer translation service. |
| 10 | * | 12 | * |
| 11 | * It uses a radix tree like structure as a sparse array indexed | 13 | * It uses a radix tree like structure as a sparse array indexed |
| @@ -35,7 +37,7 @@ | |||
| 35 | 37 | ||
| 36 | static struct kmem_cache *idr_layer_cache; | 38 | static struct kmem_cache *idr_layer_cache; |
| 37 | 39 | ||
| 38 | static struct idr_layer *alloc_layer(struct idr *idp) | 40 | static struct idr_layer *get_from_free_list(struct idr *idp) |
| 39 | { | 41 | { |
| 40 | struct idr_layer *p; | 42 | struct idr_layer *p; |
| 41 | unsigned long flags; | 43 | unsigned long flags; |
| @@ -50,15 +52,28 @@ static struct idr_layer *alloc_layer(struct idr *idp) | |||
| 50 | return(p); | 52 | return(p); |
| 51 | } | 53 | } |
| 52 | 54 | ||
| 55 | static void idr_layer_rcu_free(struct rcu_head *head) | ||
| 56 | { | ||
| 57 | struct idr_layer *layer; | ||
| 58 | |||
| 59 | layer = container_of(head, struct idr_layer, rcu_head); | ||
| 60 | kmem_cache_free(idr_layer_cache, layer); | ||
| 61 | } | ||
| 62 | |||
| 63 | static inline void free_layer(struct idr_layer *p) | ||
| 64 | { | ||
| 65 | call_rcu(&p->rcu_head, idr_layer_rcu_free); | ||
| 66 | } | ||
| 67 | |||
| 53 | /* only called when idp->lock is held */ | 68 | /* only called when idp->lock is held */ |
| 54 | static void __free_layer(struct idr *idp, struct idr_layer *p) | 69 | static void __move_to_free_list(struct idr *idp, struct idr_layer *p) |
| 55 | { | 70 | { |
| 56 | p->ary[0] = idp->id_free; | 71 | p->ary[0] = idp->id_free; |
| 57 | idp->id_free = p; | 72 | idp->id_free = p; |
| 58 | idp->id_free_cnt++; | 73 | idp->id_free_cnt++; |
| 59 | } | 74 | } |
| 60 | 75 | ||
| 61 | static void free_layer(struct idr *idp, struct idr_layer *p) | 76 | static void move_to_free_list(struct idr *idp, struct idr_layer *p) |
| 62 | { | 77 | { |
| 63 | unsigned long flags; | 78 | unsigned long flags; |
| 64 | 79 | ||
| @@ -66,7 +81,7 @@ static void free_layer(struct idr *idp, struct idr_layer *p) | |||
| 66 | * Depends on the return element being zeroed. | 81 | * Depends on the return element being zeroed. |
| 67 | */ | 82 | */ |
| 68 | spin_lock_irqsave(&idp->lock, flags); | 83 | spin_lock_irqsave(&idp->lock, flags); |
| 69 | __free_layer(idp, p); | 84 | __move_to_free_list(idp, p); |
| 70 | spin_unlock_irqrestore(&idp->lock, flags); | 85 | spin_unlock_irqrestore(&idp->lock, flags); |
| 71 | } | 86 | } |
| 72 | 87 | ||
| @@ -96,7 +111,7 @@ static void idr_mark_full(struct idr_layer **pa, int id) | |||
| 96 | * @gfp_mask: memory allocation flags | 111 | * @gfp_mask: memory allocation flags |
| 97 | * | 112 | * |
| 98 | * This function should be called prior to locking and calling the | 113 | * This function should be called prior to locking and calling the |
| 99 | * following function. It preallocates enough memory to satisfy | 114 | * idr_get_new* functions. It preallocates enough memory to satisfy |
| 100 | * the worst possible allocation. | 115 | * the worst possible allocation. |
| 101 | * | 116 | * |
| 102 | * If the system is REALLY out of memory this function returns 0, | 117 | * If the system is REALLY out of memory this function returns 0, |
| @@ -109,7 +124,7 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask) | |||
| 109 | new = kmem_cache_alloc(idr_layer_cache, gfp_mask); | 124 | new = kmem_cache_alloc(idr_layer_cache, gfp_mask); |
| 110 | if (new == NULL) | 125 | if (new == NULL) |
| 111 | return (0); | 126 | return (0); |
| 112 | free_layer(idp, new); | 127 | move_to_free_list(idp, new); |
| 113 | } | 128 | } |
| 114 | return 1; | 129 | return 1; |
| 115 | } | 130 | } |
| @@ -143,7 +158,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) | |||
| 143 | /* if already at the top layer, we need to grow */ | 158 | /* if already at the top layer, we need to grow */ |
| 144 | if (!(p = pa[l])) { | 159 | if (!(p = pa[l])) { |
| 145 | *starting_id = id; | 160 | *starting_id = id; |
| 146 | return -2; | 161 | return IDR_NEED_TO_GROW; |
| 147 | } | 162 | } |
| 148 | 163 | ||
| 149 | /* If we need to go up one layer, continue the | 164 | /* If we need to go up one layer, continue the |
| @@ -160,16 +175,17 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) | |||
| 160 | id = ((id >> sh) ^ n ^ m) << sh; | 175 | id = ((id >> sh) ^ n ^ m) << sh; |
| 161 | } | 176 | } |
| 162 | if ((id >= MAX_ID_BIT) || (id < 0)) | 177 | if ((id >= MAX_ID_BIT) || (id < 0)) |
| 163 | return -3; | 178 | return IDR_NOMORE_SPACE; |
| 164 | if (l == 0) | 179 | if (l == 0) |
| 165 | break; | 180 | break; |
| 166 | /* | 181 | /* |
| 167 | * Create the layer below if it is missing. | 182 | * Create the layer below if it is missing. |
| 168 | */ | 183 | */ |
| 169 | if (!p->ary[m]) { | 184 | if (!p->ary[m]) { |
| 170 | if (!(new = alloc_layer(idp))) | 185 | new = get_from_free_list(idp); |
| 186 | if (!new) | ||
| 171 | return -1; | 187 | return -1; |
| 172 | p->ary[m] = new; | 188 | rcu_assign_pointer(p->ary[m], new); |
| 173 | p->count++; | 189 | p->count++; |
| 174 | } | 190 | } |
| 175 | pa[l--] = p; | 191 | pa[l--] = p; |
| @@ -192,7 +208,7 @@ build_up: | |||
| 192 | p = idp->top; | 208 | p = idp->top; |
| 193 | layers = idp->layers; | 209 | layers = idp->layers; |
| 194 | if (unlikely(!p)) { | 210 | if (unlikely(!p)) { |
| 195 | if (!(p = alloc_layer(idp))) | 211 | if (!(p = get_from_free_list(idp))) |
| 196 | return -1; | 212 | return -1; |
| 197 | layers = 1; | 213 | layers = 1; |
| 198 | } | 214 | } |
| @@ -204,7 +220,7 @@ build_up: | |||
| 204 | layers++; | 220 | layers++; |
| 205 | if (!p->count) | 221 | if (!p->count) |
| 206 | continue; | 222 | continue; |
| 207 | if (!(new = alloc_layer(idp))) { | 223 | if (!(new = get_from_free_list(idp))) { |
| 208 | /* | 224 | /* |
| 209 | * The allocation failed. If we built part of | 225 | * The allocation failed. If we built part of |
| 210 | * the structure tear it down. | 226 | * the structure tear it down. |
| @@ -214,7 +230,7 @@ build_up: | |||
| 214 | p = p->ary[0]; | 230 | p = p->ary[0]; |
| 215 | new->ary[0] = NULL; | 231 | new->ary[0] = NULL; |
| 216 | new->bitmap = new->count = 0; | 232 | new->bitmap = new->count = 0; |
| 217 | __free_layer(idp, new); | 233 | __move_to_free_list(idp, new); |
| 218 | } | 234 | } |
| 219 | spin_unlock_irqrestore(&idp->lock, flags); | 235 | spin_unlock_irqrestore(&idp->lock, flags); |
| 220 | return -1; | 236 | return -1; |
| @@ -225,10 +241,10 @@ build_up: | |||
| 225 | __set_bit(0, &new->bitmap); | 241 | __set_bit(0, &new->bitmap); |
| 226 | p = new; | 242 | p = new; |
| 227 | } | 243 | } |
| 228 | idp->top = p; | 244 | rcu_assign_pointer(idp->top, p); |
| 229 | idp->layers = layers; | 245 | idp->layers = layers; |
| 230 | v = sub_alloc(idp, &id, pa); | 246 | v = sub_alloc(idp, &id, pa); |
| 231 | if (v == -2) | 247 | if (v == IDR_NEED_TO_GROW) |
| 232 | goto build_up; | 248 | goto build_up; |
| 233 | return(v); | 249 | return(v); |
| 234 | } | 250 | } |
| @@ -244,7 +260,8 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) | |||
| 244 | * Successfully found an empty slot. Install the user | 260 | * Successfully found an empty slot. Install the user |
| 245 | * pointer and mark the slot full. | 261 | * pointer and mark the slot full. |
| 246 | */ | 262 | */ |
| 247 | pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr; | 263 | rcu_assign_pointer(pa[0]->ary[id & IDR_MASK], |
| 264 | (struct idr_layer *)ptr); | ||
| 248 | pa[0]->count++; | 265 | pa[0]->count++; |
| 249 | idr_mark_full(pa, id); | 266 | idr_mark_full(pa, id); |
| 250 | } | 267 | } |
| @@ -277,12 +294,8 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id) | |||
| 277 | * This is a cheap hack until the IDR code can be fixed to | 294 | * This is a cheap hack until the IDR code can be fixed to |
| 278 | * return proper error values. | 295 | * return proper error values. |
| 279 | */ | 296 | */ |
| 280 | if (rv < 0) { | 297 | if (rv < 0) |
| 281 | if (rv == -1) | 298 | return _idr_rc_to_errno(rv); |
| 282 | return -EAGAIN; | ||
| 283 | else /* Will be -3 */ | ||
| 284 | return -ENOSPC; | ||
| 285 | } | ||
| 286 | *id = rv; | 299 | *id = rv; |
| 287 | return 0; | 300 | return 0; |
| 288 | } | 301 | } |
| @@ -312,12 +325,8 @@ int idr_get_new(struct idr *idp, void *ptr, int *id) | |||
| 312 | * This is a cheap hack until the IDR code can be fixed to | 325 | * This is a cheap hack until the IDR code can be fixed to |
| 313 | * return proper error values. | 326 | * return proper error values. |
| 314 | */ | 327 | */ |
| 315 | if (rv < 0) { | 328 | if (rv < 0) |
| 316 | if (rv == -1) | 329 | return _idr_rc_to_errno(rv); |
| 317 | return -EAGAIN; | ||
| 318 | else /* Will be -3 */ | ||
| 319 | return -ENOSPC; | ||
| 320 | } | ||
| 321 | *id = rv; | 330 | *id = rv; |
| 322 | return 0; | 331 | return 0; |
| 323 | } | 332 | } |
| @@ -325,7 +334,8 @@ EXPORT_SYMBOL(idr_get_new); | |||
| 325 | 334 | ||
| 326 | static void idr_remove_warning(int id) | 335 | static void idr_remove_warning(int id) |
| 327 | { | 336 | { |
| 328 | printk("idr_remove called for id=%d which is not allocated.\n", id); | 337 | printk(KERN_WARNING |
| 338 | "idr_remove called for id=%d which is not allocated.\n", id); | ||
| 329 | dump_stack(); | 339 | dump_stack(); |
| 330 | } | 340 | } |
| 331 | 341 | ||
| @@ -334,6 +344,7 @@ static void sub_remove(struct idr *idp, int shift, int id) | |||
| 334 | struct idr_layer *p = idp->top; | 344 | struct idr_layer *p = idp->top; |
| 335 | struct idr_layer **pa[MAX_LEVEL]; | 345 | struct idr_layer **pa[MAX_LEVEL]; |
| 336 | struct idr_layer ***paa = &pa[0]; | 346 | struct idr_layer ***paa = &pa[0]; |
| 347 | struct idr_layer *to_free; | ||
| 337 | int n; | 348 | int n; |
| 338 | 349 | ||
| 339 | *paa = NULL; | 350 | *paa = NULL; |
| @@ -349,13 +360,18 @@ static void sub_remove(struct idr *idp, int shift, int id) | |||
| 349 | n = id & IDR_MASK; | 360 | n = id & IDR_MASK; |
| 350 | if (likely(p != NULL && test_bit(n, &p->bitmap))){ | 361 | if (likely(p != NULL && test_bit(n, &p->bitmap))){ |
| 351 | __clear_bit(n, &p->bitmap); | 362 | __clear_bit(n, &p->bitmap); |
| 352 | p->ary[n] = NULL; | 363 | rcu_assign_pointer(p->ary[n], NULL); |
| 364 | to_free = NULL; | ||
| 353 | while(*paa && ! --((**paa)->count)){ | 365 | while(*paa && ! --((**paa)->count)){ |
| 354 | free_layer(idp, **paa); | 366 | if (to_free) |
| 367 | free_layer(to_free); | ||
| 368 | to_free = **paa; | ||
| 355 | **paa-- = NULL; | 369 | **paa-- = NULL; |
| 356 | } | 370 | } |
| 357 | if (!*paa) | 371 | if (!*paa) |
| 358 | idp->layers = 0; | 372 | idp->layers = 0; |
| 373 | if (to_free) | ||
| 374 | free_layer(to_free); | ||
| 359 | } else | 375 | } else |
| 360 | idr_remove_warning(id); | 376 | idr_remove_warning(id); |
| 361 | } | 377 | } |
| @@ -368,22 +384,34 @@ static void sub_remove(struct idr *idp, int shift, int id) | |||
| 368 | void idr_remove(struct idr *idp, int id) | 384 | void idr_remove(struct idr *idp, int id) |
| 369 | { | 385 | { |
| 370 | struct idr_layer *p; | 386 | struct idr_layer *p; |
| 387 | struct idr_layer *to_free; | ||
| 371 | 388 | ||
| 372 | /* Mask off upper bits we don't use for the search. */ | 389 | /* Mask off upper bits we don't use for the search. */ |
| 373 | id &= MAX_ID_MASK; | 390 | id &= MAX_ID_MASK; |
| 374 | 391 | ||
| 375 | sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); | 392 | sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); |
| 376 | if (idp->top && idp->top->count == 1 && (idp->layers > 1) && | 393 | if (idp->top && idp->top->count == 1 && (idp->layers > 1) && |
| 377 | idp->top->ary[0]) { // We can drop a layer | 394 | idp->top->ary[0]) { |
| 378 | 395 | /* | |
| 396 | * Single child at leftmost slot: we can shrink the tree. | ||
| 397 | * This level is not needed anymore since when layers are | ||
| 398 | * inserted, they are inserted at the top of the existing | ||
| 399 | * tree. | ||
| 400 | */ | ||
| 401 | to_free = idp->top; | ||
| 379 | p = idp->top->ary[0]; | 402 | p = idp->top->ary[0]; |
| 380 | idp->top->bitmap = idp->top->count = 0; | 403 | rcu_assign_pointer(idp->top, p); |
| 381 | free_layer(idp, idp->top); | ||
| 382 | idp->top = p; | ||
| 383 | --idp->layers; | 404 | --idp->layers; |
| 405 | to_free->bitmap = to_free->count = 0; | ||
| 406 | free_layer(to_free); | ||
| 384 | } | 407 | } |
| 385 | while (idp->id_free_cnt >= IDR_FREE_MAX) { | 408 | while (idp->id_free_cnt >= IDR_FREE_MAX) { |
| 386 | p = alloc_layer(idp); | 409 | p = get_from_free_list(idp); |
| 410 | /* | ||
| 411 | * Note: we don't call the rcu callback here, since the only | ||
| 412 | * layers that fall into the freelist are those that have been | ||
| 413 | * preallocated. | ||
| 414 | */ | ||
| 387 | kmem_cache_free(idr_layer_cache, p); | 415 | kmem_cache_free(idr_layer_cache, p); |
| 388 | } | 416 | } |
| 389 | return; | 417 | return; |
| @@ -424,15 +452,13 @@ void idr_remove_all(struct idr *idp) | |||
| 424 | 452 | ||
| 425 | id += 1 << n; | 453 | id += 1 << n; |
| 426 | while (n < fls(id)) { | 454 | while (n < fls(id)) { |
| 427 | if (p) { | 455 | if (p) |
| 428 | memset(p, 0, sizeof *p); | 456 | free_layer(p); |
| 429 | free_layer(idp, p); | ||
| 430 | } | ||
| 431 | n += IDR_BITS; | 457 | n += IDR_BITS; |
| 432 | p = *--paa; | 458 | p = *--paa; |
| 433 | } | 459 | } |
| 434 | } | 460 | } |
| 435 | idp->top = NULL; | 461 | rcu_assign_pointer(idp->top, NULL); |
| 436 | idp->layers = 0; | 462 | idp->layers = 0; |
| 437 | } | 463 | } |
| 438 | EXPORT_SYMBOL(idr_remove_all); | 464 | EXPORT_SYMBOL(idr_remove_all); |
| @@ -444,7 +470,7 @@ EXPORT_SYMBOL(idr_remove_all); | |||
| 444 | void idr_destroy(struct idr *idp) | 470 | void idr_destroy(struct idr *idp) |
| 445 | { | 471 | { |
| 446 | while (idp->id_free_cnt) { | 472 | while (idp->id_free_cnt) { |
| 447 | struct idr_layer *p = alloc_layer(idp); | 473 | struct idr_layer *p = get_from_free_list(idp); |
| 448 | kmem_cache_free(idr_layer_cache, p); | 474 | kmem_cache_free(idr_layer_cache, p); |
| 449 | } | 475 | } |
| 450 | } | 476 | } |
| @@ -459,7 +485,8 @@ EXPORT_SYMBOL(idr_destroy); | |||
| 459 | * return indicates that @id is not valid or you passed %NULL in | 485 | * return indicates that @id is not valid or you passed %NULL in |
| 460 | * idr_get_new(). | 486 | * idr_get_new(). |
| 461 | * | 487 | * |
| 462 | * The caller must serialize idr_find() vs idr_get_new() and idr_remove(). | 488 | * This function can be called under rcu_read_lock(), given that the leaf |
| 489 | * pointers lifetimes are correctly managed. | ||
| 463 | */ | 490 | */ |
| 464 | void *idr_find(struct idr *idp, int id) | 491 | void *idr_find(struct idr *idp, int id) |
| 465 | { | 492 | { |
| @@ -467,7 +494,7 @@ void *idr_find(struct idr *idp, int id) | |||
| 467 | struct idr_layer *p; | 494 | struct idr_layer *p; |
| 468 | 495 | ||
| 469 | n = idp->layers * IDR_BITS; | 496 | n = idp->layers * IDR_BITS; |
| 470 | p = idp->top; | 497 | p = rcu_dereference(idp->top); |
| 471 | 498 | ||
| 472 | /* Mask off upper bits we don't use for the search. */ | 499 | /* Mask off upper bits we don't use for the search. */ |
| 473 | id &= MAX_ID_MASK; | 500 | id &= MAX_ID_MASK; |
| @@ -477,7 +504,7 @@ void *idr_find(struct idr *idp, int id) | |||
| 477 | 504 | ||
| 478 | while (n > 0 && p) { | 505 | while (n > 0 && p) { |
| 479 | n -= IDR_BITS; | 506 | n -= IDR_BITS; |
| 480 | p = p->ary[(id >> n) & IDR_MASK]; | 507 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); |
| 481 | } | 508 | } |
| 482 | return((void *)p); | 509 | return((void *)p); |
| 483 | } | 510 | } |
| @@ -510,7 +537,7 @@ int idr_for_each(struct idr *idp, | |||
| 510 | struct idr_layer **paa = &pa[0]; | 537 | struct idr_layer **paa = &pa[0]; |
| 511 | 538 | ||
| 512 | n = idp->layers * IDR_BITS; | 539 | n = idp->layers * IDR_BITS; |
| 513 | p = idp->top; | 540 | p = rcu_dereference(idp->top); |
| 514 | max = 1 << n; | 541 | max = 1 << n; |
| 515 | 542 | ||
| 516 | id = 0; | 543 | id = 0; |
| @@ -518,7 +545,7 @@ int idr_for_each(struct idr *idp, | |||
| 518 | while (n > 0 && p) { | 545 | while (n > 0 && p) { |
| 519 | n -= IDR_BITS; | 546 | n -= IDR_BITS; |
| 520 | *paa++ = p; | 547 | *paa++ = p; |
| 521 | p = p->ary[(id >> n) & IDR_MASK]; | 548 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); |
| 522 | } | 549 | } |
| 523 | 550 | ||
| 524 | if (p) { | 551 | if (p) { |
| @@ -548,7 +575,7 @@ EXPORT_SYMBOL(idr_for_each); | |||
| 548 | * A -ENOENT return indicates that @id was not found. | 575 | * A -ENOENT return indicates that @id was not found. |
| 549 | * A -EINVAL return indicates that @id was not within valid constraints. | 576 | * A -EINVAL return indicates that @id was not within valid constraints. |
| 550 | * | 577 | * |
| 551 | * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove(). | 578 | * The caller must serialize with writers. |
| 552 | */ | 579 | */ |
| 553 | void *idr_replace(struct idr *idp, void *ptr, int id) | 580 | void *idr_replace(struct idr *idp, void *ptr, int id) |
| 554 | { | 581 | { |
| @@ -574,7 +601,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id) | |||
| 574 | return ERR_PTR(-ENOENT); | 601 | return ERR_PTR(-ENOENT); |
| 575 | 602 | ||
| 576 | old_p = p->ary[n]; | 603 | old_p = p->ary[n]; |
| 577 | p->ary[n] = ptr; | 604 | rcu_assign_pointer(p->ary[n], ptr); |
| 578 | 605 | ||
| 579 | return old_p; | 606 | return old_p; |
| 580 | } | 607 | } |
| @@ -694,12 +721,8 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id) | |||
| 694 | restart: | 721 | restart: |
| 695 | /* get vacant slot */ | 722 | /* get vacant slot */ |
| 696 | t = idr_get_empty_slot(&ida->idr, idr_id, pa); | 723 | t = idr_get_empty_slot(&ida->idr, idr_id, pa); |
| 697 | if (t < 0) { | 724 | if (t < 0) |
| 698 | if (t == -1) | 725 | return _idr_rc_to_errno(t); |
| 699 | return -EAGAIN; | ||
| 700 | else /* will be -3 */ | ||
| 701 | return -ENOSPC; | ||
| 702 | } | ||
| 703 | 726 | ||
| 704 | if (t * IDA_BITMAP_BITS >= MAX_ID_BIT) | 727 | if (t * IDA_BITMAP_BITS >= MAX_ID_BIT) |
| 705 | return -ENOSPC; | 728 | return -ENOSPC; |
| @@ -720,7 +743,8 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id) | |||
| 720 | return -EAGAIN; | 743 | return -EAGAIN; |
| 721 | 744 | ||
| 722 | memset(bitmap, 0, sizeof(struct ida_bitmap)); | 745 | memset(bitmap, 0, sizeof(struct ida_bitmap)); |
| 723 | pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap; | 746 | rcu_assign_pointer(pa[0]->ary[idr_id & IDR_MASK], |
| 747 | (void *)bitmap); | ||
| 724 | pa[0]->count++; | 748 | pa[0]->count++; |
| 725 | } | 749 | } |
| 726 | 750 | ||
| @@ -749,7 +773,7 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id) | |||
| 749 | * allocation. | 773 | * allocation. |
| 750 | */ | 774 | */ |
| 751 | if (ida->idr.id_free_cnt || ida->free_bitmap) { | 775 | if (ida->idr.id_free_cnt || ida->free_bitmap) { |
| 752 | struct idr_layer *p = alloc_layer(&ida->idr); | 776 | struct idr_layer *p = get_from_free_list(&ida->idr); |
| 753 | if (p) | 777 | if (p) |
| 754 | kmem_cache_free(idr_layer_cache, p); | 778 | kmem_cache_free(idr_layer_cache, p); |
| 755 | } | 779 | } |
diff --git a/lib/inflate.c b/lib/inflate.c index 9762294be062..1a8e8a978128 100644 --- a/lib/inflate.c +++ b/lib/inflate.c | |||
| @@ -230,6 +230,45 @@ STATIC const ush mask_bits[] = { | |||
| 230 | #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}} | 230 | #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}} |
| 231 | #define DUMPBITS(n) {b>>=(n);k-=(n);} | 231 | #define DUMPBITS(n) {b>>=(n);k-=(n);} |
| 232 | 232 | ||
| 233 | #ifndef NO_INFLATE_MALLOC | ||
| 234 | /* A trivial malloc implementation, adapted from | ||
| 235 | * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 | ||
| 236 | */ | ||
| 237 | |||
| 238 | static unsigned long malloc_ptr; | ||
| 239 | static int malloc_count; | ||
| 240 | |||
| 241 | static void *malloc(int size) | ||
| 242 | { | ||
| 243 | void *p; | ||
| 244 | |||
| 245 | if (size < 0) | ||
| 246 | error("Malloc error"); | ||
| 247 | if (!malloc_ptr) | ||
| 248 | malloc_ptr = free_mem_ptr; | ||
| 249 | |||
| 250 | malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */ | ||
| 251 | |||
| 252 | p = (void *)malloc_ptr; | ||
| 253 | malloc_ptr += size; | ||
| 254 | |||
| 255 | if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) | ||
| 256 | error("Out of memory"); | ||
| 257 | |||
| 258 | malloc_count++; | ||
| 259 | return p; | ||
| 260 | } | ||
| 261 | |||
| 262 | static void free(void *where) | ||
| 263 | { | ||
| 264 | malloc_count--; | ||
| 265 | if (!malloc_count) | ||
| 266 | malloc_ptr = free_mem_ptr; | ||
| 267 | } | ||
| 268 | #else | ||
| 269 | #define malloc(a) kmalloc(a, GFP_KERNEL) | ||
| 270 | #define free(a) kfree(a) | ||
| 271 | #endif | ||
| 233 | 272 | ||
| 234 | /* | 273 | /* |
| 235 | Huffman code decoding is performed using a multi-level table lookup. | 274 | Huffman code decoding is performed using a multi-level table lookup. |
| @@ -1045,7 +1084,6 @@ STATIC int INIT inflate(void) | |||
| 1045 | int e; /* last block flag */ | 1084 | int e; /* last block flag */ |
| 1046 | int r; /* result code */ | 1085 | int r; /* result code */ |
| 1047 | unsigned h; /* maximum struct huft's malloc'ed */ | 1086 | unsigned h; /* maximum struct huft's malloc'ed */ |
| 1048 | void *ptr; | ||
| 1049 | 1087 | ||
| 1050 | /* initialize window, bit buffer */ | 1088 | /* initialize window, bit buffer */ |
| 1051 | wp = 0; | 1089 | wp = 0; |
| @@ -1057,12 +1095,12 @@ STATIC int INIT inflate(void) | |||
| 1057 | h = 0; | 1095 | h = 0; |
| 1058 | do { | 1096 | do { |
| 1059 | hufts = 0; | 1097 | hufts = 0; |
| 1060 | gzip_mark(&ptr); | 1098 | #ifdef ARCH_HAS_DECOMP_WDOG |
| 1061 | if ((r = inflate_block(&e)) != 0) { | 1099 | arch_decomp_wdog(); |
| 1062 | gzip_release(&ptr); | 1100 | #endif |
| 1063 | return r; | 1101 | r = inflate_block(&e); |
| 1064 | } | 1102 | if (r) |
| 1065 | gzip_release(&ptr); | 1103 | return r; |
| 1066 | if (hufts > h) | 1104 | if (hufts > h) |
| 1067 | h = hufts; | 1105 | h = hufts; |
| 1068 | } while (!e); | 1106 | } while (!e); |
diff --git a/lib/kobject.c b/lib/kobject.c index 744401571ed7..bd732ffebc85 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
| @@ -164,9 +164,8 @@ static int kobject_add_internal(struct kobject *kobj) | |||
| 164 | return -ENOENT; | 164 | return -ENOENT; |
| 165 | 165 | ||
| 166 | if (!kobj->name || !kobj->name[0]) { | 166 | if (!kobj->name || !kobj->name[0]) { |
| 167 | pr_debug("kobject: (%p): attempted to be registered with empty " | 167 | WARN(1, "kobject: (%p): attempted to be registered with empty " |
| 168 | "name!\n", kobj); | 168 | "name!\n", kobj); |
| 169 | WARN_ON(1); | ||
| 170 | return -EINVAL; | 169 | return -EINVAL; |
| 171 | } | 170 | } |
| 172 | 171 | ||
| @@ -583,12 +582,10 @@ static void kobject_release(struct kref *kref) | |||
| 583 | void kobject_put(struct kobject *kobj) | 582 | void kobject_put(struct kobject *kobj) |
| 584 | { | 583 | { |
| 585 | if (kobj) { | 584 | if (kobj) { |
| 586 | if (!kobj->state_initialized) { | 585 | if (!kobj->state_initialized) |
| 587 | printk(KERN_WARNING "kobject: '%s' (%p): is not " | 586 | WARN(1, KERN_WARNING "kobject: '%s' (%p): is not " |
| 588 | "initialized, yet kobject_put() is being " | 587 | "initialized, yet kobject_put() is being " |
| 589 | "called.\n", kobject_name(kobj), kobj); | 588 | "called.\n", kobject_name(kobj), kobj); |
| 590 | WARN_ON(1); | ||
| 591 | } | ||
| 592 | kref_put(&kobj->kref, kobject_release); | 589 | kref_put(&kobj->kref, kobject_release); |
| 593 | } | 590 | } |
| 594 | } | 591 | } |
diff --git a/lib/list_debug.c b/lib/list_debug.c index 4350ba9655bd..1a39f4e3ae1f 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c | |||
| @@ -20,18 +20,14 @@ void __list_add(struct list_head *new, | |||
| 20 | struct list_head *prev, | 20 | struct list_head *prev, |
| 21 | struct list_head *next) | 21 | struct list_head *next) |
| 22 | { | 22 | { |
| 23 | if (unlikely(next->prev != prev)) { | 23 | WARN(next->prev != prev, |
| 24 | printk(KERN_ERR "list_add corruption. next->prev should be " | 24 | "list_add corruption. next->prev should be " |
| 25 | "prev (%p), but was %p. (next=%p).\n", | 25 | "prev (%p), but was %p. (next=%p).\n", |
| 26 | prev, next->prev, next); | 26 | prev, next->prev, next); |
| 27 | BUG(); | 27 | WARN(prev->next != next, |
| 28 | } | 28 | "list_add corruption. prev->next should be " |
| 29 | if (unlikely(prev->next != next)) { | 29 | "next (%p), but was %p. (prev=%p).\n", |
| 30 | printk(KERN_ERR "list_add corruption. prev->next should be " | 30 | next, prev->next, prev); |
| 31 | "next (%p), but was %p. (prev=%p).\n", | ||
| 32 | next, prev->next, prev); | ||
| 33 | BUG(); | ||
| 34 | } | ||
| 35 | next->prev = new; | 31 | next->prev = new; |
| 36 | new->next = next; | 32 | new->next = next; |
| 37 | new->prev = prev; | 33 | new->prev = prev; |
| @@ -40,20 +36,6 @@ void __list_add(struct list_head *new, | |||
| 40 | EXPORT_SYMBOL(__list_add); | 36 | EXPORT_SYMBOL(__list_add); |
| 41 | 37 | ||
| 42 | /** | 38 | /** |
| 43 | * list_add - add a new entry | ||
| 44 | * @new: new entry to be added | ||
| 45 | * @head: list head to add it after | ||
| 46 | * | ||
| 47 | * Insert a new entry after the specified head. | ||
| 48 | * This is good for implementing stacks. | ||
| 49 | */ | ||
| 50 | void list_add(struct list_head *new, struct list_head *head) | ||
| 51 | { | ||
| 52 | __list_add(new, head, head->next); | ||
| 53 | } | ||
| 54 | EXPORT_SYMBOL(list_add); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * list_del - deletes entry from list. | 39 | * list_del - deletes entry from list. |
| 58 | * @entry: the element to delete from the list. | 40 | * @entry: the element to delete from the list. |
| 59 | * Note: list_empty on entry does not return true after this, the entry is | 41 | * Note: list_empty on entry does not return true after this, the entry is |
| @@ -61,16 +43,12 @@ EXPORT_SYMBOL(list_add); | |||
| 61 | */ | 43 | */ |
| 62 | void list_del(struct list_head *entry) | 44 | void list_del(struct list_head *entry) |
| 63 | { | 45 | { |
| 64 | if (unlikely(entry->prev->next != entry)) { | 46 | WARN(entry->prev->next != entry, |
| 65 | printk(KERN_ERR "list_del corruption. prev->next should be %p, " | 47 | "list_del corruption. prev->next should be %p, " |
| 66 | "but was %p\n", entry, entry->prev->next); | 48 | "but was %p\n", entry, entry->prev->next); |
| 67 | BUG(); | 49 | WARN(entry->next->prev != entry, |
| 68 | } | 50 | "list_del corruption. next->prev should be %p, " |
| 69 | if (unlikely(entry->next->prev != entry)) { | 51 | "but was %p\n", entry, entry->next->prev); |
| 70 | printk(KERN_ERR "list_del corruption. next->prev should be %p, " | ||
| 71 | "but was %p\n", entry, entry->next->prev); | ||
| 72 | BUG(); | ||
| 73 | } | ||
| 74 | __list_del(entry->prev, entry->next); | 52 | __list_del(entry->prev, entry->next); |
| 75 | entry->next = LIST_POISON1; | 53 | entry->next = LIST_POISON1; |
| 76 | entry->prev = LIST_POISON2; | 54 | entry->prev = LIST_POISON2; |
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c index 77f0f9b775a9..5dc6b29c1575 100644 --- a/lib/lzo/lzo1x_decompress.c +++ b/lib/lzo/lzo1x_decompress.c | |||
| @@ -138,8 +138,7 @@ match: | |||
| 138 | t += 31 + *ip++; | 138 | t += 31 + *ip++; |
| 139 | } | 139 | } |
| 140 | m_pos = op - 1; | 140 | m_pos = op - 1; |
| 141 | m_pos -= le16_to_cpu(get_unaligned( | 141 | m_pos -= get_unaligned_le16(ip) >> 2; |
| 142 | (const unsigned short *)ip)) >> 2; | ||
| 143 | ip += 2; | 142 | ip += 2; |
| 144 | } else if (t >= 16) { | 143 | } else if (t >= 16) { |
| 145 | m_pos = op; | 144 | m_pos = op; |
| @@ -157,8 +156,7 @@ match: | |||
| 157 | } | 156 | } |
| 158 | t += 7 + *ip++; | 157 | t += 7 + *ip++; |
| 159 | } | 158 | } |
| 160 | m_pos -= le16_to_cpu(get_unaligned( | 159 | m_pos -= get_unaligned_le16(ip) >> 2; |
| 161 | (const unsigned short *)ip)) >> 2; | ||
| 162 | ip += 2; | 160 | ip += 2; |
| 163 | if (m_pos == op) | 161 | if (m_pos == op) |
| 164 | goto eof_found; | 162 | goto eof_found; |
diff --git a/lib/ratelimit.c b/lib/ratelimit.c index 485e3040dcd4..35136671b215 100644 --- a/lib/ratelimit.c +++ b/lib/ratelimit.c | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | * | 3 | * |
| 4 | * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> | 4 | * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com> |
| 5 | * | 5 | * |
| 6 | * 2008-05-01 rewrite the function and use a ratelimit_state data struct as | ||
| 7 | * parameter. Now every user can use their own standalone ratelimit_state. | ||
| 8 | * | ||
| 6 | * This file is released under the GPLv2. | 9 | * This file is released under the GPLv2. |
| 7 | * | 10 | * |
| 8 | */ | 11 | */ |
| @@ -11,41 +14,43 @@ | |||
| 11 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
| 12 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 13 | 16 | ||
| 17 | static DEFINE_SPINLOCK(ratelimit_lock); | ||
| 18 | static unsigned long flags; | ||
| 19 | |||
| 14 | /* | 20 | /* |
| 15 | * __ratelimit - rate limiting | 21 | * __ratelimit - rate limiting |
| 16 | * @ratelimit_jiffies: minimum time in jiffies between two callbacks | 22 | * @rs: ratelimit_state data |
| 17 | * @ratelimit_burst: number of callbacks we do before ratelimiting | ||
| 18 | * | 23 | * |
| 19 | * This enforces a rate limit: not more than @ratelimit_burst callbacks | 24 | * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks |
| 20 | * in every ratelimit_jiffies | 25 | * in every @rs->ratelimit_jiffies |
| 21 | */ | 26 | */ |
| 22 | int __ratelimit(int ratelimit_jiffies, int ratelimit_burst) | 27 | int __ratelimit(struct ratelimit_state *rs) |
| 23 | { | 28 | { |
| 24 | static DEFINE_SPINLOCK(ratelimit_lock); | 29 | if (!rs->interval) |
| 25 | static unsigned toks = 10 * 5 * HZ; | 30 | return 1; |
| 26 | static unsigned long last_msg; | ||
| 27 | static int missed; | ||
| 28 | unsigned long flags; | ||
| 29 | unsigned long now = jiffies; | ||
| 30 | 31 | ||
| 31 | spin_lock_irqsave(&ratelimit_lock, flags); | 32 | spin_lock_irqsave(&ratelimit_lock, flags); |
| 32 | toks += now - last_msg; | 33 | if (!rs->begin) |
| 33 | last_msg = now; | 34 | rs->begin = jiffies; |
| 34 | if (toks > (ratelimit_burst * ratelimit_jiffies)) | ||
| 35 | toks = ratelimit_burst * ratelimit_jiffies; | ||
| 36 | if (toks >= ratelimit_jiffies) { | ||
| 37 | int lost = missed; | ||
| 38 | 35 | ||
| 39 | missed = 0; | 36 | if (time_is_before_jiffies(rs->begin + rs->interval)) { |
| 40 | toks -= ratelimit_jiffies; | 37 | if (rs->missed) |
| 41 | spin_unlock_irqrestore(&ratelimit_lock, flags); | 38 | printk(KERN_WARNING "%s: %d callbacks suppressed\n", |
| 42 | if (lost) | 39 | __func__, rs->missed); |
| 43 | printk(KERN_WARNING "%s: %d messages suppressed\n", | 40 | rs->begin = 0; |
| 44 | __func__, lost); | 41 | rs->printed = 0; |
| 45 | return 1; | 42 | rs->missed = 0; |
| 46 | } | 43 | } |
| 47 | missed++; | 44 | if (rs->burst && rs->burst > rs->printed) |
| 45 | goto print; | ||
| 46 | |||
| 47 | rs->missed++; | ||
| 48 | spin_unlock_irqrestore(&ratelimit_lock, flags); | 48 | spin_unlock_irqrestore(&ratelimit_lock, flags); |
| 49 | return 0; | 49 | return 0; |
| 50 | |||
| 51 | print: | ||
| 52 | rs->printed++; | ||
| 53 | spin_unlock_irqrestore(&ratelimit_lock, flags); | ||
| 54 | return 1; | ||
| 50 | } | 55 | } |
| 51 | EXPORT_SYMBOL(__ratelimit); | 56 | EXPORT_SYMBOL(__ratelimit); |
diff --git a/mm/filemap.c b/mm/filemap.c index 7675b91f4f63..2d3ec1ffc66e 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -115,7 +115,7 @@ void __remove_from_page_cache(struct page *page) | |||
| 115 | { | 115 | { |
| 116 | struct address_space *mapping = page->mapping; | 116 | struct address_space *mapping = page->mapping; |
| 117 | 117 | ||
| 118 | mem_cgroup_uncharge_page(page); | 118 | mem_cgroup_uncharge_cache_page(page); |
| 119 | radix_tree_delete(&mapping->page_tree, page->index); | 119 | radix_tree_delete(&mapping->page_tree, page->index); |
| 120 | page->mapping = NULL; | 120 | page->mapping = NULL; |
| 121 | mapping->nrpages--; | 121 | mapping->nrpages--; |
| @@ -474,12 +474,12 @@ int add_to_page_cache(struct page *page, struct address_space *mapping, | |||
| 474 | mapping->nrpages++; | 474 | mapping->nrpages++; |
| 475 | __inc_zone_page_state(page, NR_FILE_PAGES); | 475 | __inc_zone_page_state(page, NR_FILE_PAGES); |
| 476 | } else | 476 | } else |
| 477 | mem_cgroup_uncharge_page(page); | 477 | mem_cgroup_uncharge_cache_page(page); |
| 478 | 478 | ||
| 479 | write_unlock_irq(&mapping->tree_lock); | 479 | write_unlock_irq(&mapping->tree_lock); |
| 480 | radix_tree_preload_end(); | 480 | radix_tree_preload_end(); |
| 481 | } else | 481 | } else |
| 482 | mem_cgroup_uncharge_page(page); | 482 | mem_cgroup_uncharge_cache_page(page); |
| 483 | out: | 483 | out: |
| 484 | return error; | 484 | return error; |
| 485 | } | 485 | } |
| @@ -2563,9 +2563,8 @@ EXPORT_SYMBOL(generic_file_aio_write); | |||
| 2563 | * Otherwise return zero. | 2563 | * Otherwise return zero. |
| 2564 | * | 2564 | * |
| 2565 | * The @gfp_mask argument specifies whether I/O may be performed to release | 2565 | * The @gfp_mask argument specifies whether I/O may be performed to release |
| 2566 | * this page (__GFP_IO), and whether the call may block (__GFP_WAIT). | 2566 | * this page (__GFP_IO), and whether the call may block (__GFP_WAIT & __GFP_FS). |
| 2567 | * | 2567 | * |
| 2568 | * NOTE: @gfp_mask may go away, and this function may become non-blocking. | ||
| 2569 | */ | 2568 | */ |
| 2570 | int try_to_release_page(struct page *page, gfp_t gfp_mask) | 2569 | int try_to_release_page(struct page *page, gfp_t gfp_mask) |
| 2571 | { | 2570 | { |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 41341c414194..a8bf4ab01f86 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
| @@ -1026,6 +1026,17 @@ static void __init report_hugepages(void) | |||
| 1026 | } | 1026 | } |
| 1027 | } | 1027 | } |
| 1028 | 1028 | ||
| 1029 | static unsigned int cpuset_mems_nr(unsigned int *array) | ||
| 1030 | { | ||
| 1031 | int node; | ||
| 1032 | unsigned int nr = 0; | ||
| 1033 | |||
| 1034 | for_each_node_mask(node, cpuset_current_mems_allowed) | ||
| 1035 | nr += array[node]; | ||
| 1036 | |||
| 1037 | return nr; | ||
| 1038 | } | ||
| 1039 | |||
| 1029 | #ifdef CONFIG_SYSCTL | 1040 | #ifdef CONFIG_SYSCTL |
| 1030 | #ifdef CONFIG_HIGHMEM | 1041 | #ifdef CONFIG_HIGHMEM |
| 1031 | static void try_to_free_low(struct hstate *h, unsigned long count) | 1042 | static void try_to_free_low(struct hstate *h, unsigned long count) |
| @@ -1375,17 +1386,6 @@ static int __init hugetlb_default_setup(char *s) | |||
| 1375 | } | 1386 | } |
| 1376 | __setup("default_hugepagesz=", hugetlb_default_setup); | 1387 | __setup("default_hugepagesz=", hugetlb_default_setup); |
| 1377 | 1388 | ||
| 1378 | static unsigned int cpuset_mems_nr(unsigned int *array) | ||
| 1379 | { | ||
| 1380 | int node; | ||
| 1381 | unsigned int nr = 0; | ||
| 1382 | |||
| 1383 | for_each_node_mask(node, cpuset_current_mems_allowed) | ||
| 1384 | nr += array[node]; | ||
| 1385 | |||
| 1386 | return nr; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | int hugetlb_sysctl_handler(struct ctl_table *table, int write, | 1389 | int hugetlb_sysctl_handler(struct ctl_table *table, int write, |
| 1390 | struct file *file, void __user *buffer, | 1390 | struct file *file, void __user *buffer, |
| 1391 | size_t *length, loff_t *ppos) | 1391 | size_t *length, loff_t *ppos) |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e46451e1d9b7..fba566c51322 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -35,9 +35,9 @@ | |||
| 35 | 35 | ||
| 36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
| 37 | 37 | ||
| 38 | struct cgroup_subsys mem_cgroup_subsys; | 38 | struct cgroup_subsys mem_cgroup_subsys __read_mostly; |
| 39 | static const int MEM_CGROUP_RECLAIM_RETRIES = 5; | 39 | static struct kmem_cache *page_cgroup_cache __read_mostly; |
| 40 | static struct kmem_cache *page_cgroup_cache; | 40 | #define MEM_CGROUP_RECLAIM_RETRIES 5 |
| 41 | 41 | ||
| 42 | /* | 42 | /* |
| 43 | * Statistics for memory cgroup. | 43 | * Statistics for memory cgroup. |
| @@ -166,7 +166,6 @@ struct page_cgroup { | |||
| 166 | struct list_head lru; /* per cgroup LRU list */ | 166 | struct list_head lru; /* per cgroup LRU list */ |
| 167 | struct page *page; | 167 | struct page *page; |
| 168 | struct mem_cgroup *mem_cgroup; | 168 | struct mem_cgroup *mem_cgroup; |
| 169 | int ref_cnt; /* cached, mapped, migrating */ | ||
| 170 | int flags; | 169 | int flags; |
| 171 | }; | 170 | }; |
| 172 | #define PAGE_CGROUP_FLAG_CACHE (0x1) /* charged as cache */ | 171 | #define PAGE_CGROUP_FLAG_CACHE (0x1) /* charged as cache */ |
| @@ -185,6 +184,7 @@ static enum zone_type page_cgroup_zid(struct page_cgroup *pc) | |||
| 185 | enum charge_type { | 184 | enum charge_type { |
| 186 | MEM_CGROUP_CHARGE_TYPE_CACHE = 0, | 185 | MEM_CGROUP_CHARGE_TYPE_CACHE = 0, |
| 187 | MEM_CGROUP_CHARGE_TYPE_MAPPED, | 186 | MEM_CGROUP_CHARGE_TYPE_MAPPED, |
| 187 | MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */ | ||
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | /* | 190 | /* |
| @@ -296,7 +296,7 @@ static void __mem_cgroup_remove_list(struct mem_cgroup_per_zone *mz, | |||
| 296 | MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) -= 1; | 296 | MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) -= 1; |
| 297 | 297 | ||
| 298 | mem_cgroup_charge_statistics(pc->mem_cgroup, pc->flags, false); | 298 | mem_cgroup_charge_statistics(pc->mem_cgroup, pc->flags, false); |
| 299 | list_del_init(&pc->lru); | 299 | list_del(&pc->lru); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz, | 302 | static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz, |
| @@ -354,6 +354,9 @@ void mem_cgroup_move_lists(struct page *page, bool active) | |||
| 354 | struct mem_cgroup_per_zone *mz; | 354 | struct mem_cgroup_per_zone *mz; |
| 355 | unsigned long flags; | 355 | unsigned long flags; |
| 356 | 356 | ||
| 357 | if (mem_cgroup_subsys.disabled) | ||
| 358 | return; | ||
| 359 | |||
| 357 | /* | 360 | /* |
| 358 | * We cannot lock_page_cgroup while holding zone's lru_lock, | 361 | * We cannot lock_page_cgroup while holding zone's lru_lock, |
| 359 | * because other holders of lock_page_cgroup can be interrupted | 362 | * because other holders of lock_page_cgroup can be interrupted |
| @@ -524,7 +527,8 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, | |||
| 524 | * < 0 if the cgroup is over its limit | 527 | * < 0 if the cgroup is over its limit |
| 525 | */ | 528 | */ |
| 526 | static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, | 529 | static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, |
| 527 | gfp_t gfp_mask, enum charge_type ctype) | 530 | gfp_t gfp_mask, enum charge_type ctype, |
| 531 | struct mem_cgroup *memcg) | ||
| 528 | { | 532 | { |
| 529 | struct mem_cgroup *mem; | 533 | struct mem_cgroup *mem; |
| 530 | struct page_cgroup *pc; | 534 | struct page_cgroup *pc; |
| @@ -532,35 +536,8 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, | |||
| 532 | unsigned long nr_retries = MEM_CGROUP_RECLAIM_RETRIES; | 536 | unsigned long nr_retries = MEM_CGROUP_RECLAIM_RETRIES; |
| 533 | struct mem_cgroup_per_zone *mz; | 537 | struct mem_cgroup_per_zone *mz; |
| 534 | 538 | ||
| 535 | if (mem_cgroup_subsys.disabled) | 539 | pc = kmem_cache_alloc(page_cgroup_cache, gfp_mask); |
| 536 | return 0; | 540 | if (unlikely(pc == NULL)) |
| 537 | |||
| 538 | /* | ||
| 539 | * Should page_cgroup's go to their own slab? | ||
| 540 | * One could optimize the performance of the charging routine | ||
| 541 | * by saving a bit in the page_flags and using it as a lock | ||
| 542 | * to see if the cgroup page already has a page_cgroup associated | ||
| 543 | * with it | ||
| 544 | */ | ||
| 545 | retry: | ||
| 546 | lock_page_cgroup(page); | ||
| 547 | pc = page_get_page_cgroup(page); | ||
| 548 | /* | ||
| 549 | * The page_cgroup exists and | ||
| 550 | * the page has already been accounted. | ||
| 551 | */ | ||
| 552 | if (pc) { | ||
| 553 | VM_BUG_ON(pc->page != page); | ||
| 554 | VM_BUG_ON(pc->ref_cnt <= 0); | ||
| 555 | |||
| 556 | pc->ref_cnt++; | ||
| 557 | unlock_page_cgroup(page); | ||
| 558 | goto done; | ||
| 559 | } | ||
| 560 | unlock_page_cgroup(page); | ||
| 561 | |||
| 562 | pc = kmem_cache_zalloc(page_cgroup_cache, gfp_mask); | ||
| 563 | if (pc == NULL) | ||
| 564 | goto err; | 541 | goto err; |
| 565 | 542 | ||
| 566 | /* | 543 | /* |
| @@ -569,16 +546,18 @@ retry: | |||
| 569 | * thread group leader migrates. It's possible that mm is not | 546 | * thread group leader migrates. It's possible that mm is not |
| 570 | * set, if so charge the init_mm (happens for pagecache usage). | 547 | * set, if so charge the init_mm (happens for pagecache usage). |
| 571 | */ | 548 | */ |
| 572 | if (!mm) | 549 | if (likely(!memcg)) { |
| 573 | mm = &init_mm; | 550 | rcu_read_lock(); |
| 574 | 551 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); | |
| 575 | rcu_read_lock(); | 552 | /* |
| 576 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); | 553 | * For every charge from the cgroup, increment reference count |
| 577 | /* | 554 | */ |
| 578 | * For every charge from the cgroup, increment reference count | 555 | css_get(&mem->css); |
| 579 | */ | 556 | rcu_read_unlock(); |
| 580 | css_get(&mem->css); | 557 | } else { |
| 581 | rcu_read_unlock(); | 558 | mem = memcg; |
| 559 | css_get(&memcg->css); | ||
| 560 | } | ||
| 582 | 561 | ||
| 583 | while (res_counter_charge(&mem->res, PAGE_SIZE)) { | 562 | while (res_counter_charge(&mem->res, PAGE_SIZE)) { |
| 584 | if (!(gfp_mask & __GFP_WAIT)) | 563 | if (!(gfp_mask & __GFP_WAIT)) |
| @@ -603,25 +582,24 @@ retry: | |||
| 603 | } | 582 | } |
| 604 | } | 583 | } |
| 605 | 584 | ||
| 606 | pc->ref_cnt = 1; | ||
| 607 | pc->mem_cgroup = mem; | 585 | pc->mem_cgroup = mem; |
| 608 | pc->page = page; | 586 | pc->page = page; |
| 609 | pc->flags = PAGE_CGROUP_FLAG_ACTIVE; | 587 | /* |
| 588 | * If a page is accounted as a page cache, insert to inactive list. | ||
| 589 | * If anon, insert to active list. | ||
| 590 | */ | ||
| 610 | if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) | 591 | if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) |
| 611 | pc->flags = PAGE_CGROUP_FLAG_CACHE; | 592 | pc->flags = PAGE_CGROUP_FLAG_CACHE; |
| 593 | else | ||
| 594 | pc->flags = PAGE_CGROUP_FLAG_ACTIVE; | ||
| 612 | 595 | ||
| 613 | lock_page_cgroup(page); | 596 | lock_page_cgroup(page); |
| 614 | if (page_get_page_cgroup(page)) { | 597 | if (unlikely(page_get_page_cgroup(page))) { |
| 615 | unlock_page_cgroup(page); | 598 | unlock_page_cgroup(page); |
| 616 | /* | ||
| 617 | * Another charge has been added to this page already. | ||
| 618 | * We take lock_page_cgroup(page) again and read | ||
| 619 | * page->cgroup, increment refcnt.... just retry is OK. | ||
| 620 | */ | ||
| 621 | res_counter_uncharge(&mem->res, PAGE_SIZE); | 599 | res_counter_uncharge(&mem->res, PAGE_SIZE); |
| 622 | css_put(&mem->css); | 600 | css_put(&mem->css); |
| 623 | kmem_cache_free(page_cgroup_cache, pc); | 601 | kmem_cache_free(page_cgroup_cache, pc); |
| 624 | goto retry; | 602 | goto done; |
| 625 | } | 603 | } |
| 626 | page_assign_page_cgroup(page, pc); | 604 | page_assign_page_cgroup(page, pc); |
| 627 | 605 | ||
| @@ -642,24 +620,65 @@ err: | |||
| 642 | 620 | ||
| 643 | int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask) | 621 | int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask) |
| 644 | { | 622 | { |
| 623 | if (mem_cgroup_subsys.disabled) | ||
| 624 | return 0; | ||
| 625 | |||
| 626 | /* | ||
| 627 | * If already mapped, we don't have to account. | ||
| 628 | * If page cache, page->mapping has address_space. | ||
| 629 | * But page->mapping may have out-of-use anon_vma pointer, | ||
| 630 | * detecit it by PageAnon() check. newly-mapped-anon's page->mapping | ||
| 631 | * is NULL. | ||
| 632 | */ | ||
| 633 | if (page_mapped(page) || (page->mapping && !PageAnon(page))) | ||
| 634 | return 0; | ||
| 635 | if (unlikely(!mm)) | ||
| 636 | mm = &init_mm; | ||
| 645 | return mem_cgroup_charge_common(page, mm, gfp_mask, | 637 | return mem_cgroup_charge_common(page, mm, gfp_mask, |
| 646 | MEM_CGROUP_CHARGE_TYPE_MAPPED); | 638 | MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL); |
| 647 | } | 639 | } |
| 648 | 640 | ||
| 649 | int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, | 641 | int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, |
| 650 | gfp_t gfp_mask) | 642 | gfp_t gfp_mask) |
| 651 | { | 643 | { |
| 652 | if (!mm) | 644 | if (mem_cgroup_subsys.disabled) |
| 645 | return 0; | ||
| 646 | |||
| 647 | /* | ||
| 648 | * Corner case handling. This is called from add_to_page_cache() | ||
| 649 | * in usual. But some FS (shmem) precharges this page before calling it | ||
| 650 | * and call add_to_page_cache() with GFP_NOWAIT. | ||
| 651 | * | ||
| 652 | * For GFP_NOWAIT case, the page may be pre-charged before calling | ||
| 653 | * add_to_page_cache(). (See shmem.c) check it here and avoid to call | ||
| 654 | * charge twice. (It works but has to pay a bit larger cost.) | ||
| 655 | */ | ||
| 656 | if (!(gfp_mask & __GFP_WAIT)) { | ||
| 657 | struct page_cgroup *pc; | ||
| 658 | |||
| 659 | lock_page_cgroup(page); | ||
| 660 | pc = page_get_page_cgroup(page); | ||
| 661 | if (pc) { | ||
| 662 | VM_BUG_ON(pc->page != page); | ||
| 663 | VM_BUG_ON(!pc->mem_cgroup); | ||
| 664 | unlock_page_cgroup(page); | ||
| 665 | return 0; | ||
| 666 | } | ||
| 667 | unlock_page_cgroup(page); | ||
| 668 | } | ||
| 669 | |||
| 670 | if (unlikely(!mm)) | ||
| 653 | mm = &init_mm; | 671 | mm = &init_mm; |
| 672 | |||
| 654 | return mem_cgroup_charge_common(page, mm, gfp_mask, | 673 | return mem_cgroup_charge_common(page, mm, gfp_mask, |
| 655 | MEM_CGROUP_CHARGE_TYPE_CACHE); | 674 | MEM_CGROUP_CHARGE_TYPE_CACHE, NULL); |
| 656 | } | 675 | } |
| 657 | 676 | ||
| 658 | /* | 677 | /* |
| 659 | * Uncharging is always a welcome operation, we never complain, simply | 678 | * uncharge if !page_mapped(page) |
| 660 | * uncharge. | ||
| 661 | */ | 679 | */ |
| 662 | void mem_cgroup_uncharge_page(struct page *page) | 680 | static void |
| 681 | __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) | ||
| 663 | { | 682 | { |
| 664 | struct page_cgroup *pc; | 683 | struct page_cgroup *pc; |
| 665 | struct mem_cgroup *mem; | 684 | struct mem_cgroup *mem; |
| @@ -674,98 +693,151 @@ void mem_cgroup_uncharge_page(struct page *page) | |||
| 674 | */ | 693 | */ |
| 675 | lock_page_cgroup(page); | 694 | lock_page_cgroup(page); |
| 676 | pc = page_get_page_cgroup(page); | 695 | pc = page_get_page_cgroup(page); |
| 677 | if (!pc) | 696 | if (unlikely(!pc)) |
| 678 | goto unlock; | 697 | goto unlock; |
| 679 | 698 | ||
| 680 | VM_BUG_ON(pc->page != page); | 699 | VM_BUG_ON(pc->page != page); |
| 681 | VM_BUG_ON(pc->ref_cnt <= 0); | ||
| 682 | 700 | ||
| 683 | if (--(pc->ref_cnt) == 0) { | 701 | if ((ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED) |
| 684 | mz = page_cgroup_zoneinfo(pc); | 702 | && ((pc->flags & PAGE_CGROUP_FLAG_CACHE) |
| 685 | spin_lock_irqsave(&mz->lru_lock, flags); | 703 | || page_mapped(page))) |
| 686 | __mem_cgroup_remove_list(mz, pc); | 704 | goto unlock; |
| 687 | spin_unlock_irqrestore(&mz->lru_lock, flags); | ||
| 688 | 705 | ||
| 689 | page_assign_page_cgroup(page, NULL); | 706 | mz = page_cgroup_zoneinfo(pc); |
| 690 | unlock_page_cgroup(page); | 707 | spin_lock_irqsave(&mz->lru_lock, flags); |
| 708 | __mem_cgroup_remove_list(mz, pc); | ||
| 709 | spin_unlock_irqrestore(&mz->lru_lock, flags); | ||
| 691 | 710 | ||
| 692 | mem = pc->mem_cgroup; | 711 | page_assign_page_cgroup(page, NULL); |
| 693 | res_counter_uncharge(&mem->res, PAGE_SIZE); | 712 | unlock_page_cgroup(page); |
| 694 | css_put(&mem->css); | ||
| 695 | 713 | ||
| 696 | kmem_cache_free(page_cgroup_cache, pc); | 714 | mem = pc->mem_cgroup; |
| 697 | return; | 715 | res_counter_uncharge(&mem->res, PAGE_SIZE); |
| 698 | } | 716 | css_put(&mem->css); |
| 699 | 717 | ||
| 718 | kmem_cache_free(page_cgroup_cache, pc); | ||
| 719 | return; | ||
| 700 | unlock: | 720 | unlock: |
| 701 | unlock_page_cgroup(page); | 721 | unlock_page_cgroup(page); |
| 702 | } | 722 | } |
| 703 | 723 | ||
| 724 | void mem_cgroup_uncharge_page(struct page *page) | ||
| 725 | { | ||
| 726 | __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_MAPPED); | ||
| 727 | } | ||
| 728 | |||
| 729 | void mem_cgroup_uncharge_cache_page(struct page *page) | ||
| 730 | { | ||
| 731 | VM_BUG_ON(page_mapped(page)); | ||
| 732 | __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE); | ||
| 733 | } | ||
| 734 | |||
| 704 | /* | 735 | /* |
| 705 | * Returns non-zero if a page (under migration) has valid page_cgroup member. | 736 | * Before starting migration, account against new page. |
| 706 | * Refcnt of page_cgroup is incremented. | ||
| 707 | */ | 737 | */ |
| 708 | int mem_cgroup_prepare_migration(struct page *page) | 738 | int mem_cgroup_prepare_migration(struct page *page, struct page *newpage) |
| 709 | { | 739 | { |
| 710 | struct page_cgroup *pc; | 740 | struct page_cgroup *pc; |
| 741 | struct mem_cgroup *mem = NULL; | ||
| 742 | enum charge_type ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED; | ||
| 743 | int ret = 0; | ||
| 711 | 744 | ||
| 712 | if (mem_cgroup_subsys.disabled) | 745 | if (mem_cgroup_subsys.disabled) |
| 713 | return 0; | 746 | return 0; |
| 714 | 747 | ||
| 715 | lock_page_cgroup(page); | 748 | lock_page_cgroup(page); |
| 716 | pc = page_get_page_cgroup(page); | 749 | pc = page_get_page_cgroup(page); |
| 717 | if (pc) | 750 | if (pc) { |
| 718 | pc->ref_cnt++; | 751 | mem = pc->mem_cgroup; |
| 752 | css_get(&mem->css); | ||
| 753 | if (pc->flags & PAGE_CGROUP_FLAG_CACHE) | ||
| 754 | ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; | ||
| 755 | } | ||
| 719 | unlock_page_cgroup(page); | 756 | unlock_page_cgroup(page); |
| 720 | return pc != NULL; | 757 | if (mem) { |
| 758 | ret = mem_cgroup_charge_common(newpage, NULL, GFP_KERNEL, | ||
| 759 | ctype, mem); | ||
| 760 | css_put(&mem->css); | ||
| 761 | } | ||
| 762 | return ret; | ||
| 721 | } | 763 | } |
| 722 | 764 | ||
| 723 | void mem_cgroup_end_migration(struct page *page) | 765 | /* remove redundant charge if migration failed*/ |
| 766 | void mem_cgroup_end_migration(struct page *newpage) | ||
| 724 | { | 767 | { |
| 725 | mem_cgroup_uncharge_page(page); | 768 | /* |
| 769 | * At success, page->mapping is not NULL. | ||
| 770 | * special rollback care is necessary when | ||
| 771 | * 1. at migration failure. (newpage->mapping is cleared in this case) | ||
| 772 | * 2. the newpage was moved but not remapped again because the task | ||
| 773 | * exits and the newpage is obsolete. In this case, the new page | ||
| 774 | * may be a swapcache. So, we just call mem_cgroup_uncharge_page() | ||
| 775 | * always for avoiding mess. The page_cgroup will be removed if | ||
| 776 | * unnecessary. File cache pages is still on radix-tree. Don't | ||
| 777 | * care it. | ||
| 778 | */ | ||
| 779 | if (!newpage->mapping) | ||
| 780 | __mem_cgroup_uncharge_common(newpage, | ||
| 781 | MEM_CGROUP_CHARGE_TYPE_FORCE); | ||
| 782 | else if (PageAnon(newpage)) | ||
| 783 | mem_cgroup_uncharge_page(newpage); | ||
| 726 | } | 784 | } |
| 727 | 785 | ||
| 728 | /* | 786 | /* |
| 729 | * We know both *page* and *newpage* are now not-on-LRU and PG_locked. | 787 | * A call to try to shrink memory usage under specified resource controller. |
| 730 | * And no race with uncharge() routines because page_cgroup for *page* | 788 | * This is typically used for page reclaiming for shmem for reducing side |
| 731 | * has extra one reference by mem_cgroup_prepare_migration. | 789 | * effect of page allocation from shmem, which is used by some mem_cgroup. |
| 732 | */ | 790 | */ |
| 733 | void mem_cgroup_page_migration(struct page *page, struct page *newpage) | 791 | int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask) |
| 734 | { | 792 | { |
| 735 | struct page_cgroup *pc; | 793 | struct mem_cgroup *mem; |
| 736 | struct mem_cgroup_per_zone *mz; | 794 | int progress = 0; |
| 737 | unsigned long flags; | 795 | int retry = MEM_CGROUP_RECLAIM_RETRIES; |
| 738 | 796 | ||
| 739 | lock_page_cgroup(page); | 797 | if (mem_cgroup_subsys.disabled) |
| 740 | pc = page_get_page_cgroup(page); | 798 | return 0; |
| 741 | if (!pc) { | ||
| 742 | unlock_page_cgroup(page); | ||
| 743 | return; | ||
| 744 | } | ||
| 745 | 799 | ||
| 746 | mz = page_cgroup_zoneinfo(pc); | 800 | rcu_read_lock(); |
| 747 | spin_lock_irqsave(&mz->lru_lock, flags); | 801 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); |
| 748 | __mem_cgroup_remove_list(mz, pc); | 802 | css_get(&mem->css); |
| 749 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 803 | rcu_read_unlock(); |
| 750 | 804 | ||
| 751 | page_assign_page_cgroup(page, NULL); | 805 | do { |
| 752 | unlock_page_cgroup(page); | 806 | progress = try_to_free_mem_cgroup_pages(mem, gfp_mask); |
| 807 | } while (!progress && --retry); | ||
| 753 | 808 | ||
| 754 | pc->page = newpage; | 809 | css_put(&mem->css); |
| 755 | lock_page_cgroup(newpage); | 810 | if (!retry) |
| 756 | page_assign_page_cgroup(newpage, pc); | 811 | return -ENOMEM; |
| 812 | return 0; | ||
| 813 | } | ||
| 757 | 814 | ||
| 758 | mz = page_cgroup_zoneinfo(pc); | 815 | int mem_cgroup_resize_limit(struct mem_cgroup *memcg, unsigned long long val) |
| 759 | spin_lock_irqsave(&mz->lru_lock, flags); | 816 | { |
| 760 | __mem_cgroup_add_list(mz, pc); | 817 | |
| 761 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 818 | int retry_count = MEM_CGROUP_RECLAIM_RETRIES; |
| 819 | int progress; | ||
| 820 | int ret = 0; | ||
| 762 | 821 | ||
| 763 | unlock_page_cgroup(newpage); | 822 | while (res_counter_set_limit(&memcg->res, val)) { |
| 823 | if (signal_pending(current)) { | ||
| 824 | ret = -EINTR; | ||
| 825 | break; | ||
| 826 | } | ||
| 827 | if (!retry_count) { | ||
| 828 | ret = -EBUSY; | ||
| 829 | break; | ||
| 830 | } | ||
| 831 | progress = try_to_free_mem_cgroup_pages(memcg, GFP_KERNEL); | ||
| 832 | if (!progress) | ||
| 833 | retry_count--; | ||
| 834 | } | ||
| 835 | return ret; | ||
| 764 | } | 836 | } |
| 765 | 837 | ||
| 838 | |||
| 766 | /* | 839 | /* |
| 767 | * This routine traverse page_cgroup in given list and drop them all. | 840 | * This routine traverse page_cgroup in given list and drop them all. |
| 768 | * This routine ignores page_cgroup->ref_cnt. | ||
| 769 | * *And* this routine doesn't reclaim page itself, just removes page_cgroup. | 841 | * *And* this routine doesn't reclaim page itself, just removes page_cgroup. |
| 770 | */ | 842 | */ |
| 771 | #define FORCE_UNCHARGE_BATCH (128) | 843 | #define FORCE_UNCHARGE_BATCH (128) |
| @@ -790,12 +862,20 @@ static void mem_cgroup_force_empty_list(struct mem_cgroup *mem, | |||
| 790 | page = pc->page; | 862 | page = pc->page; |
| 791 | get_page(page); | 863 | get_page(page); |
| 792 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 864 | spin_unlock_irqrestore(&mz->lru_lock, flags); |
| 793 | mem_cgroup_uncharge_page(page); | 865 | /* |
| 794 | put_page(page); | 866 | * Check if this page is on LRU. !LRU page can be found |
| 795 | if (--count <= 0) { | 867 | * if it's under page migration. |
| 796 | count = FORCE_UNCHARGE_BATCH; | 868 | */ |
| 869 | if (PageLRU(page)) { | ||
| 870 | __mem_cgroup_uncharge_common(page, | ||
| 871 | MEM_CGROUP_CHARGE_TYPE_FORCE); | ||
| 872 | put_page(page); | ||
| 873 | if (--count <= 0) { | ||
| 874 | count = FORCE_UNCHARGE_BATCH; | ||
| 875 | cond_resched(); | ||
| 876 | } | ||
| 877 | } else | ||
| 797 | cond_resched(); | 878 | cond_resched(); |
| 798 | } | ||
| 799 | spin_lock_irqsave(&mz->lru_lock, flags); | 879 | spin_lock_irqsave(&mz->lru_lock, flags); |
| 800 | } | 880 | } |
| 801 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 881 | spin_unlock_irqrestore(&mz->lru_lock, flags); |
| @@ -810,9 +890,6 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem) | |||
| 810 | int ret = -EBUSY; | 890 | int ret = -EBUSY; |
| 811 | int node, zid; | 891 | int node, zid; |
| 812 | 892 | ||
| 813 | if (mem_cgroup_subsys.disabled) | ||
| 814 | return 0; | ||
| 815 | |||
| 816 | css_get(&mem->css); | 893 | css_get(&mem->css); |
| 817 | /* | 894 | /* |
| 818 | * page reclaim code (kswapd etc..) will move pages between | 895 | * page reclaim code (kswapd etc..) will move pages between |
| @@ -838,32 +915,34 @@ out: | |||
| 838 | return ret; | 915 | return ret; |
| 839 | } | 916 | } |
| 840 | 917 | ||
| 841 | static int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp) | ||
| 842 | { | ||
| 843 | *tmp = memparse(buf, &buf); | ||
| 844 | if (*buf != '\0') | ||
| 845 | return -EINVAL; | ||
| 846 | |||
| 847 | /* | ||
| 848 | * Round up the value to the closest page size | ||
| 849 | */ | ||
| 850 | *tmp = ((*tmp + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT; | ||
| 851 | return 0; | ||
| 852 | } | ||
| 853 | |||
| 854 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) | 918 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) |
| 855 | { | 919 | { |
| 856 | return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, | 920 | return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, |
| 857 | cft->private); | 921 | cft->private); |
| 858 | } | 922 | } |
| 859 | 923 | /* | |
| 860 | static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | 924 | * The user of this function is... |
| 861 | struct file *file, const char __user *userbuf, | 925 | * RES_LIMIT. |
| 862 | size_t nbytes, loff_t *ppos) | 926 | */ |
| 927 | static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | ||
| 928 | const char *buffer) | ||
| 863 | { | 929 | { |
| 864 | return res_counter_write(&mem_cgroup_from_cont(cont)->res, | 930 | struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); |
| 865 | cft->private, userbuf, nbytes, ppos, | 931 | unsigned long long val; |
| 866 | mem_cgroup_write_strategy); | 932 | int ret; |
| 933 | |||
| 934 | switch (cft->private) { | ||
| 935 | case RES_LIMIT: | ||
| 936 | /* This function does all necessary parse...reuse it */ | ||
| 937 | ret = res_counter_memparse_write_strategy(buffer, &val); | ||
| 938 | if (!ret) | ||
| 939 | ret = mem_cgroup_resize_limit(memcg, val); | ||
| 940 | break; | ||
| 941 | default: | ||
| 942 | ret = -EINVAL; /* should be BUG() ? */ | ||
| 943 | break; | ||
| 944 | } | ||
| 945 | return ret; | ||
| 867 | } | 946 | } |
| 868 | 947 | ||
| 869 | static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) | 948 | static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) |
| @@ -940,7 +1019,7 @@ static struct cftype mem_cgroup_files[] = { | |||
| 940 | { | 1019 | { |
| 941 | .name = "limit_in_bytes", | 1020 | .name = "limit_in_bytes", |
| 942 | .private = RES_LIMIT, | 1021 | .private = RES_LIMIT, |
| 943 | .write = mem_cgroup_write, | 1022 | .write_string = mem_cgroup_write, |
| 944 | .read_u64 = mem_cgroup_read, | 1023 | .read_u64 = mem_cgroup_read, |
| 945 | }, | 1024 | }, |
| 946 | { | 1025 | { |
| @@ -1070,8 +1149,6 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss, | |||
| 1070 | static int mem_cgroup_populate(struct cgroup_subsys *ss, | 1149 | static int mem_cgroup_populate(struct cgroup_subsys *ss, |
| 1071 | struct cgroup *cont) | 1150 | struct cgroup *cont) |
| 1072 | { | 1151 | { |
| 1073 | if (mem_cgroup_subsys.disabled) | ||
| 1074 | return 0; | ||
| 1075 | return cgroup_add_files(cont, ss, mem_cgroup_files, | 1152 | return cgroup_add_files(cont, ss, mem_cgroup_files, |
| 1076 | ARRAY_SIZE(mem_cgroup_files)); | 1153 | ARRAY_SIZE(mem_cgroup_files)); |
| 1077 | } | 1154 | } |
| @@ -1084,9 +1161,6 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss, | |||
| 1084 | struct mm_struct *mm; | 1161 | struct mm_struct *mm; |
| 1085 | struct mem_cgroup *mem, *old_mem; | 1162 | struct mem_cgroup *mem, *old_mem; |
| 1086 | 1163 | ||
| 1087 | if (mem_cgroup_subsys.disabled) | ||
| 1088 | return; | ||
| 1089 | |||
| 1090 | mm = get_task_mm(p); | 1164 | mm = get_task_mm(p); |
| 1091 | if (mm == NULL) | 1165 | if (mm == NULL) |
| 1092 | return; | 1166 | return; |
diff --git a/mm/migrate.c b/mm/migrate.c index 376cceba82f9..d8c65a65c61d 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
| @@ -358,6 +358,9 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
| 358 | __inc_zone_page_state(newpage, NR_FILE_PAGES); | 358 | __inc_zone_page_state(newpage, NR_FILE_PAGES); |
| 359 | 359 | ||
| 360 | write_unlock_irq(&mapping->tree_lock); | 360 | write_unlock_irq(&mapping->tree_lock); |
| 361 | if (!PageSwapCache(newpage)) { | ||
| 362 | mem_cgroup_uncharge_cache_page(page); | ||
| 363 | } | ||
| 361 | 364 | ||
| 362 | return 0; | 365 | return 0; |
| 363 | } | 366 | } |
| @@ -611,7 +614,6 @@ static int move_to_new_page(struct page *newpage, struct page *page) | |||
| 611 | rc = fallback_migrate_page(mapping, newpage, page); | 614 | rc = fallback_migrate_page(mapping, newpage, page); |
| 612 | 615 | ||
| 613 | if (!rc) { | 616 | if (!rc) { |
| 614 | mem_cgroup_page_migration(page, newpage); | ||
| 615 | remove_migration_ptes(page, newpage); | 617 | remove_migration_ptes(page, newpage); |
| 616 | } else | 618 | } else |
| 617 | newpage->mapping = NULL; | 619 | newpage->mapping = NULL; |
| @@ -641,6 +643,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
| 641 | /* page was freed from under us. So we are done. */ | 643 | /* page was freed from under us. So we are done. */ |
| 642 | goto move_newpage; | 644 | goto move_newpage; |
| 643 | 645 | ||
| 646 | charge = mem_cgroup_prepare_migration(page, newpage); | ||
| 647 | if (charge == -ENOMEM) { | ||
| 648 | rc = -ENOMEM; | ||
| 649 | goto move_newpage; | ||
| 650 | } | ||
| 651 | /* prepare cgroup just returns 0 or -ENOMEM */ | ||
| 652 | BUG_ON(charge); | ||
| 653 | |||
| 644 | rc = -EAGAIN; | 654 | rc = -EAGAIN; |
| 645 | if (TestSetPageLocked(page)) { | 655 | if (TestSetPageLocked(page)) { |
| 646 | if (!force) | 656 | if (!force) |
| @@ -692,19 +702,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
| 692 | goto rcu_unlock; | 702 | goto rcu_unlock; |
| 693 | } | 703 | } |
| 694 | 704 | ||
| 695 | charge = mem_cgroup_prepare_migration(page); | ||
| 696 | /* Establish migration ptes or remove ptes */ | 705 | /* Establish migration ptes or remove ptes */ |
| 697 | try_to_unmap(page, 1); | 706 | try_to_unmap(page, 1); |
| 698 | 707 | ||
| 699 | if (!page_mapped(page)) | 708 | if (!page_mapped(page)) |
| 700 | rc = move_to_new_page(newpage, page); | 709 | rc = move_to_new_page(newpage, page); |
| 701 | 710 | ||
| 702 | if (rc) { | 711 | if (rc) |
| 703 | remove_migration_ptes(page, page); | 712 | remove_migration_ptes(page, page); |
| 704 | if (charge) | ||
| 705 | mem_cgroup_end_migration(page); | ||
| 706 | } else if (charge) | ||
| 707 | mem_cgroup_end_migration(newpage); | ||
| 708 | rcu_unlock: | 713 | rcu_unlock: |
| 709 | if (rcu_locked) | 714 | if (rcu_locked) |
| 710 | rcu_read_unlock(); | 715 | rcu_read_unlock(); |
| @@ -725,6 +730,8 @@ unlock: | |||
| 725 | } | 730 | } |
| 726 | 731 | ||
| 727 | move_newpage: | 732 | move_newpage: |
| 733 | if (!charge) | ||
| 734 | mem_cgroup_end_migration(newpage); | ||
| 728 | /* | 735 | /* |
| 729 | * Move the new page to the LRU. If migration was not successful | 736 | * Move the new page to the LRU. If migration was not successful |
| 730 | * then this will free the page. | 737 | * then this will free the page. |
diff --git a/mm/pdflush.c b/mm/pdflush.c index 9d834aa4b979..0cbe0c60c6bf 100644 --- a/mm/pdflush.c +++ b/mm/pdflush.c | |||
| @@ -130,7 +130,7 @@ static int __pdflush(struct pdflush_work *my_work) | |||
| 130 | * Thread creation: For how long have there been zero | 130 | * Thread creation: For how long have there been zero |
| 131 | * available threads? | 131 | * available threads? |
| 132 | */ | 132 | */ |
| 133 | if (jiffies - last_empty_jifs > 1 * HZ) { | 133 | if (time_after(jiffies, last_empty_jifs + 1 * HZ)) { |
| 134 | /* unlocked list_empty() test is OK here */ | 134 | /* unlocked list_empty() test is OK here */ |
| 135 | if (list_empty(&pdflush_list)) { | 135 | if (list_empty(&pdflush_list)) { |
| 136 | /* unlocked test is OK here */ | 136 | /* unlocked test is OK here */ |
| @@ -151,7 +151,7 @@ static int __pdflush(struct pdflush_work *my_work) | |||
| 151 | if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS) | 151 | if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS) |
| 152 | continue; | 152 | continue; |
| 153 | pdf = list_entry(pdflush_list.prev, struct pdflush_work, list); | 153 | pdf = list_entry(pdflush_list.prev, struct pdflush_work, list); |
| 154 | if (jiffies - pdf->when_i_went_to_sleep > 1 * HZ) { | 154 | if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) { |
| 155 | /* Limit exit rate */ | 155 | /* Limit exit rate */ |
| 156 | pdf->when_i_went_to_sleep = jiffies; | 156 | pdf->when_i_went_to_sleep = jiffies; |
| 157 | break; /* exeunt */ | 157 | break; /* exeunt */ |
| @@ -576,14 +576,8 @@ void page_add_anon_rmap(struct page *page, | |||
| 576 | VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); | 576 | VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); |
| 577 | if (atomic_inc_and_test(&page->_mapcount)) | 577 | if (atomic_inc_and_test(&page->_mapcount)) |
| 578 | __page_set_anon_rmap(page, vma, address); | 578 | __page_set_anon_rmap(page, vma, address); |
| 579 | else { | 579 | else |
| 580 | __page_check_anon_rmap(page, vma, address); | 580 | __page_check_anon_rmap(page, vma, address); |
| 581 | /* | ||
| 582 | * We unconditionally charged during prepare, we uncharge here | ||
| 583 | * This takes care of balancing the reference counts | ||
| 584 | */ | ||
| 585 | mem_cgroup_uncharge_page(page); | ||
| 586 | } | ||
| 587 | } | 581 | } |
| 588 | 582 | ||
| 589 | /** | 583 | /** |
| @@ -614,12 +608,6 @@ void page_add_file_rmap(struct page *page) | |||
| 614 | { | 608 | { |
| 615 | if (atomic_inc_and_test(&page->_mapcount)) | 609 | if (atomic_inc_and_test(&page->_mapcount)) |
| 616 | __inc_zone_page_state(page, NR_FILE_MAPPED); | 610 | __inc_zone_page_state(page, NR_FILE_MAPPED); |
| 617 | else | ||
| 618 | /* | ||
| 619 | * We unconditionally charged during prepare, we uncharge here | ||
| 620 | * This takes care of balancing the reference counts | ||
| 621 | */ | ||
| 622 | mem_cgroup_uncharge_page(page); | ||
| 623 | } | 611 | } |
| 624 | 612 | ||
| 625 | #ifdef CONFIG_DEBUG_VM | 613 | #ifdef CONFIG_DEBUG_VM |
diff --git a/mm/shmem.c b/mm/shmem.c index 9ffbea9b79e1..f92fea94d037 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -922,20 +922,26 @@ found: | |||
| 922 | error = 1; | 922 | error = 1; |
| 923 | if (!inode) | 923 | if (!inode) |
| 924 | goto out; | 924 | goto out; |
| 925 | /* Precharge page while we can wait, compensate afterwards */ | 925 | /* Precharge page using GFP_KERNEL while we can wait */ |
| 926 | error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL); | 926 | error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL); |
| 927 | if (error) | 927 | if (error) |
| 928 | goto out; | 928 | goto out; |
| 929 | error = radix_tree_preload(GFP_KERNEL); | 929 | error = radix_tree_preload(GFP_KERNEL); |
| 930 | if (error) | 930 | if (error) { |
| 931 | goto uncharge; | 931 | mem_cgroup_uncharge_cache_page(page); |
| 932 | goto out; | ||
| 933 | } | ||
| 932 | error = 1; | 934 | error = 1; |
| 933 | 935 | ||
| 934 | spin_lock(&info->lock); | 936 | spin_lock(&info->lock); |
| 935 | ptr = shmem_swp_entry(info, idx, NULL); | 937 | ptr = shmem_swp_entry(info, idx, NULL); |
| 936 | if (ptr && ptr->val == entry.val) | 938 | if (ptr && ptr->val == entry.val) { |
| 937 | error = add_to_page_cache(page, inode->i_mapping, | 939 | error = add_to_page_cache(page, inode->i_mapping, |
| 938 | idx, GFP_NOWAIT); | 940 | idx, GFP_NOWAIT); |
| 941 | /* does mem_cgroup_uncharge_cache_page on error */ | ||
| 942 | } else /* we must compensate for our precharge above */ | ||
| 943 | mem_cgroup_uncharge_cache_page(page); | ||
| 944 | |||
| 939 | if (error == -EEXIST) { | 945 | if (error == -EEXIST) { |
| 940 | struct page *filepage = find_get_page(inode->i_mapping, idx); | 946 | struct page *filepage = find_get_page(inode->i_mapping, idx); |
| 941 | error = 1; | 947 | error = 1; |
| @@ -961,8 +967,6 @@ found: | |||
| 961 | shmem_swp_unmap(ptr); | 967 | shmem_swp_unmap(ptr); |
| 962 | spin_unlock(&info->lock); | 968 | spin_unlock(&info->lock); |
| 963 | radix_tree_preload_end(); | 969 | radix_tree_preload_end(); |
| 964 | uncharge: | ||
| 965 | mem_cgroup_uncharge_page(page); | ||
| 966 | out: | 970 | out: |
| 967 | unlock_page(page); | 971 | unlock_page(page); |
| 968 | page_cache_release(page); | 972 | page_cache_release(page); |
| @@ -1311,17 +1315,14 @@ repeat: | |||
| 1311 | shmem_swp_unmap(entry); | 1315 | shmem_swp_unmap(entry); |
| 1312 | spin_unlock(&info->lock); | 1316 | spin_unlock(&info->lock); |
| 1313 | unlock_page(swappage); | 1317 | unlock_page(swappage); |
| 1318 | page_cache_release(swappage); | ||
| 1314 | if (error == -ENOMEM) { | 1319 | if (error == -ENOMEM) { |
| 1315 | /* allow reclaim from this memory cgroup */ | 1320 | /* allow reclaim from this memory cgroup */ |
| 1316 | error = mem_cgroup_cache_charge(swappage, | 1321 | error = mem_cgroup_shrink_usage(current->mm, |
| 1317 | current->mm, gfp & ~__GFP_HIGHMEM); | 1322 | gfp); |
| 1318 | if (error) { | 1323 | if (error) |
| 1319 | page_cache_release(swappage); | ||
| 1320 | goto failed; | 1324 | goto failed; |
| 1321 | } | ||
| 1322 | mem_cgroup_uncharge_page(swappage); | ||
| 1323 | } | 1325 | } |
| 1324 | page_cache_release(swappage); | ||
| 1325 | goto repeat; | 1326 | goto repeat; |
| 1326 | } | 1327 | } |
| 1327 | } else if (sgp == SGP_READ && !filepage) { | 1328 | } else if (sgp == SGP_READ && !filepage) { |
| @@ -1358,6 +1359,8 @@ repeat: | |||
| 1358 | } | 1359 | } |
| 1359 | 1360 | ||
| 1360 | if (!filepage) { | 1361 | if (!filepage) { |
| 1362 | int ret; | ||
| 1363 | |||
| 1361 | spin_unlock(&info->lock); | 1364 | spin_unlock(&info->lock); |
| 1362 | filepage = shmem_alloc_page(gfp, info, idx); | 1365 | filepage = shmem_alloc_page(gfp, info, idx); |
| 1363 | if (!filepage) { | 1366 | if (!filepage) { |
| @@ -1386,10 +1389,18 @@ repeat: | |||
| 1386 | swap = *entry; | 1389 | swap = *entry; |
| 1387 | shmem_swp_unmap(entry); | 1390 | shmem_swp_unmap(entry); |
| 1388 | } | 1391 | } |
| 1389 | if (error || swap.val || 0 != add_to_page_cache_lru( | 1392 | ret = error || swap.val; |
| 1390 | filepage, mapping, idx, GFP_NOWAIT)) { | 1393 | if (ret) |
| 1394 | mem_cgroup_uncharge_cache_page(filepage); | ||
| 1395 | else | ||
| 1396 | ret = add_to_page_cache_lru(filepage, mapping, | ||
| 1397 | idx, GFP_NOWAIT); | ||
| 1398 | /* | ||
| 1399 | * At add_to_page_cache_lru() failure, uncharge will | ||
| 1400 | * be done automatically. | ||
| 1401 | */ | ||
| 1402 | if (ret) { | ||
| 1391 | spin_unlock(&info->lock); | 1403 | spin_unlock(&info->lock); |
| 1392 | mem_cgroup_uncharge_page(filepage); | ||
| 1393 | page_cache_release(filepage); | 1404 | page_cache_release(filepage); |
| 1394 | shmem_unacct_blocks(info->flags, 1); | 1405 | shmem_unacct_blocks(info->flags, 1); |
| 1395 | shmem_free_blocks(inode, 1); | 1406 | shmem_free_blocks(inode, 1); |
| @@ -1398,7 +1409,6 @@ repeat: | |||
| 1398 | goto failed; | 1409 | goto failed; |
| 1399 | goto repeat; | 1410 | goto repeat; |
| 1400 | } | 1411 | } |
| 1401 | mem_cgroup_uncharge_page(filepage); | ||
| 1402 | info->flags |= SHMEM_PAGEIN; | 1412 | info->flags |= SHMEM_PAGEIN; |
| 1403 | } | 1413 | } |
| 1404 | 1414 | ||
diff --git a/mm/vmscan.c b/mm/vmscan.c index 967d30ccd92b..26672c6cd3ce 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/kthread.h> | 38 | #include <linux/kthread.h> |
| 39 | #include <linux/freezer.h> | 39 | #include <linux/freezer.h> |
| 40 | #include <linux/memcontrol.h> | 40 | #include <linux/memcontrol.h> |
| 41 | #include <linux/delayacct.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/tlbflush.h> | 43 | #include <asm/tlbflush.h> |
| 43 | #include <asm/div64.h> | 44 | #include <asm/div64.h> |
| @@ -1316,6 +1317,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
| 1316 | struct zone *zone; | 1317 | struct zone *zone; |
| 1317 | enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask); | 1318 | enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask); |
| 1318 | 1319 | ||
| 1320 | delayacct_freepages_start(); | ||
| 1321 | |||
| 1319 | if (scan_global_lru(sc)) | 1322 | if (scan_global_lru(sc)) |
| 1320 | count_vm_event(ALLOCSTALL); | 1323 | count_vm_event(ALLOCSTALL); |
| 1321 | /* | 1324 | /* |
| @@ -1396,6 +1399,8 @@ out: | |||
| 1396 | } else | 1399 | } else |
| 1397 | mem_cgroup_record_reclaim_priority(sc->mem_cgroup, priority); | 1400 | mem_cgroup_record_reclaim_priority(sc->mem_cgroup, priority); |
| 1398 | 1401 | ||
| 1402 | delayacct_freepages_end(); | ||
| 1403 | |||
| 1399 | return ret; | 1404 | return ret; |
| 1400 | } | 1405 | } |
| 1401 | 1406 | ||
diff --git a/net/802/psnap.c b/net/802/psnap.c index ea4643931446..b3cfe5a14fca 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c | |||
| @@ -31,11 +31,9 @@ static struct llc_sap *snap_sap; | |||
| 31 | */ | 31 | */ |
| 32 | static struct datalink_proto *find_snap_client(unsigned char *desc) | 32 | static struct datalink_proto *find_snap_client(unsigned char *desc) |
| 33 | { | 33 | { |
| 34 | struct list_head *entry; | ||
| 35 | struct datalink_proto *proto = NULL, *p; | 34 | struct datalink_proto *proto = NULL, *p; |
| 36 | 35 | ||
| 37 | list_for_each_rcu(entry, &snap_list) { | 36 | list_for_each_entry_rcu(p, &snap_list, node) { |
| 38 | p = list_entry(entry, struct datalink_proto, node); | ||
| 39 | if (!memcmp(p->type, desc, 5)) { | 37 | if (!memcmp(p->type, desc, 5)) { |
| 40 | proto = p; | 38 | proto = p; |
| 41 | break; | 39 | break; |
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index a570e2af22cb..f686467ff12b 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
| @@ -67,7 +67,7 @@ static struct ctl_table net_core_table[] = { | |||
| 67 | { | 67 | { |
| 68 | .ctl_name = NET_CORE_MSG_COST, | 68 | .ctl_name = NET_CORE_MSG_COST, |
| 69 | .procname = "message_cost", | 69 | .procname = "message_cost", |
| 70 | .data = &net_msg_cost, | 70 | .data = &net_ratelimit_state.interval, |
| 71 | .maxlen = sizeof(int), | 71 | .maxlen = sizeof(int), |
| 72 | .mode = 0644, | 72 | .mode = 0644, |
| 73 | .proc_handler = &proc_dointvec_jiffies, | 73 | .proc_handler = &proc_dointvec_jiffies, |
| @@ -76,7 +76,7 @@ static struct ctl_table net_core_table[] = { | |||
| 76 | { | 76 | { |
| 77 | .ctl_name = NET_CORE_MSG_BURST, | 77 | .ctl_name = NET_CORE_MSG_BURST, |
| 78 | .procname = "message_burst", | 78 | .procname = "message_burst", |
| 79 | .data = &net_msg_burst, | 79 | .data = &net_ratelimit_state.burst, |
| 80 | .maxlen = sizeof(int), | 80 | .maxlen = sizeof(int), |
| 81 | .mode = 0644, | 81 | .mode = 0644, |
| 82 | .proc_handler = &proc_dointvec, | 82 | .proc_handler = &proc_dointvec, |
diff --git a/net/core/utils.c b/net/core/utils.c index 8031eb59054e..72e0ebe964a0 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
| @@ -31,17 +31,16 @@ | |||
| 31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
| 32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
| 33 | 33 | ||
| 34 | int net_msg_cost __read_mostly = 5*HZ; | ||
| 35 | int net_msg_burst __read_mostly = 10; | ||
| 36 | int net_msg_warn __read_mostly = 1; | 34 | int net_msg_warn __read_mostly = 1; |
| 37 | EXPORT_SYMBOL(net_msg_warn); | 35 | EXPORT_SYMBOL(net_msg_warn); |
| 38 | 36 | ||
| 37 | DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10); | ||
| 39 | /* | 38 | /* |
| 40 | * All net warning printk()s should be guarded by this function. | 39 | * All net warning printk()s should be guarded by this function. |
| 41 | */ | 40 | */ |
| 42 | int net_ratelimit(void) | 41 | int net_ratelimit(void) |
| 43 | { | 42 | { |
| 44 | return __printk_ratelimit(net_msg_cost, net_msg_burst); | 43 | return __ratelimit(&net_ratelimit_state); |
| 45 | } | 44 | } |
| 46 | EXPORT_SYMBOL(net_ratelimit); | 45 | EXPORT_SYMBOL(net_ratelimit); |
| 47 | 46 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index dd919d84285f..f440a9f54924 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -264,7 +264,6 @@ static inline int inet_netns_ok(struct net *net, int protocol) | |||
| 264 | static int inet_create(struct net *net, struct socket *sock, int protocol) | 264 | static int inet_create(struct net *net, struct socket *sock, int protocol) |
| 265 | { | 265 | { |
| 266 | struct sock *sk; | 266 | struct sock *sk; |
| 267 | struct list_head *p; | ||
| 268 | struct inet_protosw *answer; | 267 | struct inet_protosw *answer; |
| 269 | struct inet_sock *inet; | 268 | struct inet_sock *inet; |
| 270 | struct proto *answer_prot; | 269 | struct proto *answer_prot; |
| @@ -281,13 +280,12 @@ static int inet_create(struct net *net, struct socket *sock, int protocol) | |||
| 281 | sock->state = SS_UNCONNECTED; | 280 | sock->state = SS_UNCONNECTED; |
| 282 | 281 | ||
| 283 | /* Look for the requested type/protocol pair. */ | 282 | /* Look for the requested type/protocol pair. */ |
| 284 | answer = NULL; | ||
| 285 | lookup_protocol: | 283 | lookup_protocol: |
| 286 | err = -ESOCKTNOSUPPORT; | 284 | err = -ESOCKTNOSUPPORT; |
| 287 | rcu_read_lock(); | 285 | rcu_read_lock(); |
| 288 | list_for_each_rcu(p, &inetsw[sock->type]) { | 286 | list_for_each_entry_rcu(answer, &inetsw[sock->type], list) { |
| 289 | answer = list_entry(p, struct inet_protosw, list); | ||
| 290 | 287 | ||
| 288 | err = 0; | ||
| 291 | /* Check the non-wild match. */ | 289 | /* Check the non-wild match. */ |
| 292 | if (protocol == answer->protocol) { | 290 | if (protocol == answer->protocol) { |
| 293 | if (protocol != IPPROTO_IP) | 291 | if (protocol != IPPROTO_IP) |
| @@ -302,10 +300,9 @@ lookup_protocol: | |||
| 302 | break; | 300 | break; |
| 303 | } | 301 | } |
| 304 | err = -EPROTONOSUPPORT; | 302 | err = -EPROTONOSUPPORT; |
| 305 | answer = NULL; | ||
| 306 | } | 303 | } |
| 307 | 304 | ||
| 308 | if (unlikely(answer == NULL)) { | 305 | if (unlikely(err)) { |
| 309 | if (try_loading_module < 2) { | 306 | if (try_loading_module < 2) { |
| 310 | rcu_read_unlock(); | 307 | rcu_read_unlock(); |
| 311 | /* | 308 | /* |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3d828bc4b1cf..60461ad7fa6f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -83,7 +83,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol) | |||
| 83 | struct inet_sock *inet; | 83 | struct inet_sock *inet; |
| 84 | struct ipv6_pinfo *np; | 84 | struct ipv6_pinfo *np; |
| 85 | struct sock *sk; | 85 | struct sock *sk; |
| 86 | struct list_head *p; | ||
| 87 | struct inet_protosw *answer; | 86 | struct inet_protosw *answer; |
| 88 | struct proto *answer_prot; | 87 | struct proto *answer_prot; |
| 89 | unsigned char answer_flags; | 88 | unsigned char answer_flags; |
| @@ -97,13 +96,12 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol) | |||
| 97 | build_ehash_secret(); | 96 | build_ehash_secret(); |
| 98 | 97 | ||
| 99 | /* Look for the requested type/protocol pair. */ | 98 | /* Look for the requested type/protocol pair. */ |
| 100 | answer = NULL; | ||
| 101 | lookup_protocol: | 99 | lookup_protocol: |
| 102 | err = -ESOCKTNOSUPPORT; | 100 | err = -ESOCKTNOSUPPORT; |
| 103 | rcu_read_lock(); | 101 | rcu_read_lock(); |
| 104 | list_for_each_rcu(p, &inetsw6[sock->type]) { | 102 | list_for_each_entry_rcu(answer, &inetsw6[sock->type], list) { |
| 105 | answer = list_entry(p, struct inet_protosw, list); | ||
| 106 | 103 | ||
| 104 | err = 0; | ||
| 107 | /* Check the non-wild match. */ | 105 | /* Check the non-wild match. */ |
| 108 | if (protocol == answer->protocol) { | 106 | if (protocol == answer->protocol) { |
| 109 | if (protocol != IPPROTO_IP) | 107 | if (protocol != IPPROTO_IP) |
| @@ -118,10 +116,9 @@ lookup_protocol: | |||
| 118 | break; | 116 | break; |
| 119 | } | 117 | } |
| 120 | err = -EPROTONOSUPPORT; | 118 | err = -EPROTONOSUPPORT; |
| 121 | answer = NULL; | ||
| 122 | } | 119 | } |
| 123 | 120 | ||
| 124 | if (!answer) { | 121 | if (err) { |
| 125 | if (try_loading_module < 2) { | 122 | if (try_loading_module < 2) { |
| 126 | rcu_read_unlock(); | 123 | rcu_read_unlock(); |
| 127 | /* | 124 | /* |
diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 007c1a6708ee..63ada437fc2f 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c | |||
| @@ -35,8 +35,22 @@ net_ctl_header_lookup(struct ctl_table_root *root, struct nsproxy *namespaces) | |||
| 35 | return &namespaces->net_ns->sysctl_table_headers; | 35 | return &namespaces->net_ns->sysctl_table_headers; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | /* Return standard mode bits for table entry. */ | ||
| 39 | static int net_ctl_permissions(struct ctl_table_root *root, | ||
| 40 | struct nsproxy *nsproxy, | ||
| 41 | struct ctl_table *table) | ||
| 42 | { | ||
| 43 | /* Allow network administrator to have same access as root. */ | ||
| 44 | if (capable(CAP_NET_ADMIN)) { | ||
| 45 | int mode = (table->mode >> 6) & 7; | ||
| 46 | return (mode << 6) | (mode << 3) | mode; | ||
| 47 | } | ||
| 48 | return table->mode; | ||
| 49 | } | ||
| 50 | |||
| 38 | static struct ctl_table_root net_sysctl_root = { | 51 | static struct ctl_table_root net_sysctl_root = { |
| 39 | .lookup = net_ctl_header_lookup, | 52 | .lookup = net_ctl_header_lookup, |
| 53 | .permissions = net_ctl_permissions, | ||
| 40 | }; | 54 | }; |
| 41 | 55 | ||
| 42 | static LIST_HEAD(net_sysctl_ro_tables); | 56 | static LIST_HEAD(net_sysctl_ro_tables); |
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index c972c0f54ce0..f63a663de158 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst | |||
| @@ -17,14 +17,15 @@ include $(srctree)/$(obj)/Makefile | |||
| 17 | 17 | ||
| 18 | include scripts/Makefile.host | 18 | include scripts/Makefile.host |
| 19 | 19 | ||
| 20 | mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-m)) | 20 | mod-fw := $(fw-shipped-m) |
| 21 | |||
| 22 | # If CONFIG_FIRMWARE_IN_KERNEL isn't set, then install the | 21 | # If CONFIG_FIRMWARE_IN_KERNEL isn't set, then install the |
| 23 | # firmware for in-kernel drivers too. | 22 | # firmware for in-kernel drivers too. |
| 24 | ifndef CONFIG_FIRMWARE_IN_KERNEL | 23 | ifndef CONFIG_FIRMWARE_IN_KERNEL |
| 25 | mod-fw += $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-y)) | 24 | mod-fw += $(fw-shipped-y) |
| 26 | endif | 25 | endif |
| 27 | 26 | ||
| 27 | installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) | ||
| 28 | |||
| 28 | installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) | 29 | installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) |
| 29 | installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. | 30 | installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. |
| 30 | 31 | ||
| @@ -49,7 +50,8 @@ PHONY += __fw_install __fw_modinst FORCE | |||
| 49 | .PHONY: $(PHONY) | 50 | .PHONY: $(PHONY) |
| 50 | 51 | ||
| 51 | __fw_install: $(installed-fw) | 52 | __fw_install: $(installed-fw) |
| 52 | __fw_modinst: $(mod-fw) | 53 | __fw_modinst: $(installed-mod-fw) |
| 54 | __fw_modbuild: $(addprefix $(obj)/,$(mod-fw)) | ||
| 53 | 55 | ||
| 54 | FORCE: | 56 | FORCE: |
| 55 | 57 | ||
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index 340ad6920511..3eca62566d6b 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl | |||
| @@ -26,12 +26,17 @@ | |||
| 26 | # $& (whole re) matches the complete objdump line with the stack growth | 26 | # $& (whole re) matches the complete objdump line with the stack growth |
| 27 | # $1 (first bracket) matches the size of the stack growth | 27 | # $1 (first bracket) matches the size of the stack growth |
| 28 | # | 28 | # |
| 29 | # $dre is similar, but for dynamic stack redutions: | ||
| 30 | # $& (whole re) matches the complete objdump line with the stack growth | ||
| 31 | # $1 (first bracket) matches the dynamic amount of the stack growth | ||
| 32 | # | ||
| 29 | # use anything else and feel the pain ;) | 33 | # use anything else and feel the pain ;) |
| 30 | my (@stack, $re, $x, $xs); | 34 | my (@stack, $re, $dre, $x, $xs); |
| 31 | { | 35 | { |
| 32 | my $arch = shift; | 36 | my $arch = shift; |
| 33 | if ($arch eq "") { | 37 | if ($arch eq "") { |
| 34 | $arch = `uname -m`; | 38 | $arch = `uname -m`; |
| 39 | chomp($arch); | ||
| 35 | } | 40 | } |
| 36 | 41 | ||
| 37 | $x = "[0-9a-f]"; # hex character | 42 | $x = "[0-9a-f]"; # hex character |
| @@ -46,9 +51,11 @@ my (@stack, $re, $x, $xs); | |||
| 46 | } elsif ($arch =~ /^i[3456]86$/) { | 51 | } elsif ($arch =~ /^i[3456]86$/) { |
| 47 | #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp | 52 | #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp |
| 48 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; | 53 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; |
| 54 | $dre = qr/^.*[as][du][db] (%.*),\%esp$/o; | ||
| 49 | } elsif ($arch eq 'x86_64') { | 55 | } elsif ($arch eq 'x86_64') { |
| 50 | # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp | 56 | # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp |
| 51 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o; | 57 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o; |
| 58 | $dre = qr/^.*[as][du][db] (\%.*),\%rsp$/o; | ||
| 52 | } elsif ($arch eq 'ia64') { | 59 | } elsif ($arch eq 'ia64') { |
| 53 | #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 | 60 | #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 |
| 54 | $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; | 61 | $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; |
| @@ -85,7 +92,7 @@ my (@stack, $re, $x, $xs); | |||
| 85 | # 0: 00 e8 38 01 LINK 0x4e0; | 92 | # 0: 00 e8 38 01 LINK 0x4e0; |
| 86 | $re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o; | 93 | $re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o; |
| 87 | } else { | 94 | } else { |
| 88 | print("wrong or unknown architecture\n"); | 95 | print("wrong or unknown architecture \"$arch\"\n"); |
| 89 | exit | 96 | exit |
| 90 | } | 97 | } |
| 91 | } | 98 | } |
| @@ -141,6 +148,22 @@ while (my $line = <STDIN>) { | |||
| 141 | next if ($size < 100); | 148 | next if ($size < 100); |
| 142 | push @stack, "$intro$size\n"; | 149 | push @stack, "$intro$size\n"; |
| 143 | } | 150 | } |
| 151 | elsif (defined $dre && $line =~ m/$dre/) { | ||
| 152 | my $size = "Dynamic ($1)"; | ||
| 153 | |||
| 154 | next if $line !~ m/^($xs*)/; | ||
| 155 | my $addr = $1; | ||
| 156 | $addr =~ s/ /0/g; | ||
| 157 | $addr = "0x$addr"; | ||
| 158 | |||
| 159 | my $intro = "$addr $func [$file]:"; | ||
| 160 | my $padlen = 56 - length($intro); | ||
| 161 | while ($padlen > 0) { | ||
| 162 | $intro .= ' '; | ||
| 163 | $padlen -= 8; | ||
| 164 | } | ||
| 165 | push @stack, "$intro$size\n"; | ||
| 166 | } | ||
| 144 | } | 167 | } |
| 145 | 168 | ||
| 146 | print sort bysize @stack; | 169 | print sort bysize @stack; |
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index ddd92cec78ed..7bd296cca041 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
| @@ -41,6 +41,7 @@ struct dev_whitelist_item { | |||
| 41 | short type; | 41 | short type; |
| 42 | short access; | 42 | short access; |
| 43 | struct list_head list; | 43 | struct list_head list; |
| 44 | struct rcu_head rcu; | ||
| 44 | }; | 45 | }; |
| 45 | 46 | ||
| 46 | struct dev_cgroup { | 47 | struct dev_cgroup { |
| @@ -59,6 +60,11 @@ static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup) | |||
| 59 | return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id)); | 60 | return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id)); |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 63 | static inline struct dev_cgroup *task_devcgroup(struct task_struct *task) | ||
| 64 | { | ||
| 65 | return css_to_devcgroup(task_subsys_state(task, devices_subsys_id)); | ||
| 66 | } | ||
| 67 | |||
| 62 | struct cgroup_subsys devices_subsys; | 68 | struct cgroup_subsys devices_subsys; |
| 63 | 69 | ||
| 64 | static int devcgroup_can_attach(struct cgroup_subsys *ss, | 70 | static int devcgroup_can_attach(struct cgroup_subsys *ss, |
| @@ -128,11 +134,19 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | |||
| 128 | } | 134 | } |
| 129 | 135 | ||
| 130 | if (whcopy != NULL) | 136 | if (whcopy != NULL) |
| 131 | list_add_tail(&whcopy->list, &dev_cgroup->whitelist); | 137 | list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist); |
| 132 | spin_unlock(&dev_cgroup->lock); | 138 | spin_unlock(&dev_cgroup->lock); |
| 133 | return 0; | 139 | return 0; |
| 134 | } | 140 | } |
| 135 | 141 | ||
| 142 | static void whitelist_item_free(struct rcu_head *rcu) | ||
| 143 | { | ||
| 144 | struct dev_whitelist_item *item; | ||
| 145 | |||
| 146 | item = container_of(rcu, struct dev_whitelist_item, rcu); | ||
| 147 | kfree(item); | ||
| 148 | } | ||
| 149 | |||
| 136 | /* | 150 | /* |
| 137 | * called under cgroup_lock() | 151 | * called under cgroup_lock() |
| 138 | * since the list is visible to other tasks, we need the spinlock also | 152 | * since the list is visible to other tasks, we need the spinlock also |
| @@ -156,8 +170,8 @@ static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, | |||
| 156 | remove: | 170 | remove: |
| 157 | walk->access &= ~wh->access; | 171 | walk->access &= ~wh->access; |
| 158 | if (!walk->access) { | 172 | if (!walk->access) { |
| 159 | list_del(&walk->list); | 173 | list_del_rcu(&walk->list); |
| 160 | kfree(walk); | 174 | call_rcu(&walk->rcu, whitelist_item_free); |
| 161 | } | 175 | } |
| 162 | } | 176 | } |
| 163 | spin_unlock(&dev_cgroup->lock); | 177 | spin_unlock(&dev_cgroup->lock); |
| @@ -188,7 +202,7 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss, | |||
| 188 | } | 202 | } |
| 189 | wh->minor = wh->major = ~0; | 203 | wh->minor = wh->major = ~0; |
| 190 | wh->type = DEV_ALL; | 204 | wh->type = DEV_ALL; |
| 191 | wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE; | 205 | wh->access = ACC_MASK; |
| 192 | list_add(&wh->list, &dev_cgroup->whitelist); | 206 | list_add(&wh->list, &dev_cgroup->whitelist); |
| 193 | } else { | 207 | } else { |
| 194 | parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); | 208 | parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); |
| @@ -250,11 +264,10 @@ static char type_to_char(short type) | |||
| 250 | 264 | ||
| 251 | static void set_majmin(char *str, unsigned m) | 265 | static void set_majmin(char *str, unsigned m) |
| 252 | { | 266 | { |
| 253 | memset(str, 0, MAJMINLEN); | ||
| 254 | if (m == ~0) | 267 | if (m == ~0) |
| 255 | sprintf(str, "*"); | 268 | strcpy(str, "*"); |
| 256 | else | 269 | else |
| 257 | snprintf(str, MAJMINLEN, "%u", m); | 270 | sprintf(str, "%u", m); |
| 258 | } | 271 | } |
| 259 | 272 | ||
| 260 | static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, | 273 | static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, |
| @@ -264,15 +277,15 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, | |||
| 264 | struct dev_whitelist_item *wh; | 277 | struct dev_whitelist_item *wh; |
| 265 | char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN]; | 278 | char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN]; |
| 266 | 279 | ||
| 267 | spin_lock(&devcgroup->lock); | 280 | rcu_read_lock(); |
| 268 | list_for_each_entry(wh, &devcgroup->whitelist, list) { | 281 | list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) { |
| 269 | set_access(acc, wh->access); | 282 | set_access(acc, wh->access); |
| 270 | set_majmin(maj, wh->major); | 283 | set_majmin(maj, wh->major); |
| 271 | set_majmin(min, wh->minor); | 284 | set_majmin(min, wh->minor); |
| 272 | seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type), | 285 | seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type), |
| 273 | maj, min, acc); | 286 | maj, min, acc); |
| 274 | } | 287 | } |
| 275 | spin_unlock(&devcgroup->lock); | 288 | rcu_read_unlock(); |
| 276 | 289 | ||
| 277 | return 0; | 290 | return 0; |
| 278 | } | 291 | } |
| @@ -312,10 +325,10 @@ static int may_access_whitelist(struct dev_cgroup *c, | |||
| 312 | * when adding a new allow rule to a device whitelist, the rule | 325 | * when adding a new allow rule to a device whitelist, the rule |
| 313 | * must be allowed in the parent device | 326 | * must be allowed in the parent device |
| 314 | */ | 327 | */ |
| 315 | static int parent_has_perm(struct cgroup *childcg, | 328 | static int parent_has_perm(struct dev_cgroup *childcg, |
| 316 | struct dev_whitelist_item *wh) | 329 | struct dev_whitelist_item *wh) |
| 317 | { | 330 | { |
| 318 | struct cgroup *pcg = childcg->parent; | 331 | struct cgroup *pcg = childcg->css.cgroup->parent; |
| 319 | struct dev_cgroup *parent; | 332 | struct dev_cgroup *parent; |
| 320 | int ret; | 333 | int ret; |
| 321 | 334 | ||
| @@ -341,39 +354,19 @@ static int parent_has_perm(struct cgroup *childcg, | |||
| 341 | * new access is only allowed if you're in the top-level cgroup, or your | 354 | * new access is only allowed if you're in the top-level cgroup, or your |
| 342 | * parent cgroup has the access you're asking for. | 355 | * parent cgroup has the access you're asking for. |
| 343 | */ | 356 | */ |
| 344 | static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, | 357 | static int devcgroup_update_access(struct dev_cgroup *devcgroup, |
| 345 | struct file *file, const char __user *userbuf, | 358 | int filetype, const char *buffer) |
| 346 | size_t nbytes, loff_t *ppos) | ||
| 347 | { | 359 | { |
| 348 | struct cgroup *cur_cgroup; | 360 | struct dev_cgroup *cur_devcgroup; |
| 349 | struct dev_cgroup *devcgroup, *cur_devcgroup; | 361 | const char *b; |
| 350 | int filetype = cft->private; | 362 | char *endp; |
| 351 | char *buffer, *b; | ||
| 352 | int retval = 0, count; | 363 | int retval = 0, count; |
| 353 | struct dev_whitelist_item wh; | 364 | struct dev_whitelist_item wh; |
| 354 | 365 | ||
| 355 | if (!capable(CAP_SYS_ADMIN)) | 366 | if (!capable(CAP_SYS_ADMIN)) |
| 356 | return -EPERM; | 367 | return -EPERM; |
| 357 | 368 | ||
| 358 | devcgroup = cgroup_to_devcgroup(cgroup); | 369 | cur_devcgroup = task_devcgroup(current); |
| 359 | cur_cgroup = task_cgroup(current, devices_subsys.subsys_id); | ||
| 360 | cur_devcgroup = cgroup_to_devcgroup(cur_cgroup); | ||
| 361 | |||
| 362 | buffer = kmalloc(nbytes+1, GFP_KERNEL); | ||
| 363 | if (!buffer) | ||
| 364 | return -ENOMEM; | ||
| 365 | |||
| 366 | if (copy_from_user(buffer, userbuf, nbytes)) { | ||
| 367 | retval = -EFAULT; | ||
| 368 | goto out1; | ||
| 369 | } | ||
| 370 | buffer[nbytes] = 0; /* nul-terminate */ | ||
| 371 | |||
| 372 | cgroup_lock(); | ||
| 373 | if (cgroup_is_removed(cgroup)) { | ||
| 374 | retval = -ENODEV; | ||
| 375 | goto out2; | ||
| 376 | } | ||
| 377 | 370 | ||
| 378 | memset(&wh, 0, sizeof(wh)); | 371 | memset(&wh, 0, sizeof(wh)); |
| 379 | b = buffer; | 372 | b = buffer; |
| @@ -392,32 +385,23 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, | |||
| 392 | wh.type = DEV_CHAR; | 385 | wh.type = DEV_CHAR; |
| 393 | break; | 386 | break; |
| 394 | default: | 387 | default: |
| 395 | retval = -EINVAL; | 388 | return -EINVAL; |
| 396 | goto out2; | ||
| 397 | } | 389 | } |
| 398 | b++; | 390 | b++; |
| 399 | if (!isspace(*b)) { | 391 | if (!isspace(*b)) |
| 400 | retval = -EINVAL; | 392 | return -EINVAL; |
| 401 | goto out2; | ||
| 402 | } | ||
| 403 | b++; | 393 | b++; |
| 404 | if (*b == '*') { | 394 | if (*b == '*') { |
| 405 | wh.major = ~0; | 395 | wh.major = ~0; |
| 406 | b++; | 396 | b++; |
| 407 | } else if (isdigit(*b)) { | 397 | } else if (isdigit(*b)) { |
| 408 | wh.major = 0; | 398 | wh.major = simple_strtoul(b, &endp, 10); |
| 409 | while (isdigit(*b)) { | 399 | b = endp; |
| 410 | wh.major = wh.major*10+(*b-'0'); | ||
| 411 | b++; | ||
| 412 | } | ||
| 413 | } else { | 400 | } else { |
| 414 | retval = -EINVAL; | 401 | return -EINVAL; |
| 415 | goto out2; | ||
| 416 | } | ||
| 417 | if (*b != ':') { | ||
| 418 | retval = -EINVAL; | ||
| 419 | goto out2; | ||
| 420 | } | 402 | } |
| 403 | if (*b != ':') | ||
| 404 | return -EINVAL; | ||
| 421 | b++; | 405 | b++; |
| 422 | 406 | ||
| 423 | /* read minor */ | 407 | /* read minor */ |
| @@ -425,19 +409,13 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, | |||
| 425 | wh.minor = ~0; | 409 | wh.minor = ~0; |
| 426 | b++; | 410 | b++; |
| 427 | } else if (isdigit(*b)) { | 411 | } else if (isdigit(*b)) { |
| 428 | wh.minor = 0; | 412 | wh.minor = simple_strtoul(b, &endp, 10); |
| 429 | while (isdigit(*b)) { | 413 | b = endp; |
| 430 | wh.minor = wh.minor*10+(*b-'0'); | ||
| 431 | b++; | ||
| 432 | } | ||
| 433 | } else { | 414 | } else { |
| 434 | retval = -EINVAL; | 415 | return -EINVAL; |
| 435 | goto out2; | ||
| 436 | } | ||
| 437 | if (!isspace(*b)) { | ||
| 438 | retval = -EINVAL; | ||
| 439 | goto out2; | ||
| 440 | } | 416 | } |
| 417 | if (!isspace(*b)) | ||
| 418 | return -EINVAL; | ||
| 441 | for (b++, count = 0; count < 3; count++, b++) { | 419 | for (b++, count = 0; count < 3; count++, b++) { |
| 442 | switch (*b) { | 420 | switch (*b) { |
| 443 | case 'r': | 421 | case 'r': |
| @@ -454,8 +432,7 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, | |||
| 454 | count = 3; | 432 | count = 3; |
| 455 | break; | 433 | break; |
| 456 | default: | 434 | default: |
| 457 | retval = -EINVAL; | 435 | return -EINVAL; |
| 458 | goto out2; | ||
| 459 | } | 436 | } |
| 460 | } | 437 | } |
| 461 | 438 | ||
| @@ -463,38 +440,39 @@ handle: | |||
| 463 | retval = 0; | 440 | retval = 0; |
| 464 | switch (filetype) { | 441 | switch (filetype) { |
| 465 | case DEVCG_ALLOW: | 442 | case DEVCG_ALLOW: |
| 466 | if (!parent_has_perm(cgroup, &wh)) | 443 | if (!parent_has_perm(devcgroup, &wh)) |
| 467 | retval = -EPERM; | 444 | return -EPERM; |
| 468 | else | 445 | return dev_whitelist_add(devcgroup, &wh); |
| 469 | retval = dev_whitelist_add(devcgroup, &wh); | ||
| 470 | break; | ||
| 471 | case DEVCG_DENY: | 446 | case DEVCG_DENY: |
| 472 | dev_whitelist_rm(devcgroup, &wh); | 447 | dev_whitelist_rm(devcgroup, &wh); |
| 473 | break; | 448 | break; |
| 474 | default: | 449 | default: |
| 475 | retval = -EINVAL; | 450 | return -EINVAL; |
| 476 | goto out2; | ||
| 477 | } | 451 | } |
| 452 | return 0; | ||
| 453 | } | ||
| 478 | 454 | ||
| 479 | if (retval == 0) | 455 | static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft, |
| 480 | retval = nbytes; | 456 | const char *buffer) |
| 481 | 457 | { | |
| 482 | out2: | 458 | int retval; |
| 459 | if (!cgroup_lock_live_group(cgrp)) | ||
| 460 | return -ENODEV; | ||
| 461 | retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp), | ||
| 462 | cft->private, buffer); | ||
| 483 | cgroup_unlock(); | 463 | cgroup_unlock(); |
| 484 | out1: | ||
| 485 | kfree(buffer); | ||
| 486 | return retval; | 464 | return retval; |
| 487 | } | 465 | } |
| 488 | 466 | ||
| 489 | static struct cftype dev_cgroup_files[] = { | 467 | static struct cftype dev_cgroup_files[] = { |
| 490 | { | 468 | { |
| 491 | .name = "allow", | 469 | .name = "allow", |
| 492 | .write = devcgroup_access_write, | 470 | .write_string = devcgroup_access_write, |
| 493 | .private = DEVCG_ALLOW, | 471 | .private = DEVCG_ALLOW, |
| 494 | }, | 472 | }, |
| 495 | { | 473 | { |
| 496 | .name = "deny", | 474 | .name = "deny", |
| 497 | .write = devcgroup_access_write, | 475 | .write_string = devcgroup_access_write, |
| 498 | .private = DEVCG_DENY, | 476 | .private = DEVCG_DENY, |
| 499 | }, | 477 | }, |
| 500 | { | 478 | { |
| @@ -535,8 +513,8 @@ int devcgroup_inode_permission(struct inode *inode, int mask) | |||
| 535 | if (!dev_cgroup) | 513 | if (!dev_cgroup) |
| 536 | return 0; | 514 | return 0; |
| 537 | 515 | ||
| 538 | spin_lock(&dev_cgroup->lock); | 516 | rcu_read_lock(); |
| 539 | list_for_each_entry(wh, &dev_cgroup->whitelist, list) { | 517 | list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) { |
| 540 | if (wh->type & DEV_ALL) | 518 | if (wh->type & DEV_ALL) |
| 541 | goto acc_check; | 519 | goto acc_check; |
| 542 | if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode)) | 520 | if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode)) |
| @@ -552,10 +530,10 @@ acc_check: | |||
| 552 | continue; | 530 | continue; |
| 553 | if ((mask & MAY_READ) && !(wh->access & ACC_READ)) | 531 | if ((mask & MAY_READ) && !(wh->access & ACC_READ)) |
| 554 | continue; | 532 | continue; |
| 555 | spin_unlock(&dev_cgroup->lock); | 533 | rcu_read_unlock(); |
| 556 | return 0; | 534 | return 0; |
| 557 | } | 535 | } |
| 558 | spin_unlock(&dev_cgroup->lock); | 536 | rcu_read_unlock(); |
| 559 | 537 | ||
| 560 | return -EPERM; | 538 | return -EPERM; |
| 561 | } | 539 | } |
| @@ -570,7 +548,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev) | |||
| 570 | if (!dev_cgroup) | 548 | if (!dev_cgroup) |
| 571 | return 0; | 549 | return 0; |
| 572 | 550 | ||
| 573 | spin_lock(&dev_cgroup->lock); | 551 | rcu_read_lock(); |
| 574 | list_for_each_entry(wh, &dev_cgroup->whitelist, list) { | 552 | list_for_each_entry(wh, &dev_cgroup->whitelist, list) { |
| 575 | if (wh->type & DEV_ALL) | 553 | if (wh->type & DEV_ALL) |
| 576 | goto acc_check; | 554 | goto acc_check; |
| @@ -585,9 +563,9 @@ int devcgroup_inode_mknod(int mode, dev_t dev) | |||
| 585 | acc_check: | 563 | acc_check: |
| 586 | if (!(wh->access & ACC_MKNOD)) | 564 | if (!(wh->access & ACC_MKNOD)) |
| 587 | continue; | 565 | continue; |
| 588 | spin_unlock(&dev_cgroup->lock); | 566 | rcu_read_unlock(); |
| 589 | return 0; | 567 | return 0; |
| 590 | } | 568 | } |
| 591 | spin_unlock(&dev_cgroup->lock); | 569 | rcu_read_unlock(); |
| 592 | return -EPERM; | 570 | return -EPERM; |
| 593 | } | 571 | } |
