diff options
325 files changed, 9440 insertions, 4070 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-memory b/Documentation/ABI/testing/sysfs-devices-memory index 9fe91c02ee40..bf1627b02a03 100644 --- a/Documentation/ABI/testing/sysfs-devices-memory +++ b/Documentation/ABI/testing/sysfs-devices-memory | |||
| @@ -60,6 +60,19 @@ Description: | |||
| 60 | Users: hotplug memory remove tools | 60 | Users: hotplug memory remove tools |
| 61 | https://w3.opensource.ibm.com/projects/powerpc-utils/ | 61 | https://w3.opensource.ibm.com/projects/powerpc-utils/ |
| 62 | 62 | ||
| 63 | |||
| 64 | What: /sys/devices/system/memoryX/nodeY | ||
| 65 | Date: October 2009 | ||
| 66 | Contact: Linux Memory Management list <linux-mm@kvack.org> | ||
| 67 | Description: | ||
| 68 | When CONFIG_NUMA is enabled, a symbolic link that | ||
| 69 | points to the corresponding NUMA node directory. | ||
| 70 | |||
| 71 | For example, the following symbolic link is created for | ||
| 72 | memory section 9 on node0: | ||
| 73 | /sys/devices/system/memory/memory9/node0 -> ../../node/node0 | ||
| 74 | |||
| 75 | |||
| 63 | What: /sys/devices/system/node/nodeX/memoryY | 76 | What: /sys/devices/system/node/nodeX/memoryY |
| 64 | Date: September 2008 | 77 | Date: September 2008 |
| 65 | Contact: Gary Hade <garyhade@us.ibm.com> | 78 | Contact: Gary Hade <garyhade@us.ibm.com> |
| @@ -70,4 +83,3 @@ Description: | |||
| 70 | memory section directory. For example, the following symbolic | 83 | memory section directory. For example, the following symbolic |
| 71 | link is created for memory section 9 on node0. | 84 | link is created for memory section 9 on node0. |
| 72 | /sys/devices/system/node/node0/memory9 -> ../../memory/memory9 | 85 | /sys/devices/system/node/node0/memory9 -> ../../memory/memory9 |
| 73 | |||
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index 2aae06fcbed7..84a710f87c64 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu | |||
| @@ -92,6 +92,20 @@ Description: Discover NUMA node a CPU belongs to | |||
| 92 | /sys/devices/system/cpu/cpu42/node2 -> ../../node/node2 | 92 | /sys/devices/system/cpu/cpu42/node2 -> ../../node/node2 |
| 93 | 93 | ||
| 94 | 94 | ||
| 95 | What: /sys/devices/system/cpu/cpu#/node | ||
| 96 | Date: October 2009 | ||
| 97 | Contact: Linux memory management mailing list <linux-mm@kvack.org> | ||
| 98 | Description: Discover NUMA node a CPU belongs to | ||
| 99 | |||
| 100 | When CONFIG_NUMA is enabled, a symbolic link that points | ||
| 101 | to the corresponding NUMA node directory. | ||
| 102 | |||
| 103 | For example, the following symlink is created for cpu42 | ||
| 104 | in NUMA node 2: | ||
| 105 | |||
| 106 | /sys/devices/system/cpu/cpu42/node2 -> ../../node/node2 | ||
| 107 | |||
| 108 | |||
| 95 | What: /sys/devices/system/cpu/cpu#/topology/core_id | 109 | What: /sys/devices/system/cpu/cpu#/topology/core_id |
| 96 | /sys/devices/system/cpu/cpu#/topology/core_siblings | 110 | /sys/devices/system/cpu/cpu#/topology/core_siblings |
| 97 | /sys/devices/system/cpu/cpu#/topology/core_siblings_list | 111 | /sys/devices/system/cpu/cpu#/topology/core_siblings_list |
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index eb2c138c277c..21ab9357326d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
| @@ -291,15 +291,6 @@ Who: Michael Buesch <mb@bu3sch.de> | |||
| 291 | 291 | ||
| 292 | --------------------------- | 292 | --------------------------- |
| 293 | 293 | ||
| 294 | What: print_fn_descriptor_symbol() | ||
| 295 | When: October 2009 | ||
| 296 | Why: The %pF vsprintf format provides the same functionality in a | ||
| 297 | simpler way. print_fn_descriptor_symbol() is deprecated but | ||
| 298 | still present to give out-of-tree modules time to change. | ||
| 299 | Who: Bjorn Helgaas <bjorn.helgaas@hp.com> | ||
| 300 | |||
| 301 | --------------------------- | ||
| 302 | |||
| 303 | What: /sys/o2cb symlink | 294 | What: /sys/o2cb symlink |
| 304 | When: January 2010 | 295 | When: January 2010 |
| 305 | Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb | 296 | Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb |
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 94b9f2056f4c..220cc6376ef8 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
| @@ -38,6 +38,7 @@ Table of Contents | |||
| 38 | 3.3 /proc/<pid>/io - Display the IO accounting fields | 38 | 3.3 /proc/<pid>/io - Display the IO accounting fields |
| 39 | 3.4 /proc/<pid>/coredump_filter - Core dump filtering settings | 39 | 3.4 /proc/<pid>/coredump_filter - Core dump filtering settings |
| 40 | 3.5 /proc/<pid>/mountinfo - Information about mounts | 40 | 3.5 /proc/<pid>/mountinfo - Information about mounts |
| 41 | 3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm | ||
| 41 | 42 | ||
| 42 | 43 | ||
| 43 | ------------------------------------------------------------------------------ | 44 | ------------------------------------------------------------------------------ |
| @@ -1409,3 +1410,11 @@ For more information on mount propagation see: | |||
| 1409 | 1410 | ||
| 1410 | Documentation/filesystems/sharedsubtree.txt | 1411 | Documentation/filesystems/sharedsubtree.txt |
| 1411 | 1412 | ||
| 1413 | |||
| 1414 | 3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm | ||
| 1415 | -------------------------------------------------------- | ||
| 1416 | These files provide a method to access a tasks comm value. It also allows for | ||
| 1417 | a task to set its own or one of its thread siblings comm value. The comm value | ||
| 1418 | is limited in size compared to the cmdline value, so writing anything longer | ||
| 1419 | then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated | ||
| 1420 | comm value. | ||
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d index effe949a7282..06534f25e643 100644 --- a/Documentation/hwmon/lis3lv02d +++ b/Documentation/hwmon/lis3lv02d | |||
| @@ -3,7 +3,8 @@ Kernel driver lis3lv02d | |||
| 3 | 3 | ||
| 4 | Supported chips: | 4 | Supported chips: |
| 5 | 5 | ||
| 6 | * STMicroelectronics LIS3LV02DL and LIS3LV02DQ | 6 | * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision) |
| 7 | * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) | ||
| 7 | 8 | ||
| 8 | Authors: | 9 | Authors: |
| 9 | Yan Burman <burman.yan@gmail.com> | 10 | Yan Burman <burman.yan@gmail.com> |
| @@ -13,32 +14,52 @@ Authors: | |||
| 13 | Description | 14 | Description |
| 14 | ----------- | 15 | ----------- |
| 15 | 16 | ||
| 16 | This driver provides support for the accelerometer found in various HP | 17 | This driver provides support for the accelerometer found in various HP laptops |
| 17 | laptops sporting the feature officially called "HP Mobile Data | 18 | sporting the feature officially called "HP Mobile Data Protection System 3D" or |
| 18 | Protection System 3D" or "HP 3D DriveGuard". It detects automatically | 19 | "HP 3D DriveGuard". It detects automatically laptops with this sensor. Known |
| 19 | laptops with this sensor. Known models (for now the HP 2133, nc6420, | 20 | models (full list can be found in drivers/hwmon/hp_accel.c) will have their |
| 20 | nc2510, nc8510, nc84x0, nw9440 and nx9420) will have their axis | 21 | axis automatically oriented on standard way (eg: you can directly play |
| 21 | automatically oriented on standard way (eg: you can directly play | 22 | neverball). The accelerometer data is readable via |
| 22 | neverball). The accelerometer data is readable via | 23 | /sys/devices/platform/lis3lv02d. Reported values are scaled |
| 23 | /sys/devices/platform/lis3lv02d. | 24 | to mg values (1/1000th of earth gravity). |
| 24 | 25 | ||
| 25 | Sysfs attributes under /sys/devices/platform/lis3lv02d/: | 26 | Sysfs attributes under /sys/devices/platform/lis3lv02d/: |
| 26 | position - 3D position that the accelerometer reports. Format: "(x,y,z)" | 27 | position - 3D position that the accelerometer reports. Format: "(x,y,z)" |
| 27 | calibrate - read: values (x, y, z) that are used as the base for input | 28 | rate - read reports the sampling rate of the accelerometer device in HZ. |
| 28 | class device operation. | 29 | write changes sampling rate of the accelerometer device. |
| 29 | write: forces the base to be recalibrated with the current | 30 | Only values which are supported by HW are accepted. |
| 30 | position. | 31 | selftest - performs selftest for the chip as specified by chip manufacturer. |
| 31 | rate - reports the sampling rate of the accelerometer device in HZ | ||
| 32 | 32 | ||
| 33 | This driver also provides an absolute input class device, allowing | 33 | This driver also provides an absolute input class device, allowing |
| 34 | the laptop to act as a pinball machine-esque joystick. | 34 | the laptop to act as a pinball machine-esque joystick. Joystick device can be |
| 35 | calibrated. Joystick device can be in two different modes. | ||
| 36 | By default output values are scaled between -32768 .. 32767. In joystick raw | ||
| 37 | mode, joystick and sysfs position entry have the same scale. There can be | ||
| 38 | small difference due to input system fuzziness feature. | ||
| 39 | Events are also available as input event device. | ||
| 40 | |||
| 41 | Selftest is meant only for hardware diagnostic purposes. It is not meant to be | ||
| 42 | used during normal operations. Position data is not corrupted during selftest | ||
| 43 | but interrupt behaviour is not guaranteed to work reliably. In test mode, the | ||
| 44 | sensing element is internally moved little bit. Selftest measures difference | ||
| 45 | between normal mode and test mode. Chip specifications tell the acceptance | ||
| 46 | limit for each type of the chip. Limits are provided via platform data | ||
| 47 | to allow adjustment of the limits without a change to the actual driver. | ||
| 48 | Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are | ||
| 49 | measured difference between modes. Axes are not remapped in selftest mode. | ||
| 50 | Measurement values are provided to help HW diagnostic applications to make | ||
| 51 | final decision. | ||
| 52 | |||
| 53 | On HP laptops, if the led infrastructure is activated, support for a led | ||
| 54 | indicating disk protection will be provided as /sys/class/leds/hp::hddprotect. | ||
| 35 | 55 | ||
| 36 | Another feature of the driver is misc device called "freefall" that | 56 | Another feature of the driver is misc device called "freefall" that |
| 37 | acts similar to /dev/rtc and reacts on free-fall interrupts received | 57 | acts similar to /dev/rtc and reacts on free-fall interrupts received |
| 38 | from the device. It supports blocking operations, poll/select and | 58 | from the device. It supports blocking operations, poll/select and |
| 39 | fasync operation modes. You must read 1 bytes from the device. The | 59 | fasync operation modes. You must read 1 bytes from the device. The |
| 40 | result is number of free-fall interrupts since the last successful | 60 | result is number of free-fall interrupts since the last successful |
| 41 | read (or 255 if number of interrupts would not fit). | 61 | read (or 255 if number of interrupts would not fit). See the hpfall.c |
| 62 | file for an example on using the device. | ||
| 42 | 63 | ||
| 43 | 64 | ||
| 44 | Axes orientation | 65 | Axes orientation |
| @@ -55,7 +76,7 @@ the accelerometer are converted into a "standard" organisation of the axes | |||
| 55 | * If the laptop is put upside-down, Z becomes negative | 76 | * If the laptop is put upside-down, Z becomes negative |
| 56 | 77 | ||
| 57 | If your laptop model is not recognized (cf "dmesg"), you can send an | 78 | If your laptop model is not recognized (cf "dmesg"), you can send an |
| 58 | email to the authors to add it to the database. When reporting a new | 79 | email to the maintainer to add it to the database. When reporting a new |
| 59 | laptop, please include the output of "dmidecode" plus the value of | 80 | laptop, please include the output of "dmidecode" plus the value of |
| 60 | /sys/devices/platform/lis3lv02d/position in these four cases. | 81 | /sys/devices/platform/lis3lv02d/position in these four cases. |
| 61 | 82 | ||
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf index 02b74899edaf..b7e42ec4b26b 100644 --- a/Documentation/hwmon/w83627ehf +++ b/Documentation/hwmon/w83627ehf | |||
| @@ -81,8 +81,14 @@ pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range: | |||
| 81 | 0 (stop) to 255 (full) | 81 | 0 (stop) to 255 (full) |
| 82 | 82 | ||
| 83 | pwm[1-4]_enable - this file controls mode of fan/temperature control: | 83 | pwm[1-4]_enable - this file controls mode of fan/temperature control: |
| 84 | * 1 Manual Mode, write to pwm file any value 0-255 (full speed) | 84 | * 1 Manual mode, write to pwm file any value 0-255 (full speed) |
| 85 | * 2 Thermal Cruise | 85 | * 2 "Thermal Cruise" mode |
| 86 | * 3 "Fan Speed Cruise" mode | ||
| 87 | * 4 "Smart Fan III" mode | ||
| 88 | |||
| 89 | pwm[1-4]_mode - controls if output is PWM or DC level | ||
| 90 | * 0 DC output (0 - 12v) | ||
| 91 | * 1 PWM output | ||
| 86 | 92 | ||
| 87 | Thermal Cruise mode | 93 | Thermal Cruise mode |
| 88 | ------------------- | 94 | ------------------- |
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index 7860aafb483d..0a74603eb671 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients | |||
| @@ -44,7 +44,7 @@ static struct i2c_driver foo_driver = { | |||
| 44 | /* if device autodetection is needed: */ | 44 | /* if device autodetection is needed: */ |
| 45 | .class = I2C_CLASS_SOMETHING, | 45 | .class = I2C_CLASS_SOMETHING, |
| 46 | .detect = foo_detect, | 46 | .detect = foo_detect, |
| 47 | .address_data = &addr_data, | 47 | .address_list = normal_i2c, |
| 48 | 48 | ||
| 49 | .shutdown = foo_shutdown, /* optional */ | 49 | .shutdown = foo_shutdown, /* optional */ |
| 50 | .suspend = foo_suspend, /* optional */ | 50 | .suspend = foo_suspend, /* optional */ |
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt index bbc8a6a36921..57e7e9cc1870 100644 --- a/Documentation/memory-hotplug.txt +++ b/Documentation/memory-hotplug.txt | |||
| @@ -160,12 +160,15 @@ Under each section, you can see 4 files. | |||
| 160 | NOTE: | 160 | NOTE: |
| 161 | These directories/files appear after physical memory hotplug phase. | 161 | These directories/files appear after physical memory hotplug phase. |
| 162 | 162 | ||
| 163 | If CONFIG_NUMA is enabled the | 163 | If CONFIG_NUMA is enabled the memoryXXX/ directories can also be accessed |
| 164 | /sys/devices/system/memory/memoryXXX memory section | 164 | via symbolic links located in the /sys/devices/system/node/node* directories. |
| 165 | directories can also be accessed via symbolic links located in | 165 | |
| 166 | the /sys/devices/system/node/node* directories. For example: | 166 | For example: |
| 167 | /sys/devices/system/node/node0/memory9 -> ../../memory/memory9 | 167 | /sys/devices/system/node/node0/memory9 -> ../../memory/memory9 |
| 168 | 168 | ||
| 169 | A backlink will also be created: | ||
| 170 | /sys/devices/system/memory/memory9/node0 -> ../../node/node0 | ||
| 171 | |||
| 169 | -------------------------------- | 172 | -------------------------------- |
| 170 | 4. Physical memory hot-add phase | 173 | 4. Physical memory hot-add phase |
| 171 | -------------------------------- | 174 | -------------------------------- |
diff --git a/Documentation/misc-devices/ad525x_dpot.txt b/Documentation/misc-devices/ad525x_dpot.txt new file mode 100644 index 000000000000..0c9413b1cbf3 --- /dev/null +++ b/Documentation/misc-devices/ad525x_dpot.txt | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | --------------------------------- | ||
| 2 | AD525x Digital Potentiometers | ||
| 3 | --------------------------------- | ||
| 4 | |||
| 5 | The ad525x_dpot driver exports a simple sysfs interface. This allows you to | ||
| 6 | work with the immediate resistance settings as well as update the saved startup | ||
| 7 | settings. Access to the factory programmed tolerance is also provided, but | ||
| 8 | interpretation of this settings is required by the end application according to | ||
| 9 | the specific part in use. | ||
| 10 | |||
| 11 | --------- | ||
| 12 | Files | ||
| 13 | --------- | ||
| 14 | |||
| 15 | Each dpot device will have a set of eeprom, rdac, and tolerance files. How | ||
| 16 | many depends on the actual part you have, as will the range of allowed values. | ||
| 17 | |||
| 18 | The eeprom files are used to program the startup value of the device. | ||
| 19 | |||
| 20 | The rdac files are used to program the immediate value of the device. | ||
| 21 | |||
| 22 | The tolerance files are the read-only factory programmed tolerance settings | ||
| 23 | and may vary greatly on a part-by-part basis. For exact interpretation of | ||
| 24 | this field, please consult the datasheet for your part. This is presented | ||
| 25 | as a hex file for easier parsing. | ||
| 26 | |||
| 27 | ----------- | ||
| 28 | Example | ||
| 29 | ----------- | ||
| 30 | |||
| 31 | Locate the device in your sysfs tree. This is probably easiest by going into | ||
| 32 | the common i2c directory and locating the device by the i2c slave address. | ||
| 33 | |||
| 34 | # ls /sys/bus/i2c/devices/ | ||
| 35 | 0-0022 0-0027 0-002f | ||
| 36 | |||
| 37 | So assuming the device in question is on the first i2c bus and has the slave | ||
| 38 | address of 0x2f, we descend (unrelated sysfs entries have been trimmed). | ||
| 39 | |||
| 40 | # ls /sys/bus/i2c/devices/0-002f/ | ||
| 41 | eeprom0 rdac0 tolerance0 | ||
| 42 | |||
| 43 | You can use simple reads/writes to access these files: | ||
| 44 | |||
| 45 | # cd /sys/bus/i2c/devices/0-002f/ | ||
| 46 | |||
| 47 | # cat eeprom0 | ||
| 48 | 0 | ||
| 49 | # echo 10 > eeprom0 | ||
| 50 | # cat eeprom0 | ||
| 51 | 10 | ||
| 52 | |||
| 53 | # cat rdac0 | ||
| 54 | 5 | ||
| 55 | # echo 3 > rdac0 | ||
| 56 | # cat rdac0 | ||
| 57 | 3 | ||
diff --git a/Documentation/nommu-mmap.txt b/Documentation/nommu-mmap.txt index b565e8279d13..8e1ddec2c78a 100644 --- a/Documentation/nommu-mmap.txt +++ b/Documentation/nommu-mmap.txt | |||
| @@ -119,6 +119,32 @@ FURTHER NOTES ON NO-MMU MMAP | |||
| 119 | granule but will only discard the excess if appropriately configured as | 119 | granule but will only discard the excess if appropriately configured as |
| 120 | this has an effect on fragmentation. | 120 | this has an effect on fragmentation. |
| 121 | 121 | ||
| 122 | (*) The memory allocated by a request for an anonymous mapping will normally | ||
| 123 | be cleared by the kernel before being returned in accordance with the | ||
| 124 | Linux man pages (ver 2.22 or later). | ||
| 125 | |||
| 126 | In the MMU case this can be achieved with reasonable performance as | ||
| 127 | regions are backed by virtual pages, with the contents only being mapped | ||
| 128 | to cleared physical pages when a write happens on that specific page | ||
| 129 | (prior to which, the pages are effectively mapped to the global zero page | ||
| 130 | from which reads can take place). This spreads out the time it takes to | ||
| 131 | initialize the contents of a page - depending on the write-usage of the | ||
| 132 | mapping. | ||
| 133 | |||
| 134 | In the no-MMU case, however, anonymous mappings are backed by physical | ||
| 135 | pages, and the entire map is cleared at allocation time. This can cause | ||
| 136 | significant delays during a userspace malloc() as the C library does an | ||
| 137 | anonymous mapping and the kernel then does a memset for the entire map. | ||
| 138 | |||
| 139 | However, for memory that isn't required to be precleared - such as that | ||
| 140 | returned by malloc() - mmap() can take a MAP_UNINITIALIZED flag to | ||
| 141 | indicate to the kernel that it shouldn't bother clearing the memory before | ||
| 142 | returning it. Note that CONFIG_MMAP_ALLOW_UNINITIALIZED must be enabled | ||
| 143 | to permit this, otherwise the flag will be ignored. | ||
| 144 | |||
| 145 | uClibc uses this to speed up malloc(), and the ELF-FDPIC binfmt uses this | ||
| 146 | to allocate the brk and stack region. | ||
| 147 | |||
| 122 | (*) A list of all the private copy and anonymous mappings on the system is | 148 | (*) A list of all the private copy and anonymous mappings on the system is |
| 123 | visible through /proc/maps in no-MMU mode. | 149 | visible through /proc/maps in no-MMU mode. |
| 124 | 150 | ||
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index 82a7bd1800b2..bc31636973e3 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt | |||
| @@ -11,23 +11,21 @@ This optimization is more critical now as bigger and bigger physical memories | |||
| 11 | (several GBs) are more readily available. | 11 | (several GBs) are more readily available. |
| 12 | 12 | ||
| 13 | Users can use the huge page support in Linux kernel by either using the mmap | 13 | Users can use the huge page support in Linux kernel by either using the mmap |
| 14 | system call or standard SYSv shared memory system calls (shmget, shmat). | 14 | system call or standard SYSV shared memory system calls (shmget, shmat). |
| 15 | 15 | ||
| 16 | First the Linux kernel needs to be built with the CONFIG_HUGETLBFS | 16 | First the Linux kernel needs to be built with the CONFIG_HUGETLBFS |
| 17 | (present under "File systems") and CONFIG_HUGETLB_PAGE (selected | 17 | (present under "File systems") and CONFIG_HUGETLB_PAGE (selected |
| 18 | automatically when CONFIG_HUGETLBFS is selected) configuration | 18 | automatically when CONFIG_HUGETLBFS is selected) configuration |
| 19 | options. | 19 | options. |
| 20 | 20 | ||
| 21 | The kernel built with huge page support should show the number of configured | 21 | The /proc/meminfo file provides information about the total number of |
| 22 | huge pages in the system by running the "cat /proc/meminfo" command. | 22 | persistent hugetlb pages in the kernel's huge page pool. It also displays |
| 23 | information about the number of free, reserved and surplus huge pages and the | ||
| 24 | default huge page size. The huge page size is needed for generating the | ||
| 25 | proper alignment and size of the arguments to system calls that map huge page | ||
| 26 | regions. | ||
| 23 | 27 | ||
| 24 | /proc/meminfo also provides information about the total number of hugetlb | 28 | The output of "cat /proc/meminfo" will include lines like: |
| 25 | pages configured in the kernel. It also displays information about the | ||
| 26 | number of free hugetlb pages at any time. It also displays information about | ||
| 27 | the configured huge page size - this is needed for generating the proper | ||
| 28 | alignment and size of the arguments to the above system calls. | ||
| 29 | |||
| 30 | The output of "cat /proc/meminfo" will have lines like: | ||
| 31 | 29 | ||
| 32 | ..... | 30 | ..... |
| 33 | HugePages_Total: vvv | 31 | HugePages_Total: vvv |
| @@ -53,59 +51,63 @@ HugePages_Surp is short for "surplus," and is the number of huge pages in | |||
| 53 | /proc/filesystems should also show a filesystem of type "hugetlbfs" configured | 51 | /proc/filesystems should also show a filesystem of type "hugetlbfs" configured |
| 54 | in the kernel. | 52 | in the kernel. |
| 55 | 53 | ||
| 56 | /proc/sys/vm/nr_hugepages indicates the current number of configured hugetlb | 54 | /proc/sys/vm/nr_hugepages indicates the current number of "persistent" huge |
| 57 | pages in the kernel. Super user can dynamically request more (or free some | 55 | pages in the kernel's huge page pool. "Persistent" huge pages will be |
| 58 | pre-configured) huge pages. | 56 | returned to the huge page pool when freed by a task. A user with root |
| 59 | The allocation (or deallocation) of hugetlb pages is possible only if there are | 57 | privileges can dynamically allocate more or free some persistent huge pages |
| 60 | enough physically contiguous free pages in system (freeing of huge pages is | 58 | by increasing or decreasing the value of 'nr_hugepages'. |
| 61 | possible only if there are enough hugetlb pages free that can be transferred | ||
| 62 | back to regular memory pool). | ||
| 63 | 59 | ||
| 64 | Pages that are used as hugetlb pages are reserved inside the kernel and cannot | 60 | Pages that are used as huge pages are reserved inside the kernel and cannot |
| 65 | be used for other purposes. | 61 | be used for other purposes. Huge pages cannot be swapped out under |
| 62 | memory pressure. | ||
| 66 | 63 | ||
| 67 | Once the kernel with Hugetlb page support is built and running, a user can | 64 | Once a number of huge pages have been pre-allocated to the kernel huge page |
| 68 | use either the mmap system call or shared memory system calls to start using | 65 | pool, a user with appropriate privilege can use either the mmap system call |
| 69 | the huge pages. It is required that the system administrator preallocate | 66 | or shared memory system calls to use the huge pages. See the discussion of |
| 70 | enough memory for huge page purposes. | 67 | Using Huge Pages, below. |
| 71 | 68 | ||
| 72 | The administrator can preallocate huge pages on the kernel boot command line by | 69 | The administrator can allocate persistent huge pages on the kernel boot |
| 73 | specifying the "hugepages=N" parameter, where 'N' = the number of huge pages | 70 | command line by specifying the "hugepages=N" parameter, where 'N' = the |
| 74 | requested. This is the most reliable method for preallocating huge pages as | 71 | number of huge pages requested. This is the most reliable method of |
| 75 | memory has not yet become fragmented. | 72 | allocating huge pages as memory has not yet become fragmented. |
| 76 | 73 | ||
| 77 | Some platforms support multiple huge page sizes. To preallocate huge pages | 74 | Some platforms support multiple huge page sizes. To allocate huge pages |
| 78 | of a specific size, one must preceed the huge pages boot command parameters | 75 | of a specific size, one must preceed the huge pages boot command parameters |
| 79 | with a huge page size selection parameter "hugepagesz=<size>". <size> must | 76 | with a huge page size selection parameter "hugepagesz=<size>". <size> must |
| 80 | be specified in bytes with optional scale suffix [kKmMgG]. The default huge | 77 | be specified in bytes with optional scale suffix [kKmMgG]. The default huge |
| 81 | page size may be selected with the "default_hugepagesz=<size>" boot parameter. | 78 | page size may be selected with the "default_hugepagesz=<size>" boot parameter. |
| 82 | 79 | ||
| 83 | /proc/sys/vm/nr_hugepages indicates the current number of configured [default | 80 | When multiple huge page sizes are supported, /proc/sys/vm/nr_hugepages |
| 84 | size] hugetlb pages in the kernel. Super user can dynamically request more | 81 | indicates the current number of pre-allocated huge pages of the default size. |
| 85 | (or free some pre-configured) huge pages. | 82 | Thus, one can use the following command to dynamically allocate/deallocate |
| 86 | 83 | default sized persistent huge pages: | |
| 87 | Use the following command to dynamically allocate/deallocate default sized | ||
| 88 | huge pages: | ||
| 89 | 84 | ||
| 90 | echo 20 > /proc/sys/vm/nr_hugepages | 85 | echo 20 > /proc/sys/vm/nr_hugepages |
| 91 | 86 | ||
| 92 | This command will try to configure 20 default sized huge pages in the system. | 87 | This command will try to adjust the number of default sized huge pages in the |
| 88 | huge page pool to 20, allocating or freeing huge pages, as required. | ||
| 89 | |||
| 93 | On a NUMA platform, the kernel will attempt to distribute the huge page pool | 90 | On a NUMA platform, the kernel will attempt to distribute the huge page pool |
| 94 | over the all on-line nodes. These huge pages, allocated when nr_hugepages | 91 | over all the set of allowed nodes specified by the NUMA memory policy of the |
| 95 | is increased, are called "persistent huge pages". | 92 | task that modifies nr_hugepages. The default for the allowed nodes--when the |
| 93 | task has default memory policy--is all on-line nodes with memory. Allowed | ||
| 94 | nodes with insufficient available, contiguous memory for a huge page will be | ||
| 95 | silently skipped when allocating persistent huge pages. See the discussion | ||
| 96 | below of the interaction of task memory policy, cpusets and per node attributes | ||
| 97 | with the allocation and freeing of persistent huge pages. | ||
| 96 | 98 | ||
| 97 | The success or failure of huge page allocation depends on the amount of | 99 | The success or failure of huge page allocation depends on the amount of |
| 98 | physically contiguous memory that is preset in system at the time of the | 100 | physically contiguous memory that is present in system at the time of the |
| 99 | allocation attempt. If the kernel is unable to allocate huge pages from | 101 | allocation attempt. If the kernel is unable to allocate huge pages from |
| 100 | some nodes in a NUMA system, it will attempt to make up the difference by | 102 | some nodes in a NUMA system, it will attempt to make up the difference by |
| 101 | allocating extra pages on other nodes with sufficient available contiguous | 103 | allocating extra pages on other nodes with sufficient available contiguous |
| 102 | memory, if any. | 104 | memory, if any. |
| 103 | 105 | ||
| 104 | System administrators may want to put this command in one of the local rc init | 106 | System administrators may want to put this command in one of the local rc |
| 105 | files. This will enable the kernel to request huge pages early in the boot | 107 | init files. This will enable the kernel to allocate huge pages early in |
| 106 | process when the possibility of getting physical contiguous pages is still | 108 | the boot process when the possibility of getting physical contiguous pages |
| 107 | very high. Administrators can verify the number of huge pages actually | 109 | is still very high. Administrators can verify the number of huge pages |
| 108 | allocated by checking the sysctl or meminfo. To check the per node | 110 | actually allocated by checking the sysctl or meminfo. To check the per node |
| 109 | distribution of huge pages in a NUMA system, use: | 111 | distribution of huge pages in a NUMA system, use: |
| 110 | 112 | ||
| 111 | cat /sys/devices/system/node/node*/meminfo | fgrep Huge | 113 | cat /sys/devices/system/node/node*/meminfo | fgrep Huge |
| @@ -113,45 +115,47 @@ distribution of huge pages in a NUMA system, use: | |||
| 113 | /proc/sys/vm/nr_overcommit_hugepages specifies how large the pool of | 115 | /proc/sys/vm/nr_overcommit_hugepages specifies how large the pool of |
| 114 | huge pages can grow, if more huge pages than /proc/sys/vm/nr_hugepages are | 116 | huge pages can grow, if more huge pages than /proc/sys/vm/nr_hugepages are |
| 115 | requested by applications. Writing any non-zero value into this file | 117 | requested by applications. Writing any non-zero value into this file |
| 116 | indicates that the hugetlb subsystem is allowed to try to obtain "surplus" | 118 | indicates that the hugetlb subsystem is allowed to try to obtain that |
| 117 | huge pages from the buddy allocator, when the normal pool is exhausted. As | 119 | number of "surplus" huge pages from the kernel's normal page pool, when the |
| 118 | these surplus huge pages go out of use, they are freed back to the buddy | 120 | persistent huge page pool is exhausted. As these surplus huge pages become |
| 119 | allocator. | 121 | unused, they are freed back to the kernel's normal page pool. |
| 120 | 122 | ||
| 121 | When increasing the huge page pool size via nr_hugepages, any surplus | 123 | When increasing the huge page pool size via nr_hugepages, any existing surplus |
| 122 | pages will first be promoted to persistent huge pages. Then, additional | 124 | pages will first be promoted to persistent huge pages. Then, additional |
| 123 | huge pages will be allocated, if necessary and if possible, to fulfill | 125 | huge pages will be allocated, if necessary and if possible, to fulfill |
| 124 | the new huge page pool size. | 126 | the new persistent huge page pool size. |
| 125 | 127 | ||
| 126 | The administrator may shrink the pool of preallocated huge pages for | 128 | The administrator may shrink the pool of persistent huge pages for |
| 127 | the default huge page size by setting the nr_hugepages sysctl to a | 129 | the default huge page size by setting the nr_hugepages sysctl to a |
| 128 | smaller value. The kernel will attempt to balance the freeing of huge pages | 130 | smaller value. The kernel will attempt to balance the freeing of huge pages |
| 129 | across all on-line nodes. Any free huge pages on the selected nodes will | 131 | across all nodes in the memory policy of the task modifying nr_hugepages. |
| 130 | be freed back to the buddy allocator. | 132 | Any free huge pages on the selected nodes will be freed back to the kernel's |
| 131 | 133 | normal page pool. | |
| 132 | Caveat: Shrinking the pool via nr_hugepages such that it becomes less | 134 | |
| 133 | than the number of huge pages in use will convert the balance to surplus | 135 | Caveat: Shrinking the persistent huge page pool via nr_hugepages such that |
| 134 | huge pages even if it would exceed the overcommit value. As long as | 136 | it becomes less than the number of huge pages in use will convert the balance |
| 135 | this condition holds, however, no more surplus huge pages will be | 137 | of the in-use huge pages to surplus huge pages. This will occur even if |
| 136 | allowed on the system until one of the two sysctls are increased | 138 | the number of surplus pages it would exceed the overcommit value. As long as |
| 137 | sufficiently, or the surplus huge pages go out of use and are freed. | 139 | this condition holds--that is, until nr_hugepages+nr_overcommit_hugepages is |
| 140 | increased sufficiently, or the surplus huge pages go out of use and are freed-- | ||
| 141 | no more surplus huge pages will be allowed to be allocated. | ||
| 138 | 142 | ||
| 139 | With support for multiple huge page pools at run-time available, much of | 143 | With support for multiple huge page pools at run-time available, much of |
| 140 | the huge page userspace interface has been duplicated in sysfs. The above | 144 | the huge page userspace interface in /proc/sys/vm has been duplicated in sysfs. |
| 141 | information applies to the default huge page size which will be | 145 | The /proc interfaces discussed above have been retained for backwards |
| 142 | controlled by the /proc interfaces for backwards compatibility. The root | 146 | compatibility. The root huge page control directory in sysfs is: |
| 143 | huge page control directory in sysfs is: | ||
| 144 | 147 | ||
| 145 | /sys/kernel/mm/hugepages | 148 | /sys/kernel/mm/hugepages |
| 146 | 149 | ||
| 147 | For each huge page size supported by the running kernel, a subdirectory | 150 | For each huge page size supported by the running kernel, a subdirectory |
| 148 | will exist, of the form | 151 | will exist, of the form: |
| 149 | 152 | ||
| 150 | hugepages-${size}kB | 153 | hugepages-${size}kB |
| 151 | 154 | ||
| 152 | Inside each of these directories, the same set of files will exist: | 155 | Inside each of these directories, the same set of files will exist: |
| 153 | 156 | ||
| 154 | nr_hugepages | 157 | nr_hugepages |
| 158 | nr_hugepages_mempolicy | ||
| 155 | nr_overcommit_hugepages | 159 | nr_overcommit_hugepages |
| 156 | free_hugepages | 160 | free_hugepages |
| 157 | resv_hugepages | 161 | resv_hugepages |
| @@ -159,6 +163,102 @@ Inside each of these directories, the same set of files will exist: | |||
| 159 | 163 | ||
| 160 | which function as described above for the default huge page-sized case. | 164 | which function as described above for the default huge page-sized case. |
| 161 | 165 | ||
| 166 | |||
| 167 | Interaction of Task Memory Policy with Huge Page Allocation/Freeing | ||
| 168 | |||
| 169 | Whether huge pages are allocated and freed via the /proc interface or | ||
| 170 | the /sysfs interface using the nr_hugepages_mempolicy attribute, the NUMA | ||
| 171 | nodes from which huge pages are allocated or freed are controlled by the | ||
| 172 | NUMA memory policy of the task that modifies the nr_hugepages_mempolicy | ||
| 173 | sysctl or attribute. When the nr_hugepages attribute is used, mempolicy | ||
| 174 | is ignored. | ||
| 175 | |||
| 176 | The recommended method to allocate or free huge pages to/from the kernel | ||
| 177 | huge page pool, using the nr_hugepages example above, is: | ||
| 178 | |||
| 179 | numactl --interleave <node-list> echo 20 \ | ||
| 180 | >/proc/sys/vm/nr_hugepages_mempolicy | ||
| 181 | |||
| 182 | or, more succinctly: | ||
| 183 | |||
| 184 | numactl -m <node-list> echo 20 >/proc/sys/vm/nr_hugepages_mempolicy | ||
| 185 | |||
| 186 | This will allocate or free abs(20 - nr_hugepages) to or from the nodes | ||
| 187 | specified in <node-list>, depending on whether number of persistent huge pages | ||
| 188 | is initially less than or greater than 20, respectively. No huge pages will be | ||
| 189 | allocated nor freed on any node not included in the specified <node-list>. | ||
| 190 | |||
| 191 | When adjusting the persistent hugepage count via nr_hugepages_mempolicy, any | ||
| 192 | memory policy mode--bind, preferred, local or interleave--may be used. The | ||
| 193 | resulting effect on persistent huge page allocation is as follows: | ||
| 194 | |||
| 195 | 1) Regardless of mempolicy mode [see Documentation/vm/numa_memory_policy.txt], | ||
| 196 | persistent huge pages will be distributed across the node or nodes | ||
| 197 | specified in the mempolicy as if "interleave" had been specified. | ||
| 198 | However, if a node in the policy does not contain sufficient contiguous | ||
| 199 | memory for a huge page, the allocation will not "fallback" to the nearest | ||
| 200 | neighbor node with sufficient contiguous memory. To do this would cause | ||
| 201 | undesirable imbalance in the distribution of the huge page pool, or | ||
| 202 | possibly, allocation of persistent huge pages on nodes not allowed by | ||
| 203 | the task's memory policy. | ||
| 204 | |||
| 205 | 2) One or more nodes may be specified with the bind or interleave policy. | ||
| 206 | If more than one node is specified with the preferred policy, only the | ||
| 207 | lowest numeric id will be used. Local policy will select the node where | ||
| 208 | the task is running at the time the nodes_allowed mask is constructed. | ||
| 209 | For local policy to be deterministic, the task must be bound to a cpu or | ||
| 210 | cpus in a single node. Otherwise, the task could be migrated to some | ||
| 211 | other node at any time after launch and the resulting node will be | ||
| 212 | indeterminate. Thus, local policy is not very useful for this purpose. | ||
| 213 | Any of the other mempolicy modes may be used to specify a single node. | ||
| 214 | |||
| 215 | 3) The nodes allowed mask will be derived from any non-default task mempolicy, | ||
| 216 | whether this policy was set explicitly by the task itself or one of its | ||
| 217 | ancestors, such as numactl. This means that if the task is invoked from a | ||
| 218 | shell with non-default policy, that policy will be used. One can specify a | ||
| 219 | node list of "all" with numactl --interleave or --membind [-m] to achieve | ||
| 220 | interleaving over all nodes in the system or cpuset. | ||
| 221 | |||
| 222 | 4) Any task mempolicy specifed--e.g., using numactl--will be constrained by | ||
| 223 | the resource limits of any cpuset in which the task runs. Thus, there will | ||
| 224 | be no way for a task with non-default policy running in a cpuset with a | ||
| 225 | subset of the system nodes to allocate huge pages outside the cpuset | ||
| 226 | without first moving to a cpuset that contains all of the desired nodes. | ||
| 227 | |||
| 228 | 5) Boot-time huge page allocation attempts to distribute the requested number | ||
| 229 | of huge pages over all on-lines nodes with memory. | ||
| 230 | |||
| 231 | Per Node Hugepages Attributes | ||
| 232 | |||
| 233 | A subset of the contents of the root huge page control directory in sysfs, | ||
| 234 | described above, will be replicated under each the system device of each | ||
| 235 | NUMA node with memory in: | ||
| 236 | |||
| 237 | /sys/devices/system/node/node[0-9]*/hugepages/ | ||
| 238 | |||
| 239 | Under this directory, the subdirectory for each supported huge page size | ||
| 240 | contains the following attribute files: | ||
| 241 | |||
| 242 | nr_hugepages | ||
| 243 | free_hugepages | ||
| 244 | surplus_hugepages | ||
| 245 | |||
| 246 | The free_' and surplus_' attribute files are read-only. They return the number | ||
| 247 | of free and surplus [overcommitted] huge pages, respectively, on the parent | ||
| 248 | node. | ||
| 249 | |||
| 250 | The nr_hugepages attribute returns the total number of huge pages on the | ||
| 251 | specified node. When this attribute is written, the number of persistent huge | ||
| 252 | pages on the parent node will be adjusted to the specified value, if sufficient | ||
| 253 | resources exist, regardless of the task's mempolicy or cpuset constraints. | ||
| 254 | |||
| 255 | Note that the number of overcommit and reserve pages remain global quantities, | ||
| 256 | as we don't know until fault time, when the faulting task's mempolicy is | ||
| 257 | applied, from which node the huge page allocation will be attempted. | ||
| 258 | |||
| 259 | |||
| 260 | Using Huge Pages | ||
| 261 | |||
| 162 | If the user applications are going to request huge pages using mmap system | 262 | If the user applications are going to request huge pages using mmap system |
| 163 | call, then it is required that system administrator mount a file system of | 263 | call, then it is required that system administrator mount a file system of |
| 164 | type hugetlbfs: | 264 | type hugetlbfs: |
| @@ -206,9 +306,11 @@ map_hugetlb.c. | |||
| 206 | * requesting huge pages. | 306 | * requesting huge pages. |
| 207 | * | 307 | * |
| 208 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for | 308 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for |
| 209 | * huge pages. That means the addresses starting with 0x800000... will need | 309 | * huge pages. That means that if one requires a fixed address, a huge page |
| 210 | * to be specified. Specifying a fixed address is not required on ppc64, | 310 | * aligned address starting with 0x800000... will be required. If a fixed |
| 211 | * i386 or x86_64. | 311 | * address is not required, the kernel will select an address in the proper |
| 312 | * range. | ||
| 313 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
| 212 | * | 314 | * |
| 213 | * Note: The default shared memory limit is quite low on many kernels, | 315 | * Note: The default shared memory limit is quite low on many kernels, |
| 214 | * you may need to increase it via: | 316 | * you may need to increase it via: |
| @@ -237,14 +339,8 @@ map_hugetlb.c. | |||
| 237 | 339 | ||
| 238 | #define dprintf(x) printf(x) | 340 | #define dprintf(x) printf(x) |
| 239 | 341 | ||
| 240 | /* Only ia64 requires this */ | 342 | #define ADDR (void *)(0x0UL) /* let kernel choose address */ |
| 241 | #ifdef __ia64__ | ||
| 242 | #define ADDR (void *)(0x8000000000000000UL) | ||
| 243 | #define SHMAT_FLAGS (SHM_RND) | ||
| 244 | #else | ||
| 245 | #define ADDR (void *)(0x0UL) | ||
| 246 | #define SHMAT_FLAGS (0) | 343 | #define SHMAT_FLAGS (0) |
| 247 | #endif | ||
| 248 | 344 | ||
| 249 | int main(void) | 345 | int main(void) |
| 250 | { | 346 | { |
| @@ -302,10 +398,12 @@ int main(void) | |||
| 302 | * example, the app is requesting memory of size 256MB that is backed by | 398 | * example, the app is requesting memory of size 256MB that is backed by |
| 303 | * huge pages. | 399 | * huge pages. |
| 304 | * | 400 | * |
| 305 | * For ia64 architecture, Linux kernel reserves Region number 4 for huge pages. | 401 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for |
| 306 | * That means the addresses starting with 0x800000... will need to be | 402 | * huge pages. That means that if one requires a fixed address, a huge page |
| 307 | * specified. Specifying a fixed address is not required on ppc64, i386 | 403 | * aligned address starting with 0x800000... will be required. If a fixed |
| 308 | * or x86_64. | 404 | * address is not required, the kernel will select an address in the proper |
| 405 | * range. | ||
| 406 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. | ||
| 309 | */ | 407 | */ |
| 310 | #include <stdlib.h> | 408 | #include <stdlib.h> |
| 311 | #include <stdio.h> | 409 | #include <stdio.h> |
| @@ -317,14 +415,8 @@ int main(void) | |||
| 317 | #define LENGTH (256UL*1024*1024) | 415 | #define LENGTH (256UL*1024*1024) |
| 318 | #define PROTECTION (PROT_READ | PROT_WRITE) | 416 | #define PROTECTION (PROT_READ | PROT_WRITE) |
| 319 | 417 | ||
| 320 | /* Only ia64 requires this */ | 418 | #define ADDR (void *)(0x0UL) /* let kernel choose address */ |
| 321 | #ifdef __ia64__ | ||
| 322 | #define ADDR (void *)(0x8000000000000000UL) | ||
| 323 | #define FLAGS (MAP_SHARED | MAP_FIXED) | ||
| 324 | #else | ||
| 325 | #define ADDR (void *)(0x0UL) | ||
| 326 | #define FLAGS (MAP_SHARED) | 419 | #define FLAGS (MAP_SHARED) |
| 327 | #endif | ||
| 328 | 420 | ||
| 329 | void check_bytes(char *addr) | 421 | void check_bytes(char *addr) |
| 330 | { | 422 | { |
diff --git a/Documentation/vm/ksm.txt b/Documentation/vm/ksm.txt index 262d8e6793a3..b392e496f816 100644 --- a/Documentation/vm/ksm.txt +++ b/Documentation/vm/ksm.txt | |||
| @@ -16,9 +16,9 @@ by sharing the data common between them. But it can be useful to any | |||
| 16 | application which generates many instances of the same data. | 16 | application which generates many instances of the same data. |
| 17 | 17 | ||
| 18 | KSM only merges anonymous (private) pages, never pagecache (file) pages. | 18 | KSM only merges anonymous (private) pages, never pagecache (file) pages. |
| 19 | KSM's merged pages are at present locked into kernel memory for as long | 19 | KSM's merged pages were originally locked into kernel memory, but can now |
| 20 | as they are shared: so cannot be swapped out like the user pages they | 20 | be swapped out just like other user pages (but sharing is broken when they |
| 21 | replace (but swapping KSM pages should follow soon in a later release). | 21 | are swapped back in: ksmd must rediscover their identity and merge again). |
| 22 | 22 | ||
| 23 | KSM only operates on those areas of address space which an application | 23 | KSM only operates on those areas of address space which an application |
| 24 | has advised to be likely candidates for merging, by using the madvise(2) | 24 | has advised to be likely candidates for merging, by using the madvise(2) |
| @@ -44,20 +44,12 @@ includes unmapped gaps (though working on the intervening mapped areas), | |||
| 44 | and might fail with EAGAIN if not enough memory for internal structures. | 44 | and might fail with EAGAIN if not enough memory for internal structures. |
| 45 | 45 | ||
| 46 | Applications should be considerate in their use of MADV_MERGEABLE, | 46 | Applications should be considerate in their use of MADV_MERGEABLE, |
| 47 | restricting its use to areas likely to benefit. KSM's scans may use | 47 | restricting its use to areas likely to benefit. KSM's scans may use a lot |
| 48 | a lot of processing power, and its kernel-resident pages are a limited | 48 | of processing power: some installations will disable KSM for that reason. |
| 49 | resource. Some installations will disable KSM for these reasons. | ||
| 50 | 49 | ||
| 51 | The KSM daemon is controlled by sysfs files in /sys/kernel/mm/ksm/, | 50 | The KSM daemon is controlled by sysfs files in /sys/kernel/mm/ksm/, |
| 52 | readable by all but writable only by root: | 51 | readable by all but writable only by root: |
| 53 | 52 | ||
| 54 | max_kernel_pages - set to maximum number of kernel pages that KSM may use | ||
| 55 | e.g. "echo 100000 > /sys/kernel/mm/ksm/max_kernel_pages" | ||
| 56 | Value 0 imposes no limit on the kernel pages KSM may use; | ||
| 57 | but note that any process using MADV_MERGEABLE can cause | ||
| 58 | KSM to allocate these pages, unswappable until it exits. | ||
| 59 | Default: quarter of memory (chosen to not pin too much) | ||
| 60 | |||
| 61 | pages_to_scan - how many present pages to scan before ksmd goes to sleep | 53 | pages_to_scan - how many present pages to scan before ksmd goes to sleep |
| 62 | e.g. "echo 100 > /sys/kernel/mm/ksm/pages_to_scan" | 54 | e.g. "echo 100 > /sys/kernel/mm/ksm/pages_to_scan" |
| 63 | Default: 100 (chosen for demonstration purposes) | 55 | Default: 100 (chosen for demonstration purposes) |
| @@ -75,7 +67,7 @@ run - set 0 to stop ksmd from running but keep merged pages, | |||
| 75 | 67 | ||
| 76 | The effectiveness of KSM and MADV_MERGEABLE is shown in /sys/kernel/mm/ksm/: | 68 | The effectiveness of KSM and MADV_MERGEABLE is shown in /sys/kernel/mm/ksm/: |
| 77 | 69 | ||
| 78 | pages_shared - how many shared unswappable kernel pages KSM is using | 70 | pages_shared - how many shared pages are being used |
| 79 | pages_sharing - how many more sites are sharing them i.e. how much saved | 71 | pages_sharing - how many more sites are sharing them i.e. how much saved |
| 80 | pages_unshared - how many pages unique but repeatedly checked for merging | 72 | pages_unshared - how many pages unique but repeatedly checked for merging |
| 81 | pages_volatile - how many pages changing too fast to be placed in a tree | 73 | pages_volatile - how many pages changing too fast to be placed in a tree |
| @@ -87,4 +79,4 @@ pages_volatile embraces several different kinds of activity, but a high | |||
| 87 | proportion there would also indicate poor use of madvise MADV_MERGEABLE. | 79 | proportion there would also indicate poor use of madvise MADV_MERGEABLE. |
| 88 | 80 | ||
| 89 | Izik Eidus, | 81 | Izik Eidus, |
| 90 | Hugh Dickins, 24 Sept 2009 | 82 | Hugh Dickins, 17 Nov 2009 |
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c index ea44ea502da1..7a7d9bab32ef 100644 --- a/Documentation/vm/page-types.c +++ b/Documentation/vm/page-types.c | |||
| @@ -100,7 +100,7 @@ | |||
| 100 | #define BIT(name) (1ULL << KPF_##name) | 100 | #define BIT(name) (1ULL << KPF_##name) |
| 101 | #define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL)) | 101 | #define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL)) |
| 102 | 102 | ||
| 103 | static char *page_flag_names[] = { | 103 | static const char *page_flag_names[] = { |
| 104 | [KPF_LOCKED] = "L:locked", | 104 | [KPF_LOCKED] = "L:locked", |
| 105 | [KPF_ERROR] = "E:error", | 105 | [KPF_ERROR] = "E:error", |
| 106 | [KPF_REFERENCED] = "R:referenced", | 106 | [KPF_REFERENCED] = "R:referenced", |
| @@ -173,7 +173,7 @@ static int kpageflags_fd; | |||
| 173 | static int opt_hwpoison; | 173 | static int opt_hwpoison; |
| 174 | static int opt_unpoison; | 174 | static int opt_unpoison; |
| 175 | 175 | ||
| 176 | static char *hwpoison_debug_fs = "/debug/hwpoison"; | 176 | static const char hwpoison_debug_fs[] = "/debug/hwpoison"; |
| 177 | static int hwpoison_inject_fd; | 177 | static int hwpoison_inject_fd; |
| 178 | static int hwpoison_forget_fd; | 178 | static int hwpoison_forget_fd; |
| 179 | 179 | ||
| @@ -560,7 +560,7 @@ static void walk_pfn(unsigned long voffset, | |||
| 560 | { | 560 | { |
| 561 | uint64_t buf[KPAGEFLAGS_BATCH]; | 561 | uint64_t buf[KPAGEFLAGS_BATCH]; |
| 562 | unsigned long batch; | 562 | unsigned long batch; |
| 563 | unsigned long pages; | 563 | long pages; |
| 564 | unsigned long i; | 564 | unsigned long i; |
| 565 | 565 | ||
| 566 | while (count) { | 566 | while (count) { |
| @@ -673,30 +673,35 @@ static void usage(void) | |||
| 673 | 673 | ||
| 674 | printf( | 674 | printf( |
| 675 | "page-types [options]\n" | 675 | "page-types [options]\n" |
| 676 | " -r|--raw Raw mode, for kernel developers\n" | 676 | " -r|--raw Raw mode, for kernel developers\n" |
| 677 | " -a|--addr addr-spec Walk a range of pages\n" | 677 | " -d|--describe flags Describe flags\n" |
| 678 | " -b|--bits bits-spec Walk pages with specified bits\n" | 678 | " -a|--addr addr-spec Walk a range of pages\n" |
| 679 | " -p|--pid pid Walk process address space\n" | 679 | " -b|--bits bits-spec Walk pages with specified bits\n" |
| 680 | " -p|--pid pid Walk process address space\n" | ||
| 680 | #if 0 /* planned features */ | 681 | #if 0 /* planned features */ |
| 681 | " -f|--file filename Walk file address space\n" | 682 | " -f|--file filename Walk file address space\n" |
| 682 | #endif | 683 | #endif |
| 683 | " -l|--list Show page details in ranges\n" | 684 | " -l|--list Show page details in ranges\n" |
| 684 | " -L|--list-each Show page details one by one\n" | 685 | " -L|--list-each Show page details one by one\n" |
| 685 | " -N|--no-summary Don't show summay info\n" | 686 | " -N|--no-summary Don't show summay info\n" |
| 686 | " -X|--hwpoison hwpoison pages\n" | 687 | " -X|--hwpoison hwpoison pages\n" |
| 687 | " -x|--unpoison unpoison pages\n" | 688 | " -x|--unpoison unpoison pages\n" |
| 688 | " -h|--help Show this usage message\n" | 689 | " -h|--help Show this usage message\n" |
| 690 | "flags:\n" | ||
| 691 | " 0x10 bitfield format, e.g.\n" | ||
| 692 | " anon bit-name, e.g.\n" | ||
| 693 | " 0x10,anon comma-separated list, e.g.\n" | ||
| 689 | "addr-spec:\n" | 694 | "addr-spec:\n" |
| 690 | " N one page at offset N (unit: pages)\n" | 695 | " N one page at offset N (unit: pages)\n" |
| 691 | " N+M pages range from N to N+M-1\n" | 696 | " N+M pages range from N to N+M-1\n" |
| 692 | " N,M pages range from N to M-1\n" | 697 | " N,M pages range from N to M-1\n" |
| 693 | " N, pages range from N to end\n" | 698 | " N, pages range from N to end\n" |
| 694 | " ,M pages range from 0 to M-1\n" | 699 | " ,M pages range from 0 to M-1\n" |
| 695 | "bits-spec:\n" | 700 | "bits-spec:\n" |
| 696 | " bit1,bit2 (flags & (bit1|bit2)) != 0\n" | 701 | " bit1,bit2 (flags & (bit1|bit2)) != 0\n" |
| 697 | " bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1\n" | 702 | " bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1\n" |
| 698 | " bit1,~bit2 (flags & (bit1|bit2)) == bit1\n" | 703 | " bit1,~bit2 (flags & (bit1|bit2)) == bit1\n" |
| 699 | " =bit1,bit2 flags == (bit1|bit2)\n" | 704 | " =bit1,bit2 flags == (bit1|bit2)\n" |
| 700 | "bit-names:\n" | 705 | "bit-names:\n" |
| 701 | ); | 706 | ); |
| 702 | 707 | ||
| @@ -884,13 +889,23 @@ static void parse_bits_mask(const char *optarg) | |||
| 884 | add_bits_filter(mask, bits); | 889 | add_bits_filter(mask, bits); |
| 885 | } | 890 | } |
| 886 | 891 | ||
| 892 | static void describe_flags(const char *optarg) | ||
| 893 | { | ||
| 894 | uint64_t flags = parse_flag_names(optarg, 0); | ||
| 887 | 895 | ||
| 888 | static struct option opts[] = { | 896 | printf("0x%016llx\t%s\t%s\n", |
| 897 | (unsigned long long)flags, | ||
| 898 | page_flag_name(flags), | ||
| 899 | page_flag_longname(flags)); | ||
| 900 | } | ||
| 901 | |||
| 902 | static const struct option opts[] = { | ||
| 889 | { "raw" , 0, NULL, 'r' }, | 903 | { "raw" , 0, NULL, 'r' }, |
| 890 | { "pid" , 1, NULL, 'p' }, | 904 | { "pid" , 1, NULL, 'p' }, |
| 891 | { "file" , 1, NULL, 'f' }, | 905 | { "file" , 1, NULL, 'f' }, |
| 892 | { "addr" , 1, NULL, 'a' }, | 906 | { "addr" , 1, NULL, 'a' }, |
| 893 | { "bits" , 1, NULL, 'b' }, | 907 | { "bits" , 1, NULL, 'b' }, |
| 908 | { "describe" , 1, NULL, 'd' }, | ||
| 894 | { "list" , 0, NULL, 'l' }, | 909 | { "list" , 0, NULL, 'l' }, |
| 895 | { "list-each" , 0, NULL, 'L' }, | 910 | { "list-each" , 0, NULL, 'L' }, |
| 896 | { "no-summary", 0, NULL, 'N' }, | 911 | { "no-summary", 0, NULL, 'N' }, |
| @@ -907,7 +922,7 @@ int main(int argc, char *argv[]) | |||
| 907 | page_size = getpagesize(); | 922 | page_size = getpagesize(); |
| 908 | 923 | ||
| 909 | while ((c = getopt_long(argc, argv, | 924 | while ((c = getopt_long(argc, argv, |
| 910 | "rp:f:a:b:lLNXxh", opts, NULL)) != -1) { | 925 | "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) { |
| 911 | switch (c) { | 926 | switch (c) { |
| 912 | case 'r': | 927 | case 'r': |
| 913 | opt_raw = 1; | 928 | opt_raw = 1; |
| @@ -924,6 +939,9 @@ int main(int argc, char *argv[]) | |||
| 924 | case 'b': | 939 | case 'b': |
| 925 | parse_bits_mask(optarg); | 940 | parse_bits_mask(optarg); |
| 926 | break; | 941 | break; |
| 942 | case 'd': | ||
| 943 | describe_flags(optarg); | ||
| 944 | exit(0); | ||
| 927 | case 'l': | 945 | case 'l': |
| 928 | opt_list = 1; | 946 | opt_list = 1; |
| 929 | break; | 947 | break; |
diff --git a/MAINTAINERS b/MAINTAINERS index 1f21c34124db..0a32c3ec6b1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -835,13 +835,13 @@ F: arch/arm/mach-pxa/palmte2.c | |||
| 835 | F: arch/arm/mach-pxa/include/mach/palmtc.h | 835 | F: arch/arm/mach-pxa/include/mach/palmtc.h |
| 836 | F: arch/arm/mach-pxa/palmtc.c | 836 | F: arch/arm/mach-pxa/palmtc.c |
| 837 | 837 | ||
| 838 | ARM/PALM TREO 680 SUPPORT | 838 | ARM/PALM TREO SUPPORT |
| 839 | M: Tomas Cech <sleep_walker@suse.cz> | 839 | M: Tomas Cech <sleep_walker@suse.cz> |
| 840 | L: linux-arm-kernel@lists.infradead.org | 840 | L: linux-arm-kernel@lists.infradead.org |
| 841 | W: http://hackndev.com | 841 | W: http://hackndev.com |
| 842 | S: Maintained | 842 | S: Maintained |
| 843 | F: arch/arm/mach-pxa/include/mach/treo680.h | 843 | F: arch/arm/mach-pxa/include/mach/palmtreo.h |
| 844 | F: arch/arm/mach-pxa/treo680.c | 844 | F: arch/arm/mach-pxa/palmtreo.c |
| 845 | 845 | ||
| 846 | ARM/PALMZ72 SUPPORT | 846 | ARM/PALMZ72 SUPPORT |
| 847 | M: Sergey Lapin <slapin@ossfans.org> | 847 | M: Sergey Lapin <slapin@ossfans.org> |
| @@ -1482,8 +1482,8 @@ F: include/linux/coda*.h | |||
| 1482 | 1482 | ||
| 1483 | COMMON INTERNET FILE SYSTEM (CIFS) | 1483 | COMMON INTERNET FILE SYSTEM (CIFS) |
| 1484 | M: Steve French <sfrench@samba.org> | 1484 | M: Steve French <sfrench@samba.org> |
| 1485 | L: linux-cifs-client@lists.samba.org | 1485 | L: linux-cifs-client@lists.samba.org (moderated for non-subscribers) |
| 1486 | L: samba-technical@lists.samba.org | 1486 | L: samba-technical@lists.samba.org (moderated for non-subscribers) |
| 1487 | W: http://linux-cifs.samba.org/ | 1487 | W: http://linux-cifs.samba.org/ |
| 1488 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git | 1488 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git |
| 1489 | S: Supported | 1489 | S: Supported |
| @@ -3081,8 +3081,11 @@ S: Maintained | |||
| 3081 | F: fs/autofs4/ | 3081 | F: fs/autofs4/ |
| 3082 | 3082 | ||
| 3083 | KERNEL BUILD | 3083 | KERNEL BUILD |
| 3084 | M: Michal Marek <mmarek@suse.cz> | ||
| 3085 | T: git git://repo.or.cz/linux-kbuild.git for-next | ||
| 3086 | T: git git://repo.or.cz/linux-kbuild.git for-linus | ||
| 3084 | L: linux-kbuild@vger.kernel.org | 3087 | L: linux-kbuild@vger.kernel.org |
| 3085 | S: Orphan | 3088 | S: Maintained |
| 3086 | F: Documentation/kbuild/ | 3089 | F: Documentation/kbuild/ |
| 3087 | F: Makefile | 3090 | F: Makefile |
| 3088 | F: scripts/Makefile.* | 3091 | F: scripts/Makefile.* |
| @@ -3124,7 +3127,6 @@ L: kvm@vger.kernel.org | |||
| 3124 | W: http://kvm.qumranet.com | 3127 | W: http://kvm.qumranet.com |
| 3125 | S: Supported | 3128 | S: Supported |
| 3126 | F: arch/x86/include/asm/svm.h | 3129 | F: arch/x86/include/asm/svm.h |
| 3127 | F: arch/x86/kvm/kvm_svm.h | ||
| 3128 | F: arch/x86/kvm/svm.c | 3130 | F: arch/x86/kvm/svm.c |
| 3129 | 3131 | ||
| 3130 | KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC | 3132 | KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC |
| @@ -5974,6 +5976,7 @@ M: Mark Brown <broonie@opensource.wolfsonmicro.com> | |||
| 5974 | T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus | 5976 | T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus |
| 5975 | W: http://opensource.wolfsonmicro.com/node/8 | 5977 | W: http://opensource.wolfsonmicro.com/node/8 |
| 5976 | S: Supported | 5978 | S: Supported |
| 5979 | F: Documentation/hwmon/wm83?? | ||
| 5977 | F: drivers/leds/leds-wm83*.c | 5980 | F: drivers/leds/leds-wm83*.c |
| 5978 | F: drivers/mfd/wm8*.c | 5981 | F: drivers/mfd/wm8*.c |
| 5979 | F: drivers/power/wm83*.c | 5982 | F: drivers/power/wm83*.c |
| @@ -5983,9 +5986,9 @@ F: drivers/video/backlight/wm83*_bl.c | |||
| 5983 | F: drivers/watchdog/wm83*_wdt.c | 5986 | F: drivers/watchdog/wm83*_wdt.c |
| 5984 | F: include/linux/mfd/wm831x/ | 5987 | F: include/linux/mfd/wm831x/ |
| 5985 | F: include/linux/mfd/wm8350/ | 5988 | F: include/linux/mfd/wm8350/ |
| 5986 | F: include/linux/mfd/wm8400/ | 5989 | F: include/linux/mfd/wm8400* |
| 5987 | F: sound/soc/codecs/wm8350.c | 5990 | F: sound/soc/codecs/wm8350.* |
| 5988 | F: sound/soc/codecs/wm8400.c | 5991 | F: sound/soc/codecs/wm8400.* |
| 5989 | 5992 | ||
| 5990 | X.25 NETWORK LAYER | 5993 | X.25 NETWORK LAYER |
| 5991 | M: Henner Eisen <eis@baty.hanse.de> | 5994 | M: Henner Eisen <eis@baty.hanse.de> |
diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c index d12af472e1c0..dbbf04f9230e 100644 --- a/arch/alpha/kernel/srm_env.c +++ b/arch/alpha/kernel/srm_env.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 35 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
| 36 | #include <linux/seq_file.h> | ||
| 36 | #include <asm/console.h> | 37 | #include <asm/console.h> |
| 37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
| 38 | #include <asm/machvec.h> | 39 | #include <asm/machvec.h> |
| @@ -79,42 +80,41 @@ static srm_env_t srm_named_entries[] = { | |||
| 79 | static srm_env_t srm_numbered_entries[256]; | 80 | static srm_env_t srm_numbered_entries[256]; |
| 80 | 81 | ||
| 81 | 82 | ||
| 82 | static int | 83 | static int srm_env_proc_show(struct seq_file *m, void *v) |
| 83 | srm_env_read(char *page, char **start, off_t off, int count, int *eof, | ||
| 84 | void *data) | ||
| 85 | { | 84 | { |
| 86 | int nbytes; | ||
| 87 | unsigned long ret; | 85 | unsigned long ret; |
| 88 | srm_env_t *entry; | 86 | srm_env_t *entry; |
| 87 | char *page; | ||
| 89 | 88 | ||
| 90 | if (off != 0) { | 89 | entry = (srm_env_t *)m->private; |
| 91 | *eof = 1; | 90 | page = (char *)__get_free_page(GFP_USER); |
| 92 | return 0; | 91 | if (!page) |
| 93 | } | 92 | return -ENOMEM; |
| 94 | 93 | ||
| 95 | entry = (srm_env_t *) data; | 94 | ret = callback_getenv(entry->id, page, PAGE_SIZE); |
| 96 | ret = callback_getenv(entry->id, page, count); | ||
| 97 | 95 | ||
| 98 | if ((ret >> 61) == 0) { | 96 | if ((ret >> 61) == 0) { |
| 99 | nbytes = (int) ret; | 97 | seq_write(m, page, ret); |
| 100 | *eof = 1; | 98 | ret = 0; |
| 101 | } else | 99 | } else |
| 102 | nbytes = -EFAULT; | 100 | ret = -EFAULT; |
| 101 | free_page((unsigned long)page); | ||
| 102 | return ret; | ||
| 103 | } | ||
| 103 | 104 | ||
| 104 | return nbytes; | 105 | static int srm_env_proc_open(struct inode *inode, struct file *file) |
| 106 | { | ||
| 107 | return single_open(file, srm_env_proc_show, PDE(inode)->data); | ||
| 105 | } | 108 | } |
| 106 | 109 | ||
| 107 | static int | 110 | static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer, |
| 108 | srm_env_write(struct file *file, const char __user *buffer, unsigned long count, | 111 | size_t count, loff_t *pos) |
| 109 | void *data) | ||
| 110 | { | 112 | { |
| 111 | int res; | 113 | int res; |
| 112 | srm_env_t *entry; | 114 | srm_env_t *entry = PDE(file->f_path.dentry->d_inode)->data; |
| 113 | char *buf = (char *) __get_free_page(GFP_USER); | 115 | char *buf = (char *) __get_free_page(GFP_USER); |
| 114 | unsigned long ret1, ret2; | 116 | unsigned long ret1, ret2; |
| 115 | 117 | ||
| 116 | entry = (srm_env_t *) data; | ||
| 117 | |||
| 118 | if (!buf) | 118 | if (!buf) |
| 119 | return -ENOMEM; | 119 | return -ENOMEM; |
| 120 | 120 | ||
| @@ -140,6 +140,15 @@ srm_env_write(struct file *file, const char __user *buffer, unsigned long count, | |||
| 140 | return res; | 140 | return res; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static const struct file_operations srm_env_proc_fops = { | ||
| 144 | .owner = THIS_MODULE, | ||
| 145 | .open = srm_env_proc_open, | ||
| 146 | .read = seq_read, | ||
| 147 | .llseek = seq_lseek, | ||
| 148 | .release = single_release, | ||
| 149 | .write = srm_env_proc_write, | ||
| 150 | }; | ||
| 151 | |||
| 143 | static void | 152 | static void |
| 144 | srm_env_cleanup(void) | 153 | srm_env_cleanup(void) |
| 145 | { | 154 | { |
| @@ -245,15 +254,10 @@ srm_env_init(void) | |||
| 245 | */ | 254 | */ |
| 246 | entry = srm_named_entries; | 255 | entry = srm_named_entries; |
| 247 | while (entry->name && entry->id) { | 256 | while (entry->name && entry->id) { |
| 248 | entry->proc_entry = create_proc_entry(entry->name, | 257 | entry->proc_entry = proc_create_data(entry->name, 0644, named_dir, |
| 249 | 0644, named_dir); | 258 | &srm_env_proc_fops, entry); |
| 250 | if (!entry->proc_entry) | 259 | if (!entry->proc_entry) |
| 251 | goto cleanup; | 260 | goto cleanup; |
| 252 | |||
| 253 | entry->proc_entry->data = (void *) entry; | ||
| 254 | entry->proc_entry->read_proc = srm_env_read; | ||
| 255 | entry->proc_entry->write_proc = srm_env_write; | ||
| 256 | |||
| 257 | entry++; | 261 | entry++; |
| 258 | } | 262 | } |
| 259 | 263 | ||
| @@ -264,15 +268,12 @@ srm_env_init(void) | |||
| 264 | entry = &srm_numbered_entries[var_num]; | 268 | entry = &srm_numbered_entries[var_num]; |
| 265 | entry->name = number[var_num]; | 269 | entry->name = number[var_num]; |
| 266 | 270 | ||
| 267 | entry->proc_entry = create_proc_entry(entry->name, | 271 | entry->proc_entry = proc_create_data(entry->name, 0644, numbered_dir, |
| 268 | 0644, numbered_dir); | 272 | &srm_env_proc_fops, entry); |
| 269 | if (!entry->proc_entry) | 273 | if (!entry->proc_entry) |
| 270 | goto cleanup; | 274 | goto cleanup; |
| 271 | 275 | ||
| 272 | entry->id = var_num; | 276 | entry->id = var_num; |
| 273 | entry->proc_entry->data = (void *) entry; | ||
| 274 | entry->proc_entry->read_proc = srm_env_read; | ||
| 275 | entry->proc_entry->write_proc = srm_env_write; | ||
| 276 | } | 277 | } |
| 277 | 278 | ||
| 278 | printk(KERN_INFO "%s: version %s loaded successfully\n", NAME, | 279 | printk(KERN_INFO "%s: version %s loaded successfully\n", NAME, |
diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h new file mode 100644 index 000000000000..998cb0c07135 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/atmel-mci.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef __MACH_ATMEL_MCI_H | ||
| 2 | #define __MACH_ATMEL_MCI_H | ||
| 3 | |||
| 4 | #include <mach/at_hdmac.h> | ||
| 5 | |||
| 6 | /** | ||
| 7 | * struct mci_dma_data - DMA data for MCI interface | ||
| 8 | */ | ||
| 9 | struct mci_dma_data { | ||
| 10 | struct at_dma_slave sdata; | ||
| 11 | }; | ||
| 12 | |||
| 13 | /* accessor macros */ | ||
| 14 | #define slave_data_ptr(s) (&(s)->sdata) | ||
| 15 | #define find_slave_dev(s) ((s)->sdata.dma_dev) | ||
| 16 | |||
| 17 | #define setup_dma_addr(s, t, r) do { \ | ||
| 18 | if (s) { \ | ||
| 19 | (s)->sdata.tx_reg = (t); \ | ||
| 20 | (s)->sdata.rx_reg = (r); \ | ||
| 21 | } \ | ||
| 22 | } while (0) | ||
| 23 | |||
| 24 | #endif /* __MACH_ATMEL_MCI_H */ | ||
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c index 6c768b71ad64..53fcef7c5201 100644 --- a/arch/arm/plat-omap/debug-leds.c +++ b/arch/arm/plat-omap/debug-leds.c | |||
| @@ -293,7 +293,7 @@ static int fpga_resume_noirq(struct device *dev) | |||
| 293 | return 0; | 293 | return 0; |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | static struct dev_pm_ops fpga_dev_pm_ops = { | 296 | static const struct dev_pm_ops fpga_dev_pm_ops = { |
| 297 | .suspend_noirq = fpga_suspend_noirq, | 297 | .suspend_noirq = fpga_suspend_noirq, |
| 298 | .resume_noirq = fpga_resume_noirq, | 298 | .resume_noirq = fpga_resume_noirq, |
| 299 | }; | 299 | }; |
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 055160e0620e..04846811d0aa 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
| @@ -1431,7 +1431,7 @@ static int omap_mpuio_resume_noirq(struct device *dev) | |||
| 1431 | return 0; | 1431 | return 0; |
| 1432 | } | 1432 | } |
| 1433 | 1433 | ||
| 1434 | static struct dev_pm_ops omap_mpuio_dev_pm_ops = { | 1434 | static const struct dev_pm_ops omap_mpuio_dev_pm_ops = { |
| 1435 | .suspend_noirq = omap_mpuio_suspend_noirq, | 1435 | .suspend_noirq = omap_mpuio_suspend_noirq, |
| 1436 | .resume_noirq = omap_mpuio_resume_noirq, | 1436 | .resume_noirq = omap_mpuio_resume_noirq, |
| 1437 | }; | 1437 | }; |
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index eb9d4dc2e86d..b40ff39e0ac8 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include <linux/gpio.h> | 15 | #include <linux/gpio.h> |
| 16 | #include <linux/spi/spi.h> | 16 | #include <linux/spi/spi.h> |
| 17 | #include <linux/usb/atmel_usba_udc.h> | 17 | #include <linux/usb/atmel_usba_udc.h> |
| 18 | |||
| 19 | #include <mach/atmel-mci.h> | ||
| 18 | #include <linux/atmel-mci.h> | 20 | #include <linux/atmel-mci.h> |
| 19 | 21 | ||
| 20 | #include <asm/io.h> | 22 | #include <asm/io.h> |
| @@ -1320,7 +1322,7 @@ struct platform_device *__init | |||
| 1320 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | 1322 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) |
| 1321 | { | 1323 | { |
| 1322 | struct platform_device *pdev; | 1324 | struct platform_device *pdev; |
| 1323 | struct dw_dma_slave *dws = &data->dma_slave; | 1325 | struct mci_dma_slave *slave; |
| 1324 | u32 pioa_mask; | 1326 | u32 pioa_mask; |
| 1325 | u32 piob_mask; | 1327 | u32 piob_mask; |
| 1326 | 1328 | ||
| @@ -1339,13 +1341,17 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | |||
| 1339 | ARRAY_SIZE(atmel_mci0_resource))) | 1341 | ARRAY_SIZE(atmel_mci0_resource))) |
| 1340 | goto fail; | 1342 | goto fail; |
| 1341 | 1343 | ||
| 1342 | dws->dma_dev = &dw_dmac0_device.dev; | 1344 | slave = kzalloc(sizeof(struct mci_dma_slave), GFP_KERNEL); |
| 1343 | dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT; | 1345 | |
| 1344 | dws->cfg_hi = (DWC_CFGH_SRC_PER(0) | 1346 | slave->sdata.dma_dev = &dw_dmac0_device.dev; |
| 1347 | slave->sdata.reg_width = DW_DMA_SLAVE_WIDTH_32BIT; | ||
| 1348 | slave->sdata.cfg_hi = (DWC_CFGH_SRC_PER(0) | ||
| 1345 | | DWC_CFGH_DST_PER(1)); | 1349 | | DWC_CFGH_DST_PER(1)); |
| 1346 | dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | 1350 | slave->sdata.cfg_lo &= ~(DWC_CFGL_HS_DST_POL |
| 1347 | | DWC_CFGL_HS_SRC_POL); | 1351 | | DWC_CFGL_HS_SRC_POL); |
| 1348 | 1352 | ||
| 1353 | data->dma_slave = slave; | ||
| 1354 | |||
| 1349 | if (platform_device_add_data(pdev, data, | 1355 | if (platform_device_add_data(pdev, data, |
| 1350 | sizeof(struct mci_platform_data))) | 1356 | sizeof(struct mci_platform_data))) |
| 1351 | goto fail; | 1357 | goto fail; |
| @@ -1411,6 +1417,8 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | |||
| 1411 | return pdev; | 1417 | return pdev; |
| 1412 | 1418 | ||
| 1413 | fail: | 1419 | fail: |
| 1420 | data->dma_slave = NULL; | ||
| 1421 | kfree(slave); | ||
| 1414 | platform_device_put(pdev); | 1422 | platform_device_put(pdev); |
| 1415 | return NULL; | 1423 | return NULL; |
| 1416 | } | 1424 | } |
diff --git a/arch/avr32/mach-at32ap/include/mach/atmel-mci.h b/arch/avr32/mach-at32ap/include/mach/atmel-mci.h new file mode 100644 index 000000000000..a9b38967f703 --- /dev/null +++ b/arch/avr32/mach-at32ap/include/mach/atmel-mci.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef __MACH_ATMEL_MCI_H | ||
| 2 | #define __MACH_ATMEL_MCI_H | ||
| 3 | |||
| 4 | #include <linux/dw_dmac.h> | ||
| 5 | |||
| 6 | /** | ||
| 7 | * struct mci_dma_data - DMA data for MCI interface | ||
| 8 | */ | ||
| 9 | struct mci_dma_data { | ||
| 10 | struct dw_dma_slave sdata; | ||
| 11 | }; | ||
| 12 | |||
| 13 | /* accessor macros */ | ||
| 14 | #define slave_data_ptr(s) (&(s)->sdata) | ||
| 15 | #define find_slave_dev(s) ((s)->sdata.dma_dev) | ||
| 16 | |||
| 17 | #define setup_dma_addr(s, t, r) do { \ | ||
| 18 | if (s) { \ | ||
| 19 | (s)->sdata.tx_reg = (t); \ | ||
| 20 | (s)->sdata.rx_reg = (r); \ | ||
| 21 | } \ | ||
| 22 | } while (0) | ||
| 23 | |||
| 24 | #endif /* __MACH_ATMEL_MCI_H */ | ||
diff --git a/arch/ia64/include/asm/numa.h b/arch/ia64/include/asm/numa.h index 3499ff57bf42..6a8a27cfae3e 100644 --- a/arch/ia64/include/asm/numa.h +++ b/arch/ia64/include/asm/numa.h | |||
| @@ -22,8 +22,6 @@ | |||
| 22 | 22 | ||
| 23 | #include <asm/mmzone.h> | 23 | #include <asm/mmzone.h> |
| 24 | 24 | ||
| 25 | #define NUMA_NO_NODE -1 | ||
| 26 | |||
| 27 | extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned; | 25 | extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned; |
| 28 | extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; | 26 | extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; |
| 29 | extern pg_data_t *pgdat_list[MAX_NUMNODES]; | 27 | extern pg_data_t *pgdat_list[MAX_NUMNODES]; |
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 495589950dc7..5c91995b74e4 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c | |||
| @@ -551,7 +551,7 @@ static int appldata_thaw(struct device *dev) | |||
| 551 | return appldata_restore(dev); | 551 | return appldata_restore(dev); |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | static struct dev_pm_ops appldata_pm_ops = { | 554 | static const struct dev_pm_ops appldata_pm_ops = { |
| 555 | .freeze = appldata_freeze, | 555 | .freeze = appldata_freeze, |
| 556 | .thaw = appldata_thaw, | 556 | .thaw = appldata_thaw, |
| 557 | .restore = appldata_restore, | 557 | .restore = appldata_restore, |
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 071c81f179ef..0168472b2fdf 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/ctype.h> | 20 | #include <linux/ctype.h> |
| 21 | #include <linux/string.h> | ||
| 21 | #include <linux/sysctl.h> | 22 | #include <linux/sysctl.h> |
| 22 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
| 23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| @@ -1178,7 +1179,7 @@ debug_get_uint(char *buf) | |||
| 1178 | { | 1179 | { |
| 1179 | int rc; | 1180 | int rc; |
| 1180 | 1181 | ||
| 1181 | for(; isspace(*buf); buf++); | 1182 | buf = skip_spaces(buf); |
| 1182 | rc = simple_strtoul(buf, &buf, 10); | 1183 | rc = simple_strtoul(buf, &buf, 10); |
| 1183 | if(*buf){ | 1184 | if(*buf){ |
| 1184 | rc = -EINVAL; | 1185 | rc = -EINVAL; |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index e14629c87de4..51069245b79a 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <linux/console.h> | 7 | #include <linux/console.h> |
| 8 | #include <linux/ctype.h> | 8 | #include <linux/ctype.h> |
| 9 | #include <linux/string.h> | ||
| 9 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> |
| 10 | #include <linux/list.h> | 11 | #include <linux/list.h> |
| 11 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
| @@ -131,7 +132,7 @@ void mconsole_proc(struct mc_request *req) | |||
| 131 | char *ptr = req->request.data, *buf; | 132 | char *ptr = req->request.data, *buf; |
| 132 | 133 | ||
| 133 | ptr += strlen("proc"); | 134 | ptr += strlen("proc"); |
| 134 | while (isspace(*ptr)) ptr++; | 135 | ptr = skip_spaces(ptr); |
| 135 | 136 | ||
| 136 | proc = get_fs_type("proc"); | 137 | proc = get_fs_type("proc"); |
| 137 | if (proc == NULL) { | 138 | if (proc == NULL) { |
| @@ -212,8 +213,7 @@ void mconsole_proc(struct mc_request *req) | |||
| 212 | char *ptr = req->request.data; | 213 | char *ptr = req->request.data; |
| 213 | 214 | ||
| 214 | ptr += strlen("proc"); | 215 | ptr += strlen("proc"); |
| 215 | while (isspace(*ptr)) | 216 | ptr = skip_spaces(ptr); |
| 216 | ptr++; | ||
| 217 | snprintf(path, sizeof(path), "/proc/%s", ptr); | 217 | snprintf(path, sizeof(path), "/proc/%s", ptr); |
| 218 | 218 | ||
| 219 | fd = sys_open(path, 0, 0); | 219 | fd = sys_open(path, 0, 0); |
| @@ -560,8 +560,7 @@ void mconsole_config(struct mc_request *req) | |||
| 560 | int err; | 560 | int err; |
| 561 | 561 | ||
| 562 | ptr += strlen("config"); | 562 | ptr += strlen("config"); |
| 563 | while (isspace(*ptr)) | 563 | ptr = skip_spaces(ptr); |
| 564 | ptr++; | ||
| 565 | dev = mconsole_find_dev(ptr); | 564 | dev = mconsole_find_dev(ptr); |
| 566 | if (dev == NULL) { | 565 | if (dev == NULL) { |
| 567 | mconsole_reply(req, "Bad configuration option", 1, 0); | 566 | mconsole_reply(req, "Bad configuration option", 1, 0); |
| @@ -588,7 +587,7 @@ void mconsole_remove(struct mc_request *req) | |||
| 588 | int err, start, end, n; | 587 | int err, start, end, n; |
| 589 | 588 | ||
| 590 | ptr += strlen("remove"); | 589 | ptr += strlen("remove"); |
| 591 | while (isspace(*ptr)) ptr++; | 590 | ptr = skip_spaces(ptr); |
| 592 | dev = mconsole_find_dev(ptr); | 591 | dev = mconsole_find_dev(ptr); |
| 593 | if (dev == NULL) { | 592 | if (dev == NULL) { |
| 594 | mconsole_reply(req, "Bad remove option", 1, 0); | 593 | mconsole_reply(req, "Bad remove option", 1, 0); |
| @@ -712,7 +711,7 @@ void mconsole_sysrq(struct mc_request *req) | |||
| 712 | char *ptr = req->request.data; | 711 | char *ptr = req->request.data; |
| 713 | 712 | ||
| 714 | ptr += strlen("sysrq"); | 713 | ptr += strlen("sysrq"); |
| 715 | while (isspace(*ptr)) ptr++; | 714 | ptr = skip_spaces(ptr); |
| 716 | 715 | ||
| 717 | /* | 716 | /* |
| 718 | * With 'b', the system will shut down without a chance to reply, | 717 | * With 'b', the system will shut down without a chance to reply, |
| @@ -757,8 +756,7 @@ void mconsole_stack(struct mc_request *req) | |||
| 757 | */ | 756 | */ |
| 758 | 757 | ||
| 759 | ptr += strlen("stack"); | 758 | ptr += strlen("stack"); |
| 760 | while (isspace(*ptr)) | 759 | ptr = skip_spaces(ptr); |
| 761 | ptr++; | ||
| 762 | 760 | ||
| 763 | /* | 761 | /* |
| 764 | * Should really check for multiple pids or reject bad args here | 762 | * Should really check for multiple pids or reject bad args here |
| @@ -833,8 +831,8 @@ static int __init mconsole_init(void) | |||
| 833 | 831 | ||
| 834 | __initcall(mconsole_init); | 832 | __initcall(mconsole_init); |
| 835 | 833 | ||
| 836 | static int write_proc_mconsole(struct file *file, const char __user *buffer, | 834 | static ssize_t mconsole_proc_write(struct file *file, |
| 837 | unsigned long count, void *data) | 835 | const char __user *buffer, size_t count, loff_t *pos) |
| 838 | { | 836 | { |
| 839 | char *buf; | 837 | char *buf; |
| 840 | 838 | ||
| @@ -855,6 +853,11 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, | |||
| 855 | return count; | 853 | return count; |
| 856 | } | 854 | } |
| 857 | 855 | ||
| 856 | static const struct file_operations mconsole_proc_fops = { | ||
| 857 | .owner = THIS_MODULE, | ||
| 858 | .write = mconsole_proc_write, | ||
| 859 | }; | ||
| 860 | |||
| 858 | static int create_proc_mconsole(void) | 861 | static int create_proc_mconsole(void) |
| 859 | { | 862 | { |
| 860 | struct proc_dir_entry *ent; | 863 | struct proc_dir_entry *ent; |
| @@ -862,15 +865,12 @@ static int create_proc_mconsole(void) | |||
| 862 | if (notify_socket == NULL) | 865 | if (notify_socket == NULL) |
| 863 | return 0; | 866 | return 0; |
| 864 | 867 | ||
| 865 | ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); | 868 | ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_fops); |
| 866 | if (ent == NULL) { | 869 | if (ent == NULL) { |
| 867 | printk(KERN_INFO "create_proc_mconsole : create_proc_entry " | 870 | printk(KERN_INFO "create_proc_mconsole : create_proc_entry " |
| 868 | "failed\n"); | 871 | "failed\n"); |
| 869 | return 0; | 872 | return 0; |
| 870 | } | 873 | } |
| 871 | |||
| 872 | ent->read_proc = NULL; | ||
| 873 | ent->write_proc = write_proc_mconsole; | ||
| 874 | return 0; | 874 | return 0; |
| 875 | } | 875 | } |
| 876 | 876 | ||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 635d16d90a80..5ff554677f40 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "linux/init.h" | 27 | #include "linux/init.h" |
| 28 | #include "linux/cdrom.h" | 28 | #include "linux/cdrom.h" |
| 29 | #include "linux/proc_fs.h" | 29 | #include "linux/proc_fs.h" |
| 30 | #include "linux/seq_file.h" | ||
| 30 | #include "linux/ctype.h" | 31 | #include "linux/ctype.h" |
| 31 | #include "linux/capability.h" | 32 | #include "linux/capability.h" |
| 32 | #include "linux/mm.h" | 33 | #include "linux/mm.h" |
| @@ -200,23 +201,25 @@ static void make_proc_ide(void) | |||
| 200 | proc_ide = proc_mkdir("ide0", proc_ide_root); | 201 | proc_ide = proc_mkdir("ide0", proc_ide_root); |
| 201 | } | 202 | } |
| 202 | 203 | ||
| 203 | static int proc_ide_read_media(char *page, char **start, off_t off, int count, | 204 | static int fake_ide_media_proc_show(struct seq_file *m, void *v) |
| 204 | int *eof, void *data) | ||
| 205 | { | 205 | { |
| 206 | int len; | 206 | seq_puts(m, "disk\n"); |
| 207 | 207 | return 0; | |
| 208 | strcpy(page, "disk\n"); | 208 | } |
| 209 | len = strlen("disk\n"); | 209 | |
| 210 | len -= off; | 210 | static int fake_ide_media_proc_open(struct inode *inode, struct file *file) |
| 211 | if (len < count){ | 211 | { |
| 212 | *eof = 1; | 212 | return single_open(file, fake_ide_media_proc_show, NULL); |
| 213 | if (len <= 0) return 0; | ||
| 214 | } | ||
| 215 | else len = count; | ||
| 216 | *start = page + off; | ||
| 217 | return len; | ||
| 218 | } | 213 | } |
| 219 | 214 | ||
| 215 | static const struct file_operations fake_ide_media_proc_fops = { | ||
| 216 | .owner = THIS_MODULE, | ||
| 217 | .open = fake_ide_media_proc_open, | ||
| 218 | .read = seq_read, | ||
| 219 | .llseek = seq_lseek, | ||
| 220 | .release = single_release, | ||
| 221 | }; | ||
| 222 | |||
| 220 | static void make_ide_entries(const char *dev_name) | 223 | static void make_ide_entries(const char *dev_name) |
| 221 | { | 224 | { |
| 222 | struct proc_dir_entry *dir, *ent; | 225 | struct proc_dir_entry *dir, *ent; |
| @@ -227,11 +230,8 @@ static void make_ide_entries(const char *dev_name) | |||
| 227 | dir = proc_mkdir(dev_name, proc_ide); | 230 | dir = proc_mkdir(dev_name, proc_ide); |
| 228 | if(!dir) return; | 231 | if(!dir) return; |
| 229 | 232 | ||
| 230 | ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); | 233 | ent = proc_create("media", S_IRUGO, dir, &fake_ide_media_proc_fops); |
| 231 | if(!ent) return; | 234 | if(!ent) return; |
| 232 | ent->data = NULL; | ||
| 233 | ent->read_proc = proc_ide_read_media; | ||
| 234 | ent->write_proc = NULL; | ||
| 235 | snprintf(name, sizeof(name), "ide0/%s", dev_name); | 235 | snprintf(name, sizeof(name), "ide0/%s", dev_name); |
| 236 | proc_symlink(dev_name, proc_ide_root, name); | 236 | proc_symlink(dev_name, proc_ide_root, name); |
| 237 | } | 237 | } |
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 6540d2c9fbb7..829df49dee99 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c | |||
| @@ -6,7 +6,9 @@ | |||
| 6 | #include <linux/ctype.h> | 6 | #include <linux/ctype.h> |
| 7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
| 8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
| 9 | #include <linux/module.h> | ||
| 9 | #include <linux/proc_fs.h> | 10 | #include <linux/proc_fs.h> |
| 11 | #include <linux/seq_file.h> | ||
| 10 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 11 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
| 12 | 14 | ||
| @@ -16,30 +18,26 @@ | |||
| 16 | */ | 18 | */ |
| 17 | int uml_exitcode = 0; | 19 | int uml_exitcode = 0; |
| 18 | 20 | ||
| 19 | static int read_proc_exitcode(char *page, char **start, off_t off, | 21 | static int exitcode_proc_show(struct seq_file *m, void *v) |
| 20 | int count, int *eof, void *data) | ||
| 21 | { | 22 | { |
| 22 | int len, val; | 23 | int val; |
| 23 | 24 | ||
| 24 | /* | 25 | /* |
| 25 | * Save uml_exitcode in a local so that we don't need to guarantee | 26 | * Save uml_exitcode in a local so that we don't need to guarantee |
| 26 | * that sprintf accesses it atomically. | 27 | * that sprintf accesses it atomically. |
| 27 | */ | 28 | */ |
| 28 | val = uml_exitcode; | 29 | val = uml_exitcode; |
| 29 | len = sprintf(page, "%d\n", val); | 30 | seq_printf(m, "%d\n", val); |
| 30 | len -= off; | 31 | return 0; |
| 31 | if (len <= off+count) | 32 | } |
| 32 | *eof = 1; | 33 | |
| 33 | *start = page + off; | 34 | static int exitcode_proc_open(struct inode *inode, struct file *file) |
| 34 | if (len > count) | 35 | { |
| 35 | len = count; | 36 | return single_open(file, exitcode_proc_show, NULL); |
| 36 | if (len < 0) | ||
| 37 | len = 0; | ||
| 38 | return len; | ||
| 39 | } | 37 | } |
| 40 | 38 | ||
| 41 | static int write_proc_exitcode(struct file *file, const char __user *buffer, | 39 | static ssize_t exitcode_proc_write(struct file *file, |
| 42 | unsigned long count, void *data) | 40 | const char __user *buffer, size_t count, loff_t *pos) |
| 43 | { | 41 | { |
| 44 | char *end, buf[sizeof("nnnnn\0")]; | 42 | char *end, buf[sizeof("nnnnn\0")]; |
| 45 | int tmp; | 43 | int tmp; |
| @@ -55,20 +53,25 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer, | |||
| 55 | return count; | 53 | return count; |
| 56 | } | 54 | } |
| 57 | 55 | ||
| 56 | static const struct file_operations exitcode_proc_fops = { | ||
| 57 | .owner = THIS_MODULE, | ||
| 58 | .open = exitcode_proc_open, | ||
| 59 | .read = seq_read, | ||
| 60 | .llseek = seq_lseek, | ||
| 61 | .release = single_release, | ||
| 62 | .write = exitcode_proc_write, | ||
| 63 | }; | ||
| 64 | |||
| 58 | static int make_proc_exitcode(void) | 65 | static int make_proc_exitcode(void) |
| 59 | { | 66 | { |
| 60 | struct proc_dir_entry *ent; | 67 | struct proc_dir_entry *ent; |
| 61 | 68 | ||
| 62 | ent = create_proc_entry("exitcode", 0600, NULL); | 69 | ent = proc_create("exitcode", 0600, NULL, &exitcode_proc_fops); |
| 63 | if (ent == NULL) { | 70 | if (ent == NULL) { |
| 64 | printk(KERN_WARNING "make_proc_exitcode : Failed to register " | 71 | printk(KERN_WARNING "make_proc_exitcode : Failed to register " |
| 65 | "/proc/exitcode\n"); | 72 | "/proc/exitcode\n"); |
| 66 | return 0; | 73 | return 0; |
| 67 | } | 74 | } |
| 68 | |||
| 69 | ent->read_proc = read_proc_exitcode; | ||
| 70 | ent->write_proc = write_proc_exitcode; | ||
| 71 | |||
| 72 | return 0; | 75 | return 0; |
| 73 | } | 76 | } |
| 74 | 77 | ||
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 4a28a1568d85..2f910a1b7454 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
| @@ -9,11 +9,13 @@ | |||
| 9 | #include <linux/hardirq.h> | 9 | #include <linux/hardirq.h> |
| 10 | #include <linux/gfp.h> | 10 | #include <linux/gfp.h> |
| 11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
| 12 | #include <linux/module.h> | ||
| 12 | #include <linux/personality.h> | 13 | #include <linux/personality.h> |
| 13 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
| 14 | #include <linux/ptrace.h> | 15 | #include <linux/ptrace.h> |
| 15 | #include <linux/random.h> | 16 | #include <linux/random.h> |
| 16 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
| 18 | #include <linux/seq_file.h> | ||
| 17 | #include <linux/tick.h> | 19 | #include <linux/tick.h> |
| 18 | #include <linux/threads.h> | 20 | #include <linux/threads.h> |
| 19 | #include <asm/current.h> | 21 | #include <asm/current.h> |
| @@ -336,16 +338,19 @@ int get_using_sysemu(void) | |||
| 336 | return atomic_read(&using_sysemu); | 338 | return atomic_read(&using_sysemu); |
| 337 | } | 339 | } |
| 338 | 340 | ||
| 339 | static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) | 341 | static int sysemu_proc_show(struct seq_file *m, void *v) |
| 340 | { | 342 | { |
| 341 | if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) | 343 | seq_printf(m, "%d\n", get_using_sysemu()); |
| 342 | /* No overflow */ | 344 | return 0; |
| 343 | *eof = 1; | 345 | } |
| 344 | 346 | ||
| 345 | return strlen(buf); | 347 | static int sysemu_proc_open(struct inode *inode, struct file *file) |
| 348 | { | ||
| 349 | return single_open(file, sysemu_proc_show, NULL); | ||
| 346 | } | 350 | } |
| 347 | 351 | ||
| 348 | static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data) | 352 | static ssize_t sysemu_proc_write(struct file *file, const char __user *buf, |
| 353 | size_t count, loff_t *pos) | ||
| 349 | { | 354 | { |
| 350 | char tmp[2]; | 355 | char tmp[2]; |
| 351 | 356 | ||
| @@ -358,13 +363,22 @@ static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned | |||
| 358 | return count; | 363 | return count; |
| 359 | } | 364 | } |
| 360 | 365 | ||
| 366 | static const struct file_operations sysemu_proc_fops = { | ||
| 367 | .owner = THIS_MODULE, | ||
| 368 | .open = sysemu_proc_open, | ||
| 369 | .read = seq_read, | ||
| 370 | .llseek = seq_lseek, | ||
| 371 | .release = single_release, | ||
| 372 | .write = sysemu_proc_write, | ||
| 373 | }; | ||
| 374 | |||
| 361 | int __init make_proc_sysemu(void) | 375 | int __init make_proc_sysemu(void) |
| 362 | { | 376 | { |
| 363 | struct proc_dir_entry *ent; | 377 | struct proc_dir_entry *ent; |
| 364 | if (!sysemu_supported) | 378 | if (!sysemu_supported) |
| 365 | return 0; | 379 | return 0; |
| 366 | 380 | ||
| 367 | ent = create_proc_entry("sysemu", 0600, NULL); | 381 | ent = proc_create("sysemu", 0600, NULL, &sysemu_proc_fops); |
| 368 | 382 | ||
| 369 | if (ent == NULL) | 383 | if (ent == NULL) |
| 370 | { | 384 | { |
| @@ -372,9 +386,6 @@ int __init make_proc_sysemu(void) | |||
| 372 | return 0; | 386 | return 0; |
| 373 | } | 387 | } |
| 374 | 388 | ||
| 375 | ent->read_proc = proc_read_sysemu; | ||
| 376 | ent->write_proc = proc_write_sysemu; | ||
| 377 | |||
| 378 | return 0; | 389 | return 0; |
| 379 | } | 390 | } |
| 380 | 391 | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 32a1918e1b88..3b2a5aca4edb 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -2012,18 +2012,9 @@ config SCx200HR_TIMER | |||
| 2012 | processor goes idle (as is done by the scheduler). The | 2012 | processor goes idle (as is done by the scheduler). The |
| 2013 | other workaround is idle=poll boot option. | 2013 | other workaround is idle=poll boot option. |
| 2014 | 2014 | ||
| 2015 | config GEODE_MFGPT_TIMER | ||
| 2016 | def_bool y | ||
| 2017 | prompt "Geode Multi-Function General Purpose Timer (MFGPT) events" | ||
| 2018 | depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS | ||
| 2019 | ---help--- | ||
| 2020 | This driver provides a clock event source based on the MFGPT | ||
| 2021 | timer(s) in the CS5535 and CS5536 companion chip for the geode. | ||
| 2022 | MFGPTs have a better resolution and max interval than the | ||
| 2023 | generic PIT, and are suitable for use as high-res timers. | ||
| 2024 | |||
| 2025 | config OLPC | 2015 | config OLPC |
| 2026 | bool "One Laptop Per Child support" | 2016 | bool "One Laptop Per Child support" |
| 2017 | select GPIOLIB | ||
| 2027 | default n | 2018 | default n |
| 2028 | ---help--- | 2019 | ---help--- |
| 2029 | Add support for detecting the unique features of the OLPC | 2020 | Add support for detecting the unique features of the OLPC |
diff --git a/arch/x86/include/asm/geode.h b/arch/x86/include/asm/geode.h index ad3c2ed75481..7cd73552a4e8 100644 --- a/arch/x86/include/asm/geode.h +++ b/arch/x86/include/asm/geode.h | |||
| @@ -12,160 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <asm/processor.h> | 13 | #include <asm/processor.h> |
| 14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 15 | 15 | #include <linux/cs5535.h> | |
| 16 | /* Generic southbridge functions */ | ||
| 17 | |||
| 18 | #define GEODE_DEV_PMS 0 | ||
| 19 | #define GEODE_DEV_ACPI 1 | ||
| 20 | #define GEODE_DEV_GPIO 2 | ||
| 21 | #define GEODE_DEV_MFGPT 3 | ||
| 22 | |||
| 23 | extern int geode_get_dev_base(unsigned int dev); | ||
| 24 | |||
| 25 | /* Useful macros */ | ||
| 26 | #define geode_pms_base() geode_get_dev_base(GEODE_DEV_PMS) | ||
| 27 | #define geode_acpi_base() geode_get_dev_base(GEODE_DEV_ACPI) | ||
| 28 | #define geode_gpio_base() geode_get_dev_base(GEODE_DEV_GPIO) | ||
| 29 | #define geode_mfgpt_base() geode_get_dev_base(GEODE_DEV_MFGPT) | ||
| 30 | |||
| 31 | /* MSRS */ | ||
| 32 | |||
| 33 | #define MSR_GLIU_P2D_RO0 0x10000029 | ||
| 34 | |||
| 35 | #define MSR_LX_GLD_MSR_CONFIG 0x48002001 | ||
| 36 | #define MSR_LX_MSR_PADSEL 0x48002011 /* NOT 0x48000011; the data | ||
| 37 | * sheet has the wrong value */ | ||
| 38 | #define MSR_GLCP_SYS_RSTPLL 0x4C000014 | ||
| 39 | #define MSR_GLCP_DOTPLL 0x4C000015 | ||
| 40 | |||
| 41 | #define MSR_LBAR_SMB 0x5140000B | ||
| 42 | #define MSR_LBAR_GPIO 0x5140000C | ||
| 43 | #define MSR_LBAR_MFGPT 0x5140000D | ||
| 44 | #define MSR_LBAR_ACPI 0x5140000E | ||
| 45 | #define MSR_LBAR_PMS 0x5140000F | ||
| 46 | |||
| 47 | #define MSR_DIVIL_SOFT_RESET 0x51400017 | ||
| 48 | |||
| 49 | #define MSR_PIC_YSEL_LOW 0x51400020 | ||
| 50 | #define MSR_PIC_YSEL_HIGH 0x51400021 | ||
| 51 | #define MSR_PIC_ZSEL_LOW 0x51400022 | ||
| 52 | #define MSR_PIC_ZSEL_HIGH 0x51400023 | ||
| 53 | #define MSR_PIC_IRQM_LPC 0x51400025 | ||
| 54 | |||
| 55 | #define MSR_MFGPT_IRQ 0x51400028 | ||
| 56 | #define MSR_MFGPT_NR 0x51400029 | ||
| 57 | #define MSR_MFGPT_SETUP 0x5140002B | ||
| 58 | |||
| 59 | #define MSR_LX_SPARE_MSR 0x80000011 /* DC-specific */ | ||
| 60 | |||
| 61 | #define MSR_GX_GLD_MSR_CONFIG 0xC0002001 | ||
| 62 | #define MSR_GX_MSR_PADSEL 0xC0002011 | ||
| 63 | |||
| 64 | /* Resource Sizes */ | ||
| 65 | |||
| 66 | #define LBAR_GPIO_SIZE 0xFF | ||
| 67 | #define LBAR_MFGPT_SIZE 0x40 | ||
| 68 | #define LBAR_ACPI_SIZE 0x40 | ||
| 69 | #define LBAR_PMS_SIZE 0x80 | ||
| 70 | |||
| 71 | /* ACPI registers (PMS block) */ | ||
| 72 | |||
| 73 | /* | ||
| 74 | * PM1_EN is only valid when VSA is enabled for 16 bit reads. | ||
| 75 | * When VSA is not enabled, *always* read both PM1_STS and PM1_EN | ||
| 76 | * with a 32 bit read at offset 0x0 | ||
| 77 | */ | ||
| 78 | |||
| 79 | #define PM1_STS 0x00 | ||
| 80 | #define PM1_EN 0x02 | ||
| 81 | #define PM1_CNT 0x08 | ||
| 82 | #define PM2_CNT 0x0C | ||
| 83 | #define PM_TMR 0x10 | ||
| 84 | #define PM_GPE0_STS 0x18 | ||
| 85 | #define PM_GPE0_EN 0x1C | ||
| 86 | |||
| 87 | /* PMC registers (PMS block) */ | ||
| 88 | |||
| 89 | #define PM_SSD 0x00 | ||
| 90 | #define PM_SCXA 0x04 | ||
| 91 | #define PM_SCYA 0x08 | ||
| 92 | #define PM_OUT_SLPCTL 0x0C | ||
| 93 | #define PM_SCLK 0x10 | ||
| 94 | #define PM_SED 0x1 | ||
| 95 | #define PM_SCXD 0x18 | ||
| 96 | #define PM_SCYD 0x1C | ||
| 97 | #define PM_IN_SLPCTL 0x20 | ||
| 98 | #define PM_WKD 0x30 | ||
| 99 | #define PM_WKXD 0x34 | ||
| 100 | #define PM_RD 0x38 | ||
| 101 | #define PM_WKXA 0x3C | ||
| 102 | #define PM_FSD 0x40 | ||
| 103 | #define PM_TSD 0x44 | ||
| 104 | #define PM_PSD 0x48 | ||
| 105 | #define PM_NWKD 0x4C | ||
| 106 | #define PM_AWKD 0x50 | ||
| 107 | #define PM_SSC 0x54 | ||
| 108 | |||
| 109 | /* VSA2 magic values */ | ||
| 110 | |||
| 111 | #define VSA_VRC_INDEX 0xAC1C | ||
| 112 | #define VSA_VRC_DATA 0xAC1E | ||
| 113 | #define VSA_VR_UNLOCK 0xFC53 /* unlock virtual register */ | ||
| 114 | #define VSA_VR_SIGNATURE 0x0003 | ||
| 115 | #define VSA_VR_MEM_SIZE 0x0200 | ||
| 116 | #define AMD_VSA_SIG 0x4132 /* signature is ascii 'VSA2' */ | ||
| 117 | #define GSW_VSA_SIG 0x534d /* General Software signature */ | ||
| 118 | /* GPIO */ | ||
| 119 | |||
| 120 | #define GPIO_OUTPUT_VAL 0x00 | ||
| 121 | #define GPIO_OUTPUT_ENABLE 0x04 | ||
| 122 | #define GPIO_OUTPUT_OPEN_DRAIN 0x08 | ||
| 123 | #define GPIO_OUTPUT_INVERT 0x0C | ||
| 124 | #define GPIO_OUTPUT_AUX1 0x10 | ||
| 125 | #define GPIO_OUTPUT_AUX2 0x14 | ||
| 126 | #define GPIO_PULL_UP 0x18 | ||
| 127 | #define GPIO_PULL_DOWN 0x1C | ||
| 128 | #define GPIO_INPUT_ENABLE 0x20 | ||
| 129 | #define GPIO_INPUT_INVERT 0x24 | ||
| 130 | #define GPIO_INPUT_FILTER 0x28 | ||
| 131 | #define GPIO_INPUT_EVENT_COUNT 0x2C | ||
| 132 | #define GPIO_READ_BACK 0x30 | ||
| 133 | #define GPIO_INPUT_AUX1 0x34 | ||
| 134 | #define GPIO_EVENTS_ENABLE 0x38 | ||
| 135 | #define GPIO_LOCK_ENABLE 0x3C | ||
| 136 | #define GPIO_POSITIVE_EDGE_EN 0x40 | ||
| 137 | #define GPIO_NEGATIVE_EDGE_EN 0x44 | ||
| 138 | #define GPIO_POSITIVE_EDGE_STS 0x48 | ||
| 139 | #define GPIO_NEGATIVE_EDGE_STS 0x4C | ||
| 140 | |||
| 141 | #define GPIO_MAP_X 0xE0 | ||
| 142 | #define GPIO_MAP_Y 0xE4 | ||
| 143 | #define GPIO_MAP_Z 0xE8 | ||
| 144 | #define GPIO_MAP_W 0xEC | ||
| 145 | |||
| 146 | static inline u32 geode_gpio(unsigned int nr) | ||
| 147 | { | ||
| 148 | BUG_ON(nr > 28); | ||
| 149 | return 1 << nr; | ||
| 150 | } | ||
| 151 | |||
| 152 | extern void geode_gpio_set(u32, unsigned int); | ||
| 153 | extern void geode_gpio_clear(u32, unsigned int); | ||
| 154 | extern int geode_gpio_isset(u32, unsigned int); | ||
| 155 | extern void geode_gpio_setup_event(unsigned int, int, int); | ||
| 156 | extern void geode_gpio_set_irq(unsigned int, unsigned int); | ||
| 157 | |||
| 158 | static inline void geode_gpio_event_irq(unsigned int gpio, int pair) | ||
| 159 | { | ||
| 160 | geode_gpio_setup_event(gpio, pair, 0); | ||
| 161 | } | ||
| 162 | |||
| 163 | static inline void geode_gpio_event_pme(unsigned int gpio, int pair) | ||
| 164 | { | ||
| 165 | geode_gpio_setup_event(gpio, pair, 1); | ||
| 166 | } | ||
| 167 | |||
| 168 | /* Specific geode tests */ | ||
| 169 | 16 | ||
| 170 | static inline int is_geode_gx(void) | 17 | static inline int is_geode_gx(void) |
| 171 | { | 18 | { |
| @@ -186,68 +33,4 @@ static inline int is_geode(void) | |||
| 186 | return (is_geode_gx() || is_geode_lx()); | 33 | return (is_geode_gx() || is_geode_lx()); |
| 187 | } | 34 | } |
| 188 | 35 | ||
| 189 | #ifdef CONFIG_MGEODE_LX | ||
| 190 | extern int geode_has_vsa2(void); | ||
| 191 | #else | ||
| 192 | static inline int geode_has_vsa2(void) | ||
| 193 | { | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | #endif | ||
| 197 | |||
| 198 | /* MFGPTs */ | ||
| 199 | |||
| 200 | #define MFGPT_MAX_TIMERS 8 | ||
| 201 | #define MFGPT_TIMER_ANY (-1) | ||
| 202 | |||
| 203 | #define MFGPT_DOMAIN_WORKING 1 | ||
| 204 | #define MFGPT_DOMAIN_STANDBY 2 | ||
| 205 | #define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY) | ||
| 206 | |||
| 207 | #define MFGPT_CMP1 0 | ||
| 208 | #define MFGPT_CMP2 1 | ||
| 209 | |||
| 210 | #define MFGPT_EVENT_IRQ 0 | ||
| 211 | #define MFGPT_EVENT_NMI 1 | ||
| 212 | #define MFGPT_EVENT_RESET 3 | ||
| 213 | |||
| 214 | #define MFGPT_REG_CMP1 0 | ||
| 215 | #define MFGPT_REG_CMP2 2 | ||
| 216 | #define MFGPT_REG_COUNTER 4 | ||
| 217 | #define MFGPT_REG_SETUP 6 | ||
| 218 | |||
| 219 | #define MFGPT_SETUP_CNTEN (1 << 15) | ||
| 220 | #define MFGPT_SETUP_CMP2 (1 << 14) | ||
| 221 | #define MFGPT_SETUP_CMP1 (1 << 13) | ||
| 222 | #define MFGPT_SETUP_SETUP (1 << 12) | ||
| 223 | #define MFGPT_SETUP_STOPEN (1 << 11) | ||
| 224 | #define MFGPT_SETUP_EXTEN (1 << 10) | ||
| 225 | #define MFGPT_SETUP_REVEN (1 << 5) | ||
| 226 | #define MFGPT_SETUP_CLKSEL (1 << 4) | ||
| 227 | |||
| 228 | static inline void geode_mfgpt_write(int timer, u16 reg, u16 value) | ||
| 229 | { | ||
| 230 | u32 base = geode_get_dev_base(GEODE_DEV_MFGPT); | ||
| 231 | outw(value, base + reg + (timer * 8)); | ||
| 232 | } | ||
| 233 | |||
| 234 | static inline u16 geode_mfgpt_read(int timer, u16 reg) | ||
| 235 | { | ||
| 236 | u32 base = geode_get_dev_base(GEODE_DEV_MFGPT); | ||
| 237 | return inw(base + reg + (timer * 8)); | ||
| 238 | } | ||
| 239 | |||
| 240 | extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable); | ||
| 241 | extern int geode_mfgpt_set_irq(int timer, int cmp, int *irq, int enable); | ||
| 242 | extern int geode_mfgpt_alloc_timer(int timer, int domain); | ||
| 243 | |||
| 244 | #define geode_mfgpt_setup_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 1) | ||
| 245 | #define geode_mfgpt_release_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 0) | ||
| 246 | |||
| 247 | #ifdef CONFIG_GEODE_MFGPT_TIMER | ||
| 248 | extern int __init mfgpt_timer_setup(void); | ||
| 249 | #else | ||
| 250 | static inline int mfgpt_timer_setup(void) { return 0; } | ||
| 251 | #endif | ||
| 252 | |||
| 253 | #endif /* _ASM_X86_GEODE_H */ | 36 | #endif /* _ASM_X86_GEODE_H */ |
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h index 834a30295fab..3a57385d9fa7 100644 --- a/arch/x86/include/asm/olpc.h +++ b/arch/x86/include/asm/olpc.h | |||
| @@ -120,7 +120,7 @@ extern int olpc_ec_mask_unset(uint8_t bits); | |||
| 120 | 120 | ||
| 121 | /* GPIO assignments */ | 121 | /* GPIO assignments */ |
| 122 | 122 | ||
| 123 | #define OLPC_GPIO_MIC_AC geode_gpio(1) | 123 | #define OLPC_GPIO_MIC_AC 1 |
| 124 | #define OLPC_GPIO_DCON_IRQ geode_gpio(7) | 124 | #define OLPC_GPIO_DCON_IRQ geode_gpio(7) |
| 125 | #define OLPC_GPIO_THRM_ALRM geode_gpio(10) | 125 | #define OLPC_GPIO_THRM_ALRM geode_gpio(10) |
| 126 | #define OLPC_GPIO_SMB_CLK geode_gpio(14) | 126 | #define OLPC_GPIO_SMB_CLK geode_gpio(14) |
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 40e37b10c6c0..c5087d796587 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h | |||
| @@ -35,11 +35,16 @@ | |||
| 35 | # endif | 35 | # endif |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | /* Node not present */ | 38 | /* |
| 39 | #define NUMA_NO_NODE (-1) | 39 | * to preserve the visibility of NUMA_NO_NODE definition, |
| 40 | * moved to there from here. May be used independent of | ||
| 41 | * CONFIG_NUMA. | ||
| 42 | */ | ||
| 43 | #include <linux/numa.h> | ||
| 40 | 44 | ||
| 41 | #ifdef CONFIG_NUMA | 45 | #ifdef CONFIG_NUMA |
| 42 | #include <linux/cpumask.h> | 46 | #include <linux/cpumask.h> |
| 47 | |||
| 43 | #include <asm/mpspec.h> | 48 | #include <asm/mpspec.h> |
| 44 | 49 | ||
| 45 | #ifdef CONFIG_X86_32 | 50 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 4f2e66e29ecc..d87f09bc5a52 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -89,7 +89,6 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | |||
| 89 | obj-$(CONFIG_HPET_TIMER) += hpet.o | 89 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
| 90 | 90 | ||
| 91 | obj-$(CONFIG_K8_NB) += k8.o | 91 | obj-$(CONFIG_K8_NB) += k8.o |
| 92 | obj-$(CONFIG_MGEODE_LX) += geode_32.o mfgpt_32.o | ||
| 93 | obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o | 92 | obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o |
| 94 | obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o | 93 | obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o |
| 95 | 94 | ||
diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index 3c1b12d461d1..e006e56f699c 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <linux/proc_fs.h> | 4 | #include <linux/proc_fs.h> |
| 5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
| 6 | #include <linux/ctype.h> | 6 | #include <linux/ctype.h> |
| 7 | #include <linux/string.h> | ||
| 7 | #include <linux/init.h> | 8 | #include <linux/init.h> |
| 8 | 9 | ||
| 9 | #define LINE_SIZE 80 | 10 | #define LINE_SIZE 80 |
| @@ -133,8 +134,7 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos) | |||
| 133 | return -EINVAL; | 134 | return -EINVAL; |
| 134 | 135 | ||
| 135 | base = simple_strtoull(line + 5, &ptr, 0); | 136 | base = simple_strtoull(line + 5, &ptr, 0); |
| 136 | while (isspace(*ptr)) | 137 | ptr = skip_spaces(ptr); |
| 137 | ptr++; | ||
| 138 | 138 | ||
| 139 | if (strncmp(ptr, "size=", 5)) | 139 | if (strncmp(ptr, "size=", 5)) |
| 140 | return -EINVAL; | 140 | return -EINVAL; |
| @@ -142,14 +142,11 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos) | |||
| 142 | size = simple_strtoull(ptr + 5, &ptr, 0); | 142 | size = simple_strtoull(ptr + 5, &ptr, 0); |
| 143 | if ((base & 0xfff) || (size & 0xfff)) | 143 | if ((base & 0xfff) || (size & 0xfff)) |
| 144 | return -EINVAL; | 144 | return -EINVAL; |
| 145 | while (isspace(*ptr)) | 145 | ptr = skip_spaces(ptr); |
| 146 | ptr++; | ||
| 147 | 146 | ||
| 148 | if (strncmp(ptr, "type=", 5)) | 147 | if (strncmp(ptr, "type=", 5)) |
| 149 | return -EINVAL; | 148 | return -EINVAL; |
| 150 | ptr += 5; | 149 | ptr = skip_spaces(ptr + 5); |
| 151 | while (isspace(*ptr)) | ||
| 152 | ptr++; | ||
| 153 | 150 | ||
| 154 | for (i = 0; i < MTRR_NUM_TYPES; ++i) { | 151 | for (i = 0; i < MTRR_NUM_TYPES; ++i) { |
| 155 | if (strcmp(ptr, mtrr_strings[i])) | 152 | if (strcmp(ptr, mtrr_strings[i])) |
diff --git a/arch/x86/kernel/geode_32.c b/arch/x86/kernel/geode_32.c deleted file mode 100644 index 9b08e852fd1a..000000000000 --- a/arch/x86/kernel/geode_32.c +++ /dev/null | |||
| @@ -1,196 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * AMD Geode southbridge support code | ||
| 3 | * Copyright (C) 2006, Advanced Micro Devices, Inc. | ||
| 4 | * Copyright (C) 2007, Andres Salomon <dilinger@debian.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of version 2 of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/ioport.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <asm/msr.h> | ||
| 16 | #include <asm/geode.h> | ||
| 17 | |||
| 18 | static struct { | ||
| 19 | char *name; | ||
| 20 | u32 msr; | ||
| 21 | int size; | ||
| 22 | u32 base; | ||
| 23 | } lbars[] = { | ||
| 24 | { "geode-pms", MSR_LBAR_PMS, LBAR_PMS_SIZE, 0 }, | ||
| 25 | { "geode-acpi", MSR_LBAR_ACPI, LBAR_ACPI_SIZE, 0 }, | ||
| 26 | { "geode-gpio", MSR_LBAR_GPIO, LBAR_GPIO_SIZE, 0 }, | ||
| 27 | { "geode-mfgpt", MSR_LBAR_MFGPT, LBAR_MFGPT_SIZE, 0 } | ||
| 28 | }; | ||
| 29 | |||
| 30 | static void __init init_lbars(void) | ||
| 31 | { | ||
| 32 | u32 lo, hi; | ||
| 33 | int i; | ||
| 34 | |||
| 35 | for (i = 0; i < ARRAY_SIZE(lbars); i++) { | ||
| 36 | rdmsr(lbars[i].msr, lo, hi); | ||
| 37 | if (hi & 0x01) | ||
| 38 | lbars[i].base = lo & 0x0000ffff; | ||
| 39 | |||
| 40 | if (lbars[i].base == 0) | ||
| 41 | printk(KERN_ERR "geode: Couldn't initialize '%s'\n", | ||
| 42 | lbars[i].name); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | int geode_get_dev_base(unsigned int dev) | ||
| 47 | { | ||
| 48 | BUG_ON(dev >= ARRAY_SIZE(lbars)); | ||
| 49 | return lbars[dev].base; | ||
| 50 | } | ||
| 51 | EXPORT_SYMBOL_GPL(geode_get_dev_base); | ||
| 52 | |||
| 53 | /* === GPIO API === */ | ||
| 54 | |||
| 55 | void geode_gpio_set(u32 gpio, unsigned int reg) | ||
| 56 | { | ||
| 57 | u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | ||
| 58 | |||
| 59 | if (!base) | ||
| 60 | return; | ||
| 61 | |||
| 62 | /* low bank register */ | ||
| 63 | if (gpio & 0xFFFF) | ||
| 64 | outl(gpio & 0xFFFF, base + reg); | ||
| 65 | /* high bank register */ | ||
| 66 | gpio >>= 16; | ||
| 67 | if (gpio) | ||
| 68 | outl(gpio, base + 0x80 + reg); | ||
| 69 | } | ||
| 70 | EXPORT_SYMBOL_GPL(geode_gpio_set); | ||
| 71 | |||
| 72 | void geode_gpio_clear(u32 gpio, unsigned int reg) | ||
| 73 | { | ||
| 74 | u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | ||
| 75 | |||
| 76 | if (!base) | ||
| 77 | return; | ||
| 78 | |||
| 79 | /* low bank register */ | ||
| 80 | if (gpio & 0xFFFF) | ||
| 81 | outl((gpio & 0xFFFF) << 16, base + reg); | ||
| 82 | /* high bank register */ | ||
| 83 | gpio &= (0xFFFF << 16); | ||
| 84 | if (gpio) | ||
| 85 | outl(gpio, base + 0x80 + reg); | ||
| 86 | } | ||
| 87 | EXPORT_SYMBOL_GPL(geode_gpio_clear); | ||
| 88 | |||
| 89 | int geode_gpio_isset(u32 gpio, unsigned int reg) | ||
| 90 | { | ||
| 91 | u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | ||
| 92 | u32 val; | ||
| 93 | |||
| 94 | if (!base) | ||
| 95 | return 0; | ||
| 96 | |||
| 97 | /* low bank register */ | ||
| 98 | if (gpio & 0xFFFF) { | ||
| 99 | val = inl(base + reg) & (gpio & 0xFFFF); | ||
| 100 | if ((gpio & 0xFFFF) == val) | ||
| 101 | return 1; | ||
| 102 | } | ||
| 103 | /* high bank register */ | ||
| 104 | gpio >>= 16; | ||
| 105 | if (gpio) { | ||
| 106 | val = inl(base + 0x80 + reg) & gpio; | ||
| 107 | if (gpio == val) | ||
| 108 | return 1; | ||
| 109 | } | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | EXPORT_SYMBOL_GPL(geode_gpio_isset); | ||
| 113 | |||
| 114 | void geode_gpio_set_irq(unsigned int group, unsigned int irq) | ||
| 115 | { | ||
| 116 | u32 lo, hi; | ||
| 117 | |||
| 118 | if (group > 7 || irq > 15) | ||
| 119 | return; | ||
| 120 | |||
| 121 | rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi); | ||
| 122 | |||
| 123 | lo &= ~(0xF << (group * 4)); | ||
| 124 | lo |= (irq & 0xF) << (group * 4); | ||
| 125 | |||
| 126 | wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi); | ||
| 127 | } | ||
| 128 | EXPORT_SYMBOL_GPL(geode_gpio_set_irq); | ||
| 129 | |||
| 130 | void geode_gpio_setup_event(unsigned int gpio, int pair, int pme) | ||
| 131 | { | ||
| 132 | u32 base = geode_get_dev_base(GEODE_DEV_GPIO); | ||
| 133 | u32 offset, shift, val; | ||
| 134 | |||
| 135 | if (gpio >= 24) | ||
| 136 | offset = GPIO_MAP_W; | ||
| 137 | else if (gpio >= 16) | ||
| 138 | offset = GPIO_MAP_Z; | ||
| 139 | else if (gpio >= 8) | ||
| 140 | offset = GPIO_MAP_Y; | ||
| 141 | else | ||
| 142 | offset = GPIO_MAP_X; | ||
| 143 | |||
| 144 | shift = (gpio % 8) * 4; | ||
| 145 | |||
| 146 | val = inl(base + offset); | ||
| 147 | |||
| 148 | /* Clear whatever was there before */ | ||
| 149 | val &= ~(0xF << shift); | ||
| 150 | |||
| 151 | /* And set the new value */ | ||
| 152 | |||
| 153 | val |= ((pair & 7) << shift); | ||
| 154 | |||
| 155 | /* Set the PME bit if this is a PME event */ | ||
| 156 | |||
| 157 | if (pme) | ||
| 158 | val |= (1 << (shift + 3)); | ||
| 159 | |||
| 160 | outl(val, base + offset); | ||
| 161 | } | ||
| 162 | EXPORT_SYMBOL_GPL(geode_gpio_setup_event); | ||
| 163 | |||
| 164 | int geode_has_vsa2(void) | ||
| 165 | { | ||
| 166 | static int has_vsa2 = -1; | ||
| 167 | |||
| 168 | if (has_vsa2 == -1) { | ||
| 169 | u16 val; | ||
| 170 | |||
| 171 | /* | ||
| 172 | * The VSA has virtual registers that we can query for a | ||
| 173 | * signature. | ||
| 174 | */ | ||
| 175 | outw(VSA_VR_UNLOCK, VSA_VRC_INDEX); | ||
| 176 | outw(VSA_VR_SIGNATURE, VSA_VRC_INDEX); | ||
| 177 | |||
| 178 | val = inw(VSA_VRC_DATA); | ||
| 179 | has_vsa2 = (val == AMD_VSA_SIG || val == GSW_VSA_SIG); | ||
| 180 | } | ||
| 181 | |||
| 182 | return has_vsa2; | ||
| 183 | } | ||
| 184 | EXPORT_SYMBOL_GPL(geode_has_vsa2); | ||
| 185 | |||
| 186 | static int __init geode_southbridge_init(void) | ||
| 187 | { | ||
| 188 | if (!is_geode()) | ||
| 189 | return -ENODEV; | ||
| 190 | |||
| 191 | init_lbars(); | ||
| 192 | (void) mfgpt_timer_setup(); | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | postcore_initcall(geode_southbridge_init); | ||
diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c deleted file mode 100644 index 2a62d843f015..000000000000 --- a/arch/x86/kernel/mfgpt_32.c +++ /dev/null | |||
| @@ -1,410 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver/API for AMD Geode Multi-Function General Purpose Timers (MFGPT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006, Advanced Micro Devices, Inc. | ||
| 5 | * Copyright (C) 2007, Andres Salomon <dilinger@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of version 2 of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * The MFGPTs are documented in AMD Geode CS5536 Companion Device Data Book. | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * We are using the 32.768kHz input clock - it's the only one that has the | ||
| 16 | * ranges we find desirable. The following table lists the suitable | ||
| 17 | * divisors and the associated Hz, minimum interval and the maximum interval: | ||
| 18 | * | ||
| 19 | * Divisor Hz Min Delta (s) Max Delta (s) | ||
| 20 | * 1 32768 .00048828125 2.000 | ||
| 21 | * 2 16384 .0009765625 4.000 | ||
| 22 | * 4 8192 .001953125 8.000 | ||
| 23 | * 8 4096 .00390625 16.000 | ||
| 24 | * 16 2048 .0078125 32.000 | ||
| 25 | * 32 1024 .015625 64.000 | ||
| 26 | * 64 512 .03125 128.000 | ||
| 27 | * 128 256 .0625 256.000 | ||
| 28 | * 256 128 .125 512.000 | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/kernel.h> | ||
| 32 | #include <linux/interrupt.h> | ||
| 33 | #include <linux/module.h> | ||
| 34 | #include <asm/geode.h> | ||
| 35 | |||
| 36 | #define MFGPT_DEFAULT_IRQ 7 | ||
| 37 | |||
| 38 | static struct mfgpt_timer_t { | ||
| 39 | unsigned int avail:1; | ||
| 40 | } mfgpt_timers[MFGPT_MAX_TIMERS]; | ||
| 41 | |||
| 42 | /* Selected from the table above */ | ||
| 43 | |||
| 44 | #define MFGPT_DIVISOR 16 | ||
| 45 | #define MFGPT_SCALE 4 /* divisor = 2^(scale) */ | ||
| 46 | #define MFGPT_HZ (32768 / MFGPT_DIVISOR) | ||
| 47 | #define MFGPT_PERIODIC (MFGPT_HZ / HZ) | ||
| 48 | |||
| 49 | /* Allow for disabling of MFGPTs */ | ||
| 50 | static int disable; | ||
| 51 | static int __init mfgpt_disable(char *s) | ||
| 52 | { | ||
| 53 | disable = 1; | ||
| 54 | return 1; | ||
| 55 | } | ||
| 56 | __setup("nomfgpt", mfgpt_disable); | ||
| 57 | |||
| 58 | /* Reset the MFGPT timers. This is required by some broken BIOSes which already | ||
| 59 | * do the same and leave the system in an unstable state. TinyBIOS 0.98 is | ||
| 60 | * affected at least (0.99 is OK with MFGPT workaround left to off). | ||
| 61 | */ | ||
| 62 | static int __init mfgpt_fix(char *s) | ||
| 63 | { | ||
| 64 | u32 val, dummy; | ||
| 65 | |||
| 66 | /* The following udocumented bit resets the MFGPT timers */ | ||
| 67 | val = 0xFF; dummy = 0; | ||
| 68 | wrmsr(MSR_MFGPT_SETUP, val, dummy); | ||
| 69 | return 1; | ||
| 70 | } | ||
| 71 | __setup("mfgptfix", mfgpt_fix); | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Check whether any MFGPTs are available for the kernel to use. In most | ||
| 75 | * cases, firmware that uses AMD's VSA code will claim all timers during | ||
| 76 | * bootup; we certainly don't want to take them if they're already in use. | ||
| 77 | * In other cases (such as with VSAless OpenFirmware), the system firmware | ||
| 78 | * leaves timers available for us to use. | ||
| 79 | */ | ||
| 80 | |||
| 81 | |||
| 82 | static int timers = -1; | ||
| 83 | |||
| 84 | static void geode_mfgpt_detect(void) | ||
| 85 | { | ||
| 86 | int i; | ||
| 87 | u16 val; | ||
| 88 | |||
| 89 | timers = 0; | ||
| 90 | |||
| 91 | if (disable) { | ||
| 92 | printk(KERN_INFO "geode-mfgpt: MFGPT support is disabled\n"); | ||
| 93 | goto done; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (!geode_get_dev_base(GEODE_DEV_MFGPT)) { | ||
| 97 | printk(KERN_INFO "geode-mfgpt: MFGPT LBAR is not set up\n"); | ||
| 98 | goto done; | ||
| 99 | } | ||
| 100 | |||
| 101 | for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | ||
| 102 | val = geode_mfgpt_read(i, MFGPT_REG_SETUP); | ||
| 103 | if (!(val & MFGPT_SETUP_SETUP)) { | ||
| 104 | mfgpt_timers[i].avail = 1; | ||
| 105 | timers++; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | done: | ||
| 110 | printk(KERN_INFO "geode-mfgpt: %d MFGPT timers available.\n", timers); | ||
| 111 | } | ||
| 112 | |||
| 113 | int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable) | ||
| 114 | { | ||
| 115 | u32 msr, mask, value, dummy; | ||
| 116 | int shift = (cmp == MFGPT_CMP1) ? 0 : 8; | ||
| 117 | |||
| 118 | if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | ||
| 119 | return -EIO; | ||
| 120 | |||
| 121 | /* | ||
| 122 | * The register maps for these are described in sections 6.17.1.x of | ||
| 123 | * the AMD Geode CS5536 Companion Device Data Book. | ||
| 124 | */ | ||
| 125 | switch (event) { | ||
| 126 | case MFGPT_EVENT_RESET: | ||
| 127 | /* | ||
| 128 | * XXX: According to the docs, we cannot reset timers above | ||
| 129 | * 6; that is, resets for 7 and 8 will be ignored. Is this | ||
| 130 | * a problem? -dilinger | ||
| 131 | */ | ||
| 132 | msr = MSR_MFGPT_NR; | ||
| 133 | mask = 1 << (timer + 24); | ||
| 134 | break; | ||
| 135 | |||
| 136 | case MFGPT_EVENT_NMI: | ||
| 137 | msr = MSR_MFGPT_NR; | ||
| 138 | mask = 1 << (timer + shift); | ||
| 139 | break; | ||
| 140 | |||
| 141 | case MFGPT_EVENT_IRQ: | ||
| 142 | msr = MSR_MFGPT_IRQ; | ||
| 143 | mask = 1 << (timer + shift); | ||
| 144 | break; | ||
| 145 | |||
| 146 | default: | ||
| 147 | return -EIO; | ||
| 148 | } | ||
| 149 | |||
| 150 | rdmsr(msr, value, dummy); | ||
| 151 | |||
| 152 | if (enable) | ||
| 153 | value |= mask; | ||
| 154 | else | ||
| 155 | value &= ~mask; | ||
| 156 | |||
| 157 | wrmsr(msr, value, dummy); | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | EXPORT_SYMBOL_GPL(geode_mfgpt_toggle_event); | ||
| 161 | |||
| 162 | int geode_mfgpt_set_irq(int timer, int cmp, int *irq, int enable) | ||
| 163 | { | ||
| 164 | u32 zsel, lpc, dummy; | ||
| 165 | int shift; | ||
| 166 | |||
| 167 | if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | ||
| 168 | return -EIO; | ||
| 169 | |||
| 170 | /* | ||
| 171 | * Unfortunately, MFGPTs come in pairs sharing their IRQ lines. If VSA | ||
| 172 | * is using the same CMP of the timer's Siamese twin, the IRQ is set to | ||
| 173 | * 2, and we mustn't use nor change it. | ||
| 174 | * XXX: Likewise, 2 Linux drivers might clash if the 2nd overwrites the | ||
| 175 | * IRQ of the 1st. This can only happen if forcing an IRQ, calling this | ||
| 176 | * with *irq==0 is safe. Currently there _are_ no 2 drivers. | ||
| 177 | */ | ||
| 178 | rdmsr(MSR_PIC_ZSEL_LOW, zsel, dummy); | ||
| 179 | shift = ((cmp == MFGPT_CMP1 ? 0 : 4) + timer % 4) * 4; | ||
| 180 | if (((zsel >> shift) & 0xF) == 2) | ||
| 181 | return -EIO; | ||
| 182 | |||
| 183 | /* Choose IRQ: if none supplied, keep IRQ already set or use default */ | ||
| 184 | if (!*irq) | ||
| 185 | *irq = (zsel >> shift) & 0xF; | ||
| 186 | if (!*irq) | ||
| 187 | *irq = MFGPT_DEFAULT_IRQ; | ||
| 188 | |||
| 189 | /* Can't use IRQ if it's 0 (=disabled), 2, or routed to LPC */ | ||
| 190 | if (*irq < 1 || *irq == 2 || *irq > 15) | ||
| 191 | return -EIO; | ||
| 192 | rdmsr(MSR_PIC_IRQM_LPC, lpc, dummy); | ||
| 193 | if (lpc & (1 << *irq)) | ||
| 194 | return -EIO; | ||
| 195 | |||
| 196 | /* All chosen and checked - go for it */ | ||
| 197 | if (geode_mfgpt_toggle_event(timer, cmp, MFGPT_EVENT_IRQ, enable)) | ||
| 198 | return -EIO; | ||
| 199 | if (enable) { | ||
| 200 | zsel = (zsel & ~(0xF << shift)) | (*irq << shift); | ||
| 201 | wrmsr(MSR_PIC_ZSEL_LOW, zsel, dummy); | ||
| 202 | } | ||
| 203 | |||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int mfgpt_get(int timer) | ||
| 208 | { | ||
| 209 | mfgpt_timers[timer].avail = 0; | ||
| 210 | printk(KERN_INFO "geode-mfgpt: Registered timer %d\n", timer); | ||
| 211 | return timer; | ||
| 212 | } | ||
| 213 | |||
| 214 | int geode_mfgpt_alloc_timer(int timer, int domain) | ||
| 215 | { | ||
| 216 | int i; | ||
| 217 | |||
| 218 | if (timers == -1) { | ||
| 219 | /* timers haven't been detected yet */ | ||
| 220 | geode_mfgpt_detect(); | ||
| 221 | } | ||
| 222 | |||
| 223 | if (!timers) | ||
| 224 | return -1; | ||
| 225 | |||
| 226 | if (timer >= MFGPT_MAX_TIMERS) | ||
| 227 | return -1; | ||
| 228 | |||
| 229 | if (timer < 0) { | ||
| 230 | /* Try to find an available timer */ | ||
| 231 | for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | ||
| 232 | if (mfgpt_timers[i].avail) | ||
| 233 | return mfgpt_get(i); | ||
| 234 | |||
| 235 | if (i == 5 && domain == MFGPT_DOMAIN_WORKING) | ||
| 236 | break; | ||
| 237 | } | ||
| 238 | } else { | ||
| 239 | /* If they requested a specific timer, try to honor that */ | ||
| 240 | if (mfgpt_timers[timer].avail) | ||
| 241 | return mfgpt_get(timer); | ||
| 242 | } | ||
| 243 | |||
| 244 | /* No timers available - too bad */ | ||
| 245 | return -1; | ||
| 246 | } | ||
| 247 | EXPORT_SYMBOL_GPL(geode_mfgpt_alloc_timer); | ||
| 248 | |||
| 249 | |||
| 250 | #ifdef CONFIG_GEODE_MFGPT_TIMER | ||
| 251 | |||
| 252 | /* | ||
| 253 | * The MFPGT timers on the CS5536 provide us with suitable timers to use | ||
| 254 | * as clock event sources - not as good as a HPET or APIC, but certainly | ||
| 255 | * better than the PIT. This isn't a general purpose MFGPT driver, but | ||
| 256 | * a simplified one designed specifically to act as a clock event source. | ||
| 257 | * For full details about the MFGPT, please consult the CS5536 data sheet. | ||
| 258 | */ | ||
| 259 | |||
| 260 | #include <linux/clocksource.h> | ||
| 261 | #include <linux/clockchips.h> | ||
| 262 | |||
| 263 | static unsigned int mfgpt_tick_mode = CLOCK_EVT_MODE_SHUTDOWN; | ||
| 264 | static u16 mfgpt_event_clock; | ||
| 265 | |||
| 266 | static int irq; | ||
| 267 | static int __init mfgpt_setup(char *str) | ||
| 268 | { | ||
| 269 | get_option(&str, &irq); | ||
| 270 | return 1; | ||
| 271 | } | ||
| 272 | __setup("mfgpt_irq=", mfgpt_setup); | ||
| 273 | |||
| 274 | static void mfgpt_disable_timer(u16 clock) | ||
| 275 | { | ||
| 276 | /* avoid races by clearing CMP1 and CMP2 unconditionally */ | ||
| 277 | geode_mfgpt_write(clock, MFGPT_REG_SETUP, (u16) ~MFGPT_SETUP_CNTEN | | ||
| 278 | MFGPT_SETUP_CMP1 | MFGPT_SETUP_CMP2); | ||
| 279 | } | ||
| 280 | |||
| 281 | static int mfgpt_next_event(unsigned long, struct clock_event_device *); | ||
| 282 | static void mfgpt_set_mode(enum clock_event_mode, struct clock_event_device *); | ||
| 283 | |||
| 284 | static struct clock_event_device mfgpt_clockevent = { | ||
| 285 | .name = "mfgpt-timer", | ||
| 286 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
| 287 | .set_mode = mfgpt_set_mode, | ||
| 288 | .set_next_event = mfgpt_next_event, | ||
| 289 | .rating = 250, | ||
| 290 | .cpumask = cpu_all_mask, | ||
| 291 | .shift = 32 | ||
| 292 | }; | ||
| 293 | |||
| 294 | static void mfgpt_start_timer(u16 delta) | ||
| 295 | { | ||
| 296 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_CMP2, (u16) delta); | ||
| 297 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | ||
| 298 | |||
| 299 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | ||
| 300 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
| 301 | } | ||
| 302 | |||
| 303 | static void mfgpt_set_mode(enum clock_event_mode mode, | ||
| 304 | struct clock_event_device *evt) | ||
| 305 | { | ||
| 306 | mfgpt_disable_timer(mfgpt_event_clock); | ||
| 307 | |||
| 308 | if (mode == CLOCK_EVT_MODE_PERIODIC) | ||
| 309 | mfgpt_start_timer(MFGPT_PERIODIC); | ||
| 310 | |||
| 311 | mfgpt_tick_mode = mode; | ||
| 312 | } | ||
| 313 | |||
| 314 | static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) | ||
| 315 | { | ||
| 316 | mfgpt_start_timer(delta); | ||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | static irqreturn_t mfgpt_tick(int irq, void *dev_id) | ||
| 321 | { | ||
| 322 | u16 val = geode_mfgpt_read(mfgpt_event_clock, MFGPT_REG_SETUP); | ||
| 323 | |||
| 324 | /* See if the interrupt was for us */ | ||
| 325 | if (!(val & (MFGPT_SETUP_SETUP | MFGPT_SETUP_CMP2 | MFGPT_SETUP_CMP1))) | ||
| 326 | return IRQ_NONE; | ||
| 327 | |||
| 328 | /* Turn off the clock (and clear the event) */ | ||
| 329 | mfgpt_disable_timer(mfgpt_event_clock); | ||
| 330 | |||
| 331 | if (mfgpt_tick_mode == CLOCK_EVT_MODE_SHUTDOWN) | ||
| 332 | return IRQ_HANDLED; | ||
| 333 | |||
| 334 | /* Clear the counter */ | ||
| 335 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | ||
| 336 | |||
| 337 | /* Restart the clock in periodic mode */ | ||
| 338 | |||
| 339 | if (mfgpt_tick_mode == CLOCK_EVT_MODE_PERIODIC) { | ||
| 340 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | ||
| 341 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
| 342 | } | ||
| 343 | |||
| 344 | mfgpt_clockevent.event_handler(&mfgpt_clockevent); | ||
| 345 | return IRQ_HANDLED; | ||
| 346 | } | ||
| 347 | |||
| 348 | static struct irqaction mfgptirq = { | ||
| 349 | .handler = mfgpt_tick, | ||
| 350 | .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, | ||
| 351 | .name = "mfgpt-timer" | ||
| 352 | }; | ||
| 353 | |||
| 354 | int __init mfgpt_timer_setup(void) | ||
| 355 | { | ||
| 356 | int timer, ret; | ||
| 357 | u16 val; | ||
| 358 | |||
| 359 | timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING); | ||
| 360 | if (timer < 0) { | ||
| 361 | printk(KERN_ERR | ||
| 362 | "mfgpt-timer: Could not allocate a MFPGT timer\n"); | ||
| 363 | return -ENODEV; | ||
| 364 | } | ||
| 365 | |||
| 366 | mfgpt_event_clock = timer; | ||
| 367 | |||
| 368 | /* Set up the IRQ on the MFGPT side */ | ||
| 369 | if (geode_mfgpt_setup_irq(mfgpt_event_clock, MFGPT_CMP2, &irq)) { | ||
| 370 | printk(KERN_ERR "mfgpt-timer: Could not set up IRQ %d\n", irq); | ||
| 371 | return -EIO; | ||
| 372 | } | ||
| 373 | |||
| 374 | /* And register it with the kernel */ | ||
| 375 | ret = setup_irq(irq, &mfgptirq); | ||
| 376 | |||
| 377 | if (ret) { | ||
| 378 | printk(KERN_ERR | ||
| 379 | "mfgpt-timer: Unable to set up the interrupt.\n"); | ||
| 380 | goto err; | ||
| 381 | } | ||
| 382 | |||
| 383 | /* Set the clock scale and enable the event mode for CMP2 */ | ||
| 384 | val = MFGPT_SCALE | (3 << 8); | ||
| 385 | |||
| 386 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val); | ||
| 387 | |||
| 388 | /* Set up the clock event */ | ||
| 389 | mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, | ||
| 390 | mfgpt_clockevent.shift); | ||
| 391 | mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF, | ||
| 392 | &mfgpt_clockevent); | ||
| 393 | mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE, | ||
| 394 | &mfgpt_clockevent); | ||
| 395 | |||
| 396 | printk(KERN_INFO | ||
| 397 | "mfgpt-timer: Registering MFGPT timer %d as a clock event, using IRQ %d\n", | ||
| 398 | timer, irq); | ||
| 399 | clockevents_register_device(&mfgpt_clockevent); | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | |||
| 403 | err: | ||
| 404 | geode_mfgpt_release_irq(mfgpt_event_clock, MFGPT_CMP2, &irq); | ||
| 405 | printk(KERN_ERR | ||
| 406 | "mfgpt-timer: Unable to set up the MFGPT clock source\n"); | ||
| 407 | return -EIO; | ||
| 408 | } | ||
| 409 | |||
| 410 | #endif | ||
diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c index 4006c522adc7..9d1d263f786f 100644 --- a/arch/x86/kernel/olpc.c +++ b/arch/x86/kernel/olpc.c | |||
| @@ -212,7 +212,7 @@ static int __init olpc_init(void) | |||
| 212 | unsigned char *romsig; | 212 | unsigned char *romsig; |
| 213 | 213 | ||
| 214 | /* The ioremap check is dangerous; limit what we run it on */ | 214 | /* The ioremap check is dangerous; limit what we run it on */ |
| 215 | if (!is_geode() || geode_has_vsa2()) | 215 | if (!is_geode() || cs5535_has_vsa2()) |
| 216 | return 0; | 216 | return 0; |
| 217 | 217 | ||
| 218 | spin_lock_init(&ec_lock); | 218 | spin_lock_init(&ec_lock); |
| @@ -244,7 +244,7 @@ static int __init olpc_init(void) | |||
| 244 | (unsigned char *) &olpc_platform_info.ecver, 1); | 244 | (unsigned char *) &olpc_platform_info.ecver, 1); |
| 245 | 245 | ||
| 246 | /* check to see if the VSA exists */ | 246 | /* check to see if the VSA exists */ |
| 247 | if (geode_has_vsa2()) | 247 | if (cs5535_has_vsa2()) |
| 248 | olpc_platform_info.flags |= OLPC_F_VSA; | 248 | olpc_platform_info.flags |= OLPC_F_VSA; |
| 249 | 249 | ||
| 250 | printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", | 250 | printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", |
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index 201eab63b05f..fda313ebbb03 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <asm/reboot_fixups.h> | 13 | #include <asm/reboot_fixups.h> |
| 14 | #include <asm/msr.h> | 14 | #include <asm/msr.h> |
| 15 | #include <asm/geode.h> | 15 | #include <linux/cs5535.h> |
| 16 | 16 | ||
| 17 | static void cs5530a_warm_reset(struct pci_dev *dev) | 17 | static void cs5530a_warm_reset(struct pci_dev *dev) |
| 18 | { | 18 | { |
diff --git a/drivers/Kconfig b/drivers/Kconfig index 26e434ad373c..8a07363417ed 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
| @@ -96,6 +96,8 @@ source "drivers/edac/Kconfig" | |||
| 96 | 96 | ||
| 97 | source "drivers/rtc/Kconfig" | 97 | source "drivers/rtc/Kconfig" |
| 98 | 98 | ||
| 99 | source "drivers/clocksource/Kconfig" | ||
| 100 | |||
| 99 | source "drivers/dma/Kconfig" | 101 | source "drivers/dma/Kconfig" |
| 100 | 102 | ||
| 101 | source "drivers/dca/Kconfig" | 103 | source "drivers/dca/Kconfig" |
diff --git a/drivers/base/node.c b/drivers/base/node.c index 1fe5536d404f..70122791683d 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
| @@ -173,6 +173,47 @@ static ssize_t node_read_distance(struct sys_device * dev, | |||
| 173 | } | 173 | } |
| 174 | static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL); | 174 | static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL); |
| 175 | 175 | ||
| 176 | #ifdef CONFIG_HUGETLBFS | ||
| 177 | /* | ||
| 178 | * hugetlbfs per node attributes registration interface: | ||
| 179 | * When/if hugetlb[fs] subsystem initializes [sometime after this module], | ||
| 180 | * it will register its per node attributes for all online nodes with | ||
| 181 | * memory. It will also call register_hugetlbfs_with_node(), below, to | ||
| 182 | * register its attribute registration functions with this node driver. | ||
| 183 | * Once these hooks have been initialized, the node driver will call into | ||
| 184 | * the hugetlb module to [un]register attributes for hot-plugged nodes. | ||
| 185 | */ | ||
| 186 | static node_registration_func_t __hugetlb_register_node; | ||
| 187 | static node_registration_func_t __hugetlb_unregister_node; | ||
| 188 | |||
| 189 | static inline bool hugetlb_register_node(struct node *node) | ||
| 190 | { | ||
| 191 | if (__hugetlb_register_node && | ||
| 192 | node_state(node->sysdev.id, N_HIGH_MEMORY)) { | ||
| 193 | __hugetlb_register_node(node); | ||
| 194 | return true; | ||
| 195 | } | ||
| 196 | return false; | ||
| 197 | } | ||
| 198 | |||
| 199 | static inline void hugetlb_unregister_node(struct node *node) | ||
| 200 | { | ||
| 201 | if (__hugetlb_unregister_node) | ||
| 202 | __hugetlb_unregister_node(node); | ||
| 203 | } | ||
| 204 | |||
| 205 | void register_hugetlbfs_with_node(node_registration_func_t doregister, | ||
| 206 | node_registration_func_t unregister) | ||
| 207 | { | ||
| 208 | __hugetlb_register_node = doregister; | ||
| 209 | __hugetlb_unregister_node = unregister; | ||
| 210 | } | ||
| 211 | #else | ||
| 212 | static inline void hugetlb_register_node(struct node *node) {} | ||
| 213 | |||
| 214 | static inline void hugetlb_unregister_node(struct node *node) {} | ||
| 215 | #endif | ||
| 216 | |||
| 176 | 217 | ||
| 177 | /* | 218 | /* |
| 178 | * register_node - Setup a sysfs device for a node. | 219 | * register_node - Setup a sysfs device for a node. |
| @@ -196,6 +237,8 @@ int register_node(struct node *node, int num, struct node *parent) | |||
| 196 | sysdev_create_file(&node->sysdev, &attr_distance); | 237 | sysdev_create_file(&node->sysdev, &attr_distance); |
| 197 | 238 | ||
| 198 | scan_unevictable_register_node(node); | 239 | scan_unevictable_register_node(node); |
| 240 | |||
| 241 | hugetlb_register_node(node); | ||
| 199 | } | 242 | } |
| 200 | return error; | 243 | return error; |
| 201 | } | 244 | } |
| @@ -216,6 +259,7 @@ void unregister_node(struct node *node) | |||
| 216 | sysdev_remove_file(&node->sysdev, &attr_distance); | 259 | sysdev_remove_file(&node->sysdev, &attr_distance); |
| 217 | 260 | ||
| 218 | scan_unevictable_unregister_node(node); | 261 | scan_unevictable_unregister_node(node); |
| 262 | hugetlb_unregister_node(node); /* no-op, if memoryless node */ | ||
| 219 | 263 | ||
| 220 | sysdev_unregister(&node->sysdev); | 264 | sysdev_unregister(&node->sysdev); |
| 221 | } | 265 | } |
| @@ -227,26 +271,43 @@ struct node node_devices[MAX_NUMNODES]; | |||
| 227 | */ | 271 | */ |
| 228 | int register_cpu_under_node(unsigned int cpu, unsigned int nid) | 272 | int register_cpu_under_node(unsigned int cpu, unsigned int nid) |
| 229 | { | 273 | { |
| 230 | if (node_online(nid)) { | 274 | int ret; |
| 231 | struct sys_device *obj = get_cpu_sysdev(cpu); | 275 | struct sys_device *obj; |
| 232 | if (!obj) | ||
| 233 | return 0; | ||
| 234 | return sysfs_create_link(&node_devices[nid].sysdev.kobj, | ||
| 235 | &obj->kobj, | ||
| 236 | kobject_name(&obj->kobj)); | ||
| 237 | } | ||
| 238 | 276 | ||
| 239 | return 0; | 277 | if (!node_online(nid)) |
| 278 | return 0; | ||
| 279 | |||
| 280 | obj = get_cpu_sysdev(cpu); | ||
| 281 | if (!obj) | ||
| 282 | return 0; | ||
| 283 | |||
| 284 | ret = sysfs_create_link(&node_devices[nid].sysdev.kobj, | ||
| 285 | &obj->kobj, | ||
| 286 | kobject_name(&obj->kobj)); | ||
| 287 | if (ret) | ||
| 288 | return ret; | ||
| 289 | |||
| 290 | return sysfs_create_link(&obj->kobj, | ||
| 291 | &node_devices[nid].sysdev.kobj, | ||
| 292 | kobject_name(&node_devices[nid].sysdev.kobj)); | ||
| 240 | } | 293 | } |
| 241 | 294 | ||
| 242 | int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) | 295 | int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) |
| 243 | { | 296 | { |
| 244 | if (node_online(nid)) { | 297 | struct sys_device *obj; |
| 245 | struct sys_device *obj = get_cpu_sysdev(cpu); | 298 | |
| 246 | if (obj) | 299 | if (!node_online(nid)) |
| 247 | sysfs_remove_link(&node_devices[nid].sysdev.kobj, | 300 | return 0; |
| 248 | kobject_name(&obj->kobj)); | 301 | |
| 249 | } | 302 | obj = get_cpu_sysdev(cpu); |
| 303 | if (!obj) | ||
| 304 | return 0; | ||
| 305 | |||
| 306 | sysfs_remove_link(&node_devices[nid].sysdev.kobj, | ||
| 307 | kobject_name(&obj->kobj)); | ||
| 308 | sysfs_remove_link(&obj->kobj, | ||
| 309 | kobject_name(&node_devices[nid].sysdev.kobj)); | ||
| 310 | |||
| 250 | return 0; | 311 | return 0; |
| 251 | } | 312 | } |
| 252 | 313 | ||
| @@ -268,6 +329,7 @@ static int get_nid_for_pfn(unsigned long pfn) | |||
| 268 | /* register memory section under specified node if it spans that node */ | 329 | /* register memory section under specified node if it spans that node */ |
| 269 | int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) | 330 | int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) |
| 270 | { | 331 | { |
| 332 | int ret; | ||
| 271 | unsigned long pfn, sect_start_pfn, sect_end_pfn; | 333 | unsigned long pfn, sect_start_pfn, sect_end_pfn; |
| 272 | 334 | ||
| 273 | if (!mem_blk) | 335 | if (!mem_blk) |
| @@ -284,9 +346,15 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) | |||
| 284 | continue; | 346 | continue; |
| 285 | if (page_nid != nid) | 347 | if (page_nid != nid) |
| 286 | continue; | 348 | continue; |
| 287 | return sysfs_create_link_nowarn(&node_devices[nid].sysdev.kobj, | 349 | ret = sysfs_create_link_nowarn(&node_devices[nid].sysdev.kobj, |
| 288 | &mem_blk->sysdev.kobj, | 350 | &mem_blk->sysdev.kobj, |
| 289 | kobject_name(&mem_blk->sysdev.kobj)); | 351 | kobject_name(&mem_blk->sysdev.kobj)); |
| 352 | if (ret) | ||
| 353 | return ret; | ||
| 354 | |||
| 355 | return sysfs_create_link_nowarn(&mem_blk->sysdev.kobj, | ||
| 356 | &node_devices[nid].sysdev.kobj, | ||
| 357 | kobject_name(&node_devices[nid].sysdev.kobj)); | ||
| 290 | } | 358 | } |
| 291 | /* mem section does not span the specified node */ | 359 | /* mem section does not span the specified node */ |
| 292 | return 0; | 360 | return 0; |
| @@ -295,12 +363,16 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) | |||
| 295 | /* unregister memory section under all nodes that it spans */ | 363 | /* unregister memory section under all nodes that it spans */ |
| 296 | int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) | 364 | int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) |
| 297 | { | 365 | { |
| 298 | nodemask_t unlinked_nodes; | 366 | NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL); |
| 299 | unsigned long pfn, sect_start_pfn, sect_end_pfn; | 367 | unsigned long pfn, sect_start_pfn, sect_end_pfn; |
| 300 | 368 | ||
| 301 | if (!mem_blk) | 369 | if (!mem_blk) { |
| 370 | NODEMASK_FREE(unlinked_nodes); | ||
| 302 | return -EFAULT; | 371 | return -EFAULT; |
| 303 | nodes_clear(unlinked_nodes); | 372 | } |
| 373 | if (!unlinked_nodes) | ||
| 374 | return -ENOMEM; | ||
| 375 | nodes_clear(*unlinked_nodes); | ||
| 304 | sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); | 376 | sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); |
| 305 | sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; | 377 | sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; |
| 306 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { | 378 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { |
| @@ -311,11 +383,14 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) | |||
| 311 | continue; | 383 | continue; |
| 312 | if (!node_online(nid)) | 384 | if (!node_online(nid)) |
| 313 | continue; | 385 | continue; |
| 314 | if (node_test_and_set(nid, unlinked_nodes)) | 386 | if (node_test_and_set(nid, *unlinked_nodes)) |
| 315 | continue; | 387 | continue; |
| 316 | sysfs_remove_link(&node_devices[nid].sysdev.kobj, | 388 | sysfs_remove_link(&node_devices[nid].sysdev.kobj, |
| 317 | kobject_name(&mem_blk->sysdev.kobj)); | 389 | kobject_name(&mem_blk->sysdev.kobj)); |
| 390 | sysfs_remove_link(&mem_blk->sysdev.kobj, | ||
| 391 | kobject_name(&node_devices[nid].sysdev.kobj)); | ||
| 318 | } | 392 | } |
| 393 | NODEMASK_FREE(unlinked_nodes); | ||
| 319 | return 0; | 394 | return 0; |
| 320 | } | 395 | } |
| 321 | 396 | ||
| @@ -345,9 +420,77 @@ static int link_mem_sections(int nid) | |||
| 345 | } | 420 | } |
| 346 | return err; | 421 | return err; |
| 347 | } | 422 | } |
| 348 | #else | 423 | |
| 424 | #ifdef CONFIG_HUGETLBFS | ||
| 425 | /* | ||
| 426 | * Handle per node hstate attribute [un]registration on transistions | ||
| 427 | * to/from memoryless state. | ||
| 428 | */ | ||
| 429 | static void node_hugetlb_work(struct work_struct *work) | ||
| 430 | { | ||
| 431 | struct node *node = container_of(work, struct node, node_work); | ||
| 432 | |||
| 433 | /* | ||
| 434 | * We only get here when a node transitions to/from memoryless state. | ||
| 435 | * We can detect which transition occurred by examining whether the | ||
| 436 | * node has memory now. hugetlb_register_node() already check this | ||
| 437 | * so we try to register the attributes. If that fails, then the | ||
| 438 | * node has transitioned to memoryless, try to unregister the | ||
| 439 | * attributes. | ||
| 440 | */ | ||
| 441 | if (!hugetlb_register_node(node)) | ||
| 442 | hugetlb_unregister_node(node); | ||
| 443 | } | ||
| 444 | |||
| 445 | static void init_node_hugetlb_work(int nid) | ||
| 446 | { | ||
| 447 | INIT_WORK(&node_devices[nid].node_work, node_hugetlb_work); | ||
| 448 | } | ||
| 449 | |||
| 450 | static int node_memory_callback(struct notifier_block *self, | ||
| 451 | unsigned long action, void *arg) | ||
| 452 | { | ||
| 453 | struct memory_notify *mnb = arg; | ||
| 454 | int nid = mnb->status_change_nid; | ||
| 455 | |||
| 456 | switch (action) { | ||
| 457 | case MEM_ONLINE: | ||
| 458 | case MEM_OFFLINE: | ||
| 459 | /* | ||
| 460 | * offload per node hstate [un]registration to a work thread | ||
| 461 | * when transitioning to/from memoryless state. | ||
| 462 | */ | ||
| 463 | if (nid != NUMA_NO_NODE) | ||
| 464 | schedule_work(&node_devices[nid].node_work); | ||
| 465 | break; | ||
| 466 | |||
| 467 | case MEM_GOING_ONLINE: | ||
| 468 | case MEM_GOING_OFFLINE: | ||
| 469 | case MEM_CANCEL_ONLINE: | ||
| 470 | case MEM_CANCEL_OFFLINE: | ||
| 471 | default: | ||
| 472 | break; | ||
| 473 | } | ||
| 474 | |||
| 475 | return NOTIFY_OK; | ||
| 476 | } | ||
| 477 | #endif /* CONFIG_HUGETLBFS */ | ||
| 478 | #else /* !CONFIG_MEMORY_HOTPLUG_SPARSE */ | ||
| 479 | |||
| 349 | static int link_mem_sections(int nid) { return 0; } | 480 | static int link_mem_sections(int nid) { return 0; } |
| 350 | #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ | 481 | #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ |
| 482 | |||
| 483 | #if !defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || \ | ||
| 484 | !defined(CONFIG_HUGETLBFS) | ||
| 485 | static inline int node_memory_callback(struct notifier_block *self, | ||
| 486 | unsigned long action, void *arg) | ||
| 487 | { | ||
| 488 | return NOTIFY_OK; | ||
| 489 | } | ||
| 490 | |||
| 491 | static void init_node_hugetlb_work(int nid) { } | ||
| 492 | |||
| 493 | #endif | ||
| 351 | 494 | ||
| 352 | int register_one_node(int nid) | 495 | int register_one_node(int nid) |
| 353 | { | 496 | { |
| @@ -371,6 +514,9 @@ int register_one_node(int nid) | |||
| 371 | 514 | ||
| 372 | /* link memory sections under this node */ | 515 | /* link memory sections under this node */ |
| 373 | error = link_mem_sections(nid); | 516 | error = link_mem_sections(nid); |
| 517 | |||
| 518 | /* initialize work queue for memory hot plug */ | ||
| 519 | init_node_hugetlb_work(nid); | ||
| 374 | } | 520 | } |
| 375 | 521 | ||
| 376 | return error; | 522 | return error; |
| @@ -460,13 +606,17 @@ static int node_states_init(void) | |||
| 460 | return err; | 606 | return err; |
| 461 | } | 607 | } |
| 462 | 608 | ||
| 609 | #define NODE_CALLBACK_PRI 2 /* lower than SLAB */ | ||
| 463 | static int __init register_node_type(void) | 610 | static int __init register_node_type(void) |
| 464 | { | 611 | { |
| 465 | int ret; | 612 | int ret; |
| 466 | 613 | ||
| 467 | ret = sysdev_class_register(&node_class); | 614 | ret = sysdev_class_register(&node_class); |
| 468 | if (!ret) | 615 | if (!ret) { |
| 469 | ret = node_states_init(); | 616 | ret = node_states_init(); |
| 617 | hotplug_memory_notifier(node_memory_callback, | ||
| 618 | NODE_CALLBACK_PRI); | ||
| 619 | } | ||
| 470 | 620 | ||
| 471 | /* | 621 | /* |
| 472 | * Note: we're not going to unregister the node class if we fail | 622 | * Note: we're not going to unregister the node class if we fail |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 5c01f747571b..3266b4f65daa 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
| @@ -3497,6 +3497,9 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | |||
| 3497 | ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) | 3497 | ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) |
| 3498 | return -EPERM; | 3498 | return -EPERM; |
| 3499 | 3499 | ||
| 3500 | if (WARN_ON(size < 0 || size > sizeof(inparam))) | ||
| 3501 | return -EINVAL; | ||
| 3502 | |||
| 3500 | /* copyin */ | 3503 | /* copyin */ |
| 3501 | CLEARSTRUCT(&inparam); | 3504 | CLEARSTRUCT(&inparam); |
| 3502 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 3505 | if (_IOC_DIR(cmd) & _IOC_WRITE) |
| @@ -4162,7 +4165,7 @@ static int floppy_resume(struct device *dev) | |||
| 4162 | return 0; | 4165 | return 0; |
| 4163 | } | 4166 | } |
| 4164 | 4167 | ||
| 4165 | static struct dev_pm_ops floppy_pm_ops = { | 4168 | static const struct dev_pm_ops floppy_pm_ops = { |
| 4166 | .resume = floppy_resume, | 4169 | .resume = floppy_resume, |
| 4167 | .restore = floppy_resume, | 4170 | .restore = floppy_resume, |
| 4168 | }; | 4171 | }; |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index b8a5d654d3d0..fe62bd0e17b7 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
| @@ -931,7 +931,7 @@ static struct hv_ops hvc_iucv_ops = { | |||
| 931 | }; | 931 | }; |
| 932 | 932 | ||
| 933 | /* Suspend / resume device operations */ | 933 | /* Suspend / resume device operations */ |
| 934 | static struct dev_pm_ops hvc_iucv_pm_ops = { | 934 | static const struct dev_pm_ops hvc_iucv_pm_ops = { |
| 935 | .freeze = hvc_iucv_pm_freeze, | 935 | .freeze = hvc_iucv_pm_freeze, |
| 936 | .thaw = hvc_iucv_pm_restore_thaw, | 936 | .thaw = hvc_iucv_pm_restore_thaw, |
| 937 | .restore = hvc_iucv_pm_restore_thaw, | 937 | .restore = hvc_iucv_pm_restore_thaw, |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index fba76fb55abf..be832b6f8279 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -34,6 +34,16 @@ | |||
| 34 | # include <linux/efi.h> | 34 | # include <linux/efi.h> |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | static inline unsigned long size_inside_page(unsigned long start, | ||
| 38 | unsigned long size) | ||
| 39 | { | ||
| 40 | unsigned long sz; | ||
| 41 | |||
| 42 | sz = PAGE_SIZE - (start & (PAGE_SIZE - 1)); | ||
| 43 | |||
| 44 | return min(sz, size); | ||
| 45 | } | ||
| 46 | |||
| 37 | /* | 47 | /* |
| 38 | * Architectures vary in how they handle caching for addresses | 48 | * Architectures vary in how they handle caching for addresses |
| 39 | * outside of main memory. | 49 | * outside of main memory. |
| @@ -126,9 +136,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
| 126 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED | 136 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
| 127 | /* we don't have page 0 mapped on sparc and m68k.. */ | 137 | /* we don't have page 0 mapped on sparc and m68k.. */ |
| 128 | if (p < PAGE_SIZE) { | 138 | if (p < PAGE_SIZE) { |
| 129 | sz = PAGE_SIZE - p; | 139 | sz = size_inside_page(p, count); |
| 130 | if (sz > count) | ||
| 131 | sz = count; | ||
| 132 | if (sz > 0) { | 140 | if (sz > 0) { |
| 133 | if (clear_user(buf, sz)) | 141 | if (clear_user(buf, sz)) |
| 134 | return -EFAULT; | 142 | return -EFAULT; |
| @@ -141,15 +149,9 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
| 141 | #endif | 149 | #endif |
| 142 | 150 | ||
| 143 | while (count > 0) { | 151 | while (count > 0) { |
| 144 | /* | 152 | unsigned long remaining; |
| 145 | * Handle first page in case it's not aligned | ||
| 146 | */ | ||
| 147 | if (-p & (PAGE_SIZE - 1)) | ||
| 148 | sz = -p & (PAGE_SIZE - 1); | ||
| 149 | else | ||
| 150 | sz = PAGE_SIZE; | ||
| 151 | 153 | ||
| 152 | sz = min_t(unsigned long, sz, count); | 154 | sz = size_inside_page(p, count); |
| 153 | 155 | ||
| 154 | if (!range_is_allowed(p >> PAGE_SHIFT, count)) | 156 | if (!range_is_allowed(p >> PAGE_SHIFT, count)) |
| 155 | return -EPERM; | 157 | return -EPERM; |
| @@ -163,12 +165,10 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
| 163 | if (!ptr) | 165 | if (!ptr) |
| 164 | return -EFAULT; | 166 | return -EFAULT; |
| 165 | 167 | ||
| 166 | if (copy_to_user(buf, ptr, sz)) { | 168 | remaining = copy_to_user(buf, ptr, sz); |
| 167 | unxlate_dev_mem_ptr(p, ptr); | ||
| 168 | return -EFAULT; | ||
| 169 | } | ||
| 170 | |||
| 171 | unxlate_dev_mem_ptr(p, ptr); | 169 | unxlate_dev_mem_ptr(p, ptr); |
| 170 | if (remaining) | ||
| 171 | return -EFAULT; | ||
| 172 | 172 | ||
| 173 | buf += sz; | 173 | buf += sz; |
| 174 | p += sz; | 174 | p += sz; |
| @@ -196,9 +196,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
| 196 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED | 196 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
| 197 | /* we don't have page 0 mapped on sparc and m68k.. */ | 197 | /* we don't have page 0 mapped on sparc and m68k.. */ |
| 198 | if (p < PAGE_SIZE) { | 198 | if (p < PAGE_SIZE) { |
| 199 | unsigned long sz = PAGE_SIZE - p; | 199 | sz = size_inside_page(p, count); |
| 200 | if (sz > count) | ||
| 201 | sz = count; | ||
| 202 | /* Hmm. Do something? */ | 200 | /* Hmm. Do something? */ |
| 203 | buf += sz; | 201 | buf += sz; |
| 204 | p += sz; | 202 | p += sz; |
| @@ -208,15 +206,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
| 208 | #endif | 206 | #endif |
| 209 | 207 | ||
| 210 | while (count > 0) { | 208 | while (count > 0) { |
| 211 | /* | 209 | sz = size_inside_page(p, count); |
| 212 | * Handle first page in case it's not aligned | ||
| 213 | */ | ||
| 214 | if (-p & (PAGE_SIZE - 1)) | ||
| 215 | sz = -p & (PAGE_SIZE - 1); | ||
| 216 | else | ||
| 217 | sz = PAGE_SIZE; | ||
| 218 | |||
| 219 | sz = min_t(unsigned long, sz, count); | ||
| 220 | 210 | ||
| 221 | if (!range_is_allowed(p >> PAGE_SHIFT, sz)) | 211 | if (!range_is_allowed(p >> PAGE_SHIFT, sz)) |
| 222 | return -EPERM; | 212 | return -EPERM; |
| @@ -234,16 +224,14 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
| 234 | } | 224 | } |
| 235 | 225 | ||
| 236 | copied = copy_from_user(ptr, buf, sz); | 226 | copied = copy_from_user(ptr, buf, sz); |
| 227 | unxlate_dev_mem_ptr(p, ptr); | ||
| 237 | if (copied) { | 228 | if (copied) { |
| 238 | written += sz - copied; | 229 | written += sz - copied; |
| 239 | unxlate_dev_mem_ptr(p, ptr); | ||
| 240 | if (written) | 230 | if (written) |
| 241 | break; | 231 | break; |
| 242 | return -EFAULT; | 232 | return -EFAULT; |
| 243 | } | 233 | } |
| 244 | 234 | ||
| 245 | unxlate_dev_mem_ptr(p, ptr); | ||
| 246 | |||
| 247 | buf += sz; | 235 | buf += sz; |
| 248 | p += sz; | 236 | p += sz; |
| 249 | count -= sz; | 237 | count -= sz; |
| @@ -417,27 +405,18 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
| 417 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED | 405 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
| 418 | /* we don't have page 0 mapped on sparc and m68k.. */ | 406 | /* we don't have page 0 mapped on sparc and m68k.. */ |
| 419 | if (p < PAGE_SIZE && low_count > 0) { | 407 | if (p < PAGE_SIZE && low_count > 0) { |
| 420 | size_t tmp = PAGE_SIZE - p; | 408 | sz = size_inside_page(p, low_count); |
| 421 | if (tmp > low_count) tmp = low_count; | 409 | if (clear_user(buf, sz)) |
| 422 | if (clear_user(buf, tmp)) | ||
| 423 | return -EFAULT; | 410 | return -EFAULT; |
| 424 | buf += tmp; | 411 | buf += sz; |
| 425 | p += tmp; | 412 | p += sz; |
| 426 | read += tmp; | 413 | read += sz; |
| 427 | low_count -= tmp; | 414 | low_count -= sz; |
| 428 | count -= tmp; | 415 | count -= sz; |
| 429 | } | 416 | } |
| 430 | #endif | 417 | #endif |
| 431 | while (low_count > 0) { | 418 | while (low_count > 0) { |
| 432 | /* | 419 | sz = size_inside_page(p, low_count); |
| 433 | * Handle first page in case it's not aligned | ||
| 434 | */ | ||
| 435 | if (-p & (PAGE_SIZE - 1)) | ||
| 436 | sz = -p & (PAGE_SIZE - 1); | ||
| 437 | else | ||
| 438 | sz = PAGE_SIZE; | ||
| 439 | |||
| 440 | sz = min_t(unsigned long, sz, low_count); | ||
| 441 | 420 | ||
| 442 | /* | 421 | /* |
| 443 | * On ia64 if a page has been mapped somewhere as | 422 | * On ia64 if a page has been mapped somewhere as |
| @@ -461,21 +440,18 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
| 461 | if (!kbuf) | 440 | if (!kbuf) |
| 462 | return -ENOMEM; | 441 | return -ENOMEM; |
| 463 | while (count > 0) { | 442 | while (count > 0) { |
| 464 | int len = count; | 443 | sz = size_inside_page(p, count); |
| 465 | 444 | sz = vread(kbuf, (char *)p, sz); | |
| 466 | if (len > PAGE_SIZE) | 445 | if (!sz) |
| 467 | len = PAGE_SIZE; | ||
| 468 | len = vread(kbuf, (char *)p, len); | ||
| 469 | if (!len) | ||
| 470 | break; | 446 | break; |
| 471 | if (copy_to_user(buf, kbuf, len)) { | 447 | if (copy_to_user(buf, kbuf, sz)) { |
| 472 | free_page((unsigned long)kbuf); | 448 | free_page((unsigned long)kbuf); |
| 473 | return -EFAULT; | 449 | return -EFAULT; |
| 474 | } | 450 | } |
| 475 | count -= len; | 451 | count -= sz; |
| 476 | buf += len; | 452 | buf += sz; |
| 477 | read += len; | 453 | read += sz; |
| 478 | p += len; | 454 | p += sz; |
| 479 | } | 455 | } |
| 480 | free_page((unsigned long)kbuf); | 456 | free_page((unsigned long)kbuf); |
| 481 | } | 457 | } |
| @@ -485,7 +461,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
| 485 | 461 | ||
| 486 | 462 | ||
| 487 | static inline ssize_t | 463 | static inline ssize_t |
| 488 | do_write_kmem(void *p, unsigned long realp, const char __user * buf, | 464 | do_write_kmem(unsigned long p, const char __user *buf, |
| 489 | size_t count, loff_t *ppos) | 465 | size_t count, loff_t *ppos) |
| 490 | { | 466 | { |
| 491 | ssize_t written, sz; | 467 | ssize_t written, sz; |
| @@ -494,14 +470,11 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, | |||
| 494 | written = 0; | 470 | written = 0; |
| 495 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED | 471 | #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
| 496 | /* we don't have page 0 mapped on sparc and m68k.. */ | 472 | /* we don't have page 0 mapped on sparc and m68k.. */ |
| 497 | if (realp < PAGE_SIZE) { | 473 | if (p < PAGE_SIZE) { |
| 498 | unsigned long sz = PAGE_SIZE - realp; | 474 | sz = size_inside_page(p, count); |
| 499 | if (sz > count) | ||
| 500 | sz = count; | ||
| 501 | /* Hmm. Do something? */ | 475 | /* Hmm. Do something? */ |
| 502 | buf += sz; | 476 | buf += sz; |
| 503 | p += sz; | 477 | p += sz; |
| 504 | realp += sz; | ||
| 505 | count -= sz; | 478 | count -= sz; |
| 506 | written += sz; | 479 | written += sz; |
| 507 | } | 480 | } |
| @@ -509,22 +482,15 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, | |||
| 509 | 482 | ||
| 510 | while (count > 0) { | 483 | while (count > 0) { |
| 511 | char *ptr; | 484 | char *ptr; |
| 512 | /* | ||
| 513 | * Handle first page in case it's not aligned | ||
| 514 | */ | ||
| 515 | if (-realp & (PAGE_SIZE - 1)) | ||
| 516 | sz = -realp & (PAGE_SIZE - 1); | ||
| 517 | else | ||
| 518 | sz = PAGE_SIZE; | ||
| 519 | 485 | ||
| 520 | sz = min_t(unsigned long, sz, count); | 486 | sz = size_inside_page(p, count); |
| 521 | 487 | ||
| 522 | /* | 488 | /* |
| 523 | * On ia64 if a page has been mapped somewhere as | 489 | * On ia64 if a page has been mapped somewhere as |
| 524 | * uncached, then it must also be accessed uncached | 490 | * uncached, then it must also be accessed uncached |
| 525 | * by the kernel or data corruption may occur | 491 | * by the kernel or data corruption may occur |
| 526 | */ | 492 | */ |
| 527 | ptr = xlate_dev_kmem_ptr(p); | 493 | ptr = xlate_dev_kmem_ptr((char *)p); |
| 528 | 494 | ||
| 529 | copied = copy_from_user(ptr, buf, sz); | 495 | copied = copy_from_user(ptr, buf, sz); |
| 530 | if (copied) { | 496 | if (copied) { |
| @@ -535,7 +501,6 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf, | |||
| 535 | } | 501 | } |
| 536 | buf += sz; | 502 | buf += sz; |
| 537 | p += sz; | 503 | p += sz; |
| 538 | realp += sz; | ||
| 539 | count -= sz; | 504 | count -= sz; |
| 540 | written += sz; | 505 | written += sz; |
| 541 | } | 506 | } |
| @@ -554,19 +519,14 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
| 554 | unsigned long p = *ppos; | 519 | unsigned long p = *ppos; |
| 555 | ssize_t wrote = 0; | 520 | ssize_t wrote = 0; |
| 556 | ssize_t virtr = 0; | 521 | ssize_t virtr = 0; |
| 557 | ssize_t written; | ||
| 558 | char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ | 522 | char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ |
| 559 | 523 | ||
| 560 | if (p < (unsigned long) high_memory) { | 524 | if (p < (unsigned long) high_memory) { |
| 561 | 525 | unsigned long to_write = min_t(unsigned long, count, | |
| 562 | wrote = count; | 526 | (unsigned long)high_memory - p); |
| 563 | if (count > (unsigned long) high_memory - p) | 527 | wrote = do_write_kmem(p, buf, to_write, ppos); |
| 564 | wrote = (unsigned long) high_memory - p; | 528 | if (wrote != to_write) |
| 565 | 529 | return wrote; | |
| 566 | written = do_write_kmem((void*)p, p, buf, wrote, ppos); | ||
| 567 | if (written != wrote) | ||
| 568 | return written; | ||
| 569 | wrote = written; | ||
| 570 | p += wrote; | 530 | p += wrote; |
| 571 | buf += wrote; | 531 | buf += wrote; |
| 572 | count -= wrote; | 532 | count -= wrote; |
| @@ -577,24 +537,21 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
| 577 | if (!kbuf) | 537 | if (!kbuf) |
| 578 | return wrote ? wrote : -ENOMEM; | 538 | return wrote ? wrote : -ENOMEM; |
| 579 | while (count > 0) { | 539 | while (count > 0) { |
| 580 | int len = count; | 540 | unsigned long sz = size_inside_page(p, count); |
| 581 | 541 | unsigned long n; | |
| 582 | if (len > PAGE_SIZE) | 542 | |
| 583 | len = PAGE_SIZE; | 543 | n = copy_from_user(kbuf, buf, sz); |
| 584 | if (len) { | 544 | if (n) { |
| 585 | written = copy_from_user(kbuf, buf, len); | 545 | if (wrote + virtr) |
| 586 | if (written) { | 546 | break; |
| 587 | if (wrote + virtr) | 547 | free_page((unsigned long)kbuf); |
| 588 | break; | 548 | return -EFAULT; |
| 589 | free_page((unsigned long)kbuf); | ||
| 590 | return -EFAULT; | ||
| 591 | } | ||
| 592 | } | 549 | } |
| 593 | len = vwrite(kbuf, (char *)p, len); | 550 | sz = vwrite(kbuf, (char *)p, sz); |
| 594 | count -= len; | 551 | count -= sz; |
| 595 | buf += len; | 552 | buf += sz; |
| 596 | virtr += len; | 553 | virtr += sz; |
| 597 | p += len; | 554 | p += sz; |
| 598 | } | 555 | } |
| 599 | free_page((unsigned long)kbuf); | 556 | free_page((unsigned long)kbuf); |
| 600 | } | 557 | } |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 96f1cd086dd2..94a136e96c06 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
| @@ -60,9 +60,7 @@ static DEFINE_MUTEX(misc_mtx); | |||
| 60 | * Assigned numbers, used for dynamic minors | 60 | * Assigned numbers, used for dynamic minors |
| 61 | */ | 61 | */ |
| 62 | #define DYNAMIC_MINORS 64 /* like dynamic majors */ | 62 | #define DYNAMIC_MINORS 64 /* like dynamic majors */ |
| 63 | static unsigned char misc_minors[DYNAMIC_MINORS / 8]; | 63 | static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS); |
| 64 | |||
| 65 | extern int pmu_device_init(void); | ||
| 66 | 64 | ||
| 67 | #ifdef CONFIG_PROC_FS | 65 | #ifdef CONFIG_PROC_FS |
| 68 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) | 66 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) |
| @@ -198,24 +196,23 @@ int misc_register(struct miscdevice * misc) | |||
| 198 | } | 196 | } |
| 199 | 197 | ||
| 200 | if (misc->minor == MISC_DYNAMIC_MINOR) { | 198 | if (misc->minor == MISC_DYNAMIC_MINOR) { |
| 201 | int i = DYNAMIC_MINORS; | 199 | int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); |
| 202 | while (--i >= 0) | 200 | if (i >= DYNAMIC_MINORS) { |
| 203 | if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) | ||
| 204 | break; | ||
| 205 | if (i<0) { | ||
| 206 | mutex_unlock(&misc_mtx); | 201 | mutex_unlock(&misc_mtx); |
| 207 | return -EBUSY; | 202 | return -EBUSY; |
| 208 | } | 203 | } |
| 209 | misc->minor = i; | 204 | misc->minor = DYNAMIC_MINORS - i - 1; |
| 205 | set_bit(i, misc_minors); | ||
| 210 | } | 206 | } |
| 211 | 207 | ||
| 212 | if (misc->minor < DYNAMIC_MINORS) | ||
| 213 | misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); | ||
| 214 | dev = MKDEV(MISC_MAJOR, misc->minor); | 208 | dev = MKDEV(MISC_MAJOR, misc->minor); |
| 215 | 209 | ||
| 216 | misc->this_device = device_create(misc_class, misc->parent, dev, | 210 | misc->this_device = device_create(misc_class, misc->parent, dev, |
| 217 | misc, "%s", misc->name); | 211 | misc, "%s", misc->name); |
| 218 | if (IS_ERR(misc->this_device)) { | 212 | if (IS_ERR(misc->this_device)) { |
| 213 | int i = DYNAMIC_MINORS - misc->minor - 1; | ||
| 214 | if (i < DYNAMIC_MINORS && i >= 0) | ||
| 215 | clear_bit(i, misc_minors); | ||
| 219 | err = PTR_ERR(misc->this_device); | 216 | err = PTR_ERR(misc->this_device); |
| 220 | goto out; | 217 | goto out; |
| 221 | } | 218 | } |
| @@ -242,7 +239,7 @@ int misc_register(struct miscdevice * misc) | |||
| 242 | 239 | ||
| 243 | int misc_deregister(struct miscdevice *misc) | 240 | int misc_deregister(struct miscdevice *misc) |
| 244 | { | 241 | { |
| 245 | int i = misc->minor; | 242 | int i = DYNAMIC_MINORS - misc->minor - 1; |
| 246 | 243 | ||
| 247 | if (list_empty(&misc->list)) | 244 | if (list_empty(&misc->list)) |
| 248 | return -EINVAL; | 245 | return -EINVAL; |
| @@ -250,9 +247,8 @@ int misc_deregister(struct miscdevice *misc) | |||
| 250 | mutex_lock(&misc_mtx); | 247 | mutex_lock(&misc_mtx); |
| 251 | list_del(&misc->list); | 248 | list_del(&misc->list); |
| 252 | device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); | 249 | device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); |
| 253 | if (i < DYNAMIC_MINORS && i>0) { | 250 | if (i < DYNAMIC_MINORS && i >= 0) |
| 254 | misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); | 251 | clear_bit(i, misc_minors); |
| 255 | } | ||
| 256 | mutex_unlock(&misc_mtx); | 252 | mutex_unlock(&misc_mtx); |
| 257 | return 0; | 253 | return 0; |
| 258 | } | 254 | } |
diff --git a/drivers/char/random.c b/drivers/char/random.c index dcd08635cf1b..8258982b49ec 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -1245,12 +1245,8 @@ static int proc_do_uuid(ctl_table *table, int write, | |||
| 1245 | if (uuid[8] == 0) | 1245 | if (uuid[8] == 0) |
| 1246 | generate_random_uuid(uuid); | 1246 | generate_random_uuid(uuid); |
| 1247 | 1247 | ||
| 1248 | sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" | 1248 | sprintf(buf, "%pU", uuid); |
| 1249 | "%02x%02x%02x%02x%02x%02x", | 1249 | |
| 1250 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
| 1251 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
| 1252 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
| 1253 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
| 1254 | fake_table.data = buf; | 1250 | fake_table.data = buf; |
| 1255 | fake_table.maxlen = sizeof(buf); | 1251 | fake_table.maxlen = sizeof(buf); |
| 1256 | 1252 | ||
| @@ -1310,7 +1306,7 @@ ctl_table random_table[] = { | |||
| 1310 | 1306 | ||
| 1311 | /******************************************************************** | 1307 | /******************************************************************** |
| 1312 | * | 1308 | * |
| 1313 | * Random funtions for networking | 1309 | * Random functions for networking |
| 1314 | * | 1310 | * |
| 1315 | ********************************************************************/ | 1311 | ********************************************************************/ |
| 1316 | 1312 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1e3d728dbf7e..e43fbc66aef0 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
| @@ -184,12 +184,10 @@ static DECLARE_WORK(console_work, console_callback); | |||
| 184 | * fg_console is the current virtual console, | 184 | * fg_console is the current virtual console, |
| 185 | * last_console is the last used one, | 185 | * last_console is the last used one, |
| 186 | * want_console is the console we want to switch to, | 186 | * want_console is the console we want to switch to, |
| 187 | * kmsg_redirect is the console for kernel messages, | ||
| 188 | */ | 187 | */ |
| 189 | int fg_console; | 188 | int fg_console; |
| 190 | int last_console; | 189 | int last_console; |
| 191 | int want_console = -1; | 190 | int want_console = -1; |
| 192 | int kmsg_redirect; | ||
| 193 | 191 | ||
| 194 | /* | 192 | /* |
| 195 | * For each existing display, we have a pointer to console currently visible | 193 | * For each existing display, we have a pointer to console currently visible |
| @@ -2434,6 +2432,37 @@ struct tty_driver *console_driver; | |||
| 2434 | 2432 | ||
| 2435 | #ifdef CONFIG_VT_CONSOLE | 2433 | #ifdef CONFIG_VT_CONSOLE |
| 2436 | 2434 | ||
| 2435 | /** | ||
| 2436 | * vt_kmsg_redirect() - Sets/gets the kernel message console | ||
| 2437 | * @new: The new virtual terminal number or -1 if the console should stay | ||
| 2438 | * unchanged | ||
| 2439 | * | ||
| 2440 | * By default, the kernel messages are always printed on the current virtual | ||
| 2441 | * console. However, the user may modify that default with the | ||
| 2442 | * TIOCL_SETKMSGREDIRECT ioctl call. | ||
| 2443 | * | ||
| 2444 | * This function sets the kernel message console to be @new. It returns the old | ||
| 2445 | * virtual console number. The virtual terminal number 0 (both as parameter and | ||
| 2446 | * return value) means no redirection (i.e. always printed on the currently | ||
| 2447 | * active console). | ||
| 2448 | * | ||
| 2449 | * The parameter -1 means that only the current console is returned, but the | ||
| 2450 | * value is not modified. You may use the macro vt_get_kmsg_redirect() in that | ||
| 2451 | * case to make the code more understandable. | ||
| 2452 | * | ||
| 2453 | * When the kernel is compiled without CONFIG_VT_CONSOLE, this function ignores | ||
| 2454 | * the parameter and always returns 0. | ||
| 2455 | */ | ||
| 2456 | int vt_kmsg_redirect(int new) | ||
| 2457 | { | ||
| 2458 | static int kmsg_con; | ||
| 2459 | |||
| 2460 | if (new != -1) | ||
| 2461 | return xchg(&kmsg_con, new); | ||
| 2462 | else | ||
| 2463 | return kmsg_con; | ||
| 2464 | } | ||
| 2465 | |||
| 2437 | /* | 2466 | /* |
| 2438 | * Console on virtual terminal | 2467 | * Console on virtual terminal |
| 2439 | * | 2468 | * |
| @@ -2448,6 +2477,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
| 2448 | const ushort *start; | 2477 | const ushort *start; |
| 2449 | ushort cnt = 0; | 2478 | ushort cnt = 0; |
| 2450 | ushort myx; | 2479 | ushort myx; |
| 2480 | int kmsg_console; | ||
| 2451 | 2481 | ||
| 2452 | /* console busy or not yet initialized */ | 2482 | /* console busy or not yet initialized */ |
| 2453 | if (!printable) | 2483 | if (!printable) |
| @@ -2455,8 +2485,9 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
| 2455 | if (!spin_trylock(&printing_lock)) | 2485 | if (!spin_trylock(&printing_lock)) |
| 2456 | return; | 2486 | return; |
| 2457 | 2487 | ||
| 2458 | if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) | 2488 | kmsg_console = vt_get_kmsg_redirect(); |
| 2459 | vc = vc_cons[kmsg_redirect - 1].d; | 2489 | if (kmsg_console && vc_cons_allocated(kmsg_console - 1)) |
| 2490 | vc = vc_cons[kmsg_console - 1].d; | ||
| 2460 | 2491 | ||
| 2461 | /* read `x' only after setting currcons properly (otherwise | 2492 | /* read `x' only after setting currcons properly (otherwise |
| 2462 | the `x' macro will read the x of the foreground console). */ | 2493 | the `x' macro will read the x of the foreground console). */ |
| @@ -2613,7 +2644,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
| 2613 | ret = set_vesa_blanking(p); | 2644 | ret = set_vesa_blanking(p); |
| 2614 | break; | 2645 | break; |
| 2615 | case TIOCL_GETKMSGREDIRECT: | 2646 | case TIOCL_GETKMSGREDIRECT: |
| 2616 | data = kmsg_redirect; | 2647 | data = vt_get_kmsg_redirect(); |
| 2617 | ret = __put_user(data, p); | 2648 | ret = __put_user(data, p); |
| 2618 | break; | 2649 | break; |
| 2619 | case TIOCL_SETKMSGREDIRECT: | 2650 | case TIOCL_SETKMSGREDIRECT: |
| @@ -2623,7 +2654,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
| 2623 | if (get_user(data, p+1)) | 2654 | if (get_user(data, p+1)) |
| 2624 | ret = -EFAULT; | 2655 | ret = -EFAULT; |
| 2625 | else | 2656 | else |
| 2626 | kmsg_redirect = data; | 2657 | vt_kmsg_redirect(data); |
| 2627 | } | 2658 | } |
| 2628 | break; | 2659 | break; |
| 2629 | case TIOCL_GETFGCONSOLE: | 2660 | case TIOCL_GETFGCONSOLE: |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig new file mode 100644 index 000000000000..08f726c5fee5 --- /dev/null +++ b/drivers/clocksource/Kconfig | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | config CS5535_CLOCK_EVENT_SRC | ||
| 2 | tristate "CS5535/CS5536 high-res timer (MFGPT) events" | ||
| 3 | depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT | ||
| 4 | help | ||
| 5 | This driver provides a clock event source based on the MFGPT | ||
| 6 | timer(s) in the CS5535 and CS5536 companion chips. | ||
| 7 | MFGPTs have a better resolution and max interval than the | ||
| 8 | generic PIT, and are suitable for use as high-res timers. | ||
| 9 | |||
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index eef216f7f61d..be61ece6330b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
| @@ -2,6 +2,7 @@ obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o | |||
| 2 | obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o | 2 | obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o |
| 3 | obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o | 3 | obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o |
| 4 | obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o | 4 | obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o |
| 5 | obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o | ||
| 5 | obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o | 6 | obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o |
| 6 | obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o | 7 | obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o |
| 7 | obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o | 8 | obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o |
diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c new file mode 100644 index 000000000000..27d20fac19d1 --- /dev/null +++ b/drivers/clocksource/cs5535-clockevt.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | /* | ||
| 2 | * Clock event driver for the CS5535/CS5536 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006, Advanced Micro Devices, Inc. | ||
| 5 | * Copyright (C) 2007 Andres Salomon <dilinger@debian.org> | ||
| 6 | * Copyright (C) 2009 Andres Salomon <dilinger@collabora.co.uk> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of version 2 of the GNU General Public License | ||
| 10 | * as published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * The MFGPTs are documented in AMD Geode CS5536 Companion Device Data Book. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/irq.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/cs5535.h> | ||
| 20 | #include <linux/clockchips.h> | ||
| 21 | |||
| 22 | #define DRV_NAME "cs5535-clockevt" | ||
| 23 | |||
| 24 | static int timer_irq = CONFIG_CS5535_MFGPT_DEFAULT_IRQ; | ||
| 25 | module_param_named(irq, timer_irq, int, 0644); | ||
| 26 | MODULE_PARM_DESC(irq, "Which IRQ to use for the clock source MFGPT ticks."); | ||
| 27 | |||
| 28 | /* | ||
| 29 | * We are using the 32.768kHz input clock - it's the only one that has the | ||
| 30 | * ranges we find desirable. The following table lists the suitable | ||
| 31 | * divisors and the associated Hz, minimum interval and the maximum interval: | ||
| 32 | * | ||
| 33 | * Divisor Hz Min Delta (s) Max Delta (s) | ||
| 34 | * 1 32768 .00048828125 2.000 | ||
| 35 | * 2 16384 .0009765625 4.000 | ||
| 36 | * 4 8192 .001953125 8.000 | ||
| 37 | * 8 4096 .00390625 16.000 | ||
| 38 | * 16 2048 .0078125 32.000 | ||
| 39 | * 32 1024 .015625 64.000 | ||
| 40 | * 64 512 .03125 128.000 | ||
| 41 | * 128 256 .0625 256.000 | ||
| 42 | * 256 128 .125 512.000 | ||
| 43 | */ | ||
| 44 | |||
| 45 | static unsigned int cs5535_tick_mode = CLOCK_EVT_MODE_SHUTDOWN; | ||
| 46 | static struct cs5535_mfgpt_timer *cs5535_event_clock; | ||
| 47 | |||
| 48 | /* Selected from the table above */ | ||
| 49 | |||
| 50 | #define MFGPT_DIVISOR 16 | ||
| 51 | #define MFGPT_SCALE 4 /* divisor = 2^(scale) */ | ||
| 52 | #define MFGPT_HZ (32768 / MFGPT_DIVISOR) | ||
| 53 | #define MFGPT_PERIODIC (MFGPT_HZ / HZ) | ||
| 54 | |||
| 55 | /* | ||
| 56 | * The MFPGT timers on the CS5536 provide us with suitable timers to use | ||
| 57 | * as clock event sources - not as good as a HPET or APIC, but certainly | ||
| 58 | * better than the PIT. This isn't a general purpose MFGPT driver, but | ||
| 59 | * a simplified one designed specifically to act as a clock event source. | ||
| 60 | * For full details about the MFGPT, please consult the CS5536 data sheet. | ||
| 61 | */ | ||
| 62 | |||
| 63 | static void disable_timer(struct cs5535_mfgpt_timer *timer) | ||
| 64 | { | ||
| 65 | /* avoid races by clearing CMP1 and CMP2 unconditionally */ | ||
| 66 | cs5535_mfgpt_write(timer, MFGPT_REG_SETUP, | ||
| 67 | (uint16_t) ~MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP1 | | ||
| 68 | MFGPT_SETUP_CMP2); | ||
| 69 | } | ||
| 70 | |||
| 71 | static void start_timer(struct cs5535_mfgpt_timer *timer, uint16_t delta) | ||
| 72 | { | ||
| 73 | cs5535_mfgpt_write(timer, MFGPT_REG_CMP2, delta); | ||
| 74 | cs5535_mfgpt_write(timer, MFGPT_REG_COUNTER, 0); | ||
| 75 | |||
| 76 | cs5535_mfgpt_write(timer, MFGPT_REG_SETUP, | ||
| 77 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
| 78 | } | ||
| 79 | |||
| 80 | static void mfgpt_set_mode(enum clock_event_mode mode, | ||
| 81 | struct clock_event_device *evt) | ||
| 82 | { | ||
| 83 | disable_timer(cs5535_event_clock); | ||
| 84 | |||
| 85 | if (mode == CLOCK_EVT_MODE_PERIODIC) | ||
| 86 | start_timer(cs5535_event_clock, MFGPT_PERIODIC); | ||
| 87 | |||
| 88 | cs5535_tick_mode = mode; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) | ||
| 92 | { | ||
| 93 | start_timer(cs5535_event_clock, delta); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static struct clock_event_device cs5535_clockevent = { | ||
| 98 | .name = DRV_NAME, | ||
| 99 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
| 100 | .set_mode = mfgpt_set_mode, | ||
| 101 | .set_next_event = mfgpt_next_event, | ||
| 102 | .rating = 250, | ||
| 103 | .cpumask = cpu_all_mask, | ||
| 104 | .shift = 32 | ||
| 105 | }; | ||
| 106 | |||
| 107 | static irqreturn_t mfgpt_tick(int irq, void *dev_id) | ||
| 108 | { | ||
| 109 | uint16_t val = cs5535_mfgpt_read(cs5535_event_clock, MFGPT_REG_SETUP); | ||
| 110 | |||
| 111 | /* See if the interrupt was for us */ | ||
| 112 | if (!(val & (MFGPT_SETUP_SETUP | MFGPT_SETUP_CMP2 | MFGPT_SETUP_CMP1))) | ||
| 113 | return IRQ_NONE; | ||
| 114 | |||
| 115 | /* Turn off the clock (and clear the event) */ | ||
| 116 | disable_timer(cs5535_event_clock); | ||
| 117 | |||
| 118 | if (cs5535_tick_mode == CLOCK_EVT_MODE_SHUTDOWN) | ||
| 119 | return IRQ_HANDLED; | ||
| 120 | |||
| 121 | /* Clear the counter */ | ||
| 122 | cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_COUNTER, 0); | ||
| 123 | |||
| 124 | /* Restart the clock in periodic mode */ | ||
| 125 | |||
| 126 | if (cs5535_tick_mode == CLOCK_EVT_MODE_PERIODIC) | ||
| 127 | cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, | ||
| 128 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
| 129 | |||
| 130 | cs5535_clockevent.event_handler(&cs5535_clockevent); | ||
| 131 | return IRQ_HANDLED; | ||
| 132 | } | ||
| 133 | |||
| 134 | static struct irqaction mfgptirq = { | ||
| 135 | .handler = mfgpt_tick, | ||
| 136 | .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, | ||
| 137 | .name = DRV_NAME, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static int __init cs5535_mfgpt_init(void) | ||
| 141 | { | ||
| 142 | struct cs5535_mfgpt_timer *timer; | ||
| 143 | int ret; | ||
| 144 | uint16_t val; | ||
| 145 | |||
| 146 | timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING); | ||
| 147 | if (!timer) { | ||
| 148 | printk(KERN_ERR DRV_NAME ": Could not allocate MFPGT timer\n"); | ||
| 149 | return -ENODEV; | ||
| 150 | } | ||
| 151 | cs5535_event_clock = timer; | ||
| 152 | |||
| 153 | /* Set up the IRQ on the MFGPT side */ | ||
| 154 | if (cs5535_mfgpt_setup_irq(timer, MFGPT_CMP2, &timer_irq)) { | ||
| 155 | printk(KERN_ERR DRV_NAME ": Could not set up IRQ %d\n", | ||
| 156 | timer_irq); | ||
| 157 | return -EIO; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* And register it with the kernel */ | ||
| 161 | ret = setup_irq(timer_irq, &mfgptirq); | ||
| 162 | if (ret) { | ||
| 163 | printk(KERN_ERR DRV_NAME ": Unable to set up the interrupt.\n"); | ||
| 164 | goto err; | ||
| 165 | } | ||
| 166 | |||
| 167 | /* Set the clock scale and enable the event mode for CMP2 */ | ||
| 168 | val = MFGPT_SCALE | (3 << 8); | ||
| 169 | |||
| 170 | cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, val); | ||
| 171 | |||
| 172 | /* Set up the clock event */ | ||
| 173 | cs5535_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, | ||
| 174 | cs5535_clockevent.shift); | ||
| 175 | cs5535_clockevent.min_delta_ns = clockevent_delta2ns(0xF, | ||
| 176 | &cs5535_clockevent); | ||
| 177 | cs5535_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE, | ||
| 178 | &cs5535_clockevent); | ||
| 179 | |||
| 180 | printk(KERN_INFO DRV_NAME | ||
| 181 | ": Registering MFGPT timer as a clock event, using IRQ %d\n", | ||
| 182 | timer_irq); | ||
| 183 | clockevents_register_device(&cs5535_clockevent); | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | |||
| 187 | err: | ||
| 188 | cs5535_mfgpt_release_irq(cs5535_event_clock, MFGPT_CMP2, &timer_irq); | ||
| 189 | printk(KERN_ERR DRV_NAME ": Unable to set up the MFGPT clock source\n"); | ||
| 190 | return -EIO; | ||
| 191 | } | ||
| 192 | |||
| 193 | module_init(cs5535_mfgpt_init); | ||
| 194 | |||
| 195 | MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>"); | ||
| 196 | MODULE_DESCRIPTION("CS5535/CS5536 MFGPT clock event driver"); | ||
| 197 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index a4bec3f919aa..1c1ceb4f218f 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c | |||
| @@ -69,9 +69,6 @@ static int ladder_select_state(struct cpuidle_device *dev) | |||
| 69 | int last_residency, last_idx = ldev->last_state_idx; | 69 | int last_residency, last_idx = ldev->last_state_idx; |
| 70 | int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY); | 70 | int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY); |
| 71 | 71 | ||
| 72 | if (unlikely(!ldev)) | ||
| 73 | return 0; | ||
| 74 | |||
| 75 | /* Special case when user has set very strict latency requirement */ | 72 | /* Special case when user has set very strict latency requirement */ |
| 76 | if (unlikely(latency_req == 0)) { | 73 | if (unlikely(latency_req == 0)) { |
| 77 | ladder_do_selection(ldev, last_idx, 0); | 74 | ladder_do_selection(ldev, last_idx, 0); |
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index c52ac9efd0bf..f15112569c1d 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
| @@ -1188,7 +1188,7 @@ static int at_dma_resume_noirq(struct device *dev) | |||
| 1188 | return 0; | 1188 | return 0; |
| 1189 | } | 1189 | } |
| 1190 | 1190 | ||
| 1191 | static struct dev_pm_ops at_dma_dev_pm_ops = { | 1191 | static const struct dev_pm_ops at_dma_dev_pm_ops = { |
| 1192 | .suspend_noirq = at_dma_suspend_noirq, | 1192 | .suspend_noirq = at_dma_suspend_noirq, |
| 1193 | .resume_noirq = at_dma_resume_noirq, | 1193 | .resume_noirq = at_dma_resume_noirq, |
| 1194 | }; | 1194 | }; |
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 2eea823516a7..285bed0fe17b 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c | |||
| @@ -1427,7 +1427,7 @@ static int dw_resume_noirq(struct device *dev) | |||
| 1427 | return 0; | 1427 | return 0; |
| 1428 | } | 1428 | } |
| 1429 | 1429 | ||
| 1430 | static struct dev_pm_ops dw_dev_pm_ops = { | 1430 | static const struct dev_pm_ops dw_dev_pm_ops = { |
| 1431 | .suspend_noirq = dw_suspend_noirq, | 1431 | .suspend_noirq = dw_suspend_noirq, |
| 1432 | .resume_noirq = dw_resume_noirq, | 1432 | .resume_noirq = dw_resume_noirq, |
| 1433 | }; | 1433 | }; |
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index fb6bb64e8861..3ebc61067e54 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c | |||
| @@ -1313,7 +1313,7 @@ static int txx9dmac_resume_noirq(struct device *dev) | |||
| 1313 | 1313 | ||
| 1314 | } | 1314 | } |
| 1315 | 1315 | ||
| 1316 | static struct dev_pm_ops txx9dmac_dev_pm_ops = { | 1316 | static const struct dev_pm_ops txx9dmac_dev_pm_ops = { |
| 1317 | .suspend_noirq = txx9dmac_suspend_noirq, | 1317 | .suspend_noirq = txx9dmac_suspend_noirq, |
| 1318 | .resume_noirq = txx9dmac_resume_noirq, | 1318 | .resume_noirq = txx9dmac_resume_noirq, |
| 1319 | }; | 1319 | }; |
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index ebb9e51deb0c..1b03ba1d0834 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
| @@ -7,7 +7,7 @@ menu "Firmware Drivers" | |||
| 7 | 7 | ||
| 8 | config EDD | 8 | config EDD |
| 9 | tristate "BIOS Enhanced Disk Drive calls determine boot disk" | 9 | tristate "BIOS Enhanced Disk Drive calls determine boot disk" |
| 10 | depends on !IA64 | 10 | depends on X86 |
| 11 | help | 11 | help |
| 12 | Say Y or M here if you want to enable BIOS Enhanced Disk Drive | 12 | Say Y or M here if you want to enable BIOS Enhanced Disk Drive |
| 13 | Services real mode BIOS calls to determine which disk | 13 | Services real mode BIOS calls to determine which disk |
| @@ -28,7 +28,7 @@ config EDD_OFF | |||
| 28 | 28 | ||
| 29 | config FIRMWARE_MEMMAP | 29 | config FIRMWARE_MEMMAP |
| 30 | bool "Add firmware-provided memory map to sysfs" if EMBEDDED | 30 | bool "Add firmware-provided memory map to sysfs" if EMBEDDED |
| 31 | default (X86_64 || X86_32) | 31 | default X86 |
| 32 | help | 32 | help |
| 33 | Add the firmware-provided (unmodified) memory map to /sys/firmware/memmap. | 33 | Add the firmware-provided (unmodified) memory map to /sys/firmware/memmap. |
| 34 | That memory map is used for example by kexec to set up parameter area | 34 | That memory map is used for example by kexec to set up parameter area |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 3a2ccb09e2f8..31b983d9462c 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
| @@ -169,10 +169,7 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde | |||
| 169 | if (!s) | 169 | if (!s) |
| 170 | return; | 170 | return; |
| 171 | 171 | ||
| 172 | sprintf(s, | 172 | sprintf(s, "%pUB", d); |
| 173 | "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", | ||
| 174 | d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], | ||
| 175 | d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); | ||
| 176 | 173 | ||
| 177 | dmi_ident[slot] = s; | 174 | dmi_ident[slot] = s; |
| 178 | } | 175 | } |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2ad0128c63c6..57ca339924ef 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -174,6 +174,16 @@ config GPIO_ADP5520 | |||
| 174 | 174 | ||
| 175 | comment "PCI GPIO expanders:" | 175 | comment "PCI GPIO expanders:" |
| 176 | 176 | ||
| 177 | config GPIO_CS5535 | ||
| 178 | tristate "AMD CS5535/CS5536 GPIO support" | ||
| 179 | depends on PCI && !CS5535_GPIO | ||
| 180 | help | ||
| 181 | The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that | ||
| 182 | can be used for quite a number of things. The CS5535/6 is found on | ||
| 183 | AMD Geode and Lemote Yeeloong devices. | ||
| 184 | |||
| 185 | If unsure, say N. | ||
| 186 | |||
| 177 | config GPIO_BT8XX | 187 | config GPIO_BT8XX |
| 178 | tristate "BT8XX GPIO abuser" | 188 | tristate "BT8XX GPIO abuser" |
| 179 | depends on PCI && VIDEO_BT848=n | 189 | depends on PCI && VIDEO_BT848=n |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 00a532c9a1e2..270b6d7839f5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_PL061) += pl061.o | |||
| 16 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 16 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
| 17 | obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o | 17 | obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o |
| 18 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | 18 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o |
| 19 | obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o | ||
| 19 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 20 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
| 20 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | 21 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o |
| 21 | obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o | 22 | obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o |
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c new file mode 100644 index 000000000000..0fdbe94f24a3 --- /dev/null +++ b/drivers/gpio/cs5535-gpio.c | |||
| @@ -0,0 +1,355 @@ | |||
| 1 | /* | ||
| 2 | * AMD CS5535/CS5536 GPIO driver | ||
| 3 | * Copyright (C) 2006 Advanced Micro Devices, Inc. | ||
| 4 | * Copyright (C) 2007-2009 Andres Salomon <dilinger@collabora.co.uk> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of version 2 of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/spinlock.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/pci.h> | ||
| 15 | #include <linux/gpio.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/cs5535.h> | ||
| 18 | |||
| 19 | #define DRV_NAME "cs5535-gpio" | ||
| 20 | #define GPIO_BAR 1 | ||
| 21 | |||
| 22 | /* | ||
| 23 | * Some GPIO pins | ||
| 24 | * 31-29,23 : reserved (always mask out) | ||
| 25 | * 28 : Power Button | ||
| 26 | * 26 : PME# | ||
| 27 | * 22-16 : LPC | ||
| 28 | * 14,15 : SMBus | ||
| 29 | * 9,8 : UART1 | ||
| 30 | * 7 : PCI INTB | ||
| 31 | * 3,4 : UART2/DDC | ||
| 32 | * 2 : IDE_IRQ0 | ||
| 33 | * 1 : AC_BEEP | ||
| 34 | * 0 : PCI INTA | ||
| 35 | * | ||
| 36 | * If a mask was not specified, allow all except | ||
| 37 | * reserved and Power Button | ||
| 38 | */ | ||
| 39 | #define GPIO_DEFAULT_MASK 0x0F7FFFFF | ||
| 40 | |||
| 41 | static ulong mask = GPIO_DEFAULT_MASK; | ||
| 42 | module_param_named(mask, mask, ulong, 0444); | ||
| 43 | MODULE_PARM_DESC(mask, "GPIO channel mask."); | ||
| 44 | |||
| 45 | static struct cs5535_gpio_chip { | ||
| 46 | struct gpio_chip chip; | ||
| 47 | resource_size_t base; | ||
| 48 | |||
| 49 | struct pci_dev *pdev; | ||
| 50 | spinlock_t lock; | ||
| 51 | } cs5535_gpio_chip; | ||
| 52 | |||
| 53 | /* | ||
| 54 | * The CS5535/CS5536 GPIOs support a number of extra features not defined | ||
| 55 | * by the gpio_chip API, so these are exported. For a full list of the | ||
| 56 | * registers, see include/linux/cs5535.h. | ||
| 57 | */ | ||
| 58 | |||
| 59 | static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset, | ||
| 60 | unsigned int reg) | ||
| 61 | { | ||
| 62 | if (offset < 16) | ||
| 63 | /* low bank register */ | ||
| 64 | outl(1 << offset, chip->base + reg); | ||
| 65 | else | ||
| 66 | /* high bank register */ | ||
| 67 | outl(1 << (offset - 16), chip->base + 0x80 + reg); | ||
| 68 | } | ||
| 69 | |||
| 70 | void cs5535_gpio_set(unsigned offset, unsigned int reg) | ||
| 71 | { | ||
| 72 | struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; | ||
| 73 | unsigned long flags; | ||
| 74 | |||
| 75 | spin_lock_irqsave(&chip->lock, flags); | ||
| 76 | __cs5535_gpio_set(chip, offset, reg); | ||
| 77 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 78 | } | ||
| 79 | EXPORT_SYMBOL_GPL(cs5535_gpio_set); | ||
| 80 | |||
| 81 | static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset, | ||
| 82 | unsigned int reg) | ||
| 83 | { | ||
| 84 | if (offset < 16) | ||
| 85 | /* low bank register */ | ||
| 86 | outl(1 << (offset + 16), chip->base + reg); | ||
| 87 | else | ||
| 88 | /* high bank register */ | ||
| 89 | outl(1 << offset, chip->base + 0x80 + reg); | ||
| 90 | } | ||
| 91 | |||
| 92 | void cs5535_gpio_clear(unsigned offset, unsigned int reg) | ||
| 93 | { | ||
| 94 | struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; | ||
| 95 | unsigned long flags; | ||
| 96 | |||
| 97 | spin_lock_irqsave(&chip->lock, flags); | ||
| 98 | __cs5535_gpio_clear(chip, offset, reg); | ||
| 99 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 100 | } | ||
| 101 | EXPORT_SYMBOL_GPL(cs5535_gpio_clear); | ||
| 102 | |||
| 103 | int cs5535_gpio_isset(unsigned offset, unsigned int reg) | ||
| 104 | { | ||
| 105 | struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; | ||
| 106 | unsigned long flags; | ||
| 107 | long val; | ||
| 108 | |||
| 109 | spin_lock_irqsave(&chip->lock, flags); | ||
| 110 | if (offset < 16) | ||
| 111 | /* low bank register */ | ||
| 112 | val = inl(chip->base + reg); | ||
| 113 | else { | ||
| 114 | /* high bank register */ | ||
| 115 | val = inl(chip->base + 0x80 + reg); | ||
| 116 | offset -= 16; | ||
| 117 | } | ||
| 118 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 119 | |||
| 120 | return (val & (1 << offset)) ? 1 : 0; | ||
| 121 | } | ||
| 122 | EXPORT_SYMBOL_GPL(cs5535_gpio_isset); | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Generic gpio_chip API support. | ||
| 126 | */ | ||
| 127 | |||
| 128 | static int chip_gpio_request(struct gpio_chip *c, unsigned offset) | ||
| 129 | { | ||
| 130 | struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | ||
| 131 | unsigned long flags; | ||
| 132 | |||
| 133 | spin_lock_irqsave(&chip->lock, flags); | ||
| 134 | |||
| 135 | /* check if this pin is available */ | ||
| 136 | if ((mask & (1 << offset)) == 0) { | ||
| 137 | dev_info(&chip->pdev->dev, | ||
| 138 | "pin %u is not available (check mask)\n", offset); | ||
| 139 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 140 | return -EINVAL; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* disable output aux 1 & 2 on this pin */ | ||
| 144 | __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1); | ||
| 145 | __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2); | ||
| 146 | |||
| 147 | /* disable input aux 1 on this pin */ | ||
| 148 | __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1); | ||
| 149 | |||
| 150 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int chip_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
| 156 | { | ||
| 157 | return cs5535_gpio_isset(offset, GPIO_OUTPUT_VAL); | ||
| 158 | } | ||
| 159 | |||
| 160 | static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
| 161 | { | ||
| 162 | if (val) | ||
| 163 | cs5535_gpio_set(offset, GPIO_OUTPUT_VAL); | ||
| 164 | else | ||
| 165 | cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL); | ||
| 166 | } | ||
| 167 | |||
| 168 | static int chip_direction_input(struct gpio_chip *c, unsigned offset) | ||
| 169 | { | ||
| 170 | struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | ||
| 171 | unsigned long flags; | ||
| 172 | |||
| 173 | spin_lock_irqsave(&chip->lock, flags); | ||
| 174 | __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); | ||
| 175 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) | ||
| 181 | { | ||
| 182 | struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | ||
| 183 | unsigned long flags; | ||
| 184 | |||
| 185 | spin_lock_irqsave(&chip->lock, flags); | ||
| 186 | |||
| 187 | __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE); | ||
| 188 | if (val) | ||
| 189 | __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL); | ||
| 190 | else | ||
| 191 | __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL); | ||
| 192 | |||
| 193 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 194 | |||
| 195 | return 0; | ||
| 196 | } | ||
| 197 | |||
| 198 | static char *cs5535_gpio_names[] = { | ||
| 199 | "GPIO0", "GPIO1", "GPIO2", "GPIO3", | ||
| 200 | "GPIO4", "GPIO5", "GPIO6", "GPIO7", | ||
| 201 | "GPIO8", "GPIO9", "GPIO10", "GPIO11", | ||
| 202 | "GPIO12", "GPIO13", "GPIO14", "GPIO15", | ||
| 203 | "GPIO16", "GPIO17", "GPIO18", "GPIO19", | ||
| 204 | "GPIO20", "GPIO21", "GPIO22", NULL, | ||
| 205 | "GPIO24", "GPIO25", "GPIO26", "GPIO27", | ||
| 206 | "GPIO28", NULL, NULL, NULL, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static struct cs5535_gpio_chip cs5535_gpio_chip = { | ||
| 210 | .chip = { | ||
| 211 | .owner = THIS_MODULE, | ||
| 212 | .label = DRV_NAME, | ||
| 213 | |||
| 214 | .base = 0, | ||
| 215 | .ngpio = 32, | ||
| 216 | .names = cs5535_gpio_names, | ||
| 217 | .request = chip_gpio_request, | ||
| 218 | |||
| 219 | .get = chip_gpio_get, | ||
| 220 | .set = chip_gpio_set, | ||
| 221 | |||
| 222 | .direction_input = chip_direction_input, | ||
| 223 | .direction_output = chip_direction_output, | ||
| 224 | }, | ||
| 225 | }; | ||
| 226 | |||
| 227 | static int __init cs5535_gpio_probe(struct pci_dev *pdev, | ||
| 228 | const struct pci_device_id *pci_id) | ||
| 229 | { | ||
| 230 | int err; | ||
| 231 | ulong mask_orig = mask; | ||
| 232 | |||
| 233 | /* There are two ways to get the GPIO base address; one is by | ||
| 234 | * fetching it from MSR_LBAR_GPIO, the other is by reading the | ||
| 235 | * PCI BAR info. The latter method is easier (especially across | ||
| 236 | * different architectures), so we'll stick with that for now. If | ||
| 237 | * it turns out to be unreliable in the face of crappy BIOSes, we | ||
| 238 | * can always go back to using MSRs.. */ | ||
| 239 | |||
| 240 | err = pci_enable_device_io(pdev); | ||
| 241 | if (err) { | ||
| 242 | dev_err(&pdev->dev, "can't enable device IO\n"); | ||
| 243 | goto done; | ||
| 244 | } | ||
| 245 | |||
| 246 | err = pci_request_region(pdev, GPIO_BAR, DRV_NAME); | ||
| 247 | if (err) { | ||
| 248 | dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR); | ||
| 249 | goto done; | ||
| 250 | } | ||
| 251 | |||
| 252 | /* set up the driver-specific struct */ | ||
| 253 | cs5535_gpio_chip.base = pci_resource_start(pdev, GPIO_BAR); | ||
| 254 | cs5535_gpio_chip.pdev = pdev; | ||
| 255 | spin_lock_init(&cs5535_gpio_chip.lock); | ||
| 256 | |||
| 257 | dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR, | ||
| 258 | (unsigned long long) cs5535_gpio_chip.base); | ||
| 259 | |||
| 260 | /* mask out reserved pins */ | ||
| 261 | mask &= 0x1F7FFFFF; | ||
| 262 | |||
| 263 | /* do not allow pin 28, Power Button, as there's special handling | ||
| 264 | * in the PMC needed. (note 12, p. 48) */ | ||
| 265 | mask &= ~(1 << 28); | ||
| 266 | |||
| 267 | if (mask_orig != mask) | ||
| 268 | dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n", | ||
| 269 | mask_orig, mask); | ||
| 270 | |||
| 271 | /* finally, register with the generic GPIO API */ | ||
| 272 | err = gpiochip_add(&cs5535_gpio_chip.chip); | ||
| 273 | if (err) | ||
| 274 | goto release_region; | ||
| 275 | |||
| 276 | dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n"); | ||
| 277 | return 0; | ||
| 278 | |||
| 279 | release_region: | ||
| 280 | pci_release_region(pdev, GPIO_BAR); | ||
| 281 | done: | ||
| 282 | return err; | ||
| 283 | } | ||
| 284 | |||
| 285 | static void __exit cs5535_gpio_remove(struct pci_dev *pdev) | ||
| 286 | { | ||
| 287 | int err; | ||
| 288 | |||
| 289 | err = gpiochip_remove(&cs5535_gpio_chip.chip); | ||
| 290 | if (err) { | ||
| 291 | /* uhh? */ | ||
| 292 | dev_err(&pdev->dev, "unable to remove gpio_chip?\n"); | ||
| 293 | } | ||
| 294 | pci_release_region(pdev, GPIO_BAR); | ||
| 295 | } | ||
| 296 | |||
| 297 | static struct pci_device_id cs5535_gpio_pci_tbl[] = { | ||
| 298 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, | ||
| 299 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, | ||
| 300 | { 0, }, | ||
| 301 | }; | ||
| 302 | MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl); | ||
| 303 | |||
| 304 | /* | ||
| 305 | * We can't use the standard PCI driver registration stuff here, since | ||
| 306 | * that allows only one driver to bind to each PCI device (and we want | ||
| 307 | * multiple drivers to be able to bind to the device). Instead, manually | ||
| 308 | * scan for the PCI device, request a single region, and keep track of the | ||
| 309 | * devices that we're using. | ||
| 310 | */ | ||
| 311 | |||
| 312 | static int __init cs5535_gpio_scan_pci(void) | ||
| 313 | { | ||
| 314 | struct pci_dev *pdev; | ||
| 315 | int err = -ENODEV; | ||
| 316 | int i; | ||
| 317 | |||
| 318 | for (i = 0; i < ARRAY_SIZE(cs5535_gpio_pci_tbl); i++) { | ||
| 319 | pdev = pci_get_device(cs5535_gpio_pci_tbl[i].vendor, | ||
| 320 | cs5535_gpio_pci_tbl[i].device, NULL); | ||
| 321 | if (pdev) { | ||
| 322 | err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]); | ||
| 323 | if (err) | ||
| 324 | pci_dev_put(pdev); | ||
| 325 | |||
| 326 | /* we only support a single CS5535/6 southbridge */ | ||
| 327 | break; | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | return err; | ||
| 332 | } | ||
| 333 | |||
| 334 | static void __exit cs5535_gpio_free_pci(void) | ||
| 335 | { | ||
| 336 | cs5535_gpio_remove(cs5535_gpio_chip.pdev); | ||
| 337 | pci_dev_put(cs5535_gpio_chip.pdev); | ||
| 338 | } | ||
| 339 | |||
| 340 | static int __init cs5535_gpio_init(void) | ||
| 341 | { | ||
| 342 | return cs5535_gpio_scan_pci(); | ||
| 343 | } | ||
| 344 | |||
| 345 | static void __exit cs5535_gpio_exit(void) | ||
| 346 | { | ||
| 347 | cs5535_gpio_free_pci(); | ||
| 348 | } | ||
| 349 | |||
| 350 | module_init(cs5535_gpio_init); | ||
| 351 | module_exit(cs5535_gpio_exit); | ||
| 352 | |||
| 353 | MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>"); | ||
| 354 | MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); | ||
| 355 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 9e640c62ebd9..95ccbe377f9c 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -1046,25 +1046,27 @@ config SENSORS_ATK0110 | |||
| 1046 | will be called asus_atk0110. | 1046 | will be called asus_atk0110. |
| 1047 | 1047 | ||
| 1048 | config SENSORS_LIS3LV02D | 1048 | config SENSORS_LIS3LV02D |
| 1049 | tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer" | 1049 | tristate "STMicroeletronics LIS3* three-axis digital accelerometer" |
| 1050 | depends on INPUT | 1050 | depends on INPUT |
| 1051 | select INPUT_POLLDEV | 1051 | select INPUT_POLLDEV |
| 1052 | select NEW_LEDS | 1052 | select NEW_LEDS |
| 1053 | select LEDS_CLASS | 1053 | select LEDS_CLASS |
| 1054 | default n | 1054 | default n |
| 1055 | help | 1055 | help |
| 1056 | This driver provides support for the LIS3LV02Dx accelerometer. In | 1056 | This driver provides support for the LIS3* accelerometers, such as the |
| 1057 | particular, it can be found in a number of HP laptops, which have the | 1057 | LIS3LV02DL or the LIS331DL. In particular, it can be found in a number |
| 1058 | "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such | 1058 | of HP laptops, which have the "Mobile Data Protection System 3D" or |
| 1059 | systems the driver should load automatically (via ACPI). The | 1059 | "3D DriveGuard" feature. On such systems the driver should load |
| 1060 | accelerometer might also be found in other systems, connected via SPI | 1060 | automatically (via ACPI alias). The accelerometer might also be found |
| 1061 | or I2C. The accelerometer data is readable via | 1061 | in other systems, connected via SPI or I2C. The accelerometer data is |
| 1062 | /sys/devices/platform/lis3lv02d. | 1062 | readable via /sys/devices/platform/lis3lv02d. |
| 1063 | 1063 | ||
| 1064 | This driver also provides an absolute input class device, allowing | 1064 | This driver also provides an absolute input class device, allowing |
| 1065 | the laptop to act as a pinball machine-esque joystick. On HP laptops, | 1065 | a laptop to act as a pinball machine-esque joystick. It provides also |
| 1066 | a misc device which can be used to detect free-fall. On HP laptops, | ||
| 1066 | if the led infrastructure is activated, support for a led indicating | 1067 | if the led infrastructure is activated, support for a led indicating |
| 1067 | disk protection will be provided as hp:red:hddprotection. | 1068 | disk protection will be provided as hp::hddprotect. For more |
| 1069 | information on the feature, refer to Documentation/hwmon/lis3lv02d. | ||
| 1068 | 1070 | ||
| 1069 | This driver can also be built as modules. If so, the core module | 1071 | This driver can also be built as modules. If so, the core module |
| 1070 | will be called lis3lv02d and a specific module for HP laptops will be | 1072 | will be called lis3lv02d and a specific module for HP laptops will be |
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 33acf29531af..1ad0a885c5a5 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c | |||
| @@ -34,9 +34,8 @@ | |||
| 34 | static const unsigned short normal_i2c[] = { | 34 | static const unsigned short normal_i2c[] = { |
| 35 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | 35 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; |
| 36 | 36 | ||
| 37 | /* Insmod parameters */ | 37 | enum chips { |
| 38 | I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, | 38 | adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066 }; |
| 39 | mc1066); | ||
| 40 | 39 | ||
| 41 | /* adm1021 constants specified below */ | 40 | /* adm1021 constants specified below */ |
| 42 | 41 | ||
| @@ -97,7 +96,7 @@ struct adm1021_data { | |||
| 97 | 96 | ||
| 98 | static int adm1021_probe(struct i2c_client *client, | 97 | static int adm1021_probe(struct i2c_client *client, |
| 99 | const struct i2c_device_id *id); | 98 | const struct i2c_device_id *id); |
| 100 | static int adm1021_detect(struct i2c_client *client, int kind, | 99 | static int adm1021_detect(struct i2c_client *client, |
| 101 | struct i2c_board_info *info); | 100 | struct i2c_board_info *info); |
| 102 | static void adm1021_init_client(struct i2c_client *client); | 101 | static void adm1021_init_client(struct i2c_client *client); |
| 103 | static int adm1021_remove(struct i2c_client *client); | 102 | static int adm1021_remove(struct i2c_client *client); |
| @@ -130,7 +129,7 @@ static struct i2c_driver adm1021_driver = { | |||
| 130 | .remove = adm1021_remove, | 129 | .remove = adm1021_remove, |
| 131 | .id_table = adm1021_id, | 130 | .id_table = adm1021_id, |
| 132 | .detect = adm1021_detect, | 131 | .detect = adm1021_detect, |
| 133 | .address_data = &addr_data, | 132 | .address_list = normal_i2c, |
| 134 | }; | 133 | }; |
| 135 | 134 | ||
| 136 | static ssize_t show_temp(struct device *dev, | 135 | static ssize_t show_temp(struct device *dev, |
| @@ -284,7 +283,7 @@ static const struct attribute_group adm1021_group = { | |||
| 284 | }; | 283 | }; |
| 285 | 284 | ||
| 286 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 285 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 287 | static int adm1021_detect(struct i2c_client *client, int kind, | 286 | static int adm1021_detect(struct i2c_client *client, |
| 288 | struct i2c_board_info *info) | 287 | struct i2c_board_info *info) |
| 289 | { | 288 | { |
| 290 | struct i2c_adapter *adapter = client->adapter; | 289 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index db6ac2b04f6f..251b63165e2a 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c | |||
| @@ -64,11 +64,7 @@ | |||
| 64 | 64 | ||
| 65 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 65 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 66 | 66 | ||
| 67 | /* | 67 | enum chips { adm1025, ne1619 }; |
| 68 | * Insmod parameters | ||
| 69 | */ | ||
| 70 | |||
| 71 | I2C_CLIENT_INSMOD_2(adm1025, ne1619); | ||
| 72 | 68 | ||
| 73 | /* | 69 | /* |
| 74 | * The ADM1025 registers | 70 | * The ADM1025 registers |
| @@ -111,7 +107,7 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; | |||
| 111 | 107 | ||
| 112 | static int adm1025_probe(struct i2c_client *client, | 108 | static int adm1025_probe(struct i2c_client *client, |
| 113 | const struct i2c_device_id *id); | 109 | const struct i2c_device_id *id); |
| 114 | static int adm1025_detect(struct i2c_client *client, int kind, | 110 | static int adm1025_detect(struct i2c_client *client, |
| 115 | struct i2c_board_info *info); | 111 | struct i2c_board_info *info); |
| 116 | static void adm1025_init_client(struct i2c_client *client); | 112 | static void adm1025_init_client(struct i2c_client *client); |
| 117 | static int adm1025_remove(struct i2c_client *client); | 113 | static int adm1025_remove(struct i2c_client *client); |
| @@ -137,7 +133,7 @@ static struct i2c_driver adm1025_driver = { | |||
| 137 | .remove = adm1025_remove, | 133 | .remove = adm1025_remove, |
| 138 | .id_table = adm1025_id, | 134 | .id_table = adm1025_id, |
| 139 | .detect = adm1025_detect, | 135 | .detect = adm1025_detect, |
| 140 | .address_data = &addr_data, | 136 | .address_list = normal_i2c, |
| 141 | }; | 137 | }; |
| 142 | 138 | ||
| 143 | /* | 139 | /* |
| @@ -409,7 +405,7 @@ static const struct attribute_group adm1025_group_in4 = { | |||
| 409 | }; | 405 | }; |
| 410 | 406 | ||
| 411 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 407 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 412 | static int adm1025_detect(struct i2c_client *client, int kind, | 408 | static int adm1025_detect(struct i2c_client *client, |
| 413 | struct i2c_board_info *info) | 409 | struct i2c_board_info *info) |
| 414 | { | 410 | { |
| 415 | struct i2c_adapter *adapter = client->adapter; | 411 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index fb5363985e21..65335b268fa9 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c | |||
| @@ -37,9 +37,6 @@ | |||
| 37 | /* Addresses to scan */ | 37 | /* Addresses to scan */ |
| 38 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 38 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 39 | 39 | ||
| 40 | /* Insmod parameters */ | ||
| 41 | I2C_CLIENT_INSMOD_1(adm1026); | ||
| 42 | |||
| 43 | static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, | 40 | static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 44 | -1, -1, -1, -1, -1, -1, -1, -1 }; | 41 | -1, -1, -1, -1, -1, -1, -1, -1 }; |
| 45 | static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, | 42 | static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| @@ -293,7 +290,7 @@ struct adm1026_data { | |||
| 293 | 290 | ||
| 294 | static int adm1026_probe(struct i2c_client *client, | 291 | static int adm1026_probe(struct i2c_client *client, |
| 295 | const struct i2c_device_id *id); | 292 | const struct i2c_device_id *id); |
| 296 | static int adm1026_detect(struct i2c_client *client, int kind, | 293 | static int adm1026_detect(struct i2c_client *client, |
| 297 | struct i2c_board_info *info); | 294 | struct i2c_board_info *info); |
| 298 | static int adm1026_remove(struct i2c_client *client); | 295 | static int adm1026_remove(struct i2c_client *client); |
| 299 | static int adm1026_read_value(struct i2c_client *client, u8 reg); | 296 | static int adm1026_read_value(struct i2c_client *client, u8 reg); |
| @@ -305,7 +302,7 @@ static void adm1026_init_client(struct i2c_client *client); | |||
| 305 | 302 | ||
| 306 | 303 | ||
| 307 | static const struct i2c_device_id adm1026_id[] = { | 304 | static const struct i2c_device_id adm1026_id[] = { |
| 308 | { "adm1026", adm1026 }, | 305 | { "adm1026", 0 }, |
| 309 | { } | 306 | { } |
| 310 | }; | 307 | }; |
| 311 | MODULE_DEVICE_TABLE(i2c, adm1026_id); | 308 | MODULE_DEVICE_TABLE(i2c, adm1026_id); |
| @@ -319,7 +316,7 @@ static struct i2c_driver adm1026_driver = { | |||
| 319 | .remove = adm1026_remove, | 316 | .remove = adm1026_remove, |
| 320 | .id_table = adm1026_id, | 317 | .id_table = adm1026_id, |
| 321 | .detect = adm1026_detect, | 318 | .detect = adm1026_detect, |
| 322 | .address_data = &addr_data, | 319 | .address_list = normal_i2c, |
| 323 | }; | 320 | }; |
| 324 | 321 | ||
| 325 | static int adm1026_read_value(struct i2c_client *client, u8 reg) | 322 | static int adm1026_read_value(struct i2c_client *client, u8 reg) |
| @@ -1650,7 +1647,7 @@ static const struct attribute_group adm1026_group_in8_9 = { | |||
| 1650 | }; | 1647 | }; |
| 1651 | 1648 | ||
| 1652 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1649 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1653 | static int adm1026_detect(struct i2c_client *client, int kind, | 1650 | static int adm1026_detect(struct i2c_client *client, |
| 1654 | struct i2c_board_info *info) | 1651 | struct i2c_board_info *info) |
| 1655 | { | 1652 | { |
| 1656 | struct i2c_adapter *adapter = client->adapter; | 1653 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index ef91e2a4a567..0b8a3b145bd2 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c | |||
| @@ -44,12 +44,6 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | |||
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | /* | 46 | /* |
| 47 | * Insmod parameters | ||
| 48 | */ | ||
| 49 | |||
| 50 | I2C_CLIENT_INSMOD_1(adm1029); | ||
| 51 | |||
| 52 | /* | ||
| 53 | * The ADM1029 registers | 47 | * The ADM1029 registers |
| 54 | * Manufacturer ID is 0x41 for Analog Devices | 48 | * Manufacturer ID is 0x41 for Analog Devices |
| 55 | */ | 49 | */ |
| @@ -117,7 +111,7 @@ static const u8 ADM1029_REG_FAN_DIV[] = { | |||
| 117 | 111 | ||
| 118 | static int adm1029_probe(struct i2c_client *client, | 112 | static int adm1029_probe(struct i2c_client *client, |
| 119 | const struct i2c_device_id *id); | 113 | const struct i2c_device_id *id); |
| 120 | static int adm1029_detect(struct i2c_client *client, int kind, | 114 | static int adm1029_detect(struct i2c_client *client, |
| 121 | struct i2c_board_info *info); | 115 | struct i2c_board_info *info); |
| 122 | static int adm1029_remove(struct i2c_client *client); | 116 | static int adm1029_remove(struct i2c_client *client); |
| 123 | static struct adm1029_data *adm1029_update_device(struct device *dev); | 117 | static struct adm1029_data *adm1029_update_device(struct device *dev); |
| @@ -128,7 +122,7 @@ static int adm1029_init_client(struct i2c_client *client); | |||
| 128 | */ | 122 | */ |
| 129 | 123 | ||
| 130 | static const struct i2c_device_id adm1029_id[] = { | 124 | static const struct i2c_device_id adm1029_id[] = { |
| 131 | { "adm1029", adm1029 }, | 125 | { "adm1029", 0 }, |
| 132 | { } | 126 | { } |
| 133 | }; | 127 | }; |
| 134 | MODULE_DEVICE_TABLE(i2c, adm1029_id); | 128 | MODULE_DEVICE_TABLE(i2c, adm1029_id); |
| @@ -142,7 +136,7 @@ static struct i2c_driver adm1029_driver = { | |||
| 142 | .remove = adm1029_remove, | 136 | .remove = adm1029_remove, |
| 143 | .id_table = adm1029_id, | 137 | .id_table = adm1029_id, |
| 144 | .detect = adm1029_detect, | 138 | .detect = adm1029_detect, |
| 145 | .address_data = &addr_data, | 139 | .address_list = normal_i2c, |
| 146 | }; | 140 | }; |
| 147 | 141 | ||
| 148 | /* | 142 | /* |
| @@ -297,7 +291,7 @@ static const struct attribute_group adm1029_group = { | |||
| 297 | */ | 291 | */ |
| 298 | 292 | ||
| 299 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 293 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 300 | static int adm1029_detect(struct i2c_client *client, int kind, | 294 | static int adm1029_detect(struct i2c_client *client, |
| 301 | struct i2c_board_info *info) | 295 | struct i2c_board_info *info) |
| 302 | { | 296 | { |
| 303 | struct i2c_adapter *adapter = client->adapter; | 297 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 0e722175aae0..1644b92e7cc4 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c | |||
| @@ -64,8 +64,7 @@ | |||
| 64 | /* Addresses to scan */ | 64 | /* Addresses to scan */ |
| 65 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 65 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 66 | 66 | ||
| 67 | /* Insmod parameters */ | 67 | enum chips { adm1030, adm1031 }; |
| 68 | I2C_CLIENT_INSMOD_2(adm1030, adm1031); | ||
| 69 | 68 | ||
| 70 | typedef u8 auto_chan_table_t[8][2]; | 69 | typedef u8 auto_chan_table_t[8][2]; |
| 71 | 70 | ||
| @@ -102,7 +101,7 @@ struct adm1031_data { | |||
| 102 | 101 | ||
| 103 | static int adm1031_probe(struct i2c_client *client, | 102 | static int adm1031_probe(struct i2c_client *client, |
| 104 | const struct i2c_device_id *id); | 103 | const struct i2c_device_id *id); |
| 105 | static int adm1031_detect(struct i2c_client *client, int kind, | 104 | static int adm1031_detect(struct i2c_client *client, |
| 106 | struct i2c_board_info *info); | 105 | struct i2c_board_info *info); |
| 107 | static void adm1031_init_client(struct i2c_client *client); | 106 | static void adm1031_init_client(struct i2c_client *client); |
| 108 | static int adm1031_remove(struct i2c_client *client); | 107 | static int adm1031_remove(struct i2c_client *client); |
| @@ -125,7 +124,7 @@ static struct i2c_driver adm1031_driver = { | |||
| 125 | .remove = adm1031_remove, | 124 | .remove = adm1031_remove, |
| 126 | .id_table = adm1031_id, | 125 | .id_table = adm1031_id, |
| 127 | .detect = adm1031_detect, | 126 | .detect = adm1031_detect, |
| 128 | .address_data = &addr_data, | 127 | .address_list = normal_i2c, |
| 129 | }; | 128 | }; |
| 130 | 129 | ||
| 131 | static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) | 130 | static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) |
| @@ -813,7 +812,7 @@ static const struct attribute_group adm1031_group_opt = { | |||
| 813 | }; | 812 | }; |
| 814 | 813 | ||
| 815 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 814 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 816 | static int adm1031_detect(struct i2c_client *client, int kind, | 815 | static int adm1031_detect(struct i2c_client *client, |
| 817 | struct i2c_board_info *info) | 816 | struct i2c_board_info *info) |
| 818 | { | 817 | { |
| 819 | struct i2c_adapter *adapter = client->adapter; | 818 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 20e0481cc206..0727ad250793 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c | |||
| @@ -55,8 +55,7 @@ | |||
| 55 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | 55 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, |
| 56 | I2C_CLIENT_END }; | 56 | I2C_CLIENT_END }; |
| 57 | 57 | ||
| 58 | /* Insmod parameters */ | 58 | enum chips { adm9240, ds1780, lm81 }; |
| 59 | I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81); | ||
| 60 | 59 | ||
| 61 | /* ADM9240 registers */ | 60 | /* ADM9240 registers */ |
| 62 | #define ADM9240_REG_MAN_ID 0x3e | 61 | #define ADM9240_REG_MAN_ID 0x3e |
| @@ -132,7 +131,7 @@ static inline unsigned int AOUT_FROM_REG(u8 reg) | |||
| 132 | 131 | ||
| 133 | static int adm9240_probe(struct i2c_client *client, | 132 | static int adm9240_probe(struct i2c_client *client, |
| 134 | const struct i2c_device_id *id); | 133 | const struct i2c_device_id *id); |
| 135 | static int adm9240_detect(struct i2c_client *client, int kind, | 134 | static int adm9240_detect(struct i2c_client *client, |
| 136 | struct i2c_board_info *info); | 135 | struct i2c_board_info *info); |
| 137 | static void adm9240_init_client(struct i2c_client *client); | 136 | static void adm9240_init_client(struct i2c_client *client); |
| 138 | static int adm9240_remove(struct i2c_client *client); | 137 | static int adm9240_remove(struct i2c_client *client); |
| @@ -156,7 +155,7 @@ static struct i2c_driver adm9240_driver = { | |||
| 156 | .remove = adm9240_remove, | 155 | .remove = adm9240_remove, |
| 157 | .id_table = adm9240_id, | 156 | .id_table = adm9240_id, |
| 158 | .detect = adm9240_detect, | 157 | .detect = adm9240_detect, |
| 159 | .address_data = &addr_data, | 158 | .address_list = normal_i2c, |
| 160 | }; | 159 | }; |
| 161 | 160 | ||
| 162 | /* per client data */ | 161 | /* per client data */ |
| @@ -545,7 +544,7 @@ static const struct attribute_group adm9240_group = { | |||
| 545 | /*** sensor chip detect and driver install ***/ | 544 | /*** sensor chip detect and driver install ***/ |
| 546 | 545 | ||
| 547 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 546 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 548 | static int adm9240_detect(struct i2c_client *new_client, int kind, | 547 | static int adm9240_detect(struct i2c_client *new_client, |
| 549 | struct i2c_board_info *info) | 548 | struct i2c_board_info *info) |
| 550 | { | 549 | { |
| 551 | struct i2c_adapter *adapter = new_client->adapter; | 550 | struct i2c_adapter *adapter = new_client->adapter; |
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index 451977bca7d6..aac85f3aed50 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c | |||
| @@ -47,10 +47,7 @@ | |||
| 47 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, | 47 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, |
| 48 | I2C_CLIENT_END }; | 48 | I2C_CLIENT_END }; |
| 49 | 49 | ||
| 50 | /* Insmod parameters */ | 50 | /* Module parameters */ |
| 51 | I2C_CLIENT_INSMOD_1(ads7828); | ||
| 52 | |||
| 53 | /* Other module parameters */ | ||
| 54 | static int se_input = 1; /* Default is SE, 0 == diff */ | 51 | static int se_input = 1; /* Default is SE, 0 == diff */ |
| 55 | static int int_vref = 1; /* Default is internal ref ON */ | 52 | static int int_vref = 1; /* Default is internal ref ON */ |
| 56 | static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */ | 53 | static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */ |
| @@ -72,7 +69,7 @@ struct ads7828_data { | |||
| 72 | }; | 69 | }; |
| 73 | 70 | ||
| 74 | /* Function declaration - necessary due to function dependencies */ | 71 | /* Function declaration - necessary due to function dependencies */ |
| 75 | static int ads7828_detect(struct i2c_client *client, int kind, | 72 | static int ads7828_detect(struct i2c_client *client, |
| 76 | struct i2c_board_info *info); | 73 | struct i2c_board_info *info); |
| 77 | static int ads7828_probe(struct i2c_client *client, | 74 | static int ads7828_probe(struct i2c_client *client, |
| 78 | const struct i2c_device_id *id); | 75 | const struct i2c_device_id *id); |
| @@ -168,7 +165,7 @@ static int ads7828_remove(struct i2c_client *client) | |||
| 168 | } | 165 | } |
| 169 | 166 | ||
| 170 | static const struct i2c_device_id ads7828_id[] = { | 167 | static const struct i2c_device_id ads7828_id[] = { |
| 171 | { "ads7828", ads7828 }, | 168 | { "ads7828", 0 }, |
| 172 | { } | 169 | { } |
| 173 | }; | 170 | }; |
| 174 | MODULE_DEVICE_TABLE(i2c, ads7828_id); | 171 | MODULE_DEVICE_TABLE(i2c, ads7828_id); |
| @@ -183,11 +180,11 @@ static struct i2c_driver ads7828_driver = { | |||
| 183 | .remove = ads7828_remove, | 180 | .remove = ads7828_remove, |
| 184 | .id_table = ads7828_id, | 181 | .id_table = ads7828_id, |
| 185 | .detect = ads7828_detect, | 182 | .detect = ads7828_detect, |
| 186 | .address_data = &addr_data, | 183 | .address_list = normal_i2c, |
| 187 | }; | 184 | }; |
| 188 | 185 | ||
| 189 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 186 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 190 | static int ads7828_detect(struct i2c_client *client, int kind, | 187 | static int ads7828_detect(struct i2c_client *client, |
| 191 | struct i2c_board_info *info) | 188 | struct i2c_board_info *info) |
| 192 | { | 189 | { |
| 193 | struct i2c_adapter *adapter = client->adapter; | 190 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index f9c9562b6a94..a1a7ef14b519 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c | |||
| @@ -32,9 +32,6 @@ | |||
| 32 | /* Addresses to scan */ | 32 | /* Addresses to scan */ |
| 33 | static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; | 33 | static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; |
| 34 | 34 | ||
| 35 | /* Insmod parameters */ | ||
| 36 | I2C_CLIENT_INSMOD_1(adt7462); | ||
| 37 | |||
| 38 | /* ADT7462 registers */ | 35 | /* ADT7462 registers */ |
| 39 | #define ADT7462_REG_DEVICE 0x3D | 36 | #define ADT7462_REG_DEVICE 0x3D |
| 40 | #define ADT7462_REG_VENDOR 0x3E | 37 | #define ADT7462_REG_VENDOR 0x3E |
| @@ -237,12 +234,12 @@ struct adt7462_data { | |||
| 237 | 234 | ||
| 238 | static int adt7462_probe(struct i2c_client *client, | 235 | static int adt7462_probe(struct i2c_client *client, |
| 239 | const struct i2c_device_id *id); | 236 | const struct i2c_device_id *id); |
| 240 | static int adt7462_detect(struct i2c_client *client, int kind, | 237 | static int adt7462_detect(struct i2c_client *client, |
| 241 | struct i2c_board_info *info); | 238 | struct i2c_board_info *info); |
| 242 | static int adt7462_remove(struct i2c_client *client); | 239 | static int adt7462_remove(struct i2c_client *client); |
| 243 | 240 | ||
| 244 | static const struct i2c_device_id adt7462_id[] = { | 241 | static const struct i2c_device_id adt7462_id[] = { |
| 245 | { "adt7462", adt7462 }, | 242 | { "adt7462", 0 }, |
| 246 | { } | 243 | { } |
| 247 | }; | 244 | }; |
| 248 | MODULE_DEVICE_TABLE(i2c, adt7462_id); | 245 | MODULE_DEVICE_TABLE(i2c, adt7462_id); |
| @@ -256,7 +253,7 @@ static struct i2c_driver adt7462_driver = { | |||
| 256 | .remove = adt7462_remove, | 253 | .remove = adt7462_remove, |
| 257 | .id_table = adt7462_id, | 254 | .id_table = adt7462_id, |
| 258 | .detect = adt7462_detect, | 255 | .detect = adt7462_detect, |
| 259 | .address_data = &addr_data, | 256 | .address_list = normal_i2c, |
| 260 | }; | 257 | }; |
| 261 | 258 | ||
| 262 | /* | 259 | /* |
| @@ -1902,7 +1899,7 @@ static struct attribute *adt7462_attr[] = | |||
| 1902 | }; | 1899 | }; |
| 1903 | 1900 | ||
| 1904 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1901 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1905 | static int adt7462_detect(struct i2c_client *client, int kind, | 1902 | static int adt7462_detect(struct i2c_client *client, |
| 1906 | struct i2c_board_info *info) | 1903 | struct i2c_board_info *info) |
| 1907 | { | 1904 | { |
| 1908 | struct i2c_adapter *adapter = client->adapter; | 1905 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 32b1750a6890..3445ce1cba81 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c | |||
| @@ -33,9 +33,6 @@ | |||
| 33 | /* Addresses to scan */ | 33 | /* Addresses to scan */ |
| 34 | static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; | 34 | static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; |
| 35 | 35 | ||
| 36 | /* Insmod parameters */ | ||
| 37 | I2C_CLIENT_INSMOD_1(adt7470); | ||
| 38 | |||
| 39 | /* ADT7470 registers */ | 36 | /* ADT7470 registers */ |
| 40 | #define ADT7470_REG_BASE_ADDR 0x20 | 37 | #define ADT7470_REG_BASE_ADDR 0x20 |
| 41 | #define ADT7470_REG_TEMP_BASE_ADDR 0x20 | 38 | #define ADT7470_REG_TEMP_BASE_ADDR 0x20 |
| @@ -177,12 +174,12 @@ struct adt7470_data { | |||
| 177 | 174 | ||
| 178 | static int adt7470_probe(struct i2c_client *client, | 175 | static int adt7470_probe(struct i2c_client *client, |
| 179 | const struct i2c_device_id *id); | 176 | const struct i2c_device_id *id); |
| 180 | static int adt7470_detect(struct i2c_client *client, int kind, | 177 | static int adt7470_detect(struct i2c_client *client, |
| 181 | struct i2c_board_info *info); | 178 | struct i2c_board_info *info); |
| 182 | static int adt7470_remove(struct i2c_client *client); | 179 | static int adt7470_remove(struct i2c_client *client); |
| 183 | 180 | ||
| 184 | static const struct i2c_device_id adt7470_id[] = { | 181 | static const struct i2c_device_id adt7470_id[] = { |
| 185 | { "adt7470", adt7470 }, | 182 | { "adt7470", 0 }, |
| 186 | { } | 183 | { } |
| 187 | }; | 184 | }; |
| 188 | MODULE_DEVICE_TABLE(i2c, adt7470_id); | 185 | MODULE_DEVICE_TABLE(i2c, adt7470_id); |
| @@ -196,7 +193,7 @@ static struct i2c_driver adt7470_driver = { | |||
| 196 | .remove = adt7470_remove, | 193 | .remove = adt7470_remove, |
| 197 | .id_table = adt7470_id, | 194 | .id_table = adt7470_id, |
| 198 | .detect = adt7470_detect, | 195 | .detect = adt7470_detect, |
| 199 | .address_data = &addr_data, | 196 | .address_list = normal_i2c, |
| 200 | }; | 197 | }; |
| 201 | 198 | ||
| 202 | /* | 199 | /* |
| @@ -1225,7 +1222,7 @@ static struct attribute *adt7470_attr[] = | |||
| 1225 | }; | 1222 | }; |
| 1226 | 1223 | ||
| 1227 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1224 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1228 | static int adt7470_detect(struct i2c_client *client, int kind, | 1225 | static int adt7470_detect(struct i2c_client *client, |
| 1229 | struct i2c_board_info *info) | 1226 | struct i2c_board_info *info) |
| 1230 | { | 1227 | { |
| 1231 | struct i2c_adapter *adapter = client->adapter; | 1228 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c index aea244db974e..434576f61c84 100644 --- a/drivers/hwmon/adt7473.c +++ b/drivers/hwmon/adt7473.c | |||
| @@ -32,9 +32,6 @@ | |||
| 32 | /* Addresses to scan */ | 32 | /* Addresses to scan */ |
| 33 | static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, I2C_CLIENT_END }; | 33 | static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, I2C_CLIENT_END }; |
| 34 | 34 | ||
| 35 | /* Insmod parameters */ | ||
| 36 | I2C_CLIENT_INSMOD_1(adt7473); | ||
| 37 | |||
| 38 | /* ADT7473 registers */ | 35 | /* ADT7473 registers */ |
| 39 | #define ADT7473_REG_BASE_ADDR 0x20 | 36 | #define ADT7473_REG_BASE_ADDR 0x20 |
| 40 | 37 | ||
| @@ -166,12 +163,12 @@ struct adt7473_data { | |||
| 166 | 163 | ||
| 167 | static int adt7473_probe(struct i2c_client *client, | 164 | static int adt7473_probe(struct i2c_client *client, |
| 168 | const struct i2c_device_id *id); | 165 | const struct i2c_device_id *id); |
| 169 | static int adt7473_detect(struct i2c_client *client, int kind, | 166 | static int adt7473_detect(struct i2c_client *client, |
| 170 | struct i2c_board_info *info); | 167 | struct i2c_board_info *info); |
| 171 | static int adt7473_remove(struct i2c_client *client); | 168 | static int adt7473_remove(struct i2c_client *client); |
| 172 | 169 | ||
| 173 | static const struct i2c_device_id adt7473_id[] = { | 170 | static const struct i2c_device_id adt7473_id[] = { |
| 174 | { "adt7473", adt7473 }, | 171 | { "adt7473", 0 }, |
| 175 | { } | 172 | { } |
| 176 | }; | 173 | }; |
| 177 | 174 | ||
| @@ -184,7 +181,7 @@ static struct i2c_driver adt7473_driver = { | |||
| 184 | .remove = adt7473_remove, | 181 | .remove = adt7473_remove, |
| 185 | .id_table = adt7473_id, | 182 | .id_table = adt7473_id, |
| 186 | .detect = adt7473_detect, | 183 | .detect = adt7473_detect, |
| 187 | .address_data = &addr_data, | 184 | .address_list = normal_i2c, |
| 188 | }; | 185 | }; |
| 189 | 186 | ||
| 190 | /* | 187 | /* |
| @@ -1085,7 +1082,7 @@ static struct attribute *adt7473_attr[] = | |||
| 1085 | }; | 1082 | }; |
| 1086 | 1083 | ||
| 1087 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1084 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1088 | static int adt7473_detect(struct i2c_client *client, int kind, | 1085 | static int adt7473_detect(struct i2c_client *client, |
| 1089 | struct i2c_board_info *info) | 1086 | struct i2c_board_info *info) |
| 1090 | { | 1087 | { |
| 1091 | struct i2c_adapter *adapter = client->adapter; | 1088 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 99abfddedbc3..a0c385145686 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c | |||
| @@ -148,7 +148,7 @@ | |||
| 148 | 148 | ||
| 149 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 149 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 150 | 150 | ||
| 151 | I2C_CLIENT_INSMOD_4(adt7473, adt7475, adt7476, adt7490); | 151 | enum chips { adt7473, adt7475, adt7476, adt7490 }; |
| 152 | 152 | ||
| 153 | static const struct i2c_device_id adt7475_id[] = { | 153 | static const struct i2c_device_id adt7475_id[] = { |
| 154 | { "adt7473", adt7473 }, | 154 | { "adt7473", adt7473 }, |
| @@ -1172,7 +1172,7 @@ static struct attribute_group in4_attr_group = { .attrs = in4_attrs }; | |||
| 1172 | static struct attribute_group in5_attr_group = { .attrs = in5_attrs }; | 1172 | static struct attribute_group in5_attr_group = { .attrs = in5_attrs }; |
| 1173 | static struct attribute_group vid_attr_group = { .attrs = vid_attrs }; | 1173 | static struct attribute_group vid_attr_group = { .attrs = vid_attrs }; |
| 1174 | 1174 | ||
| 1175 | static int adt7475_detect(struct i2c_client *client, int kind, | 1175 | static int adt7475_detect(struct i2c_client *client, |
| 1176 | struct i2c_board_info *info) | 1176 | struct i2c_board_info *info) |
| 1177 | { | 1177 | { |
| 1178 | struct i2c_adapter *adapter = client->adapter; | 1178 | struct i2c_adapter *adapter = client->adapter; |
| @@ -1412,7 +1412,7 @@ static struct i2c_driver adt7475_driver = { | |||
| 1412 | .remove = adt7475_remove, | 1412 | .remove = adt7475_remove, |
| 1413 | .id_table = adt7475_id, | 1413 | .id_table = adt7475_id, |
| 1414 | .detect = adt7475_detect, | 1414 | .detect = adt7475_detect, |
| 1415 | .address_data = &addr_data, | 1415 | .address_list = normal_i2c, |
| 1416 | }; | 1416 | }; |
| 1417 | 1417 | ||
| 1418 | static void adt7475_read_hystersis(struct i2c_client *client) | 1418 | static void adt7475_read_hystersis(struct i2c_client *client) |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 7ea6a8f66056..c1605b528e8f 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
| @@ -518,7 +518,7 @@ static int applesmc_pm_restore(struct device *dev) | |||
| 518 | return applesmc_pm_resume(dev); | 518 | return applesmc_pm_resume(dev); |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | static struct dev_pm_ops applesmc_pm_ops = { | 521 | static const struct dev_pm_ops applesmc_pm_ops = { |
| 522 | .resume = applesmc_pm_resume, | 522 | .resume = applesmc_pm_resume, |
| 523 | .restore = applesmc_pm_restore, | 523 | .restore = applesmc_pm_restore, |
| 524 | }; | 524 | }; |
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 480f80ea1fa0..7dada559b3a1 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c | |||
| @@ -51,9 +51,6 @@ | |||
| 51 | /* I2C addresses to scan */ | 51 | /* I2C addresses to scan */ |
| 52 | static const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; | 52 | static const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; |
| 53 | 53 | ||
| 54 | /* Insmod parameters */ | ||
| 55 | I2C_CLIENT_INSMOD_1(asb100); | ||
| 56 | |||
| 57 | static unsigned short force_subclients[4]; | 54 | static unsigned short force_subclients[4]; |
| 58 | module_param_array(force_subclients, short, NULL, 0); | 55 | module_param_array(force_subclients, short, NULL, 0); |
| 59 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " | 56 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " |
| @@ -209,14 +206,14 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); | |||
| 209 | 206 | ||
| 210 | static int asb100_probe(struct i2c_client *client, | 207 | static int asb100_probe(struct i2c_client *client, |
| 211 | const struct i2c_device_id *id); | 208 | const struct i2c_device_id *id); |
| 212 | static int asb100_detect(struct i2c_client *client, int kind, | 209 | static int asb100_detect(struct i2c_client *client, |
| 213 | struct i2c_board_info *info); | 210 | struct i2c_board_info *info); |
| 214 | static int asb100_remove(struct i2c_client *client); | 211 | static int asb100_remove(struct i2c_client *client); |
| 215 | static struct asb100_data *asb100_update_device(struct device *dev); | 212 | static struct asb100_data *asb100_update_device(struct device *dev); |
| 216 | static void asb100_init_client(struct i2c_client *client); | 213 | static void asb100_init_client(struct i2c_client *client); |
| 217 | 214 | ||
| 218 | static const struct i2c_device_id asb100_id[] = { | 215 | static const struct i2c_device_id asb100_id[] = { |
| 219 | { "asb100", asb100 }, | 216 | { "asb100", 0 }, |
| 220 | { } | 217 | { } |
| 221 | }; | 218 | }; |
| 222 | MODULE_DEVICE_TABLE(i2c, asb100_id); | 219 | MODULE_DEVICE_TABLE(i2c, asb100_id); |
| @@ -230,7 +227,7 @@ static struct i2c_driver asb100_driver = { | |||
| 230 | .remove = asb100_remove, | 227 | .remove = asb100_remove, |
| 231 | .id_table = asb100_id, | 228 | .id_table = asb100_id, |
| 232 | .detect = asb100_detect, | 229 | .detect = asb100_detect, |
| 233 | .address_data = &addr_data, | 230 | .address_list = normal_i2c, |
| 234 | }; | 231 | }; |
| 235 | 232 | ||
| 236 | /* 7 Voltages */ | 233 | /* 7 Voltages */ |
| @@ -697,7 +694,7 @@ ERROR_SC_2: | |||
| 697 | } | 694 | } |
| 698 | 695 | ||
| 699 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 696 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 700 | static int asb100_detect(struct i2c_client *client, int kind, | 697 | static int asb100_detect(struct i2c_client *client, |
| 701 | struct i2c_board_info *info) | 698 | struct i2c_board_info *info) |
| 702 | { | 699 | { |
| 703 | struct i2c_adapter *adapter = client->adapter; | 700 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index d6b490d3e36f..94cadc19f0c5 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c | |||
| @@ -44,17 +44,14 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>"); | |||
| 44 | 44 | ||
| 45 | static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; | 45 | static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; |
| 46 | 46 | ||
| 47 | I2C_CLIENT_INSMOD_1(atxp1); | ||
| 48 | |||
| 49 | static int atxp1_probe(struct i2c_client *client, | 47 | static int atxp1_probe(struct i2c_client *client, |
| 50 | const struct i2c_device_id *id); | 48 | const struct i2c_device_id *id); |
| 51 | static int atxp1_remove(struct i2c_client *client); | 49 | static int atxp1_remove(struct i2c_client *client); |
| 52 | static struct atxp1_data * atxp1_update_device(struct device *dev); | 50 | static struct atxp1_data * atxp1_update_device(struct device *dev); |
| 53 | static int atxp1_detect(struct i2c_client *client, int kind, | 51 | static int atxp1_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 54 | struct i2c_board_info *info); | ||
| 55 | 52 | ||
| 56 | static const struct i2c_device_id atxp1_id[] = { | 53 | static const struct i2c_device_id atxp1_id[] = { |
| 57 | { "atxp1", atxp1 }, | 54 | { "atxp1", 0 }, |
| 58 | { } | 55 | { } |
| 59 | }; | 56 | }; |
| 60 | MODULE_DEVICE_TABLE(i2c, atxp1_id); | 57 | MODULE_DEVICE_TABLE(i2c, atxp1_id); |
| @@ -68,7 +65,7 @@ static struct i2c_driver atxp1_driver = { | |||
| 68 | .remove = atxp1_remove, | 65 | .remove = atxp1_remove, |
| 69 | .id_table = atxp1_id, | 66 | .id_table = atxp1_id, |
| 70 | .detect = atxp1_detect, | 67 | .detect = atxp1_detect, |
| 71 | .address_data = &addr_data, | 68 | .address_list = normal_i2c, |
| 72 | }; | 69 | }; |
| 73 | 70 | ||
| 74 | struct atxp1_data { | 71 | struct atxp1_data { |
| @@ -275,7 +272,7 @@ static const struct attribute_group atxp1_group = { | |||
| 275 | 272 | ||
| 276 | 273 | ||
| 277 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 274 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 278 | static int atxp1_detect(struct i2c_client *new_client, int kind, | 275 | static int atxp1_detect(struct i2c_client *new_client, |
| 279 | struct i2c_board_info *info) | 276 | struct i2c_board_info *info) |
| 280 | { | 277 | { |
| 281 | struct i2c_adapter *adapter = new_client->adapter; | 278 | struct i2c_adapter *adapter = new_client->adapter; |
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 4377bb0cc526..823dd28a902c 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c | |||
| @@ -57,11 +57,7 @@ MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC " | |||
| 57 | /* Addresses to scan */ | 57 | /* Addresses to scan */ |
| 58 | static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; | 58 | static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; |
| 59 | 59 | ||
| 60 | /* Insmod parameters */ | 60 | enum chips { dme1737, sch5027, sch311x }; |
| 61 | I2C_CLIENT_INSMOD_2(dme1737, sch5027); | ||
| 62 | |||
| 63 | /* ISA chip types */ | ||
| 64 | enum isa_chips { sch311x = sch5027 + 1 }; | ||
| 65 | 61 | ||
| 66 | /* --------------------------------------------------------------------- | 62 | /* --------------------------------------------------------------------- |
| 67 | * Registers | 63 | * Registers |
| @@ -2208,7 +2204,7 @@ exit: | |||
| 2208 | } | 2204 | } |
| 2209 | 2205 | ||
| 2210 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 2206 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 2211 | static int dme1737_i2c_detect(struct i2c_client *client, int kind, | 2207 | static int dme1737_i2c_detect(struct i2c_client *client, |
| 2212 | struct i2c_board_info *info) | 2208 | struct i2c_board_info *info) |
| 2213 | { | 2209 | { |
| 2214 | struct i2c_adapter *adapter = client->adapter; | 2210 | struct i2c_adapter *adapter = client->adapter; |
| @@ -2318,7 +2314,7 @@ static struct i2c_driver dme1737_i2c_driver = { | |||
| 2318 | .remove = dme1737_i2c_remove, | 2314 | .remove = dme1737_i2c_remove, |
| 2319 | .id_table = dme1737_id, | 2315 | .id_table = dme1737_id, |
| 2320 | .detect = dme1737_i2c_detect, | 2316 | .detect = dme1737_i2c_detect, |
| 2321 | .address_data = &addr_data, | 2317 | .address_list = normal_i2c, |
| 2322 | }; | 2318 | }; |
| 2323 | 2319 | ||
| 2324 | /* --------------------------------------------------------------------- | 2320 | /* --------------------------------------------------------------------- |
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 2a4c6a05b14f..e11363467a8d 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c | |||
| @@ -38,7 +38,6 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, | |||
| 38 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; | 38 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; |
| 39 | 39 | ||
| 40 | /* Insmod parameters */ | 40 | /* Insmod parameters */ |
| 41 | I2C_CLIENT_INSMOD_1(ds1621); | ||
| 42 | static int polarity = -1; | 41 | static int polarity = -1; |
| 43 | module_param(polarity, int, 0); | 42 | module_param(polarity, int, 0); |
| 44 | MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); | 43 | MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); |
| @@ -224,7 +223,7 @@ static const struct attribute_group ds1621_group = { | |||
| 224 | 223 | ||
| 225 | 224 | ||
| 226 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 225 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 227 | static int ds1621_detect(struct i2c_client *client, int kind, | 226 | static int ds1621_detect(struct i2c_client *client, |
| 228 | struct i2c_board_info *info) | 227 | struct i2c_board_info *info) |
| 229 | { | 228 | { |
| 230 | struct i2c_adapter *adapter = client->adapter; | 229 | struct i2c_adapter *adapter = client->adapter; |
| @@ -305,8 +304,8 @@ static int ds1621_remove(struct i2c_client *client) | |||
| 305 | } | 304 | } |
| 306 | 305 | ||
| 307 | static const struct i2c_device_id ds1621_id[] = { | 306 | static const struct i2c_device_id ds1621_id[] = { |
| 308 | { "ds1621", ds1621 }, | 307 | { "ds1621", 0 }, |
| 309 | { "ds1625", ds1621 }, | 308 | { "ds1625", 0 }, |
| 310 | { } | 309 | { } |
| 311 | }; | 310 | }; |
| 312 | MODULE_DEVICE_TABLE(i2c, ds1621_id); | 311 | MODULE_DEVICE_TABLE(i2c, ds1621_id); |
| @@ -321,7 +320,7 @@ static struct i2c_driver ds1621_driver = { | |||
| 321 | .remove = ds1621_remove, | 320 | .remove = ds1621_remove, |
| 322 | .id_table = ds1621_id, | 321 | .id_table = ds1621_id, |
| 323 | .detect = ds1621_detect, | 322 | .detect = ds1621_detect, |
| 324 | .address_data = &addr_data, | 323 | .address_list = normal_i2c, |
| 325 | }; | 324 | }; |
| 326 | 325 | ||
| 327 | static int __init ds1621_init(void) | 326 | static int __init ds1621_init(void) |
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 40dfbcd3f3f2..277398f9c938 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c | |||
| @@ -39,8 +39,7 @@ | |||
| 39 | /* Addresses to scan */ | 39 | /* Addresses to scan */ |
| 40 | static const unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END }; | 40 | static const unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END }; |
| 41 | 41 | ||
| 42 | /* Insmod parameters */ | 42 | enum chips { f75373, f75375 }; |
| 43 | I2C_CLIENT_INSMOD_2(f75373, f75375); | ||
| 44 | 43 | ||
| 45 | /* Fintek F75375 registers */ | 44 | /* Fintek F75375 registers */ |
| 46 | #define F75375_REG_CONFIG0 0x0 | 45 | #define F75375_REG_CONFIG0 0x0 |
| @@ -113,7 +112,7 @@ struct f75375_data { | |||
| 113 | s8 temp_max_hyst[2]; | 112 | s8 temp_max_hyst[2]; |
| 114 | }; | 113 | }; |
| 115 | 114 | ||
| 116 | static int f75375_detect(struct i2c_client *client, int kind, | 115 | static int f75375_detect(struct i2c_client *client, |
| 117 | struct i2c_board_info *info); | 116 | struct i2c_board_info *info); |
| 118 | static int f75375_probe(struct i2c_client *client, | 117 | static int f75375_probe(struct i2c_client *client, |
| 119 | const struct i2c_device_id *id); | 118 | const struct i2c_device_id *id); |
| @@ -135,7 +134,7 @@ static struct i2c_driver f75375_driver = { | |||
| 135 | .remove = f75375_remove, | 134 | .remove = f75375_remove, |
| 136 | .id_table = f75375_id, | 135 | .id_table = f75375_id, |
| 137 | .detect = f75375_detect, | 136 | .detect = f75375_detect, |
| 138 | .address_data = &addr_data, | 137 | .address_list = normal_i2c, |
| 139 | }; | 138 | }; |
| 140 | 139 | ||
| 141 | static inline int f75375_read8(struct i2c_client *client, u8 reg) | 140 | static inline int f75375_read8(struct i2c_client *client, u8 reg) |
| @@ -677,7 +676,7 @@ static int f75375_remove(struct i2c_client *client) | |||
| 677 | } | 676 | } |
| 678 | 677 | ||
| 679 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 678 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 680 | static int f75375_detect(struct i2c_client *client, int kind, | 679 | static int f75375_detect(struct i2c_client *client, |
| 681 | struct i2c_board_info *info) | 680 | struct i2c_board_info *info) |
| 682 | { | 681 | { |
| 683 | struct i2c_adapter *adapter = client->adapter; | 682 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index 281829cd1533..bd0fc67e804b 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c | |||
| @@ -56,7 +56,8 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
| 56 | module_param(nowayout, int, 0); | 56 | module_param(nowayout, int, 0); |
| 57 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | 57 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
| 58 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 58 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
| 59 | I2C_CLIENT_INSMOD_7(fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl); | 59 | |
| 60 | enum chips { fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl }; | ||
| 60 | 61 | ||
| 61 | /* | 62 | /* |
| 62 | * The FSCHMD registers and other defines | 63 | * The FSCHMD registers and other defines |
| @@ -221,7 +222,7 @@ static const int FSCHMD_NO_TEMP_SENSORS[7] = { 3, 3, 4, 3, 5, 5, 11 }; | |||
| 221 | 222 | ||
| 222 | static int fschmd_probe(struct i2c_client *client, | 223 | static int fschmd_probe(struct i2c_client *client, |
| 223 | const struct i2c_device_id *id); | 224 | const struct i2c_device_id *id); |
| 224 | static int fschmd_detect(struct i2c_client *client, int kind, | 225 | static int fschmd_detect(struct i2c_client *client, |
| 225 | struct i2c_board_info *info); | 226 | struct i2c_board_info *info); |
| 226 | static int fschmd_remove(struct i2c_client *client); | 227 | static int fschmd_remove(struct i2c_client *client); |
| 227 | static struct fschmd_data *fschmd_update_device(struct device *dev); | 228 | static struct fschmd_data *fschmd_update_device(struct device *dev); |
| @@ -251,7 +252,7 @@ static struct i2c_driver fschmd_driver = { | |||
| 251 | .remove = fschmd_remove, | 252 | .remove = fschmd_remove, |
| 252 | .id_table = fschmd_id, | 253 | .id_table = fschmd_id, |
| 253 | .detect = fschmd_detect, | 254 | .detect = fschmd_detect, |
| 254 | .address_data = &addr_data, | 255 | .address_list = normal_i2c, |
| 255 | }; | 256 | }; |
| 256 | 257 | ||
| 257 | /* | 258 | /* |
| @@ -1000,7 +1001,7 @@ static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy) | |||
| 1000 | } | 1001 | } |
| 1001 | } | 1002 | } |
| 1002 | 1003 | ||
| 1003 | static int fschmd_detect(struct i2c_client *client, int _kind, | 1004 | static int fschmd_detect(struct i2c_client *client, |
| 1004 | struct i2c_board_info *info) | 1005 | struct i2c_board_info *info) |
| 1005 | { | 1006 | { |
| 1006 | enum chips kind; | 1007 | enum chips kind; |
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 1d69458aa0b6..e7ae5743e181 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c | |||
| @@ -46,8 +46,7 @@ | |||
| 46 | /* Addresses to scan */ | 46 | /* Addresses to scan */ |
| 47 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; | 47 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; |
| 48 | 48 | ||
| 49 | /* Insmod parameters */ | 49 | enum chips { gl518sm_r00, gl518sm_r80 }; |
| 50 | I2C_CLIENT_INSMOD_2(gl518sm_r00, gl518sm_r80); | ||
| 51 | 50 | ||
| 52 | /* Many GL518 constants specified below */ | 51 | /* Many GL518 constants specified below */ |
| 53 | 52 | ||
| @@ -139,8 +138,7 @@ struct gl518_data { | |||
| 139 | 138 | ||
| 140 | static int gl518_probe(struct i2c_client *client, | 139 | static int gl518_probe(struct i2c_client *client, |
| 141 | const struct i2c_device_id *id); | 140 | const struct i2c_device_id *id); |
| 142 | static int gl518_detect(struct i2c_client *client, int kind, | 141 | static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 143 | struct i2c_board_info *info); | ||
| 144 | static void gl518_init_client(struct i2c_client *client); | 142 | static void gl518_init_client(struct i2c_client *client); |
| 145 | static int gl518_remove(struct i2c_client *client); | 143 | static int gl518_remove(struct i2c_client *client); |
| 146 | static int gl518_read_value(struct i2c_client *client, u8 reg); | 144 | static int gl518_read_value(struct i2c_client *client, u8 reg); |
| @@ -163,7 +161,7 @@ static struct i2c_driver gl518_driver = { | |||
| 163 | .remove = gl518_remove, | 161 | .remove = gl518_remove, |
| 164 | .id_table = gl518_id, | 162 | .id_table = gl518_id, |
| 165 | .detect = gl518_detect, | 163 | .detect = gl518_detect, |
| 166 | .address_data = &addr_data, | 164 | .address_list = normal_i2c, |
| 167 | }; | 165 | }; |
| 168 | 166 | ||
| 169 | /* | 167 | /* |
| @@ -484,8 +482,7 @@ static const struct attribute_group gl518_group_r80 = { | |||
| 484 | */ | 482 | */ |
| 485 | 483 | ||
| 486 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 484 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 487 | static int gl518_detect(struct i2c_client *client, int kind, | 485 | static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 488 | struct i2c_board_info *info) | ||
| 489 | { | 486 | { |
| 490 | struct i2c_adapter *adapter = client->adapter; | 487 | struct i2c_adapter *adapter = client->adapter; |
| 491 | int rev; | 488 | int rev; |
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 92b5720ceaff..ec588026f0a9 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c | |||
| @@ -41,9 +41,6 @@ MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=tempe | |||
| 41 | /* Addresses to scan */ | 41 | /* Addresses to scan */ |
| 42 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; | 42 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; |
| 43 | 43 | ||
| 44 | /* Insmod parameters */ | ||
| 45 | I2C_CLIENT_INSMOD_1(gl520sm); | ||
| 46 | |||
| 47 | /* Many GL520 constants specified below | 44 | /* Many GL520 constants specified below |
| 48 | One of the inputs can be configured as either temp or voltage. | 45 | One of the inputs can be configured as either temp or voltage. |
| 49 | That's why _TEMP2 and _IN4 access the same register | 46 | That's why _TEMP2 and _IN4 access the same register |
| @@ -81,8 +78,7 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; | |||
| 81 | 78 | ||
| 82 | static int gl520_probe(struct i2c_client *client, | 79 | static int gl520_probe(struct i2c_client *client, |
| 83 | const struct i2c_device_id *id); | 80 | const struct i2c_device_id *id); |
| 84 | static int gl520_detect(struct i2c_client *client, int kind, | 81 | static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 85 | struct i2c_board_info *info); | ||
| 86 | static void gl520_init_client(struct i2c_client *client); | 82 | static void gl520_init_client(struct i2c_client *client); |
| 87 | static int gl520_remove(struct i2c_client *client); | 83 | static int gl520_remove(struct i2c_client *client); |
| 88 | static int gl520_read_value(struct i2c_client *client, u8 reg); | 84 | static int gl520_read_value(struct i2c_client *client, u8 reg); |
| @@ -91,7 +87,7 @@ static struct gl520_data *gl520_update_device(struct device *dev); | |||
| 91 | 87 | ||
| 92 | /* Driver data */ | 88 | /* Driver data */ |
| 93 | static const struct i2c_device_id gl520_id[] = { | 89 | static const struct i2c_device_id gl520_id[] = { |
| 94 | { "gl520sm", gl520sm }, | 90 | { "gl520sm", 0 }, |
| 95 | { } | 91 | { } |
| 96 | }; | 92 | }; |
| 97 | MODULE_DEVICE_TABLE(i2c, gl520_id); | 93 | MODULE_DEVICE_TABLE(i2c, gl520_id); |
| @@ -105,7 +101,7 @@ static struct i2c_driver gl520_driver = { | |||
| 105 | .remove = gl520_remove, | 101 | .remove = gl520_remove, |
| 106 | .id_table = gl520_id, | 102 | .id_table = gl520_id, |
| 107 | .detect = gl520_detect, | 103 | .detect = gl520_detect, |
| 108 | .address_data = &addr_data, | 104 | .address_list = normal_i2c, |
| 109 | }; | 105 | }; |
| 110 | 106 | ||
| 111 | /* Client data */ | 107 | /* Client data */ |
| @@ -681,8 +677,7 @@ static const struct attribute_group gl520_group_opt = { | |||
| 681 | */ | 677 | */ |
| 682 | 678 | ||
| 683 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 679 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 684 | static int gl520_detect(struct i2c_client *client, int kind, | 680 | static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 685 | struct i2c_board_info *info) | ||
| 686 | { | 681 | { |
| 687 | struct i2c_adapter *adapter = client->adapter; | 682 | struct i2c_adapter *adapter = client->adapter; |
| 688 | 683 | ||
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index cf5afb9a10ab..b2f2277cad3c 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c | |||
| @@ -43,13 +43,30 @@ | |||
| 43 | #define MDPS_POLL_INTERVAL 50 | 43 | #define MDPS_POLL_INTERVAL 50 |
| 44 | /* | 44 | /* |
| 45 | * The sensor can also generate interrupts (DRDY) but it's pretty pointless | 45 | * The sensor can also generate interrupts (DRDY) but it's pretty pointless |
| 46 | * because their are generated even if the data do not change. So it's better | 46 | * because they are generated even if the data do not change. So it's better |
| 47 | * to keep the interrupt for the free-fall event. The values are updated at | 47 | * to keep the interrupt for the free-fall event. The values are updated at |
| 48 | * 40Hz (at the lowest frequency), but as it can be pretty time consuming on | 48 | * 40Hz (at the lowest frequency), but as it can be pretty time consuming on |
| 49 | * some low processor, we poll the sensor only at 20Hz... enough for the | 49 | * some low processor, we poll the sensor only at 20Hz... enough for the |
| 50 | * joystick. | 50 | * joystick. |
| 51 | */ | 51 | */ |
| 52 | 52 | ||
| 53 | #define LIS3_PWRON_DELAY_WAI_12B (5000) | ||
| 54 | #define LIS3_PWRON_DELAY_WAI_8B (3000) | ||
| 55 | |||
| 56 | /* | ||
| 57 | * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG | ||
| 58 | * LIS302D spec says: 18 mG / digit | ||
| 59 | * LIS3_ACCURACY is used to increase accuracy of the intermediate | ||
| 60 | * calculation results. | ||
| 61 | */ | ||
| 62 | #define LIS3_ACCURACY 1024 | ||
| 63 | /* Sensitivity values for -2G +2G scale */ | ||
| 64 | #define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024) | ||
| 65 | #define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY) | ||
| 66 | |||
| 67 | #define LIS3_DEFAULT_FUZZ 3 | ||
| 68 | #define LIS3_DEFAULT_FLAT 3 | ||
| 69 | |||
| 53 | struct lis3lv02d lis3_dev = { | 70 | struct lis3lv02d lis3_dev = { |
| 54 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait), | 71 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait), |
| 55 | }; | 72 | }; |
| @@ -65,7 +82,7 @@ static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg) | |||
| 65 | return lo; | 82 | return lo; |
| 66 | } | 83 | } |
| 67 | 84 | ||
| 68 | static s16 lis3lv02d_read_16(struct lis3lv02d *lis3, int reg) | 85 | static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg) |
| 69 | { | 86 | { |
| 70 | u8 lo, hi; | 87 | u8 lo, hi; |
| 71 | 88 | ||
| @@ -102,16 +119,106 @@ static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3]) | |||
| 102 | static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) | 119 | static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) |
| 103 | { | 120 | { |
| 104 | int position[3]; | 121 | int position[3]; |
| 122 | int i; | ||
| 105 | 123 | ||
| 124 | mutex_lock(&lis3->mutex); | ||
| 106 | position[0] = lis3->read_data(lis3, OUTX); | 125 | position[0] = lis3->read_data(lis3, OUTX); |
| 107 | position[1] = lis3->read_data(lis3, OUTY); | 126 | position[1] = lis3->read_data(lis3, OUTY); |
| 108 | position[2] = lis3->read_data(lis3, OUTZ); | 127 | position[2] = lis3->read_data(lis3, OUTZ); |
| 128 | mutex_unlock(&lis3->mutex); | ||
| 129 | |||
| 130 | for (i = 0; i < 3; i++) | ||
| 131 | position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY; | ||
| 109 | 132 | ||
| 110 | *x = lis3lv02d_get_axis(lis3->ac.x, position); | 133 | *x = lis3lv02d_get_axis(lis3->ac.x, position); |
| 111 | *y = lis3lv02d_get_axis(lis3->ac.y, position); | 134 | *y = lis3lv02d_get_axis(lis3->ac.y, position); |
| 112 | *z = lis3lv02d_get_axis(lis3->ac.z, position); | 135 | *z = lis3lv02d_get_axis(lis3->ac.z, position); |
| 113 | } | 136 | } |
| 114 | 137 | ||
| 138 | /* conversion btw sampling rate and the register values */ | ||
| 139 | static int lis3_12_rates[4] = {40, 160, 640, 2560}; | ||
| 140 | static int lis3_8_rates[2] = {100, 400}; | ||
| 141 | |||
| 142 | /* ODR is Output Data Rate */ | ||
| 143 | static int lis3lv02d_get_odr(void) | ||
| 144 | { | ||
| 145 | u8 ctrl; | ||
| 146 | int shift; | ||
| 147 | |||
| 148 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); | ||
| 149 | ctrl &= lis3_dev.odr_mask; | ||
| 150 | shift = ffs(lis3_dev.odr_mask) - 1; | ||
| 151 | return lis3_dev.odrs[(ctrl >> shift)]; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int lis3lv02d_set_odr(int rate) | ||
| 155 | { | ||
| 156 | u8 ctrl; | ||
| 157 | int i, len, shift; | ||
| 158 | |||
| 159 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); | ||
| 160 | ctrl &= ~lis3_dev.odr_mask; | ||
| 161 | len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */ | ||
| 162 | shift = ffs(lis3_dev.odr_mask) - 1; | ||
| 163 | |||
| 164 | for (i = 0; i < len; i++) | ||
| 165 | if (lis3_dev.odrs[i] == rate) { | ||
| 166 | lis3_dev.write(&lis3_dev, CTRL_REG1, | ||
| 167 | ctrl | (i << shift)); | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | return -EINVAL; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) | ||
| 174 | { | ||
| 175 | u8 reg; | ||
| 176 | s16 x, y, z; | ||
| 177 | u8 selftest; | ||
| 178 | int ret; | ||
| 179 | |||
| 180 | mutex_lock(&lis3->mutex); | ||
| 181 | if (lis3_dev.whoami == WAI_12B) | ||
| 182 | selftest = CTRL1_ST; | ||
| 183 | else | ||
| 184 | selftest = CTRL1_STP; | ||
| 185 | |||
| 186 | lis3->read(lis3, CTRL_REG1, ®); | ||
| 187 | lis3->write(lis3, CTRL_REG1, (reg | selftest)); | ||
| 188 | msleep(lis3->pwron_delay / lis3lv02d_get_odr()); | ||
| 189 | |||
| 190 | /* Read directly to avoid axis remap */ | ||
| 191 | x = lis3->read_data(lis3, OUTX); | ||
| 192 | y = lis3->read_data(lis3, OUTY); | ||
| 193 | z = lis3->read_data(lis3, OUTZ); | ||
| 194 | |||
| 195 | /* back to normal settings */ | ||
| 196 | lis3->write(lis3, CTRL_REG1, reg); | ||
| 197 | msleep(lis3->pwron_delay / lis3lv02d_get_odr()); | ||
| 198 | |||
| 199 | results[0] = x - lis3->read_data(lis3, OUTX); | ||
| 200 | results[1] = y - lis3->read_data(lis3, OUTY); | ||
| 201 | results[2] = z - lis3->read_data(lis3, OUTZ); | ||
| 202 | |||
| 203 | ret = 0; | ||
| 204 | if (lis3->pdata) { | ||
| 205 | int i; | ||
| 206 | for (i = 0; i < 3; i++) { | ||
| 207 | /* Check against selftest acceptance limits */ | ||
| 208 | if ((results[i] < lis3->pdata->st_min_limits[i]) || | ||
| 209 | (results[i] > lis3->pdata->st_max_limits[i])) { | ||
| 210 | ret = -EIO; | ||
| 211 | goto fail; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | /* test passed */ | ||
| 217 | fail: | ||
| 218 | mutex_unlock(&lis3->mutex); | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 115 | void lis3lv02d_poweroff(struct lis3lv02d *lis3) | 222 | void lis3lv02d_poweroff(struct lis3lv02d *lis3) |
| 116 | { | 223 | { |
| 117 | /* disable X,Y,Z axis and power down */ | 224 | /* disable X,Y,Z axis and power down */ |
| @@ -125,14 +232,19 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3) | |||
| 125 | 232 | ||
| 126 | lis3->init(lis3); | 233 | lis3->init(lis3); |
| 127 | 234 | ||
| 235 | /* LIS3 power on delay is quite long */ | ||
| 236 | msleep(lis3->pwron_delay / lis3lv02d_get_odr()); | ||
| 237 | |||
| 128 | /* | 238 | /* |
| 129 | * Common configuration | 239 | * Common configuration |
| 130 | * BDU: LSB and MSB values are not updated until both have been read. | 240 | * BDU: (12 bits sensors only) LSB and MSB values are not updated until |
| 131 | * So the value read will always be correct. | 241 | * both have been read. So the value read will always be correct. |
| 132 | */ | 242 | */ |
| 133 | lis3->read(lis3, CTRL_REG2, ®); | 243 | if (lis3->whoami == WAI_12B) { |
| 134 | reg |= CTRL2_BDU; | 244 | lis3->read(lis3, CTRL_REG2, ®); |
| 135 | lis3->write(lis3, CTRL_REG2, reg); | 245 | reg |= CTRL2_BDU; |
| 246 | lis3->write(lis3, CTRL_REG2, reg); | ||
| 247 | } | ||
| 136 | } | 248 | } |
| 137 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | 249 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); |
| 138 | 250 | ||
| @@ -273,22 +385,17 @@ static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev) | |||
| 273 | int x, y, z; | 385 | int x, y, z; |
| 274 | 386 | ||
| 275 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); | 387 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
| 276 | input_report_abs(pidev->input, ABS_X, x - lis3_dev.xcalib); | 388 | input_report_abs(pidev->input, ABS_X, x); |
| 277 | input_report_abs(pidev->input, ABS_Y, y - lis3_dev.ycalib); | 389 | input_report_abs(pidev->input, ABS_Y, y); |
| 278 | input_report_abs(pidev->input, ABS_Z, z - lis3_dev.zcalib); | 390 | input_report_abs(pidev->input, ABS_Z, z); |
| 279 | } | 391 | input_sync(pidev->input); |
| 280 | |||
| 281 | |||
| 282 | static inline void lis3lv02d_calibrate_joystick(void) | ||
| 283 | { | ||
| 284 | lis3lv02d_get_xyz(&lis3_dev, | ||
| 285 | &lis3_dev.xcalib, &lis3_dev.ycalib, &lis3_dev.zcalib); | ||
| 286 | } | 392 | } |
| 287 | 393 | ||
| 288 | int lis3lv02d_joystick_enable(void) | 394 | int lis3lv02d_joystick_enable(void) |
| 289 | { | 395 | { |
| 290 | struct input_dev *input_dev; | 396 | struct input_dev *input_dev; |
| 291 | int err; | 397 | int err; |
| 398 | int max_val, fuzz, flat; | ||
| 292 | 399 | ||
| 293 | if (lis3_dev.idev) | 400 | if (lis3_dev.idev) |
| 294 | return -EINVAL; | 401 | return -EINVAL; |
| @@ -301,8 +408,6 @@ int lis3lv02d_joystick_enable(void) | |||
| 301 | lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL; | 408 | lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL; |
| 302 | input_dev = lis3_dev.idev->input; | 409 | input_dev = lis3_dev.idev->input; |
| 303 | 410 | ||
| 304 | lis3lv02d_calibrate_joystick(); | ||
| 305 | |||
| 306 | input_dev->name = "ST LIS3LV02DL Accelerometer"; | 411 | input_dev->name = "ST LIS3LV02DL Accelerometer"; |
| 307 | input_dev->phys = DRIVER_NAME "/input0"; | 412 | input_dev->phys = DRIVER_NAME "/input0"; |
| 308 | input_dev->id.bustype = BUS_HOST; | 413 | input_dev->id.bustype = BUS_HOST; |
| @@ -310,9 +415,12 @@ int lis3lv02d_joystick_enable(void) | |||
| 310 | input_dev->dev.parent = &lis3_dev.pdev->dev; | 415 | input_dev->dev.parent = &lis3_dev.pdev->dev; |
| 311 | 416 | ||
| 312 | set_bit(EV_ABS, input_dev->evbit); | 417 | set_bit(EV_ABS, input_dev->evbit); |
| 313 | input_set_abs_params(input_dev, ABS_X, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); | 418 | max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY; |
| 314 | input_set_abs_params(input_dev, ABS_Y, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); | 419 | fuzz = (LIS3_DEFAULT_FUZZ * lis3_dev.scale) / LIS3_ACCURACY; |
| 315 | input_set_abs_params(input_dev, ABS_Z, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); | 420 | flat = (LIS3_DEFAULT_FLAT * lis3_dev.scale) / LIS3_ACCURACY; |
| 421 | input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat); | ||
| 422 | input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat); | ||
| 423 | input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat); | ||
| 316 | 424 | ||
| 317 | err = input_register_polled_device(lis3_dev.idev); | 425 | err = input_register_polled_device(lis3_dev.idev); |
| 318 | if (err) { | 426 | if (err) { |
| @@ -332,11 +440,23 @@ void lis3lv02d_joystick_disable(void) | |||
| 332 | if (lis3_dev.irq) | 440 | if (lis3_dev.irq) |
| 333 | misc_deregister(&lis3lv02d_misc_device); | 441 | misc_deregister(&lis3lv02d_misc_device); |
| 334 | input_unregister_polled_device(lis3_dev.idev); | 442 | input_unregister_polled_device(lis3_dev.idev); |
| 443 | input_free_polled_device(lis3_dev.idev); | ||
| 335 | lis3_dev.idev = NULL; | 444 | lis3_dev.idev = NULL; |
| 336 | } | 445 | } |
| 337 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); | 446 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); |
| 338 | 447 | ||
| 339 | /* Sysfs stuff */ | 448 | /* Sysfs stuff */ |
| 449 | static ssize_t lis3lv02d_selftest_show(struct device *dev, | ||
| 450 | struct device_attribute *attr, char *buf) | ||
| 451 | { | ||
| 452 | int result; | ||
| 453 | s16 values[3]; | ||
| 454 | |||
| 455 | result = lis3lv02d_selftest(&lis3_dev, values); | ||
| 456 | return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL", | ||
| 457 | values[0], values[1], values[2]); | ||
| 458 | } | ||
| 459 | |||
| 340 | static ssize_t lis3lv02d_position_show(struct device *dev, | 460 | static ssize_t lis3lv02d_position_show(struct device *dev, |
| 341 | struct device_attribute *attr, char *buf) | 461 | struct device_attribute *attr, char *buf) |
| 342 | { | 462 | { |
| @@ -346,41 +466,35 @@ static ssize_t lis3lv02d_position_show(struct device *dev, | |||
| 346 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | 466 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); |
| 347 | } | 467 | } |
| 348 | 468 | ||
| 349 | static ssize_t lis3lv02d_calibrate_show(struct device *dev, | 469 | static ssize_t lis3lv02d_rate_show(struct device *dev, |
| 350 | struct device_attribute *attr, char *buf) | 470 | struct device_attribute *attr, char *buf) |
| 351 | { | 471 | { |
| 352 | return sprintf(buf, "(%d,%d,%d)\n", lis3_dev.xcalib, lis3_dev.ycalib, lis3_dev.zcalib); | 472 | return sprintf(buf, "%d\n", lis3lv02d_get_odr()); |
| 353 | } | 473 | } |
| 354 | 474 | ||
| 355 | static ssize_t lis3lv02d_calibrate_store(struct device *dev, | 475 | static ssize_t lis3lv02d_rate_set(struct device *dev, |
| 356 | struct device_attribute *attr, | 476 | struct device_attribute *attr, const char *buf, |
| 357 | const char *buf, size_t count) | 477 | size_t count) |
| 358 | { | 478 | { |
| 359 | lis3lv02d_calibrate_joystick(); | 479 | unsigned long rate; |
| 360 | return count; | ||
| 361 | } | ||
| 362 | 480 | ||
| 363 | /* conversion btw sampling rate and the register values */ | 481 | if (strict_strtoul(buf, 0, &rate)) |
| 364 | static int lis3lv02dl_df_val[4] = {40, 160, 640, 2560}; | 482 | return -EINVAL; |
| 365 | static ssize_t lis3lv02d_rate_show(struct device *dev, | ||
| 366 | struct device_attribute *attr, char *buf) | ||
| 367 | { | ||
| 368 | u8 ctrl; | ||
| 369 | int val; | ||
| 370 | 483 | ||
| 371 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); | 484 | if (lis3lv02d_set_odr(rate)) |
| 372 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; | 485 | return -EINVAL; |
| 373 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); | 486 | |
| 487 | return count; | ||
| 374 | } | 488 | } |
| 375 | 489 | ||
| 490 | static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL); | ||
| 376 | static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL); | 491 | static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL); |
| 377 | static DEVICE_ATTR(calibrate, S_IRUGO|S_IWUSR, lis3lv02d_calibrate_show, | 492 | static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show, |
| 378 | lis3lv02d_calibrate_store); | 493 | lis3lv02d_rate_set); |
| 379 | static DEVICE_ATTR(rate, S_IRUGO, lis3lv02d_rate_show, NULL); | ||
| 380 | 494 | ||
| 381 | static struct attribute *lis3lv02d_attributes[] = { | 495 | static struct attribute *lis3lv02d_attributes[] = { |
| 496 | &dev_attr_selftest.attr, | ||
| 382 | &dev_attr_position.attr, | 497 | &dev_attr_position.attr, |
| 383 | &dev_attr_calibrate.attr, | ||
| 384 | &dev_attr_rate.attr, | 498 | &dev_attr_rate.attr, |
| 385 | NULL | 499 | NULL |
| 386 | }; | 500 | }; |
| @@ -409,22 +523,30 @@ EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); | |||
| 409 | 523 | ||
| 410 | /* | 524 | /* |
| 411 | * Initialise the accelerometer and the various subsystems. | 525 | * Initialise the accelerometer and the various subsystems. |
| 412 | * Should be rather independant of the bus system. | 526 | * Should be rather independent of the bus system. |
| 413 | */ | 527 | */ |
| 414 | int lis3lv02d_init_device(struct lis3lv02d *dev) | 528 | int lis3lv02d_init_device(struct lis3lv02d *dev) |
| 415 | { | 529 | { |
| 416 | dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I); | 530 | dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I); |
| 417 | 531 | ||
| 418 | switch (dev->whoami) { | 532 | switch (dev->whoami) { |
| 419 | case LIS_DOUBLE_ID: | 533 | case WAI_12B: |
| 420 | printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); | 534 | printk(KERN_INFO DRIVER_NAME ": 12 bits sensor found\n"); |
| 421 | dev->read_data = lis3lv02d_read_16; | 535 | dev->read_data = lis3lv02d_read_12; |
| 422 | dev->mdps_max_val = 2048; | 536 | dev->mdps_max_val = 2048; |
| 537 | dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B; | ||
| 538 | dev->odrs = lis3_12_rates; | ||
| 539 | dev->odr_mask = CTRL1_DF0 | CTRL1_DF1; | ||
| 540 | dev->scale = LIS3_SENSITIVITY_12B; | ||
| 423 | break; | 541 | break; |
| 424 | case LIS_SINGLE_ID: | 542 | case WAI_8B: |
| 425 | printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); | 543 | printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n"); |
| 426 | dev->read_data = lis3lv02d_read_8; | 544 | dev->read_data = lis3lv02d_read_8; |
| 427 | dev->mdps_max_val = 128; | 545 | dev->mdps_max_val = 128; |
| 546 | dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; | ||
| 547 | dev->odrs = lis3_8_rates; | ||
| 548 | dev->odr_mask = CTRL1_DR; | ||
| 549 | dev->scale = LIS3_SENSITIVITY_8B; | ||
| 428 | break; | 550 | break; |
| 429 | default: | 551 | default: |
| 430 | printk(KERN_ERR DRIVER_NAME | 552 | printk(KERN_ERR DRIVER_NAME |
| @@ -432,6 +554,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) | |||
| 432 | return -EINVAL; | 554 | return -EINVAL; |
| 433 | } | 555 | } |
| 434 | 556 | ||
| 557 | mutex_init(&dev->mutex); | ||
| 558 | |||
| 435 | lis3lv02d_add_fs(dev); | 559 | lis3lv02d_add_fs(dev); |
| 436 | lis3lv02d_poweron(dev); | 560 | lis3lv02d_poweron(dev); |
| 437 | 561 | ||
| @@ -443,7 +567,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) | |||
| 443 | if (dev->pdata) { | 567 | if (dev->pdata) { |
| 444 | struct lis3lv02d_platform_data *p = dev->pdata; | 568 | struct lis3lv02d_platform_data *p = dev->pdata; |
| 445 | 569 | ||
| 446 | if (p->click_flags && (dev->whoami == LIS_SINGLE_ID)) { | 570 | if (p->click_flags && (dev->whoami == WAI_8B)) { |
| 447 | dev->write(dev, CLICK_CFG, p->click_flags); | 571 | dev->write(dev, CLICK_CFG, p->click_flags); |
| 448 | dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit); | 572 | dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit); |
| 449 | dev->write(dev, CLICK_LATENCY, p->click_latency); | 573 | dev->write(dev, CLICK_LATENCY, p->click_latency); |
| @@ -454,7 +578,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) | |||
| 454 | (p->click_thresh_y << 4)); | 578 | (p->click_thresh_y << 4)); |
| 455 | } | 579 | } |
| 456 | 580 | ||
| 457 | if (p->wakeup_flags && (dev->whoami == LIS_SINGLE_ID)) { | 581 | if (p->wakeup_flags && (dev->whoami == WAI_8B)) { |
| 458 | dev->write(dev, FF_WU_CFG_1, p->wakeup_flags); | 582 | dev->write(dev, FF_WU_CFG_1, p->wakeup_flags); |
| 459 | dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f); | 583 | dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f); |
| 460 | /* default to 2.5ms for now */ | 584 | /* default to 2.5ms for now */ |
| @@ -484,4 +608,3 @@ EXPORT_SYMBOL_GPL(lis3lv02d_init_device); | |||
| 484 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); | 608 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); |
| 485 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); | 609 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); |
| 486 | MODULE_LICENSE("GPL"); | 610 | MODULE_LICENSE("GPL"); |
| 487 | |||
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h index 3e1ff46f72d3..e6a01f44709b 100644 --- a/drivers/hwmon/lis3lv02d.h +++ b/drivers/hwmon/lis3lv02d.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * lis3lv02d.h - ST LIS3LV02DL accelerometer driver | 2 | * lis3lv02d.h - ST LIS3LV02DL accelerometer driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007-2008 Yan Burman | 4 | * Copyright (C) 2007-2008 Yan Burman |
| 5 | * Copyright (C) 2008 Eric Piel | 5 | * Copyright (C) 2008-2009 Eric Piel |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of the GNU General Public License as published by |
| @@ -22,20 +22,18 @@ | |||
| 22 | #include <linux/input-polldev.h> | 22 | #include <linux/input-polldev.h> |
| 23 | 23 | ||
| 24 | /* | 24 | /* |
| 25 | * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to | 25 | * This driver tries to support the "digital" accelerometer chips from |
| 26 | * be connected via SPI. There exists also several similar chips (such as LIS302DL or | 26 | * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL, |
| 27 | * LIS3L02DQ) and they have slightly different registers, but we can provide a | 27 | * LIS35DE, or LIS202DL. They are very similar in terms of programming, with |
| 28 | * common interface for all of them. | 28 | * almost the same registers. In addition to differing on physical properties, |
| 29 | * They can also be connected via I²C. | 29 | * they differ on the number of axes (2/3), precision (8/12 bits), and special |
| 30 | * features (freefall detection, click...). Unfortunately, not all the | ||
| 31 | * differences can be probed via a register. | ||
| 32 | * They can be connected either via I²C or SPI. | ||
| 30 | */ | 33 | */ |
| 31 | 34 | ||
| 32 | #include <linux/lis3lv02d.h> | 35 | #include <linux/lis3lv02d.h> |
| 33 | 36 | ||
| 34 | /* 2-byte registers */ | ||
| 35 | #define LIS_DOUBLE_ID 0x3A /* LIS3LV02D[LQ] */ | ||
| 36 | /* 1-byte registers */ | ||
| 37 | #define LIS_SINGLE_ID 0x3B /* LIS[32]02DL and others */ | ||
| 38 | |||
| 39 | enum lis3_reg { | 37 | enum lis3_reg { |
| 40 | WHO_AM_I = 0x0F, | 38 | WHO_AM_I = 0x0F, |
| 41 | OFFSET_X = 0x16, | 39 | OFFSET_X = 0x16, |
| @@ -94,7 +92,13 @@ enum lis3lv02d_reg { | |||
| 94 | DD_THSE_H = 0x3F, | 92 | DD_THSE_H = 0x3F, |
| 95 | }; | 93 | }; |
| 96 | 94 | ||
| 97 | enum lis3lv02d_ctrl1 { | 95 | enum lis3_who_am_i { |
| 96 | WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ | ||
| 97 | WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ | ||
| 98 | WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ | ||
| 99 | }; | ||
| 100 | |||
| 101 | enum lis3lv02d_ctrl1_12b { | ||
| 98 | CTRL1_Xen = 0x01, | 102 | CTRL1_Xen = 0x01, |
| 99 | CTRL1_Yen = 0x02, | 103 | CTRL1_Yen = 0x02, |
| 100 | CTRL1_Zen = 0x04, | 104 | CTRL1_Zen = 0x04, |
| @@ -104,6 +108,16 @@ enum lis3lv02d_ctrl1 { | |||
| 104 | CTRL1_PD0 = 0x40, | 108 | CTRL1_PD0 = 0x40, |
| 105 | CTRL1_PD1 = 0x80, | 109 | CTRL1_PD1 = 0x80, |
| 106 | }; | 110 | }; |
| 111 | |||
| 112 | /* Delta to ctrl1_12b version */ | ||
| 113 | enum lis3lv02d_ctrl1_8b { | ||
| 114 | CTRL1_STM = 0x08, | ||
| 115 | CTRL1_STP = 0x10, | ||
| 116 | CTRL1_FS = 0x20, | ||
| 117 | CTRL1_PD = 0x40, | ||
| 118 | CTRL1_DR = 0x80, | ||
| 119 | }; | ||
| 120 | |||
| 107 | enum lis3lv02d_ctrl2 { | 121 | enum lis3lv02d_ctrl2 { |
| 108 | CTRL2_DAS = 0x01, | 122 | CTRL2_DAS = 0x01, |
| 109 | CTRL2_SIM = 0x02, | 123 | CTRL2_SIM = 0x02, |
| @@ -194,16 +208,20 @@ struct lis3lv02d { | |||
| 194 | int (*write) (struct lis3lv02d *lis3, int reg, u8 val); | 208 | int (*write) (struct lis3lv02d *lis3, int reg, u8 val); |
| 195 | int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret); | 209 | int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret); |
| 196 | 210 | ||
| 197 | u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */ | 211 | int *odrs; /* Supported output data rates */ |
| 212 | u8 odr_mask; /* ODR bit mask */ | ||
| 213 | u8 whoami; /* indicates measurement precision */ | ||
| 198 | s16 (*read_data) (struct lis3lv02d *lis3, int reg); | 214 | s16 (*read_data) (struct lis3lv02d *lis3, int reg); |
| 199 | int mdps_max_val; | 215 | int mdps_max_val; |
| 216 | int pwron_delay; | ||
| 217 | int scale; /* | ||
| 218 | * relationship between 1 LBS and mG | ||
| 219 | * (1/1000th of earth gravity) | ||
| 220 | */ | ||
| 200 | 221 | ||
| 201 | struct input_polled_dev *idev; /* input device */ | 222 | struct input_polled_dev *idev; /* input device */ |
| 202 | struct platform_device *pdev; /* platform device */ | 223 | struct platform_device *pdev; /* platform device */ |
| 203 | atomic_t count; /* interrupt count after last read */ | 224 | atomic_t count; /* interrupt count after last read */ |
| 204 | int xcalib; /* calibrated null value for x */ | ||
| 205 | int ycalib; /* calibrated null value for y */ | ||
| 206 | int zcalib; /* calibrated null value for z */ | ||
| 207 | struct axis_conversion ac; /* hw -> logical axis */ | 225 | struct axis_conversion ac; /* hw -> logical axis */ |
| 208 | 226 | ||
| 209 | u32 irq; /* IRQ number */ | 227 | u32 irq; /* IRQ number */ |
| @@ -212,6 +230,7 @@ struct lis3lv02d { | |||
| 212 | unsigned long misc_opened; /* bit0: whether the device is open */ | 230 | unsigned long misc_opened; /* bit0: whether the device is open */ |
| 213 | 231 | ||
| 214 | struct lis3lv02d_platform_data *pdata; /* for passing board config */ | 232 | struct lis3lv02d_platform_data *pdata; /* for passing board config */ |
| 233 | struct mutex mutex; /* Serialize poll and selftest */ | ||
| 215 | }; | 234 | }; |
| 216 | 235 | ||
| 217 | int lis3lv02d_init_device(struct lis3lv02d *lis3); | 236 | int lis3lv02d_init_device(struct lis3lv02d *lis3); |
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 5da66ab04f74..bf81aff7051d 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
| @@ -56,12 +56,6 @@ | |||
| 56 | static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; | 56 | static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; |
| 57 | 57 | ||
| 58 | /* | 58 | /* |
| 59 | * Insmod parameters | ||
| 60 | */ | ||
| 61 | |||
| 62 | I2C_CLIENT_INSMOD_1(lm63); | ||
| 63 | |||
| 64 | /* | ||
| 65 | * The LM63 registers | 59 | * The LM63 registers |
| 66 | */ | 60 | */ |
| 67 | 61 | ||
| @@ -134,8 +128,7 @@ static int lm63_remove(struct i2c_client *client); | |||
| 134 | 128 | ||
| 135 | static struct lm63_data *lm63_update_device(struct device *dev); | 129 | static struct lm63_data *lm63_update_device(struct device *dev); |
| 136 | 130 | ||
| 137 | static int lm63_detect(struct i2c_client *client, int kind, | 131 | static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 138 | struct i2c_board_info *info); | ||
| 139 | static void lm63_init_client(struct i2c_client *client); | 132 | static void lm63_init_client(struct i2c_client *client); |
| 140 | 133 | ||
| 141 | /* | 134 | /* |
| @@ -143,7 +136,7 @@ static void lm63_init_client(struct i2c_client *client); | |||
| 143 | */ | 136 | */ |
| 144 | 137 | ||
| 145 | static const struct i2c_device_id lm63_id[] = { | 138 | static const struct i2c_device_id lm63_id[] = { |
| 146 | { "lm63", lm63 }, | 139 | { "lm63", 0 }, |
| 147 | { } | 140 | { } |
| 148 | }; | 141 | }; |
| 149 | MODULE_DEVICE_TABLE(i2c, lm63_id); | 142 | MODULE_DEVICE_TABLE(i2c, lm63_id); |
| @@ -157,7 +150,7 @@ static struct i2c_driver lm63_driver = { | |||
| 157 | .remove = lm63_remove, | 150 | .remove = lm63_remove, |
| 158 | .id_table = lm63_id, | 151 | .id_table = lm63_id, |
| 159 | .detect = lm63_detect, | 152 | .detect = lm63_detect, |
| 160 | .address_data = &addr_data, | 153 | .address_list = normal_i2c, |
| 161 | }; | 154 | }; |
| 162 | 155 | ||
| 163 | /* | 156 | /* |
| @@ -423,7 +416,7 @@ static const struct attribute_group lm63_group_fan1 = { | |||
| 423 | */ | 416 | */ |
| 424 | 417 | ||
| 425 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 418 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 426 | static int lm63_detect(struct i2c_client *new_client, int kind, | 419 | static int lm63_detect(struct i2c_client *new_client, |
| 427 | struct i2c_board_info *info) | 420 | struct i2c_board_info *info) |
| 428 | { | 421 | { |
| 429 | struct i2c_adapter *adapter = new_client->adapter; | 422 | struct i2c_adapter *adapter = new_client->adapter; |
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c index 0bf8b2a8e9f0..c5f39ba103c0 100644 --- a/drivers/hwmon/lm73.c +++ b/drivers/hwmon/lm73.c | |||
| @@ -27,9 +27,6 @@ | |||
| 27 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, | 27 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, |
| 28 | 0x4d, 0x4e, I2C_CLIENT_END }; | 28 | 0x4d, 0x4e, I2C_CLIENT_END }; |
| 29 | 29 | ||
| 30 | /* Insmod parameters */ | ||
| 31 | I2C_CLIENT_INSMOD_1(lm73); | ||
| 32 | |||
| 33 | /* LM73 registers */ | 30 | /* LM73 registers */ |
| 34 | #define LM73_REG_INPUT 0x00 | 31 | #define LM73_REG_INPUT 0x00 |
| 35 | #define LM73_REG_CONF 0x01 | 32 | #define LM73_REG_CONF 0x01 |
| @@ -145,13 +142,13 @@ static int lm73_remove(struct i2c_client *client) | |||
| 145 | } | 142 | } |
| 146 | 143 | ||
| 147 | static const struct i2c_device_id lm73_ids[] = { | 144 | static const struct i2c_device_id lm73_ids[] = { |
| 148 | { "lm73", lm73 }, | 145 | { "lm73", 0 }, |
| 149 | { /* LIST END */ } | 146 | { /* LIST END */ } |
| 150 | }; | 147 | }; |
| 151 | MODULE_DEVICE_TABLE(i2c, lm73_ids); | 148 | MODULE_DEVICE_TABLE(i2c, lm73_ids); |
| 152 | 149 | ||
| 153 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 150 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 154 | static int lm73_detect(struct i2c_client *new_client, int kind, | 151 | static int lm73_detect(struct i2c_client *new_client, |
| 155 | struct i2c_board_info *info) | 152 | struct i2c_board_info *info) |
| 156 | { | 153 | { |
| 157 | struct i2c_adapter *adapter = new_client->adapter; | 154 | struct i2c_adapter *adapter = new_client->adapter; |
| @@ -182,7 +179,7 @@ static struct i2c_driver lm73_driver = { | |||
| 182 | .remove = lm73_remove, | 179 | .remove = lm73_remove, |
| 183 | .id_table = lm73_ids, | 180 | .id_table = lm73_ids, |
| 184 | .detect = lm73_detect, | 181 | .detect = lm73_detect, |
| 185 | .address_data = &addr_data, | 182 | .address_list = normal_i2c, |
| 186 | }; | 183 | }; |
| 187 | 184 | ||
| 188 | /* module glue */ | 185 | /* module glue */ |
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index e392548cccb8..8ae2cfe2d827 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
| @@ -32,15 +32,12 @@ | |||
| 32 | 32 | ||
| 33 | /* | 33 | /* |
| 34 | * This driver handles the LM75 and compatible digital temperature sensors. | 34 | * This driver handles the LM75 and compatible digital temperature sensors. |
| 35 | * Only types which are _not_ listed in I2C_CLIENT_INSMOD_*() need to be | ||
| 36 | * listed here. We start at 9 since I2C_CLIENT_INSMOD_*() currently allow | ||
| 37 | * definition of up to 8 chip types (plus zero). | ||
| 38 | */ | 35 | */ |
| 39 | 36 | ||
| 40 | enum lm75_type { /* keep sorted in alphabetical order */ | 37 | enum lm75_type { /* keep sorted in alphabetical order */ |
| 41 | ds1775 = 9, | 38 | ds1775, |
| 42 | ds75, | 39 | ds75, |
| 43 | /* lm75 -- in I2C_CLIENT_INSMOD_1() */ | 40 | lm75, |
| 44 | lm75a, | 41 | lm75a, |
| 45 | max6625, | 42 | max6625, |
| 46 | max6626, | 43 | max6626, |
| @@ -58,9 +55,6 @@ enum lm75_type { /* keep sorted in alphabetical order */ | |||
| 58 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, | 55 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, |
| 59 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; | 56 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; |
| 60 | 57 | ||
| 61 | /* Insmod parameters */ | ||
| 62 | I2C_CLIENT_INSMOD_1(lm75); | ||
| 63 | |||
| 64 | 58 | ||
| 65 | /* The LM75 registers */ | 59 | /* The LM75 registers */ |
| 66 | #define LM75_REG_CONF 0x01 | 60 | #define LM75_REG_CONF 0x01 |
| @@ -234,7 +228,7 @@ static const struct i2c_device_id lm75_ids[] = { | |||
| 234 | MODULE_DEVICE_TABLE(i2c, lm75_ids); | 228 | MODULE_DEVICE_TABLE(i2c, lm75_ids); |
| 235 | 229 | ||
| 236 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 230 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 237 | static int lm75_detect(struct i2c_client *new_client, int kind, | 231 | static int lm75_detect(struct i2c_client *new_client, |
| 238 | struct i2c_board_info *info) | 232 | struct i2c_board_info *info) |
| 239 | { | 233 | { |
| 240 | struct i2c_adapter *adapter = new_client->adapter; | 234 | struct i2c_adapter *adapter = new_client->adapter; |
| @@ -295,7 +289,7 @@ static struct i2c_driver lm75_driver = { | |||
| 295 | .remove = lm75_remove, | 289 | .remove = lm75_remove, |
| 296 | .id_table = lm75_ids, | 290 | .id_table = lm75_ids, |
| 297 | .detect = lm75_detect, | 291 | .detect = lm75_detect, |
| 298 | .address_data = &addr_data, | 292 | .address_list = normal_i2c, |
| 299 | }; | 293 | }; |
| 300 | 294 | ||
| 301 | /*-----------------------------------------------------------------------*/ | 295 | /*-----------------------------------------------------------------------*/ |
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index ac067fd19482..b28a297be50c 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c | |||
| @@ -39,9 +39,6 @@ | |||
| 39 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, | 39 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, |
| 40 | I2C_CLIENT_END }; | 40 | I2C_CLIENT_END }; |
| 41 | 41 | ||
| 42 | /* Insmod parameters */ | ||
| 43 | I2C_CLIENT_INSMOD_1(lm77); | ||
| 44 | |||
| 45 | /* The LM77 registers */ | 42 | /* The LM77 registers */ |
| 46 | #define LM77_REG_TEMP 0x00 | 43 | #define LM77_REG_TEMP 0x00 |
| 47 | #define LM77_REG_CONF 0x01 | 44 | #define LM77_REG_CONF 0x01 |
| @@ -66,8 +63,7 @@ struct lm77_data { | |||
| 66 | 63 | ||
| 67 | static int lm77_probe(struct i2c_client *client, | 64 | static int lm77_probe(struct i2c_client *client, |
| 68 | const struct i2c_device_id *id); | 65 | const struct i2c_device_id *id); |
| 69 | static int lm77_detect(struct i2c_client *client, int kind, | 66 | static int lm77_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 70 | struct i2c_board_info *info); | ||
| 71 | static void lm77_init_client(struct i2c_client *client); | 67 | static void lm77_init_client(struct i2c_client *client); |
| 72 | static int lm77_remove(struct i2c_client *client); | 68 | static int lm77_remove(struct i2c_client *client); |
| 73 | static u16 lm77_read_value(struct i2c_client *client, u8 reg); | 69 | static u16 lm77_read_value(struct i2c_client *client, u8 reg); |
| @@ -77,7 +73,7 @@ static struct lm77_data *lm77_update_device(struct device *dev); | |||
| 77 | 73 | ||
| 78 | 74 | ||
| 79 | static const struct i2c_device_id lm77_id[] = { | 75 | static const struct i2c_device_id lm77_id[] = { |
| 80 | { "lm77", lm77 }, | 76 | { "lm77", 0 }, |
| 81 | { } | 77 | { } |
| 82 | }; | 78 | }; |
| 83 | MODULE_DEVICE_TABLE(i2c, lm77_id); | 79 | MODULE_DEVICE_TABLE(i2c, lm77_id); |
| @@ -92,7 +88,7 @@ static struct i2c_driver lm77_driver = { | |||
| 92 | .remove = lm77_remove, | 88 | .remove = lm77_remove, |
| 93 | .id_table = lm77_id, | 89 | .id_table = lm77_id, |
| 94 | .detect = lm77_detect, | 90 | .detect = lm77_detect, |
| 95 | .address_data = &addr_data, | 91 | .address_list = normal_i2c, |
| 96 | }; | 92 | }; |
| 97 | 93 | ||
| 98 | /* straight from the datasheet */ | 94 | /* straight from the datasheet */ |
| @@ -245,7 +241,7 @@ static const struct attribute_group lm77_group = { | |||
| 245 | }; | 241 | }; |
| 246 | 242 | ||
| 247 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 243 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 248 | static int lm77_detect(struct i2c_client *new_client, int kind, | 244 | static int lm77_detect(struct i2c_client *new_client, |
| 249 | struct i2c_board_info *info) | 245 | struct i2c_board_info *info) |
| 250 | { | 246 | { |
| 251 | struct i2c_adapter *adapter = new_client->adapter; | 247 | struct i2c_adapter *adapter = new_client->adapter; |
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 5978291cebb3..cadcbd90ff3b 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
| @@ -41,8 +41,7 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | |||
| 41 | 0x2e, 0x2f, I2C_CLIENT_END }; | 41 | 0x2e, 0x2f, I2C_CLIENT_END }; |
| 42 | static unsigned short isa_address = 0x290; | 42 | static unsigned short isa_address = 0x290; |
| 43 | 43 | ||
| 44 | /* Insmod parameters */ | 44 | enum chips { lm78, lm79 }; |
| 45 | I2C_CLIENT_INSMOD_2(lm78, lm79); | ||
| 46 | 45 | ||
| 47 | /* Many LM78 constants specified below */ | 46 | /* Many LM78 constants specified below */ |
| 48 | 47 | ||
| @@ -142,7 +141,7 @@ struct lm78_data { | |||
| 142 | }; | 141 | }; |
| 143 | 142 | ||
| 144 | 143 | ||
| 145 | static int lm78_i2c_detect(struct i2c_client *client, int kind, | 144 | static int lm78_i2c_detect(struct i2c_client *client, |
| 146 | struct i2c_board_info *info); | 145 | struct i2c_board_info *info); |
| 147 | static int lm78_i2c_probe(struct i2c_client *client, | 146 | static int lm78_i2c_probe(struct i2c_client *client, |
| 148 | const struct i2c_device_id *id); | 147 | const struct i2c_device_id *id); |
| @@ -173,7 +172,7 @@ static struct i2c_driver lm78_driver = { | |||
| 173 | .remove = lm78_i2c_remove, | 172 | .remove = lm78_i2c_remove, |
| 174 | .id_table = lm78_i2c_id, | 173 | .id_table = lm78_i2c_id, |
| 175 | .detect = lm78_i2c_detect, | 174 | .detect = lm78_i2c_detect, |
| 176 | .address_data = &addr_data, | 175 | .address_list = normal_i2c, |
| 177 | }; | 176 | }; |
| 178 | 177 | ||
| 179 | static struct platform_driver lm78_isa_driver = { | 178 | static struct platform_driver lm78_isa_driver = { |
| @@ -558,7 +557,7 @@ static int lm78_alias_detect(struct i2c_client *client, u8 chipid) | |||
| 558 | return 1; | 557 | return 1; |
| 559 | } | 558 | } |
| 560 | 559 | ||
| 561 | static int lm78_i2c_detect(struct i2c_client *client, int kind, | 560 | static int lm78_i2c_detect(struct i2c_client *client, |
| 562 | struct i2c_board_info *info) | 561 | struct i2c_board_info *info) |
| 563 | { | 562 | { |
| 564 | int i; | 563 | int i; |
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index bcffc1899403..18a0e6c5fe88 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c | |||
| @@ -35,9 +35,6 @@ | |||
| 35 | static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | 35 | static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, |
| 36 | 0x2e, 0x2f, I2C_CLIENT_END }; | 36 | 0x2e, 0x2f, I2C_CLIENT_END }; |
| 37 | 37 | ||
| 38 | /* Insmod parameters */ | ||
| 39 | I2C_CLIENT_INSMOD_1(lm80); | ||
| 40 | |||
| 41 | /* Many LM80 constants specified below */ | 38 | /* Many LM80 constants specified below */ |
| 42 | 39 | ||
| 43 | /* The LM80 registers */ | 40 | /* The LM80 registers */ |
| @@ -133,8 +130,7 @@ struct lm80_data { | |||
| 133 | 130 | ||
| 134 | static int lm80_probe(struct i2c_client *client, | 131 | static int lm80_probe(struct i2c_client *client, |
| 135 | const struct i2c_device_id *id); | 132 | const struct i2c_device_id *id); |
| 136 | static int lm80_detect(struct i2c_client *client, int kind, | 133 | static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 137 | struct i2c_board_info *info); | ||
| 138 | static void lm80_init_client(struct i2c_client *client); | 134 | static void lm80_init_client(struct i2c_client *client); |
| 139 | static int lm80_remove(struct i2c_client *client); | 135 | static int lm80_remove(struct i2c_client *client); |
| 140 | static struct lm80_data *lm80_update_device(struct device *dev); | 136 | static struct lm80_data *lm80_update_device(struct device *dev); |
| @@ -146,7 +142,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); | |||
| 146 | */ | 142 | */ |
| 147 | 143 | ||
| 148 | static const struct i2c_device_id lm80_id[] = { | 144 | static const struct i2c_device_id lm80_id[] = { |
| 149 | { "lm80", lm80 }, | 145 | { "lm80", 0 }, |
| 150 | { } | 146 | { } |
| 151 | }; | 147 | }; |
| 152 | MODULE_DEVICE_TABLE(i2c, lm80_id); | 148 | MODULE_DEVICE_TABLE(i2c, lm80_id); |
| @@ -160,7 +156,7 @@ static struct i2c_driver lm80_driver = { | |||
| 160 | .remove = lm80_remove, | 156 | .remove = lm80_remove, |
| 161 | .id_table = lm80_id, | 157 | .id_table = lm80_id, |
| 162 | .detect = lm80_detect, | 158 | .detect = lm80_detect, |
| 163 | .address_data = &addr_data, | 159 | .address_list = normal_i2c, |
| 164 | }; | 160 | }; |
| 165 | 161 | ||
| 166 | /* | 162 | /* |
| @@ -447,8 +443,7 @@ static const struct attribute_group lm80_group = { | |||
| 447 | }; | 443 | }; |
| 448 | 444 | ||
| 449 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 445 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 450 | static int lm80_detect(struct i2c_client *client, int kind, | 446 | static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 451 | struct i2c_board_info *info) | ||
| 452 | { | 447 | { |
| 453 | struct i2c_adapter *adapter = client->adapter; | 448 | struct i2c_adapter *adapter = client->adapter; |
| 454 | int i, cur; | 449 | int i, cur; |
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 08b03e6ed0b7..8290476aee4a 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c | |||
| @@ -51,11 +51,7 @@ | |||
| 51 | static const unsigned short normal_i2c[] = { | 51 | static const unsigned short normal_i2c[] = { |
| 52 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | 52 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; |
| 53 | 53 | ||
| 54 | /* | 54 | enum chips { lm83, lm82 }; |
| 55 | * Insmod parameters | ||
| 56 | */ | ||
| 57 | |||
| 58 | I2C_CLIENT_INSMOD_2(lm83, lm82); | ||
| 59 | 55 | ||
| 60 | /* | 56 | /* |
| 61 | * The LM83 registers | 57 | * The LM83 registers |
| @@ -118,7 +114,7 @@ static const u8 LM83_REG_W_HIGH[] = { | |||
| 118 | * Functions declaration | 114 | * Functions declaration |
| 119 | */ | 115 | */ |
| 120 | 116 | ||
| 121 | static int lm83_detect(struct i2c_client *new_client, int kind, | 117 | static int lm83_detect(struct i2c_client *new_client, |
| 122 | struct i2c_board_info *info); | 118 | struct i2c_board_info *info); |
| 123 | static int lm83_probe(struct i2c_client *client, | 119 | static int lm83_probe(struct i2c_client *client, |
| 124 | const struct i2c_device_id *id); | 120 | const struct i2c_device_id *id); |
| @@ -145,7 +141,7 @@ static struct i2c_driver lm83_driver = { | |||
| 145 | .remove = lm83_remove, | 141 | .remove = lm83_remove, |
| 146 | .id_table = lm83_id, | 142 | .id_table = lm83_id, |
| 147 | .detect = lm83_detect, | 143 | .detect = lm83_detect, |
| 148 | .address_data = &addr_data, | 144 | .address_list = normal_i2c, |
| 149 | }; | 145 | }; |
| 150 | 146 | ||
| 151 | /* | 147 | /* |
| @@ -291,7 +287,7 @@ static const struct attribute_group lm83_group_opt = { | |||
| 291 | */ | 287 | */ |
| 292 | 288 | ||
| 293 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 289 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 294 | static int lm83_detect(struct i2c_client *new_client, int kind, | 290 | static int lm83_detect(struct i2c_client *new_client, |
| 295 | struct i2c_board_info *info) | 291 | struct i2c_board_info *info) |
| 296 | { | 292 | { |
| 297 | struct i2c_adapter *adapter = new_client->adapter; | 293 | struct i2c_adapter *adapter = new_client->adapter; |
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index d56da2e74708..b3841a615595 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c | |||
| @@ -38,9 +38,11 @@ | |||
| 38 | /* Addresses to scan */ | 38 | /* Addresses to scan */ |
| 39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 40 | 40 | ||
| 41 | /* Insmod parameters */ | 41 | enum chips { |
| 42 | I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100, | 42 | any_chip, lm85b, lm85c, |
| 43 | emc6d102); | 43 | adm1027, adt7463, adt7468, |
| 44 | emc6d100, emc6d102 | ||
| 45 | }; | ||
| 44 | 46 | ||
| 45 | /* The LM85 registers */ | 47 | /* The LM85 registers */ |
| 46 | 48 | ||
| @@ -323,8 +325,7 @@ struct lm85_data { | |||
| 323 | struct lm85_zone zone[3]; | 325 | struct lm85_zone zone[3]; |
| 324 | }; | 326 | }; |
| 325 | 327 | ||
| 326 | static int lm85_detect(struct i2c_client *client, int kind, | 328 | static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 327 | struct i2c_board_info *info); | ||
| 328 | static int lm85_probe(struct i2c_client *client, | 329 | static int lm85_probe(struct i2c_client *client, |
| 329 | const struct i2c_device_id *id); | 330 | const struct i2c_device_id *id); |
| 330 | static int lm85_remove(struct i2c_client *client); | 331 | static int lm85_remove(struct i2c_client *client); |
| @@ -357,7 +358,7 @@ static struct i2c_driver lm85_driver = { | |||
| 357 | .remove = lm85_remove, | 358 | .remove = lm85_remove, |
| 358 | .id_table = lm85_id, | 359 | .id_table = lm85_id, |
| 359 | .detect = lm85_detect, | 360 | .detect = lm85_detect, |
| 360 | .address_data = &addr_data, | 361 | .address_list = normal_i2c, |
| 361 | }; | 362 | }; |
| 362 | 363 | ||
| 363 | 364 | ||
| @@ -1156,8 +1157,7 @@ static int lm85_is_fake(struct i2c_client *client) | |||
| 1156 | } | 1157 | } |
| 1157 | 1158 | ||
| 1158 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1159 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1159 | static int lm85_detect(struct i2c_client *client, int kind, | 1160 | static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 1160 | struct i2c_board_info *info) | ||
| 1161 | { | 1161 | { |
| 1162 | struct i2c_adapter *adapter = client->adapter; | 1162 | struct i2c_adapter *adapter = client->adapter; |
| 1163 | int address = client->addr; | 1163 | int address = client->addr; |
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 4929b1815eee..f1e6e7512ffa 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c | |||
| @@ -74,11 +74,7 @@ | |||
| 74 | 74 | ||
| 75 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 75 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 76 | 76 | ||
| 77 | /* | 77 | enum chips { lm87, adm1024 }; |
| 78 | * Insmod parameters | ||
| 79 | */ | ||
| 80 | |||
| 81 | I2C_CLIENT_INSMOD_2(lm87, adm1024); | ||
| 82 | 78 | ||
| 83 | /* | 79 | /* |
| 84 | * The LM87 registers | 80 | * The LM87 registers |
| @@ -158,7 +154,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C }; | |||
| 158 | 154 | ||
| 159 | static int lm87_probe(struct i2c_client *client, | 155 | static int lm87_probe(struct i2c_client *client, |
| 160 | const struct i2c_device_id *id); | 156 | const struct i2c_device_id *id); |
| 161 | static int lm87_detect(struct i2c_client *new_client, int kind, | 157 | static int lm87_detect(struct i2c_client *new_client, |
| 162 | struct i2c_board_info *info); | 158 | struct i2c_board_info *info); |
| 163 | static void lm87_init_client(struct i2c_client *client); | 159 | static void lm87_init_client(struct i2c_client *client); |
| 164 | static int lm87_remove(struct i2c_client *client); | 160 | static int lm87_remove(struct i2c_client *client); |
| @@ -184,7 +180,7 @@ static struct i2c_driver lm87_driver = { | |||
| 184 | .remove = lm87_remove, | 180 | .remove = lm87_remove, |
| 185 | .id_table = lm87_id, | 181 | .id_table = lm87_id, |
| 186 | .detect = lm87_detect, | 182 | .detect = lm87_detect, |
| 187 | .address_data = &addr_data, | 183 | .address_list = normal_i2c, |
| 188 | }; | 184 | }; |
| 189 | 185 | ||
| 190 | /* | 186 | /* |
| @@ -662,7 +658,7 @@ static const struct attribute_group lm87_group_opt = { | |||
| 662 | }; | 658 | }; |
| 663 | 659 | ||
| 664 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 660 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 665 | static int lm87_detect(struct i2c_client *new_client, int kind, | 661 | static int lm87_detect(struct i2c_client *new_client, |
| 666 | struct i2c_board_info *info) | 662 | struct i2c_board_info *info) |
| 667 | { | 663 | { |
| 668 | struct i2c_adapter *adapter = new_client->adapter; | 664 | struct i2c_adapter *adapter = new_client->adapter; |
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index b7c905f50ed4..7c9bdc167426 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
| @@ -93,12 +93,7 @@ | |||
| 93 | static const unsigned short normal_i2c[] = { | 93 | static const unsigned short normal_i2c[] = { |
| 94 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | 94 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; |
| 95 | 95 | ||
| 96 | /* | 96 | enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646 }; |
| 97 | * Insmod parameters | ||
| 98 | */ | ||
| 99 | |||
| 100 | I2C_CLIENT_INSMOD_8(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, | ||
| 101 | max6646); | ||
| 102 | 97 | ||
| 103 | /* | 98 | /* |
| 104 | * The LM90 registers | 99 | * The LM90 registers |
| @@ -152,8 +147,7 @@ I2C_CLIENT_INSMOD_8(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, | |||
| 152 | * Functions declaration | 147 | * Functions declaration |
| 153 | */ | 148 | */ |
| 154 | 149 | ||
| 155 | static int lm90_detect(struct i2c_client *client, int kind, | 150 | static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info); |
| 156 | struct i2c_board_info *info); | ||
| 157 | static int lm90_probe(struct i2c_client *client, | 151 | static int lm90_probe(struct i2c_client *client, |
| 158 | const struct i2c_device_id *id); | 152 | const struct i2c_device_id *id); |
| 159 | static void lm90_init_client(struct i2c_client *client); | 153 | static void lm90_init_client(struct i2c_client *client); |
| @@ -192,7 +186,7 @@ static struct i2c_driver lm90_driver = { | |||
| 192 | .remove = lm90_remove, | 186 | .remove = lm90_remove, |
| 193 | .id_table = lm90_id, | 187 | .id_table = lm90_id, |
| 194 | .detect = lm90_detect, | 188 | .detect = lm90_detect, |
| 195 | .address_data = &addr_data, | 189 | .address_list = normal_i2c, |
| 196 | }; | 190 | }; |
| 197 | 191 | ||
| 198 | /* | 192 | /* |
| @@ -656,7 +650,7 @@ static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) | |||
| 656 | } | 650 | } |
| 657 | 651 | ||
| 658 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 652 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 659 | static int lm90_detect(struct i2c_client *new_client, int kind, | 653 | static int lm90_detect(struct i2c_client *new_client, |
| 660 | struct i2c_board_info *info) | 654 | struct i2c_board_info *info) |
| 661 | { | 655 | { |
| 662 | struct i2c_adapter *adapter = new_client->adapter; | 656 | struct i2c_adapter *adapter = new_client->adapter; |
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index 47ac698709dc..7c31e6205f85 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c | |||
| @@ -54,9 +54,6 @@ | |||
| 54 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, | 54 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, |
| 55 | I2C_CLIENT_END }; | 55 | I2C_CLIENT_END }; |
| 56 | 56 | ||
| 57 | /* Insmod parameters */ | ||
| 58 | I2C_CLIENT_INSMOD_1(lm92); | ||
| 59 | |||
| 60 | /* The LM92 registers */ | 57 | /* The LM92 registers */ |
| 61 | #define LM92_REG_CONFIG 0x01 /* 8-bit, RW */ | 58 | #define LM92_REG_CONFIG 0x01 /* 8-bit, RW */ |
| 62 | #define LM92_REG_TEMP 0x00 /* 16-bit, RO */ | 59 | #define LM92_REG_TEMP 0x00 /* 16-bit, RO */ |
| @@ -319,7 +316,7 @@ static const struct attribute_group lm92_group = { | |||
| 319 | }; | 316 | }; |
| 320 | 317 | ||
| 321 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 318 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 322 | static int lm92_detect(struct i2c_client *new_client, int kind, | 319 | static int lm92_detect(struct i2c_client *new_client, |
| 323 | struct i2c_board_info *info) | 320 | struct i2c_board_info *info) |
| 324 | { | 321 | { |
| 325 | struct i2c_adapter *adapter = new_client->adapter; | 322 | struct i2c_adapter *adapter = new_client->adapter; |
| @@ -401,7 +398,7 @@ static int lm92_remove(struct i2c_client *client) | |||
| 401 | */ | 398 | */ |
| 402 | 399 | ||
| 403 | static const struct i2c_device_id lm92_id[] = { | 400 | static const struct i2c_device_id lm92_id[] = { |
| 404 | { "lm92", lm92 }, | 401 | { "lm92", 0 }, |
| 405 | /* max6635 could be added here */ | 402 | /* max6635 could be added here */ |
| 406 | { } | 403 | { } |
| 407 | }; | 404 | }; |
| @@ -416,7 +413,7 @@ static struct i2c_driver lm92_driver = { | |||
| 416 | .remove = lm92_remove, | 413 | .remove = lm92_remove, |
| 417 | .id_table = lm92_id, | 414 | .id_table = lm92_id, |
| 418 | .detect = lm92_detect, | 415 | .detect = lm92_detect, |
| 419 | .address_data = &addr_data, | 416 | .address_list = normal_i2c, |
| 420 | }; | 417 | }; |
| 421 | 418 | ||
| 422 | static int __init sensors_lm92_init(void) | 419 | static int __init sensors_lm92_init(void) |
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 124dd7cea54c..6669255aadcf 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c | |||
| @@ -145,7 +145,6 @@ | |||
| 145 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 145 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 146 | 146 | ||
| 147 | /* Insmod parameters */ | 147 | /* Insmod parameters */ |
| 148 | I2C_CLIENT_INSMOD_1(lm93); | ||
| 149 | 148 | ||
| 150 | static int disable_block; | 149 | static int disable_block; |
| 151 | module_param(disable_block, bool, 0); | 150 | module_param(disable_block, bool, 0); |
| @@ -2501,8 +2500,7 @@ static void lm93_init_client(struct i2c_client *client) | |||
| 2501 | } | 2500 | } |
| 2502 | 2501 | ||
| 2503 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 2502 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 2504 | static int lm93_detect(struct i2c_client *client, int kind, | 2503 | static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 2505 | struct i2c_board_info *info) | ||
| 2506 | { | 2504 | { |
| 2507 | struct i2c_adapter *adapter = client->adapter; | 2505 | struct i2c_adapter *adapter = client->adapter; |
| 2508 | int mfr, ver; | 2506 | int mfr, ver; |
| @@ -2603,7 +2601,7 @@ static int lm93_remove(struct i2c_client *client) | |||
| 2603 | } | 2601 | } |
| 2604 | 2602 | ||
| 2605 | static const struct i2c_device_id lm93_id[] = { | 2603 | static const struct i2c_device_id lm93_id[] = { |
| 2606 | { "lm93", lm93 }, | 2604 | { "lm93", 0 }, |
| 2607 | { } | 2605 | { } |
| 2608 | }; | 2606 | }; |
| 2609 | MODULE_DEVICE_TABLE(i2c, lm93_id); | 2607 | MODULE_DEVICE_TABLE(i2c, lm93_id); |
| @@ -2617,7 +2615,7 @@ static struct i2c_driver lm93_driver = { | |||
| 2617 | .remove = lm93_remove, | 2615 | .remove = lm93_remove, |
| 2618 | .id_table = lm93_id, | 2616 | .id_table = lm93_id, |
| 2619 | .detect = lm93_detect, | 2617 | .detect = lm93_detect, |
| 2620 | .address_data = &addr_data, | 2618 | .address_list = normal_i2c, |
| 2621 | }; | 2619 | }; |
| 2622 | 2620 | ||
| 2623 | static int __init lm93_init(void) | 2621 | static int __init lm93_init(void) |
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 906b896cf1d0..8fc8eb8cba47 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c | |||
| @@ -39,9 +39,6 @@ | |||
| 39 | static const unsigned short normal_i2c[] = { | 39 | static const unsigned short normal_i2c[] = { |
| 40 | 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; | 40 | 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; |
| 41 | 41 | ||
| 42 | /* Insmod parameters */ | ||
| 43 | I2C_CLIENT_INSMOD_1(lm95241); | ||
| 44 | |||
| 45 | /* LM95241 registers */ | 42 | /* LM95241 registers */ |
| 46 | #define LM95241_REG_R_MAN_ID 0xFE | 43 | #define LM95241_REG_R_MAN_ID 0xFE |
| 47 | #define LM95241_REG_R_CHIP_ID 0xFF | 44 | #define LM95241_REG_R_CHIP_ID 0xFF |
| @@ -310,7 +307,7 @@ static const struct attribute_group lm95241_group = { | |||
| 310 | }; | 307 | }; |
| 311 | 308 | ||
| 312 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 309 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 313 | static int lm95241_detect(struct i2c_client *new_client, int kind, | 310 | static int lm95241_detect(struct i2c_client *new_client, |
| 314 | struct i2c_board_info *info) | 311 | struct i2c_board_info *info) |
| 315 | { | 312 | { |
| 316 | struct i2c_adapter *adapter = new_client->adapter; | 313 | struct i2c_adapter *adapter = new_client->adapter; |
| @@ -446,7 +443,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev) | |||
| 446 | 443 | ||
| 447 | /* Driver data (common to all clients) */ | 444 | /* Driver data (common to all clients) */ |
| 448 | static const struct i2c_device_id lm95241_id[] = { | 445 | static const struct i2c_device_id lm95241_id[] = { |
| 449 | { "lm95241", lm95241 }, | 446 | { "lm95241", 0 }, |
| 450 | { } | 447 | { } |
| 451 | }; | 448 | }; |
| 452 | MODULE_DEVICE_TABLE(i2c, lm95241_id); | 449 | MODULE_DEVICE_TABLE(i2c, lm95241_id); |
| @@ -460,7 +457,7 @@ static struct i2c_driver lm95241_driver = { | |||
| 460 | .remove = lm95241_remove, | 457 | .remove = lm95241_remove, |
| 461 | .id_table = lm95241_id, | 458 | .id_table = lm95241_id, |
| 462 | .detect = lm95241_detect, | 459 | .detect = lm95241_detect, |
| 463 | .address_data = &addr_data, | 460 | .address_list = normal_i2c, |
| 464 | }; | 461 | }; |
| 465 | 462 | ||
| 466 | static int __init sensors_lm95241_init(void) | 463 | static int __init sensors_lm95241_init(void) |
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 7fcf5ff89e7f..022ded098100 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c | |||
| @@ -41,12 +41,6 @@ static const unsigned short normal_i2c[] = { | |||
| 41 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | 41 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; |
| 42 | 42 | ||
| 43 | /* | 43 | /* |
| 44 | * Insmod parameters | ||
| 45 | */ | ||
| 46 | |||
| 47 | I2C_CLIENT_INSMOD_1(max1619); | ||
| 48 | |||
| 49 | /* | ||
| 50 | * The MAX1619 registers | 44 | * The MAX1619 registers |
| 51 | */ | 45 | */ |
| 52 | 46 | ||
| @@ -88,7 +82,7 @@ static int temp_to_reg(int val) | |||
| 88 | 82 | ||
| 89 | static int max1619_probe(struct i2c_client *client, | 83 | static int max1619_probe(struct i2c_client *client, |
| 90 | const struct i2c_device_id *id); | 84 | const struct i2c_device_id *id); |
| 91 | static int max1619_detect(struct i2c_client *client, int kind, | 85 | static int max1619_detect(struct i2c_client *client, |
| 92 | struct i2c_board_info *info); | 86 | struct i2c_board_info *info); |
| 93 | static void max1619_init_client(struct i2c_client *client); | 87 | static void max1619_init_client(struct i2c_client *client); |
| 94 | static int max1619_remove(struct i2c_client *client); | 88 | static int max1619_remove(struct i2c_client *client); |
| @@ -99,7 +93,7 @@ static struct max1619_data *max1619_update_device(struct device *dev); | |||
| 99 | */ | 93 | */ |
| 100 | 94 | ||
| 101 | static const struct i2c_device_id max1619_id[] = { | 95 | static const struct i2c_device_id max1619_id[] = { |
| 102 | { "max1619", max1619 }, | 96 | { "max1619", 0 }, |
| 103 | { } | 97 | { } |
| 104 | }; | 98 | }; |
| 105 | MODULE_DEVICE_TABLE(i2c, max1619_id); | 99 | MODULE_DEVICE_TABLE(i2c, max1619_id); |
| @@ -113,7 +107,7 @@ static struct i2c_driver max1619_driver = { | |||
| 113 | .remove = max1619_remove, | 107 | .remove = max1619_remove, |
| 114 | .id_table = max1619_id, | 108 | .id_table = max1619_id, |
| 115 | .detect = max1619_detect, | 109 | .detect = max1619_detect, |
| 116 | .address_data = &addr_data, | 110 | .address_list = normal_i2c, |
| 117 | }; | 111 | }; |
| 118 | 112 | ||
| 119 | /* | 113 | /* |
| @@ -226,7 +220,7 @@ static const struct attribute_group max1619_group = { | |||
| 226 | */ | 220 | */ |
| 227 | 221 | ||
| 228 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 222 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 229 | static int max1619_detect(struct i2c_client *client, int kind, | 223 | static int max1619_detect(struct i2c_client *client, |
| 230 | struct i2c_board_info *info) | 224 | struct i2c_board_info *info) |
| 231 | { | 225 | { |
| 232 | struct i2c_adapter *adapter = client->adapter; | 226 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 1da561e0cb37..a0160ee5caef 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c | |||
| @@ -62,8 +62,6 @@ module_param(fan_voltage, int, S_IRUGO); | |||
| 62 | module_param(prescaler, int, S_IRUGO); | 62 | module_param(prescaler, int, S_IRUGO); |
| 63 | module_param(clock, int, S_IRUGO); | 63 | module_param(clock, int, S_IRUGO); |
| 64 | 64 | ||
| 65 | I2C_CLIENT_INSMOD_1(max6650); | ||
| 66 | |||
| 67 | /* | 65 | /* |
| 68 | * MAX 6650/6651 registers | 66 | * MAX 6650/6651 registers |
| 69 | */ | 67 | */ |
| @@ -116,7 +114,7 @@ I2C_CLIENT_INSMOD_1(max6650); | |||
| 116 | 114 | ||
| 117 | static int max6650_probe(struct i2c_client *client, | 115 | static int max6650_probe(struct i2c_client *client, |
| 118 | const struct i2c_device_id *id); | 116 | const struct i2c_device_id *id); |
| 119 | static int max6650_detect(struct i2c_client *client, int kind, | 117 | static int max6650_detect(struct i2c_client *client, |
| 120 | struct i2c_board_info *info); | 118 | struct i2c_board_info *info); |
| 121 | static int max6650_init_client(struct i2c_client *client); | 119 | static int max6650_init_client(struct i2c_client *client); |
| 122 | static int max6650_remove(struct i2c_client *client); | 120 | static int max6650_remove(struct i2c_client *client); |
| @@ -127,7 +125,7 @@ static struct max6650_data *max6650_update_device(struct device *dev); | |||
| 127 | */ | 125 | */ |
| 128 | 126 | ||
| 129 | static const struct i2c_device_id max6650_id[] = { | 127 | static const struct i2c_device_id max6650_id[] = { |
| 130 | { "max6650", max6650 }, | 128 | { "max6650", 0 }, |
| 131 | { } | 129 | { } |
| 132 | }; | 130 | }; |
| 133 | MODULE_DEVICE_TABLE(i2c, max6650_id); | 131 | MODULE_DEVICE_TABLE(i2c, max6650_id); |
| @@ -141,7 +139,7 @@ static struct i2c_driver max6650_driver = { | |||
| 141 | .remove = max6650_remove, | 139 | .remove = max6650_remove, |
| 142 | .id_table = max6650_id, | 140 | .id_table = max6650_id, |
| 143 | .detect = max6650_detect, | 141 | .detect = max6650_detect, |
| 144 | .address_data = &addr_data, | 142 | .address_list = normal_i2c, |
| 145 | }; | 143 | }; |
| 146 | 144 | ||
| 147 | /* | 145 | /* |
| @@ -528,7 +526,7 @@ static struct attribute_group max6650_attr_grp = { | |||
| 528 | */ | 526 | */ |
| 529 | 527 | ||
| 530 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 528 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 531 | static int max6650_detect(struct i2c_client *client, int kind, | 529 | static int max6650_detect(struct i2c_client *client, |
| 532 | struct i2c_board_info *info) | 530 | struct i2c_board_info *info) |
| 533 | { | 531 | { |
| 534 | struct i2c_adapter *adapter = client->adapter; | 532 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c index 1d7ffebd679d..d44787949851 100644 --- a/drivers/hwmon/pcf8591.c +++ b/drivers/hwmon/pcf8591.c | |||
| @@ -29,7 +29,6 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, | |||
| 29 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; | 29 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; |
| 30 | 30 | ||
| 31 | /* Insmod parameters */ | 31 | /* Insmod parameters */ |
| 32 | I2C_CLIENT_INSMOD_1(pcf8591); | ||
| 33 | 32 | ||
| 34 | static int input_mode; | 33 | static int input_mode; |
| 35 | module_param(input_mode, int, 0); | 34 | module_param(input_mode, int, 0); |
| @@ -169,7 +168,7 @@ static const struct attribute_group pcf8591_attr_group_opt = { | |||
| 169 | */ | 168 | */ |
| 170 | 169 | ||
| 171 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 170 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 172 | static int pcf8591_detect(struct i2c_client *client, int kind, | 171 | static int pcf8591_detect(struct i2c_client *client, |
| 173 | struct i2c_board_info *info) | 172 | struct i2c_board_info *info) |
| 174 | { | 173 | { |
| 175 | struct i2c_adapter *adapter = client->adapter; | 174 | struct i2c_adapter *adapter = client->adapter; |
| @@ -299,7 +298,7 @@ static struct i2c_driver pcf8591_driver = { | |||
| 299 | 298 | ||
| 300 | .class = I2C_CLASS_HWMON, /* Nearest choice */ | 299 | .class = I2C_CLASS_HWMON, /* Nearest choice */ |
| 301 | .detect = pcf8591_detect, | 300 | .detect = pcf8591_detect, |
| 302 | .address_data = &addr_data, | 301 | .address_list = normal_i2c, |
| 303 | }; | 302 | }; |
| 304 | 303 | ||
| 305 | static int __init pcf8591_init(void) | 304 | static int __init pcf8591_init(void) |
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index 4d88c045781c..40b26673d87f 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c | |||
| @@ -36,9 +36,6 @@ | |||
| 36 | /* Addresses to scan */ | 36 | /* Addresses to scan */ |
| 37 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; | 37 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; |
| 38 | 38 | ||
| 39 | /* Insmod parameters */ | ||
| 40 | I2C_CLIENT_INSMOD_1(smsc47m192); | ||
| 41 | |||
| 42 | /* SMSC47M192 registers */ | 39 | /* SMSC47M192 registers */ |
| 43 | #define SMSC47M192_REG_IN(nr) ((nr)<6 ? (0x20 + (nr)) : \ | 40 | #define SMSC47M192_REG_IN(nr) ((nr)<6 ? (0x20 + (nr)) : \ |
| 44 | (0x50 + (nr) - 6)) | 41 | (0x50 + (nr) - 6)) |
| @@ -115,13 +112,13 @@ struct smsc47m192_data { | |||
| 115 | 112 | ||
| 116 | static int smsc47m192_probe(struct i2c_client *client, | 113 | static int smsc47m192_probe(struct i2c_client *client, |
| 117 | const struct i2c_device_id *id); | 114 | const struct i2c_device_id *id); |
| 118 | static int smsc47m192_detect(struct i2c_client *client, int kind, | 115 | static int smsc47m192_detect(struct i2c_client *client, |
| 119 | struct i2c_board_info *info); | 116 | struct i2c_board_info *info); |
| 120 | static int smsc47m192_remove(struct i2c_client *client); | 117 | static int smsc47m192_remove(struct i2c_client *client); |
| 121 | static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); | 118 | static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); |
| 122 | 119 | ||
| 123 | static const struct i2c_device_id smsc47m192_id[] = { | 120 | static const struct i2c_device_id smsc47m192_id[] = { |
| 124 | { "smsc47m192", smsc47m192 }, | 121 | { "smsc47m192", 0 }, |
| 125 | { } | 122 | { } |
| 126 | }; | 123 | }; |
| 127 | MODULE_DEVICE_TABLE(i2c, smsc47m192_id); | 124 | MODULE_DEVICE_TABLE(i2c, smsc47m192_id); |
| @@ -135,7 +132,7 @@ static struct i2c_driver smsc47m192_driver = { | |||
| 135 | .remove = smsc47m192_remove, | 132 | .remove = smsc47m192_remove, |
| 136 | .id_table = smsc47m192_id, | 133 | .id_table = smsc47m192_id, |
| 137 | .detect = smsc47m192_detect, | 134 | .detect = smsc47m192_detect, |
| 138 | .address_data = &addr_data, | 135 | .address_list = normal_i2c, |
| 139 | }; | 136 | }; |
| 140 | 137 | ||
| 141 | /* Voltages */ | 138 | /* Voltages */ |
| @@ -481,7 +478,7 @@ static void smsc47m192_init_client(struct i2c_client *client) | |||
| 481 | } | 478 | } |
| 482 | 479 | ||
| 483 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 480 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 484 | static int smsc47m192_detect(struct i2c_client *client, int kind, | 481 | static int smsc47m192_detect(struct i2c_client *client, |
| 485 | struct i2c_board_info *info) | 482 | struct i2c_board_info *info) |
| 486 | { | 483 | { |
| 487 | struct i2c_adapter *adapter = client->adapter; | 484 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index 4b793849c738..7dfb4dec4c5f 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c | |||
| @@ -35,7 +35,7 @@ MODULE_LICENSE("GPL"); | |||
| 35 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 35 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
| 36 | 36 | ||
| 37 | /* Insmod parameters */ | 37 | /* Insmod parameters */ |
| 38 | I2C_CLIENT_INSMOD_2(thmc50, adm1022); | 38 | enum chips { thmc50, adm1022 }; |
| 39 | 39 | ||
| 40 | static unsigned short adm1022_temp3[16]; | 40 | static unsigned short adm1022_temp3[16]; |
| 41 | static unsigned int adm1022_temp3_num; | 41 | static unsigned int adm1022_temp3_num; |
| @@ -84,7 +84,7 @@ struct thmc50_data { | |||
| 84 | u8 alarms; | 84 | u8 alarms; |
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | static int thmc50_detect(struct i2c_client *client, int kind, | 87 | static int thmc50_detect(struct i2c_client *client, |
| 88 | struct i2c_board_info *info); | 88 | struct i2c_board_info *info); |
| 89 | static int thmc50_probe(struct i2c_client *client, | 89 | static int thmc50_probe(struct i2c_client *client, |
| 90 | const struct i2c_device_id *id); | 90 | const struct i2c_device_id *id); |
| @@ -108,7 +108,7 @@ static struct i2c_driver thmc50_driver = { | |||
| 108 | .remove = thmc50_remove, | 108 | .remove = thmc50_remove, |
| 109 | .id_table = thmc50_id, | 109 | .id_table = thmc50_id, |
| 110 | .detect = thmc50_detect, | 110 | .detect = thmc50_detect, |
| 111 | .address_data = &addr_data, | 111 | .address_list = normal_i2c, |
| 112 | }; | 112 | }; |
| 113 | 113 | ||
| 114 | static ssize_t show_analog_out(struct device *dev, | 114 | static ssize_t show_analog_out(struct device *dev, |
| @@ -286,7 +286,7 @@ static const struct attribute_group temp3_group = { | |||
| 286 | }; | 286 | }; |
| 287 | 287 | ||
| 288 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 288 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 289 | static int thmc50_detect(struct i2c_client *client, int kind, | 289 | static int thmc50_detect(struct i2c_client *client, |
| 290 | struct i2c_board_info *info) | 290 | struct i2c_board_info *info) |
| 291 | { | 291 | { |
| 292 | unsigned company; | 292 | unsigned company; |
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index ee9673467c4a..a13b30e8d8d8 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c | |||
| @@ -42,8 +42,7 @@ | |||
| 42 | /* Addresses to scan */ | 42 | /* Addresses to scan */ |
| 43 | static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; | 43 | static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; |
| 44 | 44 | ||
| 45 | /* Insmod parameters */ | 45 | enum chips { tmp401, tmp411 }; |
| 46 | I2C_CLIENT_INSMOD_2(tmp401, tmp411); | ||
| 47 | 46 | ||
| 48 | /* | 47 | /* |
| 49 | * The TMP401 registers, note some registers have different addresses for | 48 | * The TMP401 registers, note some registers have different addresses for |
| @@ -98,7 +97,7 @@ static const u8 TMP411_TEMP_HIGHEST_LSB[2] = { 0x33, 0x37 }; | |||
| 98 | 97 | ||
| 99 | static int tmp401_probe(struct i2c_client *client, | 98 | static int tmp401_probe(struct i2c_client *client, |
| 100 | const struct i2c_device_id *id); | 99 | const struct i2c_device_id *id); |
| 101 | static int tmp401_detect(struct i2c_client *client, int kind, | 100 | static int tmp401_detect(struct i2c_client *client, |
| 102 | struct i2c_board_info *info); | 101 | struct i2c_board_info *info); |
| 103 | static int tmp401_remove(struct i2c_client *client); | 102 | static int tmp401_remove(struct i2c_client *client); |
| 104 | static struct tmp401_data *tmp401_update_device(struct device *dev); | 103 | static struct tmp401_data *tmp401_update_device(struct device *dev); |
| @@ -123,7 +122,7 @@ static struct i2c_driver tmp401_driver = { | |||
| 123 | .remove = tmp401_remove, | 122 | .remove = tmp401_remove, |
| 124 | .id_table = tmp401_id, | 123 | .id_table = tmp401_id, |
| 125 | .detect = tmp401_detect, | 124 | .detect = tmp401_detect, |
| 126 | .address_data = &addr_data, | 125 | .address_list = normal_i2c, |
| 127 | }; | 126 | }; |
| 128 | 127 | ||
| 129 | /* | 128 | /* |
| @@ -488,7 +487,7 @@ static void tmp401_init_client(struct i2c_client *client) | |||
| 488 | i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config); | 487 | i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config); |
| 489 | } | 488 | } |
| 490 | 489 | ||
| 491 | static int tmp401_detect(struct i2c_client *client, int _kind, | 490 | static int tmp401_detect(struct i2c_client *client, |
| 492 | struct i2c_board_info *info) | 491 | struct i2c_board_info *info) |
| 493 | { | 492 | { |
| 494 | enum chips kind; | 493 | enum chips kind; |
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index bb5464a289ca..4f7c051e2d7b 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c | |||
| @@ -39,8 +39,7 @@ | |||
| 39 | static unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f, | 39 | static unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f, |
| 40 | I2C_CLIENT_END }; | 40 | I2C_CLIENT_END }; |
| 41 | 41 | ||
| 42 | /* Insmod parameters */ | 42 | enum chips { tmp421, tmp422, tmp423 }; |
| 43 | I2C_CLIENT_INSMOD_3(tmp421, tmp422, tmp423); | ||
| 44 | 43 | ||
| 45 | /* The TMP421 registers */ | 44 | /* The TMP421 registers */ |
| 46 | #define TMP421_CONFIG_REG_1 0x09 | 45 | #define TMP421_CONFIG_REG_1 0x09 |
| @@ -223,7 +222,7 @@ static int tmp421_init_client(struct i2c_client *client) | |||
| 223 | return 0; | 222 | return 0; |
| 224 | } | 223 | } |
| 225 | 224 | ||
| 226 | static int tmp421_detect(struct i2c_client *client, int _kind, | 225 | static int tmp421_detect(struct i2c_client *client, |
| 227 | struct i2c_board_info *info) | 226 | struct i2c_board_info *info) |
| 228 | { | 227 | { |
| 229 | enum chips kind; | 228 | enum chips kind; |
| @@ -322,7 +321,7 @@ static struct i2c_driver tmp421_driver = { | |||
| 322 | .remove = tmp421_remove, | 321 | .remove = tmp421_remove, |
| 323 | .id_table = tmp421_id, | 322 | .id_table = tmp421_id, |
| 324 | .detect = tmp421_detect, | 323 | .detect = tmp421_detect, |
| 325 | .address_data = &addr_data, | 324 | .address_list = normal_i2c, |
| 326 | }; | 325 | }; |
| 327 | 326 | ||
| 328 | static int __init tmp421_init(void) | 327 | static int __init tmp421_init(void) |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index bb5e78748783..0dcaba9b7189 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | Copyright (C) 2006 Yuan Mu (Winbond), | 5 | Copyright (C) 2006 Yuan Mu (Winbond), |
| 6 | Rudolf Marek <r.marek@assembler.cz> | 6 | Rudolf Marek <r.marek@assembler.cz> |
| 7 | David Hubbard <david.c.hubbard@gmail.com> | 7 | David Hubbard <david.c.hubbard@gmail.com> |
| 8 | Daniel J Blueman <daniel.blueman@gmail.com> | ||
| 8 | 9 | ||
| 9 | Shamelessly ripped from the w83627hf driver | 10 | Shamelessly ripped from the w83627hf driver |
| 10 | Copyright (C) 2003 Mark Studebaker | 11 | Copyright (C) 2003 Mark Studebaker |
| @@ -177,12 +178,15 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 }; | |||
| 177 | #define W83627EHF_REG_ALARM3 0x45B | 178 | #define W83627EHF_REG_ALARM3 0x45B |
| 178 | 179 | ||
| 179 | /* SmartFan registers */ | 180 | /* SmartFan registers */ |
| 181 | #define W83627EHF_REG_FAN_STEPUP_TIME 0x0f | ||
| 182 | #define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e | ||
| 183 | |||
| 180 | /* DC or PWM output fan configuration */ | 184 | /* DC or PWM output fan configuration */ |
| 181 | static const u8 W83627EHF_REG_PWM_ENABLE[] = { | 185 | static const u8 W83627EHF_REG_PWM_ENABLE[] = { |
| 182 | 0x04, /* SYS FAN0 output mode and PWM mode */ | 186 | 0x04, /* SYS FAN0 output mode and PWM mode */ |
| 183 | 0x04, /* CPU FAN0 output mode and PWM mode */ | 187 | 0x04, /* CPU FAN0 output mode and PWM mode */ |
| 184 | 0x12, /* AUX FAN mode */ | 188 | 0x12, /* AUX FAN mode */ |
| 185 | 0x62, /* CPU fan1 mode */ | 189 | 0x62, /* CPU FAN1 mode */ |
| 186 | }; | 190 | }; |
| 187 | 191 | ||
| 188 | static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 }; | 192 | static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 }; |
| @@ -193,10 +197,12 @@ static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 }; | |||
| 193 | static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 }; | 197 | static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 }; |
| 194 | static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 }; | 198 | static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 }; |
| 195 | 199 | ||
| 196 | |||
| 197 | /* Advanced Fan control, some values are common for all fans */ | 200 | /* Advanced Fan control, some values are common for all fans */ |
| 198 | static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; | 201 | static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 }; |
| 199 | static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 }; | 202 | static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; |
| 203 | static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 }; | ||
| 204 | static const u8 W83627EHF_REG_FAN_MAX_OUTPUT[] = { 0xff, 0x67, 0xff, 0x69 }; | ||
| 205 | static const u8 W83627EHF_REG_FAN_STEP_OUTPUT[] = { 0xff, 0x68, 0xff, 0x6a }; | ||
| 200 | 206 | ||
| 201 | /* | 207 | /* |
| 202 | * Conversions | 208 | * Conversions |
| @@ -295,14 +301,19 @@ struct w83627ehf_data { | |||
| 295 | 301 | ||
| 296 | u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ | 302 | u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ |
| 297 | u8 pwm_enable[4]; /* 1->manual | 303 | u8 pwm_enable[4]; /* 1->manual |
| 298 | 2->thermal cruise (also called SmartFan I) */ | 304 | 2->thermal cruise mode (also called SmartFan I) |
| 305 | 3->fan speed cruise mode | ||
| 306 | 4->variable thermal cruise (also called SmartFan III) */ | ||
| 299 | u8 pwm_num; /* number of pwm */ | 307 | u8 pwm_num; /* number of pwm */ |
| 300 | u8 pwm[4]; | 308 | u8 pwm[4]; |
| 301 | u8 target_temp[4]; | 309 | u8 target_temp[4]; |
| 302 | u8 tolerance[4]; | 310 | u8 tolerance[4]; |
| 303 | 311 | ||
| 304 | u8 fan_min_output[4]; /* minimum fan speed */ | 312 | u8 fan_start_output[4]; /* minimum fan speed when spinning up */ |
| 305 | u8 fan_stop_time[4]; | 313 | u8 fan_stop_output[4]; /* minimum fan speed when spinning down */ |
| 314 | u8 fan_stop_time[4]; /* time at minimum before disabling fan */ | ||
| 315 | u8 fan_max_output[4]; /* maximum fan speed */ | ||
| 316 | u8 fan_step_output[4]; /* rate of change output value */ | ||
| 306 | 317 | ||
| 307 | u8 vid; | 318 | u8 vid; |
| 308 | u8 vrm; | 319 | u8 vrm; |
| @@ -529,8 +540,10 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
| 529 | & 3) + 1; | 540 | & 3) + 1; |
| 530 | data->pwm[i] = w83627ehf_read_value(data, | 541 | data->pwm[i] = w83627ehf_read_value(data, |
| 531 | W83627EHF_REG_PWM[i]); | 542 | W83627EHF_REG_PWM[i]); |
| 532 | data->fan_min_output[i] = w83627ehf_read_value(data, | 543 | data->fan_start_output[i] = w83627ehf_read_value(data, |
| 533 | W83627EHF_REG_FAN_MIN_OUTPUT[i]); | 544 | W83627EHF_REG_FAN_START_OUTPUT[i]); |
| 545 | data->fan_stop_output[i] = w83627ehf_read_value(data, | ||
| 546 | W83627EHF_REG_FAN_STOP_OUTPUT[i]); | ||
| 534 | data->fan_stop_time[i] = w83627ehf_read_value(data, | 547 | data->fan_stop_time[i] = w83627ehf_read_value(data, |
| 535 | W83627EHF_REG_FAN_STOP_TIME[i]); | 548 | W83627EHF_REG_FAN_STOP_TIME[i]); |
| 536 | data->target_temp[i] = | 549 | data->target_temp[i] = |
| @@ -976,7 +989,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, | |||
| 976 | u32 val = simple_strtoul(buf, NULL, 10); | 989 | u32 val = simple_strtoul(buf, NULL, 10); |
| 977 | u16 reg; | 990 | u16 reg; |
| 978 | 991 | ||
| 979 | if (!val || (val > 2)) /* only modes 1 and 2 are supported */ | 992 | if (!val || (val > 4)) |
| 980 | return -EINVAL; | 993 | return -EINVAL; |
| 981 | mutex_lock(&data->update_lock); | 994 | mutex_lock(&data->update_lock); |
| 982 | reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); | 995 | reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); |
| @@ -1118,7 +1131,10 @@ store_##reg(struct device *dev, struct device_attribute *attr, \ | |||
| 1118 | return count; \ | 1131 | return count; \ |
| 1119 | } | 1132 | } |
| 1120 | 1133 | ||
| 1121 | fan_functions(fan_min_output, FAN_MIN_OUTPUT) | 1134 | fan_functions(fan_start_output, FAN_START_OUTPUT) |
| 1135 | fan_functions(fan_stop_output, FAN_STOP_OUTPUT) | ||
| 1136 | fan_functions(fan_max_output, FAN_MAX_OUTPUT) | ||
| 1137 | fan_functions(fan_step_output, FAN_STEP_OUTPUT) | ||
| 1122 | 1138 | ||
| 1123 | #define fan_time_functions(reg, REG) \ | 1139 | #define fan_time_functions(reg, REG) \ |
| 1124 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ | 1140 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ |
| @@ -1161,8 +1177,14 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |||
| 1161 | static struct sensor_device_attribute sda_sf3_arrays_fan4[] = { | 1177 | static struct sensor_device_attribute sda_sf3_arrays_fan4[] = { |
| 1162 | SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, | 1178 | SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, |
| 1163 | store_fan_stop_time, 3), | 1179 | store_fan_stop_time, 3), |
| 1164 | SENSOR_ATTR(pwm4_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | 1180 | SENSOR_ATTR(pwm4_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, |
| 1165 | store_fan_min_output, 3), | 1181 | store_fan_start_output, 3), |
| 1182 | SENSOR_ATTR(pwm4_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, | ||
| 1183 | store_fan_stop_output, 3), | ||
| 1184 | SENSOR_ATTR(pwm4_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | ||
| 1185 | store_fan_max_output, 3), | ||
| 1186 | SENSOR_ATTR(pwm4_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | ||
| 1187 | store_fan_step_output, 3), | ||
| 1166 | }; | 1188 | }; |
| 1167 | 1189 | ||
| 1168 | static struct sensor_device_attribute sda_sf3_arrays[] = { | 1190 | static struct sensor_device_attribute sda_sf3_arrays[] = { |
| @@ -1172,12 +1194,24 @@ static struct sensor_device_attribute sda_sf3_arrays[] = { | |||
| 1172 | store_fan_stop_time, 1), | 1194 | store_fan_stop_time, 1), |
| 1173 | SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, | 1195 | SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, |
| 1174 | store_fan_stop_time, 2), | 1196 | store_fan_stop_time, 2), |
| 1175 | SENSOR_ATTR(pwm1_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | 1197 | SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, |
| 1176 | store_fan_min_output, 0), | 1198 | store_fan_start_output, 0), |
| 1177 | SENSOR_ATTR(pwm2_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | 1199 | SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, |
| 1178 | store_fan_min_output, 1), | 1200 | store_fan_start_output, 1), |
| 1179 | SENSOR_ATTR(pwm3_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | 1201 | SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, |
| 1180 | store_fan_min_output, 2), | 1202 | store_fan_start_output, 2), |
| 1203 | SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, | ||
| 1204 | store_fan_stop_output, 0), | ||
| 1205 | SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, | ||
| 1206 | store_fan_stop_output, 1), | ||
| 1207 | SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, | ||
| 1208 | store_fan_stop_output, 2), | ||
| 1209 | |||
| 1210 | /* pwm1 and pwm3 don't support max and step settings */ | ||
| 1211 | SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | ||
| 1212 | store_fan_max_output, 1), | ||
| 1213 | SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | ||
| 1214 | store_fan_step_output, 1), | ||
| 1181 | }; | 1215 | }; |
| 1182 | 1216 | ||
| 1183 | static ssize_t | 1217 | static ssize_t |
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 7ab7967da0a0..05f9225b6f94 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
| @@ -56,9 +56,10 @@ | |||
| 56 | /* Addresses to scan */ | 56 | /* Addresses to scan */ |
| 57 | static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | 57 | static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, |
| 58 | 0x2e, 0x2f, I2C_CLIENT_END }; | 58 | 0x2e, 0x2f, I2C_CLIENT_END }; |
| 59 | /* Insmod parameters */ | ||
| 60 | I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f); | ||
| 61 | 59 | ||
| 60 | enum chips { w83781d, w83782d, w83783s, as99127f }; | ||
| 61 | |||
| 62 | /* Insmod parameters */ | ||
| 62 | static unsigned short force_subclients[4]; | 63 | static unsigned short force_subclients[4]; |
| 63 | module_param_array(force_subclients, short, NULL, 0); | 64 | module_param_array(force_subclients, short, NULL, 0); |
| 64 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " | 65 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " |
| @@ -1051,8 +1052,7 @@ w83781d_create_files(struct device *dev, int kind, int is_isa) | |||
| 1051 | 1052 | ||
| 1052 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1053 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1053 | static int | 1054 | static int |
| 1054 | w83781d_detect(struct i2c_client *client, int kind, | 1055 | w83781d_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 1055 | struct i2c_board_info *info) | ||
| 1056 | { | 1056 | { |
| 1057 | int val1, val2; | 1057 | int val1, val2; |
| 1058 | struct w83781d_data *isa = w83781d_data_if_isa(); | 1058 | struct w83781d_data *isa = w83781d_data_if_isa(); |
| @@ -1537,7 +1537,7 @@ static struct i2c_driver w83781d_driver = { | |||
| 1537 | .remove = w83781d_remove, | 1537 | .remove = w83781d_remove, |
| 1538 | .id_table = w83781d_ids, | 1538 | .id_table = w83781d_ids, |
| 1539 | .detect = w83781d_detect, | 1539 | .detect = w83781d_detect, |
| 1540 | .address_data = &addr_data, | 1540 | .address_list = normal_i2c, |
| 1541 | }; | 1541 | }; |
| 1542 | 1542 | ||
| 1543 | /* | 1543 | /* |
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 0410bf12c521..400a88bde278 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c | |||
| @@ -52,7 +52,6 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | |||
| 52 | I2C_CLIENT_END }; | 52 | I2C_CLIENT_END }; |
| 53 | 53 | ||
| 54 | /* Insmod parameters */ | 54 | /* Insmod parameters */ |
| 55 | I2C_CLIENT_INSMOD_1(w83791d); | ||
| 56 | 55 | ||
| 57 | static unsigned short force_subclients[4]; | 56 | static unsigned short force_subclients[4]; |
| 58 | module_param_array(force_subclients, short, NULL, 0); | 57 | module_param_array(force_subclients, short, NULL, 0); |
| @@ -326,7 +325,7 @@ struct w83791d_data { | |||
| 326 | 325 | ||
| 327 | static int w83791d_probe(struct i2c_client *client, | 326 | static int w83791d_probe(struct i2c_client *client, |
| 328 | const struct i2c_device_id *id); | 327 | const struct i2c_device_id *id); |
| 329 | static int w83791d_detect(struct i2c_client *client, int kind, | 328 | static int w83791d_detect(struct i2c_client *client, |
| 330 | struct i2c_board_info *info); | 329 | struct i2c_board_info *info); |
| 331 | static int w83791d_remove(struct i2c_client *client); | 330 | static int w83791d_remove(struct i2c_client *client); |
| 332 | 331 | ||
| @@ -341,7 +340,7 @@ static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); | |||
| 341 | static void w83791d_init_client(struct i2c_client *client); | 340 | static void w83791d_init_client(struct i2c_client *client); |
| 342 | 341 | ||
| 343 | static const struct i2c_device_id w83791d_id[] = { | 342 | static const struct i2c_device_id w83791d_id[] = { |
| 344 | { "w83791d", w83791d }, | 343 | { "w83791d", 0 }, |
| 345 | { } | 344 | { } |
| 346 | }; | 345 | }; |
| 347 | MODULE_DEVICE_TABLE(i2c, w83791d_id); | 346 | MODULE_DEVICE_TABLE(i2c, w83791d_id); |
| @@ -355,7 +354,7 @@ static struct i2c_driver w83791d_driver = { | |||
| 355 | .remove = w83791d_remove, | 354 | .remove = w83791d_remove, |
| 356 | .id_table = w83791d_id, | 355 | .id_table = w83791d_id, |
| 357 | .detect = w83791d_detect, | 356 | .detect = w83791d_detect, |
| 358 | .address_data = &addr_data, | 357 | .address_list = normal_i2c, |
| 359 | }; | 358 | }; |
| 360 | 359 | ||
| 361 | /* following are the sysfs callback functions */ | 360 | /* following are the sysfs callback functions */ |
| @@ -1259,7 +1258,7 @@ error_sc_0: | |||
| 1259 | 1258 | ||
| 1260 | 1259 | ||
| 1261 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1260 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1262 | static int w83791d_detect(struct i2c_client *client, int kind, | 1261 | static int w83791d_detect(struct i2c_client *client, |
| 1263 | struct i2c_board_info *info) | 1262 | struct i2c_board_info *info) |
| 1264 | { | 1263 | { |
| 1265 | struct i2c_adapter *adapter = client->adapter; | 1264 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 38978851333f..679718e6b017 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
| @@ -50,7 +50,6 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | |||
| 50 | I2C_CLIENT_END }; | 50 | I2C_CLIENT_END }; |
| 51 | 51 | ||
| 52 | /* Insmod parameters */ | 52 | /* Insmod parameters */ |
| 53 | I2C_CLIENT_INSMOD_1(w83792d); | ||
| 54 | 53 | ||
| 55 | static unsigned short force_subclients[4]; | 54 | static unsigned short force_subclients[4]; |
| 56 | module_param_array(force_subclients, short, NULL, 0); | 55 | module_param_array(force_subclients, short, NULL, 0); |
| @@ -302,7 +301,7 @@ struct w83792d_data { | |||
| 302 | 301 | ||
| 303 | static int w83792d_probe(struct i2c_client *client, | 302 | static int w83792d_probe(struct i2c_client *client, |
| 304 | const struct i2c_device_id *id); | 303 | const struct i2c_device_id *id); |
| 305 | static int w83792d_detect(struct i2c_client *client, int kind, | 304 | static int w83792d_detect(struct i2c_client *client, |
| 306 | struct i2c_board_info *info); | 305 | struct i2c_board_info *info); |
| 307 | static int w83792d_remove(struct i2c_client *client); | 306 | static int w83792d_remove(struct i2c_client *client); |
| 308 | static struct w83792d_data *w83792d_update_device(struct device *dev); | 307 | static struct w83792d_data *w83792d_update_device(struct device *dev); |
| @@ -314,7 +313,7 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); | |||
| 314 | static void w83792d_init_client(struct i2c_client *client); | 313 | static void w83792d_init_client(struct i2c_client *client); |
| 315 | 314 | ||
| 316 | static const struct i2c_device_id w83792d_id[] = { | 315 | static const struct i2c_device_id w83792d_id[] = { |
| 317 | { "w83792d", w83792d }, | 316 | { "w83792d", 0 }, |
| 318 | { } | 317 | { } |
| 319 | }; | 318 | }; |
| 320 | MODULE_DEVICE_TABLE(i2c, w83792d_id); | 319 | MODULE_DEVICE_TABLE(i2c, w83792d_id); |
| @@ -328,7 +327,7 @@ static struct i2c_driver w83792d_driver = { | |||
| 328 | .remove = w83792d_remove, | 327 | .remove = w83792d_remove, |
| 329 | .id_table = w83792d_id, | 328 | .id_table = w83792d_id, |
| 330 | .detect = w83792d_detect, | 329 | .detect = w83792d_detect, |
| 331 | .address_data = &addr_data, | 330 | .address_list = normal_i2c, |
| 332 | }; | 331 | }; |
| 333 | 332 | ||
| 334 | static inline long in_count_from_reg(int nr, struct w83792d_data *data) | 333 | static inline long in_count_from_reg(int nr, struct w83792d_data *data) |
| @@ -1263,7 +1262,7 @@ static const struct attribute_group w83792d_group = { | |||
| 1263 | 1262 | ||
| 1264 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1263 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1265 | static int | 1264 | static int |
| 1266 | w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) | 1265 | w83792d_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 1267 | { | 1266 | { |
| 1268 | struct i2c_adapter *adapter = client->adapter; | 1267 | struct i2c_adapter *adapter = client->adapter; |
| 1269 | int val1, val2; | 1268 | int val1, val2; |
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 80a2191bf127..9a2022b67495 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c | |||
| @@ -41,7 +41,6 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | |||
| 41 | I2C_CLIENT_END }; | 41 | I2C_CLIENT_END }; |
| 42 | 42 | ||
| 43 | /* Insmod parameters */ | 43 | /* Insmod parameters */ |
| 44 | I2C_CLIENT_INSMOD_1(w83793); | ||
| 45 | 44 | ||
| 46 | static unsigned short force_subclients[4]; | 45 | static unsigned short force_subclients[4]; |
| 47 | module_param_array(force_subclients, short, NULL, 0); | 46 | module_param_array(force_subclients, short, NULL, 0); |
| @@ -230,7 +229,7 @@ static u8 w83793_read_value(struct i2c_client *client, u16 reg); | |||
| 230 | static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); | 229 | static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); |
| 231 | static int w83793_probe(struct i2c_client *client, | 230 | static int w83793_probe(struct i2c_client *client, |
| 232 | const struct i2c_device_id *id); | 231 | const struct i2c_device_id *id); |
| 233 | static int w83793_detect(struct i2c_client *client, int kind, | 232 | static int w83793_detect(struct i2c_client *client, |
| 234 | struct i2c_board_info *info); | 233 | struct i2c_board_info *info); |
| 235 | static int w83793_remove(struct i2c_client *client); | 234 | static int w83793_remove(struct i2c_client *client); |
| 236 | static void w83793_init_client(struct i2c_client *client); | 235 | static void w83793_init_client(struct i2c_client *client); |
| @@ -238,7 +237,7 @@ static void w83793_update_nonvolatile(struct device *dev); | |||
| 238 | static struct w83793_data *w83793_update_device(struct device *dev); | 237 | static struct w83793_data *w83793_update_device(struct device *dev); |
| 239 | 238 | ||
| 240 | static const struct i2c_device_id w83793_id[] = { | 239 | static const struct i2c_device_id w83793_id[] = { |
| 241 | { "w83793", w83793 }, | 240 | { "w83793", 0 }, |
| 242 | { } | 241 | { } |
| 243 | }; | 242 | }; |
| 244 | MODULE_DEVICE_TABLE(i2c, w83793_id); | 243 | MODULE_DEVICE_TABLE(i2c, w83793_id); |
| @@ -252,7 +251,7 @@ static struct i2c_driver w83793_driver = { | |||
| 252 | .remove = w83793_remove, | 251 | .remove = w83793_remove, |
| 253 | .id_table = w83793_id, | 252 | .id_table = w83793_id, |
| 254 | .detect = w83793_detect, | 253 | .detect = w83793_detect, |
| 255 | .address_data = &addr_data, | 254 | .address_list = normal_i2c, |
| 256 | }; | 255 | }; |
| 257 | 256 | ||
| 258 | static ssize_t | 257 | static ssize_t |
| @@ -1161,7 +1160,7 @@ ERROR_SC_0: | |||
| 1161 | } | 1160 | } |
| 1162 | 1161 | ||
| 1163 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 1162 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 1164 | static int w83793_detect(struct i2c_client *client, int kind, | 1163 | static int w83793_detect(struct i2c_client *client, |
| 1165 | struct i2c_board_info *info) | 1164 | struct i2c_board_info *info) |
| 1166 | { | 1165 | { |
| 1167 | u8 tmp, bank, chip_id; | 1166 | u8 tmp, bank, chip_id; |
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index 9b6c4c10fba7..20781def65ed 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c | |||
| @@ -52,12 +52,6 @@ | |||
| 52 | static const unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END }; | 52 | static const unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END }; |
| 53 | 53 | ||
| 54 | /* | 54 | /* |
| 55 | * Insmod parameters | ||
| 56 | */ | ||
| 57 | |||
| 58 | I2C_CLIENT_INSMOD_1(w83l785ts); | ||
| 59 | |||
| 60 | /* | ||
| 61 | * The W83L785TS-S registers | 55 | * The W83L785TS-S registers |
| 62 | * Manufacturer ID is 0x5CA3 for Winbond. | 56 | * Manufacturer ID is 0x5CA3 for Winbond. |
| 63 | */ | 57 | */ |
| @@ -83,7 +77,7 @@ I2C_CLIENT_INSMOD_1(w83l785ts); | |||
| 83 | 77 | ||
| 84 | static int w83l785ts_probe(struct i2c_client *client, | 78 | static int w83l785ts_probe(struct i2c_client *client, |
| 85 | const struct i2c_device_id *id); | 79 | const struct i2c_device_id *id); |
| 86 | static int w83l785ts_detect(struct i2c_client *client, int kind, | 80 | static int w83l785ts_detect(struct i2c_client *client, |
| 87 | struct i2c_board_info *info); | 81 | struct i2c_board_info *info); |
| 88 | static int w83l785ts_remove(struct i2c_client *client); | 82 | static int w83l785ts_remove(struct i2c_client *client); |
| 89 | static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval); | 83 | static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval); |
| @@ -94,7 +88,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); | |||
| 94 | */ | 88 | */ |
| 95 | 89 | ||
| 96 | static const struct i2c_device_id w83l785ts_id[] = { | 90 | static const struct i2c_device_id w83l785ts_id[] = { |
| 97 | { "w83l785ts", w83l785ts }, | 91 | { "w83l785ts", 0 }, |
| 98 | { } | 92 | { } |
| 99 | }; | 93 | }; |
| 100 | MODULE_DEVICE_TABLE(i2c, w83l785ts_id); | 94 | MODULE_DEVICE_TABLE(i2c, w83l785ts_id); |
| @@ -108,7 +102,7 @@ static struct i2c_driver w83l785ts_driver = { | |||
| 108 | .remove = w83l785ts_remove, | 102 | .remove = w83l785ts_remove, |
| 109 | .id_table = w83l785ts_id, | 103 | .id_table = w83l785ts_id, |
| 110 | .detect = w83l785ts_detect, | 104 | .detect = w83l785ts_detect, |
| 111 | .address_data = &addr_data, | 105 | .address_list = normal_i2c, |
| 112 | }; | 106 | }; |
| 113 | 107 | ||
| 114 | /* | 108 | /* |
| @@ -146,7 +140,7 @@ static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1); | |||
| 146 | */ | 140 | */ |
| 147 | 141 | ||
| 148 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 142 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 149 | static int w83l785ts_detect(struct i2c_client *client, int kind, | 143 | static int w83l785ts_detect(struct i2c_client *client, |
| 150 | struct i2c_board_info *info) | 144 | struct i2c_board_info *info) |
| 151 | { | 145 | { |
| 152 | struct i2c_adapter *adapter = client->adapter; | 146 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 27da7d2b15fb..0254e181893d 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c | |||
| @@ -38,7 +38,6 @@ | |||
| 38 | static const unsigned short normal_i2c[] = { 0x2e, 0x2f, I2C_CLIENT_END }; | 38 | static const unsigned short normal_i2c[] = { 0x2e, 0x2f, I2C_CLIENT_END }; |
| 39 | 39 | ||
| 40 | /* Insmod parameters */ | 40 | /* Insmod parameters */ |
| 41 | I2C_CLIENT_INSMOD_1(w83l786ng); | ||
| 42 | 41 | ||
| 43 | static int reset; | 42 | static int reset; |
| 44 | module_param(reset, bool, 0); | 43 | module_param(reset, bool, 0); |
| @@ -147,14 +146,14 @@ struct w83l786ng_data { | |||
| 147 | 146 | ||
| 148 | static int w83l786ng_probe(struct i2c_client *client, | 147 | static int w83l786ng_probe(struct i2c_client *client, |
| 149 | const struct i2c_device_id *id); | 148 | const struct i2c_device_id *id); |
| 150 | static int w83l786ng_detect(struct i2c_client *client, int kind, | 149 | static int w83l786ng_detect(struct i2c_client *client, |
| 151 | struct i2c_board_info *info); | 150 | struct i2c_board_info *info); |
| 152 | static int w83l786ng_remove(struct i2c_client *client); | 151 | static int w83l786ng_remove(struct i2c_client *client); |
| 153 | static void w83l786ng_init_client(struct i2c_client *client); | 152 | static void w83l786ng_init_client(struct i2c_client *client); |
| 154 | static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); | 153 | static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); |
| 155 | 154 | ||
| 156 | static const struct i2c_device_id w83l786ng_id[] = { | 155 | static const struct i2c_device_id w83l786ng_id[] = { |
| 157 | { "w83l786ng", w83l786ng }, | 156 | { "w83l786ng", 0 }, |
| 158 | { } | 157 | { } |
| 159 | }; | 158 | }; |
| 160 | MODULE_DEVICE_TABLE(i2c, w83l786ng_id); | 159 | MODULE_DEVICE_TABLE(i2c, w83l786ng_id); |
| @@ -168,7 +167,7 @@ static struct i2c_driver w83l786ng_driver = { | |||
| 168 | .remove = w83l786ng_remove, | 167 | .remove = w83l786ng_remove, |
| 169 | .id_table = w83l786ng_id, | 168 | .id_table = w83l786ng_id, |
| 170 | .detect = w83l786ng_detect, | 169 | .detect = w83l786ng_detect, |
| 171 | .address_data = &addr_data, | 170 | .address_list = normal_i2c, |
| 172 | }; | 171 | }; |
| 173 | 172 | ||
| 174 | static u8 | 173 | static u8 |
| @@ -586,8 +585,7 @@ static const struct attribute_group w83l786ng_group = { | |||
| 586 | }; | 585 | }; |
| 587 | 586 | ||
| 588 | static int | 587 | static int |
| 589 | w83l786ng_detect(struct i2c_client *client, int kind, | 588 | w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 590 | struct i2c_board_info *info) | ||
| 591 | { | 589 | { |
| 592 | struct i2c_adapter *adapter = client->adapter; | 590 | struct i2c_adapter *adapter = client->adapter; |
| 593 | u16 man_id; | 591 | u16 man_id; |
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 049555777f67..7647a20523a0 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
| @@ -1155,7 +1155,7 @@ static int i2c_pxa_resume_noirq(struct device *dev) | |||
| 1155 | return 0; | 1155 | return 0; |
| 1156 | } | 1156 | } |
| 1157 | 1157 | ||
| 1158 | static struct dev_pm_ops i2c_pxa_dev_pm_ops = { | 1158 | static const struct dev_pm_ops i2c_pxa_dev_pm_ops = { |
| 1159 | .suspend_noirq = i2c_pxa_suspend_noirq, | 1159 | .suspend_noirq = i2c_pxa_suspend_noirq, |
| 1160 | .resume_noirq = i2c_pxa_resume_noirq, | 1160 | .resume_noirq = i2c_pxa_resume_noirq, |
| 1161 | }; | 1161 | }; |
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 96aafb91b69a..1d8c98613fa0 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
| @@ -967,7 +967,7 @@ static int s3c24xx_i2c_resume(struct device *dev) | |||
| 967 | return 0; | 967 | return 0; |
| 968 | } | 968 | } |
| 969 | 969 | ||
| 970 | static struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { | 970 | static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { |
| 971 | .suspend_noirq = s3c24xx_i2c_suspend_noirq, | 971 | .suspend_noirq = s3c24xx_i2c_suspend_noirq, |
| 972 | .resume = s3c24xx_i2c_resume, | 972 | .resume = s3c24xx_i2c_resume, |
| 973 | }; | 973 | }; |
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 86a9d4e81472..ccc46418ef7f 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
| @@ -647,7 +647,7 @@ static int sh_mobile_i2c_runtime_nop(struct device *dev) | |||
| 647 | return 0; | 647 | return 0; |
| 648 | } | 648 | } |
| 649 | 649 | ||
| 650 | static struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = { | 650 | static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = { |
| 651 | .runtime_suspend = sh_mobile_i2c_runtime_nop, | 651 | .runtime_suspend = sh_mobile_i2c_runtime_nop, |
| 652 | .runtime_resume = sh_mobile_i2c_runtime_nop, | 652 | .runtime_resume = sh_mobile_i2c_runtime_nop, |
| 653 | }; | 653 | }; |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 4f34823e86b1..0ac2f90ab840 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
| @@ -155,6 +155,35 @@ static void i2c_device_shutdown(struct device *dev) | |||
| 155 | driver->shutdown(client); | 155 | driver->shutdown(client); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | #ifdef CONFIG_SUSPEND | ||
| 159 | static int i2c_device_pm_suspend(struct device *dev) | ||
| 160 | { | ||
| 161 | const struct dev_pm_ops *pm; | ||
| 162 | |||
| 163 | if (!dev->driver) | ||
| 164 | return 0; | ||
| 165 | pm = dev->driver->pm; | ||
| 166 | if (!pm || !pm->suspend) | ||
| 167 | return 0; | ||
| 168 | return pm->suspend(dev); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int i2c_device_pm_resume(struct device *dev) | ||
| 172 | { | ||
| 173 | const struct dev_pm_ops *pm; | ||
| 174 | |||
| 175 | if (!dev->driver) | ||
| 176 | return 0; | ||
| 177 | pm = dev->driver->pm; | ||
| 178 | if (!pm || !pm->resume) | ||
| 179 | return 0; | ||
| 180 | return pm->resume(dev); | ||
| 181 | } | ||
| 182 | #else | ||
| 183 | #define i2c_device_pm_suspend NULL | ||
| 184 | #define i2c_device_pm_resume NULL | ||
| 185 | #endif | ||
| 186 | |||
| 158 | static int i2c_device_suspend(struct device *dev, pm_message_t mesg) | 187 | static int i2c_device_suspend(struct device *dev, pm_message_t mesg) |
| 159 | { | 188 | { |
| 160 | struct i2c_client *client = i2c_verify_client(dev); | 189 | struct i2c_client *client = i2c_verify_client(dev); |
| @@ -219,6 +248,11 @@ static const struct attribute_group *i2c_dev_attr_groups[] = { | |||
| 219 | NULL | 248 | NULL |
| 220 | }; | 249 | }; |
| 221 | 250 | ||
| 251 | const static struct dev_pm_ops i2c_device_pm_ops = { | ||
| 252 | .suspend = i2c_device_pm_suspend, | ||
| 253 | .resume = i2c_device_pm_resume, | ||
| 254 | }; | ||
| 255 | |||
| 222 | struct bus_type i2c_bus_type = { | 256 | struct bus_type i2c_bus_type = { |
| 223 | .name = "i2c", | 257 | .name = "i2c", |
| 224 | .match = i2c_device_match, | 258 | .match = i2c_device_match, |
| @@ -227,6 +261,7 @@ struct bus_type i2c_bus_type = { | |||
| 227 | .shutdown = i2c_device_shutdown, | 261 | .shutdown = i2c_device_shutdown, |
| 228 | .suspend = i2c_device_suspend, | 262 | .suspend = i2c_device_suspend, |
| 229 | .resume = i2c_device_resume, | 263 | .resume = i2c_device_resume, |
| 264 | .pm = &i2c_device_pm_ops, | ||
| 230 | }; | 265 | }; |
| 231 | EXPORT_SYMBOL_GPL(i2c_bus_type); | 266 | EXPORT_SYMBOL_GPL(i2c_bus_type); |
| 232 | 267 | ||
| @@ -1184,7 +1219,7 @@ static int i2c_detect_address(struct i2c_client *temp_client, | |||
| 1184 | /* Finally call the custom detection function */ | 1219 | /* Finally call the custom detection function */ |
| 1185 | memset(&info, 0, sizeof(struct i2c_board_info)); | 1220 | memset(&info, 0, sizeof(struct i2c_board_info)); |
| 1186 | info.addr = addr; | 1221 | info.addr = addr; |
| 1187 | err = driver->detect(temp_client, -1, &info); | 1222 | err = driver->detect(temp_client, &info); |
| 1188 | if (err) { | 1223 | if (err) { |
| 1189 | /* -ENODEV is returned if the detection fails. We catch it | 1224 | /* -ENODEV is returned if the detection fails. We catch it |
| 1190 | here as this isn't an error. */ | 1225 | here as this isn't an error. */ |
| @@ -1214,13 +1249,13 @@ static int i2c_detect_address(struct i2c_client *temp_client, | |||
| 1214 | 1249 | ||
| 1215 | static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | 1250 | static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) |
| 1216 | { | 1251 | { |
| 1217 | const struct i2c_client_address_data *address_data; | 1252 | const unsigned short *address_list; |
| 1218 | struct i2c_client *temp_client; | 1253 | struct i2c_client *temp_client; |
| 1219 | int i, err = 0; | 1254 | int i, err = 0; |
| 1220 | int adap_id = i2c_adapter_id(adapter); | 1255 | int adap_id = i2c_adapter_id(adapter); |
| 1221 | 1256 | ||
| 1222 | address_data = driver->address_data; | 1257 | address_list = driver->address_list; |
| 1223 | if (!driver->detect || !address_data) | 1258 | if (!driver->detect || !address_list) |
| 1224 | return 0; | 1259 | return 0; |
| 1225 | 1260 | ||
| 1226 | /* Set up a temporary client to help detect callback */ | 1261 | /* Set up a temporary client to help detect callback */ |
| @@ -1235,7 +1270,7 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | |||
| 1235 | 1270 | ||
| 1236 | /* Stop here if we can't use SMBUS_QUICK */ | 1271 | /* Stop here if we can't use SMBUS_QUICK */ |
| 1237 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { | 1272 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { |
| 1238 | if (address_data->normal_i2c[0] == I2C_CLIENT_END) | 1273 | if (address_list[0] == I2C_CLIENT_END) |
| 1239 | goto exit_free; | 1274 | goto exit_free; |
| 1240 | 1275 | ||
| 1241 | dev_warn(&adapter->dev, "SMBus Quick command not supported, " | 1276 | dev_warn(&adapter->dev, "SMBus Quick command not supported, " |
| @@ -1244,11 +1279,10 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) | |||
| 1244 | goto exit_free; | 1279 | goto exit_free; |
| 1245 | } | 1280 | } |
| 1246 | 1281 | ||
| 1247 | for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) { | 1282 | for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { |
| 1248 | dev_dbg(&adapter->dev, "found normal entry for adapter %d, " | 1283 | dev_dbg(&adapter->dev, "found normal entry for adapter %d, " |
| 1249 | "addr 0x%02x\n", adap_id, | 1284 | "addr 0x%02x\n", adap_id, address_list[i]); |
| 1250 | address_data->normal_i2c[i]); | 1285 | temp_client->addr = address_list[i]; |
| 1251 | temp_client->addr = address_data->normal_i2c[i]; | ||
| 1252 | err = i2c_detect_address(temp_client, driver); | 1286 | err = i2c_detect_address(temp_client, driver); |
| 1253 | if (err) | 1287 | if (err) |
| 1254 | goto exit_free; | 1288 | goto exit_free; |
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index d48c808d5928..1edb596d927b 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c | |||
| @@ -319,7 +319,7 @@ static int adp5588_resume(struct device *dev) | |||
| 319 | return 0; | 319 | return 0; |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | static struct dev_pm_ops adp5588_dev_pm_ops = { | 322 | static const struct dev_pm_ops adp5588_dev_pm_ops = { |
| 323 | .suspend = adp5588_suspend, | 323 | .suspend = adp5588_suspend, |
| 324 | .resume = adp5588_resume, | 324 | .resume = adp5588_resume, |
| 325 | }; | 325 | }; |
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 076111fc72d2..8e9380bfed40 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
| @@ -295,7 +295,7 @@ static int sh_keysc_resume(struct device *dev) | |||
| 295 | return 0; | 295 | return 0; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static struct dev_pm_ops sh_keysc_dev_pm_ops = { | 298 | static const struct dev_pm_ops sh_keysc_dev_pm_ops = { |
| 299 | .suspend = sh_keysc_suspend, | 299 | .suspend = sh_keysc_suspend, |
| 300 | .resume = sh_keysc_resume, | 300 | .resume = sh_keysc_resume, |
| 301 | }; | 301 | }; |
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index 690f3fafa03b..61d10177fa83 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c | |||
| @@ -247,7 +247,7 @@ static int bfin_rotary_resume(struct device *dev) | |||
| 247 | return 0; | 247 | return 0; |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | static struct dev_pm_ops bfin_rotary_pm_ops = { | 250 | static const struct dev_pm_ops bfin_rotary_pm_ops = { |
| 251 | .suspend = bfin_rotary_suspend, | 251 | .suspend = bfin_rotary_suspend, |
| 252 | .resume = bfin_rotary_resume, | 252 | .resume = bfin_rotary_resume, |
| 253 | }; | 253 | }; |
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 21cb755a54fb..ea4e1fd12651 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
| @@ -127,7 +127,7 @@ static void pcspkr_shutdown(struct platform_device *dev) | |||
| 127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); | 127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | static struct dev_pm_ops pcspkr_pm_ops = { | 130 | static const struct dev_pm_ops pcspkr_pm_ops = { |
| 131 | .suspend = pcspkr_suspend, | 131 | .suspend = pcspkr_suspend, |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c index 67fcd33595de..b79097e3028a 100644 --- a/drivers/input/touchscreen/pcap_ts.c +++ b/drivers/input/touchscreen/pcap_ts.c | |||
| @@ -233,7 +233,7 @@ static int pcap_ts_resume(struct device *dev) | |||
| 233 | return 0; | 233 | return 0; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static struct dev_pm_ops pcap_ts_pm_ops = { | 236 | static const struct dev_pm_ops pcap_ts_pm_ops = { |
| 237 | .suspend = pcap_ts_suspend, | 237 | .suspend = pcap_ts_suspend, |
| 238 | .resume = pcap_ts_resume, | 238 | .resume = pcap_ts_resume, |
| 239 | }; | 239 | }; |
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index f2cc13d76810..782f95822eab 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c | |||
| @@ -50,7 +50,7 @@ static ssize_t led_brightness_store(struct device *dev, | |||
| 50 | unsigned long state = simple_strtoul(buf, &after, 10); | 50 | unsigned long state = simple_strtoul(buf, &after, 10); |
| 51 | size_t count = after - buf; | 51 | size_t count = after - buf; |
| 52 | 52 | ||
| 53 | if (*after && isspace(*after)) | 53 | if (isspace(*after)) |
| 54 | count++; | 54 | count++; |
| 55 | 55 | ||
| 56 | if (count == size) { | 56 | if (count == size) { |
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 3b83406de752..38b3378be442 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c | |||
| @@ -83,7 +83,7 @@ static ssize_t led_delay_on_store(struct device *dev, | |||
| 83 | unsigned long state = simple_strtoul(buf, &after, 10); | 83 | unsigned long state = simple_strtoul(buf, &after, 10); |
| 84 | size_t count = after - buf; | 84 | size_t count = after - buf; |
| 85 | 85 | ||
| 86 | if (*after && isspace(*after)) | 86 | if (isspace(*after)) |
| 87 | count++; | 87 | count++; |
| 88 | 88 | ||
| 89 | if (count == size) { | 89 | if (count == size) { |
| @@ -127,7 +127,7 @@ static ssize_t led_delay_off_store(struct device *dev, | |||
| 127 | unsigned long state = simple_strtoul(buf, &after, 10); | 127 | unsigned long state = simple_strtoul(buf, &after, 10); |
| 128 | size_t count = after - buf; | 128 | size_t count = after - buf; |
| 129 | 129 | ||
| 130 | if (*after && isspace(*after)) | 130 | if (isspace(*after)) |
| 131 | count++; | 131 | count++; |
| 132 | 132 | ||
| 133 | if (count == size) { | 133 | if (count == size) { |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 1a6cb3c7822e..91976e8fae5f 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/blkdev.h> | 12 | #include <linux/blkdev.h> |
| 13 | #include <linux/namei.h> | 13 | #include <linux/namei.h> |
| 14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
| 15 | #include <linux/string.h> | ||
| 15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 17 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
| @@ -600,11 +601,8 @@ int dm_split_args(int *argc, char ***argvp, char *input) | |||
| 600 | return -ENOMEM; | 601 | return -ENOMEM; |
| 601 | 602 | ||
| 602 | while (1) { | 603 | while (1) { |
| 603 | start = end; | ||
| 604 | |||
| 605 | /* Skip whitespace */ | 604 | /* Skip whitespace */ |
| 606 | while (*start && isspace(*start)) | 605 | start = skip_spaces(end); |
| 607 | start++; | ||
| 608 | 606 | ||
| 609 | if (!*start) | 607 | if (!*start) |
| 610 | break; /* success, we hit the end */ | 608 | break; /* success, we hit the end */ |
diff --git a/drivers/md/md.c b/drivers/md/md.c index e1f3c1715cca..f4f5f82f9f53 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/buffer_head.h> /* for invalidate_bdev */ | 39 | #include <linux/buffer_head.h> /* for invalidate_bdev */ |
| 40 | #include <linux/poll.h> | 40 | #include <linux/poll.h> |
| 41 | #include <linux/ctype.h> | 41 | #include <linux/ctype.h> |
| 42 | #include <linux/string.h> | ||
| 42 | #include <linux/hdreg.h> | 43 | #include <linux/hdreg.h> |
| 43 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
| 44 | #include <linux/random.h> | 45 | #include <linux/random.h> |
| @@ -1935,15 +1936,11 @@ static void print_sb_1(struct mdp_superblock_1 *sb) | |||
| 1935 | 1936 | ||
| 1936 | uuid = sb->set_uuid; | 1937 | uuid = sb->set_uuid; |
| 1937 | printk(KERN_INFO | 1938 | printk(KERN_INFO |
| 1938 | "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x" | 1939 | "md: SB: (V:%u) (F:0x%08x) Array-ID:<%pU>\n" |
| 1939 | ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n" | ||
| 1940 | "md: Name: \"%s\" CT:%llu\n", | 1940 | "md: Name: \"%s\" CT:%llu\n", |
| 1941 | le32_to_cpu(sb->major_version), | 1941 | le32_to_cpu(sb->major_version), |
| 1942 | le32_to_cpu(sb->feature_map), | 1942 | le32_to_cpu(sb->feature_map), |
| 1943 | uuid[0], uuid[1], uuid[2], uuid[3], | 1943 | uuid, |
| 1944 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
| 1945 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
| 1946 | uuid[12], uuid[13], uuid[14], uuid[15], | ||
| 1947 | sb->set_name, | 1944 | sb->set_name, |
| 1948 | (unsigned long long)le64_to_cpu(sb->ctime) | 1945 | (unsigned long long)le64_to_cpu(sb->ctime) |
| 1949 | & MD_SUPERBLOCK_1_TIME_SEC_MASK); | 1946 | & MD_SUPERBLOCK_1_TIME_SEC_MASK); |
| @@ -1952,8 +1949,7 @@ static void print_sb_1(struct mdp_superblock_1 *sb) | |||
| 1952 | printk(KERN_INFO | 1949 | printk(KERN_INFO |
| 1953 | "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" | 1950 | "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" |
| 1954 | " RO:%llu\n" | 1951 | " RO:%llu\n" |
| 1955 | "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x" | 1952 | "md: Dev:%08x UUID: %pU\n" |
| 1956 | ":%02x%02x%02x%02x%02x%02x\n" | ||
| 1957 | "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" | 1953 | "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" |
| 1958 | "md: (MaxDev:%u) \n", | 1954 | "md: (MaxDev:%u) \n", |
| 1959 | le32_to_cpu(sb->level), | 1955 | le32_to_cpu(sb->level), |
| @@ -1966,10 +1962,7 @@ static void print_sb_1(struct mdp_superblock_1 *sb) | |||
| 1966 | (unsigned long long)le64_to_cpu(sb->super_offset), | 1962 | (unsigned long long)le64_to_cpu(sb->super_offset), |
| 1967 | (unsigned long long)le64_to_cpu(sb->recovery_offset), | 1963 | (unsigned long long)le64_to_cpu(sb->recovery_offset), |
| 1968 | le32_to_cpu(sb->dev_number), | 1964 | le32_to_cpu(sb->dev_number), |
| 1969 | uuid[0], uuid[1], uuid[2], uuid[3], | 1965 | uuid, |
| 1970 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
| 1971 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
| 1972 | uuid[12], uuid[13], uuid[14], uuid[15], | ||
| 1973 | sb->devflags, | 1966 | sb->devflags, |
| 1974 | (unsigned long long)le64_to_cpu(sb->utime) & MD_SUPERBLOCK_1_TIME_SEC_MASK, | 1967 | (unsigned long long)le64_to_cpu(sb->utime) & MD_SUPERBLOCK_1_TIME_SEC_MASK, |
| 1975 | (unsigned long long)le64_to_cpu(sb->events), | 1968 | (unsigned long long)le64_to_cpu(sb->events), |
| @@ -3439,8 +3432,7 @@ bitmap_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 3439 | } | 3432 | } |
| 3440 | if (*end && !isspace(*end)) break; | 3433 | if (*end && !isspace(*end)) break; |
| 3441 | bitmap_dirty_bits(mddev->bitmap, chunk, end_chunk); | 3434 | bitmap_dirty_bits(mddev->bitmap, chunk, end_chunk); |
| 3442 | buf = end; | 3435 | buf = skip_spaces(end); |
| 3443 | while (isspace(*buf)) buf++; | ||
| 3444 | } | 3436 | } |
| 3445 | bitmap_unplug(mddev->bitmap); /* flush the bits to disk */ | 3437 | bitmap_unplug(mddev->bitmap); /* flush the bits to disk */ |
| 3446 | out: | 3438 | out: |
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 12a1b3d7132d..c3916a42668e 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
| @@ -2127,7 +2127,7 @@ vpfe_resume(struct device *dev) | |||
| 2127 | return -1; | 2127 | return -1; |
| 2128 | } | 2128 | } |
| 2129 | 2129 | ||
| 2130 | static struct dev_pm_ops vpfe_dev_pm_ops = { | 2130 | static const struct dev_pm_ops vpfe_dev_pm_ops = { |
| 2131 | .suspend = vpfe_suspend, | 2131 | .suspend = vpfe_suspend, |
| 2132 | .resume = vpfe_resume, | 2132 | .resume = vpfe_resume, |
| 2133 | }; | 2133 | }; |
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index d947ee5e4eb4..78130721f578 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c | |||
| @@ -2107,7 +2107,7 @@ vpif_resume(struct device *dev) | |||
| 2107 | return -1; | 2107 | return -1; |
| 2108 | } | 2108 | } |
| 2109 | 2109 | ||
| 2110 | static struct dev_pm_ops vpif_dev_pm_ops = { | 2110 | static const struct dev_pm_ops vpif_dev_pm_ops = { |
| 2111 | .suspend = vpif_suspend, | 2111 | .suspend = vpif_suspend, |
| 2112 | .resume = vpif_resume, | 2112 | .resume = vpif_resume, |
| 2113 | }; | 2113 | }; |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index a4f3472d4db8..961e4484d721 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
| @@ -1825,7 +1825,7 @@ static int sh_mobile_ceu_runtime_nop(struct device *dev) | |||
| 1825 | return 0; | 1825 | return 0; |
| 1826 | } | 1826 | } |
| 1827 | 1827 | ||
| 1828 | static struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = { | 1828 | static const struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = { |
| 1829 | .runtime_suspend = sh_mobile_ceu_runtime_nop, | 1829 | .runtime_suspend = sh_mobile_ceu_runtime_nop, |
| 1830 | .runtime_resume = sh_mobile_ceu_runtime_nop, | 1830 | .runtime_resume = sh_mobile_ceu_runtime_nop, |
| 1831 | }; | 1831 | }; |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2c16ca6501d5..59f4ba1b7034 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -13,6 +13,20 @@ menuconfig MISC_DEVICES | |||
| 13 | 13 | ||
| 14 | if MISC_DEVICES | 14 | if MISC_DEVICES |
| 15 | 15 | ||
| 16 | config AD525X_DPOT | ||
| 17 | tristate "Analog Devices AD525x Digital Potentiometers" | ||
| 18 | depends on I2C && SYSFS | ||
| 19 | help | ||
| 20 | If you say yes here, you get support for the Analog Devices | ||
| 21 | AD5258, AD5259, AD5251, AD5252, AD5253, AD5254 and AD5255 | ||
| 22 | digital potentiometer chips. | ||
| 23 | |||
| 24 | See Documentation/misc-devices/ad525x_dpot.txt for the | ||
| 25 | userspace interface. | ||
| 26 | |||
| 27 | This driver can also be built as a module. If so, the module | ||
| 28 | will be called ad525x_dpot. | ||
| 29 | |||
| 16 | config ATMEL_PWM | 30 | config ATMEL_PWM |
| 17 | tristate "Atmel AT32/AT91 PWM support" | 31 | tristate "Atmel AT32/AT91 PWM support" |
| 18 | depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 | 32 | depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 |
| @@ -173,6 +187,30 @@ config SGI_XP | |||
| 173 | this feature will allow for direct communication between SSIs | 187 | this feature will allow for direct communication between SSIs |
| 174 | based on a network adapter and DMA messaging. | 188 | based on a network adapter and DMA messaging. |
| 175 | 189 | ||
| 190 | config CS5535_MFGPT | ||
| 191 | tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support" | ||
| 192 | depends on PCI | ||
| 193 | depends on X86 | ||
| 194 | default n | ||
| 195 | help | ||
| 196 | This driver provides access to MFGPT functionality for other | ||
| 197 | drivers that need timers. MFGPTs are available in the CS5535 and | ||
| 198 | CS5536 companion chips that are found in AMD Geode and several | ||
| 199 | other platforms. They have a better resolution and max interval | ||
| 200 | than the generic PIT, and are suitable for use as high-res timers. | ||
| 201 | You probably don't want to enable this manually; other drivers that | ||
| 202 | make use of it should enable it. | ||
| 203 | |||
| 204 | config CS5535_MFGPT_DEFAULT_IRQ | ||
| 205 | int | ||
| 206 | default 7 | ||
| 207 | help | ||
| 208 | MFGPTs on the CS5535 require an interrupt. The selected IRQ | ||
| 209 | can be overridden as a module option as well as by driver that | ||
| 210 | use the cs5535_mfgpt_ API; however, different architectures might | ||
| 211 | want to use a different IRQ by default. This is here for | ||
| 212 | architectures to set as necessary. | ||
| 213 | |||
| 176 | config HP_ILO | 214 | config HP_ILO |
| 177 | tristate "Channel interface driver for HP iLO/iLO2 processor" | 215 | tristate "Channel interface driver for HP iLO/iLO2 processor" |
| 178 | depends on PCI | 216 | depends on PCI |
| @@ -256,6 +294,16 @@ config DS1682 | |||
| 256 | This driver can also be built as a module. If so, the module | 294 | This driver can also be built as a module. If so, the module |
| 257 | will be called ds1682. | 295 | will be called ds1682. |
| 258 | 296 | ||
| 297 | config TI_DAC7512 | ||
| 298 | tristate "Texas Instruments DAC7512" | ||
| 299 | depends on SPI && SYSFS | ||
| 300 | help | ||
| 301 | If you say yes here you get support for the Texas Instruments | ||
| 302 | DAC7512 16-bit digital-to-analog converter. | ||
| 303 | |||
| 304 | This driver can also be built as a module. If so, the module | ||
| 305 | will be calles ti_dac7512. | ||
| 306 | |||
| 259 | source "drivers/misc/c2port/Kconfig" | 307 | source "drivers/misc/c2port/Kconfig" |
| 260 | source "drivers/misc/eeprom/Kconfig" | 308 | source "drivers/misc/eeprom/Kconfig" |
| 261 | source "drivers/misc/cb710/Kconfig" | 309 | source "drivers/misc/cb710/Kconfig" |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 906a0edcea40..049ff2482f30 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_IBM_ASM) += ibmasm/ | 5 | obj-$(CONFIG_IBM_ASM) += ibmasm/ |
| 6 | obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ | 6 | obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ |
| 7 | obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o | ||
| 7 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o | 8 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o |
| 8 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o | 9 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
| 9 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | 10 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o |
| @@ -17,10 +18,12 @@ obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o | |||
| 17 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | 18 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o |
| 18 | obj-$(CONFIG_SGI_XP) += sgi-xp/ | 19 | obj-$(CONFIG_SGI_XP) += sgi-xp/ |
| 19 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ | 20 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ |
| 21 | obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o | ||
| 20 | obj-$(CONFIG_HP_ILO) += hpilo.o | 22 | obj-$(CONFIG_HP_ILO) += hpilo.o |
| 21 | obj-$(CONFIG_ISL29003) += isl29003.o | 23 | obj-$(CONFIG_ISL29003) += isl29003.o |
| 22 | obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o | 24 | obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o |
| 23 | obj-$(CONFIG_DS1682) += ds1682.o | 25 | obj-$(CONFIG_DS1682) += ds1682.o |
| 26 | obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o | ||
| 24 | obj-$(CONFIG_C2PORT) += c2port/ | 27 | obj-$(CONFIG_C2PORT) += c2port/ |
| 25 | obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ | 28 | obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ |
| 26 | obj-y += eeprom/ | 29 | obj-y += eeprom/ |
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c new file mode 100644 index 000000000000..30a59f2bacd2 --- /dev/null +++ b/drivers/misc/ad525x_dpot.c | |||
| @@ -0,0 +1,666 @@ | |||
| 1 | /* | ||
| 2 | * ad525x_dpot: Driver for the Analog Devices AD525x digital potentiometers | ||
| 3 | * Copyright (c) 2009 Analog Devices, Inc. | ||
| 4 | * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> | ||
| 5 | * | ||
| 6 | * DEVID #Wipers #Positions Resistor Options (kOhm) | ||
| 7 | * AD5258 1 64 1, 10, 50, 100 | ||
| 8 | * AD5259 1 256 5, 10, 50, 100 | ||
| 9 | * AD5251 2 64 1, 10, 50, 100 | ||
| 10 | * AD5252 2 256 1, 10, 50, 100 | ||
| 11 | * AD5255 3 512 25, 250 | ||
| 12 | * AD5253 4 64 1, 10, 50, 100 | ||
| 13 | * AD5254 4 256 1, 10, 50, 100 | ||
| 14 | * | ||
| 15 | * See Documentation/misc-devices/ad525x_dpot.txt for more info. | ||
| 16 | * | ||
| 17 | * derived from ad5258.c | ||
| 18 | * Copyright (c) 2009 Cyber Switching, Inc. | ||
| 19 | * Author: Chris Verges <chrisv@cyberswitching.com> | ||
| 20 | * | ||
| 21 | * derived from ad5252.c | ||
| 22 | * Copyright (c) 2006 Michael Hennerich <hennerich@blackfin.uclinux.org> | ||
| 23 | * | ||
| 24 | * Licensed under the GPL-2 or later. | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/device.h> | ||
| 29 | #include <linux/kernel.h> | ||
| 30 | #include <linux/init.h> | ||
| 31 | #include <linux/slab.h> | ||
| 32 | #include <linux/i2c.h> | ||
| 33 | #include <linux/delay.h> | ||
| 34 | |||
| 35 | #define DRIVER_NAME "ad525x_dpot" | ||
| 36 | #define DRIVER_VERSION "0.1" | ||
| 37 | |||
| 38 | enum dpot_devid { | ||
| 39 | AD5258_ID, | ||
| 40 | AD5259_ID, | ||
| 41 | AD5251_ID, | ||
| 42 | AD5252_ID, | ||
| 43 | AD5253_ID, | ||
| 44 | AD5254_ID, | ||
| 45 | AD5255_ID, | ||
| 46 | }; | ||
| 47 | |||
| 48 | #define AD5258_MAX_POSITION 64 | ||
| 49 | #define AD5259_MAX_POSITION 256 | ||
| 50 | #define AD5251_MAX_POSITION 64 | ||
| 51 | #define AD5252_MAX_POSITION 256 | ||
| 52 | #define AD5253_MAX_POSITION 64 | ||
| 53 | #define AD5254_MAX_POSITION 256 | ||
| 54 | #define AD5255_MAX_POSITION 512 | ||
| 55 | |||
| 56 | #define AD525X_RDAC0 0 | ||
| 57 | #define AD525X_RDAC1 1 | ||
| 58 | #define AD525X_RDAC2 2 | ||
| 59 | #define AD525X_RDAC3 3 | ||
| 60 | |||
| 61 | #define AD525X_REG_TOL 0x18 | ||
| 62 | #define AD525X_TOL_RDAC0 (AD525X_REG_TOL | AD525X_RDAC0) | ||
| 63 | #define AD525X_TOL_RDAC1 (AD525X_REG_TOL | AD525X_RDAC1) | ||
| 64 | #define AD525X_TOL_RDAC2 (AD525X_REG_TOL | AD525X_RDAC2) | ||
| 65 | #define AD525X_TOL_RDAC3 (AD525X_REG_TOL | AD525X_RDAC3) | ||
| 66 | |||
| 67 | /* RDAC-to-EEPROM Interface Commands */ | ||
| 68 | #define AD525X_I2C_RDAC (0x00 << 5) | ||
| 69 | #define AD525X_I2C_EEPROM (0x01 << 5) | ||
| 70 | #define AD525X_I2C_CMD (0x80) | ||
| 71 | |||
| 72 | #define AD525X_DEC_ALL_6DB (AD525X_I2C_CMD | (0x4 << 3)) | ||
| 73 | #define AD525X_INC_ALL_6DB (AD525X_I2C_CMD | (0x9 << 3)) | ||
| 74 | #define AD525X_DEC_ALL (AD525X_I2C_CMD | (0x6 << 3)) | ||
| 75 | #define AD525X_INC_ALL (AD525X_I2C_CMD | (0xB << 3)) | ||
| 76 | |||
| 77 | static s32 ad525x_read(struct i2c_client *client, u8 reg); | ||
| 78 | static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value); | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Client data (each client gets its own) | ||
| 82 | */ | ||
| 83 | |||
| 84 | struct dpot_data { | ||
| 85 | struct mutex update_lock; | ||
| 86 | unsigned rdac_mask; | ||
| 87 | unsigned max_pos; | ||
| 88 | unsigned devid; | ||
| 89 | }; | ||
| 90 | |||
| 91 | /* sysfs functions */ | ||
| 92 | |||
| 93 | static ssize_t sysfs_show_reg(struct device *dev, | ||
| 94 | struct device_attribute *attr, char *buf, u32 reg) | ||
| 95 | { | ||
| 96 | struct i2c_client *client = to_i2c_client(dev); | ||
| 97 | struct dpot_data *data = i2c_get_clientdata(client); | ||
| 98 | s32 value; | ||
| 99 | |||
| 100 | mutex_lock(&data->update_lock); | ||
| 101 | value = ad525x_read(client, reg); | ||
| 102 | mutex_unlock(&data->update_lock); | ||
| 103 | |||
| 104 | if (value < 0) | ||
| 105 | return -EINVAL; | ||
| 106 | /* | ||
| 107 | * Let someone else deal with converting this ... | ||
| 108 | * the tolerance is a two-byte value where the MSB | ||
| 109 | * is a sign + integer value, and the LSB is a | ||
| 110 | * decimal value. See page 18 of the AD5258 | ||
| 111 | * datasheet (Rev. A) for more details. | ||
| 112 | */ | ||
| 113 | |||
| 114 | if (reg & AD525X_REG_TOL) | ||
| 115 | return sprintf(buf, "0x%04x\n", value & 0xFFFF); | ||
| 116 | else | ||
| 117 | return sprintf(buf, "%u\n", value & data->rdac_mask); | ||
| 118 | } | ||
| 119 | |||
| 120 | static ssize_t sysfs_set_reg(struct device *dev, | ||
| 121 | struct device_attribute *attr, | ||
| 122 | const char *buf, size_t count, u32 reg) | ||
| 123 | { | ||
| 124 | struct i2c_client *client = to_i2c_client(dev); | ||
| 125 | struct dpot_data *data = i2c_get_clientdata(client); | ||
| 126 | unsigned long value; | ||
| 127 | int err; | ||
| 128 | |||
| 129 | err = strict_strtoul(buf, 10, &value); | ||
| 130 | if (err) | ||
| 131 | return err; | ||
| 132 | |||
| 133 | if (value > data->rdac_mask) | ||
| 134 | value = data->rdac_mask; | ||
| 135 | |||
| 136 | mutex_lock(&data->update_lock); | ||
| 137 | ad525x_write(client, reg, value); | ||
| 138 | if (reg & AD525X_I2C_EEPROM) | ||
| 139 | msleep(26); /* Sleep while the EEPROM updates */ | ||
| 140 | mutex_unlock(&data->update_lock); | ||
| 141 | |||
| 142 | return count; | ||
| 143 | } | ||
| 144 | |||
| 145 | static ssize_t sysfs_do_cmd(struct device *dev, | ||
| 146 | struct device_attribute *attr, | ||
| 147 | const char *buf, size_t count, u32 reg) | ||
| 148 | { | ||
| 149 | struct i2c_client *client = to_i2c_client(dev); | ||
| 150 | struct dpot_data *data = i2c_get_clientdata(client); | ||
| 151 | |||
| 152 | mutex_lock(&data->update_lock); | ||
| 153 | ad525x_write(client, reg, 0); | ||
| 154 | mutex_unlock(&data->update_lock); | ||
| 155 | |||
| 156 | return count; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* ------------------------------------------------------------------------- */ | ||
| 160 | |||
| 161 | static ssize_t show_rdac0(struct device *dev, | ||
| 162 | struct device_attribute *attr, char *buf) | ||
| 163 | { | ||
| 164 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC0); | ||
| 165 | } | ||
| 166 | |||
| 167 | static ssize_t set_rdac0(struct device *dev, | ||
| 168 | struct device_attribute *attr, | ||
| 169 | const char *buf, size_t count) | ||
| 170 | { | ||
| 171 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 172 | AD525X_I2C_RDAC | AD525X_RDAC0); | ||
| 173 | } | ||
| 174 | |||
| 175 | static DEVICE_ATTR(rdac0, S_IWUSR | S_IRUGO, show_rdac0, set_rdac0); | ||
| 176 | |||
| 177 | static ssize_t show_eeprom0(struct device *dev, | ||
| 178 | struct device_attribute *attr, char *buf) | ||
| 179 | { | ||
| 180 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC0); | ||
| 181 | } | ||
| 182 | |||
| 183 | static ssize_t set_eeprom0(struct device *dev, | ||
| 184 | struct device_attribute *attr, | ||
| 185 | const char *buf, size_t count) | ||
| 186 | { | ||
| 187 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 188 | AD525X_I2C_EEPROM | AD525X_RDAC0); | ||
| 189 | } | ||
| 190 | |||
| 191 | static DEVICE_ATTR(eeprom0, S_IWUSR | S_IRUGO, show_eeprom0, set_eeprom0); | ||
| 192 | |||
| 193 | static ssize_t show_tolerance0(struct device *dev, | ||
| 194 | struct device_attribute *attr, char *buf) | ||
| 195 | { | ||
| 196 | return sysfs_show_reg(dev, attr, buf, | ||
| 197 | AD525X_I2C_EEPROM | AD525X_TOL_RDAC0); | ||
| 198 | } | ||
| 199 | |||
| 200 | static DEVICE_ATTR(tolerance0, S_IRUGO, show_tolerance0, NULL); | ||
| 201 | |||
| 202 | /* ------------------------------------------------------------------------- */ | ||
| 203 | |||
| 204 | static ssize_t show_rdac1(struct device *dev, | ||
| 205 | struct device_attribute *attr, char *buf) | ||
| 206 | { | ||
| 207 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC1); | ||
| 208 | } | ||
| 209 | |||
| 210 | static ssize_t set_rdac1(struct device *dev, | ||
| 211 | struct device_attribute *attr, | ||
| 212 | const char *buf, size_t count) | ||
| 213 | { | ||
| 214 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 215 | AD525X_I2C_RDAC | AD525X_RDAC1); | ||
| 216 | } | ||
| 217 | |||
| 218 | static DEVICE_ATTR(rdac1, S_IWUSR | S_IRUGO, show_rdac1, set_rdac1); | ||
| 219 | |||
| 220 | static ssize_t show_eeprom1(struct device *dev, | ||
| 221 | struct device_attribute *attr, char *buf) | ||
| 222 | { | ||
| 223 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC1); | ||
| 224 | } | ||
| 225 | |||
| 226 | static ssize_t set_eeprom1(struct device *dev, | ||
| 227 | struct device_attribute *attr, | ||
| 228 | const char *buf, size_t count) | ||
| 229 | { | ||
| 230 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 231 | AD525X_I2C_EEPROM | AD525X_RDAC1); | ||
| 232 | } | ||
| 233 | |||
| 234 | static DEVICE_ATTR(eeprom1, S_IWUSR | S_IRUGO, show_eeprom1, set_eeprom1); | ||
| 235 | |||
| 236 | static ssize_t show_tolerance1(struct device *dev, | ||
| 237 | struct device_attribute *attr, char *buf) | ||
| 238 | { | ||
| 239 | return sysfs_show_reg(dev, attr, buf, | ||
| 240 | AD525X_I2C_EEPROM | AD525X_TOL_RDAC1); | ||
| 241 | } | ||
| 242 | |||
| 243 | static DEVICE_ATTR(tolerance1, S_IRUGO, show_tolerance1, NULL); | ||
| 244 | |||
| 245 | /* ------------------------------------------------------------------------- */ | ||
| 246 | |||
| 247 | static ssize_t show_rdac2(struct device *dev, | ||
| 248 | struct device_attribute *attr, char *buf) | ||
| 249 | { | ||
| 250 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC2); | ||
| 251 | } | ||
| 252 | |||
| 253 | static ssize_t set_rdac2(struct device *dev, | ||
| 254 | struct device_attribute *attr, | ||
| 255 | const char *buf, size_t count) | ||
| 256 | { | ||
| 257 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 258 | AD525X_I2C_RDAC | AD525X_RDAC2); | ||
| 259 | } | ||
| 260 | |||
| 261 | static DEVICE_ATTR(rdac2, S_IWUSR | S_IRUGO, show_rdac2, set_rdac2); | ||
| 262 | |||
| 263 | static ssize_t show_eeprom2(struct device *dev, | ||
| 264 | struct device_attribute *attr, char *buf) | ||
| 265 | { | ||
| 266 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC2); | ||
| 267 | } | ||
| 268 | |||
| 269 | static ssize_t set_eeprom2(struct device *dev, | ||
| 270 | struct device_attribute *attr, | ||
| 271 | const char *buf, size_t count) | ||
| 272 | { | ||
| 273 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 274 | AD525X_I2C_EEPROM | AD525X_RDAC2); | ||
| 275 | } | ||
| 276 | |||
| 277 | static DEVICE_ATTR(eeprom2, S_IWUSR | S_IRUGO, show_eeprom2, set_eeprom2); | ||
| 278 | |||
| 279 | static ssize_t show_tolerance2(struct device *dev, | ||
| 280 | struct device_attribute *attr, char *buf) | ||
| 281 | { | ||
| 282 | return sysfs_show_reg(dev, attr, buf, | ||
| 283 | AD525X_I2C_EEPROM | AD525X_TOL_RDAC2); | ||
| 284 | } | ||
| 285 | |||
| 286 | static DEVICE_ATTR(tolerance2, S_IRUGO, show_tolerance2, NULL); | ||
| 287 | |||
| 288 | /* ------------------------------------------------------------------------- */ | ||
| 289 | |||
| 290 | static ssize_t show_rdac3(struct device *dev, | ||
| 291 | struct device_attribute *attr, char *buf) | ||
| 292 | { | ||
| 293 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC3); | ||
| 294 | } | ||
| 295 | |||
| 296 | static ssize_t set_rdac3(struct device *dev, | ||
| 297 | struct device_attribute *attr, | ||
| 298 | const char *buf, size_t count) | ||
| 299 | { | ||
| 300 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 301 | AD525X_I2C_RDAC | AD525X_RDAC3); | ||
| 302 | } | ||
| 303 | |||
| 304 | static DEVICE_ATTR(rdac3, S_IWUSR | S_IRUGO, show_rdac3, set_rdac3); | ||
| 305 | |||
| 306 | static ssize_t show_eeprom3(struct device *dev, | ||
| 307 | struct device_attribute *attr, char *buf) | ||
| 308 | { | ||
| 309 | return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC3); | ||
| 310 | } | ||
| 311 | |||
| 312 | static ssize_t set_eeprom3(struct device *dev, | ||
| 313 | struct device_attribute *attr, | ||
| 314 | const char *buf, size_t count) | ||
| 315 | { | ||
| 316 | return sysfs_set_reg(dev, attr, buf, count, | ||
| 317 | AD525X_I2C_EEPROM | AD525X_RDAC3); | ||
| 318 | } | ||
| 319 | |||
| 320 | static DEVICE_ATTR(eeprom3, S_IWUSR | S_IRUGO, show_eeprom3, set_eeprom3); | ||
| 321 | |||
| 322 | static ssize_t show_tolerance3(struct device *dev, | ||
| 323 | struct device_attribute *attr, char *buf) | ||
| 324 | { | ||
| 325 | return sysfs_show_reg(dev, attr, buf, | ||
| 326 | AD525X_I2C_EEPROM | AD525X_TOL_RDAC3); | ||
| 327 | } | ||
| 328 | |||
| 329 | static DEVICE_ATTR(tolerance3, S_IRUGO, show_tolerance3, NULL); | ||
| 330 | |||
| 331 | static struct attribute *ad525x_attributes_wipers[4][4] = { | ||
| 332 | { | ||
| 333 | &dev_attr_rdac0.attr, | ||
| 334 | &dev_attr_eeprom0.attr, | ||
| 335 | &dev_attr_tolerance0.attr, | ||
| 336 | NULL | ||
| 337 | }, { | ||
| 338 | &dev_attr_rdac1.attr, | ||
| 339 | &dev_attr_eeprom1.attr, | ||
| 340 | &dev_attr_tolerance1.attr, | ||
| 341 | NULL | ||
| 342 | }, { | ||
| 343 | &dev_attr_rdac2.attr, | ||
| 344 | &dev_attr_eeprom2.attr, | ||
| 345 | &dev_attr_tolerance2.attr, | ||
| 346 | NULL | ||
| 347 | }, { | ||
| 348 | &dev_attr_rdac3.attr, | ||
| 349 | &dev_attr_eeprom3.attr, | ||
| 350 | &dev_attr_tolerance3.attr, | ||
| 351 | NULL | ||
| 352 | } | ||
| 353 | }; | ||
| 354 | |||
| 355 | static const struct attribute_group ad525x_group_wipers[] = { | ||
| 356 | {.attrs = ad525x_attributes_wipers[AD525X_RDAC0]}, | ||
| 357 | {.attrs = ad525x_attributes_wipers[AD525X_RDAC1]}, | ||
| 358 | {.attrs = ad525x_attributes_wipers[AD525X_RDAC2]}, | ||
| 359 | {.attrs = ad525x_attributes_wipers[AD525X_RDAC3]}, | ||
| 360 | }; | ||
| 361 | |||
| 362 | /* ------------------------------------------------------------------------- */ | ||
| 363 | |||
| 364 | static ssize_t set_inc_all(struct device *dev, | ||
| 365 | struct device_attribute *attr, | ||
| 366 | const char *buf, size_t count) | ||
| 367 | { | ||
| 368 | return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL); | ||
| 369 | } | ||
| 370 | |||
| 371 | static DEVICE_ATTR(inc_all, S_IWUSR, NULL, set_inc_all); | ||
| 372 | |||
| 373 | static ssize_t set_dec_all(struct device *dev, | ||
| 374 | struct device_attribute *attr, | ||
| 375 | const char *buf, size_t count) | ||
| 376 | { | ||
| 377 | return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL); | ||
| 378 | } | ||
| 379 | |||
| 380 | static DEVICE_ATTR(dec_all, S_IWUSR, NULL, set_dec_all); | ||
| 381 | |||
| 382 | static ssize_t set_inc_all_6db(struct device *dev, | ||
| 383 | struct device_attribute *attr, | ||
| 384 | const char *buf, size_t count) | ||
| 385 | { | ||
| 386 | return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL_6DB); | ||
| 387 | } | ||
| 388 | |||
| 389 | static DEVICE_ATTR(inc_all_6db, S_IWUSR, NULL, set_inc_all_6db); | ||
| 390 | |||
| 391 | static ssize_t set_dec_all_6db(struct device *dev, | ||
| 392 | struct device_attribute *attr, | ||
| 393 | const char *buf, size_t count) | ||
| 394 | { | ||
| 395 | return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL_6DB); | ||
| 396 | } | ||
| 397 | |||
| 398 | static DEVICE_ATTR(dec_all_6db, S_IWUSR, NULL, set_dec_all_6db); | ||
| 399 | |||
| 400 | static struct attribute *ad525x_attributes_commands[] = { | ||
| 401 | &dev_attr_inc_all.attr, | ||
| 402 | &dev_attr_dec_all.attr, | ||
| 403 | &dev_attr_inc_all_6db.attr, | ||
| 404 | &dev_attr_dec_all_6db.attr, | ||
| 405 | NULL | ||
| 406 | }; | ||
| 407 | |||
| 408 | static const struct attribute_group ad525x_group_commands = { | ||
| 409 | .attrs = ad525x_attributes_commands, | ||
| 410 | }; | ||
| 411 | |||
| 412 | /* ------------------------------------------------------------------------- */ | ||
| 413 | |||
| 414 | /* i2c device functions */ | ||
| 415 | |||
| 416 | /** | ||
| 417 | * ad525x_read - return the value contained in the specified register | ||
| 418 | * on the AD5258 device. | ||
| 419 | * @client: value returned from i2c_new_device() | ||
| 420 | * @reg: the register to read | ||
| 421 | * | ||
| 422 | * If the tolerance register is specified, 2 bytes are returned. | ||
| 423 | * Otherwise, 1 byte is returned. A negative value indicates an error | ||
| 424 | * occurred while reading the register. | ||
| 425 | */ | ||
| 426 | static s32 ad525x_read(struct i2c_client *client, u8 reg) | ||
| 427 | { | ||
| 428 | struct dpot_data *data = i2c_get_clientdata(client); | ||
| 429 | |||
| 430 | if ((reg & AD525X_REG_TOL) || (data->max_pos > 256)) | ||
| 431 | return i2c_smbus_read_word_data(client, (reg & 0xF8) | | ||
| 432 | ((reg & 0x7) << 1)); | ||
| 433 | else | ||
| 434 | return i2c_smbus_read_byte_data(client, reg); | ||
| 435 | } | ||
| 436 | |||
| 437 | /** | ||
| 438 | * ad525x_write - store the given value in the specified register on | ||
| 439 | * the AD5258 device. | ||
| 440 | * @client: value returned from i2c_new_device() | ||
| 441 | * @reg: the register to write | ||
| 442 | * @value: the byte to store in the register | ||
| 443 | * | ||
| 444 | * For certain instructions that do not require a data byte, "NULL" | ||
| 445 | * should be specified for the "value" parameter. These instructions | ||
| 446 | * include NOP, RESTORE_FROM_EEPROM, and STORE_TO_EEPROM. | ||
| 447 | * | ||
| 448 | * A negative return value indicates an error occurred while reading | ||
| 449 | * the register. | ||
| 450 | */ | ||
| 451 | static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value) | ||
| 452 | { | ||
| 453 | struct dpot_data *data = i2c_get_clientdata(client); | ||
| 454 | |||
| 455 | /* Only write the instruction byte for certain commands */ | ||
| 456 | if (reg & AD525X_I2C_CMD) | ||
| 457 | return i2c_smbus_write_byte(client, reg); | ||
| 458 | |||
| 459 | if (data->max_pos > 256) | ||
| 460 | return i2c_smbus_write_word_data(client, (reg & 0xF8) | | ||
| 461 | ((reg & 0x7) << 1), value); | ||
| 462 | else | ||
| 463 | /* All other registers require instruction + data bytes */ | ||
| 464 | return i2c_smbus_write_byte_data(client, reg, value); | ||
| 465 | } | ||
| 466 | |||
| 467 | static int ad525x_probe(struct i2c_client *client, | ||
| 468 | const struct i2c_device_id *id) | ||
| 469 | { | ||
| 470 | struct device *dev = &client->dev; | ||
| 471 | struct dpot_data *data; | ||
| 472 | int err = 0; | ||
| 473 | |||
| 474 | dev_dbg(dev, "%s\n", __func__); | ||
| 475 | |||
| 476 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { | ||
| 477 | dev_err(dev, "missing I2C functionality for this driver\n"); | ||
| 478 | goto exit; | ||
| 479 | } | ||
| 480 | |||
| 481 | data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL); | ||
| 482 | if (!data) { | ||
| 483 | err = -ENOMEM; | ||
| 484 | goto exit; | ||
| 485 | } | ||
| 486 | |||
| 487 | i2c_set_clientdata(client, data); | ||
| 488 | mutex_init(&data->update_lock); | ||
| 489 | |||
| 490 | switch (id->driver_data) { | ||
| 491 | case AD5258_ID: | ||
| 492 | data->max_pos = AD5258_MAX_POSITION; | ||
| 493 | err = sysfs_create_group(&dev->kobj, | ||
| 494 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 495 | break; | ||
| 496 | case AD5259_ID: | ||
| 497 | data->max_pos = AD5259_MAX_POSITION; | ||
| 498 | err = sysfs_create_group(&dev->kobj, | ||
| 499 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 500 | break; | ||
| 501 | case AD5251_ID: | ||
| 502 | data->max_pos = AD5251_MAX_POSITION; | ||
| 503 | err = sysfs_create_group(&dev->kobj, | ||
| 504 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 505 | err |= sysfs_create_group(&dev->kobj, | ||
| 506 | &ad525x_group_wipers[AD525X_RDAC3]); | ||
| 507 | err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands); | ||
| 508 | break; | ||
| 509 | case AD5252_ID: | ||
| 510 | data->max_pos = AD5252_MAX_POSITION; | ||
| 511 | err = sysfs_create_group(&dev->kobj, | ||
| 512 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 513 | err |= sysfs_create_group(&dev->kobj, | ||
| 514 | &ad525x_group_wipers[AD525X_RDAC3]); | ||
| 515 | err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands); | ||
| 516 | break; | ||
| 517 | case AD5253_ID: | ||
| 518 | data->max_pos = AD5253_MAX_POSITION; | ||
| 519 | err = sysfs_create_group(&dev->kobj, | ||
| 520 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 521 | err |= sysfs_create_group(&dev->kobj, | ||
| 522 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 523 | err |= sysfs_create_group(&dev->kobj, | ||
| 524 | &ad525x_group_wipers[AD525X_RDAC2]); | ||
| 525 | err |= sysfs_create_group(&dev->kobj, | ||
| 526 | &ad525x_group_wipers[AD525X_RDAC3]); | ||
| 527 | err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands); | ||
| 528 | break; | ||
| 529 | case AD5254_ID: | ||
| 530 | data->max_pos = AD5254_MAX_POSITION; | ||
| 531 | err = sysfs_create_group(&dev->kobj, | ||
| 532 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 533 | err |= sysfs_create_group(&dev->kobj, | ||
| 534 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 535 | err |= sysfs_create_group(&dev->kobj, | ||
| 536 | &ad525x_group_wipers[AD525X_RDAC2]); | ||
| 537 | err |= sysfs_create_group(&dev->kobj, | ||
| 538 | &ad525x_group_wipers[AD525X_RDAC3]); | ||
| 539 | err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands); | ||
| 540 | break; | ||
| 541 | case AD5255_ID: | ||
| 542 | data->max_pos = AD5255_MAX_POSITION; | ||
| 543 | err = sysfs_create_group(&dev->kobj, | ||
| 544 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 545 | err |= sysfs_create_group(&dev->kobj, | ||
| 546 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 547 | err |= sysfs_create_group(&dev->kobj, | ||
| 548 | &ad525x_group_wipers[AD525X_RDAC2]); | ||
| 549 | err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands); | ||
| 550 | break; | ||
| 551 | default: | ||
| 552 | err = -ENODEV; | ||
| 553 | goto exit_free; | ||
| 554 | } | ||
| 555 | |||
| 556 | if (err) { | ||
| 557 | dev_err(dev, "failed to register sysfs hooks\n"); | ||
| 558 | goto exit_free; | ||
| 559 | } | ||
| 560 | |||
| 561 | data->devid = id->driver_data; | ||
| 562 | data->rdac_mask = data->max_pos - 1; | ||
| 563 | |||
| 564 | dev_info(dev, "%s %d-Position Digital Potentiometer registered\n", | ||
| 565 | id->name, data->max_pos); | ||
| 566 | |||
| 567 | return 0; | ||
| 568 | |||
| 569 | exit_free: | ||
| 570 | kfree(data); | ||
| 571 | i2c_set_clientdata(client, NULL); | ||
| 572 | exit: | ||
| 573 | dev_err(dev, "failed to create client\n"); | ||
| 574 | return err; | ||
| 575 | } | ||
| 576 | |||
| 577 | static int __devexit ad525x_remove(struct i2c_client *client) | ||
| 578 | { | ||
| 579 | struct dpot_data *data = i2c_get_clientdata(client); | ||
| 580 | struct device *dev = &client->dev; | ||
| 581 | |||
| 582 | switch (data->devid) { | ||
| 583 | case AD5258_ID: | ||
| 584 | case AD5259_ID: | ||
| 585 | sysfs_remove_group(&dev->kobj, | ||
| 586 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 587 | break; | ||
| 588 | case AD5251_ID: | ||
| 589 | case AD5252_ID: | ||
| 590 | sysfs_remove_group(&dev->kobj, | ||
| 591 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 592 | sysfs_remove_group(&dev->kobj, | ||
| 593 | &ad525x_group_wipers[AD525X_RDAC3]); | ||
| 594 | sysfs_remove_group(&dev->kobj, &ad525x_group_commands); | ||
| 595 | break; | ||
| 596 | case AD5253_ID: | ||
| 597 | case AD5254_ID: | ||
| 598 | sysfs_remove_group(&dev->kobj, | ||
| 599 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 600 | sysfs_remove_group(&dev->kobj, | ||
| 601 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 602 | sysfs_remove_group(&dev->kobj, | ||
| 603 | &ad525x_group_wipers[AD525X_RDAC2]); | ||
| 604 | sysfs_remove_group(&dev->kobj, | ||
| 605 | &ad525x_group_wipers[AD525X_RDAC3]); | ||
| 606 | sysfs_remove_group(&dev->kobj, &ad525x_group_commands); | ||
| 607 | break; | ||
| 608 | case AD5255_ID: | ||
| 609 | sysfs_remove_group(&dev->kobj, | ||
| 610 | &ad525x_group_wipers[AD525X_RDAC0]); | ||
| 611 | sysfs_remove_group(&dev->kobj, | ||
| 612 | &ad525x_group_wipers[AD525X_RDAC1]); | ||
| 613 | sysfs_remove_group(&dev->kobj, | ||
| 614 | &ad525x_group_wipers[AD525X_RDAC2]); | ||
| 615 | sysfs_remove_group(&dev->kobj, &ad525x_group_commands); | ||
| 616 | break; | ||
| 617 | } | ||
| 618 | |||
| 619 | i2c_set_clientdata(client, NULL); | ||
| 620 | kfree(data); | ||
| 621 | |||
| 622 | return 0; | ||
| 623 | } | ||
| 624 | |||
| 625 | static const struct i2c_device_id ad525x_idtable[] = { | ||
| 626 | {"ad5258", AD5258_ID}, | ||
| 627 | {"ad5259", AD5259_ID}, | ||
| 628 | {"ad5251", AD5251_ID}, | ||
| 629 | {"ad5252", AD5252_ID}, | ||
| 630 | {"ad5253", AD5253_ID}, | ||
| 631 | {"ad5254", AD5254_ID}, | ||
| 632 | {"ad5255", AD5255_ID}, | ||
| 633 | {} | ||
| 634 | }; | ||
| 635 | |||
| 636 | MODULE_DEVICE_TABLE(i2c, ad525x_idtable); | ||
| 637 | |||
| 638 | static struct i2c_driver ad525x_driver = { | ||
| 639 | .driver = { | ||
| 640 | .owner = THIS_MODULE, | ||
| 641 | .name = DRIVER_NAME, | ||
| 642 | }, | ||
| 643 | .id_table = ad525x_idtable, | ||
| 644 | .probe = ad525x_probe, | ||
| 645 | .remove = __devexit_p(ad525x_remove), | ||
| 646 | }; | ||
| 647 | |||
| 648 | static int __init ad525x_init(void) | ||
| 649 | { | ||
| 650 | return i2c_add_driver(&ad525x_driver); | ||
| 651 | } | ||
| 652 | |||
| 653 | module_init(ad525x_init); | ||
| 654 | |||
| 655 | static void __exit ad525x_exit(void) | ||
| 656 | { | ||
| 657 | i2c_del_driver(&ad525x_driver); | ||
| 658 | } | ||
| 659 | |||
| 660 | module_exit(ad525x_exit); | ||
| 661 | |||
| 662 | MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, " | ||
| 663 | "Michael Hennerich <hennerich@blackfin.uclinux.org>, "); | ||
| 664 | MODULE_DESCRIPTION("AD5258/9 digital potentiometer driver"); | ||
| 665 | MODULE_LICENSE("GPL"); | ||
| 666 | MODULE_VERSION(DRIVER_VERSION); | ||
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c new file mode 100644 index 000000000000..8110460558ff --- /dev/null +++ b/drivers/misc/cs5535-mfgpt.c | |||
| @@ -0,0 +1,370 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the CS5535/CS5536 Multi-Function General Purpose Timers (MFGPT) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006, Advanced Micro Devices, Inc. | ||
| 5 | * Copyright (C) 2007 Andres Salomon <dilinger@debian.org> | ||
| 6 | * Copyright (C) 2009 Andres Salomon <dilinger@collabora.co.uk> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of version 2 of the GNU General Public License | ||
| 10 | * as published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * The MFGPTs are documented in AMD Geode CS5536 Companion Device Data Book. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/spinlock.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/pci.h> | ||
| 20 | #include <linux/cs5535.h> | ||
| 21 | |||
| 22 | #define DRV_NAME "cs5535-mfgpt" | ||
| 23 | #define MFGPT_BAR 2 | ||
| 24 | |||
| 25 | static int mfgpt_reset_timers; | ||
| 26 | module_param_named(mfgptfix, mfgpt_reset_timers, int, 0644); | ||
| 27 | MODULE_PARM_DESC(mfgptfix, "Reset the MFGPT timers during init; " | ||
| 28 | "required by some broken BIOSes (ie, TinyBIOS < 0.99)."); | ||
| 29 | |||
| 30 | struct cs5535_mfgpt_timer { | ||
| 31 | struct cs5535_mfgpt_chip *chip; | ||
| 32 | int nr; | ||
| 33 | }; | ||
| 34 | |||
| 35 | static struct cs5535_mfgpt_chip { | ||
| 36 | DECLARE_BITMAP(avail, MFGPT_MAX_TIMERS); | ||
| 37 | resource_size_t base; | ||
| 38 | |||
| 39 | struct pci_dev *pdev; | ||
| 40 | spinlock_t lock; | ||
| 41 | int initialized; | ||
| 42 | } cs5535_mfgpt_chip; | ||
| 43 | |||
| 44 | int cs5535_mfgpt_toggle_event(struct cs5535_mfgpt_timer *timer, int cmp, | ||
| 45 | int event, int enable) | ||
| 46 | { | ||
| 47 | uint32_t msr, mask, value, dummy; | ||
| 48 | int shift = (cmp == MFGPT_CMP1) ? 0 : 8; | ||
| 49 | |||
| 50 | if (!timer) { | ||
| 51 | WARN_ON(1); | ||
| 52 | return -EIO; | ||
| 53 | } | ||
| 54 | |||
| 55 | /* | ||
| 56 | * The register maps for these are described in sections 6.17.1.x of | ||
| 57 | * the AMD Geode CS5536 Companion Device Data Book. | ||
| 58 | */ | ||
| 59 | switch (event) { | ||
| 60 | case MFGPT_EVENT_RESET: | ||
| 61 | /* | ||
| 62 | * XXX: According to the docs, we cannot reset timers above | ||
| 63 | * 6; that is, resets for 7 and 8 will be ignored. Is this | ||
| 64 | * a problem? -dilinger | ||
| 65 | */ | ||
| 66 | msr = MSR_MFGPT_NR; | ||
| 67 | mask = 1 << (timer->nr + 24); | ||
| 68 | break; | ||
| 69 | |||
| 70 | case MFGPT_EVENT_NMI: | ||
| 71 | msr = MSR_MFGPT_NR; | ||
| 72 | mask = 1 << (timer->nr + shift); | ||
| 73 | break; | ||
| 74 | |||
| 75 | case MFGPT_EVENT_IRQ: | ||
| 76 | msr = MSR_MFGPT_IRQ; | ||
| 77 | mask = 1 << (timer->nr + shift); | ||
| 78 | break; | ||
| 79 | |||
| 80 | default: | ||
| 81 | return -EIO; | ||
| 82 | } | ||
| 83 | |||
| 84 | rdmsr(msr, value, dummy); | ||
| 85 | |||
| 86 | if (enable) | ||
| 87 | value |= mask; | ||
| 88 | else | ||
| 89 | value &= ~mask; | ||
| 90 | |||
| 91 | wrmsr(msr, value, dummy); | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_toggle_event); | ||
| 95 | |||
| 96 | int cs5535_mfgpt_set_irq(struct cs5535_mfgpt_timer *timer, int cmp, int *irq, | ||
| 97 | int enable) | ||
| 98 | { | ||
| 99 | uint32_t zsel, lpc, dummy; | ||
| 100 | int shift; | ||
| 101 | |||
| 102 | if (!timer) { | ||
| 103 | WARN_ON(1); | ||
| 104 | return -EIO; | ||
| 105 | } | ||
| 106 | |||
| 107 | /* | ||
| 108 | * Unfortunately, MFGPTs come in pairs sharing their IRQ lines. If VSA | ||
| 109 | * is using the same CMP of the timer's Siamese twin, the IRQ is set to | ||
| 110 | * 2, and we mustn't use nor change it. | ||
| 111 | * XXX: Likewise, 2 Linux drivers might clash if the 2nd overwrites the | ||
| 112 | * IRQ of the 1st. This can only happen if forcing an IRQ, calling this | ||
| 113 | * with *irq==0 is safe. Currently there _are_ no 2 drivers. | ||
| 114 | */ | ||
| 115 | rdmsr(MSR_PIC_ZSEL_LOW, zsel, dummy); | ||
| 116 | shift = ((cmp == MFGPT_CMP1 ? 0 : 4) + timer->nr % 4) * 4; | ||
| 117 | if (((zsel >> shift) & 0xF) == 2) | ||
| 118 | return -EIO; | ||
| 119 | |||
| 120 | /* Choose IRQ: if none supplied, keep IRQ already set or use default */ | ||
| 121 | if (!*irq) | ||
| 122 | *irq = (zsel >> shift) & 0xF; | ||
| 123 | if (!*irq) | ||
| 124 | *irq = CONFIG_CS5535_MFGPT_DEFAULT_IRQ; | ||
| 125 | |||
| 126 | /* Can't use IRQ if it's 0 (=disabled), 2, or routed to LPC */ | ||
| 127 | if (*irq < 1 || *irq == 2 || *irq > 15) | ||
| 128 | return -EIO; | ||
| 129 | rdmsr(MSR_PIC_IRQM_LPC, lpc, dummy); | ||
| 130 | if (lpc & (1 << *irq)) | ||
| 131 | return -EIO; | ||
| 132 | |||
| 133 | /* All chosen and checked - go for it */ | ||
| 134 | if (cs5535_mfgpt_toggle_event(timer, cmp, MFGPT_EVENT_IRQ, enable)) | ||
| 135 | return -EIO; | ||
| 136 | if (enable) { | ||
| 137 | zsel = (zsel & ~(0xF << shift)) | (*irq << shift); | ||
| 138 | wrmsr(MSR_PIC_ZSEL_LOW, zsel, dummy); | ||
| 139 | } | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_set_irq); | ||
| 144 | |||
| 145 | struct cs5535_mfgpt_timer *cs5535_mfgpt_alloc_timer(int timer_nr, int domain) | ||
| 146 | { | ||
| 147 | struct cs5535_mfgpt_chip *mfgpt = &cs5535_mfgpt_chip; | ||
| 148 | struct cs5535_mfgpt_timer *timer = NULL; | ||
| 149 | unsigned long flags; | ||
| 150 | int max; | ||
| 151 | |||
| 152 | if (!mfgpt->initialized) | ||
| 153 | goto done; | ||
| 154 | |||
| 155 | /* only allocate timers from the working domain if requested */ | ||
| 156 | if (domain == MFGPT_DOMAIN_WORKING) | ||
| 157 | max = 6; | ||
| 158 | else | ||
| 159 | max = MFGPT_MAX_TIMERS; | ||
| 160 | |||
| 161 | if (timer_nr >= max) { | ||
| 162 | /* programmer error. silly programmers! */ | ||
| 163 | WARN_ON(1); | ||
| 164 | goto done; | ||
| 165 | } | ||
| 166 | |||
| 167 | spin_lock_irqsave(&mfgpt->lock, flags); | ||
| 168 | if (timer_nr < 0) { | ||
| 169 | unsigned long t; | ||
| 170 | |||
| 171 | /* try to find any available timer */ | ||
| 172 | t = find_first_bit(mfgpt->avail, max); | ||
| 173 | /* set timer_nr to -1 if no timers available */ | ||
| 174 | timer_nr = t < max ? (int) t : -1; | ||
| 175 | } else { | ||
| 176 | /* check if the requested timer's available */ | ||
| 177 | if (test_bit(timer_nr, mfgpt->avail)) | ||
| 178 | timer_nr = -1; | ||
| 179 | } | ||
| 180 | |||
| 181 | if (timer_nr >= 0) | ||
| 182 | /* if timer_nr is not -1, it's an available timer */ | ||
| 183 | __clear_bit(timer_nr, mfgpt->avail); | ||
| 184 | spin_unlock_irqrestore(&mfgpt->lock, flags); | ||
| 185 | |||
| 186 | if (timer_nr < 0) | ||
| 187 | goto done; | ||
| 188 | |||
| 189 | timer = kmalloc(sizeof(*timer), GFP_KERNEL); | ||
| 190 | if (!timer) { | ||
| 191 | /* aw hell */ | ||
| 192 | spin_lock_irqsave(&mfgpt->lock, flags); | ||
| 193 | __set_bit(timer_nr, mfgpt->avail); | ||
| 194 | spin_unlock_irqrestore(&mfgpt->lock, flags); | ||
| 195 | goto done; | ||
| 196 | } | ||
| 197 | timer->chip = mfgpt; | ||
| 198 | timer->nr = timer_nr; | ||
| 199 | dev_info(&mfgpt->pdev->dev, "registered timer %d\n", timer_nr); | ||
| 200 | |||
| 201 | done: | ||
| 202 | return timer; | ||
| 203 | } | ||
| 204 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_alloc_timer); | ||
| 205 | |||
| 206 | /* | ||
| 207 | * XXX: This frees the timer memory, but never resets the actual hardware | ||
| 208 | * timer. The old geode_mfgpt code did this; it would be good to figure | ||
| 209 | * out a way to actually release the hardware timer. See comments below. | ||
| 210 | */ | ||
| 211 | void cs5535_mfgpt_free_timer(struct cs5535_mfgpt_timer *timer) | ||
| 212 | { | ||
| 213 | kfree(timer); | ||
| 214 | } | ||
| 215 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_free_timer); | ||
| 216 | |||
| 217 | uint16_t cs5535_mfgpt_read(struct cs5535_mfgpt_timer *timer, uint16_t reg) | ||
| 218 | { | ||
| 219 | return inw(timer->chip->base + reg + (timer->nr * 8)); | ||
| 220 | } | ||
| 221 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_read); | ||
| 222 | |||
| 223 | void cs5535_mfgpt_write(struct cs5535_mfgpt_timer *timer, uint16_t reg, | ||
| 224 | uint16_t value) | ||
| 225 | { | ||
| 226 | outw(value, timer->chip->base + reg + (timer->nr * 8)); | ||
| 227 | } | ||
| 228 | EXPORT_SYMBOL_GPL(cs5535_mfgpt_write); | ||
| 229 | |||
| 230 | /* | ||
| 231 | * This is a sledgehammer that resets all MFGPT timers. This is required by | ||
| 232 | * some broken BIOSes which leave the system in an unstable state | ||
| 233 | * (TinyBIOS 0.98, for example; fixed in 0.99). It's uncertain as to | ||
| 234 | * whether or not this secret MSR can be used to release individual timers. | ||
| 235 | * Jordan tells me that he and Mitch once played w/ it, but it's unclear | ||
| 236 | * what the results of that were (and they experienced some instability). | ||
| 237 | */ | ||
| 238 | static void __init reset_all_timers(void) | ||
| 239 | { | ||
| 240 | uint32_t val, dummy; | ||
| 241 | |||
| 242 | /* The following undocumented bit resets the MFGPT timers */ | ||
| 243 | val = 0xFF; dummy = 0; | ||
| 244 | wrmsr(MSR_MFGPT_SETUP, val, dummy); | ||
| 245 | } | ||
| 246 | |||
| 247 | /* | ||
| 248 | * Check whether any MFGPTs are available for the kernel to use. In most | ||
| 249 | * cases, firmware that uses AMD's VSA code will claim all timers during | ||
| 250 | * bootup; we certainly don't want to take them if they're already in use. | ||
| 251 | * In other cases (such as with VSAless OpenFirmware), the system firmware | ||
| 252 | * leaves timers available for us to use. | ||
| 253 | */ | ||
| 254 | static int __init scan_timers(struct cs5535_mfgpt_chip *mfgpt) | ||
| 255 | { | ||
| 256 | struct cs5535_mfgpt_timer timer = { .chip = mfgpt }; | ||
| 257 | unsigned long flags; | ||
| 258 | int timers = 0; | ||
| 259 | uint16_t val; | ||
| 260 | int i; | ||
| 261 | |||
| 262 | /* bios workaround */ | ||
| 263 | if (mfgpt_reset_timers) | ||
| 264 | reset_all_timers(); | ||
| 265 | |||
| 266 | /* just to be safe, protect this section w/ lock */ | ||
| 267 | spin_lock_irqsave(&mfgpt->lock, flags); | ||
| 268 | for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | ||
| 269 | timer.nr = i; | ||
| 270 | val = cs5535_mfgpt_read(&timer, MFGPT_REG_SETUP); | ||
| 271 | if (!(val & MFGPT_SETUP_SETUP)) { | ||
| 272 | __set_bit(i, mfgpt->avail); | ||
| 273 | timers++; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | spin_unlock_irqrestore(&mfgpt->lock, flags); | ||
| 277 | |||
| 278 | return timers; | ||
| 279 | } | ||
| 280 | |||
| 281 | static int __init cs5535_mfgpt_probe(struct pci_dev *pdev, | ||
| 282 | const struct pci_device_id *pci_id) | ||
| 283 | { | ||
| 284 | int err, t; | ||
| 285 | |||
| 286 | /* There are two ways to get the MFGPT base address; one is by | ||
| 287 | * fetching it from MSR_LBAR_MFGPT, the other is by reading the | ||
| 288 | * PCI BAR info. The latter method is easier (especially across | ||
| 289 | * different architectures), so we'll stick with that for now. If | ||
| 290 | * it turns out to be unreliable in the face of crappy BIOSes, we | ||
| 291 | * can always go back to using MSRs.. */ | ||
| 292 | |||
| 293 | err = pci_enable_device_io(pdev); | ||
| 294 | if (err) { | ||
| 295 | dev_err(&pdev->dev, "can't enable device IO\n"); | ||
| 296 | goto done; | ||
| 297 | } | ||
| 298 | |||
| 299 | err = pci_request_region(pdev, MFGPT_BAR, DRV_NAME); | ||
| 300 | if (err) { | ||
| 301 | dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", MFGPT_BAR); | ||
| 302 | goto done; | ||
| 303 | } | ||
| 304 | |||
| 305 | /* set up the driver-specific struct */ | ||
| 306 | cs5535_mfgpt_chip.base = pci_resource_start(pdev, MFGPT_BAR); | ||
| 307 | cs5535_mfgpt_chip.pdev = pdev; | ||
| 308 | spin_lock_init(&cs5535_mfgpt_chip.lock); | ||
| 309 | |||
| 310 | dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", MFGPT_BAR, | ||
| 311 | (unsigned long long) cs5535_mfgpt_chip.base); | ||
| 312 | |||
| 313 | /* detect the available timers */ | ||
| 314 | t = scan_timers(&cs5535_mfgpt_chip); | ||
| 315 | dev_info(&pdev->dev, DRV_NAME ": %d MFGPT timers available\n", t); | ||
| 316 | cs5535_mfgpt_chip.initialized = 1; | ||
| 317 | return 0; | ||
| 318 | |||
| 319 | done: | ||
| 320 | return err; | ||
| 321 | } | ||
| 322 | |||
| 323 | static struct pci_device_id cs5535_mfgpt_pci_tbl[] = { | ||
| 324 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, | ||
| 325 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, | ||
| 326 | { 0, }, | ||
| 327 | }; | ||
| 328 | MODULE_DEVICE_TABLE(pci, cs5535_mfgpt_pci_tbl); | ||
| 329 | |||
| 330 | /* | ||
| 331 | * Just like with the cs5535-gpio driver, we can't use the standard PCI driver | ||
| 332 | * registration stuff. It only allows only one driver to bind to each PCI | ||
| 333 | * device, and we want the GPIO and MFGPT drivers to be able to share a PCI | ||
| 334 | * device. Instead, we manually scan for the PCI device, request a single | ||
| 335 | * region, and keep track of the devices that we're using. | ||
| 336 | */ | ||
| 337 | |||
| 338 | static int __init cs5535_mfgpt_scan_pci(void) | ||
| 339 | { | ||
| 340 | struct pci_dev *pdev; | ||
| 341 | int err = -ENODEV; | ||
| 342 | int i; | ||
| 343 | |||
| 344 | for (i = 0; i < ARRAY_SIZE(cs5535_mfgpt_pci_tbl); i++) { | ||
| 345 | pdev = pci_get_device(cs5535_mfgpt_pci_tbl[i].vendor, | ||
| 346 | cs5535_mfgpt_pci_tbl[i].device, NULL); | ||
| 347 | if (pdev) { | ||
| 348 | err = cs5535_mfgpt_probe(pdev, | ||
| 349 | &cs5535_mfgpt_pci_tbl[i]); | ||
| 350 | if (err) | ||
| 351 | pci_dev_put(pdev); | ||
| 352 | |||
| 353 | /* we only support a single CS5535/6 southbridge */ | ||
| 354 | break; | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 | return err; | ||
| 359 | } | ||
| 360 | |||
| 361 | static int __init cs5535_mfgpt_init(void) | ||
| 362 | { | ||
| 363 | return cs5535_mfgpt_scan_pci(); | ||
| 364 | } | ||
| 365 | |||
| 366 | module_init(cs5535_mfgpt_init); | ||
| 367 | |||
| 368 | MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>"); | ||
| 369 | MODULE_DESCRIPTION("CS5535/CS5536 MFGPT timer driver"); | ||
| 370 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c index 2c27193aeaa0..f939ebc2507c 100644 --- a/drivers/misc/eeprom/eeprom.c +++ b/drivers/misc/eeprom/eeprom.c | |||
| @@ -32,9 +32,6 @@ | |||
| 32 | static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, | 32 | static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, |
| 33 | 0x55, 0x56, 0x57, I2C_CLIENT_END }; | 33 | 0x55, 0x56, 0x57, I2C_CLIENT_END }; |
| 34 | 34 | ||
| 35 | /* Insmod parameters */ | ||
| 36 | I2C_CLIENT_INSMOD_1(eeprom); | ||
| 37 | |||
| 38 | 35 | ||
| 39 | /* Size of EEPROM in bytes */ | 36 | /* Size of EEPROM in bytes */ |
| 40 | #define EEPROM_SIZE 256 | 37 | #define EEPROM_SIZE 256 |
| @@ -135,8 +132,7 @@ static struct bin_attribute eeprom_attr = { | |||
| 135 | }; | 132 | }; |
| 136 | 133 | ||
| 137 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 134 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 138 | static int eeprom_detect(struct i2c_client *client, int kind, | 135 | static int eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) |
| 139 | struct i2c_board_info *info) | ||
| 140 | { | 136 | { |
| 141 | struct i2c_adapter *adapter = client->adapter; | 137 | struct i2c_adapter *adapter = client->adapter; |
| 142 | 138 | ||
| @@ -233,7 +229,7 @@ static struct i2c_driver eeprom_driver = { | |||
| 233 | 229 | ||
| 234 | .class = I2C_CLASS_DDC | I2C_CLASS_SPD, | 230 | .class = I2C_CLASS_DDC | I2C_CLASS_SPD, |
| 235 | .detect = eeprom_detect, | 231 | .detect = eeprom_detect, |
| 236 | .address_data = &addr_data, | 232 | .address_list = normal_i2c, |
| 237 | }; | 233 | }; |
| 238 | 234 | ||
| 239 | static int __init eeprom_init(void) | 235 | static int __init eeprom_init(void) |
diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c index 4bb7a3af9ad9..395a4ea64e9c 100644 --- a/drivers/misc/ics932s401.c +++ b/drivers/misc/ics932s401.c | |||
| @@ -30,9 +30,6 @@ | |||
| 30 | /* Addresses to scan */ | 30 | /* Addresses to scan */ |
| 31 | static const unsigned short normal_i2c[] = { 0x69, I2C_CLIENT_END }; | 31 | static const unsigned short normal_i2c[] = { 0x69, I2C_CLIENT_END }; |
| 32 | 32 | ||
| 33 | /* Insmod parameters */ | ||
| 34 | I2C_CLIENT_INSMOD_1(ics932s401); | ||
| 35 | |||
| 36 | /* ICS932S401 registers */ | 33 | /* ICS932S401 registers */ |
| 37 | #define ICS932S401_REG_CFG2 0x01 | 34 | #define ICS932S401_REG_CFG2 0x01 |
| 38 | #define ICS932S401_CFG1_SPREAD 0x01 | 35 | #define ICS932S401_CFG1_SPREAD 0x01 |
| @@ -106,12 +103,12 @@ struct ics932s401_data { | |||
| 106 | 103 | ||
| 107 | static int ics932s401_probe(struct i2c_client *client, | 104 | static int ics932s401_probe(struct i2c_client *client, |
| 108 | const struct i2c_device_id *id); | 105 | const struct i2c_device_id *id); |
| 109 | static int ics932s401_detect(struct i2c_client *client, int kind, | 106 | static int ics932s401_detect(struct i2c_client *client, |
| 110 | struct i2c_board_info *info); | 107 | struct i2c_board_info *info); |
| 111 | static int ics932s401_remove(struct i2c_client *client); | 108 | static int ics932s401_remove(struct i2c_client *client); |
| 112 | 109 | ||
| 113 | static const struct i2c_device_id ics932s401_id[] = { | 110 | static const struct i2c_device_id ics932s401_id[] = { |
| 114 | { "ics932s401", ics932s401 }, | 111 | { "ics932s401", 0 }, |
| 115 | { } | 112 | { } |
| 116 | }; | 113 | }; |
| 117 | MODULE_DEVICE_TABLE(i2c, ics932s401_id); | 114 | MODULE_DEVICE_TABLE(i2c, ics932s401_id); |
| @@ -125,7 +122,7 @@ static struct i2c_driver ics932s401_driver = { | |||
| 125 | .remove = ics932s401_remove, | 122 | .remove = ics932s401_remove, |
| 126 | .id_table = ics932s401_id, | 123 | .id_table = ics932s401_id, |
| 127 | .detect = ics932s401_detect, | 124 | .detect = ics932s401_detect, |
| 128 | .address_data = &addr_data, | 125 | .address_list = normal_i2c, |
| 129 | }; | 126 | }; |
| 130 | 127 | ||
| 131 | static struct ics932s401_data *ics932s401_update_device(struct device *dev) | 128 | static struct ics932s401_data *ics932s401_update_device(struct device *dev) |
| @@ -413,7 +410,7 @@ static ssize_t show_spread(struct device *dev, | |||
| 413 | } | 410 | } |
| 414 | 411 | ||
| 415 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 412 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 416 | static int ics932s401_detect(struct i2c_client *client, int kind, | 413 | static int ics932s401_detect(struct i2c_client *client, |
| 417 | struct i2c_board_info *info) | 414 | struct i2c_board_info *info) |
| 418 | { | 415 | { |
| 419 | struct i2c_adapter *adapter = client->adapter; | 416 | struct i2c_adapter *adapter = client->adapter; |
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 60b0b1a4fb3a..09dcb699e667 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c | |||
| @@ -138,7 +138,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is) | |||
| 138 | * even though the following code utilizes external interrupt registers | 138 | * even though the following code utilizes external interrupt registers |
| 139 | * to perform the speed calculation. | 139 | * to perform the speed calculation. |
| 140 | */ | 140 | */ |
| 141 | static void | 141 | static void __devinit |
| 142 | ioc4_clock_calibrate(struct ioc4_driver_data *idd) | 142 | ioc4_clock_calibrate(struct ioc4_driver_data *idd) |
| 143 | { | 143 | { |
| 144 | union ioc4_int_out int_out; | 144 | union ioc4_int_out int_out; |
| @@ -230,7 +230,7 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd) | |||
| 230 | * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. | 230 | * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. |
| 231 | * If neither is present, it's a PCI-RT. | 231 | * If neither is present, it's a PCI-RT. |
| 232 | */ | 232 | */ |
| 233 | static unsigned int | 233 | static unsigned int __devinit |
| 234 | ioc4_variant(struct ioc4_driver_data *idd) | 234 | ioc4_variant(struct ioc4_driver_data *idd) |
| 235 | { | 235 | { |
| 236 | struct pci_dev *pdev = NULL; | 236 | struct pci_dev *pdev = NULL; |
| @@ -269,7 +269,7 @@ ioc4_variant(struct ioc4_driver_data *idd) | |||
| 269 | return IOC4_VARIANT_PCI_RT; | 269 | return IOC4_VARIANT_PCI_RT; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | static void | 272 | static void __devinit |
| 273 | ioc4_load_modules(struct work_struct *work) | 273 | ioc4_load_modules(struct work_struct *work) |
| 274 | { | 274 | { |
| 275 | /* arg just has to be freed */ | 275 | /* arg just has to be freed */ |
| @@ -280,7 +280,7 @@ ioc4_load_modules(struct work_struct *work) | |||
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | /* Adds a new instance of an IOC4 card */ | 282 | /* Adds a new instance of an IOC4 card */ |
| 283 | static int | 283 | static int __devinit |
| 284 | ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | 284 | ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) |
| 285 | { | 285 | { |
| 286 | struct ioc4_driver_data *idd; | 286 | struct ioc4_driver_data *idd; |
| @@ -425,7 +425,7 @@ out: | |||
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | /* Removes a particular instance of an IOC4 card. */ | 427 | /* Removes a particular instance of an IOC4 card. */ |
| 428 | static void | 428 | static void __devexit |
| 429 | ioc4_remove(struct pci_dev *pdev) | 429 | ioc4_remove(struct pci_dev *pdev) |
| 430 | { | 430 | { |
| 431 | struct ioc4_submodule *is; | 431 | struct ioc4_submodule *is; |
| @@ -476,7 +476,7 @@ static struct pci_driver ioc4_driver = { | |||
| 476 | .name = "IOC4", | 476 | .name = "IOC4", |
| 477 | .id_table = ioc4_id_table, | 477 | .id_table = ioc4_id_table, |
| 478 | .probe = ioc4_probe, | 478 | .probe = ioc4_probe, |
| 479 | .remove = ioc4_remove, | 479 | .remove = __devexit_p(ioc4_remove), |
| 480 | }; | 480 | }; |
| 481 | 481 | ||
| 482 | MODULE_DEVICE_TABLE(pci, ioc4_id_table); | 482 | MODULE_DEVICE_TABLE(pci, ioc4_id_table); |
| @@ -486,14 +486,14 @@ MODULE_DEVICE_TABLE(pci, ioc4_id_table); | |||
| 486 | *********************/ | 486 | *********************/ |
| 487 | 487 | ||
| 488 | /* Module load */ | 488 | /* Module load */ |
| 489 | static int __devinit | 489 | static int __init |
| 490 | ioc4_init(void) | 490 | ioc4_init(void) |
| 491 | { | 491 | { |
| 492 | return pci_register_driver(&ioc4_driver); | 492 | return pci_register_driver(&ioc4_driver); |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | /* Module unload */ | 495 | /* Module unload */ |
| 496 | static void __devexit | 496 | static void __exit |
| 497 | ioc4_exit(void) | 497 | ioc4_exit(void) |
| 498 | { | 498 | { |
| 499 | /* Ensure ioc4_load_modules() has completed before exiting */ | 499 | /* Ensure ioc4_load_modules() has completed before exiting */ |
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c new file mode 100644 index 000000000000..d3f229a3a77e --- /dev/null +++ b/drivers/misc/ti_dac7512.c | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | /* | ||
| 2 | * dac7512.c - Linux kernel module for | ||
| 3 | * Texas Instruments DAC7512 | ||
| 4 | * | ||
| 5 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/spi/spi.h> | ||
| 25 | |||
| 26 | #define DAC7512_DRV_NAME "dac7512" | ||
| 27 | #define DRIVER_VERSION "1.0" | ||
| 28 | |||
| 29 | static ssize_t dac7512_store_val(struct device *dev, | ||
| 30 | struct device_attribute *attr, | ||
| 31 | const char *buf, size_t count) | ||
| 32 | { | ||
| 33 | struct spi_device *spi = to_spi_device(dev); | ||
| 34 | unsigned char tmp[2]; | ||
| 35 | unsigned long val; | ||
| 36 | |||
| 37 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 38 | return -EINVAL; | ||
| 39 | |||
| 40 | tmp[0] = val >> 8; | ||
| 41 | tmp[1] = val & 0xff; | ||
| 42 | spi_write(spi, tmp, sizeof(tmp)); | ||
| 43 | return count; | ||
| 44 | } | ||
| 45 | |||
| 46 | static DEVICE_ATTR(value, S_IWUSR, NULL, dac7512_store_val); | ||
| 47 | |||
| 48 | static struct attribute *dac7512_attributes[] = { | ||
| 49 | &dev_attr_value.attr, | ||
| 50 | NULL | ||
| 51 | }; | ||
| 52 | |||
| 53 | static const struct attribute_group dac7512_attr_group = { | ||
| 54 | .attrs = dac7512_attributes, | ||
| 55 | }; | ||
| 56 | |||
| 57 | static int __devinit dac7512_probe(struct spi_device *spi) | ||
| 58 | { | ||
| 59 | int ret; | ||
| 60 | |||
| 61 | spi->bits_per_word = 8; | ||
| 62 | spi->mode = SPI_MODE_0; | ||
| 63 | ret = spi_setup(spi); | ||
| 64 | if (ret < 0) | ||
| 65 | return ret; | ||
| 66 | |||
| 67 | return sysfs_create_group(&spi->dev.kobj, &dac7512_attr_group); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int __devexit dac7512_remove(struct spi_device *spi) | ||
| 71 | { | ||
| 72 | sysfs_remove_group(&spi->dev.kobj, &dac7512_attr_group); | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | static struct spi_driver dac7512_driver = { | ||
| 77 | .driver = { | ||
| 78 | .name = DAC7512_DRV_NAME, | ||
| 79 | .owner = THIS_MODULE, | ||
| 80 | }, | ||
| 81 | .probe = dac7512_probe, | ||
| 82 | .remove = __devexit_p(dac7512_remove), | ||
| 83 | }; | ||
| 84 | |||
| 85 | static int __init dac7512_init(void) | ||
| 86 | { | ||
| 87 | return spi_register_driver(&dac7512_driver); | ||
| 88 | } | ||
| 89 | |||
| 90 | static void __exit dac7512_exit(void) | ||
| 91 | { | ||
| 92 | spi_unregister_driver(&dac7512_driver); | ||
| 93 | } | ||
| 94 | |||
| 95 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
| 96 | MODULE_DESCRIPTION("DAC7512 16-bit DAC"); | ||
| 97 | MODULE_LICENSE("GPL v2"); | ||
| 98 | MODULE_VERSION(DRIVER_VERSION); | ||
| 99 | |||
| 100 | module_init(dac7512_init); | ||
| 101 | module_exit(dac7512_exit); | ||
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index ab37a6d9d32a..bb22ffd76ef8 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | config MMC_UNSAFE_RESUME | 5 | config MMC_UNSAFE_RESUME |
| 6 | bool "Allow unsafe resume (DANGEROUS)" | 6 | bool "Assume MMC/SD cards are non-removable (DANGEROUS)" |
| 7 | help | 7 | help |
| 8 | If you say Y here, the MMC layer will assume that all cards | 8 | If you say Y here, the MMC layer will assume that all cards |
| 9 | stayed in their respective slots during the suspend. The | 9 | stayed in their respective slots during the suspend. The |
| @@ -14,3 +14,5 @@ config MMC_UNSAFE_RESUME | |||
| 14 | This option is usually just for embedded systems which use | 14 | This option is usually just for embedded systems which use |
| 15 | a MMC/SD card for rootfs. Most people should say N here. | 15 | a MMC/SD card for rootfs. Most people should say N here. |
| 16 | 16 | ||
| 17 | This option sets a default which can be overridden by the | ||
| 18 | module parameter "removable=0" or "removable=1". | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7dab2e5f4bc9..30acd5265821 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -48,6 +48,22 @@ int use_spi_crc = 1; | |||
| 48 | module_param(use_spi_crc, bool, 0); | 48 | module_param(use_spi_crc, bool, 0); |
| 49 | 49 | ||
| 50 | /* | 50 | /* |
| 51 | * We normally treat cards as removed during suspend if they are not | ||
| 52 | * known to be on a non-removable bus, to avoid the risk of writing | ||
| 53 | * back data to a different card after resume. Allow this to be | ||
| 54 | * overridden if necessary. | ||
| 55 | */ | ||
| 56 | #ifdef CONFIG_MMC_UNSAFE_RESUME | ||
| 57 | int mmc_assume_removable; | ||
| 58 | #else | ||
| 59 | int mmc_assume_removable = 1; | ||
| 60 | #endif | ||
| 61 | module_param_named(removable, mmc_assume_removable, bool, 0644); | ||
| 62 | MODULE_PARM_DESC( | ||
| 63 | removable, | ||
| 64 | "MMC/SD cards are removable and may be removed during suspend"); | ||
| 65 | |||
| 66 | /* | ||
| 51 | * Internal function. Schedule delayed work in the MMC work queue. | 67 | * Internal function. Schedule delayed work in the MMC work queue. |
| 52 | */ | 68 | */ |
| 53 | static int mmc_schedule_delayed_work(struct delayed_work *work, | 69 | static int mmc_schedule_delayed_work(struct delayed_work *work, |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 67ae6abc4230..a811c52a1659 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
| @@ -54,7 +54,9 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr); | |||
| 54 | int mmc_attach_sd(struct mmc_host *host, u32 ocr); | 54 | int mmc_attach_sd(struct mmc_host *host, u32 ocr); |
| 55 | int mmc_attach_sdio(struct mmc_host *host, u32 ocr); | 55 | int mmc_attach_sdio(struct mmc_host *host, u32 ocr); |
| 56 | 56 | ||
| 57 | /* Module parameters */ | ||
| 57 | extern int use_spi_crc; | 58 | extern int use_spi_crc; |
| 59 | extern int mmc_assume_removable; | ||
| 58 | 60 | ||
| 59 | /* Debugfs information for hosts and cards */ | 61 | /* Debugfs information for hosts and cards */ |
| 60 | void mmc_add_host_debugfs(struct mmc_host *host); | 62 | void mmc_add_host_debugfs(struct mmc_host *host); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index bfefce365ae7..c11189446a1f 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -602,25 +602,6 @@ static int mmc_awake(struct mmc_host *host) | |||
| 602 | return err; | 602 | return err; |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | #ifdef CONFIG_MMC_UNSAFE_RESUME | ||
| 606 | |||
| 607 | static const struct mmc_bus_ops mmc_ops = { | ||
| 608 | .awake = mmc_awake, | ||
| 609 | .sleep = mmc_sleep, | ||
| 610 | .remove = mmc_remove, | ||
| 611 | .detect = mmc_detect, | ||
| 612 | .suspend = mmc_suspend, | ||
| 613 | .resume = mmc_resume, | ||
| 614 | .power_restore = mmc_power_restore, | ||
| 615 | }; | ||
| 616 | |||
| 617 | static void mmc_attach_bus_ops(struct mmc_host *host) | ||
| 618 | { | ||
| 619 | mmc_attach_bus(host, &mmc_ops); | ||
| 620 | } | ||
| 621 | |||
| 622 | #else | ||
| 623 | |||
| 624 | static const struct mmc_bus_ops mmc_ops = { | 605 | static const struct mmc_bus_ops mmc_ops = { |
| 625 | .awake = mmc_awake, | 606 | .awake = mmc_awake, |
| 626 | .sleep = mmc_sleep, | 607 | .sleep = mmc_sleep, |
| @@ -645,15 +626,13 @@ static void mmc_attach_bus_ops(struct mmc_host *host) | |||
| 645 | { | 626 | { |
| 646 | const struct mmc_bus_ops *bus_ops; | 627 | const struct mmc_bus_ops *bus_ops; |
| 647 | 628 | ||
| 648 | if (host->caps & MMC_CAP_NONREMOVABLE) | 629 | if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable) |
| 649 | bus_ops = &mmc_ops_unsafe; | 630 | bus_ops = &mmc_ops_unsafe; |
| 650 | else | 631 | else |
| 651 | bus_ops = &mmc_ops; | 632 | bus_ops = &mmc_ops; |
| 652 | mmc_attach_bus(host, bus_ops); | 633 | mmc_attach_bus(host, bus_ops); |
| 653 | } | 634 | } |
| 654 | 635 | ||
| 655 | #endif | ||
| 656 | |||
| 657 | /* | 636 | /* |
| 658 | * Starting point for MMC card init. | 637 | * Starting point for MMC card init. |
| 659 | */ | 638 | */ |
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 10b2a4d20f5a..fdd414eded09 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -606,23 +606,6 @@ static void mmc_sd_power_restore(struct mmc_host *host) | |||
| 606 | mmc_release_host(host); | 606 | mmc_release_host(host); |
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | #ifdef CONFIG_MMC_UNSAFE_RESUME | ||
| 610 | |||
| 611 | static const struct mmc_bus_ops mmc_sd_ops = { | ||
| 612 | .remove = mmc_sd_remove, | ||
| 613 | .detect = mmc_sd_detect, | ||
| 614 | .suspend = mmc_sd_suspend, | ||
| 615 | .resume = mmc_sd_resume, | ||
| 616 | .power_restore = mmc_sd_power_restore, | ||
| 617 | }; | ||
| 618 | |||
| 619 | static void mmc_sd_attach_bus_ops(struct mmc_host *host) | ||
| 620 | { | ||
| 621 | mmc_attach_bus(host, &mmc_sd_ops); | ||
| 622 | } | ||
| 623 | |||
| 624 | #else | ||
| 625 | |||
| 626 | static const struct mmc_bus_ops mmc_sd_ops = { | 609 | static const struct mmc_bus_ops mmc_sd_ops = { |
| 627 | .remove = mmc_sd_remove, | 610 | .remove = mmc_sd_remove, |
| 628 | .detect = mmc_sd_detect, | 611 | .detect = mmc_sd_detect, |
| @@ -643,15 +626,13 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) | |||
| 643 | { | 626 | { |
| 644 | const struct mmc_bus_ops *bus_ops; | 627 | const struct mmc_bus_ops *bus_ops; |
| 645 | 628 | ||
| 646 | if (host->caps & MMC_CAP_NONREMOVABLE) | 629 | if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable) |
| 647 | bus_ops = &mmc_sd_ops_unsafe; | 630 | bus_ops = &mmc_sd_ops_unsafe; |
| 648 | else | 631 | else |
| 649 | bus_ops = &mmc_sd_ops; | 632 | bus_ops = &mmc_sd_ops; |
| 650 | mmc_attach_bus(host, bus_ops); | 633 | mmc_attach_bus(host, bus_ops); |
| 651 | } | 634 | } |
| 652 | 635 | ||
| 653 | #endif | ||
| 654 | |||
| 655 | /* | 636 | /* |
| 656 | * Starting point for SD card init. | 637 | * Starting point for SD card init. |
| 657 | */ | 638 | */ |
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index f85dcd536508..9538389783c1 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c | |||
| @@ -97,26 +97,56 @@ static const unsigned char speed_val[16] = | |||
| 97 | static const unsigned int speed_unit[8] = | 97 | static const unsigned int speed_unit[8] = |
| 98 | { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; | 98 | { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 }; |
| 99 | 99 | ||
| 100 | /* FUNCE tuples with these types get passed to SDIO drivers */ | 100 | |
| 101 | static const unsigned char funce_type_whitelist[] = { | 101 | typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *, |
| 102 | 4 /* CISTPL_FUNCE_LAN_NODE_ID used in Broadcom cards */ | 102 | const unsigned char *, unsigned); |
| 103 | |||
| 104 | struct cis_tpl { | ||
| 105 | unsigned char code; | ||
| 106 | unsigned char min_size; | ||
| 107 | tpl_parse_t *parse; | ||
| 103 | }; | 108 | }; |
| 104 | 109 | ||
| 105 | static int cistpl_funce_whitelisted(unsigned char type) | 110 | static int cis_tpl_parse(struct mmc_card *card, struct sdio_func *func, |
| 111 | const char *tpl_descr, | ||
| 112 | const struct cis_tpl *tpl, int tpl_count, | ||
| 113 | unsigned char code, | ||
| 114 | const unsigned char *buf, unsigned size) | ||
| 106 | { | 115 | { |
| 107 | int i; | 116 | int i, ret; |
| 108 | 117 | ||
| 109 | for (i = 0; i < ARRAY_SIZE(funce_type_whitelist); i++) { | 118 | /* look for a matching code in the table */ |
| 110 | if (funce_type_whitelist[i] == type) | 119 | for (i = 0; i < tpl_count; i++, tpl++) { |
| 111 | return 1; | 120 | if (tpl->code == code) |
| 121 | break; | ||
| 112 | } | 122 | } |
| 113 | return 0; | 123 | if (i < tpl_count) { |
| 124 | if (size >= tpl->min_size) { | ||
| 125 | if (tpl->parse) | ||
| 126 | ret = tpl->parse(card, func, buf, size); | ||
| 127 | else | ||
| 128 | ret = -EILSEQ; /* known tuple, not parsed */ | ||
| 129 | } else { | ||
| 130 | /* invalid tuple */ | ||
| 131 | ret = -EINVAL; | ||
| 132 | } | ||
| 133 | if (ret && ret != -EILSEQ && ret != -ENOENT) { | ||
| 134 | printk(KERN_ERR "%s: bad %s tuple 0x%02x (%u bytes)\n", | ||
| 135 | mmc_hostname(card->host), tpl_descr, code, size); | ||
| 136 | } | ||
| 137 | } else { | ||
| 138 | /* unknown tuple */ | ||
| 139 | ret = -ENOENT; | ||
| 140 | } | ||
| 141 | |||
| 142 | return ret; | ||
| 114 | } | 143 | } |
| 115 | 144 | ||
| 116 | static int cistpl_funce_common(struct mmc_card *card, | 145 | static int cistpl_funce_common(struct mmc_card *card, struct sdio_func *func, |
| 117 | const unsigned char *buf, unsigned size) | 146 | const unsigned char *buf, unsigned size) |
| 118 | { | 147 | { |
| 119 | if (size < 0x04 || buf[0] != 0) | 148 | /* Only valid for the common CIS (function 0) */ |
| 149 | if (func) | ||
| 120 | return -EINVAL; | 150 | return -EINVAL; |
| 121 | 151 | ||
| 122 | /* TPLFE_FN0_BLK_SIZE */ | 152 | /* TPLFE_FN0_BLK_SIZE */ |
| @@ -129,20 +159,24 @@ static int cistpl_funce_common(struct mmc_card *card, | |||
| 129 | return 0; | 159 | return 0; |
| 130 | } | 160 | } |
| 131 | 161 | ||
| 132 | static int cistpl_funce_func(struct sdio_func *func, | 162 | static int cistpl_funce_func(struct mmc_card *card, struct sdio_func *func, |
| 133 | const unsigned char *buf, unsigned size) | 163 | const unsigned char *buf, unsigned size) |
| 134 | { | 164 | { |
| 135 | unsigned vsn; | 165 | unsigned vsn; |
| 136 | unsigned min_size; | 166 | unsigned min_size; |
| 137 | 167 | ||
| 138 | /* let SDIO drivers take care of whitelisted FUNCE tuples */ | 168 | /* Only valid for the individual function's CIS (1-7) */ |
| 139 | if (cistpl_funce_whitelisted(buf[0])) | 169 | if (!func) |
| 140 | return -EILSEQ; | 170 | return -EINVAL; |
| 141 | 171 | ||
| 172 | /* | ||
| 173 | * This tuple has a different length depending on the SDIO spec | ||
| 174 | * version. | ||
| 175 | */ | ||
| 142 | vsn = func->card->cccr.sdio_vsn; | 176 | vsn = func->card->cccr.sdio_vsn; |
| 143 | min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42; | 177 | min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42; |
| 144 | 178 | ||
| 145 | if (size < min_size || buf[0] != 1) | 179 | if (size < min_size) |
| 146 | return -EINVAL; | 180 | return -EINVAL; |
| 147 | 181 | ||
| 148 | /* TPLFE_MAX_BLK_SIZE */ | 182 | /* TPLFE_MAX_BLK_SIZE */ |
| @@ -157,39 +191,32 @@ static int cistpl_funce_func(struct sdio_func *func, | |||
| 157 | return 0; | 191 | return 0; |
| 158 | } | 192 | } |
| 159 | 193 | ||
| 194 | /* | ||
| 195 | * Known TPLFE_TYPEs table for CISTPL_FUNCE tuples. | ||
| 196 | * | ||
| 197 | * Note that, unlike PCMCIA, CISTPL_FUNCE tuples are not parsed depending | ||
| 198 | * on the TPLFID_FUNCTION value of the previous CISTPL_FUNCID as on SDIO | ||
| 199 | * TPLFID_FUNCTION is always hardcoded to 0x0C. | ||
| 200 | */ | ||
| 201 | static const struct cis_tpl cis_tpl_funce_list[] = { | ||
| 202 | { 0x00, 4, cistpl_funce_common }, | ||
| 203 | { 0x01, 0, cistpl_funce_func }, | ||
| 204 | { 0x04, 1+1+6, /* CISTPL_FUNCE_LAN_NODE_ID */ }, | ||
| 205 | }; | ||
| 206 | |||
| 160 | static int cistpl_funce(struct mmc_card *card, struct sdio_func *func, | 207 | static int cistpl_funce(struct mmc_card *card, struct sdio_func *func, |
| 161 | const unsigned char *buf, unsigned size) | 208 | const unsigned char *buf, unsigned size) |
| 162 | { | 209 | { |
| 163 | int ret; | 210 | if (size < 1) |
| 164 | 211 | return -EINVAL; | |
| 165 | /* | ||
| 166 | * There should be two versions of the CISTPL_FUNCE tuple, | ||
| 167 | * one for the common CIS (function 0) and a version used by | ||
| 168 | * the individual function's CIS (1-7). Yet, the later has a | ||
| 169 | * different length depending on the SDIO spec version. | ||
| 170 | */ | ||
| 171 | if (func) | ||
| 172 | ret = cistpl_funce_func(func, buf, size); | ||
| 173 | else | ||
| 174 | ret = cistpl_funce_common(card, buf, size); | ||
| 175 | |||
| 176 | if (ret && ret != -EILSEQ) { | ||
| 177 | printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u " | ||
| 178 | "type %u\n", mmc_hostname(card->host), size, buf[0]); | ||
| 179 | } | ||
| 180 | 212 | ||
| 181 | return ret; | 213 | return cis_tpl_parse(card, func, "CISTPL_FUNCE", |
| 214 | cis_tpl_funce_list, | ||
| 215 | ARRAY_SIZE(cis_tpl_funce_list), | ||
| 216 | buf[0], buf, size); | ||
| 182 | } | 217 | } |
| 183 | 218 | ||
| 184 | typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *, | 219 | /* Known TPL_CODEs table for CIS tuples */ |
| 185 | const unsigned char *, unsigned); | ||
| 186 | |||
| 187 | struct cis_tpl { | ||
| 188 | unsigned char code; | ||
| 189 | unsigned char min_size; | ||
| 190 | tpl_parse_t *parse; | ||
| 191 | }; | ||
| 192 | |||
| 193 | static const struct cis_tpl cis_tpl_list[] = { | 220 | static const struct cis_tpl cis_tpl_list[] = { |
| 194 | { 0x15, 3, cistpl_vers_1 }, | 221 | { 0x15, 3, cistpl_vers_1 }, |
| 195 | { 0x20, 4, cistpl_manfid }, | 222 | { 0x20, 4, cistpl_manfid }, |
| @@ -268,46 +295,38 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) | |||
| 268 | break; | 295 | break; |
| 269 | } | 296 | } |
| 270 | 297 | ||
| 271 | for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++) | 298 | /* Try to parse the CIS tuple */ |
| 272 | if (cis_tpl_list[i].code == tpl_code) | 299 | ret = cis_tpl_parse(card, func, "CIS", |
| 273 | break; | 300 | cis_tpl_list, ARRAY_SIZE(cis_tpl_list), |
| 274 | if (i < ARRAY_SIZE(cis_tpl_list)) { | 301 | tpl_code, this->data, tpl_link); |
| 275 | const struct cis_tpl *tpl = cis_tpl_list + i; | 302 | if (ret == -EILSEQ || ret == -ENOENT) { |
| 276 | if (tpl_link < tpl->min_size) { | ||
| 277 | printk(KERN_ERR | ||
| 278 | "%s: bad CIS tuple 0x%02x" | ||
| 279 | " (length = %u, expected >= %u)\n", | ||
| 280 | mmc_hostname(card->host), | ||
| 281 | tpl_code, tpl_link, tpl->min_size); | ||
| 282 | ret = -EINVAL; | ||
| 283 | } else if (tpl->parse) { | ||
| 284 | ret = tpl->parse(card, func, | ||
| 285 | this->data, tpl_link); | ||
| 286 | } | ||
| 287 | /* | 303 | /* |
| 288 | * We don't need the tuple anymore if it was | 304 | * The tuple is unknown or known but not parsed. |
| 289 | * successfully parsed by the SDIO core or if it is | 305 | * Queue the tuple for the function driver. |
| 290 | * not going to be parsed by SDIO drivers. | ||
| 291 | */ | 306 | */ |
| 292 | if (!ret || ret != -EILSEQ) | ||
| 293 | kfree(this); | ||
| 294 | } else { | ||
| 295 | /* unknown tuple */ | ||
| 296 | ret = -EILSEQ; | ||
| 297 | } | ||
| 298 | |||
| 299 | if (ret == -EILSEQ) { | ||
| 300 | /* this tuple is unknown to the core or whitelisted */ | ||
| 301 | this->next = NULL; | 307 | this->next = NULL; |
| 302 | this->code = tpl_code; | 308 | this->code = tpl_code; |
| 303 | this->size = tpl_link; | 309 | this->size = tpl_link; |
| 304 | *prev = this; | 310 | *prev = this; |
| 305 | prev = &this->next; | 311 | prev = &this->next; |
| 306 | printk(KERN_DEBUG | 312 | |
| 307 | "%s: queuing CIS tuple 0x%02x length %u\n", | 313 | if (ret == -ENOENT) { |
| 308 | mmc_hostname(card->host), tpl_code, tpl_link); | 314 | /* warn about unknown tuples */ |
| 315 | printk(KERN_WARNING "%s: queuing unknown" | ||
| 316 | " CIS tuple 0x%02x (%u bytes)\n", | ||
| 317 | mmc_hostname(card->host), | ||
| 318 | tpl_code, tpl_link); | ||
| 319 | } | ||
| 320 | |||
| 309 | /* keep on analyzing tuples */ | 321 | /* keep on analyzing tuples */ |
| 310 | ret = 0; | 322 | ret = 0; |
| 323 | } else { | ||
| 324 | /* | ||
| 325 | * We don't need the tuple anymore if it was | ||
| 326 | * successfully parsed by the SDIO core or if it is | ||
| 327 | * not going to be queued for a driver. | ||
| 328 | */ | ||
| 329 | kfree(this); | ||
| 311 | } | 330 | } |
| 312 | 331 | ||
| 313 | ptr += tpl_link; | 332 | ptr += tpl_link; |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index e04b751680d0..9d405b181781 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -251,6 +251,14 @@ config MMC_MVSDIO | |||
| 251 | To compile this driver as a module, choose M here: the | 251 | To compile this driver as a module, choose M here: the |
| 252 | module will be called mvsdio. | 252 | module will be called mvsdio. |
| 253 | 253 | ||
| 254 | config MMC_DAVINCI | ||
| 255 | tristate "TI DAVINCI Multimedia Card Interface support" | ||
| 256 | depends on ARCH_DAVINCI | ||
| 257 | help | ||
| 258 | This selects the TI DAVINCI Multimedia card Interface. | ||
| 259 | If you have an DAVINCI board with a Multimedia Card slot, | ||
| 260 | say Y or M here. If unsure, say N. | ||
| 261 | |||
| 254 | config MMC_SPI | 262 | config MMC_SPI |
| 255 | tristate "MMC/SD/SDIO over SPI" | 263 | tristate "MMC/SD/SDIO over SPI" |
| 256 | depends on SPI_MASTER && !HIGHMEM && HAS_DMA | 264 | depends on SPI_MASTER && !HIGHMEM && HAS_DMA |
| @@ -357,3 +365,22 @@ config MMC_VIA_SDMMC | |||
| 357 | If you have a controller with this interface, say Y or M here. | 365 | If you have a controller with this interface, say Y or M here. |
| 358 | 366 | ||
| 359 | If unsure, say N. | 367 | If unsure, say N. |
| 368 | |||
| 369 | config SDH_BFIN | ||
| 370 | tristate "Blackfin Secure Digital Host support" | ||
| 371 | depends on MMC && ((BF54x && !BF544) || (BF51x && !BF512)) | ||
| 372 | help | ||
| 373 | If you say yes here you will get support for the Blackfin on-chip | ||
| 374 | Secure Digital Host interface. This includes support for MMC and | ||
| 375 | SD cards. | ||
| 376 | |||
| 377 | To compile this driver as a module, choose M here: the | ||
| 378 | module will be called bfin_sdh. | ||
| 379 | |||
| 380 | If unsure, say N. | ||
| 381 | |||
| 382 | config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
| 383 | bool "Blackfin EZkit Missing SDH_CMD Pull Up Resistor Workaround" | ||
| 384 | depends on SDH_BFIN | ||
| 385 | help | ||
| 386 | If you say yes here SD-Cards may work on the EZkit. | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index abcb0400e06d..ded4d8cdd9d7 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -25,6 +25,7 @@ obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o | |||
| 25 | obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o | 25 | obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o |
| 26 | obj-$(CONFIG_MMC_MSM7X00A) += msm_sdcc.o | 26 | obj-$(CONFIG_MMC_MSM7X00A) += msm_sdcc.o |
| 27 | obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o | 27 | obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o |
| 28 | obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o | ||
| 28 | obj-$(CONFIG_MMC_SPI) += mmc_spi.o | 29 | obj-$(CONFIG_MMC_SPI) += mmc_spi.o |
| 29 | ifeq ($(CONFIG_OF),y) | 30 | ifeq ($(CONFIG_OF),y) |
| 30 | obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o | 31 | obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o |
| @@ -34,6 +35,7 @@ obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o | |||
| 34 | obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o | 35 | obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o |
| 35 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o | 36 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o |
| 36 | obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o | 37 | obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o |
| 38 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | ||
| 37 | 39 | ||
| 38 | ifeq ($(CONFIG_CB710_DEBUG),y) | 40 | ifeq ($(CONFIG_CB710_DEBUG),y) |
| 39 | CFLAGS-cb710-mmc += -DDEBUG | 41 | CFLAGS-cb710-mmc += -DDEBUG |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fc25586b7ee1..8072128e933b 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include <linux/stat.h> | 25 | #include <linux/stat.h> |
| 26 | 26 | ||
| 27 | #include <linux/mmc/host.h> | 27 | #include <linux/mmc/host.h> |
| 28 | |||
| 29 | #include <mach/atmel-mci.h> | ||
| 28 | #include <linux/atmel-mci.h> | 30 | #include <linux/atmel-mci.h> |
| 29 | 31 | ||
| 30 | #include <asm/io.h> | 32 | #include <asm/io.h> |
| @@ -92,6 +94,7 @@ struct atmel_mci_dma { | |||
| 92 | * @need_clock_update: Update the clock rate before the next request. | 94 | * @need_clock_update: Update the clock rate before the next request. |
| 93 | * @need_reset: Reset controller before next request. | 95 | * @need_reset: Reset controller before next request. |
| 94 | * @mode_reg: Value of the MR register. | 96 | * @mode_reg: Value of the MR register. |
| 97 | * @cfg_reg: Value of the CFG register. | ||
| 95 | * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus | 98 | * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus |
| 96 | * rate and timeout calculations. | 99 | * rate and timeout calculations. |
| 97 | * @mapbase: Physical address of the MMIO registers. | 100 | * @mapbase: Physical address of the MMIO registers. |
| @@ -155,6 +158,7 @@ struct atmel_mci { | |||
| 155 | bool need_clock_update; | 158 | bool need_clock_update; |
| 156 | bool need_reset; | 159 | bool need_reset; |
| 157 | u32 mode_reg; | 160 | u32 mode_reg; |
| 161 | u32 cfg_reg; | ||
| 158 | unsigned long bus_hz; | 162 | unsigned long bus_hz; |
| 159 | unsigned long mapbase; | 163 | unsigned long mapbase; |
| 160 | struct clk *mck; | 164 | struct clk *mck; |
| @@ -223,6 +227,19 @@ static bool mci_has_rwproof(void) | |||
| 223 | } | 227 | } |
| 224 | 228 | ||
| 225 | /* | 229 | /* |
| 230 | * The new MCI2 module isn't 100% compatible with the old MCI module, | ||
| 231 | * and it has a few nice features which we want to use... | ||
| 232 | */ | ||
| 233 | static inline bool atmci_is_mci2(void) | ||
| 234 | { | ||
| 235 | if (cpu_is_at91sam9g45()) | ||
| 236 | return true; | ||
| 237 | |||
| 238 | return false; | ||
| 239 | } | ||
| 240 | |||
| 241 | |||
| 242 | /* | ||
| 226 | * The debugfs stuff below is mostly optimized away when | 243 | * The debugfs stuff below is mostly optimized away when |
| 227 | * CONFIG_DEBUG_FS is not set. | 244 | * CONFIG_DEBUG_FS is not set. |
| 228 | */ | 245 | */ |
| @@ -357,12 +374,33 @@ static int atmci_regs_show(struct seq_file *s, void *v) | |||
| 357 | buf[MCI_BLKR / 4], | 374 | buf[MCI_BLKR / 4], |
| 358 | buf[MCI_BLKR / 4] & 0xffff, | 375 | buf[MCI_BLKR / 4] & 0xffff, |
| 359 | (buf[MCI_BLKR / 4] >> 16) & 0xffff); | 376 | (buf[MCI_BLKR / 4] >> 16) & 0xffff); |
| 377 | if (atmci_is_mci2()) | ||
| 378 | seq_printf(s, "CSTOR:\t0x%08x\n", buf[MCI_CSTOR / 4]); | ||
| 360 | 379 | ||
| 361 | /* Don't read RSPR and RDR; it will consume the data there */ | 380 | /* Don't read RSPR and RDR; it will consume the data there */ |
| 362 | 381 | ||
| 363 | atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); | 382 | atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]); |
| 364 | atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); | 383 | atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]); |
| 365 | 384 | ||
| 385 | if (atmci_is_mci2()) { | ||
| 386 | u32 val; | ||
| 387 | |||
| 388 | val = buf[MCI_DMA / 4]; | ||
| 389 | seq_printf(s, "DMA:\t0x%08x OFFSET=%u CHKSIZE=%u%s\n", | ||
| 390 | val, val & 3, | ||
| 391 | ((val >> 4) & 3) ? | ||
| 392 | 1 << (((val >> 4) & 3) + 1) : 1, | ||
| 393 | val & MCI_DMAEN ? " DMAEN" : ""); | ||
| 394 | |||
| 395 | val = buf[MCI_CFG / 4]; | ||
| 396 | seq_printf(s, "CFG:\t0x%08x%s%s%s%s\n", | ||
| 397 | val, | ||
| 398 | val & MCI_CFG_FIFOMODE_1DATA ? " FIFOMODE_ONE_DATA" : "", | ||
| 399 | val & MCI_CFG_FERRCTRL_COR ? " FERRCTRL_CLEAR_ON_READ" : "", | ||
| 400 | val & MCI_CFG_HSMODE ? " HSMODE" : "", | ||
| 401 | val & MCI_CFG_LSYNC ? " LSYNC" : ""); | ||
| 402 | } | ||
| 403 | |||
| 366 | kfree(buf); | 404 | kfree(buf); |
| 367 | 405 | ||
| 368 | return 0; | 406 | return 0; |
| @@ -557,6 +595,10 @@ static void atmci_dma_complete(void *arg) | |||
| 557 | 595 | ||
| 558 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); | 596 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); |
| 559 | 597 | ||
| 598 | if (atmci_is_mci2()) | ||
| 599 | /* Disable DMA hardware handshaking on MCI */ | ||
| 600 | mci_writel(host, DMA, mci_readl(host, DMA) & ~MCI_DMAEN); | ||
| 601 | |||
| 560 | atmci_dma_cleanup(host); | 602 | atmci_dma_cleanup(host); |
| 561 | 603 | ||
| 562 | /* | 604 | /* |
| @@ -592,7 +634,7 @@ static void atmci_dma_complete(void *arg) | |||
| 592 | } | 634 | } |
| 593 | 635 | ||
| 594 | static int | 636 | static int |
| 595 | atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | 637 | atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) |
| 596 | { | 638 | { |
| 597 | struct dma_chan *chan; | 639 | struct dma_chan *chan; |
| 598 | struct dma_async_tx_descriptor *desc; | 640 | struct dma_async_tx_descriptor *desc; |
| @@ -624,6 +666,9 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | |||
| 624 | if (!chan) | 666 | if (!chan) |
| 625 | return -ENODEV; | 667 | return -ENODEV; |
| 626 | 668 | ||
| 669 | if (atmci_is_mci2()) | ||
| 670 | mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN); | ||
| 671 | |||
| 627 | if (data->flags & MMC_DATA_READ) | 672 | if (data->flags & MMC_DATA_READ) |
| 628 | direction = DMA_FROM_DEVICE; | 673 | direction = DMA_FROM_DEVICE; |
| 629 | else | 674 | else |
| @@ -641,10 +686,6 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | |||
| 641 | host->dma.data_desc = desc; | 686 | host->dma.data_desc = desc; |
| 642 | desc->callback = atmci_dma_complete; | 687 | desc->callback = atmci_dma_complete; |
| 643 | desc->callback_param = host; | 688 | desc->callback_param = host; |
| 644 | desc->tx_submit(desc); | ||
| 645 | |||
| 646 | /* Go! */ | ||
| 647 | chan->device->device_issue_pending(chan); | ||
| 648 | 689 | ||
| 649 | return 0; | 690 | return 0; |
| 650 | unmap_exit: | 691 | unmap_exit: |
| @@ -652,13 +693,26 @@ unmap_exit: | |||
| 652 | return -ENOMEM; | 693 | return -ENOMEM; |
| 653 | } | 694 | } |
| 654 | 695 | ||
| 696 | static void atmci_submit_data(struct atmel_mci *host) | ||
| 697 | { | ||
| 698 | struct dma_chan *chan = host->data_chan; | ||
| 699 | struct dma_async_tx_descriptor *desc = host->dma.data_desc; | ||
| 700 | |||
| 701 | if (chan) { | ||
| 702 | desc->tx_submit(desc); | ||
| 703 | chan->device->device_issue_pending(chan); | ||
| 704 | } | ||
| 705 | } | ||
| 706 | |||
| 655 | #else /* CONFIG_MMC_ATMELMCI_DMA */ | 707 | #else /* CONFIG_MMC_ATMELMCI_DMA */ |
| 656 | 708 | ||
| 657 | static int atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | 709 | static int atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) |
| 658 | { | 710 | { |
| 659 | return -ENOSYS; | 711 | return -ENOSYS; |
| 660 | } | 712 | } |
| 661 | 713 | ||
| 714 | static void atmci_submit_data(struct atmel_mci *host) {} | ||
| 715 | |||
| 662 | static void atmci_stop_dma(struct atmel_mci *host) | 716 | static void atmci_stop_dma(struct atmel_mci *host) |
| 663 | { | 717 | { |
| 664 | /* Data transfer was stopped by the interrupt handler */ | 718 | /* Data transfer was stopped by the interrupt handler */ |
| @@ -672,7 +726,7 @@ static void atmci_stop_dma(struct atmel_mci *host) | |||
| 672 | * Returns a mask of interrupt flags to be enabled after the whole | 726 | * Returns a mask of interrupt flags to be enabled after the whole |
| 673 | * request has been prepared. | 727 | * request has been prepared. |
| 674 | */ | 728 | */ |
| 675 | static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) | 729 | static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) |
| 676 | { | 730 | { |
| 677 | u32 iflags; | 731 | u32 iflags; |
| 678 | 732 | ||
| @@ -683,7 +737,7 @@ static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) | |||
| 683 | host->data = data; | 737 | host->data = data; |
| 684 | 738 | ||
| 685 | iflags = ATMCI_DATA_ERROR_FLAGS; | 739 | iflags = ATMCI_DATA_ERROR_FLAGS; |
| 686 | if (atmci_submit_data_dma(host, data)) { | 740 | if (atmci_prepare_data_dma(host, data)) { |
| 687 | host->data_chan = NULL; | 741 | host->data_chan = NULL; |
| 688 | 742 | ||
| 689 | /* | 743 | /* |
| @@ -729,6 +783,8 @@ static void atmci_start_request(struct atmel_mci *host, | |||
| 729 | mci_writel(host, CR, MCI_CR_SWRST); | 783 | mci_writel(host, CR, MCI_CR_SWRST); |
| 730 | mci_writel(host, CR, MCI_CR_MCIEN); | 784 | mci_writel(host, CR, MCI_CR_MCIEN); |
| 731 | mci_writel(host, MR, host->mode_reg); | 785 | mci_writel(host, MR, host->mode_reg); |
| 786 | if (atmci_is_mci2()) | ||
| 787 | mci_writel(host, CFG, host->cfg_reg); | ||
| 732 | host->need_reset = false; | 788 | host->need_reset = false; |
| 733 | } | 789 | } |
| 734 | mci_writel(host, SDCR, slot->sdc_reg); | 790 | mci_writel(host, SDCR, slot->sdc_reg); |
| @@ -744,6 +800,7 @@ static void atmci_start_request(struct atmel_mci *host, | |||
| 744 | while (!(mci_readl(host, SR) & MCI_CMDRDY)) | 800 | while (!(mci_readl(host, SR) & MCI_CMDRDY)) |
| 745 | cpu_relax(); | 801 | cpu_relax(); |
| 746 | } | 802 | } |
| 803 | iflags = 0; | ||
| 747 | data = mrq->data; | 804 | data = mrq->data; |
| 748 | if (data) { | 805 | if (data) { |
| 749 | atmci_set_timeout(host, slot, data); | 806 | atmci_set_timeout(host, slot, data); |
| @@ -753,15 +810,17 @@ static void atmci_start_request(struct atmel_mci *host, | |||
| 753 | | MCI_BLKLEN(data->blksz)); | 810 | | MCI_BLKLEN(data->blksz)); |
| 754 | dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", | 811 | dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", |
| 755 | MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); | 812 | MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); |
| 813 | |||
| 814 | iflags |= atmci_prepare_data(host, data); | ||
| 756 | } | 815 | } |
| 757 | 816 | ||
| 758 | iflags = MCI_CMDRDY; | 817 | iflags |= MCI_CMDRDY; |
| 759 | cmd = mrq->cmd; | 818 | cmd = mrq->cmd; |
| 760 | cmdflags = atmci_prepare_command(slot->mmc, cmd); | 819 | cmdflags = atmci_prepare_command(slot->mmc, cmd); |
| 761 | atmci_start_command(host, cmd, cmdflags); | 820 | atmci_start_command(host, cmd, cmdflags); |
| 762 | 821 | ||
| 763 | if (data) | 822 | if (data) |
| 764 | iflags |= atmci_submit_data(host, data); | 823 | atmci_submit_data(host); |
| 765 | 824 | ||
| 766 | if (mrq->stop) { | 825 | if (mrq->stop) { |
| 767 | host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); | 826 | host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); |
| @@ -857,6 +916,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 857 | clk_enable(host->mck); | 916 | clk_enable(host->mck); |
| 858 | mci_writel(host, CR, MCI_CR_SWRST); | 917 | mci_writel(host, CR, MCI_CR_SWRST); |
| 859 | mci_writel(host, CR, MCI_CR_MCIEN); | 918 | mci_writel(host, CR, MCI_CR_MCIEN); |
| 919 | if (atmci_is_mci2()) | ||
| 920 | mci_writel(host, CFG, host->cfg_reg); | ||
| 860 | } | 921 | } |
| 861 | 922 | ||
| 862 | /* | 923 | /* |
| @@ -1095,6 +1156,8 @@ static void atmci_detect_change(unsigned long data) | |||
| 1095 | mci_writel(host, CR, MCI_CR_SWRST); | 1156 | mci_writel(host, CR, MCI_CR_SWRST); |
| 1096 | mci_writel(host, CR, MCI_CR_MCIEN); | 1157 | mci_writel(host, CR, MCI_CR_MCIEN); |
| 1097 | mci_writel(host, MR, host->mode_reg); | 1158 | mci_writel(host, MR, host->mode_reg); |
| 1159 | if (atmci_is_mci2()) | ||
| 1160 | mci_writel(host, CFG, host->cfg_reg); | ||
| 1098 | 1161 | ||
| 1099 | host->data = NULL; | 1162 | host->data = NULL; |
| 1100 | host->cmd = NULL; | 1163 | host->cmd = NULL; |
| @@ -1584,14 +1647,47 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, | |||
| 1584 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1647 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
| 1585 | static bool filter(struct dma_chan *chan, void *slave) | 1648 | static bool filter(struct dma_chan *chan, void *slave) |
| 1586 | { | 1649 | { |
| 1587 | struct dw_dma_slave *dws = slave; | 1650 | struct mci_dma_data *sl = slave; |
| 1588 | 1651 | ||
| 1589 | if (dws->dma_dev == chan->device->dev) { | 1652 | if (sl && find_slave_dev(sl) == chan->device->dev) { |
| 1590 | chan->private = dws; | 1653 | chan->private = slave_data_ptr(sl); |
| 1591 | return true; | 1654 | return true; |
| 1592 | } else | 1655 | } else { |
| 1593 | return false; | 1656 | return false; |
| 1657 | } | ||
| 1594 | } | 1658 | } |
| 1659 | |||
| 1660 | static void atmci_configure_dma(struct atmel_mci *host) | ||
| 1661 | { | ||
| 1662 | struct mci_platform_data *pdata; | ||
| 1663 | |||
| 1664 | if (host == NULL) | ||
| 1665 | return; | ||
| 1666 | |||
| 1667 | pdata = host->pdev->dev.platform_data; | ||
| 1668 | |||
| 1669 | if (pdata && find_slave_dev(pdata->dma_slave)) { | ||
| 1670 | dma_cap_mask_t mask; | ||
| 1671 | |||
| 1672 | setup_dma_addr(pdata->dma_slave, | ||
| 1673 | host->mapbase + MCI_TDR, | ||
| 1674 | host->mapbase + MCI_RDR); | ||
| 1675 | |||
| 1676 | /* Try to grab a DMA channel */ | ||
| 1677 | dma_cap_zero(mask); | ||
| 1678 | dma_cap_set(DMA_SLAVE, mask); | ||
| 1679 | host->dma.chan = | ||
| 1680 | dma_request_channel(mask, filter, pdata->dma_slave); | ||
| 1681 | } | ||
| 1682 | if (!host->dma.chan) | ||
| 1683 | dev_notice(&host->pdev->dev, "DMA not available, using PIO\n"); | ||
| 1684 | else | ||
| 1685 | dev_info(&host->pdev->dev, | ||
| 1686 | "Using %s for DMA transfers\n", | ||
| 1687 | dma_chan_name(host->dma.chan)); | ||
| 1688 | } | ||
| 1689 | #else | ||
| 1690 | static void atmci_configure_dma(struct atmel_mci *host) {} | ||
| 1595 | #endif | 1691 | #endif |
| 1596 | 1692 | ||
| 1597 | static int __init atmci_probe(struct platform_device *pdev) | 1693 | static int __init atmci_probe(struct platform_device *pdev) |
| @@ -1645,22 +1741,7 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
| 1645 | if (ret) | 1741 | if (ret) |
| 1646 | goto err_request_irq; | 1742 | goto err_request_irq; |
| 1647 | 1743 | ||
| 1648 | #ifdef CONFIG_MMC_ATMELMCI_DMA | 1744 | atmci_configure_dma(host); |
| 1649 | if (pdata->dma_slave.dma_dev) { | ||
| 1650 | struct dw_dma_slave *dws = &pdata->dma_slave; | ||
| 1651 | dma_cap_mask_t mask; | ||
| 1652 | |||
| 1653 | dws->tx_reg = regs->start + MCI_TDR; | ||
| 1654 | dws->rx_reg = regs->start + MCI_RDR; | ||
| 1655 | |||
| 1656 | /* Try to grab a DMA channel */ | ||
| 1657 | dma_cap_zero(mask); | ||
| 1658 | dma_cap_set(DMA_SLAVE, mask); | ||
| 1659 | host->dma.chan = dma_request_channel(mask, filter, dws); | ||
| 1660 | } | ||
| 1661 | if (!host->dma.chan) | ||
| 1662 | dev_notice(&pdev->dev, "DMA not available, using PIO\n"); | ||
| 1663 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | ||
| 1664 | 1745 | ||
| 1665 | platform_set_drvdata(pdev, host); | 1746 | platform_set_drvdata(pdev, host); |
| 1666 | 1747 | ||
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c new file mode 100644 index 000000000000..3343a57355cc --- /dev/null +++ b/drivers/mmc/host/bfin_sdh.c | |||
| @@ -0,0 +1,639 @@ | |||
| 1 | /* | ||
| 2 | * bfin_sdh.c - Analog Devices Blackfin SDH Controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007-2009 Analog Device Inc. | ||
| 5 | * | ||
| 6 | * Licensed under the GPL-2 or later. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #define DRIVER_NAME "bfin-sdh" | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/ioport.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/dma-mapping.h> | ||
| 18 | #include <linux/mmc/host.h> | ||
| 19 | #include <linux/proc_fs.h> | ||
| 20 | |||
| 21 | #include <asm/cacheflush.h> | ||
| 22 | #include <asm/dma.h> | ||
| 23 | #include <asm/portmux.h> | ||
| 24 | #include <asm/bfin_sdh.h> | ||
| 25 | |||
| 26 | #if defined(CONFIG_BF51x) | ||
| 27 | #define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL | ||
| 28 | #define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL | ||
| 29 | #define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CTL | ||
| 30 | #define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CTL | ||
| 31 | #define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT | ||
| 32 | #define bfin_write_SDH_COMMAND bfin_write_RSI_COMMAND | ||
| 33 | #define bfin_write_SDH_DATA_TIMER bfin_write_RSI_DATA_TIMER | ||
| 34 | #define bfin_read_SDH_RESPONSE0 bfin_read_RSI_RESPONSE0 | ||
| 35 | #define bfin_read_SDH_RESPONSE1 bfin_read_RSI_RESPONSE1 | ||
| 36 | #define bfin_read_SDH_RESPONSE2 bfin_read_RSI_RESPONSE2 | ||
| 37 | #define bfin_read_SDH_RESPONSE3 bfin_read_RSI_RESPONSE3 | ||
| 38 | #define bfin_write_SDH_DATA_LGTH bfin_write_RSI_DATA_LGTH | ||
| 39 | #define bfin_read_SDH_DATA_CTL bfin_read_RSI_DATA_CTL | ||
| 40 | #define bfin_write_SDH_DATA_CTL bfin_write_RSI_DATA_CTL | ||
| 41 | #define bfin_read_SDH_DATA_CNT bfin_read_RSI_DATA_CNT | ||
| 42 | #define bfin_write_SDH_STATUS_CLR bfin_write_RSI_STATUS_CLR | ||
| 43 | #define bfin_read_SDH_E_STATUS bfin_read_RSI_E_STATUS | ||
| 44 | #define bfin_write_SDH_E_STATUS bfin_write_RSI_E_STATUS | ||
| 45 | #define bfin_read_SDH_STATUS bfin_read_RSI_STATUS | ||
| 46 | #define bfin_write_SDH_MASK0 bfin_write_RSI_MASK0 | ||
| 47 | #define bfin_read_SDH_CFG bfin_read_RSI_CFG | ||
| 48 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG | ||
| 49 | #endif | ||
| 50 | |||
| 51 | struct dma_desc_array { | ||
| 52 | unsigned long start_addr; | ||
| 53 | unsigned short cfg; | ||
| 54 | unsigned short x_count; | ||
| 55 | short x_modify; | ||
| 56 | } __packed; | ||
| 57 | |||
| 58 | struct sdh_host { | ||
| 59 | struct mmc_host *mmc; | ||
| 60 | spinlock_t lock; | ||
| 61 | struct resource *res; | ||
| 62 | void __iomem *base; | ||
| 63 | int irq; | ||
| 64 | int stat_irq; | ||
| 65 | int dma_ch; | ||
| 66 | int dma_dir; | ||
| 67 | struct dma_desc_array *sg_cpu; | ||
| 68 | dma_addr_t sg_dma; | ||
| 69 | int dma_len; | ||
| 70 | |||
| 71 | unsigned int imask; | ||
| 72 | unsigned int power_mode; | ||
| 73 | unsigned int clk_div; | ||
| 74 | |||
| 75 | struct mmc_request *mrq; | ||
| 76 | struct mmc_command *cmd; | ||
| 77 | struct mmc_data *data; | ||
| 78 | }; | ||
| 79 | |||
| 80 | static struct bfin_sd_host *get_sdh_data(struct platform_device *pdev) | ||
| 81 | { | ||
| 82 | return pdev->dev.platform_data; | ||
| 83 | } | ||
| 84 | |||
| 85 | static void sdh_stop_clock(struct sdh_host *host) | ||
| 86 | { | ||
| 87 | bfin_write_SDH_CLK_CTL(bfin_read_SDH_CLK_CTL() & ~CLK_E); | ||
| 88 | SSYNC(); | ||
| 89 | } | ||
| 90 | |||
| 91 | static void sdh_enable_stat_irq(struct sdh_host *host, unsigned int mask) | ||
| 92 | { | ||
| 93 | unsigned long flags; | ||
| 94 | |||
| 95 | spin_lock_irqsave(&host->lock, flags); | ||
| 96 | host->imask |= mask; | ||
| 97 | bfin_write_SDH_MASK0(mask); | ||
| 98 | SSYNC(); | ||
| 99 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 100 | } | ||
| 101 | |||
| 102 | static void sdh_disable_stat_irq(struct sdh_host *host, unsigned int mask) | ||
| 103 | { | ||
| 104 | unsigned long flags; | ||
| 105 | |||
| 106 | spin_lock_irqsave(&host->lock, flags); | ||
| 107 | host->imask &= ~mask; | ||
| 108 | bfin_write_SDH_MASK0(host->imask); | ||
| 109 | SSYNC(); | ||
| 110 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 111 | } | ||
| 112 | |||
| 113 | static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | ||
| 114 | { | ||
| 115 | unsigned int length; | ||
| 116 | unsigned int data_ctl; | ||
| 117 | unsigned int dma_cfg; | ||
| 118 | struct scatterlist *sg; | ||
| 119 | |||
| 120 | dev_dbg(mmc_dev(host->mmc), "%s enter flags: 0x%x\n", __func__, data->flags); | ||
| 121 | host->data = data; | ||
| 122 | data_ctl = 0; | ||
| 123 | dma_cfg = 0; | ||
| 124 | |||
| 125 | length = data->blksz * data->blocks; | ||
| 126 | bfin_write_SDH_DATA_LGTH(length); | ||
| 127 | |||
| 128 | if (data->flags & MMC_DATA_STREAM) | ||
| 129 | data_ctl |= DTX_MODE; | ||
| 130 | |||
| 131 | if (data->flags & MMC_DATA_READ) | ||
| 132 | data_ctl |= DTX_DIR; | ||
| 133 | /* Only supports power-of-2 block size */ | ||
| 134 | if (data->blksz & (data->blksz - 1)) | ||
| 135 | return -EINVAL; | ||
| 136 | data_ctl |= ((ffs(data->blksz) - 1) << 4); | ||
| 137 | |||
| 138 | bfin_write_SDH_DATA_CTL(data_ctl); | ||
| 139 | |||
| 140 | bfin_write_SDH_DATA_TIMER(0xFFFF); | ||
| 141 | SSYNC(); | ||
| 142 | |||
| 143 | if (data->flags & MMC_DATA_READ) { | ||
| 144 | host->dma_dir = DMA_FROM_DEVICE; | ||
| 145 | dma_cfg |= WNR; | ||
| 146 | } else | ||
| 147 | host->dma_dir = DMA_TO_DEVICE; | ||
| 148 | |||
| 149 | sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); | ||
| 150 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); | ||
| 151 | #if defined(CONFIG_BF54x) | ||
| 152 | dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN; | ||
| 153 | { | ||
| 154 | int i; | ||
| 155 | for_each_sg(data->sg, sg, host->dma_len, i) { | ||
| 156 | host->sg_cpu[i].start_addr = sg_dma_address(sg); | ||
| 157 | host->sg_cpu[i].cfg = dma_cfg; | ||
| 158 | host->sg_cpu[i].x_count = sg_dma_len(sg) / 4; | ||
| 159 | host->sg_cpu[i].x_modify = 4; | ||
| 160 | dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, " | ||
| 161 | "cfg:0x%x, x_count:0x%x, x_modify:0x%x\n", | ||
| 162 | i, host->sg_cpu[i].start_addr, | ||
| 163 | host->sg_cpu[i].cfg, host->sg_cpu[i].x_count, | ||
| 164 | host->sg_cpu[i].x_modify); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | flush_dcache_range((unsigned int)host->sg_cpu, | ||
| 168 | (unsigned int)host->sg_cpu + | ||
| 169 | host->dma_len * sizeof(struct dma_desc_array)); | ||
| 170 | /* Set the last descriptor to stop mode */ | ||
| 171 | host->sg_cpu[host->dma_len - 1].cfg &= ~(DMAFLOW | NDSIZE); | ||
| 172 | host->sg_cpu[host->dma_len - 1].cfg |= DI_EN; | ||
| 173 | |||
| 174 | set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma); | ||
| 175 | set_dma_x_count(host->dma_ch, 0); | ||
| 176 | set_dma_x_modify(host->dma_ch, 0); | ||
| 177 | set_dma_config(host->dma_ch, dma_cfg); | ||
| 178 | #elif defined(CONFIG_BF51x) | ||
| 179 | /* RSI DMA doesn't work in array mode */ | ||
| 180 | dma_cfg |= WDSIZE_32 | DMAEN; | ||
| 181 | set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0])); | ||
| 182 | set_dma_x_count(host->dma_ch, length / 4); | ||
| 183 | set_dma_x_modify(host->dma_ch, 4); | ||
| 184 | set_dma_config(host->dma_ch, dma_cfg); | ||
| 185 | #endif | ||
| 186 | bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); | ||
| 187 | |||
| 188 | SSYNC(); | ||
| 189 | |||
| 190 | dev_dbg(mmc_dev(host->mmc), "%s exit\n", __func__); | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static void sdh_start_cmd(struct sdh_host *host, struct mmc_command *cmd) | ||
| 195 | { | ||
| 196 | unsigned int sdh_cmd; | ||
| 197 | unsigned int stat_mask; | ||
| 198 | |||
| 199 | dev_dbg(mmc_dev(host->mmc), "%s enter cmd: 0x%p\n", __func__, cmd); | ||
| 200 | WARN_ON(host->cmd != NULL); | ||
| 201 | host->cmd = cmd; | ||
| 202 | |||
| 203 | sdh_cmd = 0; | ||
| 204 | stat_mask = 0; | ||
| 205 | |||
| 206 | sdh_cmd |= cmd->opcode; | ||
| 207 | |||
| 208 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
| 209 | sdh_cmd |= CMD_RSP; | ||
| 210 | stat_mask |= CMD_RESP_END; | ||
| 211 | } else { | ||
| 212 | stat_mask |= CMD_SENT; | ||
| 213 | } | ||
| 214 | |||
| 215 | if (cmd->flags & MMC_RSP_136) | ||
| 216 | sdh_cmd |= CMD_L_RSP; | ||
| 217 | |||
| 218 | stat_mask |= CMD_CRC_FAIL | CMD_TIME_OUT; | ||
| 219 | |||
| 220 | sdh_enable_stat_irq(host, stat_mask); | ||
| 221 | |||
| 222 | bfin_write_SDH_ARGUMENT(cmd->arg); | ||
| 223 | bfin_write_SDH_COMMAND(sdh_cmd | CMD_E); | ||
| 224 | bfin_write_SDH_CLK_CTL(bfin_read_SDH_CLK_CTL() | CLK_E); | ||
| 225 | SSYNC(); | ||
| 226 | } | ||
| 227 | |||
| 228 | static void sdh_finish_request(struct sdh_host *host, struct mmc_request *mrq) | ||
| 229 | { | ||
| 230 | dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); | ||
| 231 | host->mrq = NULL; | ||
| 232 | host->cmd = NULL; | ||
| 233 | host->data = NULL; | ||
| 234 | mmc_request_done(host->mmc, mrq); | ||
| 235 | } | ||
| 236 | |||
| 237 | static int sdh_cmd_done(struct sdh_host *host, unsigned int stat) | ||
| 238 | { | ||
| 239 | struct mmc_command *cmd = host->cmd; | ||
| 240 | int ret = 0; | ||
| 241 | |||
| 242 | dev_dbg(mmc_dev(host->mmc), "%s enter cmd: %p\n", __func__, cmd); | ||
| 243 | if (!cmd) | ||
| 244 | return 0; | ||
| 245 | |||
| 246 | host->cmd = NULL; | ||
| 247 | |||
| 248 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
| 249 | cmd->resp[0] = bfin_read_SDH_RESPONSE0(); | ||
| 250 | if (cmd->flags & MMC_RSP_136) { | ||
| 251 | cmd->resp[1] = bfin_read_SDH_RESPONSE1(); | ||
| 252 | cmd->resp[2] = bfin_read_SDH_RESPONSE2(); | ||
| 253 | cmd->resp[3] = bfin_read_SDH_RESPONSE3(); | ||
| 254 | } | ||
| 255 | } | ||
| 256 | if (stat & CMD_TIME_OUT) | ||
| 257 | cmd->error = -ETIMEDOUT; | ||
| 258 | else if (stat & CMD_CRC_FAIL && cmd->flags & MMC_RSP_CRC) | ||
| 259 | cmd->error = -EILSEQ; | ||
| 260 | |||
| 261 | sdh_disable_stat_irq(host, (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | CMD_CRC_FAIL)); | ||
| 262 | |||
| 263 | if (host->data && !cmd->error) { | ||
| 264 | if (host->data->flags & MMC_DATA_WRITE) { | ||
| 265 | ret = sdh_setup_data(host, host->data); | ||
| 266 | if (ret) | ||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | sdh_enable_stat_irq(host, DAT_END | RX_OVERRUN | TX_UNDERRUN | DAT_TIME_OUT); | ||
| 271 | } else | ||
| 272 | sdh_finish_request(host, host->mrq); | ||
| 273 | |||
| 274 | return 1; | ||
| 275 | } | ||
| 276 | |||
| 277 | static int sdh_data_done(struct sdh_host *host, unsigned int stat) | ||
| 278 | { | ||
| 279 | struct mmc_data *data = host->data; | ||
| 280 | |||
| 281 | dev_dbg(mmc_dev(host->mmc), "%s enter stat: 0x%x\n", __func__, stat); | ||
| 282 | if (!data) | ||
| 283 | return 0; | ||
| 284 | |||
| 285 | disable_dma(host->dma_ch); | ||
| 286 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | ||
| 287 | host->dma_dir); | ||
| 288 | |||
| 289 | if (stat & DAT_TIME_OUT) | ||
| 290 | data->error = -ETIMEDOUT; | ||
| 291 | else if (stat & DAT_CRC_FAIL) | ||
| 292 | data->error = -EILSEQ; | ||
| 293 | else if (stat & (RX_OVERRUN | TX_UNDERRUN)) | ||
| 294 | data->error = -EIO; | ||
| 295 | |||
| 296 | if (!data->error) | ||
| 297 | data->bytes_xfered = data->blocks * data->blksz; | ||
| 298 | else | ||
| 299 | data->bytes_xfered = 0; | ||
| 300 | |||
| 301 | sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN); | ||
| 302 | bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ | ||
| 303 | DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); | ||
| 304 | bfin_write_SDH_DATA_CTL(0); | ||
| 305 | SSYNC(); | ||
| 306 | |||
| 307 | host->data = NULL; | ||
| 308 | if (host->mrq->stop) { | ||
| 309 | sdh_stop_clock(host); | ||
| 310 | sdh_start_cmd(host, host->mrq->stop); | ||
| 311 | } else { | ||
| 312 | sdh_finish_request(host, host->mrq); | ||
| 313 | } | ||
| 314 | |||
| 315 | return 1; | ||
| 316 | } | ||
| 317 | |||
| 318 | static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
| 319 | { | ||
| 320 | struct sdh_host *host = mmc_priv(mmc); | ||
| 321 | int ret = 0; | ||
| 322 | |||
| 323 | dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); | ||
| 324 | WARN_ON(host->mrq != NULL); | ||
| 325 | |||
| 326 | host->mrq = mrq; | ||
| 327 | host->data = mrq->data; | ||
| 328 | |||
| 329 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) { | ||
| 330 | ret = sdh_setup_data(host, mrq->data); | ||
| 331 | if (ret) | ||
| 332 | return; | ||
| 333 | } | ||
| 334 | |||
| 335 | sdh_start_cmd(host, mrq->cmd); | ||
| 336 | } | ||
| 337 | |||
| 338 | static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 339 | { | ||
| 340 | struct sdh_host *host; | ||
| 341 | unsigned long flags; | ||
| 342 | u16 clk_ctl = 0; | ||
| 343 | u16 pwr_ctl = 0; | ||
| 344 | u16 cfg; | ||
| 345 | host = mmc_priv(mmc); | ||
| 346 | |||
| 347 | spin_lock_irqsave(&host->lock, flags); | ||
| 348 | if (ios->clock) { | ||
| 349 | unsigned long sys_clk, ios_clk; | ||
| 350 | unsigned char clk_div; | ||
| 351 | ios_clk = 2 * ios->clock; | ||
| 352 | sys_clk = get_sclk(); | ||
| 353 | clk_div = sys_clk / ios_clk; | ||
| 354 | if (sys_clk % ios_clk == 0) | ||
| 355 | clk_div -= 1; | ||
| 356 | clk_div = min_t(unsigned char, clk_div, 0xFF); | ||
| 357 | clk_ctl |= clk_div; | ||
| 358 | clk_ctl |= CLK_E; | ||
| 359 | host->clk_div = clk_div; | ||
| 360 | } else | ||
| 361 | sdh_stop_clock(host); | ||
| 362 | |||
| 363 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
| 364 | #ifdef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
| 365 | pwr_ctl |= ROD_CTL; | ||
| 366 | #else | ||
| 367 | pwr_ctl |= SD_CMD_OD | ROD_CTL; | ||
| 368 | #endif | ||
| 369 | |||
| 370 | if (ios->bus_width == MMC_BUS_WIDTH_4) { | ||
| 371 | cfg = bfin_read_SDH_CFG(); | ||
| 372 | cfg &= ~PD_SDDAT3; | ||
| 373 | cfg |= PUP_SDDAT3; | ||
| 374 | /* Enable 4 bit SDIO */ | ||
| 375 | cfg |= (SD4E | MWE); | ||
| 376 | bfin_write_SDH_CFG(cfg); | ||
| 377 | clk_ctl |= WIDE_BUS; | ||
| 378 | } else { | ||
| 379 | cfg = bfin_read_SDH_CFG(); | ||
| 380 | cfg |= MWE; | ||
| 381 | bfin_write_SDH_CFG(cfg); | ||
| 382 | } | ||
| 383 | |||
| 384 | bfin_write_SDH_CLK_CTL(clk_ctl); | ||
| 385 | |||
| 386 | host->power_mode = ios->power_mode; | ||
| 387 | if (ios->power_mode == MMC_POWER_ON) | ||
| 388 | pwr_ctl |= PWR_ON; | ||
| 389 | |||
| 390 | bfin_write_SDH_PWR_CTL(pwr_ctl); | ||
| 391 | SSYNC(); | ||
| 392 | |||
| 393 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 394 | |||
| 395 | dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", | ||
| 396 | host->clk_div, | ||
| 397 | host->clk_div ? get_sclk() / (2 * (host->clk_div + 1)) : 0, | ||
| 398 | ios->clock); | ||
| 399 | } | ||
| 400 | |||
| 401 | static const struct mmc_host_ops sdh_ops = { | ||
| 402 | .request = sdh_request, | ||
| 403 | .set_ios = sdh_set_ios, | ||
| 404 | }; | ||
| 405 | |||
| 406 | static irqreturn_t sdh_dma_irq(int irq, void *devid) | ||
| 407 | { | ||
| 408 | struct sdh_host *host = devid; | ||
| 409 | |||
| 410 | dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04x\n", __func__, | ||
| 411 | get_dma_curr_irqstat(host->dma_ch)); | ||
| 412 | clear_dma_irqstat(host->dma_ch); | ||
| 413 | SSYNC(); | ||
| 414 | |||
| 415 | return IRQ_HANDLED; | ||
| 416 | } | ||
| 417 | |||
| 418 | static irqreturn_t sdh_stat_irq(int irq, void *devid) | ||
| 419 | { | ||
| 420 | struct sdh_host *host = devid; | ||
| 421 | unsigned int status; | ||
| 422 | int handled = 0; | ||
| 423 | |||
| 424 | dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); | ||
| 425 | status = bfin_read_SDH_E_STATUS(); | ||
| 426 | if (status & SD_CARD_DET) { | ||
| 427 | mmc_detect_change(host->mmc, 0); | ||
| 428 | bfin_write_SDH_E_STATUS(SD_CARD_DET); | ||
| 429 | } | ||
| 430 | status = bfin_read_SDH_STATUS(); | ||
| 431 | if (status & (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | CMD_CRC_FAIL)) { | ||
| 432 | handled |= sdh_cmd_done(host, status); | ||
| 433 | bfin_write_SDH_STATUS_CLR(CMD_SENT_STAT | CMD_RESP_END_STAT | \ | ||
| 434 | CMD_TIMEOUT_STAT | CMD_CRC_FAIL_STAT); | ||
| 435 | SSYNC(); | ||
| 436 | } | ||
| 437 | |||
| 438 | status = bfin_read_SDH_STATUS(); | ||
| 439 | if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) | ||
| 440 | handled |= sdh_data_done(host, status); | ||
| 441 | |||
| 442 | dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); | ||
| 443 | |||
| 444 | return IRQ_RETVAL(handled); | ||
| 445 | } | ||
| 446 | |||
| 447 | static int __devinit sdh_probe(struct platform_device *pdev) | ||
| 448 | { | ||
| 449 | struct mmc_host *mmc; | ||
| 450 | struct sdh_host *host; | ||
| 451 | struct bfin_sd_host *drv_data = get_sdh_data(pdev); | ||
| 452 | int ret; | ||
| 453 | |||
| 454 | if (!drv_data) { | ||
| 455 | dev_err(&pdev->dev, "missing platform driver data\n"); | ||
| 456 | ret = -EINVAL; | ||
| 457 | goto out; | ||
| 458 | } | ||
| 459 | |||
| 460 | mmc = mmc_alloc_host(sizeof(*mmc), &pdev->dev); | ||
| 461 | if (!mmc) { | ||
| 462 | ret = -ENOMEM; | ||
| 463 | goto out; | ||
| 464 | } | ||
| 465 | |||
| 466 | mmc->ops = &sdh_ops; | ||
| 467 | mmc->max_phys_segs = 32; | ||
| 468 | mmc->max_seg_size = 1 << 16; | ||
| 469 | mmc->max_blk_size = 1 << 11; | ||
| 470 | mmc->max_blk_count = 1 << 11; | ||
| 471 | mmc->max_req_size = PAGE_SIZE; | ||
| 472 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
| 473 | mmc->f_max = get_sclk(); | ||
| 474 | mmc->f_min = mmc->f_max >> 9; | ||
| 475 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; | ||
| 476 | host = mmc_priv(mmc); | ||
| 477 | host->mmc = mmc; | ||
| 478 | |||
| 479 | spin_lock_init(&host->lock); | ||
| 480 | host->irq = drv_data->irq_int0; | ||
| 481 | host->dma_ch = drv_data->dma_chan; | ||
| 482 | |||
| 483 | ret = request_dma(host->dma_ch, DRIVER_NAME "DMA"); | ||
| 484 | if (ret) { | ||
| 485 | dev_err(&pdev->dev, "unable to request DMA channel\n"); | ||
| 486 | goto out1; | ||
| 487 | } | ||
| 488 | |||
| 489 | ret = set_dma_callback(host->dma_ch, sdh_dma_irq, host); | ||
| 490 | if (ret) { | ||
| 491 | dev_err(&pdev->dev, "unable to request DMA irq\n"); | ||
| 492 | goto out2; | ||
| 493 | } | ||
| 494 | |||
| 495 | host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL); | ||
| 496 | if (host->sg_cpu == NULL) { | ||
| 497 | ret = -ENOMEM; | ||
| 498 | goto out2; | ||
| 499 | } | ||
| 500 | |||
| 501 | platform_set_drvdata(pdev, mmc); | ||
| 502 | mmc_add_host(mmc); | ||
| 503 | |||
| 504 | ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host); | ||
| 505 | if (ret) { | ||
| 506 | dev_err(&pdev->dev, "unable to request status irq\n"); | ||
| 507 | goto out3; | ||
| 508 | } | ||
| 509 | |||
| 510 | ret = peripheral_request_list(drv_data->pin_req, DRIVER_NAME); | ||
| 511 | if (ret) { | ||
| 512 | dev_err(&pdev->dev, "unable to request peripheral pins\n"); | ||
| 513 | goto out4; | ||
| 514 | } | ||
| 515 | #if defined(CONFIG_BF54x) | ||
| 516 | /* Secure Digital Host shares DMA with Nand controller */ | ||
| 517 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
| 518 | #endif | ||
| 519 | |||
| 520 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
| 521 | SSYNC(); | ||
| 522 | |||
| 523 | /* Disable card inserting detection pin. set MMC_CAP_NEES_POLL, and | ||
| 524 | * mmc stack will do the detection. | ||
| 525 | */ | ||
| 526 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
| 527 | SSYNC(); | ||
| 528 | |||
| 529 | return 0; | ||
| 530 | |||
| 531 | out4: | ||
| 532 | free_irq(host->irq, host); | ||
| 533 | out3: | ||
| 534 | mmc_remove_host(mmc); | ||
| 535 | dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); | ||
| 536 | out2: | ||
| 537 | free_dma(host->dma_ch); | ||
| 538 | out1: | ||
| 539 | mmc_free_host(mmc); | ||
| 540 | out: | ||
| 541 | return ret; | ||
| 542 | } | ||
| 543 | |||
| 544 | static int __devexit sdh_remove(struct platform_device *pdev) | ||
| 545 | { | ||
| 546 | struct mmc_host *mmc = platform_get_drvdata(pdev); | ||
| 547 | |||
| 548 | platform_set_drvdata(pdev, NULL); | ||
| 549 | |||
| 550 | if (mmc) { | ||
| 551 | struct sdh_host *host = mmc_priv(mmc); | ||
| 552 | |||
| 553 | mmc_remove_host(mmc); | ||
| 554 | |||
| 555 | sdh_stop_clock(host); | ||
| 556 | free_irq(host->irq, host); | ||
| 557 | free_dma(host->dma_ch); | ||
| 558 | dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); | ||
| 559 | |||
| 560 | mmc_free_host(mmc); | ||
| 561 | } | ||
| 562 | |||
| 563 | return 0; | ||
| 564 | } | ||
| 565 | |||
| 566 | #ifdef CONFIG_PM | ||
| 567 | static int sdh_suspend(struct platform_device *dev, pm_message_t state) | ||
| 568 | { | ||
| 569 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
| 570 | struct bfin_sd_host *drv_data = get_sdh_data(dev); | ||
| 571 | int ret = 0; | ||
| 572 | |||
| 573 | if (mmc) | ||
| 574 | ret = mmc_suspend_host(mmc, state); | ||
| 575 | |||
| 576 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON); | ||
| 577 | peripheral_free_list(drv_data->pin_req); | ||
| 578 | |||
| 579 | return ret; | ||
| 580 | } | ||
| 581 | |||
| 582 | static int sdh_resume(struct platform_device *dev) | ||
| 583 | { | ||
| 584 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
| 585 | struct bfin_sd_host *drv_data = get_sdh_data(dev); | ||
| 586 | int ret = 0; | ||
| 587 | |||
| 588 | ret = peripheral_request_list(drv_data->pin_req, DRIVER_NAME); | ||
| 589 | if (ret) { | ||
| 590 | dev_err(&dev->dev, "unable to request peripheral pins\n"); | ||
| 591 | return ret; | ||
| 592 | } | ||
| 593 | |||
| 594 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() | PWR_ON); | ||
| 595 | #if defined(CONFIG_BF54x) | ||
| 596 | /* Secure Digital Host shares DMA with Nand controller */ | ||
| 597 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
| 598 | #endif | ||
| 599 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
| 600 | SSYNC(); | ||
| 601 | |||
| 602 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
| 603 | SSYNC(); | ||
| 604 | |||
| 605 | if (mmc) | ||
| 606 | ret = mmc_resume_host(mmc); | ||
| 607 | |||
| 608 | return ret; | ||
| 609 | } | ||
| 610 | #else | ||
| 611 | # define sdh_suspend NULL | ||
| 612 | # define sdh_resume NULL | ||
| 613 | #endif | ||
| 614 | |||
| 615 | static struct platform_driver sdh_driver = { | ||
| 616 | .probe = sdh_probe, | ||
| 617 | .remove = __devexit_p(sdh_remove), | ||
| 618 | .suspend = sdh_suspend, | ||
| 619 | .resume = sdh_resume, | ||
| 620 | .driver = { | ||
| 621 | .name = DRIVER_NAME, | ||
| 622 | }, | ||
| 623 | }; | ||
| 624 | |||
| 625 | static int __init sdh_init(void) | ||
| 626 | { | ||
| 627 | return platform_driver_register(&sdh_driver); | ||
| 628 | } | ||
| 629 | module_init(sdh_init); | ||
| 630 | |||
| 631 | static void __exit sdh_exit(void) | ||
| 632 | { | ||
| 633 | platform_driver_unregister(&sdh_driver); | ||
| 634 | } | ||
| 635 | module_exit(sdh_exit); | ||
| 636 | |||
| 637 | MODULE_DESCRIPTION("Blackfin Secure Digital Host Driver"); | ||
| 638 | MODULE_AUTHOR("Cliff Cai, Roy Huang"); | ||
| 639 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c new file mode 100644 index 000000000000..dd45e7c3517e --- /dev/null +++ b/drivers/mmc/host/davinci_mmc.c | |||
| @@ -0,0 +1,1349 @@ | |||
| 1 | /* | ||
| 2 | * davinci_mmc.c - TI DaVinci MMC/SD/SDIO driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Texas Instruments. | ||
| 5 | * Original author: Purushotam Kumar | ||
| 6 | * Copyright (C) 2009 David Brownell | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/clk.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/cpufreq.h> | ||
| 29 | #include <linux/mmc/host.h> | ||
| 30 | #include <linux/io.h> | ||
| 31 | #include <linux/irq.h> | ||
| 32 | #include <linux/delay.h> | ||
| 33 | #include <linux/dma-mapping.h> | ||
| 34 | #include <linux/mmc/mmc.h> | ||
| 35 | |||
| 36 | #include <mach/mmc.h> | ||
| 37 | #include <mach/edma.h> | ||
| 38 | |||
| 39 | /* | ||
| 40 | * Register Definitions | ||
| 41 | */ | ||
| 42 | #define DAVINCI_MMCCTL 0x00 /* Control Register */ | ||
| 43 | #define DAVINCI_MMCCLK 0x04 /* Memory Clock Control Register */ | ||
| 44 | #define DAVINCI_MMCST0 0x08 /* Status Register 0 */ | ||
| 45 | #define DAVINCI_MMCST1 0x0C /* Status Register 1 */ | ||
| 46 | #define DAVINCI_MMCIM 0x10 /* Interrupt Mask Register */ | ||
| 47 | #define DAVINCI_MMCTOR 0x14 /* Response Time-Out Register */ | ||
| 48 | #define DAVINCI_MMCTOD 0x18 /* Data Read Time-Out Register */ | ||
| 49 | #define DAVINCI_MMCBLEN 0x1C /* Block Length Register */ | ||
| 50 | #define DAVINCI_MMCNBLK 0x20 /* Number of Blocks Register */ | ||
| 51 | #define DAVINCI_MMCNBLC 0x24 /* Number of Blocks Counter Register */ | ||
| 52 | #define DAVINCI_MMCDRR 0x28 /* Data Receive Register */ | ||
| 53 | #define DAVINCI_MMCDXR 0x2C /* Data Transmit Register */ | ||
| 54 | #define DAVINCI_MMCCMD 0x30 /* Command Register */ | ||
| 55 | #define DAVINCI_MMCARGHL 0x34 /* Argument Register */ | ||
| 56 | #define DAVINCI_MMCRSP01 0x38 /* Response Register 0 and 1 */ | ||
| 57 | #define DAVINCI_MMCRSP23 0x3C /* Response Register 0 and 1 */ | ||
| 58 | #define DAVINCI_MMCRSP45 0x40 /* Response Register 0 and 1 */ | ||
| 59 | #define DAVINCI_MMCRSP67 0x44 /* Response Register 0 and 1 */ | ||
| 60 | #define DAVINCI_MMCDRSP 0x48 /* Data Response Register */ | ||
| 61 | #define DAVINCI_MMCETOK 0x4C | ||
| 62 | #define DAVINCI_MMCCIDX 0x50 /* Command Index Register */ | ||
| 63 | #define DAVINCI_MMCCKC 0x54 | ||
| 64 | #define DAVINCI_MMCTORC 0x58 | ||
| 65 | #define DAVINCI_MMCTODC 0x5C | ||
| 66 | #define DAVINCI_MMCBLNC 0x60 | ||
| 67 | #define DAVINCI_SDIOCTL 0x64 | ||
| 68 | #define DAVINCI_SDIOST0 0x68 | ||
| 69 | #define DAVINCI_SDIOEN 0x6C | ||
| 70 | #define DAVINCI_SDIOST 0x70 | ||
| 71 | #define DAVINCI_MMCFIFOCTL 0x74 /* FIFO Control Register */ | ||
| 72 | |||
| 73 | /* DAVINCI_MMCCTL definitions */ | ||
| 74 | #define MMCCTL_DATRST (1 << 0) | ||
| 75 | #define MMCCTL_CMDRST (1 << 1) | ||
| 76 | #define MMCCTL_WIDTH_4_BIT (1 << 2) | ||
| 77 | #define MMCCTL_DATEG_DISABLED (0 << 6) | ||
| 78 | #define MMCCTL_DATEG_RISING (1 << 6) | ||
| 79 | #define MMCCTL_DATEG_FALLING (2 << 6) | ||
| 80 | #define MMCCTL_DATEG_BOTH (3 << 6) | ||
| 81 | #define MMCCTL_PERMDR_LE (0 << 9) | ||
| 82 | #define MMCCTL_PERMDR_BE (1 << 9) | ||
| 83 | #define MMCCTL_PERMDX_LE (0 << 10) | ||
| 84 | #define MMCCTL_PERMDX_BE (1 << 10) | ||
| 85 | |||
| 86 | /* DAVINCI_MMCCLK definitions */ | ||
| 87 | #define MMCCLK_CLKEN (1 << 8) | ||
| 88 | #define MMCCLK_CLKRT_MASK (0xFF << 0) | ||
| 89 | |||
| 90 | /* IRQ bit definitions, for DAVINCI_MMCST0 and DAVINCI_MMCIM */ | ||
| 91 | #define MMCST0_DATDNE BIT(0) /* data done */ | ||
| 92 | #define MMCST0_BSYDNE BIT(1) /* busy done */ | ||
| 93 | #define MMCST0_RSPDNE BIT(2) /* command done */ | ||
| 94 | #define MMCST0_TOUTRD BIT(3) /* data read timeout */ | ||
| 95 | #define MMCST0_TOUTRS BIT(4) /* command response timeout */ | ||
| 96 | #define MMCST0_CRCWR BIT(5) /* data write CRC error */ | ||
| 97 | #define MMCST0_CRCRD BIT(6) /* data read CRC error */ | ||
| 98 | #define MMCST0_CRCRS BIT(7) /* command response CRC error */ | ||
| 99 | #define MMCST0_DXRDY BIT(9) /* data transmit ready (fifo empty) */ | ||
| 100 | #define MMCST0_DRRDY BIT(10) /* data receive ready (data in fifo)*/ | ||
| 101 | #define MMCST0_DATED BIT(11) /* DAT3 edge detect */ | ||
| 102 | #define MMCST0_TRNDNE BIT(12) /* transfer done */ | ||
| 103 | |||
| 104 | /* DAVINCI_MMCST1 definitions */ | ||
| 105 | #define MMCST1_BUSY (1 << 0) | ||
| 106 | |||
| 107 | /* DAVINCI_MMCCMD definitions */ | ||
| 108 | #define MMCCMD_CMD_MASK (0x3F << 0) | ||
| 109 | #define MMCCMD_PPLEN (1 << 7) | ||
| 110 | #define MMCCMD_BSYEXP (1 << 8) | ||
| 111 | #define MMCCMD_RSPFMT_MASK (3 << 9) | ||
| 112 | #define MMCCMD_RSPFMT_NONE (0 << 9) | ||
| 113 | #define MMCCMD_RSPFMT_R1456 (1 << 9) | ||
| 114 | #define MMCCMD_RSPFMT_R2 (2 << 9) | ||
| 115 | #define MMCCMD_RSPFMT_R3 (3 << 9) | ||
| 116 | #define MMCCMD_DTRW (1 << 11) | ||
| 117 | #define MMCCMD_STRMTP (1 << 12) | ||
| 118 | #define MMCCMD_WDATX (1 << 13) | ||
| 119 | #define MMCCMD_INITCK (1 << 14) | ||
| 120 | #define MMCCMD_DCLR (1 << 15) | ||
| 121 | #define MMCCMD_DMATRIG (1 << 16) | ||
| 122 | |||
| 123 | /* DAVINCI_MMCFIFOCTL definitions */ | ||
| 124 | #define MMCFIFOCTL_FIFORST (1 << 0) | ||
| 125 | #define MMCFIFOCTL_FIFODIR_WR (1 << 1) | ||
| 126 | #define MMCFIFOCTL_FIFODIR_RD (0 << 1) | ||
| 127 | #define MMCFIFOCTL_FIFOLEV (1 << 2) /* 0 = 128 bits, 1 = 256 bits */ | ||
| 128 | #define MMCFIFOCTL_ACCWD_4 (0 << 3) /* access width of 4 bytes */ | ||
| 129 | #define MMCFIFOCTL_ACCWD_3 (1 << 3) /* access width of 3 bytes */ | ||
| 130 | #define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */ | ||
| 131 | #define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */ | ||
| 132 | |||
| 133 | |||
| 134 | /* MMCSD Init clock in Hz in opendrain mode */ | ||
| 135 | #define MMCSD_INIT_CLOCK 200000 | ||
| 136 | |||
| 137 | /* | ||
| 138 | * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, | ||
| 139 | * and we handle up to NR_SG segments. MMC_BLOCK_BOUNCE kicks in only | ||
| 140 | * for drivers with max_hw_segs == 1, making the segments bigger (64KB) | ||
| 141 | * than the page or two that's otherwise typical. NR_SG == 16 gives at | ||
| 142 | * least the same throughput boost, using EDMA transfer linkage instead | ||
| 143 | * of spending CPU time copying pages. | ||
| 144 | */ | ||
| 145 | #define MAX_CCNT ((1 << 16) - 1) | ||
| 146 | |||
| 147 | #define NR_SG 16 | ||
| 148 | |||
| 149 | static unsigned rw_threshold = 32; | ||
| 150 | module_param(rw_threshold, uint, S_IRUGO); | ||
| 151 | MODULE_PARM_DESC(rw_threshold, | ||
| 152 | "Read/Write threshold. Default = 32"); | ||
| 153 | |||
| 154 | static unsigned __initdata use_dma = 1; | ||
| 155 | module_param(use_dma, uint, 0); | ||
| 156 | MODULE_PARM_DESC(use_dma, "Whether to use DMA or not. Default = 1"); | ||
| 157 | |||
| 158 | struct mmc_davinci_host { | ||
| 159 | struct mmc_command *cmd; | ||
| 160 | struct mmc_data *data; | ||
| 161 | struct mmc_host *mmc; | ||
| 162 | struct clk *clk; | ||
| 163 | unsigned int mmc_input_clk; | ||
| 164 | void __iomem *base; | ||
| 165 | struct resource *mem_res; | ||
| 166 | int irq; | ||
| 167 | unsigned char bus_mode; | ||
| 168 | |||
| 169 | #define DAVINCI_MMC_DATADIR_NONE 0 | ||
| 170 | #define DAVINCI_MMC_DATADIR_READ 1 | ||
| 171 | #define DAVINCI_MMC_DATADIR_WRITE 2 | ||
| 172 | unsigned char data_dir; | ||
| 173 | |||
| 174 | /* buffer is used during PIO of one scatterlist segment, and | ||
| 175 | * is updated along with buffer_bytes_left. bytes_left applies | ||
| 176 | * to all N blocks of the PIO transfer. | ||
| 177 | */ | ||
| 178 | u8 *buffer; | ||
| 179 | u32 buffer_bytes_left; | ||
| 180 | u32 bytes_left; | ||
| 181 | |||
| 182 | u32 rxdma, txdma; | ||
| 183 | bool use_dma; | ||
| 184 | bool do_dma; | ||
| 185 | |||
| 186 | /* Scatterlist DMA uses one or more parameter RAM entries: | ||
| 187 | * the main one (associated with rxdma or txdma) plus zero or | ||
| 188 | * more links. The entries for a given transfer differ only | ||
| 189 | * by memory buffer (address, length) and link field. | ||
| 190 | */ | ||
| 191 | struct edmacc_param tx_template; | ||
| 192 | struct edmacc_param rx_template; | ||
| 193 | unsigned n_link; | ||
| 194 | u32 links[NR_SG - 1]; | ||
| 195 | |||
| 196 | /* For PIO we walk scatterlists one segment at a time. */ | ||
| 197 | unsigned int sg_len; | ||
| 198 | struct scatterlist *sg; | ||
| 199 | |||
| 200 | /* Version of the MMC/SD controller */ | ||
| 201 | u8 version; | ||
| 202 | /* for ns in one cycle calculation */ | ||
| 203 | unsigned ns_in_one_cycle; | ||
| 204 | #ifdef CONFIG_CPU_FREQ | ||
| 205 | struct notifier_block freq_transition; | ||
| 206 | #endif | ||
| 207 | }; | ||
| 208 | |||
| 209 | |||
| 210 | /* PIO only */ | ||
| 211 | static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host) | ||
| 212 | { | ||
| 213 | host->buffer_bytes_left = sg_dma_len(host->sg); | ||
| 214 | host->buffer = sg_virt(host->sg); | ||
| 215 | if (host->buffer_bytes_left > host->bytes_left) | ||
| 216 | host->buffer_bytes_left = host->bytes_left; | ||
| 217 | } | ||
| 218 | |||
| 219 | static void davinci_fifo_data_trans(struct mmc_davinci_host *host, | ||
| 220 | unsigned int n) | ||
| 221 | { | ||
| 222 | u8 *p; | ||
| 223 | unsigned int i; | ||
| 224 | |||
| 225 | if (host->buffer_bytes_left == 0) { | ||
| 226 | host->sg = sg_next(host->data->sg); | ||
| 227 | mmc_davinci_sg_to_buf(host); | ||
| 228 | } | ||
| 229 | |||
| 230 | p = host->buffer; | ||
| 231 | if (n > host->buffer_bytes_left) | ||
| 232 | n = host->buffer_bytes_left; | ||
| 233 | host->buffer_bytes_left -= n; | ||
| 234 | host->bytes_left -= n; | ||
| 235 | |||
| 236 | /* NOTE: we never transfer more than rw_threshold bytes | ||
| 237 | * to/from the fifo here; there's no I/O overlap. | ||
| 238 | * This also assumes that access width( i.e. ACCWD) is 4 bytes | ||
| 239 | */ | ||
| 240 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { | ||
| 241 | for (i = 0; i < (n >> 2); i++) { | ||
| 242 | writel(*((u32 *)p), host->base + DAVINCI_MMCDXR); | ||
| 243 | p = p + 4; | ||
| 244 | } | ||
| 245 | if (n & 3) { | ||
| 246 | iowrite8_rep(host->base + DAVINCI_MMCDXR, p, (n & 3)); | ||
| 247 | p = p + (n & 3); | ||
| 248 | } | ||
| 249 | } else { | ||
| 250 | for (i = 0; i < (n >> 2); i++) { | ||
| 251 | *((u32 *)p) = readl(host->base + DAVINCI_MMCDRR); | ||
| 252 | p = p + 4; | ||
| 253 | } | ||
| 254 | if (n & 3) { | ||
| 255 | ioread8_rep(host->base + DAVINCI_MMCDRR, p, (n & 3)); | ||
| 256 | p = p + (n & 3); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | host->buffer = p; | ||
| 260 | } | ||
| 261 | |||
| 262 | static void mmc_davinci_start_command(struct mmc_davinci_host *host, | ||
| 263 | struct mmc_command *cmd) | ||
| 264 | { | ||
| 265 | u32 cmd_reg = 0; | ||
| 266 | u32 im_val; | ||
| 267 | |||
| 268 | dev_dbg(mmc_dev(host->mmc), "CMD%d, arg 0x%08x%s\n", | ||
| 269 | cmd->opcode, cmd->arg, | ||
| 270 | ({ char *s; | ||
| 271 | switch (mmc_resp_type(cmd)) { | ||
| 272 | case MMC_RSP_R1: | ||
| 273 | s = ", R1/R5/R6/R7 response"; | ||
| 274 | break; | ||
| 275 | case MMC_RSP_R1B: | ||
| 276 | s = ", R1b response"; | ||
| 277 | break; | ||
| 278 | case MMC_RSP_R2: | ||
| 279 | s = ", R2 response"; | ||
| 280 | break; | ||
| 281 | case MMC_RSP_R3: | ||
| 282 | s = ", R3/R4 response"; | ||
| 283 | break; | ||
| 284 | default: | ||
| 285 | s = ", (R? response)"; | ||
| 286 | break; | ||
| 287 | }; s; })); | ||
| 288 | host->cmd = cmd; | ||
| 289 | |||
| 290 | switch (mmc_resp_type(cmd)) { | ||
| 291 | case MMC_RSP_R1B: | ||
| 292 | /* There's some spec confusion about when R1B is | ||
| 293 | * allowed, but if the card doesn't issue a BUSY | ||
| 294 | * then it's harmless for us to allow it. | ||
| 295 | */ | ||
| 296 | cmd_reg |= MMCCMD_BSYEXP; | ||
| 297 | /* FALLTHROUGH */ | ||
| 298 | case MMC_RSP_R1: /* 48 bits, CRC */ | ||
| 299 | cmd_reg |= MMCCMD_RSPFMT_R1456; | ||
| 300 | break; | ||
| 301 | case MMC_RSP_R2: /* 136 bits, CRC */ | ||
| 302 | cmd_reg |= MMCCMD_RSPFMT_R2; | ||
| 303 | break; | ||
| 304 | case MMC_RSP_R3: /* 48 bits, no CRC */ | ||
| 305 | cmd_reg |= MMCCMD_RSPFMT_R3; | ||
| 306 | break; | ||
| 307 | default: | ||
| 308 | cmd_reg |= MMCCMD_RSPFMT_NONE; | ||
| 309 | dev_dbg(mmc_dev(host->mmc), "unknown resp_type %04x\n", | ||
| 310 | mmc_resp_type(cmd)); | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | |||
| 314 | /* Set command index */ | ||
| 315 | cmd_reg |= cmd->opcode; | ||
| 316 | |||
| 317 | /* Enable EDMA transfer triggers */ | ||
| 318 | if (host->do_dma) | ||
| 319 | cmd_reg |= MMCCMD_DMATRIG; | ||
| 320 | |||
| 321 | if (host->version == MMC_CTLR_VERSION_2 && host->data != NULL && | ||
| 322 | host->data_dir == DAVINCI_MMC_DATADIR_READ) | ||
| 323 | cmd_reg |= MMCCMD_DMATRIG; | ||
| 324 | |||
| 325 | /* Setting whether command involves data transfer or not */ | ||
| 326 | if (cmd->data) | ||
| 327 | cmd_reg |= MMCCMD_WDATX; | ||
| 328 | |||
| 329 | /* Setting whether stream or block transfer */ | ||
| 330 | if (cmd->flags & MMC_DATA_STREAM) | ||
| 331 | cmd_reg |= MMCCMD_STRMTP; | ||
| 332 | |||
| 333 | /* Setting whether data read or write */ | ||
| 334 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) | ||
| 335 | cmd_reg |= MMCCMD_DTRW; | ||
| 336 | |||
| 337 | if (host->bus_mode == MMC_BUSMODE_PUSHPULL) | ||
| 338 | cmd_reg |= MMCCMD_PPLEN; | ||
| 339 | |||
| 340 | /* set Command timeout */ | ||
| 341 | writel(0x1FFF, host->base + DAVINCI_MMCTOR); | ||
| 342 | |||
| 343 | /* Enable interrupt (calculate here, defer until FIFO is stuffed). */ | ||
| 344 | im_val = MMCST0_RSPDNE | MMCST0_CRCRS | MMCST0_TOUTRS; | ||
| 345 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { | ||
| 346 | im_val |= MMCST0_DATDNE | MMCST0_CRCWR; | ||
| 347 | |||
| 348 | if (!host->do_dma) | ||
| 349 | im_val |= MMCST0_DXRDY; | ||
| 350 | } else if (host->data_dir == DAVINCI_MMC_DATADIR_READ) { | ||
| 351 | im_val |= MMCST0_DATDNE | MMCST0_CRCRD | MMCST0_TOUTRD; | ||
| 352 | |||
| 353 | if (!host->do_dma) | ||
| 354 | im_val |= MMCST0_DRRDY; | ||
| 355 | } | ||
| 356 | |||
| 357 | /* | ||
| 358 | * Before non-DMA WRITE commands the controller needs priming: | ||
| 359 | * FIFO should be populated with 32 bytes i.e. whatever is the FIFO size | ||
| 360 | */ | ||
| 361 | if (!host->do_dma && (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)) | ||
| 362 | davinci_fifo_data_trans(host, rw_threshold); | ||
| 363 | |||
| 364 | writel(cmd->arg, host->base + DAVINCI_MMCARGHL); | ||
| 365 | writel(cmd_reg, host->base + DAVINCI_MMCCMD); | ||
| 366 | writel(im_val, host->base + DAVINCI_MMCIM); | ||
| 367 | } | ||
| 368 | |||
| 369 | /*----------------------------------------------------------------------*/ | ||
| 370 | |||
| 371 | /* DMA infrastructure */ | ||
| 372 | |||
| 373 | static void davinci_abort_dma(struct mmc_davinci_host *host) | ||
| 374 | { | ||
| 375 | int sync_dev; | ||
| 376 | |||
| 377 | if (host->data_dir == DAVINCI_MMC_DATADIR_READ) | ||
| 378 | sync_dev = host->rxdma; | ||
| 379 | else | ||
| 380 | sync_dev = host->txdma; | ||
| 381 | |||
| 382 | edma_stop(sync_dev); | ||
| 383 | edma_clean_channel(sync_dev); | ||
| 384 | } | ||
| 385 | |||
| 386 | static void | ||
| 387 | mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data); | ||
| 388 | |||
| 389 | static void mmc_davinci_dma_cb(unsigned channel, u16 ch_status, void *data) | ||
| 390 | { | ||
| 391 | if (DMA_COMPLETE != ch_status) { | ||
| 392 | struct mmc_davinci_host *host = data; | ||
| 393 | |||
| 394 | /* Currently means: DMA Event Missed, or "null" transfer | ||
| 395 | * request was seen. In the future, TC errors (like bad | ||
| 396 | * addresses) might be presented too. | ||
| 397 | */ | ||
| 398 | dev_warn(mmc_dev(host->mmc), "DMA %s error\n", | ||
| 399 | (host->data->flags & MMC_DATA_WRITE) | ||
| 400 | ? "write" : "read"); | ||
| 401 | host->data->error = -EIO; | ||
| 402 | mmc_davinci_xfer_done(host, host->data); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | /* Set up tx or rx template, to be modified and updated later */ | ||
| 407 | static void __init mmc_davinci_dma_setup(struct mmc_davinci_host *host, | ||
| 408 | bool tx, struct edmacc_param *template) | ||
| 409 | { | ||
| 410 | unsigned sync_dev; | ||
| 411 | const u16 acnt = 4; | ||
| 412 | const u16 bcnt = rw_threshold >> 2; | ||
| 413 | const u16 ccnt = 0; | ||
| 414 | u32 src_port = 0; | ||
| 415 | u32 dst_port = 0; | ||
| 416 | s16 src_bidx, dst_bidx; | ||
| 417 | s16 src_cidx, dst_cidx; | ||
| 418 | |||
| 419 | /* | ||
| 420 | * A-B Sync transfer: each DMA request is for one "frame" of | ||
| 421 | * rw_threshold bytes, broken into "acnt"-size chunks repeated | ||
| 422 | * "bcnt" times. Each segment needs "ccnt" such frames; since | ||
| 423 | * we tell the block layer our mmc->max_seg_size limit, we can | ||
| 424 | * trust (later) that it's within bounds. | ||
| 425 | * | ||
| 426 | * The FIFOs are read/written in 4-byte chunks (acnt == 4) and | ||
| 427 | * EDMA will optimize memory operations to use larger bursts. | ||
| 428 | */ | ||
| 429 | if (tx) { | ||
| 430 | sync_dev = host->txdma; | ||
| 431 | |||
| 432 | /* src_prt, ccnt, and link to be set up later */ | ||
| 433 | src_bidx = acnt; | ||
| 434 | src_cidx = acnt * bcnt; | ||
| 435 | |||
| 436 | dst_port = host->mem_res->start + DAVINCI_MMCDXR; | ||
| 437 | dst_bidx = 0; | ||
| 438 | dst_cidx = 0; | ||
| 439 | } else { | ||
| 440 | sync_dev = host->rxdma; | ||
| 441 | |||
| 442 | src_port = host->mem_res->start + DAVINCI_MMCDRR; | ||
| 443 | src_bidx = 0; | ||
| 444 | src_cidx = 0; | ||
| 445 | |||
| 446 | /* dst_prt, ccnt, and link to be set up later */ | ||
| 447 | dst_bidx = acnt; | ||
| 448 | dst_cidx = acnt * bcnt; | ||
| 449 | } | ||
| 450 | |||
| 451 | /* | ||
| 452 | * We can't use FIFO mode for the FIFOs because MMC FIFO addresses | ||
| 453 | * are not 256-bit (32-byte) aligned. So we use INCR, and the W8BIT | ||
| 454 | * parameter is ignored. | ||
| 455 | */ | ||
| 456 | edma_set_src(sync_dev, src_port, INCR, W8BIT); | ||
| 457 | edma_set_dest(sync_dev, dst_port, INCR, W8BIT); | ||
| 458 | |||
| 459 | edma_set_src_index(sync_dev, src_bidx, src_cidx); | ||
| 460 | edma_set_dest_index(sync_dev, dst_bidx, dst_cidx); | ||
| 461 | |||
| 462 | edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC); | ||
| 463 | |||
| 464 | edma_read_slot(sync_dev, template); | ||
| 465 | |||
| 466 | /* don't bother with irqs or chaining */ | ||
| 467 | template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12; | ||
| 468 | } | ||
| 469 | |||
| 470 | static void mmc_davinci_send_dma_request(struct mmc_davinci_host *host, | ||
| 471 | struct mmc_data *data) | ||
| 472 | { | ||
| 473 | struct edmacc_param *template; | ||
| 474 | int channel, slot; | ||
| 475 | unsigned link; | ||
| 476 | struct scatterlist *sg; | ||
| 477 | unsigned sg_len; | ||
| 478 | unsigned bytes_left = host->bytes_left; | ||
| 479 | const unsigned shift = ffs(rw_threshold) - 1;; | ||
| 480 | |||
| 481 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { | ||
| 482 | template = &host->tx_template; | ||
| 483 | channel = host->txdma; | ||
| 484 | } else { | ||
| 485 | template = &host->rx_template; | ||
| 486 | channel = host->rxdma; | ||
| 487 | } | ||
| 488 | |||
| 489 | /* We know sg_len and ccnt will never be out of range because | ||
| 490 | * we told the mmc layer which in turn tells the block layer | ||
| 491 | * to ensure that it only hands us one scatterlist segment | ||
| 492 | * per EDMA PARAM entry. Update the PARAM | ||
| 493 | * entries needed for each segment of this scatterlist. | ||
| 494 | */ | ||
| 495 | for (slot = channel, link = 0, sg = data->sg, sg_len = host->sg_len; | ||
| 496 | sg_len-- != 0 && bytes_left; | ||
| 497 | sg = sg_next(sg), slot = host->links[link++]) { | ||
| 498 | u32 buf = sg_dma_address(sg); | ||
| 499 | unsigned count = sg_dma_len(sg); | ||
| 500 | |||
| 501 | template->link_bcntrld = sg_len | ||
| 502 | ? (EDMA_CHAN_SLOT(host->links[link]) << 5) | ||
| 503 | : 0xffff; | ||
| 504 | |||
| 505 | if (count > bytes_left) | ||
| 506 | count = bytes_left; | ||
| 507 | bytes_left -= count; | ||
| 508 | |||
| 509 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) | ||
| 510 | template->src = buf; | ||
| 511 | else | ||
| 512 | template->dst = buf; | ||
| 513 | template->ccnt = count >> shift; | ||
| 514 | |||
| 515 | edma_write_slot(slot, template); | ||
| 516 | } | ||
| 517 | |||
| 518 | if (host->version == MMC_CTLR_VERSION_2) | ||
| 519 | edma_clear_event(channel); | ||
| 520 | |||
| 521 | edma_start(channel); | ||
| 522 | } | ||
| 523 | |||
| 524 | static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, | ||
| 525 | struct mmc_data *data) | ||
| 526 | { | ||
| 527 | int i; | ||
| 528 | int mask = rw_threshold - 1; | ||
| 529 | |||
| 530 | host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | ||
| 531 | ((data->flags & MMC_DATA_WRITE) | ||
| 532 | ? DMA_TO_DEVICE | ||
| 533 | : DMA_FROM_DEVICE)); | ||
| 534 | |||
| 535 | /* no individual DMA segment should need a partial FIFO */ | ||
| 536 | for (i = 0; i < host->sg_len; i++) { | ||
| 537 | if (sg_dma_len(data->sg + i) & mask) { | ||
| 538 | dma_unmap_sg(mmc_dev(host->mmc), | ||
| 539 | data->sg, data->sg_len, | ||
| 540 | (data->flags & MMC_DATA_WRITE) | ||
| 541 | ? DMA_TO_DEVICE | ||
| 542 | : DMA_FROM_DEVICE); | ||
| 543 | return -1; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | host->do_dma = 1; | ||
| 548 | mmc_davinci_send_dma_request(host, data); | ||
| 549 | |||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | static void __init_or_module | ||
| 554 | davinci_release_dma_channels(struct mmc_davinci_host *host) | ||
| 555 | { | ||
| 556 | unsigned i; | ||
| 557 | |||
| 558 | if (!host->use_dma) | ||
| 559 | return; | ||
| 560 | |||
| 561 | for (i = 0; i < host->n_link; i++) | ||
| 562 | edma_free_slot(host->links[i]); | ||
| 563 | |||
| 564 | edma_free_channel(host->txdma); | ||
| 565 | edma_free_channel(host->rxdma); | ||
| 566 | } | ||
| 567 | |||
| 568 | static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) | ||
| 569 | { | ||
| 570 | int r, i; | ||
| 571 | |||
| 572 | /* Acquire master DMA write channel */ | ||
| 573 | r = edma_alloc_channel(host->txdma, mmc_davinci_dma_cb, host, | ||
| 574 | EVENTQ_DEFAULT); | ||
| 575 | if (r < 0) { | ||
| 576 | dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", | ||
| 577 | "tx", r); | ||
| 578 | return r; | ||
| 579 | } | ||
| 580 | mmc_davinci_dma_setup(host, true, &host->tx_template); | ||
| 581 | |||
| 582 | /* Acquire master DMA read channel */ | ||
| 583 | r = edma_alloc_channel(host->rxdma, mmc_davinci_dma_cb, host, | ||
| 584 | EVENTQ_DEFAULT); | ||
| 585 | if (r < 0) { | ||
| 586 | dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", | ||
| 587 | "rx", r); | ||
| 588 | goto free_master_write; | ||
| 589 | } | ||
| 590 | mmc_davinci_dma_setup(host, false, &host->rx_template); | ||
| 591 | |||
| 592 | /* Allocate parameter RAM slots, which will later be bound to a | ||
| 593 | * channel as needed to handle a scatterlist. | ||
| 594 | */ | ||
| 595 | for (i = 0; i < ARRAY_SIZE(host->links); i++) { | ||
| 596 | r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); | ||
| 597 | if (r < 0) { | ||
| 598 | dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n", | ||
| 599 | r); | ||
| 600 | break; | ||
| 601 | } | ||
| 602 | host->links[i] = r; | ||
| 603 | } | ||
| 604 | host->n_link = i; | ||
| 605 | |||
| 606 | return 0; | ||
| 607 | |||
| 608 | free_master_write: | ||
| 609 | edma_free_channel(host->txdma); | ||
| 610 | |||
| 611 | return r; | ||
| 612 | } | ||
| 613 | |||
| 614 | /*----------------------------------------------------------------------*/ | ||
| 615 | |||
| 616 | static void | ||
| 617 | mmc_davinci_prepare_data(struct mmc_davinci_host *host, struct mmc_request *req) | ||
| 618 | { | ||
| 619 | int fifo_lev = (rw_threshold == 32) ? MMCFIFOCTL_FIFOLEV : 0; | ||
| 620 | int timeout; | ||
| 621 | struct mmc_data *data = req->data; | ||
| 622 | |||
| 623 | if (host->version == MMC_CTLR_VERSION_2) | ||
| 624 | fifo_lev = (rw_threshold == 64) ? MMCFIFOCTL_FIFOLEV : 0; | ||
| 625 | |||
| 626 | host->data = data; | ||
| 627 | if (data == NULL) { | ||
| 628 | host->data_dir = DAVINCI_MMC_DATADIR_NONE; | ||
| 629 | writel(0, host->base + DAVINCI_MMCBLEN); | ||
| 630 | writel(0, host->base + DAVINCI_MMCNBLK); | ||
| 631 | return; | ||
| 632 | } | ||
| 633 | |||
| 634 | dev_dbg(mmc_dev(host->mmc), "%s %s, %d blocks of %d bytes\n", | ||
| 635 | (data->flags & MMC_DATA_STREAM) ? "stream" : "block", | ||
| 636 | (data->flags & MMC_DATA_WRITE) ? "write" : "read", | ||
| 637 | data->blocks, data->blksz); | ||
| 638 | dev_dbg(mmc_dev(host->mmc), " DTO %d cycles + %d ns\n", | ||
| 639 | data->timeout_clks, data->timeout_ns); | ||
| 640 | timeout = data->timeout_clks + | ||
| 641 | (data->timeout_ns / host->ns_in_one_cycle); | ||
| 642 | if (timeout > 0xffff) | ||
| 643 | timeout = 0xffff; | ||
| 644 | |||
| 645 | writel(timeout, host->base + DAVINCI_MMCTOD); | ||
| 646 | writel(data->blocks, host->base + DAVINCI_MMCNBLK); | ||
| 647 | writel(data->blksz, host->base + DAVINCI_MMCBLEN); | ||
| 648 | |||
| 649 | /* Configure the FIFO */ | ||
| 650 | switch (data->flags & MMC_DATA_WRITE) { | ||
| 651 | case MMC_DATA_WRITE: | ||
| 652 | host->data_dir = DAVINCI_MMC_DATADIR_WRITE; | ||
| 653 | writel(fifo_lev | MMCFIFOCTL_FIFODIR_WR | MMCFIFOCTL_FIFORST, | ||
| 654 | host->base + DAVINCI_MMCFIFOCTL); | ||
| 655 | writel(fifo_lev | MMCFIFOCTL_FIFODIR_WR, | ||
| 656 | host->base + DAVINCI_MMCFIFOCTL); | ||
| 657 | break; | ||
| 658 | |||
| 659 | default: | ||
| 660 | host->data_dir = DAVINCI_MMC_DATADIR_READ; | ||
| 661 | writel(fifo_lev | MMCFIFOCTL_FIFODIR_RD | MMCFIFOCTL_FIFORST, | ||
| 662 | host->base + DAVINCI_MMCFIFOCTL); | ||
| 663 | writel(fifo_lev | MMCFIFOCTL_FIFODIR_RD, | ||
| 664 | host->base + DAVINCI_MMCFIFOCTL); | ||
| 665 | break; | ||
| 666 | } | ||
| 667 | |||
| 668 | host->buffer = NULL; | ||
| 669 | host->bytes_left = data->blocks * data->blksz; | ||
| 670 | |||
| 671 | /* For now we try to use DMA whenever we won't need partial FIFO | ||
| 672 | * reads or writes, either for the whole transfer (as tested here) | ||
| 673 | * or for any individual scatterlist segment (tested when we call | ||
| 674 | * start_dma_transfer). | ||
| 675 | * | ||
| 676 | * While we *could* change that, unusual block sizes are rarely | ||
| 677 | * used. The occasional fallback to PIO should't hurt. | ||
| 678 | */ | ||
| 679 | if (host->use_dma && (host->bytes_left & (rw_threshold - 1)) == 0 | ||
| 680 | && mmc_davinci_start_dma_transfer(host, data) == 0) { | ||
| 681 | /* zero this to ensure we take no PIO paths */ | ||
| 682 | host->bytes_left = 0; | ||
| 683 | } else { | ||
| 684 | /* Revert to CPU Copy */ | ||
| 685 | host->sg_len = data->sg_len; | ||
| 686 | host->sg = host->data->sg; | ||
| 687 | mmc_davinci_sg_to_buf(host); | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | static void mmc_davinci_request(struct mmc_host *mmc, struct mmc_request *req) | ||
| 692 | { | ||
| 693 | struct mmc_davinci_host *host = mmc_priv(mmc); | ||
| 694 | unsigned long timeout = jiffies + msecs_to_jiffies(900); | ||
| 695 | u32 mmcst1 = 0; | ||
| 696 | |||
| 697 | /* Card may still be sending BUSY after a previous operation, | ||
| 698 | * typically some kind of write. If so, we can't proceed yet. | ||
| 699 | */ | ||
| 700 | while (time_before(jiffies, timeout)) { | ||
| 701 | mmcst1 = readl(host->base + DAVINCI_MMCST1); | ||
| 702 | if (!(mmcst1 & MMCST1_BUSY)) | ||
| 703 | break; | ||
| 704 | cpu_relax(); | ||
| 705 | } | ||
| 706 | if (mmcst1 & MMCST1_BUSY) { | ||
| 707 | dev_err(mmc_dev(host->mmc), "still BUSY? bad ... \n"); | ||
| 708 | req->cmd->error = -ETIMEDOUT; | ||
| 709 | mmc_request_done(mmc, req); | ||
| 710 | return; | ||
| 711 | } | ||
| 712 | |||
| 713 | host->do_dma = 0; | ||
| 714 | mmc_davinci_prepare_data(host, req); | ||
| 715 | mmc_davinci_start_command(host, req->cmd); | ||
| 716 | } | ||
| 717 | |||
| 718 | static unsigned int calculate_freq_for_card(struct mmc_davinci_host *host, | ||
| 719 | unsigned int mmc_req_freq) | ||
| 720 | { | ||
| 721 | unsigned int mmc_freq = 0, mmc_pclk = 0, mmc_push_pull_divisor = 0; | ||
| 722 | |||
| 723 | mmc_pclk = host->mmc_input_clk; | ||
| 724 | if (mmc_req_freq && mmc_pclk > (2 * mmc_req_freq)) | ||
| 725 | mmc_push_pull_divisor = ((unsigned int)mmc_pclk | ||
| 726 | / (2 * mmc_req_freq)) - 1; | ||
| 727 | else | ||
| 728 | mmc_push_pull_divisor = 0; | ||
| 729 | |||
| 730 | mmc_freq = (unsigned int)mmc_pclk | ||
| 731 | / (2 * (mmc_push_pull_divisor + 1)); | ||
| 732 | |||
| 733 | if (mmc_freq > mmc_req_freq) | ||
| 734 | mmc_push_pull_divisor = mmc_push_pull_divisor + 1; | ||
| 735 | /* Convert ns to clock cycles */ | ||
| 736 | if (mmc_req_freq <= 400000) | ||
| 737 | host->ns_in_one_cycle = (1000000) / (((mmc_pclk | ||
| 738 | / (2 * (mmc_push_pull_divisor + 1)))/1000)); | ||
| 739 | else | ||
| 740 | host->ns_in_one_cycle = (1000000) / (((mmc_pclk | ||
| 741 | / (2 * (mmc_push_pull_divisor + 1)))/1000000)); | ||
| 742 | |||
| 743 | return mmc_push_pull_divisor; | ||
| 744 | } | ||
| 745 | |||
| 746 | static void calculate_clk_divider(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 747 | { | ||
| 748 | unsigned int open_drain_freq = 0, mmc_pclk = 0; | ||
| 749 | unsigned int mmc_push_pull_freq = 0; | ||
| 750 | struct mmc_davinci_host *host = mmc_priv(mmc); | ||
| 751 | |||
| 752 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { | ||
| 753 | u32 temp; | ||
| 754 | |||
| 755 | /* Ignoring the init clock value passed for fixing the inter | ||
| 756 | * operability with different cards. | ||
| 757 | */ | ||
| 758 | open_drain_freq = ((unsigned int)mmc_pclk | ||
| 759 | / (2 * MMCSD_INIT_CLOCK)) - 1; | ||
| 760 | |||
| 761 | if (open_drain_freq > 0xFF) | ||
| 762 | open_drain_freq = 0xFF; | ||
| 763 | |||
| 764 | temp = readl(host->base + DAVINCI_MMCCLK) & ~MMCCLK_CLKRT_MASK; | ||
| 765 | temp |= open_drain_freq; | ||
| 766 | writel(temp, host->base + DAVINCI_MMCCLK); | ||
| 767 | |||
| 768 | /* Convert ns to clock cycles */ | ||
| 769 | host->ns_in_one_cycle = (1000000) / (MMCSD_INIT_CLOCK/1000); | ||
| 770 | } else { | ||
| 771 | u32 temp; | ||
| 772 | mmc_push_pull_freq = calculate_freq_for_card(host, ios->clock); | ||
| 773 | |||
| 774 | if (mmc_push_pull_freq > 0xFF) | ||
| 775 | mmc_push_pull_freq = 0xFF; | ||
| 776 | |||
| 777 | temp = readl(host->base + DAVINCI_MMCCLK) & ~MMCCLK_CLKEN; | ||
| 778 | writel(temp, host->base + DAVINCI_MMCCLK); | ||
| 779 | |||
| 780 | udelay(10); | ||
| 781 | |||
| 782 | temp = readl(host->base + DAVINCI_MMCCLK) & ~MMCCLK_CLKRT_MASK; | ||
| 783 | temp |= mmc_push_pull_freq; | ||
| 784 | writel(temp, host->base + DAVINCI_MMCCLK); | ||
| 785 | |||
| 786 | writel(temp | MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK); | ||
| 787 | |||
| 788 | udelay(10); | ||
| 789 | } | ||
| 790 | } | ||
| 791 | |||
| 792 | static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 793 | { | ||
| 794 | unsigned int mmc_pclk = 0; | ||
| 795 | struct mmc_davinci_host *host = mmc_priv(mmc); | ||
| 796 | |||
| 797 | mmc_pclk = host->mmc_input_clk; | ||
| 798 | dev_dbg(mmc_dev(host->mmc), | ||
| 799 | "clock %dHz busmode %d powermode %d Vdd %04x\n", | ||
| 800 | ios->clock, ios->bus_mode, ios->power_mode, | ||
| 801 | ios->vdd); | ||
| 802 | if (ios->bus_width == MMC_BUS_WIDTH_4) { | ||
| 803 | dev_dbg(mmc_dev(host->mmc), "Enabling 4 bit mode\n"); | ||
| 804 | writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_WIDTH_4_BIT, | ||
| 805 | host->base + DAVINCI_MMCCTL); | ||
| 806 | } else { | ||
| 807 | dev_dbg(mmc_dev(host->mmc), "Disabling 4 bit mode\n"); | ||
| 808 | writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_WIDTH_4_BIT, | ||
| 809 | host->base + DAVINCI_MMCCTL); | ||
| 810 | } | ||
| 811 | |||
| 812 | calculate_clk_divider(mmc, ios); | ||
| 813 | |||
| 814 | host->bus_mode = ios->bus_mode; | ||
| 815 | if (ios->power_mode == MMC_POWER_UP) { | ||
| 816 | unsigned long timeout = jiffies + msecs_to_jiffies(50); | ||
| 817 | bool lose = true; | ||
| 818 | |||
| 819 | /* Send clock cycles, poll completion */ | ||
| 820 | writel(0, host->base + DAVINCI_MMCARGHL); | ||
| 821 | writel(MMCCMD_INITCK, host->base + DAVINCI_MMCCMD); | ||
| 822 | while (time_before(jiffies, timeout)) { | ||
| 823 | u32 tmp = readl(host->base + DAVINCI_MMCST0); | ||
| 824 | |||
| 825 | if (tmp & MMCST0_RSPDNE) { | ||
| 826 | lose = false; | ||
| 827 | break; | ||
| 828 | } | ||
| 829 | cpu_relax(); | ||
| 830 | } | ||
| 831 | if (lose) | ||
| 832 | dev_warn(mmc_dev(host->mmc), "powerup timeout\n"); | ||
| 833 | } | ||
| 834 | |||
| 835 | /* FIXME on power OFF, reset things ... */ | ||
| 836 | } | ||
| 837 | |||
| 838 | static void | ||
| 839 | mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data) | ||
| 840 | { | ||
| 841 | host->data = NULL; | ||
| 842 | |||
| 843 | if (host->do_dma) { | ||
| 844 | davinci_abort_dma(host); | ||
| 845 | |||
| 846 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | ||
| 847 | (data->flags & MMC_DATA_WRITE) | ||
| 848 | ? DMA_TO_DEVICE | ||
| 849 | : DMA_FROM_DEVICE); | ||
| 850 | host->do_dma = false; | ||
| 851 | } | ||
| 852 | host->data_dir = DAVINCI_MMC_DATADIR_NONE; | ||
| 853 | |||
| 854 | if (!data->stop || (host->cmd && host->cmd->error)) { | ||
| 855 | mmc_request_done(host->mmc, data->mrq); | ||
| 856 | writel(0, host->base + DAVINCI_MMCIM); | ||
| 857 | } else | ||
| 858 | mmc_davinci_start_command(host, data->stop); | ||
| 859 | } | ||
| 860 | |||
| 861 | static void mmc_davinci_cmd_done(struct mmc_davinci_host *host, | ||
| 862 | struct mmc_command *cmd) | ||
| 863 | { | ||
| 864 | host->cmd = NULL; | ||
| 865 | |||
| 866 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
| 867 | if (cmd->flags & MMC_RSP_136) { | ||
| 868 | /* response type 2 */ | ||
| 869 | cmd->resp[3] = readl(host->base + DAVINCI_MMCRSP01); | ||
| 870 | cmd->resp[2] = readl(host->base + DAVINCI_MMCRSP23); | ||
| 871 | cmd->resp[1] = readl(host->base + DAVINCI_MMCRSP45); | ||
| 872 | cmd->resp[0] = readl(host->base + DAVINCI_MMCRSP67); | ||
| 873 | } else { | ||
| 874 | /* response types 1, 1b, 3, 4, 5, 6 */ | ||
| 875 | cmd->resp[0] = readl(host->base + DAVINCI_MMCRSP67); | ||
| 876 | } | ||
| 877 | } | ||
| 878 | |||
| 879 | if (host->data == NULL || cmd->error) { | ||
| 880 | if (cmd->error == -ETIMEDOUT) | ||
| 881 | cmd->mrq->cmd->retries = 0; | ||
| 882 | mmc_request_done(host->mmc, cmd->mrq); | ||
| 883 | writel(0, host->base + DAVINCI_MMCIM); | ||
| 884 | } | ||
| 885 | } | ||
| 886 | |||
| 887 | static void | ||
| 888 | davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data) | ||
| 889 | { | ||
| 890 | u32 temp; | ||
| 891 | |||
| 892 | /* reset command and data state machines */ | ||
| 893 | temp = readl(host->base + DAVINCI_MMCCTL); | ||
| 894 | writel(temp | MMCCTL_CMDRST | MMCCTL_DATRST, | ||
| 895 | host->base + DAVINCI_MMCCTL); | ||
| 896 | |||
| 897 | temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST); | ||
| 898 | udelay(10); | ||
| 899 | writel(temp, host->base + DAVINCI_MMCCTL); | ||
| 900 | } | ||
| 901 | |||
| 902 | static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) | ||
| 903 | { | ||
| 904 | struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id; | ||
| 905 | unsigned int status, qstatus; | ||
| 906 | int end_command = 0; | ||
| 907 | int end_transfer = 0; | ||
| 908 | struct mmc_data *data = host->data; | ||
| 909 | |||
| 910 | if (host->cmd == NULL && host->data == NULL) { | ||
| 911 | status = readl(host->base + DAVINCI_MMCST0); | ||
| 912 | dev_dbg(mmc_dev(host->mmc), | ||
| 913 | "Spurious interrupt 0x%04x\n", status); | ||
| 914 | /* Disable the interrupt from mmcsd */ | ||
| 915 | writel(0, host->base + DAVINCI_MMCIM); | ||
| 916 | return IRQ_NONE; | ||
| 917 | } | ||
| 918 | |||
| 919 | status = readl(host->base + DAVINCI_MMCST0); | ||
| 920 | qstatus = status; | ||
| 921 | |||
| 922 | /* handle FIFO first when using PIO for data. | ||
| 923 | * bytes_left will decrease to zero as I/O progress and status will | ||
| 924 | * read zero over iteration because this controller status | ||
| 925 | * register(MMCST0) reports any status only once and it is cleared | ||
| 926 | * by read. So, it is not unbouned loop even in the case of | ||
| 927 | * non-dma. | ||
| 928 | */ | ||
| 929 | while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) { | ||
| 930 | davinci_fifo_data_trans(host, rw_threshold); | ||
| 931 | status = readl(host->base + DAVINCI_MMCST0); | ||
| 932 | if (!status) | ||
| 933 | break; | ||
| 934 | qstatus |= status; | ||
| 935 | } | ||
| 936 | |||
| 937 | if (qstatus & MMCST0_DATDNE) { | ||
| 938 | /* All blocks sent/received, and CRC checks passed */ | ||
| 939 | if (data != NULL) { | ||
| 940 | if ((host->do_dma == 0) && (host->bytes_left > 0)) { | ||
| 941 | /* if datasize < rw_threshold | ||
| 942 | * no RX ints are generated | ||
| 943 | */ | ||
| 944 | davinci_fifo_data_trans(host, host->bytes_left); | ||
| 945 | } | ||
| 946 | end_transfer = 1; | ||
| 947 | data->bytes_xfered = data->blocks * data->blksz; | ||
| 948 | } else { | ||
| 949 | dev_err(mmc_dev(host->mmc), | ||
| 950 | "DATDNE with no host->data\n"); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 954 | if (qstatus & MMCST0_TOUTRD) { | ||
| 955 | /* Read data timeout */ | ||
| 956 | data->error = -ETIMEDOUT; | ||
| 957 | end_transfer = 1; | ||
| 958 | |||
| 959 | dev_dbg(mmc_dev(host->mmc), | ||
| 960 | "read data timeout, status %x\n", | ||
| 961 | qstatus); | ||
| 962 | |||
| 963 | davinci_abort_data(host, data); | ||
| 964 | } | ||
| 965 | |||
| 966 | if (qstatus & (MMCST0_CRCWR | MMCST0_CRCRD)) { | ||
| 967 | /* Data CRC error */ | ||
| 968 | data->error = -EILSEQ; | ||
| 969 | end_transfer = 1; | ||
| 970 | |||
| 971 | /* NOTE: this controller uses CRCWR to report both CRC | ||
| 972 | * errors and timeouts (on writes). MMCDRSP values are | ||
| 973 | * only weakly documented, but 0x9f was clearly a timeout | ||
| 974 | * case and the two three-bit patterns in various SD specs | ||
| 975 | * (101, 010) aren't part of it ... | ||
| 976 | */ | ||
| 977 | if (qstatus & MMCST0_CRCWR) { | ||
| 978 | u32 temp = readb(host->base + DAVINCI_MMCDRSP); | ||
| 979 | |||
| 980 | if (temp == 0x9f) | ||
| 981 | data->error = -ETIMEDOUT; | ||
| 982 | } | ||
| 983 | dev_dbg(mmc_dev(host->mmc), "data %s %s error\n", | ||
| 984 | (qstatus & MMCST0_CRCWR) ? "write" : "read", | ||
| 985 | (data->error == -ETIMEDOUT) ? "timeout" : "CRC"); | ||
| 986 | |||
| 987 | davinci_abort_data(host, data); | ||
| 988 | } | ||
| 989 | |||
| 990 | if (qstatus & MMCST0_TOUTRS) { | ||
| 991 | /* Command timeout */ | ||
| 992 | if (host->cmd) { | ||
| 993 | dev_dbg(mmc_dev(host->mmc), | ||
| 994 | "CMD%d timeout, status %x\n", | ||
| 995 | host->cmd->opcode, qstatus); | ||
| 996 | host->cmd->error = -ETIMEDOUT; | ||
| 997 | if (data) { | ||
| 998 | end_transfer = 1; | ||
| 999 | davinci_abort_data(host, data); | ||
| 1000 | } else | ||
| 1001 | end_command = 1; | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | if (qstatus & MMCST0_CRCRS) { | ||
| 1006 | /* Command CRC error */ | ||
| 1007 | dev_dbg(mmc_dev(host->mmc), "Command CRC error\n"); | ||
| 1008 | if (host->cmd) { | ||
| 1009 | host->cmd->error = -EILSEQ; | ||
| 1010 | end_command = 1; | ||
| 1011 | } | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | if (qstatus & MMCST0_RSPDNE) { | ||
| 1015 | /* End of command phase */ | ||
| 1016 | end_command = (int) host->cmd; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | if (end_command) | ||
| 1020 | mmc_davinci_cmd_done(host, host->cmd); | ||
| 1021 | if (end_transfer) | ||
| 1022 | mmc_davinci_xfer_done(host, data); | ||
| 1023 | return IRQ_HANDLED; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | static int mmc_davinci_get_cd(struct mmc_host *mmc) | ||
| 1027 | { | ||
| 1028 | struct platform_device *pdev = to_platform_device(mmc->parent); | ||
| 1029 | struct davinci_mmc_config *config = pdev->dev.platform_data; | ||
| 1030 | |||
| 1031 | if (!config || !config->get_cd) | ||
| 1032 | return -ENOSYS; | ||
| 1033 | return config->get_cd(pdev->id); | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | static int mmc_davinci_get_ro(struct mmc_host *mmc) | ||
| 1037 | { | ||
| 1038 | struct platform_device *pdev = to_platform_device(mmc->parent); | ||
| 1039 | struct davinci_mmc_config *config = pdev->dev.platform_data; | ||
| 1040 | |||
| 1041 | if (!config || !config->get_ro) | ||
| 1042 | return -ENOSYS; | ||
| 1043 | return config->get_ro(pdev->id); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static struct mmc_host_ops mmc_davinci_ops = { | ||
| 1047 | .request = mmc_davinci_request, | ||
| 1048 | .set_ios = mmc_davinci_set_ios, | ||
| 1049 | .get_cd = mmc_davinci_get_cd, | ||
| 1050 | .get_ro = mmc_davinci_get_ro, | ||
| 1051 | }; | ||
| 1052 | |||
| 1053 | /*----------------------------------------------------------------------*/ | ||
| 1054 | |||
| 1055 | #ifdef CONFIG_CPU_FREQ | ||
| 1056 | static int mmc_davinci_cpufreq_transition(struct notifier_block *nb, | ||
| 1057 | unsigned long val, void *data) | ||
| 1058 | { | ||
| 1059 | struct mmc_davinci_host *host; | ||
| 1060 | unsigned int mmc_pclk; | ||
| 1061 | struct mmc_host *mmc; | ||
| 1062 | unsigned long flags; | ||
| 1063 | |||
| 1064 | host = container_of(nb, struct mmc_davinci_host, freq_transition); | ||
| 1065 | mmc = host->mmc; | ||
| 1066 | mmc_pclk = clk_get_rate(host->clk); | ||
| 1067 | |||
| 1068 | if (val == CPUFREQ_POSTCHANGE) { | ||
| 1069 | spin_lock_irqsave(&mmc->lock, flags); | ||
| 1070 | host->mmc_input_clk = mmc_pclk; | ||
| 1071 | calculate_clk_divider(mmc, &mmc->ios); | ||
| 1072 | spin_unlock_irqrestore(&mmc->lock, flags); | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | return 0; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | static inline int mmc_davinci_cpufreq_register(struct mmc_davinci_host *host) | ||
| 1079 | { | ||
| 1080 | host->freq_transition.notifier_call = mmc_davinci_cpufreq_transition; | ||
| 1081 | |||
| 1082 | return cpufreq_register_notifier(&host->freq_transition, | ||
| 1083 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static inline void mmc_davinci_cpufreq_deregister(struct mmc_davinci_host *host) | ||
| 1087 | { | ||
| 1088 | cpufreq_unregister_notifier(&host->freq_transition, | ||
| 1089 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 1090 | } | ||
| 1091 | #else | ||
| 1092 | static inline int mmc_davinci_cpufreq_register(struct mmc_davinci_host *host) | ||
| 1093 | { | ||
| 1094 | return 0; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | static inline void mmc_davinci_cpufreq_deregister(struct mmc_davinci_host *host) | ||
| 1098 | { | ||
| 1099 | } | ||
| 1100 | #endif | ||
| 1101 | static void __init init_mmcsd_host(struct mmc_davinci_host *host) | ||
| 1102 | { | ||
| 1103 | /* DAT line portion is diabled and in reset state */ | ||
| 1104 | writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_DATRST, | ||
| 1105 | host->base + DAVINCI_MMCCTL); | ||
| 1106 | |||
| 1107 | /* CMD line portion is diabled and in reset state */ | ||
| 1108 | writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_CMDRST, | ||
| 1109 | host->base + DAVINCI_MMCCTL); | ||
| 1110 | |||
| 1111 | udelay(10); | ||
| 1112 | |||
| 1113 | writel(0, host->base + DAVINCI_MMCCLK); | ||
| 1114 | writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK); | ||
| 1115 | |||
| 1116 | writel(0x1FFF, host->base + DAVINCI_MMCTOR); | ||
| 1117 | writel(0xFFFF, host->base + DAVINCI_MMCTOD); | ||
| 1118 | |||
| 1119 | writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_DATRST, | ||
| 1120 | host->base + DAVINCI_MMCCTL); | ||
| 1121 | writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_CMDRST, | ||
| 1122 | host->base + DAVINCI_MMCCTL); | ||
| 1123 | |||
| 1124 | udelay(10); | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | static int __init davinci_mmcsd_probe(struct platform_device *pdev) | ||
| 1128 | { | ||
| 1129 | struct davinci_mmc_config *pdata = pdev->dev.platform_data; | ||
| 1130 | struct mmc_davinci_host *host = NULL; | ||
| 1131 | struct mmc_host *mmc = NULL; | ||
| 1132 | struct resource *r, *mem = NULL; | ||
| 1133 | int ret = 0, irq = 0; | ||
| 1134 | size_t mem_size; | ||
| 1135 | |||
| 1136 | /* REVISIT: when we're fully converted, fail if pdata is NULL */ | ||
| 1137 | |||
| 1138 | ret = -ENODEV; | ||
| 1139 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1140 | irq = platform_get_irq(pdev, 0); | ||
| 1141 | if (!r || irq == NO_IRQ) | ||
| 1142 | goto out; | ||
| 1143 | |||
| 1144 | ret = -EBUSY; | ||
| 1145 | mem_size = resource_size(r); | ||
| 1146 | mem = request_mem_region(r->start, mem_size, pdev->name); | ||
| 1147 | if (!mem) | ||
| 1148 | goto out; | ||
| 1149 | |||
| 1150 | ret = -ENOMEM; | ||
| 1151 | mmc = mmc_alloc_host(sizeof(struct mmc_davinci_host), &pdev->dev); | ||
| 1152 | if (!mmc) | ||
| 1153 | goto out; | ||
| 1154 | |||
| 1155 | host = mmc_priv(mmc); | ||
| 1156 | host->mmc = mmc; /* Important */ | ||
| 1157 | |||
| 1158 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
| 1159 | if (!r) | ||
| 1160 | goto out; | ||
| 1161 | host->rxdma = r->start; | ||
| 1162 | |||
| 1163 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
| 1164 | if (!r) | ||
| 1165 | goto out; | ||
| 1166 | host->txdma = r->start; | ||
| 1167 | |||
| 1168 | host->mem_res = mem; | ||
| 1169 | host->base = ioremap(mem->start, mem_size); | ||
| 1170 | if (!host->base) | ||
| 1171 | goto out; | ||
| 1172 | |||
| 1173 | ret = -ENXIO; | ||
| 1174 | host->clk = clk_get(&pdev->dev, "MMCSDCLK"); | ||
| 1175 | if (IS_ERR(host->clk)) { | ||
| 1176 | ret = PTR_ERR(host->clk); | ||
| 1177 | goto out; | ||
| 1178 | } | ||
| 1179 | clk_enable(host->clk); | ||
| 1180 | host->mmc_input_clk = clk_get_rate(host->clk); | ||
| 1181 | |||
| 1182 | init_mmcsd_host(host); | ||
| 1183 | |||
| 1184 | host->use_dma = use_dma; | ||
| 1185 | host->irq = irq; | ||
| 1186 | |||
| 1187 | if (host->use_dma && davinci_acquire_dma_channels(host) != 0) | ||
| 1188 | host->use_dma = 0; | ||
| 1189 | |||
| 1190 | /* REVISIT: someday, support IRQ-driven card detection. */ | ||
| 1191 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
| 1192 | |||
| 1193 | if (!pdata || pdata->wires == 4 || pdata->wires == 0) | ||
| 1194 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
| 1195 | |||
| 1196 | host->version = pdata->version; | ||
| 1197 | |||
| 1198 | mmc->ops = &mmc_davinci_ops; | ||
| 1199 | mmc->f_min = 312500; | ||
| 1200 | mmc->f_max = 25000000; | ||
| 1201 | if (pdata && pdata->max_freq) | ||
| 1202 | mmc->f_max = pdata->max_freq; | ||
| 1203 | if (pdata && pdata->caps) | ||
| 1204 | mmc->caps |= pdata->caps; | ||
| 1205 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
| 1206 | |||
| 1207 | /* With no iommu coalescing pages, each phys_seg is a hw_seg. | ||
| 1208 | * Each hw_seg uses one EDMA parameter RAM slot, always one | ||
| 1209 | * channel and then usually some linked slots. | ||
| 1210 | */ | ||
| 1211 | mmc->max_hw_segs = 1 + host->n_link; | ||
| 1212 | mmc->max_phys_segs = mmc->max_hw_segs; | ||
| 1213 | |||
| 1214 | /* EDMA limit per hw segment (one or two MBytes) */ | ||
| 1215 | mmc->max_seg_size = MAX_CCNT * rw_threshold; | ||
| 1216 | |||
| 1217 | /* MMC/SD controller limits for multiblock requests */ | ||
| 1218 | mmc->max_blk_size = 4095; /* BLEN is 12 bits */ | ||
| 1219 | mmc->max_blk_count = 65535; /* NBLK is 16 bits */ | ||
| 1220 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
| 1221 | |||
| 1222 | dev_dbg(mmc_dev(host->mmc), "max_phys_segs=%d\n", mmc->max_phys_segs); | ||
| 1223 | dev_dbg(mmc_dev(host->mmc), "max_hw_segs=%d\n", mmc->max_hw_segs); | ||
| 1224 | dev_dbg(mmc_dev(host->mmc), "max_blk_size=%d\n", mmc->max_blk_size); | ||
| 1225 | dev_dbg(mmc_dev(host->mmc), "max_req_size=%d\n", mmc->max_req_size); | ||
| 1226 | dev_dbg(mmc_dev(host->mmc), "max_seg_size=%d\n", mmc->max_seg_size); | ||
| 1227 | |||
| 1228 | platform_set_drvdata(pdev, host); | ||
| 1229 | |||
| 1230 | ret = mmc_davinci_cpufreq_register(host); | ||
| 1231 | if (ret) { | ||
| 1232 | dev_err(&pdev->dev, "failed to register cpufreq\n"); | ||
| 1233 | goto cpu_freq_fail; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | ret = mmc_add_host(mmc); | ||
| 1237 | if (ret < 0) | ||
| 1238 | goto out; | ||
| 1239 | |||
| 1240 | ret = request_irq(irq, mmc_davinci_irq, 0, mmc_hostname(mmc), host); | ||
| 1241 | if (ret) | ||
| 1242 | goto out; | ||
| 1243 | |||
| 1244 | rename_region(mem, mmc_hostname(mmc)); | ||
| 1245 | |||
| 1246 | dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n", | ||
| 1247 | host->use_dma ? "DMA" : "PIO", | ||
| 1248 | (mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1); | ||
| 1249 | |||
| 1250 | return 0; | ||
| 1251 | |||
| 1252 | out: | ||
| 1253 | mmc_davinci_cpufreq_deregister(host); | ||
| 1254 | cpu_freq_fail: | ||
| 1255 | if (host) { | ||
| 1256 | davinci_release_dma_channels(host); | ||
| 1257 | |||
| 1258 | if (host->clk) { | ||
| 1259 | clk_disable(host->clk); | ||
| 1260 | clk_put(host->clk); | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | if (host->base) | ||
| 1264 | iounmap(host->base); | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | if (mmc) | ||
| 1268 | mmc_free_host(mmc); | ||
| 1269 | |||
| 1270 | if (mem) | ||
| 1271 | release_resource(mem); | ||
| 1272 | |||
| 1273 | dev_dbg(&pdev->dev, "probe err %d\n", ret); | ||
| 1274 | |||
| 1275 | return ret; | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | static int __exit davinci_mmcsd_remove(struct platform_device *pdev) | ||
| 1279 | { | ||
| 1280 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | ||
| 1281 | |||
| 1282 | platform_set_drvdata(pdev, NULL); | ||
| 1283 | if (host) { | ||
| 1284 | mmc_davinci_cpufreq_deregister(host); | ||
| 1285 | |||
| 1286 | mmc_remove_host(host->mmc); | ||
| 1287 | free_irq(host->irq, host); | ||
| 1288 | |||
| 1289 | davinci_release_dma_channels(host); | ||
| 1290 | |||
| 1291 | clk_disable(host->clk); | ||
| 1292 | clk_put(host->clk); | ||
| 1293 | |||
| 1294 | iounmap(host->base); | ||
| 1295 | |||
| 1296 | release_resource(host->mem_res); | ||
| 1297 | |||
| 1298 | mmc_free_host(host->mmc); | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | return 0; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | #ifdef CONFIG_PM | ||
| 1305 | static int davinci_mmcsd_suspend(struct platform_device *pdev, pm_message_t msg) | ||
| 1306 | { | ||
| 1307 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | ||
| 1308 | |||
| 1309 | return mmc_suspend_host(host->mmc, msg); | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | static int davinci_mmcsd_resume(struct platform_device *pdev) | ||
| 1313 | { | ||
| 1314 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | ||
| 1315 | |||
| 1316 | return mmc_resume_host(host->mmc); | ||
| 1317 | } | ||
| 1318 | #else | ||
| 1319 | #define davinci_mmcsd_suspend NULL | ||
| 1320 | #define davinci_mmcsd_resume NULL | ||
| 1321 | #endif | ||
| 1322 | |||
| 1323 | static struct platform_driver davinci_mmcsd_driver = { | ||
| 1324 | .driver = { | ||
| 1325 | .name = "davinci_mmc", | ||
| 1326 | .owner = THIS_MODULE, | ||
| 1327 | }, | ||
| 1328 | .remove = __exit_p(davinci_mmcsd_remove), | ||
| 1329 | .suspend = davinci_mmcsd_suspend, | ||
| 1330 | .resume = davinci_mmcsd_resume, | ||
| 1331 | }; | ||
| 1332 | |||
| 1333 | static int __init davinci_mmcsd_init(void) | ||
| 1334 | { | ||
| 1335 | return platform_driver_probe(&davinci_mmcsd_driver, | ||
| 1336 | davinci_mmcsd_probe); | ||
| 1337 | } | ||
| 1338 | module_init(davinci_mmcsd_init); | ||
| 1339 | |||
| 1340 | static void __exit davinci_mmcsd_exit(void) | ||
| 1341 | { | ||
| 1342 | platform_driver_unregister(&davinci_mmcsd_driver); | ||
| 1343 | } | ||
| 1344 | module_exit(davinci_mmcsd_exit); | ||
| 1345 | |||
| 1346 | MODULE_AUTHOR("Texas Instruments India"); | ||
| 1347 | MODULE_LICENSE("GPL"); | ||
| 1348 | MODULE_DESCRIPTION("MMC/SD driver for Davinci MMC controller"); | ||
| 1349 | |||
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 88671529c45d..60a2b69e54f5 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
| @@ -679,17 +679,17 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
| 679 | { | 679 | { |
| 680 | struct mmc_host *mmc; | 680 | struct mmc_host *mmc; |
| 681 | struct mxcmci_host *host = NULL; | 681 | struct mxcmci_host *host = NULL; |
| 682 | struct resource *r; | 682 | struct resource *iores, *r; |
| 683 | int ret = 0, irq; | 683 | int ret = 0, irq; |
| 684 | 684 | ||
| 685 | printk(KERN_INFO "i.MX SDHC driver\n"); | 685 | printk(KERN_INFO "i.MX SDHC driver\n"); |
| 686 | 686 | ||
| 687 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 687 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 688 | irq = platform_get_irq(pdev, 0); | 688 | irq = platform_get_irq(pdev, 0); |
| 689 | if (!r || irq < 0) | 689 | if (!iores || irq < 0) |
| 690 | return -EINVAL; | 690 | return -EINVAL; |
| 691 | 691 | ||
| 692 | r = request_mem_region(r->start, resource_size(r), pdev->name); | 692 | r = request_mem_region(iores->start, resource_size(iores), pdev->name); |
| 693 | if (!r) | 693 | if (!r) |
| 694 | return -EBUSY; | 694 | return -EBUSY; |
| 695 | 695 | ||
| @@ -809,7 +809,7 @@ out_iounmap: | |||
| 809 | out_free: | 809 | out_free: |
| 810 | mmc_free_host(mmc); | 810 | mmc_free_host(mmc); |
| 811 | out_release_mem: | 811 | out_release_mem: |
| 812 | release_mem_region(host->res->start, resource_size(host->res)); | 812 | release_mem_region(iores->start, resource_size(iores)); |
| 813 | return ret; | 813 | return ret; |
| 814 | } | 814 | } |
| 815 | 815 | ||
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 5f970e253e50..c6d7e8ecadbf 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
| @@ -1459,8 +1459,10 @@ static int __init mmc_omap_probe(struct platform_device *pdev) | |||
| 1459 | goto err_ioremap; | 1459 | goto err_ioremap; |
| 1460 | 1460 | ||
| 1461 | host->iclk = clk_get(&pdev->dev, "ick"); | 1461 | host->iclk = clk_get(&pdev->dev, "ick"); |
| 1462 | if (IS_ERR(host->iclk)) | 1462 | if (IS_ERR(host->iclk)) { |
| 1463 | ret = PTR_ERR(host->iclk); | ||
| 1463 | goto err_free_mmc_host; | 1464 | goto err_free_mmc_host; |
| 1465 | } | ||
| 1464 | clk_enable(host->iclk); | 1466 | clk_enable(host->iclk); |
| 1465 | 1467 | ||
| 1466 | host->fclk = clk_get(&pdev->dev, "fck"); | 1468 | host->fclk = clk_get(&pdev->dev, "fck"); |
| @@ -1500,10 +1502,8 @@ err_free_irq: | |||
| 1500 | err_free_fclk: | 1502 | err_free_fclk: |
| 1501 | clk_put(host->fclk); | 1503 | clk_put(host->fclk); |
| 1502 | err_free_iclk: | 1504 | err_free_iclk: |
| 1503 | if (host->iclk != NULL) { | 1505 | clk_disable(host->iclk); |
| 1504 | clk_disable(host->iclk); | 1506 | clk_put(host->iclk); |
| 1505 | clk_put(host->iclk); | ||
| 1506 | } | ||
| 1507 | err_free_mmc_host: | 1507 | err_free_mmc_host: |
| 1508 | iounmap(host->virt_base); | 1508 | iounmap(host->virt_base); |
| 1509 | err_ioremap: | 1509 | err_ioremap: |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index bb47ff465c04..0d783f3e79ed 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -828,7 +828,7 @@ static int pxamci_resume(struct device *dev) | |||
| 828 | return ret; | 828 | return ret; |
| 829 | } | 829 | } |
| 830 | 830 | ||
| 831 | static struct dev_pm_ops pxamci_pm_ops = { | 831 | static const struct dev_pm_ops pxamci_pm_ops = { |
| 832 | .suspend = pxamci_suspend, | 832 | .suspend = pxamci_suspend, |
| 833 | .resume = pxamci_resume, | 833 | .resume = pxamci_resume, |
| 834 | }; | 834 | }; |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 941a4d35ef8d..d96e1abf2d64 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
| @@ -820,7 +820,7 @@ fail_request: | |||
| 820 | static void finalize_request(struct s3cmci_host *host) | 820 | static void finalize_request(struct s3cmci_host *host) |
| 821 | { | 821 | { |
| 822 | struct mmc_request *mrq = host->mrq; | 822 | struct mmc_request *mrq = host->mrq; |
| 823 | struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd; | 823 | struct mmc_command *cmd; |
| 824 | int debug_as_failure = 0; | 824 | int debug_as_failure = 0; |
| 825 | 825 | ||
| 826 | if (host->complete_what != COMPLETION_FINALIZE) | 826 | if (host->complete_what != COMPLETION_FINALIZE) |
| @@ -828,6 +828,7 @@ static void finalize_request(struct s3cmci_host *host) | |||
| 828 | 828 | ||
| 829 | if (!mrq) | 829 | if (!mrq) |
| 830 | return; | 830 | return; |
| 831 | cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd; | ||
| 831 | 832 | ||
| 832 | if (cmd->data && (cmd->error == 0) && | 833 | if (cmd->data && (cmd->error == 0) && |
| 833 | (cmd->data->error == 0)) { | 834 | (cmd->data->error == 0)) { |
| @@ -1302,10 +1303,8 @@ static int s3cmci_get_ro(struct mmc_host *mmc) | |||
| 1302 | if (pdata->no_wprotect) | 1303 | if (pdata->no_wprotect) |
| 1303 | return 0; | 1304 | return 0; |
| 1304 | 1305 | ||
| 1305 | ret = s3c2410_gpio_getpin(pdata->gpio_wprotect); | 1306 | ret = gpio_get_value(pdata->gpio_wprotect) ? 1 : 0; |
| 1306 | 1307 | ret ^= pdata->wprotect_invert; | |
| 1307 | if (pdata->wprotect_invert) | ||
| 1308 | ret = !ret; | ||
| 1309 | 1308 | ||
| 1310 | return ret; | 1309 | return ret; |
| 1311 | } | 1310 | } |
| @@ -1654,7 +1653,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) | |||
| 1654 | goto probe_free_irq; | 1653 | goto probe_free_irq; |
| 1655 | } | 1654 | } |
| 1656 | 1655 | ||
| 1657 | host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect); | 1656 | host->irq_cd = gpio_to_irq(host->pdata->gpio_detect); |
| 1658 | 1657 | ||
| 1659 | if (host->irq_cd >= 0) { | 1658 | if (host->irq_cd >= 0) { |
| 1660 | if (request_irq(host->irq_cd, s3cmci_irq_cd, | 1659 | if (request_irq(host->irq_cd, s3cmci_irq_cd, |
| @@ -1892,7 +1891,7 @@ static int s3cmci_resume(struct device *dev) | |||
| 1892 | return mmc_resume_host(mmc); | 1891 | return mmc_resume_host(mmc); |
| 1893 | } | 1892 | } |
| 1894 | 1893 | ||
| 1895 | static struct dev_pm_ops s3cmci_pm = { | 1894 | static const struct dev_pm_ops s3cmci_pm = { |
| 1896 | .suspend = s3cmci_suspend, | 1895 | .suspend = s3cmci_suspend, |
| 1897 | .resume = s3cmci_resume, | 1896 | .resume = s3cmci_resume, |
| 1898 | }; | 1897 | }; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index e0356644d1aa..5c3a1767770a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -285,6 +285,73 @@ static const struct sdhci_pci_fixes sdhci_jmicron = { | |||
| 285 | .resume = jmicron_resume, | 285 | .resume = jmicron_resume, |
| 286 | }; | 286 | }; |
| 287 | 287 | ||
| 288 | /* SysKonnect CardBus2SDIO extra registers */ | ||
| 289 | #define SYSKT_CTRL 0x200 | ||
| 290 | #define SYSKT_RDFIFO_STAT 0x204 | ||
| 291 | #define SYSKT_WRFIFO_STAT 0x208 | ||
| 292 | #define SYSKT_POWER_DATA 0x20c | ||
| 293 | #define SYSKT_POWER_330 0xef | ||
| 294 | #define SYSKT_POWER_300 0xf8 | ||
| 295 | #define SYSKT_POWER_184 0xcc | ||
| 296 | #define SYSKT_POWER_CMD 0x20d | ||
| 297 | #define SYSKT_POWER_START (1 << 7) | ||
| 298 | #define SYSKT_POWER_STATUS 0x20e | ||
| 299 | #define SYSKT_POWER_STATUS_OK (1 << 0) | ||
| 300 | #define SYSKT_BOARD_REV 0x210 | ||
| 301 | #define SYSKT_CHIP_REV 0x211 | ||
| 302 | #define SYSKT_CONF_DATA 0x212 | ||
| 303 | #define SYSKT_CONF_DATA_1V8 (1 << 2) | ||
| 304 | #define SYSKT_CONF_DATA_2V5 (1 << 1) | ||
| 305 | #define SYSKT_CONF_DATA_3V3 (1 << 0) | ||
| 306 | |||
| 307 | static int syskt_probe(struct sdhci_pci_chip *chip) | ||
| 308 | { | ||
| 309 | if ((chip->pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { | ||
| 310 | chip->pdev->class &= ~0x0000FF; | ||
| 311 | chip->pdev->class |= PCI_SDHCI_IFDMA; | ||
| 312 | } | ||
| 313 | return 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | static int syskt_probe_slot(struct sdhci_pci_slot *slot) | ||
| 317 | { | ||
| 318 | int tm, ps; | ||
| 319 | |||
| 320 | u8 board_rev = readb(slot->host->ioaddr + SYSKT_BOARD_REV); | ||
| 321 | u8 chip_rev = readb(slot->host->ioaddr + SYSKT_CHIP_REV); | ||
| 322 | dev_info(&slot->chip->pdev->dev, "SysKonnect CardBus2SDIO, " | ||
| 323 | "board rev %d.%d, chip rev %d.%d\n", | ||
| 324 | board_rev >> 4, board_rev & 0xf, | ||
| 325 | chip_rev >> 4, chip_rev & 0xf); | ||
| 326 | if (chip_rev >= 0x20) | ||
| 327 | slot->host->quirks |= SDHCI_QUIRK_FORCE_DMA; | ||
| 328 | |||
| 329 | writeb(SYSKT_POWER_330, slot->host->ioaddr + SYSKT_POWER_DATA); | ||
| 330 | writeb(SYSKT_POWER_START, slot->host->ioaddr + SYSKT_POWER_CMD); | ||
| 331 | udelay(50); | ||
| 332 | tm = 10; /* Wait max 1 ms */ | ||
| 333 | do { | ||
| 334 | ps = readw(slot->host->ioaddr + SYSKT_POWER_STATUS); | ||
| 335 | if (ps & SYSKT_POWER_STATUS_OK) | ||
| 336 | break; | ||
| 337 | udelay(100); | ||
| 338 | } while (--tm); | ||
| 339 | if (!tm) { | ||
| 340 | dev_err(&slot->chip->pdev->dev, | ||
| 341 | "power regulator never stabilized"); | ||
| 342 | writeb(0, slot->host->ioaddr + SYSKT_POWER_CMD); | ||
| 343 | return -ENODEV; | ||
| 344 | } | ||
| 345 | |||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | static const struct sdhci_pci_fixes sdhci_syskt = { | ||
| 350 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER, | ||
| 351 | .probe = syskt_probe, | ||
| 352 | .probe_slot = syskt_probe_slot, | ||
| 353 | }; | ||
| 354 | |||
| 288 | static int via_probe(struct sdhci_pci_chip *chip) | 355 | static int via_probe(struct sdhci_pci_chip *chip) |
| 289 | { | 356 | { |
| 290 | if (chip->pdev->revision == 0x10) | 357 | if (chip->pdev->revision == 0x10) |
| @@ -363,6 +430,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
| 363 | }, | 430 | }, |
| 364 | 431 | ||
| 365 | { | 432 | { |
| 433 | .vendor = PCI_VENDOR_ID_SYSKONNECT, | ||
| 434 | .device = 0x8000, | ||
| 435 | .subvendor = PCI_ANY_ID, | ||
| 436 | .subdevice = PCI_ANY_ID, | ||
| 437 | .driver_data = (kernel_ulong_t)&sdhci_syskt, | ||
| 438 | }, | ||
| 439 | |||
| 440 | { | ||
| 366 | .vendor = PCI_VENDOR_ID_VIA, | 441 | .vendor = PCI_VENDOR_ID_VIA, |
| 367 | .device = 0x95d0, | 442 | .device = 0x95d0, |
| 368 | .subvendor = PCI_ANY_ID, | 443 | .subvendor = PCI_ANY_ID, |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 91991b460c45..7cccc8523747 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
| @@ -591,7 +591,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) | |||
| 591 | disable_mmc_irqs(host, TMIO_MASK_ALL); | 591 | disable_mmc_irqs(host, TMIO_MASK_ALL); |
| 592 | 592 | ||
| 593 | ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | | 593 | ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | |
| 594 | IRQF_TRIGGER_FALLING, "tmio-mmc", host); | 594 | IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); |
| 595 | if (ret) | 595 | if (ret) |
| 596 | goto unmap_cnf; | 596 | goto unmap_cnf; |
| 597 | 597 | ||
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c index 7c302d55910e..66123419f65d 100644 --- a/drivers/mtd/nand/nomadik_nand.c +++ b/drivers/mtd/nand/nomadik_nand.c | |||
| @@ -216,7 +216,7 @@ static int nomadik_nand_resume(struct device *dev) | |||
| 216 | return 0; | 216 | return 0; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static struct dev_pm_ops nomadik_nand_pm_ops = { | 219 | static const struct dev_pm_ops nomadik_nand_pm_ops = { |
| 220 | .suspend = nomadik_nand_suspend, | 220 | .suspend = nomadik_nand_suspend, |
| 221 | .resume = nomadik_nand_resume, | 221 | .resume = nomadik_nand_resume, |
| 222 | }; | 222 | }; |
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 78b7167a8ce3..39db0e96815d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c | |||
| @@ -837,7 +837,7 @@ static int vortex_resume(struct device *dev) | |||
| 837 | return 0; | 837 | return 0; |
| 838 | } | 838 | } |
| 839 | 839 | ||
| 840 | static struct dev_pm_ops vortex_pm_ops = { | 840 | static const struct dev_pm_ops vortex_pm_ops = { |
| 841 | .suspend = vortex_suspend, | 841 | .suspend = vortex_suspend, |
| 842 | .resume = vortex_resume, | 842 | .resume = vortex_resume, |
| 843 | .freeze = vortex_suspend, | 843 | .freeze = vortex_suspend, |
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 0cbe3c0e7c06..b37730065688 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c | |||
| @@ -1646,7 +1646,7 @@ dm9000_drv_resume(struct device *dev) | |||
| 1646 | return 0; | 1646 | return 0; |
| 1647 | } | 1647 | } |
| 1648 | 1648 | ||
| 1649 | static struct dev_pm_ops dm9000_drv_pm_ops = { | 1649 | static const struct dev_pm_ops dm9000_drv_pm_ops = { |
| 1650 | .suspend = dm9000_drv_suspend, | 1650 | .suspend = dm9000_drv_suspend, |
| 1651 | .resume = dm9000_drv_resume, | 1651 | .resume = dm9000_drv_resume, |
| 1652 | }; | 1652 | }; |
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index acfc5a3aa490..60f96c468a24 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -4859,7 +4859,7 @@ out: | |||
| 4859 | return 0; | 4859 | return 0; |
| 4860 | } | 4860 | } |
| 4861 | 4861 | ||
| 4862 | static struct dev_pm_ops rtl8169_pm_ops = { | 4862 | static const struct dev_pm_ops rtl8169_pm_ops = { |
| 4863 | .suspend = rtl8169_suspend, | 4863 | .suspend = rtl8169_suspend, |
| 4864 | .resume = rtl8169_resume, | 4864 | .resume = rtl8169_resume, |
| 4865 | .freeze = rtl8169_suspend, | 4865 | .freeze = rtl8169_suspend, |
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 20d6095cf411..494cd91ea39c 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
| @@ -2154,7 +2154,7 @@ static int smsc911x_resume(struct device *dev) | |||
| 2154 | return (to == 0) ? -EIO : 0; | 2154 | return (to == 0) ? -EIO : 0; |
| 2155 | } | 2155 | } |
| 2156 | 2156 | ||
| 2157 | static struct dev_pm_ops smsc911x_pm_ops = { | 2157 | static const struct dev_pm_ops smsc911x_pm_ops = { |
| 2158 | .suspend = smsc911x_suspend, | 2158 | .suspend = smsc911x_suspend, |
| 2159 | .resume = smsc911x_resume, | 2159 | .resume = smsc911x_resume, |
| 2160 | }; | 2160 | }; |
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 1ceb9d0f8b97..9cc438282d77 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c | |||
| @@ -2689,7 +2689,7 @@ vmxnet3_resume(struct device *device) | |||
| 2689 | return 0; | 2689 | return 0; |
| 2690 | } | 2690 | } |
| 2691 | 2691 | ||
| 2692 | static struct dev_pm_ops vmxnet3_pm_ops = { | 2692 | static const struct dev_pm_ops vmxnet3_pm_ops = { |
| 2693 | .suspend = vmxnet3_suspend, | 2693 | .suspend = vmxnet3_suspend, |
| 2694 | .resume = vmxnet3_resume, | 2694 | .resume = vmxnet3_resume, |
| 2695 | }; | 2695 | }; |
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 13a64bc081b6..0bc5d474b168 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c | |||
| @@ -779,12 +779,9 @@ static ssize_t pdcs_auto_write(struct kobject *kobj, | |||
| 779 | read_unlock(&pathentry->rw_lock); | 779 | read_unlock(&pathentry->rw_lock); |
| 780 | 780 | ||
| 781 | DPRINTK("%s: flags before: 0x%X\n", __func__, flags); | 781 | DPRINTK("%s: flags before: 0x%X\n", __func__, flags); |
| 782 | 782 | ||
| 783 | temp = in; | 783 | temp = skip_spaces(in); |
| 784 | 784 | ||
| 785 | while (*temp && isspace(*temp)) | ||
| 786 | temp++; | ||
| 787 | |||
| 788 | c = *temp++ - '0'; | 785 | c = *temp++ - '0'; |
| 789 | if ((c != 0) && (c != 1)) | 786 | if ((c != 0) && (c != 1)) |
| 790 | goto parse_error; | 787 | goto parse_error; |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index ce52ea34fee5..a49452e2aed9 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
| @@ -43,7 +43,7 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev) | |||
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | #ifdef CONFIG_PM | 45 | #ifdef CONFIG_PM |
| 46 | static struct dev_pm_ops pcie_portdrv_pm_ops = { | 46 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { |
| 47 | .suspend = pcie_port_device_suspend, | 47 | .suspend = pcie_port_device_suspend, |
| 48 | .resume = pcie_port_device_resume, | 48 | .resume = pcie_port_device_resume, |
| 49 | .freeze = pcie_port_device_suspend, | 49 | .freeze = pcie_port_device_suspend, |
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index da346eb7e77e..3aabf1e37988 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c | |||
| @@ -336,7 +336,7 @@ static int pxa2xx_drv_pcmcia_resume(struct device *dev) | |||
| 336 | return pcmcia_socket_dev_resume(dev); | 336 | return pcmcia_socket_dev_resume(dev); |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | static struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = { | 339 | static const struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = { |
| 340 | .suspend = pxa2xx_drv_pcmcia_suspend, | 340 | .suspend = pxa2xx_drv_pcmcia_suspend, |
| 341 | .resume = pxa2xx_drv_pcmcia_resume, | 341 | .resume = pxa2xx_drv_pcmcia_resume, |
| 342 | }; | 342 | }; |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index fe02cfd4b5e9..e4d12acdd525 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
| @@ -1330,7 +1330,7 @@ static int yenta_dev_resume(struct device *dev) | |||
| 1330 | return 0; | 1330 | return 0; |
| 1331 | } | 1331 | } |
| 1332 | 1332 | ||
| 1333 | static struct dev_pm_ops yenta_pm_ops = { | 1333 | static const struct dev_pm_ops yenta_pm_ops = { |
| 1334 | .suspend_noirq = yenta_dev_suspend_noirq, | 1334 | .suspend_noirq = yenta_dev_suspend_noirq, |
| 1335 | .resume_noirq = yenta_dev_resume_noirq, | 1335 | .resume_noirq = yenta_dev_resume_noirq, |
| 1336 | .resume = yenta_dev_resume, | 1336 | .resume = yenta_dev_resume, |
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index ab64522aaa64..be27aa47e810 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c | |||
| @@ -460,7 +460,7 @@ static int acerhdf_remove(struct platform_device *device) | |||
| 460 | return 0; | 460 | return 0; |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | static struct dev_pm_ops acerhdf_pm_ops = { | 463 | static const struct dev_pm_ops acerhdf_pm_ops = { |
| 464 | .suspend = acerhdf_suspend, | 464 | .suspend = acerhdf_suspend, |
| 465 | .freeze = acerhdf_suspend, | 465 | .freeze = acerhdf_suspend, |
| 466 | }; | 466 | }; |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 4226e5352738..e647a856b9bf 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -154,7 +154,7 @@ static struct eeepc_hotk *ehotk; | |||
| 154 | static int eeepc_hotk_thaw(struct device *device); | 154 | static int eeepc_hotk_thaw(struct device *device); |
| 155 | static int eeepc_hotk_restore(struct device *device); | 155 | static int eeepc_hotk_restore(struct device *device); |
| 156 | 156 | ||
| 157 | static struct dev_pm_ops eeepc_pm_ops = { | 157 | static const struct dev_pm_ops eeepc_pm_ops = { |
| 158 | .thaw = eeepc_hotk_thaw, | 158 | .thaw = eeepc_hotk_thaw, |
| 159 | .restore = eeepc_hotk_restore, | 159 | .restore = eeepc_hotk_restore, |
| 160 | }; | 160 | }; |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index c2842171cec6..f00a71c58e69 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
| @@ -94,7 +94,7 @@ static struct rfkill *wifi_rfkill; | |||
| 94 | static struct rfkill *bluetooth_rfkill; | 94 | static struct rfkill *bluetooth_rfkill; |
| 95 | static struct rfkill *wwan_rfkill; | 95 | static struct rfkill *wwan_rfkill; |
| 96 | 96 | ||
| 97 | static struct dev_pm_ops hp_wmi_pm_ops = { | 97 | static const struct dev_pm_ops hp_wmi_pm_ops = { |
| 98 | .resume = hp_wmi_resume_handler, | 98 | .resume = hp_wmi_resume_handler, |
| 99 | .restore = hp_wmi_resume_handler, | 99 | .restore = hp_wmi_resume_handler, |
| 100 | }; | 100 | }; |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 0ed84806f8ae..cf61d6a8ef6f 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -1006,11 +1006,8 @@ static int parse_strtoul(const char *buf, | |||
| 1006 | { | 1006 | { |
| 1007 | char *endp; | 1007 | char *endp; |
| 1008 | 1008 | ||
| 1009 | while (*buf && isspace(*buf)) | 1009 | *value = simple_strtoul(skip_spaces(buf), &endp, 0); |
| 1010 | buf++; | 1010 | endp = skip_spaces(endp); |
| 1011 | *value = simple_strtoul(buf, &endp, 0); | ||
| 1012 | while (*endp && isspace(*endp)) | ||
| 1013 | endp++; | ||
| 1014 | if (*endp || *value > max) | 1011 | if (*endp || *value > max) |
| 1015 | return -EINVAL; | 1012 | return -EINVAL; |
| 1016 | 1013 | ||
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index c3f1c8e9d254..68b0c04987e4 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c | |||
| @@ -310,8 +310,7 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, | |||
| 310 | goto done; | 310 | goto done; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | while (isspace(*buf)) | 313 | buf = skip_spaces(buf); |
| 314 | ++buf; | ||
| 315 | if (!strnicmp(buf, "disable", 7)) { | 314 | if (!strnicmp(buf, "disable", 7)) { |
| 316 | retval = pnp_disable_dev(dev); | 315 | retval = pnp_disable_dev(dev); |
| 317 | goto done; | 316 | goto done; |
| @@ -353,19 +352,13 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, | |||
| 353 | pnp_init_resources(dev); | 352 | pnp_init_resources(dev); |
| 354 | mutex_lock(&pnp_res_mutex); | 353 | mutex_lock(&pnp_res_mutex); |
| 355 | while (1) { | 354 | while (1) { |
| 356 | while (isspace(*buf)) | 355 | buf = skip_spaces(buf); |
| 357 | ++buf; | ||
| 358 | if (!strnicmp(buf, "io", 2)) { | 356 | if (!strnicmp(buf, "io", 2)) { |
| 359 | buf += 2; | 357 | buf = skip_spaces(buf + 2); |
| 360 | while (isspace(*buf)) | ||
| 361 | ++buf; | ||
| 362 | start = simple_strtoul(buf, &buf, 0); | 358 | start = simple_strtoul(buf, &buf, 0); |
| 363 | while (isspace(*buf)) | 359 | buf = skip_spaces(buf); |
| 364 | ++buf; | ||
| 365 | if (*buf == '-') { | 360 | if (*buf == '-') { |
| 366 | buf += 1; | 361 | buf = skip_spaces(buf + 1); |
| 367 | while (isspace(*buf)) | ||
| 368 | ++buf; | ||
| 369 | end = simple_strtoul(buf, &buf, 0); | 362 | end = simple_strtoul(buf, &buf, 0); |
| 370 | } else | 363 | } else |
| 371 | end = start; | 364 | end = start; |
| @@ -373,16 +366,11 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, | |||
| 373 | continue; | 366 | continue; |
| 374 | } | 367 | } |
| 375 | if (!strnicmp(buf, "mem", 3)) { | 368 | if (!strnicmp(buf, "mem", 3)) { |
| 376 | buf += 3; | 369 | buf = skip_spaces(buf + 3); |
| 377 | while (isspace(*buf)) | ||
| 378 | ++buf; | ||
| 379 | start = simple_strtoul(buf, &buf, 0); | 370 | start = simple_strtoul(buf, &buf, 0); |
| 380 | while (isspace(*buf)) | 371 | buf = skip_spaces(buf); |
| 381 | ++buf; | ||
| 382 | if (*buf == '-') { | 372 | if (*buf == '-') { |
| 383 | buf += 1; | 373 | buf = skip_spaces(buf + 1); |
| 384 | while (isspace(*buf)) | ||
| 385 | ++buf; | ||
| 386 | end = simple_strtoul(buf, &buf, 0); | 374 | end = simple_strtoul(buf, &buf, 0); |
| 387 | } else | 375 | } else |
| 388 | end = start; | 376 | end = start; |
| @@ -390,17 +378,13 @@ static ssize_t pnp_set_current_resources(struct device *dmdev, | |||
| 390 | continue; | 378 | continue; |
| 391 | } | 379 | } |
| 392 | if (!strnicmp(buf, "irq", 3)) { | 380 | if (!strnicmp(buf, "irq", 3)) { |
| 393 | buf += 3; | 381 | buf = skip_spaces(buf + 3); |
| 394 | while (isspace(*buf)) | ||
| 395 | ++buf; | ||
| 396 | start = simple_strtoul(buf, &buf, 0); | 382 | start = simple_strtoul(buf, &buf, 0); |
| 397 | pnp_add_irq_resource(dev, start, 0); | 383 | pnp_add_irq_resource(dev, start, 0); |
| 398 | continue; | 384 | continue; |
| 399 | } | 385 | } |
| 400 | if (!strnicmp(buf, "dma", 3)) { | 386 | if (!strnicmp(buf, "dma", 3)) { |
| 401 | buf += 3; | 387 | buf = skip_spaces(buf + 3); |
| 402 | while (isspace(*buf)) | ||
| 403 | ++buf; | ||
| 404 | start = simple_strtoul(buf, &buf, 0); | 388 | start = simple_strtoul(buf, &buf, 0); |
| 405 | pnp_add_dma_resource(dev, start, 0); | 389 | pnp_add_dma_resource(dev, start, 0); |
| 406 | continue; | 390 | continue; |
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c index f2bfd296dbae..fa39e759a275 100644 --- a/drivers/power/wm97xx_battery.c +++ b/drivers/power/wm97xx_battery.c | |||
| @@ -157,7 +157,7 @@ static int wm97xx_bat_resume(struct device *dev) | |||
| 157 | return 0; | 157 | return 0; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | static struct dev_pm_ops wm97xx_bat_pm_ops = { | 160 | static const struct dev_pm_ops wm97xx_bat_pm_ops = { |
| 161 | .suspend = wm97xx_bat_suspend, | 161 | .suspend = wm97xx_bat_suspend, |
| 162 | .resume = wm97xx_bat_resume, | 162 | .resume = wm97xx_bat_resume, |
| 163 | }; | 163 | }; |
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index 747ca194fad4..e6351b743da6 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
| @@ -456,7 +456,7 @@ static int pxa_rtc_resume(struct device *dev) | |||
| 456 | return 0; | 456 | return 0; |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static struct dev_pm_ops pxa_rtc_pm_ops = { | 459 | static const struct dev_pm_ops pxa_rtc_pm_ops = { |
| 460 | .suspend = pxa_rtc_suspend, | 460 | .suspend = pxa_rtc_suspend, |
| 461 | .resume = pxa_rtc_resume, | 461 | .resume = pxa_rtc_resume, |
| 462 | }; | 462 | }; |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 29f98a70586e..e4a44b641702 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -407,7 +407,7 @@ static int sa1100_rtc_resume(struct device *dev) | |||
| 407 | return 0; | 407 | return 0; |
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | static struct dev_pm_ops sa1100_rtc_pm_ops = { | 410 | static const struct dev_pm_ops sa1100_rtc_pm_ops = { |
| 411 | .suspend = sa1100_rtc_suspend, | 411 | .suspend = sa1100_rtc_suspend, |
| 412 | .resume = sa1100_rtc_resume, | 412 | .resume = sa1100_rtc_resume, |
| 413 | }; | 413 | }; |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index e6ed5404bca0..e95cc6f8d61e 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
| @@ -826,7 +826,7 @@ static int sh_rtc_resume(struct device *dev) | |||
| 826 | return 0; | 826 | return 0; |
| 827 | } | 827 | } |
| 828 | 828 | ||
| 829 | static struct dev_pm_ops sh_rtc_dev_pm_ops = { | 829 | static const struct dev_pm_ops sh_rtc_dev_pm_ops = { |
| 830 | .suspend = sh_rtc_suspend, | 830 | .suspend = sh_rtc_suspend, |
| 831 | .resume = sh_rtc_resume, | 831 | .resume = sh_rtc_resume, |
| 832 | }; | 832 | }; |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 79795cdf6ed8..000c7e481e59 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
| @@ -485,7 +485,7 @@ static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | |||
| 485 | return 0; | 485 | return 0; |
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | static struct dev_pm_ops wm831x_rtc_pm_ops = { | 488 | static const struct dev_pm_ops wm831x_rtc_pm_ops = { |
| 489 | .suspend = wm831x_rtc_suspend, | 489 | .suspend = wm831x_rtc_suspend, |
| 490 | .resume = wm831x_rtc_resume, | 490 | .resume = wm831x_rtc_resume, |
| 491 | 491 | ||
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 5f23eca82804..6315fbd8e68b 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #define KMSG_COMPONENT "dasd" | 14 | #define KMSG_COMPONENT "dasd" |
| 15 | 15 | ||
| 16 | #include <linux/ctype.h> | 16 | #include <linux/ctype.h> |
| 17 | #include <linux/string.h> | ||
| 17 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
| 18 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
| 19 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
| @@ -272,10 +273,10 @@ dasd_statistics_write(struct file *file, const char __user *user_buf, | |||
| 272 | DBF_EVENT(DBF_DEBUG, "/proc/dasd/statictics: '%s'\n", buffer); | 273 | DBF_EVENT(DBF_DEBUG, "/proc/dasd/statictics: '%s'\n", buffer); |
| 273 | 274 | ||
| 274 | /* check for valid verbs */ | 275 | /* check for valid verbs */ |
| 275 | for (str = buffer; isspace(*str); str++); | 276 | str = skip_spaces(buffer); |
| 276 | if (strncmp(str, "set", 3) == 0 && isspace(str[3])) { | 277 | if (strncmp(str, "set", 3) == 0 && isspace(str[3])) { |
| 277 | /* 'set xxx' was given */ | 278 | /* 'set xxx' was given */ |
| 278 | for (str = str + 4; isspace(*str); str++); | 279 | str = skip_spaces(str + 4); |
| 279 | if (strcmp(str, "on") == 0) { | 280 | if (strcmp(str, "on") == 0) { |
| 280 | /* switch on statistics profiling */ | 281 | /* switch on statistics profiling */ |
| 281 | dasd_profile_level = DASD_PROFILE_ON; | 282 | dasd_profile_level = DASD_PROFILE_ON; |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index f76f4bd82b9f..9b43ae94beba 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
| @@ -1005,7 +1005,7 @@ static int dcssblk_thaw(struct device *dev) | |||
| 1005 | return 0; | 1005 | return 0; |
| 1006 | } | 1006 | } |
| 1007 | 1007 | ||
| 1008 | static struct dev_pm_ops dcssblk_pm_ops = { | 1008 | static const struct dev_pm_ops dcssblk_pm_ops = { |
| 1009 | .freeze = dcssblk_freeze, | 1009 | .freeze = dcssblk_freeze, |
| 1010 | .thaw = dcssblk_thaw, | 1010 | .thaw = dcssblk_thaw, |
| 1011 | .restore = dcssblk_restore, | 1011 | .restore = dcssblk_restore, |
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 116d1b3eeb15..118de392af63 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
| @@ -407,7 +407,7 @@ static int xpram_restore(struct device *dev) | |||
| 407 | return 0; | 407 | return 0; |
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | static struct dev_pm_ops xpram_pm_ops = { | 410 | static const struct dev_pm_ops xpram_pm_ops = { |
| 411 | .restore = xpram_restore, | 411 | .restore = xpram_restore, |
| 412 | }; | 412 | }; |
| 413 | 413 | ||
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 60473f86e1f9..33e96484d54f 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c | |||
| @@ -529,7 +529,7 @@ static int monreader_restore(struct device *dev) | |||
| 529 | return monreader_thaw(dev); | 529 | return monreader_thaw(dev); |
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | static struct dev_pm_ops monreader_pm_ops = { | 532 | static const struct dev_pm_ops monreader_pm_ops = { |
| 533 | .freeze = monreader_freeze, | 533 | .freeze = monreader_freeze, |
| 534 | .thaw = monreader_thaw, | 534 | .thaw = monreader_thaw, |
| 535 | .restore = monreader_restore, | 535 | .restore = monreader_restore, |
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index 6532ed8b4afa..668a0579b26b 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c | |||
| @@ -323,7 +323,7 @@ static int monwriter_thaw(struct device *dev) | |||
| 323 | return monwriter_restore(dev); | 323 | return monwriter_restore(dev); |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | static struct dev_pm_ops monwriter_pm_ops = { | 326 | static const struct dev_pm_ops monwriter_pm_ops = { |
| 327 | .freeze = monwriter_freeze, | 327 | .freeze = monwriter_freeze, |
| 328 | .thaw = monwriter_thaw, | 328 | .thaw = monwriter_thaw, |
| 329 | .restore = monwriter_restore, | 329 | .restore = monwriter_restore, |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index a983f5086788..ec88c59842e3 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
| @@ -1019,7 +1019,7 @@ static int sclp_restore(struct device *dev) | |||
| 1019 | return sclp_undo_suspend(SCLP_PM_EVENT_RESTORE); | 1019 | return sclp_undo_suspend(SCLP_PM_EVENT_RESTORE); |
| 1020 | } | 1020 | } |
| 1021 | 1021 | ||
| 1022 | static struct dev_pm_ops sclp_pm_ops = { | 1022 | static const struct dev_pm_ops sclp_pm_ops = { |
| 1023 | .freeze = sclp_freeze, | 1023 | .freeze = sclp_freeze, |
| 1024 | .thaw = sclp_thaw, | 1024 | .thaw = sclp_thaw, |
| 1025 | .restore = sclp_restore, | 1025 | .restore = sclp_restore, |
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 28b5afc129c3..b3beab610da4 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
| @@ -547,7 +547,7 @@ struct read_storage_sccb { | |||
| 547 | u32 entries[0]; | 547 | u32 entries[0]; |
| 548 | } __packed; | 548 | } __packed; |
| 549 | 549 | ||
| 550 | static struct dev_pm_ops sclp_mem_pm_ops = { | 550 | static const struct dev_pm_ops sclp_mem_pm_ops = { |
| 551 | .freeze = sclp_mem_freeze, | 551 | .freeze = sclp_mem_freeze, |
| 552 | }; | 552 | }; |
| 553 | 553 | ||
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 899aa795bf38..7dfa5412d5a8 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
| @@ -675,7 +675,7 @@ static int vmlogrdr_pm_prepare(struct device *dev) | |||
| 675 | } | 675 | } |
| 676 | 676 | ||
| 677 | 677 | ||
| 678 | static struct dev_pm_ops vmlogrdr_pm_ops = { | 678 | static const struct dev_pm_ops vmlogrdr_pm_ops = { |
| 679 | .prepare = vmlogrdr_pm_prepare, | 679 | .prepare = vmlogrdr_pm_prepare, |
| 680 | }; | 680 | }; |
| 681 | 681 | ||
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index a5a62f1f7747..5f97ea2ee6b1 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
| @@ -560,7 +560,7 @@ static int ccwgroup_pm_restore(struct device *dev) | |||
| 560 | return gdrv->restore ? gdrv->restore(gdev) : 0; | 560 | return gdrv->restore ? gdrv->restore(gdev) : 0; |
| 561 | } | 561 | } |
| 562 | 562 | ||
| 563 | static struct dev_pm_ops ccwgroup_pm_ops = { | 563 | static const struct dev_pm_ops ccwgroup_pm_ops = { |
| 564 | .prepare = ccwgroup_pm_prepare, | 564 | .prepare = ccwgroup_pm_prepare, |
| 565 | .complete = ccwgroup_pm_complete, | 565 | .complete = ccwgroup_pm_complete, |
| 566 | .freeze = ccwgroup_pm_freeze, | 566 | .freeze = ccwgroup_pm_freeze, |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 92ff88ac1107..7679aee6fa14 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
| @@ -1148,7 +1148,7 @@ static int css_pm_restore(struct device *dev) | |||
| 1148 | return drv->restore ? drv->restore(sch) : 0; | 1148 | return drv->restore ? drv->restore(sch) : 0; |
| 1149 | } | 1149 | } |
| 1150 | 1150 | ||
| 1151 | static struct dev_pm_ops css_pm_ops = { | 1151 | static const struct dev_pm_ops css_pm_ops = { |
| 1152 | .prepare = css_pm_prepare, | 1152 | .prepare = css_pm_prepare, |
| 1153 | .complete = css_pm_complete, | 1153 | .complete = css_pm_complete, |
| 1154 | .freeze = css_pm_freeze, | 1154 | .freeze = css_pm_freeze, |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 9fecfb4223a8..73901c9e260f 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -1904,7 +1904,7 @@ out_unlock: | |||
| 1904 | return ret; | 1904 | return ret; |
| 1905 | } | 1905 | } |
| 1906 | 1906 | ||
| 1907 | static struct dev_pm_ops ccw_pm_ops = { | 1907 | static const struct dev_pm_ops ccw_pm_ops = { |
| 1908 | .prepare = ccw_device_pm_prepare, | 1908 | .prepare = ccw_device_pm_prepare, |
| 1909 | .complete = ccw_device_pm_complete, | 1909 | .complete = ccw_device_pm_complete, |
| 1910 | .freeze = ccw_device_pm_freeze, | 1910 | .freeze = ccw_device_pm_freeze, |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 98c04cac43c1..65ebee0a3266 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
| @@ -159,7 +159,7 @@ static void netiucv_pm_complete(struct device *); | |||
| 159 | static int netiucv_pm_freeze(struct device *); | 159 | static int netiucv_pm_freeze(struct device *); |
| 160 | static int netiucv_pm_restore_thaw(struct device *); | 160 | static int netiucv_pm_restore_thaw(struct device *); |
| 161 | 161 | ||
| 162 | static struct dev_pm_ops netiucv_pm_ops = { | 162 | static const struct dev_pm_ops netiucv_pm_ops = { |
| 163 | .prepare = netiucv_pm_prepare, | 163 | .prepare = netiucv_pm_prepare, |
| 164 | .complete = netiucv_pm_complete, | 164 | .complete = netiucv_pm_complete, |
| 165 | .freeze = netiucv_pm_freeze, | 165 | .freeze = netiucv_pm_freeze, |
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 3012355f8304..67f2485d2372 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c | |||
| @@ -168,7 +168,7 @@ static int smsg_pm_restore_thaw(struct device *dev) | |||
| 168 | return 0; | 168 | return 0; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | static struct dev_pm_ops smsg_pm_ops = { | 171 | static const struct dev_pm_ops smsg_pm_ops = { |
| 172 | .freeze = smsg_pm_freeze, | 172 | .freeze = smsg_pm_freeze, |
| 173 | .thaw = smsg_pm_restore_thaw, | 173 | .thaw = smsg_pm_restore_thaw, |
| 174 | .restore = smsg_pm_restore_thaw, | 174 | .restore = smsg_pm_restore_thaw, |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 206c2fa8c1ba..8643f5089361 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -1333,7 +1333,7 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
| 1333 | 1333 | ||
| 1334 | error = &hostrcb->hcam.u.error.u.type_17_error; | 1334 | error = &hostrcb->hcam.u.error.u.type_17_error; |
| 1335 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; | 1335 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; |
| 1336 | strstrip(error->failure_reason); | 1336 | strim(error->failure_reason); |
| 1337 | 1337 | ||
| 1338 | ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, | 1338 | ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, |
| 1339 | be32_to_cpu(hostrcb->hcam.u.error.prc)); | 1339 | be32_to_cpu(hostrcb->hcam.u.error.prc)); |
| @@ -1359,7 +1359,7 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
| 1359 | 1359 | ||
| 1360 | error = &hostrcb->hcam.u.error.u.type_07_error; | 1360 | error = &hostrcb->hcam.u.error.u.type_07_error; |
| 1361 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; | 1361 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; |
| 1362 | strstrip(error->failure_reason); | 1362 | strim(error->failure_reason); |
| 1363 | 1363 | ||
| 1364 | ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, | 1364 | ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, |
| 1365 | be32_to_cpu(hostrcb->hcam.u.error.prc)); | 1365 | be32_to_cpu(hostrcb->hcam.u.error.prc)); |
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 2b38f6ad6e11..8b955b534a36 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c | |||
| @@ -984,7 +984,7 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc) | |||
| 984 | } | 984 | } |
| 985 | } | 985 | } |
| 986 | 986 | ||
| 987 | static int skip_spaces(char *ptr, int len) | 987 | static int sym_skip_spaces(char *ptr, int len) |
| 988 | { | 988 | { |
| 989 | int cnt, c; | 989 | int cnt, c; |
| 990 | 990 | ||
| @@ -1012,7 +1012,7 @@ static int is_keyword(char *ptr, int len, char *verb) | |||
| 1012 | } | 1012 | } |
| 1013 | 1013 | ||
| 1014 | #define SKIP_SPACES(ptr, len) \ | 1014 | #define SKIP_SPACES(ptr, len) \ |
| 1015 | if ((arg_len = skip_spaces(ptr, len)) < 1) \ | 1015 | if ((arg_len = sym_skip_spaces(ptr, len)) < 1) \ |
| 1016 | return -EINVAL; \ | 1016 | return -EINVAL; \ |
| 1017 | ptr += arg_len; len -= arg_len; | 1017 | ptr += arg_len; len -= arg_len; |
| 1018 | 1018 | ||
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index d8983dd5c4b2..85dc0410ac1a 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
| @@ -2162,7 +2162,7 @@ static struct ioc3_submodule ioc3uart_ops = { | |||
| 2162 | /** | 2162 | /** |
| 2163 | * ioc3_detect - module init called, | 2163 | * ioc3_detect - module init called, |
| 2164 | */ | 2164 | */ |
| 2165 | static int __devinit ioc3uart_init(void) | 2165 | static int __init ioc3uart_init(void) |
| 2166 | { | 2166 | { |
| 2167 | int ret; | 2167 | int ret; |
| 2168 | 2168 | ||
| @@ -2179,7 +2179,7 @@ static int __devinit ioc3uart_init(void) | |||
| 2179 | return ret; | 2179 | return ret; |
| 2180 | } | 2180 | } |
| 2181 | 2181 | ||
| 2182 | static void __devexit ioc3uart_exit(void) | 2182 | static void __exit ioc3uart_exit(void) |
| 2183 | { | 2183 | { |
| 2184 | ioc3_unregister_submodule(&ioc3uart_ops); | 2184 | ioc3_unregister_submodule(&ioc3uart_ops); |
| 2185 | uart_unregister_driver(&ioc3_uart); | 2185 | uart_unregister_driver(&ioc3_uart); |
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 2e02c3026d24..836d9ab4f729 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c | |||
| @@ -2904,7 +2904,7 @@ static struct ioc4_submodule ioc4_serial_submodule = { | |||
| 2904 | /** | 2904 | /** |
| 2905 | * ioc4_serial_init - module init | 2905 | * ioc4_serial_init - module init |
| 2906 | */ | 2906 | */ |
| 2907 | int ioc4_serial_init(void) | 2907 | static int __init ioc4_serial_init(void) |
| 2908 | { | 2908 | { |
| 2909 | int ret; | 2909 | int ret; |
| 2910 | 2910 | ||
| @@ -2913,20 +2913,30 @@ int ioc4_serial_init(void) | |||
| 2913 | printk(KERN_WARNING | 2913 | printk(KERN_WARNING |
| 2914 | "%s: Couldn't register rs232 IOC4 serial driver\n", | 2914 | "%s: Couldn't register rs232 IOC4 serial driver\n", |
| 2915 | __func__); | 2915 | __func__); |
| 2916 | return ret; | 2916 | goto out; |
| 2917 | } | 2917 | } |
| 2918 | if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) { | 2918 | if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) { |
| 2919 | printk(KERN_WARNING | 2919 | printk(KERN_WARNING |
| 2920 | "%s: Couldn't register rs422 IOC4 serial driver\n", | 2920 | "%s: Couldn't register rs422 IOC4 serial driver\n", |
| 2921 | __func__); | 2921 | __func__); |
| 2922 | return ret; | 2922 | goto out_uart_rs232; |
| 2923 | } | 2923 | } |
| 2924 | 2924 | ||
| 2925 | /* register with IOC4 main module */ | 2925 | /* register with IOC4 main module */ |
| 2926 | return ioc4_register_submodule(&ioc4_serial_submodule); | 2926 | ret = ioc4_register_submodule(&ioc4_serial_submodule); |
| 2927 | if (ret) | ||
| 2928 | goto out_uart_rs422; | ||
| 2929 | return 0; | ||
| 2930 | |||
| 2931 | out_uart_rs422: | ||
| 2932 | uart_unregister_driver(&ioc4_uart_rs422); | ||
| 2933 | out_uart_rs232: | ||
| 2934 | uart_unregister_driver(&ioc4_uart_rs232); | ||
| 2935 | out: | ||
| 2936 | return ret; | ||
| 2927 | } | 2937 | } |
| 2928 | 2938 | ||
| 2929 | static void __devexit ioc4_serial_exit(void) | 2939 | static void __exit ioc4_serial_exit(void) |
| 2930 | { | 2940 | { |
| 2931 | ioc4_unregister_submodule(&ioc4_serial_submodule); | 2941 | ioc4_unregister_submodule(&ioc4_serial_submodule); |
| 2932 | uart_unregister_driver(&ioc4_uart_rs232); | 2942 | uart_unregister_driver(&ioc4_uart_rs232); |
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 4a821046baae..56ee082157aa 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
| @@ -756,7 +756,7 @@ static int serial_pxa_resume(struct device *dev) | |||
| 756 | return 0; | 756 | return 0; |
| 757 | } | 757 | } |
| 758 | 758 | ||
| 759 | static struct dev_pm_ops serial_pxa_pm_ops = { | 759 | static const struct dev_pm_ops serial_pxa_pm_ops = { |
| 760 | .suspend = serial_pxa_suspend, | 760 | .suspend = serial_pxa_suspend, |
| 761 | .resume = serial_pxa_resume, | 761 | .resume = serial_pxa_resume, |
| 762 | }; | 762 | }; |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index ff38dbdb5c6e..7e3f4ff58cfd 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -1312,7 +1312,7 @@ static int sci_resume(struct device *dev) | |||
| 1312 | return 0; | 1312 | return 0; |
| 1313 | } | 1313 | } |
| 1314 | 1314 | ||
| 1315 | static struct dev_pm_ops sci_dev_pm_ops = { | 1315 | static const struct dev_pm_ops sci_dev_pm_ops = { |
| 1316 | .suspend = sci_suspend, | 1316 | .suspend = sci_suspend, |
| 1317 | .resume = sci_resume, | 1317 | .resume = sci_resume, |
| 1318 | }; | 1318 | }; |
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c index 816d4c592a3c..66802a4390cc 100644 --- a/drivers/sn/ioc3.c +++ b/drivers/sn/ioc3.c | |||
| @@ -574,11 +574,11 @@ void ioc3_unregister_submodule(struct ioc3_submodule *is) | |||
| 574 | * Device management * | 574 | * Device management * |
| 575 | *********************/ | 575 | *********************/ |
| 576 | 576 | ||
| 577 | static char * | 577 | static char * __devinitdata |
| 578 | ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3", | 578 | ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3", |
| 579 | "MENET 4", "CADduo", "Altix Serial"}; | 579 | "MENET 4", "CADduo", "Altix Serial"}; |
| 580 | 580 | ||
| 581 | static int ioc3_class(struct ioc3_driver_data *idd) | 581 | static int __devinit ioc3_class(struct ioc3_driver_data *idd) |
| 582 | { | 582 | { |
| 583 | int res = IOC3_CLASS_NONE; | 583 | int res = IOC3_CLASS_NONE; |
| 584 | /* NIC-based logic */ | 584 | /* NIC-based logic */ |
| @@ -601,7 +601,8 @@ static int ioc3_class(struct ioc3_driver_data *idd) | |||
| 601 | return res; | 601 | return res; |
| 602 | } | 602 | } |
| 603 | /* Adds a new instance of an IOC3 card */ | 603 | /* Adds a new instance of an IOC3 card */ |
| 604 | static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | 604 | static int __devinit |
| 605 | ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | ||
| 605 | { | 606 | { |
| 606 | struct ioc3_driver_data *idd; | 607 | struct ioc3_driver_data *idd; |
| 607 | uint32_t pcmd; | 608 | uint32_t pcmd; |
| @@ -753,7 +754,7 @@ out: | |||
| 753 | } | 754 | } |
| 754 | 755 | ||
| 755 | /* Removes a particular instance of an IOC3 card. */ | 756 | /* Removes a particular instance of an IOC3 card. */ |
| 756 | static void ioc3_remove(struct pci_dev *pdev) | 757 | static void __devexit ioc3_remove(struct pci_dev *pdev) |
| 757 | { | 758 | { |
| 758 | int id; | 759 | int id; |
| 759 | struct ioc3_driver_data *idd; | 760 | struct ioc3_driver_data *idd; |
| @@ -805,7 +806,7 @@ static struct pci_driver ioc3_driver = { | |||
| 805 | .name = "IOC3", | 806 | .name = "IOC3", |
| 806 | .id_table = ioc3_id_table, | 807 | .id_table = ioc3_id_table, |
| 807 | .probe = ioc3_probe, | 808 | .probe = ioc3_probe, |
| 808 | .remove = ioc3_remove, | 809 | .remove = __devexit_p(ioc3_remove), |
| 809 | }; | 810 | }; |
| 810 | 811 | ||
| 811 | MODULE_DEVICE_TABLE(pci, ioc3_id_table); | 812 | MODULE_DEVICE_TABLE(pci, ioc3_id_table); |
| @@ -815,15 +816,15 @@ MODULE_DEVICE_TABLE(pci, ioc3_id_table); | |||
| 815 | *********************/ | 816 | *********************/ |
| 816 | 817 | ||
| 817 | /* Module load */ | 818 | /* Module load */ |
| 818 | static int __devinit ioc3_init(void) | 819 | static int __init ioc3_init(void) |
| 819 | { | 820 | { |
| 820 | if (ia64_platform_is("sn2")) | 821 | if (ia64_platform_is("sn2")) |
| 821 | return pci_register_driver(&ioc3_driver); | 822 | return pci_register_driver(&ioc3_driver); |
| 822 | return 0; | 823 | return -ENODEV; |
| 823 | } | 824 | } |
| 824 | 825 | ||
| 825 | /* Module unload */ | 826 | /* Module unload */ |
| 826 | static void __devexit ioc3_exit(void) | 827 | static void __exit ioc3_exit(void) |
| 827 | { | 828 | { |
| 828 | pci_unregister_driver(&ioc3_driver); | 829 | pci_unregister_driver(&ioc3_driver); |
| 829 | } | 830 | } |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index c8c2b693ffac..c2f707e5ce74 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
| @@ -1709,7 +1709,7 @@ static int pxa2xx_spi_resume(struct device *dev) | |||
| 1709 | return 0; | 1709 | return 0; |
| 1710 | } | 1710 | } |
| 1711 | 1711 | ||
| 1712 | static struct dev_pm_ops pxa2xx_spi_pm_ops = { | 1712 | static const struct dev_pm_ops pxa2xx_spi_pm_ops = { |
| 1713 | .suspend = pxa2xx_spi_suspend, | 1713 | .suspend = pxa2xx_spi_suspend, |
| 1714 | .resume = pxa2xx_spi_resume, | 1714 | .resume = pxa2xx_spi_resume, |
| 1715 | }; | 1715 | }; |
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 33d94f76b9ef..276591569c8b 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
| @@ -489,7 +489,7 @@ static int s3c24xx_spi_resume(struct device *dev) | |||
| 489 | return 0; | 489 | return 0; |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | static struct dev_pm_ops s3c24xx_spi_pmops = { | 492 | static const struct dev_pm_ops s3c24xx_spi_pmops = { |
| 493 | .suspend = s3c24xx_spi_suspend, | 493 | .suspend = s3c24xx_spi_suspend, |
| 494 | .resume = s3c24xx_spi_resume, | 494 | .resume = s3c24xx_spi_resume, |
| 495 | }; | 495 | }; |
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index aa53db9f2e88..1ef3b8fc50b3 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c | |||
| @@ -210,7 +210,7 @@ static int uio_pdrv_genirq_runtime_nop(struct device *dev) | |||
| 210 | return 0; | 210 | return 0; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | static struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = { | 213 | static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = { |
| 214 | .runtime_suspend = uio_pdrv_genirq_runtime_nop, | 214 | .runtime_suspend = uio_pdrv_genirq_runtime_nop, |
| 215 | .runtime_resume = uio_pdrv_genirq_runtime_nop, | 215 | .runtime_resume = uio_pdrv_genirq_runtime_nop, |
| 216 | }; | 216 | }; |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 91f2885b6ee1..2dcf906df569 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
| @@ -363,7 +363,7 @@ static int hcd_pci_restore(struct device *dev) | |||
| 363 | return resume_common(dev, true); | 363 | return resume_common(dev, true); |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | struct dev_pm_ops usb_hcd_pci_pm_ops = { | 366 | const struct dev_pm_ops usb_hcd_pci_pm_ops = { |
| 367 | .suspend = hcd_pci_suspend, | 367 | .suspend = hcd_pci_suspend, |
| 368 | .suspend_noirq = hcd_pci_suspend_noirq, | 368 | .suspend_noirq = hcd_pci_suspend_noirq, |
| 369 | .resume_noirq = hcd_pci_resume_noirq, | 369 | .resume_noirq = hcd_pci_resume_noirq, |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index d8b43aee581e..bbe2b924aae8 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
| @@ -330,7 +330,7 @@ extern void usb_hcd_pci_remove(struct pci_dev *dev); | |||
| 330 | extern void usb_hcd_pci_shutdown(struct pci_dev *dev); | 330 | extern void usb_hcd_pci_shutdown(struct pci_dev *dev); |
| 331 | 331 | ||
| 332 | #ifdef CONFIG_PM_SLEEP | 332 | #ifdef CONFIG_PM_SLEEP |
| 333 | extern struct dev_pm_ops usb_hcd_pci_pm_ops; | 333 | extern const struct dev_pm_ops usb_hcd_pci_pm_ops; |
| 334 | #endif | 334 | #endif |
| 335 | #endif /* CONFIG_PCI */ | 335 | #endif /* CONFIG_PCI */ |
| 336 | 336 | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index d86276c639c1..2fb42043b305 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
| @@ -329,7 +329,7 @@ static int usb_dev_restore(struct device *dev) | |||
| 329 | return usb_resume(dev, PMSG_RESTORE); | 329 | return usb_resume(dev, PMSG_RESTORE); |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | static struct dev_pm_ops usb_device_pm_ops = { | 332 | static const struct dev_pm_ops usb_device_pm_ops = { |
| 333 | .prepare = usb_dev_prepare, | 333 | .prepare = usb_dev_prepare, |
| 334 | .complete = usb_dev_complete, | 334 | .complete = usb_dev_complete, |
| 335 | .suspend = usb_dev_suspend, | 335 | .suspend = usb_dev_suspend, |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index ed77be76d6bb..dbfb482a94e3 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
| @@ -297,7 +297,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev) | |||
| 297 | return 0; | 297 | return 0; |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | static struct dev_pm_ops au1xxx_ehci_pmops = { | 300 | static const struct dev_pm_ops au1xxx_ehci_pmops = { |
| 301 | .suspend = ehci_hcd_au1xxx_drv_suspend, | 301 | .suspend = ehci_hcd_au1xxx_drv_suspend, |
| 302 | .resume = ehci_hcd_au1xxx_drv_resume, | 302 | .resume = ehci_hcd_au1xxx_drv_resume, |
| 303 | }; | 303 | }; |
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index e4380082ebb1..17a6043c1fa0 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
| @@ -294,7 +294,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct device *dev) | |||
| 294 | return 0; | 294 | return 0; |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | static struct dev_pm_ops au1xxx_ohci_pmops = { | 297 | static const struct dev_pm_ops au1xxx_ohci_pmops = { |
| 298 | .suspend = ohci_hcd_au1xxx_drv_suspend, | 298 | .suspend = ohci_hcd_au1xxx_drv_suspend, |
| 299 | .resume = ohci_hcd_au1xxx_drv_resume, | 299 | .resume = ohci_hcd_au1xxx_drv_resume, |
| 300 | }; | 300 | }; |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index f1c06202fdf2..a18debdd79b8 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
| @@ -518,7 +518,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev) | |||
| 518 | return 0; | 518 | return 0; |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | static struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = { | 521 | static const struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = { |
| 522 | .suspend = ohci_hcd_pxa27x_drv_suspend, | 522 | .suspend = ohci_hcd_pxa27x_drv_suspend, |
| 523 | .resume = ohci_hcd_pxa27x_drv_resume, | 523 | .resume = ohci_hcd_pxa27x_drv_resume, |
| 524 | }; | 524 | }; |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 41dbc70ae752..b7a661c02bcd 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
| @@ -2353,7 +2353,7 @@ static int r8a66597_resume(struct device *dev) | |||
| 2353 | return 0; | 2353 | return 0; |
| 2354 | } | 2354 | } |
| 2355 | 2355 | ||
| 2356 | static struct dev_pm_ops r8a66597_dev_pm_ops = { | 2356 | static const struct dev_pm_ops r8a66597_dev_pm_ops = { |
| 2357 | .suspend = r8a66597_suspend, | 2357 | .suspend = r8a66597_suspend, |
| 2358 | .resume = r8a66597_resume, | 2358 | .resume = r8a66597_resume, |
| 2359 | .poweroff = r8a66597_suspend, | 2359 | .poweroff = r8a66597_suspend, |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 49f2346afad3..bfe08f4975a3 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
| @@ -2214,7 +2214,7 @@ static int musb_resume_noirq(struct device *dev) | |||
| 2214 | return 0; | 2214 | return 0; |
| 2215 | } | 2215 | } |
| 2216 | 2216 | ||
| 2217 | static struct dev_pm_ops musb_dev_pm_ops = { | 2217 | static const struct dev_pm_ops musb_dev_pm_ops = { |
| 2218 | .suspend = musb_suspend, | 2218 | .suspend = musb_suspend, |
| 2219 | .resume_noirq = musb_resume_noirq, | 2219 | .resume_noirq = musb_resume_noirq, |
| 2220 | }; | 2220 | }; |
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 7fcb0eb54c60..f2d76dae1eb3 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c | |||
| @@ -177,7 +177,7 @@ static int da903x_backlight_resume(struct device *dev) | |||
| 177 | return 0; | 177 | return 0; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | static struct dev_pm_ops da903x_backlight_pm_ops = { | 180 | static const struct dev_pm_ops da903x_backlight_pm_ops = { |
| 181 | .suspend = da903x_backlight_suspend, | 181 | .suspend = da903x_backlight_suspend, |
| 182 | .resume = da903x_backlight_resume, | 182 | .resume = da903x_backlight_resume, |
| 183 | }; | 183 | }; |
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index a482dd7b0311..9b3be74cee5a 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
| @@ -101,7 +101,7 @@ static ssize_t lcd_store_power(struct device *dev, | |||
| 101 | int power = simple_strtoul(buf, &endp, 0); | 101 | int power = simple_strtoul(buf, &endp, 0); |
| 102 | size_t size = endp - buf; | 102 | size_t size = endp - buf; |
| 103 | 103 | ||
| 104 | if (*endp && isspace(*endp)) | 104 | if (isspace(*endp)) |
| 105 | size++; | 105 | size++; |
| 106 | if (size != count) | 106 | if (size != count) |
| 107 | return -EINVAL; | 107 | return -EINVAL; |
| @@ -140,7 +140,7 @@ static ssize_t lcd_store_contrast(struct device *dev, | |||
| 140 | int contrast = simple_strtoul(buf, &endp, 0); | 140 | int contrast = simple_strtoul(buf, &endp, 0); |
| 141 | size_t size = endp - buf; | 141 | size_t size = endp - buf; |
| 142 | 142 | ||
| 143 | if (*endp && isspace(*endp)) | 143 | if (isspace(*endp)) |
| 144 | size++; | 144 | size++; |
| 145 | if (size != count) | 145 | if (size != count) |
| 146 | return -EINVAL; | 146 | return -EINVAL; |
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c index 4830b1bf51e5..80abbf323b99 100644 --- a/drivers/video/display/display-sysfs.c +++ b/drivers/video/display/display-sysfs.c | |||
| @@ -67,7 +67,7 @@ static ssize_t display_store_contrast(struct device *dev, | |||
| 67 | contrast = simple_strtoul(buf, &endp, 0); | 67 | contrast = simple_strtoul(buf, &endp, 0); |
| 68 | size = endp - buf; | 68 | size = endp - buf; |
| 69 | 69 | ||
| 70 | if (*endp && isspace(*endp)) | 70 | if (isspace(*endp)) |
| 71 | size++; | 71 | size++; |
| 72 | 72 | ||
| 73 | if (size != count) | 73 | if (size != count) |
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c index e759895bf3d3..f0af911a096d 100644 --- a/drivers/video/geode/display_gx.c +++ b/drivers/video/geode/display_gx.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
| 18 | #include <asm/div64.h> | 18 | #include <asm/div64.h> |
| 19 | #include <asm/delay.h> | 19 | #include <asm/delay.h> |
| 20 | #include <asm/geode.h> | 20 | #include <linux/cs5535.h> |
| 21 | 21 | ||
| 22 | #include "gxfb.h" | 22 | #include "gxfb.h" |
| 23 | 23 | ||
| @@ -25,7 +25,7 @@ unsigned int gx_frame_buffer_size(void) | |||
| 25 | { | 25 | { |
| 26 | unsigned int val; | 26 | unsigned int val; |
| 27 | 27 | ||
| 28 | if (!geode_has_vsa2()) { | 28 | if (!cs5535_has_vsa2()) { |
| 29 | uint32_t hi, lo; | 29 | uint32_t hi, lo; |
| 30 | 30 | ||
| 31 | /* The number of pages is (PMAX - PMIN)+1 */ | 31 | /* The number of pages is (PMAX - PMIN)+1 */ |
diff --git a/drivers/video/geode/gxfb.h b/drivers/video/geode/gxfb.h index 16a96f8fd8c5..d19e9378b0c0 100644 --- a/drivers/video/geode/gxfb.h +++ b/drivers/video/geode/gxfb.h | |||
| @@ -340,7 +340,7 @@ static inline void write_fp(struct gxfb_par *par, int reg, uint32_t val) | |||
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | 342 | ||
| 343 | /* MSRs are defined in asm/geode.h; their bitfields are here */ | 343 | /* MSRs are defined in linux/cs5535.h; their bitfields are here */ |
| 344 | 344 | ||
| 345 | #define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (1 << 3) | 345 | #define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (1 << 3) |
| 346 | #define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (1 << 2) | 346 | #define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (1 << 2) |
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 2552cac39e1c..b3e639d1e12c 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #include <linux/suspend.h> | 32 | #include <linux/suspend.h> |
| 33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| 34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 35 | #include <asm/geode.h> | 35 | #include <linux/cs5535.h> |
| 36 | 36 | ||
| 37 | #include "gxfb.h" | 37 | #include "gxfb.h" |
| 38 | 38 | ||
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h index 6a51448fd3f7..fc68a8b0a144 100644 --- a/drivers/video/geode/lxfb.h +++ b/drivers/video/geode/lxfb.h | |||
| @@ -409,7 +409,7 @@ static inline void write_fp(struct lxfb_par *par, int reg, uint32_t val) | |||
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | 411 | ||
| 412 | /* MSRs are defined in asm/geode.h; their bitfields are here */ | 412 | /* MSRs are defined in linux/cs5535.h; their bitfields are here */ |
| 413 | 413 | ||
| 414 | #define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */ | 414 | #define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */ |
| 415 | #define MSR_GLCP_DOTPLL_HALFPIX (1 << 24) | 415 | #define MSR_GLCP_DOTPLL_HALFPIX (1 << 24) |
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c index b1cd49c99356..0e5d8c7c3eba 100644 --- a/drivers/video/geode/lxfb_ops.c +++ b/drivers/video/geode/lxfb_ops.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include <linux/fb.h> | 13 | #include <linux/fb.h> |
| 14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
| 15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <asm/geode.h> | 16 | #include <linux/cs5535.h> |
| 17 | 17 | ||
| 18 | #include "lxfb.h" | 18 | #include "lxfb.h" |
| 19 | 19 | ||
| @@ -307,7 +307,7 @@ unsigned int lx_framebuffer_size(void) | |||
| 307 | { | 307 | { |
| 308 | unsigned int val; | 308 | unsigned int val; |
| 309 | 309 | ||
| 310 | if (!geode_has_vsa2()) { | 310 | if (!cs5535_has_vsa2()) { |
| 311 | uint32_t hi, lo; | 311 | uint32_t hi, lo; |
| 312 | 312 | ||
| 313 | /* The number of pages is (PMAX - PMIN)+1 */ | 313 | /* The number of pages is (PMAX - PMIN)+1 */ |
diff --git a/drivers/video/geode/suspend_gx.c b/drivers/video/geode/suspend_gx.c index 9aff32ef8bb6..1bb043d70c64 100644 --- a/drivers/video/geode/suspend_gx.c +++ b/drivers/video/geode/suspend_gx.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include <linux/fb.h> | 10 | #include <linux/fb.h> |
| 11 | #include <asm/io.h> | 11 | #include <asm/io.h> |
| 12 | #include <asm/msr.h> | 12 | #include <asm/msr.h> |
| 13 | #include <asm/geode.h> | 13 | #include <linux/cs5535.h> |
| 14 | #include <asm/delay.h> | 14 | #include <asm/delay.h> |
| 15 | 15 | ||
| 16 | #include "gxfb.h" | 16 | #include "gxfb.h" |
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c index b8d52a8360db..6082f653c68a 100644 --- a/drivers/video/geode/video_gx.c +++ b/drivers/video/geode/video_gx.c | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
| 17 | #include <asm/delay.h> | 17 | #include <asm/delay.h> |
| 18 | #include <asm/msr.h> | 18 | #include <asm/msr.h> |
| 19 | #include <asm/geode.h> | 19 | #include <linux/cs5535.h> |
| 20 | 20 | ||
| 21 | #include "gxfb.h" | 21 | #include "gxfb.h" |
| 22 | 22 | ||
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index e7116a6d82d3..73c83a8de2d3 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c | |||
| @@ -456,7 +456,7 @@ static int hitfb_resume(struct device *dev) | |||
| 456 | return 0; | 456 | return 0; |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static struct dev_pm_ops hitfb_dev_pm_ops = { | 459 | static const struct dev_pm_ops hitfb_dev_pm_ops = { |
| 460 | .suspend = hitfb_suspend, | 460 | .suspend = hitfb_suspend, |
| 461 | .resume = hitfb_resume, | 461 | .resume = hitfb_resume, |
| 462 | }; | 462 | }; |
diff --git a/drivers/video/output.c b/drivers/video/output.c index 5e6439ae7394..5137aa016b83 100644 --- a/drivers/video/output.c +++ b/drivers/video/output.c | |||
| @@ -50,7 +50,7 @@ static ssize_t video_output_store_state(struct device *dev, | |||
| 50 | int request_state = simple_strtoul(buf,&endp,0); | 50 | int request_state = simple_strtoul(buf,&endp,0); |
| 51 | size_t size = endp - buf; | 51 | size_t size = endp - buf; |
| 52 | 52 | ||
| 53 | if (*endp && isspace(*endp)) | 53 | if (isspace(*endp)) |
| 54 | size++; | 54 | size++; |
| 55 | if (size != count) | 55 | if (size != count) |
| 56 | return -EINVAL; | 56 | return -EINVAL; |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index f58a3aae6ea6..b7e58059b592 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -1667,7 +1667,7 @@ static int pxafb_resume(struct device *dev) | |||
| 1667 | return 0; | 1667 | return 0; |
| 1668 | } | 1668 | } |
| 1669 | 1669 | ||
| 1670 | static struct dev_pm_ops pxafb_pm_ops = { | 1670 | static const struct dev_pm_ops pxafb_pm_ops = { |
| 1671 | .suspend = pxafb_suspend, | 1671 | .suspend = pxafb_suspend, |
| 1672 | .resume = pxafb_resume, | 1672 | .resume = pxafb_resume, |
| 1673 | }; | 1673 | }; |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index b4b5de930cf5..8a65fb6648a6 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
| @@ -890,7 +890,7 @@ static int sh_mobile_lcdc_runtime_resume(struct device *dev) | |||
| 890 | return 0; | 890 | return 0; |
| 891 | } | 891 | } |
| 892 | 892 | ||
| 893 | static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { | 893 | static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { |
| 894 | .suspend = sh_mobile_lcdc_suspend, | 894 | .suspend = sh_mobile_lcdc_suspend, |
| 895 | .resume = sh_mobile_lcdc_resume, | 895 | .resume = sh_mobile_lcdc_resume, |
| 896 | .runtime_suspend = sh_mobile_lcdc_runtime_suspend, | 896 | .runtime_suspend = sh_mobile_lcdc_runtime_suspend, |
diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c index 77afb0acc500..9c6594473d3b 100644 --- a/drivers/watchdog/adx_wdt.c +++ b/drivers/watchdog/adx_wdt.c | |||
| @@ -314,7 +314,7 @@ static int adx_wdt_resume(struct device *dev) | |||
| 314 | return 0; | 314 | return 0; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | static struct dev_pm_ops adx_wdt_pm_ops = { | 317 | static const struct dev_pm_ops adx_wdt_pm_ops = { |
| 318 | .suspend = adx_wdt_suspend, | 318 | .suspend = adx_wdt_suspend, |
| 319 | .resume = adx_wdt_resume, | 319 | .resume = adx_wdt_resume, |
| 320 | }; | 320 | }; |
diff --git a/fs/Kconfig b/fs/Kconfig index 64d44efad7a5..f8fccaaad628 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -6,6 +6,10 @@ menu "File systems" | |||
| 6 | 6 | ||
| 7 | if BLOCK | 7 | if BLOCK |
| 8 | 8 | ||
| 9 | config FS_JOURNAL_INFO | ||
| 10 | bool | ||
| 11 | default n | ||
| 12 | |||
| 9 | source "fs/ext2/Kconfig" | 13 | source "fs/ext2/Kconfig" |
| 10 | source "fs/ext3/Kconfig" | 14 | source "fs/ext3/Kconfig" |
| 11 | source "fs/ext4/Kconfig" | 15 | source "fs/ext4/Kconfig" |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 38502c67987c..79d2b1aa389f 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
| @@ -380,7 +380,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
| 380 | down_write(¤t->mm->mmap_sem); | 380 | down_write(¤t->mm->mmap_sem); |
| 381 | current->mm->start_brk = do_mmap(NULL, 0, stack_size, | 381 | current->mm->start_brk = do_mmap(NULL, 0, stack_size, |
| 382 | PROT_READ | PROT_WRITE | PROT_EXEC, | 382 | PROT_READ | PROT_WRITE | PROT_EXEC, |
| 383 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, | 383 | MAP_PRIVATE | MAP_ANONYMOUS | |
| 384 | MAP_UNINITIALIZED | MAP_GROWSDOWN, | ||
| 384 | 0); | 385 | 0); |
| 385 | 386 | ||
| 386 | if (IS_ERR_VALUE(current->mm->start_brk)) { | 387 | if (IS_ERR_VALUE(current->mm->start_brk)) { |
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig index 7bb3c020e570..402afe0a0bfb 100644 --- a/fs/btrfs/Kconfig +++ b/fs/btrfs/Kconfig | |||
| @@ -4,6 +4,7 @@ config BTRFS_FS | |||
| 4 | select LIBCRC32C | 4 | select LIBCRC32C |
| 5 | select ZLIB_INFLATE | 5 | select ZLIB_INFLATE |
| 6 | select ZLIB_DEFLATE | 6 | select ZLIB_DEFLATE |
| 7 | select FS_JOURNAL_INFO | ||
| 7 | help | 8 | help |
| 8 | Btrfs is a new filesystem with extents, writable snapshotting, | 9 | Btrfs is a new filesystem with extents, writable snapshotting, |
| 9 | support for multiple devices and many more features. | 10 | support for multiple devices and many more features. |
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index 4618516dd994..c2413561ea75 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
| 22 | #include <linux/statfs.h> | 22 | #include <linux/statfs.h> |
| 23 | #include <linux/ctype.h> | 23 | #include <linux/ctype.h> |
| 24 | #include <linux/string.h> | ||
| 24 | #include <linux/fs_struct.h> | 25 | #include <linux/fs_struct.h> |
| 25 | #include "internal.h" | 26 | #include "internal.h" |
| 26 | 27 | ||
| @@ -257,8 +258,7 @@ static ssize_t cachefiles_daemon_write(struct file *file, | |||
| 257 | if (args == data) | 258 | if (args == data) |
| 258 | goto error; | 259 | goto error; |
| 259 | *args = '\0'; | 260 | *args = '\0'; |
| 260 | for (args++; isspace(*args); args++) | 261 | args = skip_spaces(++args); |
| 261 | continue; | ||
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | /* run the appropriate command handler */ | 264 | /* run the appropriate command handler */ |
| @@ -923,6 +923,15 @@ char *get_task_comm(char *buf, struct task_struct *tsk) | |||
| 923 | void set_task_comm(struct task_struct *tsk, char *buf) | 923 | void set_task_comm(struct task_struct *tsk, char *buf) |
| 924 | { | 924 | { |
| 925 | task_lock(tsk); | 925 | task_lock(tsk); |
| 926 | |||
| 927 | /* | ||
| 928 | * Threads may access current->comm without holding | ||
| 929 | * the task lock, so write the string carefully. | ||
| 930 | * Readers without a lock may see incomplete new | ||
| 931 | * names but are safe from non-terminating string reads. | ||
| 932 | */ | ||
| 933 | memset(tsk->comm, 0, TASK_COMM_LEN); | ||
| 934 | wmb(); | ||
| 926 | strlcpy(tsk->comm, buf, sizeof(tsk->comm)); | 935 | strlcpy(tsk->comm, buf, sizeof(tsk->comm)); |
| 927 | task_unlock(tsk); | 936 | task_unlock(tsk); |
| 928 | perf_event_comm(tsk); | 937 | perf_event_comm(tsk); |
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 9acf7e808139..e5f6774846e4 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig | |||
| @@ -2,6 +2,7 @@ config EXT4_FS | |||
| 2 | tristate "The Extended 4 (ext4) filesystem" | 2 | tristate "The Extended 4 (ext4) filesystem" |
| 3 | select JBD2 | 3 | select JBD2 |
| 4 | select CRC16 | 4 | select CRC16 |
| 5 | select FS_JOURNAL_INFO | ||
| 5 | help | 6 | help |
| 6 | This is the next generation of the ext3 filesystem. | 7 | This is the next generation of the ext3 filesystem. |
| 7 | 8 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 768c111a77ec..827bde1f2594 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -2137,11 +2137,8 @@ static int parse_strtoul(const char *buf, | |||
| 2137 | { | 2137 | { |
| 2138 | char *endp; | 2138 | char *endp; |
| 2139 | 2139 | ||
| 2140 | while (*buf && isspace(*buf)) | 2140 | *value = simple_strtoul(skip_spaces(buf), &endp, 0); |
| 2141 | buf++; | 2141 | endp = skip_spaces(endp); |
| 2142 | *value = simple_strtoul(buf, &endp, 0); | ||
| 2143 | while (*endp && isspace(*endp)) | ||
| 2144 | endp++; | ||
| 2145 | if (*endp || *value > max) | 2142 | if (*endp || *value > max) |
| 2146 | return -EINVAL; | 2143 | return -EINVAL; |
| 2147 | 2144 | ||
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index 4dcddf83326f..b192c661caa6 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig | |||
| @@ -10,6 +10,7 @@ config GFS2_FS | |||
| 10 | select SLOW_WORK | 10 | select SLOW_WORK |
| 11 | select QUOTA | 11 | select QUOTA |
| 12 | select QUOTACTL | 12 | select QUOTACTL |
| 13 | select FS_JOURNAL_INFO | ||
| 13 | help | 14 | help |
| 14 | A cluster filesystem. | 15 | A cluster filesystem. |
| 15 | 16 | ||
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index c5dad1eb7b91..0dc34621f6a6 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
| @@ -85,11 +85,7 @@ static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf) | |||
| 85 | buf[0] = '\0'; | 85 | buf[0] = '\0'; |
| 86 | if (!gfs2_uuid_valid(uuid)) | 86 | if (!gfs2_uuid_valid(uuid)) |
| 87 | return 0; | 87 | return 0; |
| 88 | return snprintf(buf, PAGE_SIZE, "%02X%02X%02X%02X-%02X%02X-" | 88 | return snprintf(buf, PAGE_SIZE, "%pUB\n", uuid); |
| 89 | "%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", | ||
| 90 | uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], | ||
| 91 | uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11], | ||
| 92 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
| 93 | } | 89 | } |
| 94 | 90 | ||
| 95 | static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf) | 91 | static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf) |
| @@ -575,14 +571,8 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, | |||
| 575 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); | 571 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); |
| 576 | if (!sdp->sd_args.ar_spectator) | 572 | if (!sdp->sd_args.ar_spectator) |
| 577 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); | 573 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); |
| 578 | if (gfs2_uuid_valid(uuid)) { | 574 | if (gfs2_uuid_valid(uuid)) |
| 579 | add_uevent_var(env, "UUID=%02X%02X%02X%02X-%02X%02X-%02X%02X-" | 575 | add_uevent_var(env, "UUID=%pUB", uuid); |
| 580 | "%02X%02X-%02X%02X%02X%02X%02X%02X", | ||
| 581 | uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], | ||
| 582 | uuid[5], uuid[6], uuid[7], uuid[8], uuid[9], | ||
| 583 | uuid[10], uuid[11], uuid[12], uuid[13], | ||
| 584 | uuid[14], uuid[15]); | ||
| 585 | } | ||
| 586 | return 0; | 576 | return 0; |
| 587 | } | 577 | } |
| 588 | 578 | ||
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c index 6d98f116ca03..424b0337f524 100644 --- a/fs/hfs/catalog.c +++ b/fs/hfs/catalog.c | |||
| @@ -289,6 +289,10 @@ int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name, | |||
| 289 | err = hfs_brec_find(&src_fd); | 289 | err = hfs_brec_find(&src_fd); |
| 290 | if (err) | 290 | if (err) |
| 291 | goto out; | 291 | goto out; |
| 292 | if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) { | ||
| 293 | err = -EIO; | ||
| 294 | goto out; | ||
| 295 | } | ||
| 292 | 296 | ||
| 293 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, | 297 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, |
| 294 | src_fd.entrylength); | 298 | src_fd.entrylength); |
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 7c69b98a2e45..2b3b8611b41b 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
| @@ -79,6 +79,11 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 79 | filp->f_pos++; | 79 | filp->f_pos++; |
| 80 | /* fall through */ | 80 | /* fall through */ |
| 81 | case 1: | 81 | case 1: |
| 82 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | ||
| 83 | err = -EIO; | ||
| 84 | goto out; | ||
| 85 | } | ||
| 86 | |||
| 82 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); | 87 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
| 83 | if (entry.type != HFS_CDR_THD) { | 88 | if (entry.type != HFS_CDR_THD) { |
| 84 | printk(KERN_ERR "hfs: bad catalog folder thread\n"); | 89 | printk(KERN_ERR "hfs: bad catalog folder thread\n"); |
| @@ -109,6 +114,12 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 109 | err = -EIO; | 114 | err = -EIO; |
| 110 | goto out; | 115 | goto out; |
| 111 | } | 116 | } |
| 117 | |||
| 118 | if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | ||
| 119 | err = -EIO; | ||
| 120 | goto out; | ||
| 121 | } | ||
| 122 | |||
| 112 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); | 123 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
| 113 | type = entry.type; | 124 | type = entry.type; |
| 114 | len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName); | 125 | len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName); |
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index f7fcbe49da72..5ed7252b7b23 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
| @@ -409,8 +409,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 409 | /* try to get the root inode */ | 409 | /* try to get the root inode */ |
| 410 | hfs_find_init(HFS_SB(sb)->cat_tree, &fd); | 410 | hfs_find_init(HFS_SB(sb)->cat_tree, &fd); |
| 411 | res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd); | 411 | res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd); |
| 412 | if (!res) | 412 | if (!res) { |
| 413 | if (fd.entrylength > sizeof(rec) || fd.entrylength < 0) { | ||
| 414 | res = -EIO; | ||
| 415 | goto bail; | ||
| 416 | } | ||
| 413 | hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength); | 417 | hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength); |
| 418 | } | ||
| 414 | if (res) { | 419 | if (res) { |
| 415 | hfs_find_exit(&fd); | 420 | hfs_find_exit(&fd); |
| 416 | goto bail_no_root; | 421 | goto bail_no_root; |
diff --git a/fs/jbd/Kconfig b/fs/jbd/Kconfig index 4e28beeed157..a8408983abd4 100644 --- a/fs/jbd/Kconfig +++ b/fs/jbd/Kconfig | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | config JBD | 1 | config JBD |
| 2 | tristate | 2 | tristate |
| 3 | select FS_JOURNAL_INFO | ||
| 3 | help | 4 | help |
| 4 | This is a generic journalling layer for block devices. It is | 5 | This is a generic journalling layer for block devices. It is |
| 5 | currently used by the ext3 file system, but it could also be | 6 | currently used by the ext3 file system, but it could also be |
diff --git a/fs/jbd2/Kconfig b/fs/jbd2/Kconfig index f32f346f4b0a..0f7d1ceafdfd 100644 --- a/fs/jbd2/Kconfig +++ b/fs/jbd2/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | config JBD2 | 1 | config JBD2 |
| 2 | tristate | 2 | tristate |
| 3 | select CRC32 | 3 | select CRC32 |
| 4 | select FS_JOURNAL_INFO | ||
| 4 | help | 5 | help |
| 5 | This is a generic journaling layer for block devices that support | 6 | This is a generic journaling layer for block devices that support |
| 6 | both 32-bit and 64-bit block numbers. It is currently used by | 7 | both 32-bit and 64-bit block numbers. It is currently used by |
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig index 251da07b2a1d..1225af7b2166 100644 --- a/fs/nilfs2/Kconfig +++ b/fs/nilfs2/Kconfig | |||
| @@ -2,6 +2,7 @@ config NILFS2_FS | |||
| 2 | tristate "NILFS2 file system support (EXPERIMENTAL)" | 2 | tristate "NILFS2 file system support (EXPERIMENTAL)" |
| 3 | depends on EXPERIMENTAL | 3 | depends on EXPERIMENTAL |
| 4 | select CRC32 | 4 | select CRC32 |
| 5 | select FS_JOURNAL_INFO | ||
| 5 | help | 6 | help |
| 6 | NILFS2 is a log-structured file system (LFS) supporting continuous | 7 | NILFS2 is a log-structured file system (LFS) supporting continuous |
| 7 | snapshotting. In addition to versioning capability of the entire | 8 | snapshotting. In addition to versioning capability of the entire |
diff --git a/fs/proc/base.c b/fs/proc/base.c index af643b5aefe8..4df4a464a919 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -1265,6 +1265,72 @@ static const struct file_operations proc_pid_sched_operations = { | |||
| 1265 | 1265 | ||
| 1266 | #endif | 1266 | #endif |
| 1267 | 1267 | ||
| 1268 | static ssize_t comm_write(struct file *file, const char __user *buf, | ||
| 1269 | size_t count, loff_t *offset) | ||
| 1270 | { | ||
| 1271 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 1272 | struct task_struct *p; | ||
| 1273 | char buffer[TASK_COMM_LEN]; | ||
| 1274 | |||
| 1275 | memset(buffer, 0, sizeof(buffer)); | ||
| 1276 | if (count > sizeof(buffer) - 1) | ||
| 1277 | count = sizeof(buffer) - 1; | ||
| 1278 | if (copy_from_user(buffer, buf, count)) | ||
| 1279 | return -EFAULT; | ||
| 1280 | |||
| 1281 | p = get_proc_task(inode); | ||
| 1282 | if (!p) | ||
| 1283 | return -ESRCH; | ||
| 1284 | |||
| 1285 | if (same_thread_group(current, p)) | ||
| 1286 | set_task_comm(p, buffer); | ||
| 1287 | else | ||
| 1288 | count = -EINVAL; | ||
| 1289 | |||
| 1290 | put_task_struct(p); | ||
| 1291 | |||
| 1292 | return count; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | static int comm_show(struct seq_file *m, void *v) | ||
| 1296 | { | ||
| 1297 | struct inode *inode = m->private; | ||
| 1298 | struct task_struct *p; | ||
| 1299 | |||
| 1300 | p = get_proc_task(inode); | ||
| 1301 | if (!p) | ||
| 1302 | return -ESRCH; | ||
| 1303 | |||
| 1304 | task_lock(p); | ||
| 1305 | seq_printf(m, "%s\n", p->comm); | ||
| 1306 | task_unlock(p); | ||
| 1307 | |||
| 1308 | put_task_struct(p); | ||
| 1309 | |||
| 1310 | return 0; | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | static int comm_open(struct inode *inode, struct file *filp) | ||
| 1314 | { | ||
| 1315 | int ret; | ||
| 1316 | |||
| 1317 | ret = single_open(filp, comm_show, NULL); | ||
| 1318 | if (!ret) { | ||
| 1319 | struct seq_file *m = filp->private_data; | ||
| 1320 | |||
| 1321 | m->private = inode; | ||
| 1322 | } | ||
| 1323 | return ret; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | static const struct file_operations proc_pid_set_comm_operations = { | ||
| 1327 | .open = comm_open, | ||
| 1328 | .read = seq_read, | ||
| 1329 | .write = comm_write, | ||
| 1330 | .llseek = seq_lseek, | ||
| 1331 | .release = single_release, | ||
| 1332 | }; | ||
| 1333 | |||
| 1268 | /* | 1334 | /* |
| 1269 | * We added or removed a vma mapping the executable. The vmas are only mapped | 1335 | * We added or removed a vma mapping the executable. The vmas are only mapped |
| 1270 | * during exec and are not mapped with the mmap system call. | 1336 | * during exec and are not mapped with the mmap system call. |
| @@ -2504,6 +2570,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2504 | #ifdef CONFIG_SCHED_DEBUG | 2570 | #ifdef CONFIG_SCHED_DEBUG |
| 2505 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 2571 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
| 2506 | #endif | 2572 | #endif |
| 2573 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), | ||
| 2507 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2574 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
| 2508 | INF("syscall", S_IRUSR, proc_pid_syscall), | 2575 | INF("syscall", S_IRUSR, proc_pid_syscall), |
| 2509 | #endif | 2576 | #endif |
| @@ -2838,6 +2905,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2838 | #ifdef CONFIG_SCHED_DEBUG | 2905 | #ifdef CONFIG_SCHED_DEBUG |
| 2839 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 2906 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
| 2840 | #endif | 2907 | #endif |
| 2908 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), | ||
| 2841 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2909 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
| 2842 | INF("syscall", S_IRUSR, proc_pid_syscall), | 2910 | INF("syscall", S_IRUSR, proc_pid_syscall), |
| 2843 | #endif | 2911 | #endif |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 2a1bef9203c6..47c03f4336b8 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -650,6 +650,50 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
| 650 | return err; | 650 | return err; |
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | static u64 huge_pte_to_pagemap_entry(pte_t pte, int offset) | ||
| 654 | { | ||
| 655 | u64 pme = 0; | ||
| 656 | if (pte_present(pte)) | ||
| 657 | pme = PM_PFRAME(pte_pfn(pte) + offset) | ||
| 658 | | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT; | ||
| 659 | return pme; | ||
| 660 | } | ||
| 661 | |||
| 662 | static int pagemap_hugetlb_range(pte_t *pte, unsigned long addr, | ||
| 663 | unsigned long end, struct mm_walk *walk) | ||
| 664 | { | ||
| 665 | struct vm_area_struct *vma; | ||
| 666 | struct pagemapread *pm = walk->private; | ||
| 667 | struct hstate *hs = NULL; | ||
| 668 | int err = 0; | ||
| 669 | |||
| 670 | vma = find_vma(walk->mm, addr); | ||
| 671 | if (vma) | ||
| 672 | hs = hstate_vma(vma); | ||
| 673 | for (; addr != end; addr += PAGE_SIZE) { | ||
| 674 | u64 pfn = PM_NOT_PRESENT; | ||
| 675 | |||
| 676 | if (vma && (addr >= vma->vm_end)) { | ||
| 677 | vma = find_vma(walk->mm, addr); | ||
| 678 | if (vma) | ||
| 679 | hs = hstate_vma(vma); | ||
| 680 | } | ||
| 681 | |||
| 682 | if (vma && (vma->vm_start <= addr) && is_vm_hugetlb_page(vma)) { | ||
| 683 | /* calculate pfn of the "raw" page in the hugepage. */ | ||
| 684 | int offset = (addr & ~huge_page_mask(hs)) >> PAGE_SHIFT; | ||
| 685 | pfn = huge_pte_to_pagemap_entry(*pte, offset); | ||
| 686 | } | ||
| 687 | err = add_to_pagemap(addr, pfn, pm); | ||
| 688 | if (err) | ||
| 689 | return err; | ||
| 690 | } | ||
| 691 | |||
| 692 | cond_resched(); | ||
| 693 | |||
| 694 | return err; | ||
| 695 | } | ||
| 696 | |||
| 653 | /* | 697 | /* |
| 654 | * /proc/pid/pagemap - an array mapping virtual pages to pfns | 698 | * /proc/pid/pagemap - an array mapping virtual pages to pfns |
| 655 | * | 699 | * |
| @@ -742,6 +786,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
| 742 | 786 | ||
| 743 | pagemap_walk.pmd_entry = pagemap_pte_range; | 787 | pagemap_walk.pmd_entry = pagemap_pte_range; |
| 744 | pagemap_walk.pte_hole = pagemap_pte_hole; | 788 | pagemap_walk.pte_hole = pagemap_pte_hole; |
| 789 | pagemap_walk.hugetlb_entry = pagemap_hugetlb_range; | ||
| 745 | pagemap_walk.mm = mm; | 790 | pagemap_walk.mm = mm; |
| 746 | pagemap_walk.private = ± | 791 | pagemap_walk.private = ± |
| 747 | 792 | ||
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 8f5c05d3dbd3..5d9fd64ef81a 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
| @@ -110,9 +110,13 @@ int task_statm(struct mm_struct *mm, int *shared, int *text, | |||
| 110 | } | 110 | } |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | size += (*text = mm->end_code - mm->start_code); | 113 | *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) |
| 114 | size += (*data = mm->start_stack - mm->start_data); | 114 | >> PAGE_SHIFT; |
| 115 | *data = (PAGE_ALIGN(mm->start_stack) - (mm->start_data & PAGE_MASK)) | ||
| 116 | >> PAGE_SHIFT; | ||
| 115 | up_read(&mm->mmap_sem); | 117 | up_read(&mm->mmap_sem); |
| 118 | size >>= PAGE_SHIFT; | ||
| 119 | size += *text + *data; | ||
| 116 | *resident = size; | 120 | *resident = size; |
| 117 | return size; | 121 | return size; |
| 118 | } | 122 | } |
diff --git a/fs/reiserfs/Kconfig b/fs/reiserfs/Kconfig index 513f431038f9..ac7cd75c86f8 100644 --- a/fs/reiserfs/Kconfig +++ b/fs/reiserfs/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | config REISERFS_FS | 1 | config REISERFS_FS |
| 2 | tristate "Reiserfs support" | 2 | tristate "Reiserfs support" |
| 3 | select CRC32 | 3 | select CRC32 |
| 4 | select FS_JOURNAL_INFO | ||
| 4 | help | 5 | help |
| 5 | Stores not just filenames but the files themselves in a balanced | 6 | Stores not just filenames but the files themselves in a balanced |
| 6 | tree. Uses journalling. | 7 | tree. Uses journalling. |
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 8a771c59ac3e..90492327b383 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
| @@ -350,13 +350,8 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) | |||
| 350 | le32_to_cpu(sup->fmt_version)); | 350 | le32_to_cpu(sup->fmt_version)); |
| 351 | printk(KERN_DEBUG "\ttime_gran %u\n", | 351 | printk(KERN_DEBUG "\ttime_gran %u\n", |
| 352 | le32_to_cpu(sup->time_gran)); | 352 | le32_to_cpu(sup->time_gran)); |
| 353 | printk(KERN_DEBUG "\tUUID %02X%02X%02X%02X-%02X%02X" | 353 | printk(KERN_DEBUG "\tUUID %pUB\n", |
| 354 | "-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", | 354 | sup->uuid); |
| 355 | sup->uuid[0], sup->uuid[1], sup->uuid[2], sup->uuid[3], | ||
| 356 | sup->uuid[4], sup->uuid[5], sup->uuid[6], sup->uuid[7], | ||
| 357 | sup->uuid[8], sup->uuid[9], sup->uuid[10], sup->uuid[11], | ||
| 358 | sup->uuid[12], sup->uuid[13], sup->uuid[14], | ||
| 359 | sup->uuid[15]); | ||
| 360 | break; | 355 | break; |
| 361 | } | 356 | } |
| 362 | case UBIFS_MST_NODE: | 357 | case UBIFS_MST_NODE: |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 943ad5624530..43f9d19a6f33 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -1393,12 +1393,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1393 | c->leb_size, c->leb_size >> 10); | 1393 | c->leb_size, c->leb_size >> 10); |
| 1394 | dbg_msg("data journal heads: %d", | 1394 | dbg_msg("data journal heads: %d", |
| 1395 | c->jhead_cnt - NONDATA_JHEADS_CNT); | 1395 | c->jhead_cnt - NONDATA_JHEADS_CNT); |
| 1396 | dbg_msg("UUID: %02X%02X%02X%02X-%02X%02X" | 1396 | dbg_msg("UUID: %pUB", c->uuid); |
| 1397 | "-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", | ||
| 1398 | c->uuid[0], c->uuid[1], c->uuid[2], c->uuid[3], | ||
| 1399 | c->uuid[4], c->uuid[5], c->uuid[6], c->uuid[7], | ||
| 1400 | c->uuid[8], c->uuid[9], c->uuid[10], c->uuid[11], | ||
| 1401 | c->uuid[12], c->uuid[13], c->uuid[14], c->uuid[15]); | ||
| 1402 | dbg_msg("big_lpt %d", c->big_lpt); | 1397 | dbg_msg("big_lpt %d", c->big_lpt); |
| 1403 | dbg_msg("log LEBs: %d (%d - %d)", | 1398 | dbg_msg("log LEBs: %d (%d - %d)", |
| 1404 | c->log_lebs, UBIFS_LOG_LNUM, c->log_last); | 1399 | c->log_lebs, UBIFS_LOG_LNUM, c->log_last); |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 1ec98ed914d4..9d4fdcaf897f 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
| @@ -225,16 +225,10 @@ xlog_header_check_dump( | |||
| 225 | xfs_mount_t *mp, | 225 | xfs_mount_t *mp, |
| 226 | xlog_rec_header_t *head) | 226 | xlog_rec_header_t *head) |
| 227 | { | 227 | { |
| 228 | int b; | 228 | cmn_err(CE_DEBUG, "%s: SB : uuid = %pU, fmt = %d\n", |
| 229 | 229 | __func__, &mp->m_sb.sb_uuid, XLOG_FMT); | |
| 230 | cmn_err(CE_DEBUG, "%s: SB : uuid = ", __func__); | 230 | cmn_err(CE_DEBUG, " log : uuid = %pU, fmt = %d\n", |
| 231 | for (b = 0; b < 16; b++) | 231 | &head->h_fs_uuid, be32_to_cpu(head->h_fmt)); |
| 232 | cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&mp->m_sb.sb_uuid)[b]); | ||
| 233 | cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT); | ||
| 234 | cmn_err(CE_DEBUG, " log : uuid = "); | ||
| 235 | for (b = 0; b < 16; b++) | ||
| 236 | cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&head->h_fs_uuid)[b]); | ||
| 237 | cmn_err(CE_DEBUG, ", fmt = %d\n", be32_to_cpu(head->h_fmt)); | ||
| 238 | } | 232 | } |
| 239 | #else | 233 | #else |
| 240 | #define xlog_header_check_dump(mp, head) | 234 | #define xlog_header_check_dump(mp, head) |
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 4b6755984d24..18c435d7c082 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h | |||
| @@ -113,22 +113,22 @@ extern void warn_slowpath_null(const char *file, const int line); | |||
| 113 | #endif | 113 | #endif |
| 114 | 114 | ||
| 115 | #define WARN_ON_ONCE(condition) ({ \ | 115 | #define WARN_ON_ONCE(condition) ({ \ |
| 116 | static int __warned; \ | 116 | static bool __warned; \ |
| 117 | int __ret_warn_once = !!(condition); \ | 117 | int __ret_warn_once = !!(condition); \ |
| 118 | \ | 118 | \ |
| 119 | if (unlikely(__ret_warn_once)) \ | 119 | if (unlikely(__ret_warn_once)) \ |
| 120 | if (WARN_ON(!__warned)) \ | 120 | if (WARN_ON(!__warned)) \ |
| 121 | __warned = 1; \ | 121 | __warned = true; \ |
| 122 | unlikely(__ret_warn_once); \ | 122 | unlikely(__ret_warn_once); \ |
| 123 | }) | 123 | }) |
| 124 | 124 | ||
| 125 | #define WARN_ONCE(condition, format...) ({ \ | 125 | #define WARN_ONCE(condition, format...) ({ \ |
| 126 | static int __warned; \ | 126 | static bool __warned; \ |
| 127 | int __ret_warn_once = !!(condition); \ | 127 | int __ret_warn_once = !!(condition); \ |
| 128 | \ | 128 | \ |
| 129 | if (unlikely(__ret_warn_once)) \ | 129 | if (unlikely(__ret_warn_once)) \ |
| 130 | if (WARN(!__warned, format)) \ | 130 | if (WARN(!__warned, format)) \ |
| 131 | __warned = 1; \ | 131 | __warned = true; \ |
| 132 | unlikely(__ret_warn_once); \ | 132 | unlikely(__ret_warn_once); \ |
| 133 | }) | 133 | }) |
| 134 | 134 | ||
diff --git a/include/asm-generic/mman-common.h b/include/asm-generic/mman-common.h index 5ee13b2fd223..20111265afd8 100644 --- a/include/asm-generic/mman-common.h +++ b/include/asm-generic/mman-common.h | |||
| @@ -19,6 +19,11 @@ | |||
| 19 | #define MAP_TYPE 0x0f /* Mask for type of mapping */ | 19 | #define MAP_TYPE 0x0f /* Mask for type of mapping */ |
| 20 | #define MAP_FIXED 0x10 /* Interpret addr exactly */ | 20 | #define MAP_FIXED 0x10 /* Interpret addr exactly */ |
| 21 | #define MAP_ANONYMOUS 0x20 /* don't use a file */ | 21 | #define MAP_ANONYMOUS 0x20 /* don't use a file */ |
| 22 | #ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED | ||
| 23 | # define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be uninitialized */ | ||
| 24 | #else | ||
| 25 | # define MAP_UNINITIALIZED 0x0 /* Don't support this flag */ | ||
| 26 | #endif | ||
| 22 | 27 | ||
| 23 | #define MS_ASYNC 1 /* sync memory asynchronously */ | 28 | #define MS_ASYNC 1 /* sync memory asynchronously */ |
| 24 | #define MS_INVALIDATE 2 /* invalidate the caches */ | 29 | #define MS_INVALIDATE 2 /* invalidate the caches */ |
diff --git a/include/linux/atmel-mci.h b/include/linux/atmel-mci.h index 57b1846a3c87..3e09b345f4d6 100644 --- a/include/linux/atmel-mci.h +++ b/include/linux/atmel-mci.h | |||
| @@ -3,8 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #define ATMEL_MCI_MAX_NR_SLOTS 2 | 4 | #define ATMEL_MCI_MAX_NR_SLOTS 2 |
| 5 | 5 | ||
| 6 | #include <linux/dw_dmac.h> | ||
| 7 | |||
| 8 | /** | 6 | /** |
| 9 | * struct mci_slot_pdata - board-specific per-slot configuration | 7 | * struct mci_slot_pdata - board-specific per-slot configuration |
| 10 | * @bus_width: Number of data lines wired up the slot | 8 | * @bus_width: Number of data lines wired up the slot |
| @@ -34,7 +32,7 @@ struct mci_slot_pdata { | |||
| 34 | * @slot: Per-slot configuration data. | 32 | * @slot: Per-slot configuration data. |
| 35 | */ | 33 | */ |
| 36 | struct mci_platform_data { | 34 | struct mci_platform_data { |
| 37 | struct dw_dma_slave dma_slave; | 35 | struct mci_dma_data *dma_slave; |
| 38 | struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; | 36 | struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; |
| 39 | }; | 37 | }; |
| 40 | 38 | ||
diff --git a/include/linux/cs5535.h b/include/linux/cs5535.h new file mode 100644 index 000000000000..d5a1d4810b80 --- /dev/null +++ b/include/linux/cs5535.h | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | /* | ||
| 2 | * AMD CS5535/CS5536 definitions | ||
| 3 | * Copyright (C) 2006 Advanced Micro Devices, Inc. | ||
| 4 | * Copyright (C) 2009 Andres Salomon <dilinger@collabora.co.uk> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of version 2 of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef _CS5535_H | ||
| 12 | #define _CS5535_H | ||
| 13 | |||
| 14 | /* MSRs */ | ||
| 15 | #define MSR_GLIU_P2D_RO0 0x10000029 | ||
| 16 | |||
| 17 | #define MSR_LX_GLD_MSR_CONFIG 0x48002001 | ||
| 18 | #define MSR_LX_MSR_PADSEL 0x48002011 /* NOT 0x48000011; the data | ||
| 19 | * sheet has the wrong value */ | ||
| 20 | #define MSR_GLCP_SYS_RSTPLL 0x4C000014 | ||
| 21 | #define MSR_GLCP_DOTPLL 0x4C000015 | ||
| 22 | |||
| 23 | #define MSR_LBAR_SMB 0x5140000B | ||
| 24 | #define MSR_LBAR_GPIO 0x5140000C | ||
| 25 | #define MSR_LBAR_MFGPT 0x5140000D | ||
| 26 | #define MSR_LBAR_ACPI 0x5140000E | ||
| 27 | #define MSR_LBAR_PMS 0x5140000F | ||
| 28 | |||
| 29 | #define MSR_DIVIL_SOFT_RESET 0x51400017 | ||
| 30 | |||
| 31 | #define MSR_PIC_YSEL_LOW 0x51400020 | ||
| 32 | #define MSR_PIC_YSEL_HIGH 0x51400021 | ||
| 33 | #define MSR_PIC_ZSEL_LOW 0x51400022 | ||
| 34 | #define MSR_PIC_ZSEL_HIGH 0x51400023 | ||
| 35 | #define MSR_PIC_IRQM_LPC 0x51400025 | ||
| 36 | |||
| 37 | #define MSR_MFGPT_IRQ 0x51400028 | ||
| 38 | #define MSR_MFGPT_NR 0x51400029 | ||
| 39 | #define MSR_MFGPT_SETUP 0x5140002B | ||
| 40 | |||
| 41 | #define MSR_LX_SPARE_MSR 0x80000011 /* DC-specific */ | ||
| 42 | |||
| 43 | #define MSR_GX_GLD_MSR_CONFIG 0xC0002001 | ||
| 44 | #define MSR_GX_MSR_PADSEL 0xC0002011 | ||
| 45 | |||
| 46 | /* resource sizes */ | ||
| 47 | #define LBAR_GPIO_SIZE 0xFF | ||
| 48 | #define LBAR_MFGPT_SIZE 0x40 | ||
| 49 | #define LBAR_ACPI_SIZE 0x40 | ||
| 50 | #define LBAR_PMS_SIZE 0x80 | ||
| 51 | |||
| 52 | /* VSA2 magic values */ | ||
| 53 | #define VSA_VRC_INDEX 0xAC1C | ||
| 54 | #define VSA_VRC_DATA 0xAC1E | ||
| 55 | #define VSA_VR_UNLOCK 0xFC53 /* unlock virtual register */ | ||
| 56 | #define VSA_VR_SIGNATURE 0x0003 | ||
| 57 | #define VSA_VR_MEM_SIZE 0x0200 | ||
| 58 | #define AMD_VSA_SIG 0x4132 /* signature is ascii 'VSA2' */ | ||
| 59 | #define GSW_VSA_SIG 0x534d /* General Software signature */ | ||
| 60 | |||
| 61 | #include <linux/io.h> | ||
| 62 | |||
| 63 | static inline int cs5535_has_vsa2(void) | ||
| 64 | { | ||
| 65 | static int has_vsa2 = -1; | ||
| 66 | |||
| 67 | if (has_vsa2 == -1) { | ||
| 68 | uint16_t val; | ||
| 69 | |||
| 70 | /* | ||
| 71 | * The VSA has virtual registers that we can query for a | ||
| 72 | * signature. | ||
| 73 | */ | ||
| 74 | outw(VSA_VR_UNLOCK, VSA_VRC_INDEX); | ||
| 75 | outw(VSA_VR_SIGNATURE, VSA_VRC_INDEX); | ||
| 76 | |||
| 77 | val = inw(VSA_VRC_DATA); | ||
| 78 | has_vsa2 = (val == AMD_VSA_SIG || val == GSW_VSA_SIG); | ||
| 79 | } | ||
| 80 | |||
| 81 | return has_vsa2; | ||
| 82 | } | ||
| 83 | |||
| 84 | /* GPIOs */ | ||
| 85 | #define GPIO_OUTPUT_VAL 0x00 | ||
| 86 | #define GPIO_OUTPUT_ENABLE 0x04 | ||
| 87 | #define GPIO_OUTPUT_OPEN_DRAIN 0x08 | ||
| 88 | #define GPIO_OUTPUT_INVERT 0x0C | ||
| 89 | #define GPIO_OUTPUT_AUX1 0x10 | ||
| 90 | #define GPIO_OUTPUT_AUX2 0x14 | ||
| 91 | #define GPIO_PULL_UP 0x18 | ||
| 92 | #define GPIO_PULL_DOWN 0x1C | ||
| 93 | #define GPIO_INPUT_ENABLE 0x20 | ||
| 94 | #define GPIO_INPUT_INVERT 0x24 | ||
| 95 | #define GPIO_INPUT_FILTER 0x28 | ||
| 96 | #define GPIO_INPUT_EVENT_COUNT 0x2C | ||
| 97 | #define GPIO_READ_BACK 0x30 | ||
| 98 | #define GPIO_INPUT_AUX1 0x34 | ||
| 99 | #define GPIO_EVENTS_ENABLE 0x38 | ||
| 100 | #define GPIO_LOCK_ENABLE 0x3C | ||
| 101 | #define GPIO_POSITIVE_EDGE_EN 0x40 | ||
| 102 | #define GPIO_NEGATIVE_EDGE_EN 0x44 | ||
| 103 | #define GPIO_POSITIVE_EDGE_STS 0x48 | ||
| 104 | #define GPIO_NEGATIVE_EDGE_STS 0x4C | ||
| 105 | |||
| 106 | #define GPIO_MAP_X 0xE0 | ||
| 107 | #define GPIO_MAP_Y 0xE4 | ||
| 108 | #define GPIO_MAP_Z 0xE8 | ||
| 109 | #define GPIO_MAP_W 0xEC | ||
| 110 | |||
| 111 | void cs5535_gpio_set(unsigned offset, unsigned int reg); | ||
| 112 | void cs5535_gpio_clear(unsigned offset, unsigned int reg); | ||
| 113 | int cs5535_gpio_isset(unsigned offset, unsigned int reg); | ||
| 114 | |||
| 115 | /* MFGPTs */ | ||
| 116 | |||
| 117 | #define MFGPT_MAX_TIMERS 8 | ||
| 118 | #define MFGPT_TIMER_ANY (-1) | ||
| 119 | |||
| 120 | #define MFGPT_DOMAIN_WORKING 1 | ||
| 121 | #define MFGPT_DOMAIN_STANDBY 2 | ||
| 122 | #define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY) | ||
| 123 | |||
| 124 | #define MFGPT_CMP1 0 | ||
| 125 | #define MFGPT_CMP2 1 | ||
| 126 | |||
| 127 | #define MFGPT_EVENT_IRQ 0 | ||
| 128 | #define MFGPT_EVENT_NMI 1 | ||
| 129 | #define MFGPT_EVENT_RESET 3 | ||
| 130 | |||
| 131 | #define MFGPT_REG_CMP1 0 | ||
| 132 | #define MFGPT_REG_CMP2 2 | ||
| 133 | #define MFGPT_REG_COUNTER 4 | ||
| 134 | #define MFGPT_REG_SETUP 6 | ||
| 135 | |||
| 136 | #define MFGPT_SETUP_CNTEN (1 << 15) | ||
| 137 | #define MFGPT_SETUP_CMP2 (1 << 14) | ||
| 138 | #define MFGPT_SETUP_CMP1 (1 << 13) | ||
| 139 | #define MFGPT_SETUP_SETUP (1 << 12) | ||
| 140 | #define MFGPT_SETUP_STOPEN (1 << 11) | ||
| 141 | #define MFGPT_SETUP_EXTEN (1 << 10) | ||
| 142 | #define MFGPT_SETUP_REVEN (1 << 5) | ||
| 143 | #define MFGPT_SETUP_CLKSEL (1 << 4) | ||
| 144 | |||
| 145 | struct cs5535_mfgpt_timer; | ||
| 146 | |||
| 147 | extern uint16_t cs5535_mfgpt_read(struct cs5535_mfgpt_timer *timer, | ||
| 148 | uint16_t reg); | ||
| 149 | extern void cs5535_mfgpt_write(struct cs5535_mfgpt_timer *timer, uint16_t reg, | ||
| 150 | uint16_t value); | ||
| 151 | |||
| 152 | extern int cs5535_mfgpt_toggle_event(struct cs5535_mfgpt_timer *timer, int cmp, | ||
| 153 | int event, int enable); | ||
| 154 | extern int cs5535_mfgpt_set_irq(struct cs5535_mfgpt_timer *timer, int cmp, | ||
| 155 | int *irq, int enable); | ||
| 156 | extern struct cs5535_mfgpt_timer *cs5535_mfgpt_alloc_timer(int timer, | ||
| 157 | int domain); | ||
| 158 | extern void cs5535_mfgpt_free_timer(struct cs5535_mfgpt_timer *timer); | ||
| 159 | |||
| 160 | static inline int cs5535_mfgpt_setup_irq(struct cs5535_mfgpt_timer *timer, | ||
| 161 | int cmp, int *irq) | ||
| 162 | { | ||
| 163 | return cs5535_mfgpt_set_irq(timer, cmp, irq, 1); | ||
| 164 | } | ||
| 165 | |||
| 166 | static inline int cs5535_mfgpt_release_irq(struct cs5535_mfgpt_timer *timer, | ||
| 167 | int cmp, int *irq) | ||
| 168 | { | ||
| 169 | return cs5535_mfgpt_set_irq(timer, cmp, irq, 0); | ||
| 170 | } | ||
| 171 | |||
| 172 | #endif | ||
diff --git a/include/linux/ctype.h b/include/linux/ctype.h index afa36392297a..a3d6ee0044f9 100644 --- a/include/linux/ctype.h +++ b/include/linux/ctype.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #define _X 0x40 /* hex digit */ | 15 | #define _X 0x40 /* hex digit */ |
| 16 | #define _SP 0x80 /* hard space (0x20) */ | 16 | #define _SP 0x80 /* hard space (0x20) */ |
| 17 | 17 | ||
| 18 | extern unsigned char _ctype[]; | 18 | extern const unsigned char _ctype[]; |
| 19 | 19 | ||
| 20 | #define __ismask(x) (_ctype[(int)(unsigned char)(x)]) | 20 | #define __ismask(x) (_ctype[(int)(unsigned char)(x)]) |
| 21 | 21 | ||
| @@ -27,6 +27,7 @@ extern unsigned char _ctype[]; | |||
| 27 | #define islower(c) ((__ismask(c)&(_L)) != 0) | 27 | #define islower(c) ((__ismask(c)&(_L)) != 0) |
| 28 | #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) | 28 | #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) |
| 29 | #define ispunct(c) ((__ismask(c)&(_P)) != 0) | 29 | #define ispunct(c) ((__ismask(c)&(_P)) != 0) |
| 30 | /* Note: isspace() must return false for %NUL-terminator */ | ||
| 30 | #define isspace(c) ((__ismask(c)&(_S)) != 0) | 31 | #define isspace(c) ((__ismask(c)&(_S)) != 0) |
| 31 | #define isupper(c) ((__ismask(c)&(_U)) != 0) | 32 | #define isupper(c) ((__ismask(c)&(_U)) != 0) |
| 32 | #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) | 33 | #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) |
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index a0d9422a1569..f8c2e1767500 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h | |||
| @@ -57,8 +57,7 @@ extern int ddebug_remove_module(char *mod_name); | |||
| 57 | { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ | 57 | { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ |
| 58 | DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ | 58 | DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ |
| 59 | if (__dynamic_dbg_enabled(descriptor)) \ | 59 | if (__dynamic_dbg_enabled(descriptor)) \ |
| 60 | printk(KERN_DEBUG KBUILD_MODNAME ":" pr_fmt(fmt), \ | 60 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ |
| 61 | ##__VA_ARGS__); \ | ||
| 62 | } while (0) | 61 | } while (0) |
| 63 | 62 | ||
| 64 | 63 | ||
| @@ -69,9 +68,7 @@ extern int ddebug_remove_module(char *mod_name); | |||
| 69 | { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ | 68 | { KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ |
| 70 | DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ | 69 | DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ |
| 71 | if (__dynamic_dbg_enabled(descriptor)) \ | 70 | if (__dynamic_dbg_enabled(descriptor)) \ |
| 72 | dev_printk(KERN_DEBUG, dev, \ | 71 | dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ |
| 73 | KBUILD_MODNAME ": " fmt, \ | ||
| 74 | ##__VA_ARGS__); \ | ||
| 75 | } while (0) | 72 | } while (0) |
| 76 | 73 | ||
| 77 | #else | 74 | #else |
| @@ -81,8 +78,10 @@ static inline int ddebug_remove_module(char *mod) | |||
| 81 | return 0; | 78 | return 0; |
| 82 | } | 79 | } |
| 83 | 80 | ||
| 84 | #define dynamic_pr_debug(fmt, ...) do { } while (0) | 81 | #define dynamic_pr_debug(fmt, ...) \ |
| 85 | #define dynamic_dev_dbg(dev, format, ...) do { } while (0) | 82 | do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0) |
| 83 | #define dynamic_dev_dbg(dev, format, ...) \ | ||
| 84 | do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0) | ||
| 86 | #endif | 85 | #endif |
| 87 | 86 | ||
| 88 | #endif | 87 | #endif |
diff --git a/include/linux/efi.h b/include/linux/efi.h index ce4581fbc08b..fb737bc19a8c 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
| @@ -280,11 +280,7 @@ efi_guidcmp (efi_guid_t left, efi_guid_t right) | |||
| 280 | static inline char * | 280 | static inline char * |
| 281 | efi_guid_unparse(efi_guid_t *guid, char *out) | 281 | efi_guid_unparse(efi_guid_t *guid, char *out) |
| 282 | { | 282 | { |
| 283 | sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", | 283 | sprintf(out, "%pUl", guid->b); |
| 284 | guid->b[3], guid->b[2], guid->b[1], guid->b[0], | ||
| 285 | guid->b[5], guid->b[4], guid->b[7], guid->b[6], | ||
| 286 | guid->b[8], guid->b[9], guid->b[10], guid->b[11], | ||
| 287 | guid->b[12], guid->b[13], guid->b[14], guid->b[15]); | ||
| 288 | return out; | 284 | return out; |
| 289 | } | 285 | } |
| 290 | 286 | ||
diff --git a/include/linux/err.h b/include/linux/err.h index ec87f3142bf3..1b12642636c7 100644 --- a/include/linux/err.h +++ b/include/linux/err.h | |||
| @@ -34,6 +34,11 @@ static inline long IS_ERR(const void *ptr) | |||
| 34 | return IS_ERR_VALUE((unsigned long)ptr); | 34 | return IS_ERR_VALUE((unsigned long)ptr); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static inline long IS_ERR_OR_NULL(const void *ptr) | ||
| 38 | { | ||
| 39 | return !ptr || IS_ERR_VALUE((unsigned long)ptr); | ||
| 40 | } | ||
| 41 | |||
| 37 | /** | 42 | /** |
| 38 | * ERR_CAST - Explicitly cast an error-valued pointer to another pointer type | 43 | * ERR_CAST - Explicitly cast an error-valued pointer to another pointer type |
| 39 | * @ptr: The pointer to cast. | 44 | * @ptr: The pointer to cast. |
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 41a59afc70fa..78b4bc64c006 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h | |||
| @@ -23,6 +23,12 @@ void reset_vma_resv_huge_pages(struct vm_area_struct *vma); | |||
| 23 | int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); | 23 | int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); |
| 24 | int hugetlb_overcommit_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); | 24 | int hugetlb_overcommit_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); |
| 25 | int hugetlb_treat_movable_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); | 25 | int hugetlb_treat_movable_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); |
| 26 | |||
| 27 | #ifdef CONFIG_NUMA | ||
| 28 | int hugetlb_mempolicy_sysctl_handler(struct ctl_table *, int, | ||
| 29 | void __user *, size_t *, loff_t *); | ||
| 30 | #endif | ||
| 31 | |||
| 26 | int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *); | 32 | int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *); |
| 27 | int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, | 33 | int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, |
| 28 | struct page **, struct vm_area_struct **, | 34 | struct page **, struct vm_area_struct **, |
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 419ab546b266..02fc617782ef 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
| @@ -110,7 +110,7 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, | |||
| 110 | * @driver: Device driver model driver | 110 | * @driver: Device driver model driver |
| 111 | * @id_table: List of I2C devices supported by this driver | 111 | * @id_table: List of I2C devices supported by this driver |
| 112 | * @detect: Callback for device detection | 112 | * @detect: Callback for device detection |
| 113 | * @address_data: The I2C addresses to probe (for detect) | 113 | * @address_list: The I2C addresses to probe (for detect) |
| 114 | * @clients: List of detected clients we created (for i2c-core use only) | 114 | * @clients: List of detected clients we created (for i2c-core use only) |
| 115 | * | 115 | * |
| 116 | * The driver.owner field should be set to the module owner of this driver. | 116 | * The driver.owner field should be set to the module owner of this driver. |
| @@ -161,8 +161,8 @@ struct i2c_driver { | |||
| 161 | const struct i2c_device_id *id_table; | 161 | const struct i2c_device_id *id_table; |
| 162 | 162 | ||
| 163 | /* Device detection callback for automatic device creation */ | 163 | /* Device detection callback for automatic device creation */ |
| 164 | int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *); | 164 | int (*detect)(struct i2c_client *, struct i2c_board_info *); |
| 165 | const struct i2c_client_address_data *address_data; | 165 | const unsigned short *address_list; |
| 166 | struct list_head clients; | 166 | struct list_head clients; |
| 167 | }; | 167 | }; |
| 168 | #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) | 168 | #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) |
| @@ -391,14 +391,6 @@ static inline void i2c_unlock_adapter(struct i2c_adapter *adapter) | |||
| 391 | #define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */ | 391 | #define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */ |
| 392 | #define I2C_CLASS_SPD (1<<7) /* SPD EEPROMs and similar */ | 392 | #define I2C_CLASS_SPD (1<<7) /* SPD EEPROMs and similar */ |
| 393 | 393 | ||
| 394 | /* i2c_client_address_data is the struct for holding default client | ||
| 395 | * addresses for a driver and for the parameters supplied on the | ||
| 396 | * command line | ||
| 397 | */ | ||
| 398 | struct i2c_client_address_data { | ||
| 399 | const unsigned short *normal_i2c; | ||
| 400 | }; | ||
| 401 | |||
| 402 | /* Internal numbers to terminate lists */ | 394 | /* Internal numbers to terminate lists */ |
| 403 | #define I2C_CLIENT_END 0xfffeU | 395 | #define I2C_CLIENT_END 0xfffeU |
| 404 | 396 | ||
| @@ -576,82 +568,4 @@ union i2c_smbus_data { | |||
| 576 | #define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ | 568 | #define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ |
| 577 | #define I2C_SMBUS_I2C_BLOCK_DATA 8 | 569 | #define I2C_SMBUS_I2C_BLOCK_DATA 8 |
| 578 | 570 | ||
| 579 | |||
| 580 | #ifdef __KERNEL__ | ||
| 581 | |||
| 582 | /* These defines are used for probing i2c client addresses */ | ||
| 583 | /* The length of the option lists */ | ||
| 584 | #define I2C_CLIENT_MAX_OPTS 48 | ||
| 585 | |||
| 586 | /* Default fill of many variables */ | ||
| 587 | #define I2C_CLIENT_DEFAULTS {I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 588 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 589 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 590 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 591 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 592 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 593 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 594 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 595 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 596 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 597 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 598 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 599 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 600 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 601 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \ | ||
| 602 | I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END} | ||
| 603 | |||
| 604 | /* I2C_CLIENT_MODULE_PARM creates a module parameter, and puts it in the | ||
| 605 | module header */ | ||
| 606 | |||
| 607 | #define I2C_CLIENT_MODULE_PARM(var,desc) \ | ||
| 608 | static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \ | ||
| 609 | static unsigned int var##_num; \ | ||
| 610 | module_param_array(var, short, &var##_num, 0); \ | ||
| 611 | MODULE_PARM_DESC(var, desc) | ||
| 612 | |||
| 613 | #define I2C_CLIENT_INSMOD_COMMON \ | ||
| 614 | static const struct i2c_client_address_data addr_data = { \ | ||
| 615 | .normal_i2c = normal_i2c, \ | ||
| 616 | } | ||
| 617 | |||
| 618 | /* These are the ones you want to use in your own drivers. Pick the one | ||
| 619 | which matches the number of devices the driver differenciates between. */ | ||
| 620 | #define I2C_CLIENT_INSMOD \ | ||
| 621 | I2C_CLIENT_INSMOD_COMMON | ||
| 622 | |||
| 623 | #define I2C_CLIENT_INSMOD_1(chip1) \ | ||
| 624 | enum chips { any_chip, chip1 }; \ | ||
| 625 | I2C_CLIENT_INSMOD_COMMON | ||
| 626 | |||
| 627 | #define I2C_CLIENT_INSMOD_2(chip1, chip2) \ | ||
| 628 | enum chips { any_chip, chip1, chip2 }; \ | ||
| 629 | I2C_CLIENT_INSMOD_COMMON | ||
| 630 | |||
| 631 | #define I2C_CLIENT_INSMOD_3(chip1, chip2, chip3) \ | ||
| 632 | enum chips { any_chip, chip1, chip2, chip3 }; \ | ||
| 633 | I2C_CLIENT_INSMOD_COMMON | ||
| 634 | |||
| 635 | #define I2C_CLIENT_INSMOD_4(chip1, chip2, chip3, chip4) \ | ||
| 636 | enum chips { any_chip, chip1, chip2, chip3, chip4 }; \ | ||
| 637 | I2C_CLIENT_INSMOD_COMMON | ||
| 638 | |||
| 639 | #define I2C_CLIENT_INSMOD_5(chip1, chip2, chip3, chip4, chip5) \ | ||
| 640 | enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \ | ||
| 641 | I2C_CLIENT_INSMOD_COMMON | ||
| 642 | |||
| 643 | #define I2C_CLIENT_INSMOD_6(chip1, chip2, chip3, chip4, chip5, chip6) \ | ||
| 644 | enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \ | ||
| 645 | I2C_CLIENT_INSMOD_COMMON | ||
| 646 | |||
| 647 | #define I2C_CLIENT_INSMOD_7(chip1, chip2, chip3, chip4, chip5, chip6, chip7) \ | ||
| 648 | enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \ | ||
| 649 | chip7 }; \ | ||
| 650 | I2C_CLIENT_INSMOD_COMMON | ||
| 651 | |||
| 652 | #define I2C_CLIENT_INSMOD_8(chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8) \ | ||
| 653 | enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \ | ||
| 654 | chip7, chip8 }; \ | ||
| 655 | I2C_CLIENT_INSMOD_COMMON | ||
| 656 | #endif /* __KERNEL__ */ | ||
| 657 | #endif /* _LINUX_I2C_H */ | 571 | #endif /* _LINUX_I2C_H */ |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 8d10aa7fd4c9..8ed0abf06f89 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
| @@ -111,6 +111,12 @@ extern struct cred init_cred; | |||
| 111 | # define INIT_PERF_EVENTS(tsk) | 111 | # define INIT_PERF_EVENTS(tsk) |
| 112 | #endif | 112 | #endif |
| 113 | 113 | ||
| 114 | #ifdef CONFIG_FS_JOURNAL_INFO | ||
| 115 | #define INIT_JOURNAL_INFO .journal_info = NULL, | ||
| 116 | #else | ||
| 117 | #define INIT_JOURNAL_INFO | ||
| 118 | #endif | ||
| 119 | |||
| 114 | /* | 120 | /* |
| 115 | * INIT_TASK is used to set up the first task table, touch at | 121 | * INIT_TASK is used to set up the first task table, touch at |
| 116 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 122 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
| @@ -162,7 +168,6 @@ extern struct cred init_cred; | |||
| 162 | .signal = {{0}}}, \ | 168 | .signal = {{0}}}, \ |
| 163 | .blocked = {{0}}, \ | 169 | .blocked = {{0}}, \ |
| 164 | .alloc_lock = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock), \ | 170 | .alloc_lock = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock), \ |
| 165 | .journal_info = NULL, \ | ||
| 166 | .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ | 171 | .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ |
| 167 | .fs_excl = ATOMIC_INIT(0), \ | 172 | .fs_excl = ATOMIC_INIT(0), \ |
| 168 | .pi_lock = __SPIN_LOCK_UNLOCKED(tsk.pi_lock), \ | 173 | .pi_lock = __SPIN_LOCK_UNLOCKED(tsk.pi_lock), \ |
| @@ -173,6 +178,7 @@ extern struct cred init_cred; | |||
| 173 | [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ | 178 | [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ |
| 174 | }, \ | 179 | }, \ |
| 175 | .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \ | 180 | .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \ |
| 181 | INIT_JOURNAL_INFO \ | ||
| 176 | INIT_IDS \ | 182 | INIT_IDS \ |
| 177 | INIT_PERF_EVENTS(tsk) \ | 183 | INIT_PERF_EVENTS(tsk) \ |
| 178 | INIT_TRACE_IRQFLAGS \ | 184 | INIT_TRACE_IRQFLAGS \ |
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 792274269f2b..d8e9b3d1c23c 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h | |||
| @@ -107,18 +107,6 @@ static inline void print_symbol(const char *fmt, unsigned long addr) | |||
| 107 | __builtin_extract_return_addr((void *)addr)); | 107 | __builtin_extract_return_addr((void *)addr)); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | /* | ||
| 111 | * Pretty-print a function pointer. This function is deprecated. | ||
| 112 | * Please use the "%pF" vsprintf format instead. | ||
| 113 | */ | ||
| 114 | static inline void __deprecated print_fn_descriptor_symbol(const char *fmt, void *addr) | ||
| 115 | { | ||
| 116 | #if defined(CONFIG_IA64) || defined(CONFIG_PPC64) | ||
| 117 | addr = *(void **)addr; | ||
| 118 | #endif | ||
| 119 | print_symbol(fmt, (unsigned long)addr); | ||
| 120 | } | ||
| 121 | |||
| 122 | static inline void print_ip_sym(unsigned long ip) | 110 | static inline void print_ip_sym(unsigned long ip) |
| 123 | { | 111 | { |
| 124 | printk("[<%p>] %pS\n", (void *) ip, (void *) ip); | 112 | printk("[<%p>] %pS\n", (void *) ip, (void *) ip); |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 3fa4c590cf12..4d9c916d06d9 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
| @@ -251,10 +251,10 @@ extern int printk_delay_msec; | |||
| 251 | * Print a one-time message (analogous to WARN_ONCE() et al): | 251 | * Print a one-time message (analogous to WARN_ONCE() et al): |
| 252 | */ | 252 | */ |
| 253 | #define printk_once(x...) ({ \ | 253 | #define printk_once(x...) ({ \ |
| 254 | static bool __print_once = true; \ | 254 | static bool __print_once; \ |
| 255 | \ | 255 | \ |
| 256 | if (__print_once) { \ | 256 | if (!__print_once) { \ |
| 257 | __print_once = false; \ | 257 | __print_once = true; \ |
| 258 | printk(x); \ | 258 | printk(x); \ |
| 259 | } \ | 259 | } \ |
| 260 | }) | 260 | }) |
| @@ -397,15 +397,58 @@ static inline char *pack_hex_byte(char *buf, u8 byte) | |||
| 397 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | 397 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) |
| 398 | #elif defined(CONFIG_DYNAMIC_DEBUG) | 398 | #elif defined(CONFIG_DYNAMIC_DEBUG) |
| 399 | /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */ | 399 | /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */ |
| 400 | #define pr_debug(fmt, ...) do { \ | 400 | #define pr_debug(fmt, ...) \ |
| 401 | dynamic_pr_debug(fmt, ##__VA_ARGS__); \ | 401 | dynamic_pr_debug(fmt, ##__VA_ARGS__) |
| 402 | } while (0) | ||
| 403 | #else | 402 | #else |
| 404 | #define pr_debug(fmt, ...) \ | 403 | #define pr_debug(fmt, ...) \ |
| 405 | ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; }) | 404 | ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; }) |
| 406 | #endif | 405 | #endif |
| 407 | 406 | ||
| 408 | /* | 407 | /* |
| 408 | * ratelimited messages with local ratelimit_state, | ||
| 409 | * no local ratelimit_state used in the !PRINTK case | ||
| 410 | */ | ||
| 411 | #ifdef CONFIG_PRINTK | ||
| 412 | #define printk_ratelimited(fmt, ...) ({ \ | ||
| 413 | static struct ratelimit_state _rs = { \ | ||
| 414 | .interval = DEFAULT_RATELIMIT_INTERVAL, \ | ||
| 415 | .burst = DEFAULT_RATELIMIT_BURST, \ | ||
| 416 | }; \ | ||
| 417 | \ | ||
| 418 | if (!__ratelimit(&_rs)) \ | ||
| 419 | printk(fmt, ##__VA_ARGS__); \ | ||
| 420 | }) | ||
| 421 | #else | ||
| 422 | /* No effect, but we still get type checking even in the !PRINTK case: */ | ||
| 423 | #define printk_ratelimited printk | ||
| 424 | #endif | ||
| 425 | |||
| 426 | #define pr_emerg_ratelimited(fmt, ...) \ | ||
| 427 | printk_ratelimited(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) | ||
| 428 | #define pr_alert_ratelimited(fmt, ...) \ | ||
| 429 | printk_ratelimited(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) | ||
| 430 | #define pr_crit_ratelimited(fmt, ...) \ | ||
| 431 | printk_ratelimited(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) | ||
| 432 | #define pr_err_ratelimited(fmt, ...) \ | ||
| 433 | printk_ratelimited(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) | ||
| 434 | #define pr_warning_ratelimited(fmt, ...) \ | ||
| 435 | printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) | ||
| 436 | #define pr_notice_ratelimited(fmt, ...) \ | ||
| 437 | printk_ratelimited(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) | ||
| 438 | #define pr_info_ratelimited(fmt, ...) \ | ||
| 439 | printk_ratelimited(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) | ||
| 440 | /* no pr_cont_ratelimited, don't do that... */ | ||
| 441 | /* If you are writing a driver, please use dev_dbg instead */ | ||
| 442 | #if defined(DEBUG) | ||
| 443 | #define pr_debug_ratelimited(fmt, ...) \ | ||
| 444 | printk_ratelimited(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | ||
| 445 | #else | ||
| 446 | #define pr_debug_ratelimited(fmt, ...) \ | ||
| 447 | ({ if (0) printk_ratelimited(KERN_DEBUG pr_fmt(fmt), \ | ||
| 448 | ##__VA_ARGS__); 0; }) | ||
| 449 | #endif | ||
| 450 | |||
| 451 | /* | ||
| 409 | * General tracing related utility functions - trace_printk(), | 452 | * General tracing related utility functions - trace_printk(), |
| 410 | * tracing_on/tracing_off and tracing_start()/tracing_stop | 453 | * tracing_on/tracing_off and tracing_start()/tracing_stop |
| 411 | * | 454 | * |
diff --git a/include/linux/ksm.h b/include/linux/ksm.h index a485c14ecd5d..bed5f16ba827 100644 --- a/include/linux/ksm.h +++ b/include/linux/ksm.h | |||
| @@ -9,8 +9,12 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
| 11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
| 12 | #include <linux/pagemap.h> | ||
| 13 | #include <linux/rmap.h> | ||
| 12 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
| 13 | #include <linux/vmstat.h> | 15 | |
| 16 | struct stable_node; | ||
| 17 | struct mem_cgroup; | ||
| 14 | 18 | ||
| 15 | #ifdef CONFIG_KSM | 19 | #ifdef CONFIG_KSM |
| 16 | int ksm_madvise(struct vm_area_struct *vma, unsigned long start, | 20 | int ksm_madvise(struct vm_area_struct *vma, unsigned long start, |
| @@ -34,23 +38,60 @@ static inline void ksm_exit(struct mm_struct *mm) | |||
| 34 | /* | 38 | /* |
| 35 | * A KSM page is one of those write-protected "shared pages" or "merged pages" | 39 | * A KSM page is one of those write-protected "shared pages" or "merged pages" |
| 36 | * which KSM maps into multiple mms, wherever identical anonymous page content | 40 | * which KSM maps into multiple mms, wherever identical anonymous page content |
| 37 | * is found in VM_MERGEABLE vmas. It's a PageAnon page, with NULL anon_vma. | 41 | * is found in VM_MERGEABLE vmas. It's a PageAnon page, pointing not to any |
| 42 | * anon_vma, but to that page's node of the stable tree. | ||
| 38 | */ | 43 | */ |
| 39 | static inline int PageKsm(struct page *page) | 44 | static inline int PageKsm(struct page *page) |
| 40 | { | 45 | { |
| 41 | return ((unsigned long)page->mapping == PAGE_MAPPING_ANON); | 46 | return ((unsigned long)page->mapping & PAGE_MAPPING_FLAGS) == |
| 47 | (PAGE_MAPPING_ANON | PAGE_MAPPING_KSM); | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline struct stable_node *page_stable_node(struct page *page) | ||
| 51 | { | ||
| 52 | return PageKsm(page) ? page_rmapping(page) : NULL; | ||
| 53 | } | ||
| 54 | |||
| 55 | static inline void set_page_stable_node(struct page *page, | ||
| 56 | struct stable_node *stable_node) | ||
| 57 | { | ||
| 58 | page->mapping = (void *)stable_node + | ||
| 59 | (PAGE_MAPPING_ANON | PAGE_MAPPING_KSM); | ||
| 42 | } | 60 | } |
| 43 | 61 | ||
| 44 | /* | 62 | /* |
| 45 | * But we have to avoid the checking which page_add_anon_rmap() performs. | 63 | * When do_swap_page() first faults in from swap what used to be a KSM page, |
| 64 | * no problem, it will be assigned to this vma's anon_vma; but thereafter, | ||
| 65 | * it might be faulted into a different anon_vma (or perhaps to a different | ||
| 66 | * offset in the same anon_vma). do_swap_page() cannot do all the locking | ||
| 67 | * needed to reconstitute a cross-anon_vma KSM page: for now it has to make | ||
| 68 | * a copy, and leave remerging the pages to a later pass of ksmd. | ||
| 69 | * | ||
| 70 | * We'd like to make this conditional on vma->vm_flags & VM_MERGEABLE, | ||
| 71 | * but what if the vma was unmerged while the page was swapped out? | ||
| 46 | */ | 72 | */ |
| 47 | static inline void page_add_ksm_rmap(struct page *page) | 73 | struct page *ksm_does_need_to_copy(struct page *page, |
| 74 | struct vm_area_struct *vma, unsigned long address); | ||
| 75 | static inline struct page *ksm_might_need_to_copy(struct page *page, | ||
| 76 | struct vm_area_struct *vma, unsigned long address) | ||
| 48 | { | 77 | { |
| 49 | if (atomic_inc_and_test(&page->_mapcount)) { | 78 | struct anon_vma *anon_vma = page_anon_vma(page); |
| 50 | page->mapping = (void *) PAGE_MAPPING_ANON; | 79 | |
| 51 | __inc_zone_page_state(page, NR_ANON_PAGES); | 80 | if (!anon_vma || |
| 52 | } | 81 | (anon_vma == vma->anon_vma && |
| 82 | page->index == linear_page_index(vma, address))) | ||
| 83 | return page; | ||
| 84 | |||
| 85 | return ksm_does_need_to_copy(page, vma, address); | ||
| 53 | } | 86 | } |
| 87 | |||
| 88 | int page_referenced_ksm(struct page *page, | ||
| 89 | struct mem_cgroup *memcg, unsigned long *vm_flags); | ||
| 90 | int try_to_unmap_ksm(struct page *page, enum ttu_flags flags); | ||
| 91 | int rmap_walk_ksm(struct page *page, int (*rmap_one)(struct page *, | ||
| 92 | struct vm_area_struct *, unsigned long, void *), void *arg); | ||
| 93 | void ksm_migrate_page(struct page *newpage, struct page *oldpage); | ||
| 94 | |||
| 54 | #else /* !CONFIG_KSM */ | 95 | #else /* !CONFIG_KSM */ |
| 55 | 96 | ||
| 56 | static inline int ksm_madvise(struct vm_area_struct *vma, unsigned long start, | 97 | static inline int ksm_madvise(struct vm_area_struct *vma, unsigned long start, |
| @@ -73,7 +114,32 @@ static inline int PageKsm(struct page *page) | |||
| 73 | return 0; | 114 | return 0; |
| 74 | } | 115 | } |
| 75 | 116 | ||
| 76 | /* No stub required for page_add_ksm_rmap(page) */ | 117 | static inline struct page *ksm_might_need_to_copy(struct page *page, |
| 118 | struct vm_area_struct *vma, unsigned long address) | ||
| 119 | { | ||
| 120 | return page; | ||
| 121 | } | ||
| 122 | |||
| 123 | static inline int page_referenced_ksm(struct page *page, | ||
| 124 | struct mem_cgroup *memcg, unsigned long *vm_flags) | ||
| 125 | { | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static inline int try_to_unmap_ksm(struct page *page, enum ttu_flags flags) | ||
| 130 | { | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static inline int rmap_walk_ksm(struct page *page, int (*rmap_one)(struct page*, | ||
| 135 | struct vm_area_struct *, unsigned long, void *), void *arg) | ||
| 136 | { | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static inline void ksm_migrate_page(struct page *newpage, struct page *oldpage) | ||
| 141 | { | ||
| 142 | } | ||
| 77 | #endif /* !CONFIG_KSM */ | 143 | #endif /* !CONFIG_KSM */ |
| 78 | 144 | ||
| 79 | #endif | 145 | #endif /* __LINUX_KSM_H */ |
diff --git a/include/linux/lis3lv02d.h b/include/linux/lis3lv02d.h index 3cc2f2c53e4c..f1ca0dcc1628 100644 --- a/include/linux/lis3lv02d.h +++ b/include/linux/lis3lv02d.h | |||
| @@ -43,6 +43,21 @@ struct lis3lv02d_platform_data { | |||
| 43 | #define LIS3_WAKEUP_Z_HI (1 << 5) | 43 | #define LIS3_WAKEUP_Z_HI (1 << 5) |
| 44 | unsigned char wakeup_flags; | 44 | unsigned char wakeup_flags; |
| 45 | unsigned char wakeup_thresh; | 45 | unsigned char wakeup_thresh; |
| 46 | #define LIS3_NO_MAP 0 | ||
| 47 | #define LIS3_DEV_X 1 | ||
| 48 | #define LIS3_DEV_Y 2 | ||
| 49 | #define LIS3_DEV_Z 3 | ||
| 50 | #define LIS3_INV_DEV_X -1 | ||
| 51 | #define LIS3_INV_DEV_Y -2 | ||
| 52 | #define LIS3_INV_DEV_Z -3 | ||
| 53 | s8 axis_x; | ||
| 54 | s8 axis_y; | ||
| 55 | s8 axis_z; | ||
| 56 | int (*setup_resources)(void); | ||
| 57 | int (*release_resources)(void); | ||
| 58 | /* Limits for selftest are specified in chip data sheet */ | ||
| 59 | s16 st_min_limits[3]; /* min pass limit x, y, z */ | ||
| 60 | s16 st_max_limits[3]; /* max pass limit x, y, z */ | ||
| 46 | }; | 61 | }; |
| 47 | 62 | ||
| 48 | #endif /* __LIS3LV02D_H_ */ | 63 | #endif /* __LIS3LV02D_H_ */ |
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index fed969281a41..35b07b773e6c 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h | |||
| @@ -69,7 +69,6 @@ extern void online_page(struct page *page); | |||
| 69 | /* VM interface that may be used by firmware interface */ | 69 | /* VM interface that may be used by firmware interface */ |
| 70 | extern int online_pages(unsigned long, unsigned long); | 70 | extern int online_pages(unsigned long, unsigned long); |
| 71 | extern void __offline_isolated_pages(unsigned long, unsigned long); | 71 | extern void __offline_isolated_pages(unsigned long, unsigned long); |
| 72 | extern int offline_pages(unsigned long, unsigned long, unsigned long); | ||
| 73 | 72 | ||
| 74 | /* reasonably generic interface to expand the physical pages in a zone */ | 73 | /* reasonably generic interface to expand the physical pages in a zone */ |
| 75 | extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn, | 74 | extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn, |
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 085c903fe0f1..1cc966cd3e5f 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h | |||
| @@ -201,6 +201,7 @@ extern void mpol_fix_fork_child_flag(struct task_struct *p); | |||
| 201 | extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, | 201 | extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, |
| 202 | unsigned long addr, gfp_t gfp_flags, | 202 | unsigned long addr, gfp_t gfp_flags, |
| 203 | struct mempolicy **mpol, nodemask_t **nodemask); | 203 | struct mempolicy **mpol, nodemask_t **nodemask); |
| 204 | extern bool init_nodemask_of_mempolicy(nodemask_t *mask); | ||
| 204 | extern unsigned slab_node(struct mempolicy *policy); | 205 | extern unsigned slab_node(struct mempolicy *policy); |
| 205 | 206 | ||
| 206 | extern enum zone_type policy_zone; | 207 | extern enum zone_type policy_zone; |
| @@ -328,6 +329,8 @@ static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma, | |||
| 328 | return node_zonelist(0, gfp_flags); | 329 | return node_zonelist(0, gfp_flags); |
| 329 | } | 330 | } |
| 330 | 331 | ||
| 332 | static inline bool init_nodemask_of_mempolicy(nodemask_t *m) { return false; } | ||
| 333 | |||
| 331 | static inline int do_migrate_pages(struct mm_struct *mm, | 334 | static inline int do_migrate_pages(struct mm_struct *mm, |
| 332 | const nodemask_t *from_nodes, | 335 | const nodemask_t *from_nodes, |
| 333 | const nodemask_t *to_nodes, int flags) | 336 | const nodemask_t *to_nodes, int flags) |
diff --git a/include/linux/migrate.h b/include/linux/migrate.h index 527602cdea1c..7f085c97c799 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h | |||
| @@ -12,7 +12,8 @@ typedef struct page *new_page_t(struct page *, unsigned long private, int **); | |||
| 12 | extern int putback_lru_pages(struct list_head *l); | 12 | extern int putback_lru_pages(struct list_head *l); |
| 13 | extern int migrate_page(struct address_space *, | 13 | extern int migrate_page(struct address_space *, |
| 14 | struct page *, struct page *); | 14 | struct page *, struct page *); |
| 15 | extern int migrate_pages(struct list_head *l, new_page_t x, unsigned long); | 15 | extern int migrate_pages(struct list_head *l, new_page_t x, |
| 16 | unsigned long private, int offlining); | ||
| 16 | 17 | ||
| 17 | extern int fail_migrate_page(struct address_space *, | 18 | extern int fail_migrate_page(struct address_space *, |
| 18 | struct page *, struct page *); | 19 | struct page *, struct page *); |
| @@ -26,10 +27,7 @@ extern int migrate_vmas(struct mm_struct *mm, | |||
| 26 | 27 | ||
| 27 | static inline int putback_lru_pages(struct list_head *l) { return 0; } | 28 | static inline int putback_lru_pages(struct list_head *l) { return 0; } |
| 28 | static inline int migrate_pages(struct list_head *l, new_page_t x, | 29 | static inline int migrate_pages(struct list_head *l, new_page_t x, |
| 29 | unsigned long private) { return -ENOSYS; } | 30 | unsigned long private, int offlining) { return -ENOSYS; } |
| 30 | |||
| 31 | static inline int migrate_pages_to(struct list_head *pagelist, | ||
| 32 | struct vm_area_struct *vma, int dest) { return 0; } | ||
| 33 | 31 | ||
| 34 | static inline int migrate_prep(void) { return -ENOSYS; } | 32 | static inline int migrate_prep(void) { return -ENOSYS; } |
| 35 | 33 | ||
diff --git a/include/linux/mm.h b/include/linux/mm.h index 24c395694f4d..9d65ae4ba0e0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -620,13 +620,22 @@ void page_address_init(void); | |||
| 620 | /* | 620 | /* |
| 621 | * On an anonymous page mapped into a user virtual memory area, | 621 | * On an anonymous page mapped into a user virtual memory area, |
| 622 | * page->mapping points to its anon_vma, not to a struct address_space; | 622 | * page->mapping points to its anon_vma, not to a struct address_space; |
| 623 | * with the PAGE_MAPPING_ANON bit set to distinguish it. | 623 | * with the PAGE_MAPPING_ANON bit set to distinguish it. See rmap.h. |
| 624 | * | ||
| 625 | * On an anonymous page in a VM_MERGEABLE area, if CONFIG_KSM is enabled, | ||
| 626 | * the PAGE_MAPPING_KSM bit may be set along with the PAGE_MAPPING_ANON bit; | ||
| 627 | * and then page->mapping points, not to an anon_vma, but to a private | ||
| 628 | * structure which KSM associates with that merged page. See ksm.h. | ||
| 629 | * | ||
| 630 | * PAGE_MAPPING_KSM without PAGE_MAPPING_ANON is currently never used. | ||
| 624 | * | 631 | * |
| 625 | * Please note that, confusingly, "page_mapping" refers to the inode | 632 | * Please note that, confusingly, "page_mapping" refers to the inode |
| 626 | * address_space which maps the page from disk; whereas "page_mapped" | 633 | * address_space which maps the page from disk; whereas "page_mapped" |
| 627 | * refers to user virtual address space into which the page is mapped. | 634 | * refers to user virtual address space into which the page is mapped. |
| 628 | */ | 635 | */ |
| 629 | #define PAGE_MAPPING_ANON 1 | 636 | #define PAGE_MAPPING_ANON 1 |
| 637 | #define PAGE_MAPPING_KSM 2 | ||
| 638 | #define PAGE_MAPPING_FLAGS (PAGE_MAPPING_ANON | PAGE_MAPPING_KSM) | ||
| 630 | 639 | ||
| 631 | extern struct address_space swapper_space; | 640 | extern struct address_space swapper_space; |
| 632 | static inline struct address_space *page_mapping(struct page *page) | 641 | static inline struct address_space *page_mapping(struct page *page) |
| @@ -634,16 +643,19 @@ static inline struct address_space *page_mapping(struct page *page) | |||
| 634 | struct address_space *mapping = page->mapping; | 643 | struct address_space *mapping = page->mapping; |
| 635 | 644 | ||
| 636 | VM_BUG_ON(PageSlab(page)); | 645 | VM_BUG_ON(PageSlab(page)); |
| 637 | #ifdef CONFIG_SWAP | ||
| 638 | if (unlikely(PageSwapCache(page))) | 646 | if (unlikely(PageSwapCache(page))) |
| 639 | mapping = &swapper_space; | 647 | mapping = &swapper_space; |
| 640 | else | 648 | else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON)) |
| 641 | #endif | ||
| 642 | if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON)) | ||
| 643 | mapping = NULL; | 649 | mapping = NULL; |
| 644 | return mapping; | 650 | return mapping; |
| 645 | } | 651 | } |
| 646 | 652 | ||
| 653 | /* Neutral page->mapping pointer to address_space or anon_vma or other */ | ||
| 654 | static inline void *page_rmapping(struct page *page) | ||
| 655 | { | ||
| 656 | return (void *)((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS); | ||
| 657 | } | ||
| 658 | |||
| 647 | static inline int PageAnon(struct page *page) | 659 | static inline int PageAnon(struct page *page) |
| 648 | { | 660 | { |
| 649 | return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; | 661 | return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; |
| @@ -758,6 +770,7 @@ unsigned long unmap_vmas(struct mmu_gather **tlb, | |||
| 758 | * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry | 770 | * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry |
| 759 | * @pte_entry: if set, called for each non-empty PTE (4th-level) entry | 771 | * @pte_entry: if set, called for each non-empty PTE (4th-level) entry |
| 760 | * @pte_hole: if set, called for each hole at all levels | 772 | * @pte_hole: if set, called for each hole at all levels |
| 773 | * @hugetlb_entry: if set, called for each hugetlb entry | ||
| 761 | * | 774 | * |
| 762 | * (see walk_page_range for more details) | 775 | * (see walk_page_range for more details) |
| 763 | */ | 776 | */ |
| @@ -767,6 +780,8 @@ struct mm_walk { | |||
| 767 | int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, struct mm_walk *); | 780 | int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, struct mm_walk *); |
| 768 | int (*pte_entry)(pte_t *, unsigned long, unsigned long, struct mm_walk *); | 781 | int (*pte_entry)(pte_t *, unsigned long, unsigned long, struct mm_walk *); |
| 769 | int (*pte_hole)(unsigned long, unsigned long, struct mm_walk *); | 782 | int (*pte_hole)(unsigned long, unsigned long, struct mm_walk *); |
| 783 | int (*hugetlb_entry)(pte_t *, unsigned long, unsigned long, | ||
| 784 | struct mm_walk *); | ||
| 770 | struct mm_struct *mm; | 785 | struct mm_struct *mm; |
| 771 | void *private; | 786 | void *private; |
| 772 | }; | 787 | }; |
diff --git a/include/linux/node.h b/include/linux/node.h index 681a697b9a86..06292dac3eab 100644 --- a/include/linux/node.h +++ b/include/linux/node.h | |||
| @@ -21,13 +21,19 @@ | |||
| 21 | 21 | ||
| 22 | #include <linux/sysdev.h> | 22 | #include <linux/sysdev.h> |
| 23 | #include <linux/cpumask.h> | 23 | #include <linux/cpumask.h> |
| 24 | #include <linux/workqueue.h> | ||
| 24 | 25 | ||
| 25 | struct node { | 26 | struct node { |
| 26 | struct sys_device sysdev; | 27 | struct sys_device sysdev; |
| 28 | |||
| 29 | #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HUGETLBFS) | ||
| 30 | struct work_struct node_work; | ||
| 31 | #endif | ||
| 27 | }; | 32 | }; |
| 28 | 33 | ||
| 29 | struct memory_block; | 34 | struct memory_block; |
| 30 | extern struct node node_devices[]; | 35 | extern struct node node_devices[]; |
| 36 | typedef void (*node_registration_func_t)(struct node *); | ||
| 31 | 37 | ||
| 32 | extern int register_node(struct node *, int, struct node *); | 38 | extern int register_node(struct node *, int, struct node *); |
| 33 | extern void unregister_node(struct node *node); | 39 | extern void unregister_node(struct node *node); |
| @@ -39,6 +45,11 @@ extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid); | |||
| 39 | extern int register_mem_sect_under_node(struct memory_block *mem_blk, | 45 | extern int register_mem_sect_under_node(struct memory_block *mem_blk, |
| 40 | int nid); | 46 | int nid); |
| 41 | extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk); | 47 | extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk); |
| 48 | |||
| 49 | #ifdef CONFIG_HUGETLBFS | ||
| 50 | extern void register_hugetlbfs_with_node(node_registration_func_t doregister, | ||
| 51 | node_registration_func_t unregister); | ||
| 52 | #endif | ||
| 42 | #else | 53 | #else |
| 43 | static inline int register_one_node(int nid) | 54 | static inline int register_one_node(int nid) |
| 44 | { | 55 | { |
| @@ -65,6 +76,11 @@ static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) | |||
| 65 | { | 76 | { |
| 66 | return 0; | 77 | return 0; |
| 67 | } | 78 | } |
| 79 | |||
| 80 | static inline void register_hugetlbfs_with_node(node_registration_func_t reg, | ||
| 81 | node_registration_func_t unreg) | ||
| 82 | { | ||
| 83 | } | ||
| 68 | #endif | 84 | #endif |
| 69 | 85 | ||
| 70 | #define to_node(sys_device) container_of(sys_device, struct node, sysdev) | 86 | #define to_node(sys_device) container_of(sys_device, struct node, sysdev) |
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index b359c4a9ec9e..454997cccbd8 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h | |||
| @@ -245,14 +245,19 @@ static inline int __next_node(int n, const nodemask_t *srcp) | |||
| 245 | return min_t(int,MAX_NUMNODES,find_next_bit(srcp->bits, MAX_NUMNODES, n+1)); | 245 | return min_t(int,MAX_NUMNODES,find_next_bit(srcp->bits, MAX_NUMNODES, n+1)); |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | static inline void init_nodemask_of_node(nodemask_t *mask, int node) | ||
| 249 | { | ||
| 250 | nodes_clear(*mask); | ||
| 251 | node_set(node, *mask); | ||
| 252 | } | ||
| 253 | |||
| 248 | #define nodemask_of_node(node) \ | 254 | #define nodemask_of_node(node) \ |
| 249 | ({ \ | 255 | ({ \ |
| 250 | typeof(_unused_nodemask_arg_) m; \ | 256 | typeof(_unused_nodemask_arg_) m; \ |
| 251 | if (sizeof(m) == sizeof(unsigned long)) { \ | 257 | if (sizeof(m) == sizeof(unsigned long)) { \ |
| 252 | m.bits[0] = 1UL<<(node); \ | 258 | m.bits[0] = 1UL << (node); \ |
| 253 | } else { \ | 259 | } else { \ |
| 254 | nodes_clear(m); \ | 260 | init_nodemask_of_node(&m, (node)); \ |
| 255 | node_set((node), m); \ | ||
| 256 | } \ | 261 | } \ |
| 257 | m; \ | 262 | m; \ |
| 258 | }) | 263 | }) |
| @@ -480,15 +485,17 @@ static inline int num_node_state(enum node_states state) | |||
| 480 | #define for_each_online_node(node) for_each_node_state(node, N_ONLINE) | 485 | #define for_each_online_node(node) for_each_node_state(node, N_ONLINE) |
| 481 | 486 | ||
| 482 | /* | 487 | /* |
| 483 | * For nodemask scrach area.(See CPUMASK_ALLOC() in cpumask.h) | 488 | * For nodemask scrach area. |
| 489 | * NODEMASK_ALLOC(type, name) allocates an object with a specified type and | ||
| 490 | * name. | ||
| 484 | */ | 491 | */ |
| 485 | 492 | #if NODES_SHIFT > 8 /* nodemask_t > 256 bytes */ | |
| 486 | #if NODES_SHIFT > 8 /* nodemask_t > 64 bytes */ | 493 | #define NODEMASK_ALLOC(type, name, gfp_flags) \ |
| 487 | #define NODEMASK_ALLOC(x, m) struct x *m = kmalloc(sizeof(*m), GFP_KERNEL) | 494 | type *name = kmalloc(sizeof(*name), gfp_flags) |
| 488 | #define NODEMASK_FREE(m) kfree(m) | 495 | #define NODEMASK_FREE(m) kfree(m) |
| 489 | #else | 496 | #else |
| 490 | #define NODEMASK_ALLOC(x, m) struct x _m, *m = &_m | 497 | #define NODEMASK_ALLOC(type, name, gfp_flags) type _name, *name = &_name |
| 491 | #define NODEMASK_FREE(m) | 498 | #define NODEMASK_FREE(m) do {} while (0) |
| 492 | #endif | 499 | #endif |
| 493 | 500 | ||
| 494 | /* A example struture for using NODEMASK_ALLOC, used in mempolicy. */ | 501 | /* A example struture for using NODEMASK_ALLOC, used in mempolicy. */ |
| @@ -497,8 +504,10 @@ struct nodemask_scratch { | |||
| 497 | nodemask_t mask2; | 504 | nodemask_t mask2; |
| 498 | }; | 505 | }; |
| 499 | 506 | ||
| 500 | #define NODEMASK_SCRATCH(x) NODEMASK_ALLOC(nodemask_scratch, x) | 507 | #define NODEMASK_SCRATCH(x) \ |
| 501 | #define NODEMASK_SCRATCH_FREE(x) NODEMASK_FREE(x) | 508 | NODEMASK_ALLOC(struct nodemask_scratch, x, \ |
| 509 | GFP_KERNEL | __GFP_NORETRY) | ||
| 510 | #define NODEMASK_SCRATCH_FREE(x) NODEMASK_FREE(x) | ||
| 502 | 511 | ||
| 503 | 512 | ||
| 504 | #endif /* __LINUX_NODEMASK_H */ | 513 | #endif /* __LINUX_NODEMASK_H */ |
diff --git a/include/linux/numa.h b/include/linux/numa.h index a31a7301b159..3aaa31603a86 100644 --- a/include/linux/numa.h +++ b/include/linux/numa.h | |||
| @@ -10,4 +10,6 @@ | |||
| 10 | 10 | ||
| 11 | #define MAX_NUMNODES (1 << NODES_SHIFT) | 11 | #define MAX_NUMNODES (1 << NODES_SHIFT) |
| 12 | 12 | ||
| 13 | #define NUMA_NO_NODE (-1) | ||
| 14 | |||
| 13 | #endif /* _LINUX_NUMA_H */ | 15 | #endif /* _LINUX_NUMA_H */ |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 6b202b173955..49e907bd067f 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
| @@ -99,7 +99,7 @@ enum pageflags { | |||
| 99 | PG_buddy, /* Page is free, on buddy lists */ | 99 | PG_buddy, /* Page is free, on buddy lists */ |
| 100 | PG_swapbacked, /* Page is backed by RAM/swap */ | 100 | PG_swapbacked, /* Page is backed by RAM/swap */ |
| 101 | PG_unevictable, /* Page is "unevictable" */ | 101 | PG_unevictable, /* Page is "unevictable" */ |
| 102 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | 102 | #ifdef CONFIG_MMU |
| 103 | PG_mlocked, /* Page is vma mlocked */ | 103 | PG_mlocked, /* Page is vma mlocked */ |
| 104 | #endif | 104 | #endif |
| 105 | #ifdef CONFIG_ARCH_USES_PG_UNCACHED | 105 | #ifdef CONFIG_ARCH_USES_PG_UNCACHED |
| @@ -259,12 +259,10 @@ PAGEFLAG_FALSE(SwapCache) | |||
| 259 | PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable) | 259 | PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable) |
| 260 | TESTCLEARFLAG(Unevictable, unevictable) | 260 | TESTCLEARFLAG(Unevictable, unevictable) |
| 261 | 261 | ||
| 262 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | 262 | #ifdef CONFIG_MMU |
| 263 | #define MLOCK_PAGES 1 | ||
| 264 | PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked) | 263 | PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked) |
| 265 | TESTSCFLAG(Mlocked, mlocked) __TESTCLEARFLAG(Mlocked, mlocked) | 264 | TESTSCFLAG(Mlocked, mlocked) __TESTCLEARFLAG(Mlocked, mlocked) |
| 266 | #else | 265 | #else |
| 267 | #define MLOCK_PAGES 0 | ||
| 268 | PAGEFLAG_FALSE(Mlocked) SETPAGEFLAG_NOOP(Mlocked) | 266 | PAGEFLAG_FALSE(Mlocked) SETPAGEFLAG_NOOP(Mlocked) |
| 269 | TESTCLEARFLAG_FALSE(Mlocked) __TESTCLEARFLAG_FALSE(Mlocked) | 267 | TESTCLEARFLAG_FALSE(Mlocked) __TESTCLEARFLAG_FALSE(Mlocked) |
| 270 | #endif | 268 | #endif |
| @@ -393,7 +391,7 @@ static inline void __ClearPageTail(struct page *page) | |||
| 393 | 391 | ||
| 394 | #endif /* !PAGEFLAGS_EXTENDED */ | 392 | #endif /* !PAGEFLAGS_EXTENDED */ |
| 395 | 393 | ||
| 396 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | 394 | #ifdef CONFIG_MMU |
| 397 | #define __PG_MLOCKED (1 << PG_mlocked) | 395 | #define __PG_MLOCKED (1 << PG_mlocked) |
| 398 | #else | 396 | #else |
| 399 | #define __PG_MLOCKED 0 | 397 | #define __PG_MLOCKED 0 |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 0d65934246af..198b8f9fe05e 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
| @@ -219,7 +219,7 @@ struct dev_pm_ops { | |||
| 219 | * to RAM and hibernation. | 219 | * to RAM and hibernation. |
| 220 | */ | 220 | */ |
| 221 | #define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ | 221 | #define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ |
| 222 | struct dev_pm_ops name = { \ | 222 | const struct dev_pm_ops name = { \ |
| 223 | .suspend = suspend_fn, \ | 223 | .suspend = suspend_fn, \ |
| 224 | .resume = resume_fn, \ | 224 | .resume = resume_fn, \ |
| 225 | .freeze = suspend_fn, \ | 225 | .freeze = suspend_fn, \ |
diff --git a/include/linux/rmap.h b/include/linux/rmap.h index cb0ba7032609..b019ae64e2ab 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h | |||
| @@ -26,6 +26,9 @@ | |||
| 26 | */ | 26 | */ |
| 27 | struct anon_vma { | 27 | struct anon_vma { |
| 28 | spinlock_t lock; /* Serialize access to vma list */ | 28 | spinlock_t lock; /* Serialize access to vma list */ |
| 29 | #ifdef CONFIG_KSM | ||
| 30 | atomic_t ksm_refcount; | ||
| 31 | #endif | ||
| 29 | /* | 32 | /* |
| 30 | * NOTE: the LSB of the head.next is set by | 33 | * NOTE: the LSB of the head.next is set by |
| 31 | * mm_take_all_locks() _after_ taking the above lock. So the | 34 | * mm_take_all_locks() _after_ taking the above lock. So the |
| @@ -38,6 +41,34 @@ struct anon_vma { | |||
| 38 | }; | 41 | }; |
| 39 | 42 | ||
| 40 | #ifdef CONFIG_MMU | 43 | #ifdef CONFIG_MMU |
| 44 | #ifdef CONFIG_KSM | ||
| 45 | static inline void ksm_refcount_init(struct anon_vma *anon_vma) | ||
| 46 | { | ||
| 47 | atomic_set(&anon_vma->ksm_refcount, 0); | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline int ksm_refcount(struct anon_vma *anon_vma) | ||
| 51 | { | ||
| 52 | return atomic_read(&anon_vma->ksm_refcount); | ||
| 53 | } | ||
| 54 | #else | ||
| 55 | static inline void ksm_refcount_init(struct anon_vma *anon_vma) | ||
| 56 | { | ||
| 57 | } | ||
| 58 | |||
| 59 | static inline int ksm_refcount(struct anon_vma *anon_vma) | ||
| 60 | { | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | #endif /* CONFIG_KSM */ | ||
| 64 | |||
| 65 | static inline struct anon_vma *page_anon_vma(struct page *page) | ||
| 66 | { | ||
| 67 | if (((unsigned long)page->mapping & PAGE_MAPPING_FLAGS) != | ||
| 68 | PAGE_MAPPING_ANON) | ||
| 69 | return NULL; | ||
| 70 | return page_rmapping(page); | ||
| 71 | } | ||
| 41 | 72 | ||
| 42 | static inline void anon_vma_lock(struct vm_area_struct *vma) | 73 | static inline void anon_vma_lock(struct vm_area_struct *vma) |
| 43 | { | 74 | { |
| @@ -62,6 +93,7 @@ void __anon_vma_merge(struct vm_area_struct *, struct vm_area_struct *); | |||
| 62 | void anon_vma_unlink(struct vm_area_struct *); | 93 | void anon_vma_unlink(struct vm_area_struct *); |
| 63 | void anon_vma_link(struct vm_area_struct *); | 94 | void anon_vma_link(struct vm_area_struct *); |
| 64 | void __anon_vma_link(struct vm_area_struct *); | 95 | void __anon_vma_link(struct vm_area_struct *); |
| 96 | void anon_vma_free(struct anon_vma *); | ||
| 65 | 97 | ||
| 66 | /* | 98 | /* |
| 67 | * rmap interfaces called when adding or removing pte of page | 99 | * rmap interfaces called when adding or removing pte of page |
| @@ -81,6 +113,9 @@ static inline void page_dup_rmap(struct page *page) | |||
| 81 | */ | 113 | */ |
| 82 | int page_referenced(struct page *, int is_locked, | 114 | int page_referenced(struct page *, int is_locked, |
| 83 | struct mem_cgroup *cnt, unsigned long *vm_flags); | 115 | struct mem_cgroup *cnt, unsigned long *vm_flags); |
| 116 | int page_referenced_one(struct page *, struct vm_area_struct *, | ||
| 117 | unsigned long address, unsigned int *mapcount, unsigned long *vm_flags); | ||
| 118 | |||
| 84 | enum ttu_flags { | 119 | enum ttu_flags { |
| 85 | TTU_UNMAP = 0, /* unmap mode */ | 120 | TTU_UNMAP = 0, /* unmap mode */ |
| 86 | TTU_MIGRATION = 1, /* migration mode */ | 121 | TTU_MIGRATION = 1, /* migration mode */ |
| @@ -94,6 +129,8 @@ enum ttu_flags { | |||
| 94 | #define TTU_ACTION(x) ((x) & TTU_ACTION_MASK) | 129 | #define TTU_ACTION(x) ((x) & TTU_ACTION_MASK) |
| 95 | 130 | ||
| 96 | int try_to_unmap(struct page *, enum ttu_flags flags); | 131 | int try_to_unmap(struct page *, enum ttu_flags flags); |
| 132 | int try_to_unmap_one(struct page *, struct vm_area_struct *, | ||
| 133 | unsigned long address, enum ttu_flags flags); | ||
| 97 | 134 | ||
| 98 | /* | 135 | /* |
| 99 | * Called from mm/filemap_xip.c to unmap empty zero page | 136 | * Called from mm/filemap_xip.c to unmap empty zero page |
| @@ -127,6 +164,12 @@ struct anon_vma *page_lock_anon_vma(struct page *page); | |||
| 127 | void page_unlock_anon_vma(struct anon_vma *anon_vma); | 164 | void page_unlock_anon_vma(struct anon_vma *anon_vma); |
| 128 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); | 165 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); |
| 129 | 166 | ||
| 167 | /* | ||
| 168 | * Called by migrate.c to remove migration ptes, but might be used more later. | ||
| 169 | */ | ||
| 170 | int rmap_walk(struct page *page, int (*rmap_one)(struct page *, | ||
| 171 | struct vm_area_struct *, unsigned long, void *), void *arg); | ||
| 172 | |||
| 130 | #else /* !CONFIG_MMU */ | 173 | #else /* !CONFIG_MMU */ |
| 131 | 174 | ||
| 132 | #define anon_vma_init() do {} while (0) | 175 | #define anon_vma_init() do {} while (0) |
diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h index 6c3c0f6c261f..bdfcc2527970 100644 --- a/include/linux/rwsem-spinlock.h +++ b/include/linux/rwsem-spinlock.h | |||
| @@ -68,11 +68,7 @@ extern int __down_write_trylock(struct rw_semaphore *sem); | |||
| 68 | extern void __up_read(struct rw_semaphore *sem); | 68 | extern void __up_read(struct rw_semaphore *sem); |
| 69 | extern void __up_write(struct rw_semaphore *sem); | 69 | extern void __up_write(struct rw_semaphore *sem); |
| 70 | extern void __downgrade_write(struct rw_semaphore *sem); | 70 | extern void __downgrade_write(struct rw_semaphore *sem); |
| 71 | 71 | extern int rwsem_is_locked(struct rw_semaphore *sem); | |
| 72 | static inline int rwsem_is_locked(struct rw_semaphore *sem) | ||
| 73 | { | ||
| 74 | return (sem->activity != 0); | ||
| 75 | } | ||
| 76 | 72 | ||
| 77 | #endif /* __KERNEL__ */ | 73 | #endif /* __KERNEL__ */ |
| 78 | #endif /* _LINUX_RWSEM_SPINLOCK_H */ | 74 | #endif /* _LINUX_RWSEM_SPINLOCK_H */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 294eb2f80144..7d388494f45d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1446,8 +1446,10 @@ struct task_struct { | |||
| 1446 | gfp_t lockdep_reclaim_gfp; | 1446 | gfp_t lockdep_reclaim_gfp; |
| 1447 | #endif | 1447 | #endif |
| 1448 | 1448 | ||
| 1449 | #ifdef CONFIG_FS_JOURNAL_INFO | ||
| 1449 | /* journalling filesystem info */ | 1450 | /* journalling filesystem info */ |
| 1450 | void *journal_info; | 1451 | void *journal_info; |
| 1452 | #endif | ||
| 1451 | 1453 | ||
| 1452 | /* stacked block device info */ | 1454 | /* stacked block device info */ |
| 1453 | struct bio *bio_list, **bio_tail; | 1455 | struct bio *bio_list, **bio_tail; |
diff --git a/include/linux/string.h b/include/linux/string.h index b8508868d5ad..651839a2a755 100644 --- a/include/linux/string.h +++ b/include/linux/string.h | |||
| @@ -62,7 +62,15 @@ extern char * strnchr(const char *, size_t, int); | |||
| 62 | #ifndef __HAVE_ARCH_STRRCHR | 62 | #ifndef __HAVE_ARCH_STRRCHR |
| 63 | extern char * strrchr(const char *,int); | 63 | extern char * strrchr(const char *,int); |
| 64 | #endif | 64 | #endif |
| 65 | extern char * __must_check strstrip(char *); | 65 | extern char * __must_check skip_spaces(const char *); |
| 66 | |||
| 67 | extern char *strim(char *); | ||
| 68 | |||
| 69 | static inline __must_check char *strstrip(char *str) | ||
| 70 | { | ||
| 71 | return strim(str); | ||
| 72 | } | ||
| 73 | |||
| 66 | #ifndef __HAVE_ARCH_STRSTR | 74 | #ifndef __HAVE_ARCH_STRSTR |
| 67 | extern char * strstr(const char *,const char *); | 75 | extern char * strstr(const char *,const char *); |
| 68 | #endif | 76 | #endif |
diff --git a/include/linux/swap.h b/include/linux/swap.h index 4ec90019c1a4..a2602a8207a6 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
| @@ -145,38 +145,43 @@ enum { | |||
| 145 | SWP_DISCARDABLE = (1 << 2), /* blkdev supports discard */ | 145 | SWP_DISCARDABLE = (1 << 2), /* blkdev supports discard */ |
| 146 | SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */ | 146 | SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */ |
| 147 | SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ | 147 | SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ |
| 148 | SWP_CONTINUED = (1 << 5), /* swap_map has count continuation */ | ||
| 148 | /* add others here before... */ | 149 | /* add others here before... */ |
| 149 | SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */ | 150 | SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */ |
| 150 | }; | 151 | }; |
| 151 | 152 | ||
| 152 | #define SWAP_CLUSTER_MAX 32 | 153 | #define SWAP_CLUSTER_MAX 32 |
| 153 | 154 | ||
| 154 | #define SWAP_MAP_MAX 0x7ffe | 155 | #define SWAP_MAP_MAX 0x3e /* Max duplication count, in first swap_map */ |
| 155 | #define SWAP_MAP_BAD 0x7fff | 156 | #define SWAP_MAP_BAD 0x3f /* Note pageblock is bad, in first swap_map */ |
| 156 | #define SWAP_HAS_CACHE 0x8000 /* There is a swap cache of entry. */ | 157 | #define SWAP_HAS_CACHE 0x40 /* Flag page is cached, in first swap_map */ |
| 157 | #define SWAP_COUNT_MASK (~SWAP_HAS_CACHE) | 158 | #define SWAP_CONT_MAX 0x7f /* Max count, in each swap_map continuation */ |
| 159 | #define COUNT_CONTINUED 0x80 /* See swap_map continuation for full count */ | ||
| 160 | #define SWAP_MAP_SHMEM 0xbf /* Owned by shmem/tmpfs, in first swap_map */ | ||
| 161 | |||
| 158 | /* | 162 | /* |
| 159 | * The in-memory structure used to track swap areas. | 163 | * The in-memory structure used to track swap areas. |
| 160 | */ | 164 | */ |
| 161 | struct swap_info_struct { | 165 | struct swap_info_struct { |
| 162 | unsigned long flags; | 166 | unsigned long flags; /* SWP_USED etc: see above */ |
| 163 | int prio; /* swap priority */ | 167 | signed short prio; /* swap priority of this type */ |
| 164 | int next; /* next entry on swap list */ | 168 | signed char type; /* strange name for an index */ |
| 165 | struct file *swap_file; | 169 | signed char next; /* next type on the swap list */ |
| 166 | struct block_device *bdev; | 170 | unsigned int max; /* extent of the swap_map */ |
| 167 | struct list_head extent_list; | 171 | unsigned char *swap_map; /* vmalloc'ed array of usage counts */ |
| 168 | struct swap_extent *curr_swap_extent; | 172 | unsigned int lowest_bit; /* index of first free in swap_map */ |
| 169 | unsigned short *swap_map; | 173 | unsigned int highest_bit; /* index of last free in swap_map */ |
| 170 | unsigned int lowest_bit; | 174 | unsigned int pages; /* total of usable pages of swap */ |
| 171 | unsigned int highest_bit; | 175 | unsigned int inuse_pages; /* number of those currently in use */ |
| 176 | unsigned int cluster_next; /* likely index for next allocation */ | ||
| 177 | unsigned int cluster_nr; /* countdown to next cluster search */ | ||
| 172 | unsigned int lowest_alloc; /* while preparing discard cluster */ | 178 | unsigned int lowest_alloc; /* while preparing discard cluster */ |
| 173 | unsigned int highest_alloc; /* while preparing discard cluster */ | 179 | unsigned int highest_alloc; /* while preparing discard cluster */ |
| 174 | unsigned int cluster_next; | 180 | struct swap_extent *curr_swap_extent; |
| 175 | unsigned int cluster_nr; | 181 | struct swap_extent first_swap_extent; |
| 176 | unsigned int pages; | 182 | struct block_device *bdev; /* swap device or bdev of swap file */ |
| 177 | unsigned int max; | 183 | struct file *swap_file; /* seldom referenced */ |
| 178 | unsigned int inuse_pages; | 184 | unsigned int old_block_size; /* seldom referenced */ |
| 179 | unsigned int old_block_size; | ||
| 180 | }; | 185 | }; |
| 181 | 186 | ||
| 182 | struct swap_list_t { | 187 | struct swap_list_t { |
| @@ -273,6 +278,7 @@ extern int scan_unevictable_register_node(struct node *node); | |||
| 273 | extern void scan_unevictable_unregister_node(struct node *node); | 278 | extern void scan_unevictable_unregister_node(struct node *node); |
| 274 | 279 | ||
| 275 | extern int kswapd_run(int nid); | 280 | extern int kswapd_run(int nid); |
| 281 | extern void kswapd_stop(int nid); | ||
| 276 | 282 | ||
| 277 | #ifdef CONFIG_MMU | 283 | #ifdef CONFIG_MMU |
| 278 | /* linux/mm/shmem.c */ | 284 | /* linux/mm/shmem.c */ |
| @@ -309,17 +315,18 @@ extern long total_swap_pages; | |||
| 309 | extern void si_swapinfo(struct sysinfo *); | 315 | extern void si_swapinfo(struct sysinfo *); |
| 310 | extern swp_entry_t get_swap_page(void); | 316 | extern swp_entry_t get_swap_page(void); |
| 311 | extern swp_entry_t get_swap_page_of_type(int); | 317 | extern swp_entry_t get_swap_page_of_type(int); |
| 312 | extern void swap_duplicate(swp_entry_t); | ||
| 313 | extern int swapcache_prepare(swp_entry_t); | ||
| 314 | extern int valid_swaphandles(swp_entry_t, unsigned long *); | 318 | extern int valid_swaphandles(swp_entry_t, unsigned long *); |
| 319 | extern int add_swap_count_continuation(swp_entry_t, gfp_t); | ||
| 320 | extern void swap_shmem_alloc(swp_entry_t); | ||
| 321 | extern int swap_duplicate(swp_entry_t); | ||
| 322 | extern int swapcache_prepare(swp_entry_t); | ||
| 315 | extern void swap_free(swp_entry_t); | 323 | extern void swap_free(swp_entry_t); |
| 316 | extern void swapcache_free(swp_entry_t, struct page *page); | 324 | extern void swapcache_free(swp_entry_t, struct page *page); |
| 317 | extern int free_swap_and_cache(swp_entry_t); | 325 | extern int free_swap_and_cache(swp_entry_t); |
| 318 | extern int swap_type_of(dev_t, sector_t, struct block_device **); | 326 | extern int swap_type_of(dev_t, sector_t, struct block_device **); |
| 319 | extern unsigned int count_swap_pages(int, int); | 327 | extern unsigned int count_swap_pages(int, int); |
| 320 | extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t); | 328 | extern sector_t map_swap_page(struct page *, struct block_device **); |
| 321 | extern sector_t swapdev_block(int, pgoff_t); | 329 | extern sector_t swapdev_block(int, pgoff_t); |
| 322 | extern struct swap_info_struct *get_swap_info_struct(unsigned); | ||
| 323 | extern int reuse_swap_page(struct page *); | 330 | extern int reuse_swap_page(struct page *); |
| 324 | extern int try_to_free_swap(struct page *); | 331 | extern int try_to_free_swap(struct page *); |
| 325 | struct backing_dev_info; | 332 | struct backing_dev_info; |
| @@ -384,8 +391,18 @@ static inline void show_swap_cache_info(void) | |||
| 384 | #define free_swap_and_cache(swp) is_migration_entry(swp) | 391 | #define free_swap_and_cache(swp) is_migration_entry(swp) |
| 385 | #define swapcache_prepare(swp) is_migration_entry(swp) | 392 | #define swapcache_prepare(swp) is_migration_entry(swp) |
| 386 | 393 | ||
| 387 | static inline void swap_duplicate(swp_entry_t swp) | 394 | static inline int add_swap_count_continuation(swp_entry_t swp, gfp_t gfp_mask) |
| 388 | { | 395 | { |
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static inline void swap_shmem_alloc(swp_entry_t swp) | ||
| 400 | { | ||
| 401 | } | ||
| 402 | |||
| 403 | static inline int swap_duplicate(swp_entry_t swp) | ||
| 404 | { | ||
| 405 | return 0; | ||
| 389 | } | 406 | } |
| 390 | 407 | ||
| 391 | static inline void swap_free(swp_entry_t swp) | 408 | static inline void swap_free(swp_entry_t swp) |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 405a9035fe40..ef3a2947b102 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -350,8 +350,6 @@ extern void tty_write_flush(struct tty_struct *); | |||
| 350 | 350 | ||
| 351 | extern struct ktermios tty_std_termios; | 351 | extern struct ktermios tty_std_termios; |
| 352 | 352 | ||
| 353 | extern int kmsg_redirect; | ||
| 354 | |||
| 355 | extern void console_init(void); | 353 | extern void console_init(void); |
| 356 | extern int vcs_init(void); | 354 | extern int vcs_init(void); |
| 357 | 355 | ||
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index d85889710f9b..ee03bba9c5df 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h | |||
| @@ -40,6 +40,8 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, | |||
| 40 | PGSCAN_ZONE_RECLAIM_FAILED, | 40 | PGSCAN_ZONE_RECLAIM_FAILED, |
| 41 | #endif | 41 | #endif |
| 42 | PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL, | 42 | PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL, |
| 43 | KSWAPD_LOW_WMARK_HIT_QUICKLY, KSWAPD_HIGH_WMARK_HIT_QUICKLY, | ||
| 44 | KSWAPD_SKIP_CONGESTION_WAIT, | ||
| 43 | PAGEOUTRUN, ALLOCSTALL, PGROTATED, | 45 | PAGEOUTRUN, ALLOCSTALL, PGROTATED, |
| 44 | #ifdef CONFIG_HUGETLB_PAGE | 46 | #ifdef CONFIG_HUGETLB_PAGE |
| 45 | HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL, | 47 | HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL, |
diff --git a/include/linux/vt.h b/include/linux/vt.h index 7ffa11f06232..3fb9944e50a6 100644 --- a/include/linux/vt.h +++ b/include/linux/vt.h | |||
| @@ -84,4 +84,19 @@ struct vt_setactivate { | |||
| 84 | 84 | ||
| 85 | #define VT_SETACTIVATE 0x560F /* Activate and set the mode of a console */ | 85 | #define VT_SETACTIVATE 0x560F /* Activate and set the mode of a console */ |
| 86 | 86 | ||
| 87 | #ifdef CONFIG_VT_CONSOLE | ||
| 88 | |||
| 89 | extern int vt_kmsg_redirect(int new); | ||
| 90 | |||
| 91 | #else | ||
| 92 | |||
| 93 | static inline int vt_kmsg_redirect(int new) | ||
| 94 | { | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | #endif | ||
| 99 | |||
| 100 | #define vt_get_kmsg_redirect() vt_kmsg_redirect(-1) | ||
| 101 | |||
| 87 | #endif /* _LINUX_VT_H */ | 102 | #endif /* _LINUX_VT_H */ |
diff --git a/init/Kconfig b/init/Kconfig index 54c655ce9c04..a23da9f01803 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
| @@ -1079,6 +1079,28 @@ config SLOB | |||
| 1079 | 1079 | ||
| 1080 | endchoice | 1080 | endchoice |
| 1081 | 1081 | ||
| 1082 | config MMAP_ALLOW_UNINITIALIZED | ||
| 1083 | bool "Allow mmapped anonymous memory to be uninitialized" | ||
| 1084 | depends on EMBEDDED && !MMU | ||
| 1085 | default n | ||
| 1086 | help | ||
| 1087 | Normally, and according to the Linux spec, anonymous memory obtained | ||
| 1088 | from mmap() has it's contents cleared before it is passed to | ||
| 1089 | userspace. Enabling this config option allows you to request that | ||
| 1090 | mmap() skip that if it is given an MAP_UNINITIALIZED flag, thus | ||
| 1091 | providing a huge performance boost. If this option is not enabled, | ||
| 1092 | then the flag will be ignored. | ||
| 1093 | |||
| 1094 | This is taken advantage of by uClibc's malloc(), and also by | ||
| 1095 | ELF-FDPIC binfmt's brk and stack allocator. | ||
| 1096 | |||
| 1097 | Because of the obvious security issues, this option should only be | ||
| 1098 | enabled on embedded devices where you control what is run in | ||
| 1099 | userspace. Since that isn't generally a problem on no-MMU systems, | ||
| 1100 | it is normally safe to say Y here. | ||
| 1101 | |||
| 1102 | See Documentation/nommu-mmap.txt for more information. | ||
| 1103 | |||
| 1082 | config PROFILING | 1104 | config PROFILING |
| 1083 | bool "Profiling support (EXPERIMENTAL)" | 1105 | bool "Profiling support (EXPERIMENTAL)" |
| 1084 | help | 1106 | help |
diff --git a/init/main.c b/init/main.c index 4051d75dd2d6..c3db4a98b369 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -691,10 +691,10 @@ asmlinkage void __init start_kernel(void) | |||
| 691 | static void __init do_ctors(void) | 691 | static void __init do_ctors(void) |
| 692 | { | 692 | { |
| 693 | #ifdef CONFIG_CONSTRUCTORS | 693 | #ifdef CONFIG_CONSTRUCTORS |
| 694 | ctor_fn_t *call = (ctor_fn_t *) __ctors_start; | 694 | ctor_fn_t *fn = (ctor_fn_t *) __ctors_start; |
| 695 | 695 | ||
| 696 | for (; call < (ctor_fn_t *) __ctors_end; call++) | 696 | for (; fn < (ctor_fn_t *) __ctors_end; fn++) |
| 697 | (*call)(); | 697 | (*fn)(); |
| 698 | #endif | 698 | #endif |
| 699 | } | 699 | } |
| 700 | 700 | ||
| @@ -755,10 +755,10 @@ extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; | |||
| 755 | 755 | ||
| 756 | static void __init do_initcalls(void) | 756 | static void __init do_initcalls(void) |
| 757 | { | 757 | { |
| 758 | initcall_t *call; | 758 | initcall_t *fn; |
| 759 | 759 | ||
| 760 | for (call = __early_initcall_end; call < __initcall_end; call++) | 760 | for (fn = __early_initcall_end; fn < __initcall_end; fn++) |
| 761 | do_one_initcall(*call); | 761 | do_one_initcall(*fn); |
| 762 | 762 | ||
| 763 | /* Make sure there is no pending stuff from the initcall sequence */ | 763 | /* Make sure there is no pending stuff from the initcall sequence */ |
| 764 | flush_scheduled_work(); | 764 | flush_scheduled_work(); |
| @@ -785,10 +785,10 @@ static void __init do_basic_setup(void) | |||
| 785 | 785 | ||
| 786 | static void __init do_pre_smp_initcalls(void) | 786 | static void __init do_pre_smp_initcalls(void) |
| 787 | { | 787 | { |
| 788 | initcall_t *call; | 788 | initcall_t *fn; |
| 789 | 789 | ||
| 790 | for (call = __initcall_start; call < __early_initcall_end; call++) | 790 | for (fn = __initcall_start; fn < __early_initcall_end; fn++) |
| 791 | do_one_initcall(*call); | 791 | do_one_initcall(*fn); |
| 792 | } | 792 | } |
| 793 | 793 | ||
| 794 | static void run_init_process(char *init_filename) | 794 | static void run_init_process(char *init_filename) |
diff --git a/kernel/acct.c b/kernel/acct.c index 9a4715a2f6bf..a6605ca921b6 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
| @@ -536,7 +536,8 @@ static void do_acct_process(struct bsd_acct_struct *acct, | |||
| 536 | do_div(elapsed, AHZ); | 536 | do_div(elapsed, AHZ); |
| 537 | ac.ac_btime = get_seconds() - elapsed; | 537 | ac.ac_btime = get_seconds() - elapsed; |
| 538 | /* we really need to bite the bullet and change layout */ | 538 | /* we really need to bite the bullet and change layout */ |
| 539 | current_uid_gid(&ac.ac_uid, &ac.ac_gid); | 539 | ac.ac_uid = orig_cred->uid; |
| 540 | ac.ac_gid = orig_cred->gid; | ||
| 540 | #if ACCT_VERSION==2 | 541 | #if ACCT_VERSION==2 |
| 541 | ac.ac_ahz = AHZ; | 542 | ac.ac_ahz = AHZ; |
| 542 | #endif | 543 | #endif |
diff --git a/kernel/params.c b/kernel/params.c index d656c276508d..cf1b69183127 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
| 27 | #include <linux/string.h> | ||
| 27 | 28 | ||
| 28 | #if 0 | 29 | #if 0 |
| 29 | #define DEBUGP printk | 30 | #define DEBUGP printk |
| @@ -122,9 +123,7 @@ static char *next_arg(char *args, char **param, char **val) | |||
| 122 | next = args + i; | 123 | next = args + i; |
| 123 | 124 | ||
| 124 | /* Chew up trailing spaces. */ | 125 | /* Chew up trailing spaces. */ |
| 125 | while (isspace(*next)) | 126 | return skip_spaces(next); |
| 126 | next++; | ||
| 127 | return next; | ||
| 128 | } | 127 | } |
| 129 | 128 | ||
| 130 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ | 129 | /* Args looks like "foo=bar,bar2 baz=fuz wiz". */ |
| @@ -139,8 +138,7 @@ int parse_args(const char *name, | |||
| 139 | DEBUGP("Parsing ARGS: %s\n", args); | 138 | DEBUGP("Parsing ARGS: %s\n", args); |
| 140 | 139 | ||
| 141 | /* Chew leading spaces */ | 140 | /* Chew leading spaces */ |
| 142 | while (isspace(*args)) | 141 | args = skip_spaces(args); |
| 143 | args++; | ||
| 144 | 142 | ||
| 145 | while (*args) { | 143 | while (*args) { |
| 146 | int ret; | 144 | int ret; |
diff --git a/kernel/power/console.c b/kernel/power/console.c index 5187136fe1de..218e5af90156 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <linux/vt_kern.h> | 7 | #include <linux/vt_kern.h> |
| 8 | #include <linux/kbd_kern.h> | 8 | #include <linux/kbd_kern.h> |
| 9 | #include <linux/console.h> | 9 | #include <linux/vt.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include "power.h" | 11 | #include "power.h" |
| 12 | 12 | ||
| @@ -21,8 +21,7 @@ int pm_prepare_console(void) | |||
| 21 | if (orig_fgconsole < 0) | 21 | if (orig_fgconsole < 0) |
| 22 | return 1; | 22 | return 1; |
| 23 | 23 | ||
| 24 | orig_kmsg = kmsg_redirect; | 24 | orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE); |
| 25 | kmsg_redirect = SUSPEND_CONSOLE; | ||
| 26 | return 0; | 25 | return 0; |
| 27 | } | 26 | } |
| 28 | 27 | ||
| @@ -30,7 +29,7 @@ void pm_restore_console(void) | |||
| 30 | { | 29 | { |
| 31 | if (orig_fgconsole >= 0) { | 30 | if (orig_fgconsole >= 0) { |
| 32 | vt_move_to_console(orig_fgconsole, 0); | 31 | vt_move_to_console(orig_fgconsole, 0); |
| 33 | kmsg_redirect = orig_kmsg; | 32 | vt_kmsg_redirect(orig_kmsg); |
| 34 | } | 33 | } |
| 35 | } | 34 | } |
| 36 | #endif | 35 | #endif |
diff --git a/kernel/smp.c b/kernel/smp.c index a8c76069cf50..00a1d0ede532 100644 --- a/kernel/smp.c +++ b/kernel/smp.c | |||
| @@ -171,7 +171,7 @@ void generic_exec_single(int cpu, struct call_single_data *data, int wait) | |||
| 171 | void generic_smp_call_function_interrupt(void) | 171 | void generic_smp_call_function_interrupt(void) |
| 172 | { | 172 | { |
| 173 | struct call_function_data *data; | 173 | struct call_function_data *data; |
| 174 | int cpu = get_cpu(); | 174 | int cpu = smp_processor_id(); |
| 175 | 175 | ||
| 176 | /* | 176 | /* |
| 177 | * Shouldn't receive this interrupt on a cpu that is not yet online. | 177 | * Shouldn't receive this interrupt on a cpu that is not yet online. |
| @@ -212,7 +212,6 @@ void generic_smp_call_function_interrupt(void) | |||
| 212 | csd_unlock(&data->csd); | 212 | csd_unlock(&data->csd); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | put_cpu(); | ||
| 216 | } | 215 | } |
| 217 | 216 | ||
| 218 | /* | 217 | /* |
diff --git a/kernel/sys.c b/kernel/sys.c index 585d6cd10040..20ccfb5da6af 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -189,10 +189,10 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
| 189 | !(user = find_user(who))) | 189 | !(user = find_user(who))) |
| 190 | goto out_unlock; /* No processes for this user */ | 190 | goto out_unlock; /* No processes for this user */ |
| 191 | 191 | ||
| 192 | do_each_thread(g, p) | 192 | do_each_thread(g, p) { |
| 193 | if (__task_cred(p)->uid == who) | 193 | if (__task_cred(p)->uid == who) |
| 194 | error = set_one_prio(p, niceval, error); | 194 | error = set_one_prio(p, niceval, error); |
| 195 | while_each_thread(g, p); | 195 | } while_each_thread(g, p); |
| 196 | if (who != cred->uid) | 196 | if (who != cred->uid) |
| 197 | free_uid(user); /* For find_user() */ | 197 | free_uid(user); /* For find_user() */ |
| 198 | break; | 198 | break; |
| @@ -252,13 +252,13 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
| 252 | !(user = find_user(who))) | 252 | !(user = find_user(who))) |
| 253 | goto out_unlock; /* No processes for this user */ | 253 | goto out_unlock; /* No processes for this user */ |
| 254 | 254 | ||
| 255 | do_each_thread(g, p) | 255 | do_each_thread(g, p) { |
| 256 | if (__task_cred(p)->uid == who) { | 256 | if (__task_cred(p)->uid == who) { |
| 257 | niceval = 20 - task_nice(p); | 257 | niceval = 20 - task_nice(p); |
| 258 | if (niceval > retval) | 258 | if (niceval > retval) |
| 259 | retval = niceval; | 259 | retval = niceval; |
| 260 | } | 260 | } |
| 261 | while_each_thread(g, p); | 261 | } while_each_thread(g, p); |
| 262 | if (who != cred->uid) | 262 | if (who != cred->uid) |
| 263 | free_uid(user); /* for find_user() */ | 263 | free_uid(user); /* for find_user() */ |
| 264 | break; | 264 | break; |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 554ac4894f0f..45e4bef0012a 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -1051,7 +1051,7 @@ static struct ctl_table vm_table[] = { | |||
| 1051 | .extra2 = &one_hundred, | 1051 | .extra2 = &one_hundred, |
| 1052 | }, | 1052 | }, |
| 1053 | #ifdef CONFIG_HUGETLB_PAGE | 1053 | #ifdef CONFIG_HUGETLB_PAGE |
| 1054 | { | 1054 | { |
| 1055 | .procname = "nr_hugepages", | 1055 | .procname = "nr_hugepages", |
| 1056 | .data = NULL, | 1056 | .data = NULL, |
| 1057 | .maxlen = sizeof(unsigned long), | 1057 | .maxlen = sizeof(unsigned long), |
| @@ -1059,7 +1059,18 @@ static struct ctl_table vm_table[] = { | |||
| 1059 | .proc_handler = hugetlb_sysctl_handler, | 1059 | .proc_handler = hugetlb_sysctl_handler, |
| 1060 | .extra1 = (void *)&hugetlb_zero, | 1060 | .extra1 = (void *)&hugetlb_zero, |
| 1061 | .extra2 = (void *)&hugetlb_infinity, | 1061 | .extra2 = (void *)&hugetlb_infinity, |
| 1062 | }, | 1062 | }, |
| 1063 | #ifdef CONFIG_NUMA | ||
| 1064 | { | ||
| 1065 | .procname = "nr_hugepages_mempolicy", | ||
| 1066 | .data = NULL, | ||
| 1067 | .maxlen = sizeof(unsigned long), | ||
| 1068 | .mode = 0644, | ||
| 1069 | .proc_handler = &hugetlb_mempolicy_sysctl_handler, | ||
| 1070 | .extra1 = (void *)&hugetlb_zero, | ||
| 1071 | .extra2 = (void *)&hugetlb_infinity, | ||
| 1072 | }, | ||
| 1073 | #endif | ||
| 1063 | { | 1074 | { |
| 1064 | .procname = "hugetlb_shm_group", | 1075 | .procname = "hugetlb_shm_group", |
| 1065 | .data = &sysctl_hugetlb_shm_group, | 1076 | .data = &sysctl_hugetlb_shm_group, |
| @@ -1120,7 +1131,8 @@ static struct ctl_table vm_table[] = { | |||
| 1120 | .data = &sysctl_max_map_count, | 1131 | .data = &sysctl_max_map_count, |
| 1121 | .maxlen = sizeof(sysctl_max_map_count), | 1132 | .maxlen = sizeof(sysctl_max_map_count), |
| 1122 | .mode = 0644, | 1133 | .mode = 0644, |
| 1123 | .proc_handler = proc_dointvec | 1134 | .proc_handler = proc_dointvec, |
| 1135 | .extra1 = &zero, | ||
| 1124 | }, | 1136 | }, |
| 1125 | #else | 1137 | #else |
| 1126 | { | 1138 | { |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2f22cf4576db..8cf9938dd147 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -575,7 +575,7 @@ config DEBUG_BUGVERBOSE | |||
| 575 | depends on BUG | 575 | depends on BUG |
| 576 | depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || \ | 576 | depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || \ |
| 577 | FRV || SUPERH || GENERIC_BUG || BLACKFIN || MN10300 | 577 | FRV || SUPERH || GENERIC_BUG || BLACKFIN || MN10300 |
| 578 | default !EMBEDDED | 578 | default y |
| 579 | help | 579 | help |
| 580 | Say Y here to make BUG() panics output the file name and line number | 580 | Say Y here to make BUG() panics output the file name and line number |
| 581 | of the BUG call as well as the EIP and oops trace. This aids | 581 | of the BUG call as well as the EIP and oops trace. This aids |
diff --git a/lib/argv_split.c b/lib/argv_split.c index 5205a8dae5bc..4b1b083f219c 100644 --- a/lib/argv_split.c +++ b/lib/argv_split.c | |||
| @@ -4,17 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
| 6 | #include <linux/ctype.h> | 6 | #include <linux/ctype.h> |
| 7 | #include <linux/string.h> | ||
| 7 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
| 8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 9 | 10 | ||
| 10 | static const char *skip_sep(const char *cp) | ||
| 11 | { | ||
| 12 | while (*cp && isspace(*cp)) | ||
| 13 | cp++; | ||
| 14 | |||
| 15 | return cp; | ||
| 16 | } | ||
| 17 | |||
| 18 | static const char *skip_arg(const char *cp) | 11 | static const char *skip_arg(const char *cp) |
| 19 | { | 12 | { |
| 20 | while (*cp && !isspace(*cp)) | 13 | while (*cp && !isspace(*cp)) |
| @@ -28,7 +21,7 @@ static int count_argc(const char *str) | |||
| 28 | int count = 0; | 21 | int count = 0; |
| 29 | 22 | ||
| 30 | while (*str) { | 23 | while (*str) { |
| 31 | str = skip_sep(str); | 24 | str = skip_spaces(str); |
| 32 | if (*str) { | 25 | if (*str) { |
| 33 | count++; | 26 | count++; |
| 34 | str = skip_arg(str); | 27 | str = skip_arg(str); |
| @@ -82,7 +75,7 @@ char **argv_split(gfp_t gfp, const char *str, int *argcp) | |||
| 82 | argvp = argv; | 75 | argvp = argv; |
| 83 | 76 | ||
| 84 | while (*str) { | 77 | while (*str) { |
| 85 | str = skip_sep(str); | 78 | str = skip_spaces(str); |
| 86 | 79 | ||
| 87 | if (*str) { | 80 | if (*str) { |
| 88 | const char *p = str; | 81 | const char *p = str; |
diff --git a/lib/crc32.c b/lib/crc32.c index 49d1c9e3ce38..02e3b31b3a79 100644 --- a/lib/crc32.c +++ b/lib/crc32.c | |||
| @@ -42,6 +42,48 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>"); | |||
| 42 | MODULE_DESCRIPTION("Ethernet CRC32 calculations"); | 42 | MODULE_DESCRIPTION("Ethernet CRC32 calculations"); |
| 43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
| 44 | 44 | ||
| 45 | #if CRC_LE_BITS == 8 || CRC_BE_BITS == 8 | ||
| 46 | |||
| 47 | static inline u32 | ||
| 48 | crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 *tab) | ||
| 49 | { | ||
| 50 | # ifdef __LITTLE_ENDIAN | ||
| 51 | # define DO_CRC(x) crc = tab[(crc ^ (x)) & 255 ] ^ (crc >> 8) | ||
| 52 | # else | ||
| 53 | # define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8) | ||
| 54 | # endif | ||
| 55 | const u32 *b = (const u32 *)buf; | ||
| 56 | size_t rem_len; | ||
| 57 | |||
| 58 | /* Align it */ | ||
| 59 | if (unlikely((long)b & 3 && len)) { | ||
| 60 | u8 *p = (u8 *)b; | ||
| 61 | do { | ||
| 62 | DO_CRC(*p++); | ||
| 63 | } while ((--len) && ((long)p)&3); | ||
| 64 | b = (u32 *)p; | ||
| 65 | } | ||
| 66 | rem_len = len & 3; | ||
| 67 | /* load data 32 bits wide, xor data 32 bits wide. */ | ||
| 68 | len = len >> 2; | ||
| 69 | for (--b; len; --len) { | ||
| 70 | crc ^= *++b; /* use pre increment for speed */ | ||
| 71 | DO_CRC(0); | ||
| 72 | DO_CRC(0); | ||
| 73 | DO_CRC(0); | ||
| 74 | DO_CRC(0); | ||
| 75 | } | ||
| 76 | len = rem_len; | ||
| 77 | /* And the last few bytes */ | ||
| 78 | if (len) { | ||
| 79 | u8 *p = (u8 *)(b + 1) - 1; | ||
| 80 | do { | ||
| 81 | DO_CRC(*++p); /* use pre increment for speed */ | ||
| 82 | } while (--len); | ||
| 83 | } | ||
| 84 | return crc; | ||
| 85 | } | ||
| 86 | #endif | ||
| 45 | /** | 87 | /** |
| 46 | * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 | 88 | * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 |
| 47 | * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for | 89 | * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for |
| @@ -72,48 +114,10 @@ u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | |||
| 72 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | 114 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) |
| 73 | { | 115 | { |
| 74 | # if CRC_LE_BITS == 8 | 116 | # if CRC_LE_BITS == 8 |
| 75 | const u32 *b =(u32 *)p; | ||
| 76 | const u32 *tab = crc32table_le; | 117 | const u32 *tab = crc32table_le; |
| 77 | 118 | ||
| 78 | # ifdef __LITTLE_ENDIAN | ||
| 79 | # define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) | ||
| 80 | # else | ||
| 81 | # define DO_CRC(x) crc = tab[ ((crc >> 24) ^ (x)) & 255] ^ (crc<<8) | ||
| 82 | # endif | ||
| 83 | |||
| 84 | crc = __cpu_to_le32(crc); | 119 | crc = __cpu_to_le32(crc); |
| 85 | /* Align it */ | 120 | crc = crc32_body(crc, p, len, tab); |
| 86 | if(unlikely(((long)b)&3 && len)){ | ||
| 87 | do { | ||
| 88 | u8 *p = (u8 *)b; | ||
| 89 | DO_CRC(*p++); | ||
| 90 | b = (void *)p; | ||
| 91 | } while ((--len) && ((long)b)&3 ); | ||
| 92 | } | ||
| 93 | if(likely(len >= 4)){ | ||
| 94 | /* load data 32 bits wide, xor data 32 bits wide. */ | ||
| 95 | size_t save_len = len & 3; | ||
| 96 | len = len >> 2; | ||
| 97 | --b; /* use pre increment below(*++b) for speed */ | ||
| 98 | do { | ||
| 99 | crc ^= *++b; | ||
| 100 | DO_CRC(0); | ||
| 101 | DO_CRC(0); | ||
| 102 | DO_CRC(0); | ||
| 103 | DO_CRC(0); | ||
| 104 | } while (--len); | ||
| 105 | b++; /* point to next byte(s) */ | ||
| 106 | len = save_len; | ||
| 107 | } | ||
| 108 | /* And the last few bytes */ | ||
| 109 | if(len){ | ||
| 110 | do { | ||
| 111 | u8 *p = (u8 *)b; | ||
| 112 | DO_CRC(*p++); | ||
| 113 | b = (void *)p; | ||
| 114 | } while (--len); | ||
| 115 | } | ||
| 116 | |||
| 117 | return __le32_to_cpu(crc); | 121 | return __le32_to_cpu(crc); |
| 118 | #undef ENDIAN_SHIFT | 122 | #undef ENDIAN_SHIFT |
| 119 | #undef DO_CRC | 123 | #undef DO_CRC |
| @@ -170,47 +174,10 @@ u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | |||
| 170 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | 174 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) |
| 171 | { | 175 | { |
| 172 | # if CRC_BE_BITS == 8 | 176 | # if CRC_BE_BITS == 8 |
| 173 | const u32 *b =(u32 *)p; | ||
| 174 | const u32 *tab = crc32table_be; | 177 | const u32 *tab = crc32table_be; |
| 175 | 178 | ||
| 176 | # ifdef __LITTLE_ENDIAN | ||
| 177 | # define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) | ||
| 178 | # else | ||
| 179 | # define DO_CRC(x) crc = tab[ ((crc >> 24) ^ (x)) & 255] ^ (crc<<8) | ||
| 180 | # endif | ||
| 181 | |||
| 182 | crc = __cpu_to_be32(crc); | 179 | crc = __cpu_to_be32(crc); |
| 183 | /* Align it */ | 180 | crc = crc32_body(crc, p, len, tab); |
| 184 | if(unlikely(((long)b)&3 && len)){ | ||
| 185 | do { | ||
| 186 | u8 *p = (u8 *)b; | ||
| 187 | DO_CRC(*p++); | ||
| 188 | b = (u32 *)p; | ||
| 189 | } while ((--len) && ((long)b)&3 ); | ||
| 190 | } | ||
| 191 | if(likely(len >= 4)){ | ||
| 192 | /* load data 32 bits wide, xor data 32 bits wide. */ | ||
| 193 | size_t save_len = len & 3; | ||
| 194 | len = len >> 2; | ||
| 195 | --b; /* use pre increment below(*++b) for speed */ | ||
| 196 | do { | ||
| 197 | crc ^= *++b; | ||
| 198 | DO_CRC(0); | ||
| 199 | DO_CRC(0); | ||
| 200 | DO_CRC(0); | ||
| 201 | DO_CRC(0); | ||
| 202 | } while (--len); | ||
| 203 | b++; /* point to next byte(s) */ | ||
| 204 | len = save_len; | ||
| 205 | } | ||
| 206 | /* And the last few bytes */ | ||
| 207 | if(len){ | ||
| 208 | do { | ||
| 209 | u8 *p = (u8 *)b; | ||
| 210 | DO_CRC(*p++); | ||
| 211 | b = (void *)p; | ||
| 212 | } while (--len); | ||
| 213 | } | ||
| 214 | return __be32_to_cpu(crc); | 181 | return __be32_to_cpu(crc); |
| 215 | #undef ENDIAN_SHIFT | 182 | #undef ENDIAN_SHIFT |
| 216 | #undef DO_CRC | 183 | #undef DO_CRC |
diff --git a/lib/ctype.c b/lib/ctype.c index d02ace14a322..26baa620e95b 100644 --- a/lib/ctype.c +++ b/lib/ctype.c | |||
| @@ -7,30 +7,30 @@ | |||
| 7 | #include <linux/ctype.h> | 7 | #include <linux/ctype.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | 9 | ||
| 10 | unsigned char _ctype[] = { | 10 | const unsigned char _ctype[] = { |
| 11 | _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ | 11 | _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ |
| 12 | _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ | 12 | _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ |
| 13 | _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ | 13 | _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ |
| 14 | _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ | 14 | _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ |
| 15 | _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ | 15 | _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ |
| 16 | _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ | 16 | _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ |
| 17 | _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ | 17 | _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ |
| 18 | _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ | 18 | _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ |
| 19 | _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ | 19 | _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ |
| 20 | _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ | 20 | _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ |
| 21 | _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ | 21 | _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ |
| 22 | _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ | 22 | _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ |
| 23 | _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ | 23 | _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ |
| 24 | _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ | 24 | _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ |
| 25 | _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ | 25 | _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ |
| 26 | _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ | 26 | _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ |
| 27 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ | 27 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ |
| 28 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ | 28 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ |
| 29 | _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ | 29 | _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ |
| 30 | _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ | 30 | _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ |
| 31 | _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ | 31 | _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ |
| 32 | _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ | 32 | _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ |
| 33 | _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ | 33 | _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ |
| 34 | _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ | 34 | _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ |
| 35 | 35 | ||
| 36 | EXPORT_SYMBOL(_ctype); | 36 | EXPORT_SYMBOL(_ctype); |
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index e22c148e4b7f..f93502915988 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
| 22 | #include <linux/sysctl.h> | 22 | #include <linux/sysctl.h> |
| 23 | #include <linux/ctype.h> | 23 | #include <linux/ctype.h> |
| 24 | #include <linux/string.h> | ||
| 24 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
| 25 | #include <linux/dynamic_debug.h> | 26 | #include <linux/dynamic_debug.h> |
| 26 | #include <linux/debugfs.h> | 27 | #include <linux/debugfs.h> |
| @@ -209,8 +210,7 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords) | |||
| 209 | char *end; | 210 | char *end; |
| 210 | 211 | ||
| 211 | /* Skip leading whitespace */ | 212 | /* Skip leading whitespace */ |
| 212 | while (*buf && isspace(*buf)) | 213 | buf = skip_spaces(buf); |
| 213 | buf++; | ||
| 214 | if (!*buf) | 214 | if (!*buf) |
| 215 | break; /* oh, it was trailing whitespace */ | 215 | break; /* oh, it was trailing whitespace */ |
| 216 | 216 | ||
diff --git a/lib/parser.c b/lib/parser.c index b00d02059a5f..fb34977246bb 100644 --- a/lib/parser.c +++ b/lib/parser.c | |||
| @@ -56,13 +56,16 @@ static int match_one(char *s, const char *p, substring_t args[]) | |||
| 56 | 56 | ||
| 57 | args[argc].from = s; | 57 | args[argc].from = s; |
| 58 | switch (*p++) { | 58 | switch (*p++) { |
| 59 | case 's': | 59 | case 's': { |
| 60 | if (strlen(s) == 0) | 60 | size_t str_len = strlen(s); |
| 61 | |||
| 62 | if (str_len == 0) | ||
| 61 | return 0; | 63 | return 0; |
| 62 | else if (len == -1 || len > strlen(s)) | 64 | if (len == -1 || len > str_len) |
| 63 | len = strlen(s); | 65 | len = str_len; |
| 64 | args[argc].to = s + len; | 66 | args[argc].to = s + len; |
| 65 | break; | 67 | break; |
| 68 | } | ||
| 66 | case 'd': | 69 | case 'd': |
| 67 | simple_strtol(s, &args[argc].to, 0); | 70 | simple_strtol(s, &args[argc].to, 0); |
| 68 | goto num; | 71 | goto num; |
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index 9df3ca56db11..ccf95bff7984 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c | |||
| @@ -17,6 +17,19 @@ struct rwsem_waiter { | |||
| 17 | #define RWSEM_WAITING_FOR_WRITE 0x00000002 | 17 | #define RWSEM_WAITING_FOR_WRITE 0x00000002 |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | int rwsem_is_locked(struct rw_semaphore *sem) | ||
| 21 | { | ||
| 22 | int ret = 1; | ||
| 23 | unsigned long flags; | ||
| 24 | |||
| 25 | if (spin_trylock_irqsave(&sem->wait_lock, flags)) { | ||
| 26 | ret = (sem->activity != 0); | ||
| 27 | spin_unlock_irqrestore(&sem->wait_lock, flags); | ||
| 28 | } | ||
| 29 | return ret; | ||
| 30 | } | ||
| 31 | EXPORT_SYMBOL(rwsem_is_locked); | ||
| 32 | |||
| 20 | /* | 33 | /* |
| 21 | * initialise the semaphore | 34 | * initialise the semaphore |
| 22 | */ | 35 | */ |
| @@ -34,6 +47,7 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name, | |||
| 34 | spin_lock_init(&sem->wait_lock); | 47 | spin_lock_init(&sem->wait_lock); |
| 35 | INIT_LIST_HEAD(&sem->wait_list); | 48 | INIT_LIST_HEAD(&sem->wait_list); |
| 36 | } | 49 | } |
| 50 | EXPORT_SYMBOL(__init_rwsem); | ||
| 37 | 51 | ||
| 38 | /* | 52 | /* |
| 39 | * handle the lock release when processes blocked on it that can now run | 53 | * handle the lock release when processes blocked on it that can now run |
| @@ -305,12 +319,3 @@ void __downgrade_write(struct rw_semaphore *sem) | |||
| 305 | spin_unlock_irqrestore(&sem->wait_lock, flags); | 319 | spin_unlock_irqrestore(&sem->wait_lock, flags); |
| 306 | } | 320 | } |
| 307 | 321 | ||
| 308 | EXPORT_SYMBOL(__init_rwsem); | ||
| 309 | EXPORT_SYMBOL(__down_read); | ||
| 310 | EXPORT_SYMBOL(__down_read_trylock); | ||
| 311 | EXPORT_SYMBOL(__down_write_nested); | ||
| 312 | EXPORT_SYMBOL(__down_write); | ||
| 313 | EXPORT_SYMBOL(__down_write_trylock); | ||
| 314 | EXPORT_SYMBOL(__up_read); | ||
| 315 | EXPORT_SYMBOL(__up_write); | ||
| 316 | EXPORT_SYMBOL(__downgrade_write); | ||
diff --git a/lib/string.c b/lib/string.c index e96421ab9a9a..afce96af3afd 100644 --- a/lib/string.c +++ b/lib/string.c | |||
| @@ -338,20 +338,34 @@ EXPORT_SYMBOL(strnchr); | |||
| 338 | #endif | 338 | #endif |
| 339 | 339 | ||
| 340 | /** | 340 | /** |
| 341 | * strstrip - Removes leading and trailing whitespace from @s. | 341 | * skip_spaces - Removes leading whitespace from @s. |
| 342 | * @s: The string to be stripped. | ||
| 343 | * | ||
| 344 | * Returns a pointer to the first non-whitespace character in @s. | ||
| 345 | */ | ||
| 346 | char *skip_spaces(const char *str) | ||
| 347 | { | ||
| 348 | while (isspace(*str)) | ||
| 349 | ++str; | ||
| 350 | return (char *)str; | ||
| 351 | } | ||
| 352 | EXPORT_SYMBOL(skip_spaces); | ||
| 353 | |||
| 354 | /** | ||
| 355 | * strim - Removes leading and trailing whitespace from @s. | ||
| 342 | * @s: The string to be stripped. | 356 | * @s: The string to be stripped. |
| 343 | * | 357 | * |
| 344 | * Note that the first trailing whitespace is replaced with a %NUL-terminator | 358 | * Note that the first trailing whitespace is replaced with a %NUL-terminator |
| 345 | * in the given string @s. Returns a pointer to the first non-whitespace | 359 | * in the given string @s. Returns a pointer to the first non-whitespace |
| 346 | * character in @s. | 360 | * character in @s. |
| 347 | */ | 361 | */ |
| 348 | char *strstrip(char *s) | 362 | char *strim(char *s) |
| 349 | { | 363 | { |
| 350 | size_t size; | 364 | size_t size; |
| 351 | char *end; | 365 | char *end; |
| 352 | 366 | ||
| 367 | s = skip_spaces(s); | ||
| 353 | size = strlen(s); | 368 | size = strlen(s); |
| 354 | |||
| 355 | if (!size) | 369 | if (!size) |
| 356 | return s; | 370 | return s; |
| 357 | 371 | ||
| @@ -360,12 +374,9 @@ char *strstrip(char *s) | |||
| 360 | end--; | 374 | end--; |
| 361 | *(end + 1) = '\0'; | 375 | *(end + 1) = '\0'; |
| 362 | 376 | ||
| 363 | while (*s && isspace(*s)) | ||
| 364 | s++; | ||
| 365 | |||
| 366 | return s; | 377 | return s; |
| 367 | } | 378 | } |
| 368 | EXPORT_SYMBOL(strstrip); | 379 | EXPORT_SYMBOL(strim); |
| 369 | 380 | ||
| 370 | #ifndef __HAVE_ARCH_STRLEN | 381 | #ifndef __HAVE_ARCH_STRLEN |
| 371 | /** | 382 | /** |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 6438cd5599ee..735343fc857a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | * Wirzenius wrote this portably, Torvalds fucked it up :-) | 9 | * Wirzenius wrote this portably, Torvalds fucked it up :-) |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | /* | 12 | /* |
| 13 | * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> | 13 | * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> |
| 14 | * - changed to provide snprintf and vsnprintf functions | 14 | * - changed to provide snprintf and vsnprintf functions |
| 15 | * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de> | 15 | * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de> |
| @@ -47,14 +47,14 @@ static unsigned int simple_guess_base(const char *cp) | |||
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /** | 49 | /** |
| 50 | * simple_strtoul - convert a string to an unsigned long | 50 | * simple_strtoull - convert a string to an unsigned long long |
| 51 | * @cp: The start of the string | 51 | * @cp: The start of the string |
| 52 | * @endp: A pointer to the end of the parsed string will be placed here | 52 | * @endp: A pointer to the end of the parsed string will be placed here |
| 53 | * @base: The number base to use | 53 | * @base: The number base to use |
| 54 | */ | 54 | */ |
| 55 | unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) | 55 | unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) |
| 56 | { | 56 | { |
| 57 | unsigned long result = 0; | 57 | unsigned long long result = 0; |
| 58 | 58 | ||
| 59 | if (!base) | 59 | if (!base) |
| 60 | base = simple_guess_base(cp); | 60 | base = simple_guess_base(cp); |
| @@ -71,58 +71,39 @@ unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) | |||
| 71 | result = result * base + value; | 71 | result = result * base + value; |
| 72 | cp++; | 72 | cp++; |
| 73 | } | 73 | } |
| 74 | |||
| 75 | if (endp) | 74 | if (endp) |
| 76 | *endp = (char *)cp; | 75 | *endp = (char *)cp; |
| 76 | |||
| 77 | return result; | 77 | return result; |
| 78 | } | 78 | } |
| 79 | EXPORT_SYMBOL(simple_strtoul); | 79 | EXPORT_SYMBOL(simple_strtoull); |
| 80 | 80 | ||
| 81 | /** | 81 | /** |
| 82 | * simple_strtol - convert a string to a signed long | 82 | * simple_strtoul - convert a string to an unsigned long |
| 83 | * @cp: The start of the string | 83 | * @cp: The start of the string |
| 84 | * @endp: A pointer to the end of the parsed string will be placed here | 84 | * @endp: A pointer to the end of the parsed string will be placed here |
| 85 | * @base: The number base to use | 85 | * @base: The number base to use |
| 86 | */ | 86 | */ |
| 87 | long simple_strtol(const char *cp, char **endp, unsigned int base) | 87 | unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) |
| 88 | { | 88 | { |
| 89 | if(*cp == '-') | 89 | return simple_strtoull(cp, endp, base); |
| 90 | return -simple_strtoul(cp + 1, endp, base); | ||
| 91 | return simple_strtoul(cp, endp, base); | ||
| 92 | } | 90 | } |
| 93 | EXPORT_SYMBOL(simple_strtol); | 91 | EXPORT_SYMBOL(simple_strtoul); |
| 94 | 92 | ||
| 95 | /** | 93 | /** |
| 96 | * simple_strtoull - convert a string to an unsigned long long | 94 | * simple_strtol - convert a string to a signed long |
| 97 | * @cp: The start of the string | 95 | * @cp: The start of the string |
| 98 | * @endp: A pointer to the end of the parsed string will be placed here | 96 | * @endp: A pointer to the end of the parsed string will be placed here |
| 99 | * @base: The number base to use | 97 | * @base: The number base to use |
| 100 | */ | 98 | */ |
| 101 | unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) | 99 | long simple_strtol(const char *cp, char **endp, unsigned int base) |
| 102 | { | 100 | { |
| 103 | unsigned long long result = 0; | 101 | if (*cp == '-') |
| 104 | 102 | return -simple_strtoul(cp + 1, endp, base); | |
| 105 | if (!base) | ||
| 106 | base = simple_guess_base(cp); | ||
| 107 | |||
| 108 | if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x') | ||
| 109 | cp += 2; | ||
| 110 | |||
| 111 | while (isxdigit(*cp)) { | ||
| 112 | unsigned int value; | ||
| 113 | |||
| 114 | value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10; | ||
| 115 | if (value >= base) | ||
| 116 | break; | ||
| 117 | result = result * base + value; | ||
| 118 | cp++; | ||
| 119 | } | ||
| 120 | 103 | ||
| 121 | if (endp) | 104 | return simple_strtoul(cp, endp, base); |
| 122 | *endp = (char *)cp; | ||
| 123 | return result; | ||
| 124 | } | 105 | } |
| 125 | EXPORT_SYMBOL(simple_strtoull); | 106 | EXPORT_SYMBOL(simple_strtol); |
| 126 | 107 | ||
| 127 | /** | 108 | /** |
| 128 | * simple_strtoll - convert a string to a signed long long | 109 | * simple_strtoll - convert a string to a signed long long |
| @@ -132,8 +113,9 @@ EXPORT_SYMBOL(simple_strtoull); | |||
| 132 | */ | 113 | */ |
| 133 | long long simple_strtoll(const char *cp, char **endp, unsigned int base) | 114 | long long simple_strtoll(const char *cp, char **endp, unsigned int base) |
| 134 | { | 115 | { |
| 135 | if(*cp=='-') | 116 | if (*cp == '-') |
| 136 | return -simple_strtoull(cp + 1, endp, base); | 117 | return -simple_strtoull(cp + 1, endp, base); |
| 118 | |||
| 137 | return simple_strtoull(cp, endp, base); | 119 | return simple_strtoull(cp, endp, base); |
| 138 | } | 120 | } |
| 139 | 121 | ||
| @@ -173,6 +155,7 @@ int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) | |||
| 173 | val = simple_strtoul(cp, &tail, base); | 155 | val = simple_strtoul(cp, &tail, base); |
| 174 | if (tail == cp) | 156 | if (tail == cp) |
| 175 | return -EINVAL; | 157 | return -EINVAL; |
| 158 | |||
| 176 | if ((*tail == '\0') || | 159 | if ((*tail == '\0') || |
| 177 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { | 160 | ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { |
| 178 | *res = val; | 161 | *res = val; |
| @@ -285,10 +268,11 @@ EXPORT_SYMBOL(strict_strtoll); | |||
| 285 | 268 | ||
| 286 | static int skip_atoi(const char **s) | 269 | static int skip_atoi(const char **s) |
| 287 | { | 270 | { |
| 288 | int i=0; | 271 | int i = 0; |
| 289 | 272 | ||
| 290 | while (isdigit(**s)) | 273 | while (isdigit(**s)) |
| 291 | i = i*10 + *((*s)++) - '0'; | 274 | i = i*10 + *((*s)++) - '0'; |
| 275 | |||
| 292 | return i; | 276 | return i; |
| 293 | } | 277 | } |
| 294 | 278 | ||
| @@ -302,7 +286,7 @@ static int skip_atoi(const char **s) | |||
| 302 | /* Formats correctly any integer in [0,99999]. | 286 | /* Formats correctly any integer in [0,99999]. |
| 303 | * Outputs from one to five digits depending on input. | 287 | * Outputs from one to five digits depending on input. |
| 304 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ | 288 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ |
| 305 | static char* put_dec_trunc(char *buf, unsigned q) | 289 | static char *put_dec_trunc(char *buf, unsigned q) |
| 306 | { | 290 | { |
| 307 | unsigned d3, d2, d1, d0; | 291 | unsigned d3, d2, d1, d0; |
| 308 | d1 = (q>>4) & 0xf; | 292 | d1 = (q>>4) & 0xf; |
| @@ -331,14 +315,15 @@ static char* put_dec_trunc(char *buf, unsigned q) | |||
| 331 | d3 = d3 - 10*q; | 315 | d3 = d3 - 10*q; |
| 332 | *buf++ = d3 + '0'; /* next digit */ | 316 | *buf++ = d3 + '0'; /* next digit */ |
| 333 | if (q != 0) | 317 | if (q != 0) |
| 334 | *buf++ = q + '0'; /* most sign. digit */ | 318 | *buf++ = q + '0'; /* most sign. digit */ |
| 335 | } | 319 | } |
| 336 | } | 320 | } |
| 337 | } | 321 | } |
| 322 | |||
| 338 | return buf; | 323 | return buf; |
| 339 | } | 324 | } |
| 340 | /* Same with if's removed. Always emits five digits */ | 325 | /* Same with if's removed. Always emits five digits */ |
| 341 | static char* put_dec_full(char *buf, unsigned q) | 326 | static char *put_dec_full(char *buf, unsigned q) |
| 342 | { | 327 | { |
| 343 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ | 328 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ |
| 344 | /* but anyway, gcc produces better code with full-sized ints */ | 329 | /* but anyway, gcc produces better code with full-sized ints */ |
| @@ -347,14 +332,15 @@ static char* put_dec_full(char *buf, unsigned q) | |||
| 347 | d2 = (q>>8) & 0xf; | 332 | d2 = (q>>8) & 0xf; |
| 348 | d3 = (q>>12); | 333 | d3 = (q>>12); |
| 349 | 334 | ||
| 350 | /* Possible ways to approx. divide by 10 */ | 335 | /* |
| 351 | /* gcc -O2 replaces multiply with shifts and adds */ | 336 | * Possible ways to approx. divide by 10 |
| 352 | // (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386) | 337 | * gcc -O2 replaces multiply with shifts and adds |
| 353 | // (x * 0x67) >> 10: 1100111 | 338 | * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386) |
| 354 | // (x * 0x34) >> 9: 110100 - same | 339 | * (x * 0x67) >> 10: 1100111 |
| 355 | // (x * 0x1a) >> 8: 11010 - same | 340 | * (x * 0x34) >> 9: 110100 - same |
| 356 | // (x * 0x0d) >> 7: 1101 - same, shortest code (on i386) | 341 | * (x * 0x1a) >> 8: 11010 - same |
| 357 | 342 | * (x * 0x0d) >> 7: 1101 - same, shortest code (on i386) | |
| 343 | */ | ||
| 358 | d0 = 6*(d3 + d2 + d1) + (q & 0xf); | 344 | d0 = 6*(d3 + d2 + d1) + (q & 0xf); |
| 359 | q = (d0 * 0xcd) >> 11; | 345 | q = (d0 * 0xcd) >> 11; |
| 360 | d0 = d0 - 10*q; | 346 | d0 = d0 - 10*q; |
| @@ -375,10 +361,11 @@ static char* put_dec_full(char *buf, unsigned q) | |||
| 375 | d3 = d3 - 10*q; | 361 | d3 = d3 - 10*q; |
| 376 | *buf++ = d3 + '0'; | 362 | *buf++ = d3 + '0'; |
| 377 | *buf++ = q + '0'; | 363 | *buf++ = q + '0'; |
| 364 | |||
| 378 | return buf; | 365 | return buf; |
| 379 | } | 366 | } |
| 380 | /* No inlining helps gcc to use registers better */ | 367 | /* No inlining helps gcc to use registers better */ |
| 381 | static noinline char* put_dec(char *buf, unsigned long long num) | 368 | static noinline char *put_dec(char *buf, unsigned long long num) |
| 382 | { | 369 | { |
| 383 | while (1) { | 370 | while (1) { |
| 384 | unsigned rem; | 371 | unsigned rem; |
| @@ -448,9 +435,9 @@ static char *number(char *buf, char *end, unsigned long long num, | |||
| 448 | spec.flags &= ~ZEROPAD; | 435 | spec.flags &= ~ZEROPAD; |
| 449 | sign = 0; | 436 | sign = 0; |
| 450 | if (spec.flags & SIGN) { | 437 | if (spec.flags & SIGN) { |
| 451 | if ((signed long long) num < 0) { | 438 | if ((signed long long)num < 0) { |
| 452 | sign = '-'; | 439 | sign = '-'; |
| 453 | num = - (signed long long) num; | 440 | num = -(signed long long)num; |
| 454 | spec.field_width--; | 441 | spec.field_width--; |
| 455 | } else if (spec.flags & PLUS) { | 442 | } else if (spec.flags & PLUS) { |
| 456 | sign = '+'; | 443 | sign = '+'; |
| @@ -478,7 +465,9 @@ static char *number(char *buf, char *end, unsigned long long num, | |||
| 478 | else if (spec.base != 10) { /* 8 or 16 */ | 465 | else if (spec.base != 10) { /* 8 or 16 */ |
| 479 | int mask = spec.base - 1; | 466 | int mask = spec.base - 1; |
| 480 | int shift = 3; | 467 | int shift = 3; |
| 481 | if (spec.base == 16) shift = 4; | 468 | |
| 469 | if (spec.base == 16) | ||
| 470 | shift = 4; | ||
| 482 | do { | 471 | do { |
| 483 | tmp[i++] = (digits[((unsigned char)num) & mask] | locase); | 472 | tmp[i++] = (digits[((unsigned char)num) & mask] | locase); |
| 484 | num >>= shift; | 473 | num >>= shift; |
| @@ -493,7 +482,7 @@ static char *number(char *buf, char *end, unsigned long long num, | |||
| 493 | /* leading space padding */ | 482 | /* leading space padding */ |
| 494 | spec.field_width -= spec.precision; | 483 | spec.field_width -= spec.precision; |
| 495 | if (!(spec.flags & (ZEROPAD+LEFT))) { | 484 | if (!(spec.flags & (ZEROPAD+LEFT))) { |
| 496 | while(--spec.field_width >= 0) { | 485 | while (--spec.field_width >= 0) { |
| 497 | if (buf < end) | 486 | if (buf < end) |
| 498 | *buf = ' '; | 487 | *buf = ' '; |
| 499 | ++buf; | 488 | ++buf; |
| @@ -543,15 +532,16 @@ static char *number(char *buf, char *end, unsigned long long num, | |||
| 543 | *buf = ' '; | 532 | *buf = ' '; |
| 544 | ++buf; | 533 | ++buf; |
| 545 | } | 534 | } |
| 535 | |||
| 546 | return buf; | 536 | return buf; |
| 547 | } | 537 | } |
| 548 | 538 | ||
| 549 | static char *string(char *buf, char *end, char *s, struct printf_spec spec) | 539 | static char *string(char *buf, char *end, const char *s, struct printf_spec spec) |
| 550 | { | 540 | { |
| 551 | int len, i; | 541 | int len, i; |
| 552 | 542 | ||
| 553 | if ((unsigned long)s < PAGE_SIZE) | 543 | if ((unsigned long)s < PAGE_SIZE) |
| 554 | s = "<NULL>"; | 544 | s = "(null)"; |
| 555 | 545 | ||
| 556 | len = strnlen(s, spec.precision); | 546 | len = strnlen(s, spec.precision); |
| 557 | 547 | ||
| @@ -572,6 +562,7 @@ static char *string(char *buf, char *end, char *s, struct printf_spec spec) | |||
| 572 | *buf = ' '; | 562 | *buf = ' '; |
| 573 | ++buf; | 563 | ++buf; |
| 574 | } | 564 | } |
| 565 | |||
| 575 | return buf; | 566 | return buf; |
| 576 | } | 567 | } |
| 577 | 568 | ||
| @@ -585,11 +576,13 @@ static char *symbol_string(char *buf, char *end, void *ptr, | |||
| 585 | sprint_symbol(sym, value); | 576 | sprint_symbol(sym, value); |
| 586 | else | 577 | else |
| 587 | kallsyms_lookup(value, NULL, NULL, NULL, sym); | 578 | kallsyms_lookup(value, NULL, NULL, NULL, sym); |
| 579 | |||
| 588 | return string(buf, end, sym, spec); | 580 | return string(buf, end, sym, spec); |
| 589 | #else | 581 | #else |
| 590 | spec.field_width = 2*sizeof(void *); | 582 | spec.field_width = 2 * sizeof(void *); |
| 591 | spec.flags |= SPECIAL | SMALL | ZEROPAD; | 583 | spec.flags |= SPECIAL | SMALL | ZEROPAD; |
| 592 | spec.base = 16; | 584 | spec.base = 16; |
| 585 | |||
| 593 | return number(buf, end, value, spec); | 586 | return number(buf, end, value, spec); |
| 594 | #endif | 587 | #endif |
| 595 | } | 588 | } |
| @@ -718,22 +711,19 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) | |||
| 718 | if (i < 3) | 711 | if (i < 3) |
| 719 | *p++ = '.'; | 712 | *p++ = '.'; |
| 720 | } | 713 | } |
| 721 | |||
| 722 | *p = '\0'; | 714 | *p = '\0'; |
| 715 | |||
| 723 | return p; | 716 | return p; |
| 724 | } | 717 | } |
| 725 | 718 | ||
| 726 | static char *ip6_compressed_string(char *p, const char *addr) | 719 | static char *ip6_compressed_string(char *p, const char *addr) |
| 727 | { | 720 | { |
| 728 | int i; | 721 | int i, j, range; |
| 729 | int j; | ||
| 730 | int range; | ||
| 731 | unsigned char zerolength[8]; | 722 | unsigned char zerolength[8]; |
| 732 | int longest = 1; | 723 | int longest = 1; |
| 733 | int colonpos = -1; | 724 | int colonpos = -1; |
| 734 | u16 word; | 725 | u16 word; |
| 735 | u8 hi; | 726 | u8 hi, lo; |
| 736 | u8 lo; | ||
| 737 | bool needcolon = false; | 727 | bool needcolon = false; |
| 738 | bool useIPv4; | 728 | bool useIPv4; |
| 739 | struct in6_addr in6; | 729 | struct in6_addr in6; |
| @@ -787,8 +777,9 @@ static char *ip6_compressed_string(char *p, const char *addr) | |||
| 787 | p = pack_hex_byte(p, hi); | 777 | p = pack_hex_byte(p, hi); |
| 788 | else | 778 | else |
| 789 | *p++ = hex_asc_lo(hi); | 779 | *p++ = hex_asc_lo(hi); |
| 780 | p = pack_hex_byte(p, lo); | ||
| 790 | } | 781 | } |
| 791 | if (hi || lo > 0x0f) | 782 | else if (lo > 0x0f) |
| 792 | p = pack_hex_byte(p, lo); | 783 | p = pack_hex_byte(p, lo); |
| 793 | else | 784 | else |
| 794 | *p++ = hex_asc_lo(lo); | 785 | *p++ = hex_asc_lo(lo); |
| @@ -800,22 +791,23 @@ static char *ip6_compressed_string(char *p, const char *addr) | |||
| 800 | *p++ = ':'; | 791 | *p++ = ':'; |
| 801 | p = ip4_string(p, &in6.s6_addr[12], false); | 792 | p = ip4_string(p, &in6.s6_addr[12], false); |
| 802 | } | 793 | } |
| 803 | |||
| 804 | *p = '\0'; | 794 | *p = '\0'; |
| 795 | |||
| 805 | return p; | 796 | return p; |
| 806 | } | 797 | } |
| 807 | 798 | ||
| 808 | static char *ip6_string(char *p, const char *addr, const char *fmt) | 799 | static char *ip6_string(char *p, const char *addr, const char *fmt) |
| 809 | { | 800 | { |
| 810 | int i; | 801 | int i; |
| 802 | |||
| 811 | for (i = 0; i < 8; i++) { | 803 | for (i = 0; i < 8; i++) { |
| 812 | p = pack_hex_byte(p, *addr++); | 804 | p = pack_hex_byte(p, *addr++); |
| 813 | p = pack_hex_byte(p, *addr++); | 805 | p = pack_hex_byte(p, *addr++); |
| 814 | if (fmt[0] == 'I' && i != 7) | 806 | if (fmt[0] == 'I' && i != 7) |
| 815 | *p++ = ':'; | 807 | *p++ = ':'; |
| 816 | } | 808 | } |
| 817 | |||
| 818 | *p = '\0'; | 809 | *p = '\0'; |
| 810 | |||
| 819 | return p; | 811 | return p; |
| 820 | } | 812 | } |
| 821 | 813 | ||
| @@ -842,6 +834,52 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | |||
| 842 | return string(buf, end, ip4_addr, spec); | 834 | return string(buf, end, ip4_addr, spec); |
| 843 | } | 835 | } |
| 844 | 836 | ||
| 837 | static char *uuid_string(char *buf, char *end, const u8 *addr, | ||
| 838 | struct printf_spec spec, const char *fmt) | ||
| 839 | { | ||
| 840 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; | ||
| 841 | char *p = uuid; | ||
| 842 | int i; | ||
| 843 | static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; | ||
| 844 | static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15}; | ||
| 845 | const u8 *index = be; | ||
| 846 | bool uc = false; | ||
| 847 | |||
| 848 | switch (*(++fmt)) { | ||
| 849 | case 'L': | ||
| 850 | uc = true; /* fall-through */ | ||
| 851 | case 'l': | ||
| 852 | index = le; | ||
| 853 | break; | ||
| 854 | case 'B': | ||
| 855 | uc = true; | ||
| 856 | break; | ||
| 857 | } | ||
| 858 | |||
| 859 | for (i = 0; i < 16; i++) { | ||
| 860 | p = pack_hex_byte(p, addr[index[i]]); | ||
| 861 | switch (i) { | ||
| 862 | case 3: | ||
| 863 | case 5: | ||
| 864 | case 7: | ||
| 865 | case 9: | ||
| 866 | *p++ = '-'; | ||
| 867 | break; | ||
| 868 | } | ||
| 869 | } | ||
| 870 | |||
| 871 | *p = 0; | ||
| 872 | |||
| 873 | if (uc) { | ||
| 874 | p = uuid; | ||
| 875 | do { | ||
| 876 | *p = toupper(*p); | ||
| 877 | } while (*(++p)); | ||
| 878 | } | ||
| 879 | |||
| 880 | return string(buf, end, uuid, spec); | ||
| 881 | } | ||
| 882 | |||
| 845 | /* | 883 | /* |
| 846 | * Show a '%p' thing. A kernel extension is that the '%p' is followed | 884 | * Show a '%p' thing. A kernel extension is that the '%p' is followed |
| 847 | * by an extra set of alphanumeric characters that are extended format | 885 | * by an extra set of alphanumeric characters that are extended format |
| @@ -866,6 +904,18 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | |||
| 866 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) | 904 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) |
| 867 | * - 'I6c' for IPv6 addresses printed as specified by | 905 | * - 'I6c' for IPv6 addresses printed as specified by |
| 868 | * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt | 906 | * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt |
| 907 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form | ||
| 908 | * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | ||
| 909 | * Options for %pU are: | ||
| 910 | * b big endian lower case hex (default) | ||
| 911 | * B big endian UPPER case hex | ||
| 912 | * l little endian lower case hex | ||
| 913 | * L little endian UPPER case hex | ||
| 914 | * big endian output byte order is: | ||
| 915 | * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] | ||
| 916 | * little endian output byte order is: | ||
| 917 | * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] | ||
| 918 | * | ||
| 869 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 919 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
| 870 | * function pointers are really function descriptors, which contain a | 920 | * function pointers are really function descriptors, which contain a |
| 871 | * pointer to the real address. | 921 | * pointer to the real address. |
| @@ -880,9 +930,9 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 880 | case 'F': | 930 | case 'F': |
| 881 | case 'f': | 931 | case 'f': |
| 882 | ptr = dereference_function_descriptor(ptr); | 932 | ptr = dereference_function_descriptor(ptr); |
| 883 | case 's': | ||
| 884 | /* Fallthrough */ | 933 | /* Fallthrough */ |
| 885 | case 'S': | 934 | case 'S': |
| 935 | case 's': | ||
| 886 | return symbol_string(buf, end, ptr, spec, *fmt); | 936 | return symbol_string(buf, end, ptr, spec, *fmt); |
| 887 | case 'R': | 937 | case 'R': |
| 888 | case 'r': | 938 | case 'r': |
| @@ -906,6 +956,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 906 | return ip4_addr_string(buf, end, ptr, spec, fmt); | 956 | return ip4_addr_string(buf, end, ptr, spec, fmt); |
| 907 | } | 957 | } |
| 908 | break; | 958 | break; |
| 959 | case 'U': | ||
| 960 | return uuid_string(buf, end, ptr, spec, fmt); | ||
| 909 | } | 961 | } |
| 910 | spec.flags |= SMALL; | 962 | spec.flags |= SMALL; |
| 911 | if (spec.field_width == -1) { | 963 | if (spec.field_width == -1) { |
| @@ -1023,8 +1075,8 @@ precision: | |||
| 1023 | qualifier: | 1075 | qualifier: |
| 1024 | /* get the conversion qualifier */ | 1076 | /* get the conversion qualifier */ |
| 1025 | spec->qualifier = -1; | 1077 | spec->qualifier = -1; |
| 1026 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || | 1078 | if (*fmt == 'h' || TOLOWER(*fmt) == 'l' || |
| 1027 | *fmt == 'Z' || *fmt == 'z' || *fmt == 't') { | 1079 | TOLOWER(*fmt) == 'z' || *fmt == 't') { |
| 1028 | spec->qualifier = *fmt++; | 1080 | spec->qualifier = *fmt++; |
| 1029 | if (unlikely(spec->qualifier == *fmt)) { | 1081 | if (unlikely(spec->qualifier == *fmt)) { |
| 1030 | if (spec->qualifier == 'l') { | 1082 | if (spec->qualifier == 'l') { |
| @@ -1091,7 +1143,7 @@ qualifier: | |||
| 1091 | spec->type = FORMAT_TYPE_LONG; | 1143 | spec->type = FORMAT_TYPE_LONG; |
| 1092 | else | 1144 | else |
| 1093 | spec->type = FORMAT_TYPE_ULONG; | 1145 | spec->type = FORMAT_TYPE_ULONG; |
| 1094 | } else if (spec->qualifier == 'Z' || spec->qualifier == 'z') { | 1146 | } else if (TOLOWER(spec->qualifier) == 'z') { |
| 1095 | spec->type = FORMAT_TYPE_SIZE_T; | 1147 | spec->type = FORMAT_TYPE_SIZE_T; |
| 1096 | } else if (spec->qualifier == 't') { | 1148 | } else if (spec->qualifier == 't') { |
| 1097 | spec->type = FORMAT_TYPE_PTRDIFF; | 1149 | spec->type = FORMAT_TYPE_PTRDIFF; |
| @@ -1144,8 +1196,7 @@ qualifier: | |||
| 1144 | int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | 1196 | int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) |
| 1145 | { | 1197 | { |
| 1146 | unsigned long long num; | 1198 | unsigned long long num; |
| 1147 | char *str, *end, c; | 1199 | char *str, *end; |
| 1148 | int read; | ||
| 1149 | struct printf_spec spec = {0}; | 1200 | struct printf_spec spec = {0}; |
| 1150 | 1201 | ||
| 1151 | /* Reject out-of-range values early. Large positive sizes are | 1202 | /* Reject out-of-range values early. Large positive sizes are |
| @@ -1164,8 +1215,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1164 | 1215 | ||
| 1165 | while (*fmt) { | 1216 | while (*fmt) { |
| 1166 | const char *old_fmt = fmt; | 1217 | const char *old_fmt = fmt; |
| 1167 | 1218 | int read = format_decode(fmt, &spec); | |
| 1168 | read = format_decode(fmt, &spec); | ||
| 1169 | 1219 | ||
| 1170 | fmt += read; | 1220 | fmt += read; |
| 1171 | 1221 | ||
| @@ -1189,7 +1239,9 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1189 | spec.precision = va_arg(args, int); | 1239 | spec.precision = va_arg(args, int); |
| 1190 | break; | 1240 | break; |
| 1191 | 1241 | ||
| 1192 | case FORMAT_TYPE_CHAR: | 1242 | case FORMAT_TYPE_CHAR: { |
| 1243 | char c; | ||
| 1244 | |||
| 1193 | if (!(spec.flags & LEFT)) { | 1245 | if (!(spec.flags & LEFT)) { |
| 1194 | while (--spec.field_width > 0) { | 1246 | while (--spec.field_width > 0) { |
| 1195 | if (str < end) | 1247 | if (str < end) |
| @@ -1208,6 +1260,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1208 | ++str; | 1260 | ++str; |
| 1209 | } | 1261 | } |
| 1210 | break; | 1262 | break; |
| 1263 | } | ||
| 1211 | 1264 | ||
| 1212 | case FORMAT_TYPE_STR: | 1265 | case FORMAT_TYPE_STR: |
| 1213 | str = string(str, end, va_arg(args, char *), spec); | 1266 | str = string(str, end, va_arg(args, char *), spec); |
| @@ -1238,8 +1291,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1238 | if (qualifier == 'l') { | 1291 | if (qualifier == 'l') { |
| 1239 | long *ip = va_arg(args, long *); | 1292 | long *ip = va_arg(args, long *); |
| 1240 | *ip = (str - buf); | 1293 | *ip = (str - buf); |
| 1241 | } else if (qualifier == 'Z' || | 1294 | } else if (TOLOWER(qualifier) == 'z') { |
| 1242 | qualifier == 'z') { | ||
| 1243 | size_t *ip = va_arg(args, size_t *); | 1295 | size_t *ip = va_arg(args, size_t *); |
| 1244 | *ip = (str - buf); | 1296 | *ip = (str - buf); |
| 1245 | } else { | 1297 | } else { |
| @@ -1322,7 +1374,8 @@ int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1322 | { | 1374 | { |
| 1323 | int i; | 1375 | int i; |
| 1324 | 1376 | ||
| 1325 | i=vsnprintf(buf,size,fmt,args); | 1377 | i = vsnprintf(buf, size, fmt, args); |
| 1378 | |||
| 1326 | return (i >= size) ? (size - 1) : i; | 1379 | return (i >= size) ? (size - 1) : i; |
| 1327 | } | 1380 | } |
| 1328 | EXPORT_SYMBOL(vscnprintf); | 1381 | EXPORT_SYMBOL(vscnprintf); |
| @@ -1341,14 +1394,15 @@ EXPORT_SYMBOL(vscnprintf); | |||
| 1341 | * | 1394 | * |
| 1342 | * See the vsnprintf() documentation for format string extensions over C99. | 1395 | * See the vsnprintf() documentation for format string extensions over C99. |
| 1343 | */ | 1396 | */ |
| 1344 | int snprintf(char * buf, size_t size, const char *fmt, ...) | 1397 | int snprintf(char *buf, size_t size, const char *fmt, ...) |
| 1345 | { | 1398 | { |
| 1346 | va_list args; | 1399 | va_list args; |
| 1347 | int i; | 1400 | int i; |
| 1348 | 1401 | ||
| 1349 | va_start(args, fmt); | 1402 | va_start(args, fmt); |
| 1350 | i=vsnprintf(buf,size,fmt,args); | 1403 | i = vsnprintf(buf, size, fmt, args); |
| 1351 | va_end(args); | 1404 | va_end(args); |
| 1405 | |||
| 1352 | return i; | 1406 | return i; |
| 1353 | } | 1407 | } |
| 1354 | EXPORT_SYMBOL(snprintf); | 1408 | EXPORT_SYMBOL(snprintf); |
| @@ -1364,7 +1418,7 @@ EXPORT_SYMBOL(snprintf); | |||
| 1364 | * the trailing '\0'. If @size is <= 0 the function returns 0. | 1418 | * the trailing '\0'. If @size is <= 0 the function returns 0. |
| 1365 | */ | 1419 | */ |
| 1366 | 1420 | ||
| 1367 | int scnprintf(char * buf, size_t size, const char *fmt, ...) | 1421 | int scnprintf(char *buf, size_t size, const char *fmt, ...) |
| 1368 | { | 1422 | { |
| 1369 | va_list args; | 1423 | va_list args; |
| 1370 | int i; | 1424 | int i; |
| @@ -1372,6 +1426,7 @@ int scnprintf(char * buf, size_t size, const char *fmt, ...) | |||
| 1372 | va_start(args, fmt); | 1426 | va_start(args, fmt); |
| 1373 | i = vsnprintf(buf, size, fmt, args); | 1427 | i = vsnprintf(buf, size, fmt, args); |
| 1374 | va_end(args); | 1428 | va_end(args); |
| 1429 | |||
| 1375 | return (i >= size) ? (size - 1) : i; | 1430 | return (i >= size) ? (size - 1) : i; |
| 1376 | } | 1431 | } |
| 1377 | EXPORT_SYMBOL(scnprintf); | 1432 | EXPORT_SYMBOL(scnprintf); |
| @@ -1409,14 +1464,15 @@ EXPORT_SYMBOL(vsprintf); | |||
| 1409 | * | 1464 | * |
| 1410 | * See the vsnprintf() documentation for format string extensions over C99. | 1465 | * See the vsnprintf() documentation for format string extensions over C99. |
| 1411 | */ | 1466 | */ |
| 1412 | int sprintf(char * buf, const char *fmt, ...) | 1467 | int sprintf(char *buf, const char *fmt, ...) |
| 1413 | { | 1468 | { |
| 1414 | va_list args; | 1469 | va_list args; |
| 1415 | int i; | 1470 | int i; |
| 1416 | 1471 | ||
| 1417 | va_start(args, fmt); | 1472 | va_start(args, fmt); |
| 1418 | i=vsnprintf(buf, INT_MAX, fmt, args); | 1473 | i = vsnprintf(buf, INT_MAX, fmt, args); |
| 1419 | va_end(args); | 1474 | va_end(args); |
| 1475 | |||
| 1420 | return i; | 1476 | return i; |
| 1421 | } | 1477 | } |
| 1422 | EXPORT_SYMBOL(sprintf); | 1478 | EXPORT_SYMBOL(sprintf); |
| @@ -1449,7 +1505,6 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args) | |||
| 1449 | { | 1505 | { |
| 1450 | struct printf_spec spec = {0}; | 1506 | struct printf_spec spec = {0}; |
| 1451 | char *str, *end; | 1507 | char *str, *end; |
| 1452 | int read; | ||
| 1453 | 1508 | ||
| 1454 | str = (char *)bin_buf; | 1509 | str = (char *)bin_buf; |
| 1455 | end = (char *)(bin_buf + size); | 1510 | end = (char *)(bin_buf + size); |
| @@ -1474,14 +1529,15 @@ do { \ | |||
| 1474 | str += sizeof(type); \ | 1529 | str += sizeof(type); \ |
| 1475 | } while (0) | 1530 | } while (0) |
| 1476 | 1531 | ||
| 1477 | |||
| 1478 | while (*fmt) { | 1532 | while (*fmt) { |
| 1479 | read = format_decode(fmt, &spec); | 1533 | int read = format_decode(fmt, &spec); |
| 1480 | 1534 | ||
| 1481 | fmt += read; | 1535 | fmt += read; |
| 1482 | 1536 | ||
| 1483 | switch (spec.type) { | 1537 | switch (spec.type) { |
| 1484 | case FORMAT_TYPE_NONE: | 1538 | case FORMAT_TYPE_NONE: |
| 1539 | case FORMAT_TYPE_INVALID: | ||
| 1540 | case FORMAT_TYPE_PERCENT_CHAR: | ||
| 1485 | break; | 1541 | break; |
| 1486 | 1542 | ||
| 1487 | case FORMAT_TYPE_WIDTH: | 1543 | case FORMAT_TYPE_WIDTH: |
| @@ -1496,13 +1552,14 @@ do { \ | |||
| 1496 | case FORMAT_TYPE_STR: { | 1552 | case FORMAT_TYPE_STR: { |
| 1497 | const char *save_str = va_arg(args, char *); | 1553 | const char *save_str = va_arg(args, char *); |
| 1498 | size_t len; | 1554 | size_t len; |
| 1555 | |||
| 1499 | if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE | 1556 | if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE |
| 1500 | || (unsigned long)save_str < PAGE_SIZE) | 1557 | || (unsigned long)save_str < PAGE_SIZE) |
| 1501 | save_str = "<NULL>"; | 1558 | save_str = "(null)"; |
| 1502 | len = strlen(save_str); | 1559 | len = strlen(save_str) + 1; |
| 1503 | if (str + len + 1 < end) | 1560 | if (str + len < end) |
| 1504 | memcpy(str, save_str, len + 1); | 1561 | memcpy(str, save_str, len); |
| 1505 | str += len + 1; | 1562 | str += len; |
| 1506 | break; | 1563 | break; |
| 1507 | } | 1564 | } |
| 1508 | 1565 | ||
| @@ -1513,19 +1570,13 @@ do { \ | |||
| 1513 | fmt++; | 1570 | fmt++; |
| 1514 | break; | 1571 | break; |
| 1515 | 1572 | ||
| 1516 | case FORMAT_TYPE_PERCENT_CHAR: | ||
| 1517 | break; | ||
| 1518 | |||
| 1519 | case FORMAT_TYPE_INVALID: | ||
| 1520 | break; | ||
| 1521 | |||
| 1522 | case FORMAT_TYPE_NRCHARS: { | 1573 | case FORMAT_TYPE_NRCHARS: { |
| 1523 | /* skip %n 's argument */ | 1574 | /* skip %n 's argument */ |
| 1524 | int qualifier = spec.qualifier; | 1575 | int qualifier = spec.qualifier; |
| 1525 | void *skip_arg; | 1576 | void *skip_arg; |
| 1526 | if (qualifier == 'l') | 1577 | if (qualifier == 'l') |
| 1527 | skip_arg = va_arg(args, long *); | 1578 | skip_arg = va_arg(args, long *); |
| 1528 | else if (qualifier == 'Z' || qualifier == 'z') | 1579 | else if (TOLOWER(qualifier) == 'z') |
| 1529 | skip_arg = va_arg(args, size_t *); | 1580 | skip_arg = va_arg(args, size_t *); |
| 1530 | else | 1581 | else |
| 1531 | skip_arg = va_arg(args, int *); | 1582 | skip_arg = va_arg(args, int *); |
| @@ -1561,8 +1612,8 @@ do { \ | |||
| 1561 | } | 1612 | } |
| 1562 | } | 1613 | } |
| 1563 | } | 1614 | } |
| 1564 | return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf; | ||
| 1565 | 1615 | ||
| 1616 | return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf; | ||
| 1566 | #undef save_arg | 1617 | #undef save_arg |
| 1567 | } | 1618 | } |
| 1568 | EXPORT_SYMBOL_GPL(vbin_printf); | 1619 | EXPORT_SYMBOL_GPL(vbin_printf); |
| @@ -1591,11 +1642,9 @@ EXPORT_SYMBOL_GPL(vbin_printf); | |||
| 1591 | */ | 1642 | */ |
| 1592 | int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | 1643 | int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) |
| 1593 | { | 1644 | { |
| 1594 | unsigned long long num; | ||
| 1595 | char *str, *end, c; | ||
| 1596 | const char *args = (const char *)bin_buf; | ||
| 1597 | |||
| 1598 | struct printf_spec spec = {0}; | 1645 | struct printf_spec spec = {0}; |
| 1646 | char *str, *end; | ||
| 1647 | const char *args = (const char *)bin_buf; | ||
| 1599 | 1648 | ||
| 1600 | if (WARN_ON_ONCE((int) size < 0)) | 1649 | if (WARN_ON_ONCE((int) size < 0)) |
| 1601 | return 0; | 1650 | return 0; |
| @@ -1625,10 +1674,8 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 1625 | } | 1674 | } |
| 1626 | 1675 | ||
| 1627 | while (*fmt) { | 1676 | while (*fmt) { |
| 1628 | int read; | ||
| 1629 | const char *old_fmt = fmt; | 1677 | const char *old_fmt = fmt; |
| 1630 | 1678 | int read = format_decode(fmt, &spec); | |
| 1631 | read = format_decode(fmt, &spec); | ||
| 1632 | 1679 | ||
| 1633 | fmt += read; | 1680 | fmt += read; |
| 1634 | 1681 | ||
| @@ -1652,7 +1699,9 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 1652 | spec.precision = get_arg(int); | 1699 | spec.precision = get_arg(int); |
| 1653 | break; | 1700 | break; |
| 1654 | 1701 | ||
| 1655 | case FORMAT_TYPE_CHAR: | 1702 | case FORMAT_TYPE_CHAR: { |
| 1703 | char c; | ||
| 1704 | |||
| 1656 | if (!(spec.flags & LEFT)) { | 1705 | if (!(spec.flags & LEFT)) { |
| 1657 | while (--spec.field_width > 0) { | 1706 | while (--spec.field_width > 0) { |
| 1658 | if (str < end) | 1707 | if (str < end) |
| @@ -1670,11 +1719,11 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 1670 | ++str; | 1719 | ++str; |
| 1671 | } | 1720 | } |
| 1672 | break; | 1721 | break; |
| 1722 | } | ||
| 1673 | 1723 | ||
| 1674 | case FORMAT_TYPE_STR: { | 1724 | case FORMAT_TYPE_STR: { |
| 1675 | const char *str_arg = args; | 1725 | const char *str_arg = args; |
| 1676 | size_t len = strlen(str_arg); | 1726 | args += strlen(str_arg) + 1; |
| 1677 | args += len + 1; | ||
| 1678 | str = string(str, end, (char *)str_arg, spec); | 1727 | str = string(str, end, (char *)str_arg, spec); |
| 1679 | break; | 1728 | break; |
| 1680 | } | 1729 | } |
| @@ -1686,11 +1735,6 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 1686 | break; | 1735 | break; |
| 1687 | 1736 | ||
| 1688 | case FORMAT_TYPE_PERCENT_CHAR: | 1737 | case FORMAT_TYPE_PERCENT_CHAR: |
| 1689 | if (str < end) | ||
| 1690 | *str = '%'; | ||
| 1691 | ++str; | ||
| 1692 | break; | ||
| 1693 | |||
| 1694 | case FORMAT_TYPE_INVALID: | 1738 | case FORMAT_TYPE_INVALID: |
| 1695 | if (str < end) | 1739 | if (str < end) |
| 1696 | *str = '%'; | 1740 | *str = '%'; |
| @@ -1701,15 +1745,15 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 1701 | /* skip */ | 1745 | /* skip */ |
| 1702 | break; | 1746 | break; |
| 1703 | 1747 | ||
| 1704 | default: | 1748 | default: { |
| 1749 | unsigned long long num; | ||
| 1750 | |||
| 1705 | switch (spec.type) { | 1751 | switch (spec.type) { |
| 1706 | 1752 | ||
| 1707 | case FORMAT_TYPE_LONG_LONG: | 1753 | case FORMAT_TYPE_LONG_LONG: |
| 1708 | num = get_arg(long long); | 1754 | num = get_arg(long long); |
| 1709 | break; | 1755 | break; |
| 1710 | case FORMAT_TYPE_ULONG: | 1756 | case FORMAT_TYPE_ULONG: |
| 1711 | num = get_arg(unsigned long); | ||
| 1712 | break; | ||
| 1713 | case FORMAT_TYPE_LONG: | 1757 | case FORMAT_TYPE_LONG: |
| 1714 | num = get_arg(unsigned long); | 1758 | num = get_arg(unsigned long); |
| 1715 | break; | 1759 | break; |
| @@ -1739,8 +1783,9 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 1739 | } | 1783 | } |
| 1740 | 1784 | ||
| 1741 | str = number(str, end, num, spec); | 1785 | str = number(str, end, num, spec); |
| 1742 | } | 1786 | } /* default: */ |
| 1743 | } | 1787 | } /* switch(spec.type) */ |
| 1788 | } /* while(*fmt) */ | ||
| 1744 | 1789 | ||
| 1745 | if (size > 0) { | 1790 | if (size > 0) { |
| 1746 | if (str < end) | 1791 | if (str < end) |
| @@ -1774,6 +1819,7 @@ int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) | |||
| 1774 | va_start(args, fmt); | 1819 | va_start(args, fmt); |
| 1775 | ret = vbin_printf(bin_buf, size, fmt, args); | 1820 | ret = vbin_printf(bin_buf, size, fmt, args); |
| 1776 | va_end(args); | 1821 | va_end(args); |
| 1822 | |||
| 1777 | return ret; | 1823 | return ret; |
| 1778 | } | 1824 | } |
| 1779 | EXPORT_SYMBOL_GPL(bprintf); | 1825 | EXPORT_SYMBOL_GPL(bprintf); |
| @@ -1786,27 +1832,23 @@ EXPORT_SYMBOL_GPL(bprintf); | |||
| 1786 | * @fmt: format of buffer | 1832 | * @fmt: format of buffer |
| 1787 | * @args: arguments | 1833 | * @args: arguments |
| 1788 | */ | 1834 | */ |
| 1789 | int vsscanf(const char * buf, const char * fmt, va_list args) | 1835 | int vsscanf(const char *buf, const char *fmt, va_list args) |
| 1790 | { | 1836 | { |
| 1791 | const char *str = buf; | 1837 | const char *str = buf; |
| 1792 | char *next; | 1838 | char *next; |
| 1793 | char digit; | 1839 | char digit; |
| 1794 | int num = 0; | 1840 | int num = 0; |
| 1795 | int qualifier; | 1841 | int qualifier, base, field_width; |
| 1796 | int base; | 1842 | bool is_sign; |
| 1797 | int field_width; | ||
| 1798 | int is_sign = 0; | ||
| 1799 | 1843 | ||
| 1800 | while(*fmt && *str) { | 1844 | while (*fmt && *str) { |
| 1801 | /* skip any white space in format */ | 1845 | /* skip any white space in format */ |
| 1802 | /* white space in format matchs any amount of | 1846 | /* white space in format matchs any amount of |
| 1803 | * white space, including none, in the input. | 1847 | * white space, including none, in the input. |
| 1804 | */ | 1848 | */ |
| 1805 | if (isspace(*fmt)) { | 1849 | if (isspace(*fmt)) { |
| 1806 | while (isspace(*fmt)) | 1850 | fmt = skip_spaces(++fmt); |
| 1807 | ++fmt; | 1851 | str = skip_spaces(str); |
| 1808 | while (isspace(*str)) | ||
| 1809 | ++str; | ||
| 1810 | } | 1852 | } |
| 1811 | 1853 | ||
| 1812 | /* anything that is not a conversion must match exactly */ | 1854 | /* anything that is not a conversion must match exactly */ |
| @@ -1819,7 +1861,7 @@ int vsscanf(const char * buf, const char * fmt, va_list args) | |||
| 1819 | if (!*fmt) | 1861 | if (!*fmt) |
| 1820 | break; | 1862 | break; |
| 1821 | ++fmt; | 1863 | ++fmt; |
| 1822 | 1864 | ||
| 1823 | /* skip this conversion. | 1865 | /* skip this conversion. |
| 1824 | * advance both strings to next white space | 1866 | * advance both strings to next white space |
| 1825 | */ | 1867 | */ |
| @@ -1838,8 +1880,8 @@ int vsscanf(const char * buf, const char * fmt, va_list args) | |||
| 1838 | 1880 | ||
| 1839 | /* get conversion qualifier */ | 1881 | /* get conversion qualifier */ |
| 1840 | qualifier = -1; | 1882 | qualifier = -1; |
| 1841 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || | 1883 | if (*fmt == 'h' || TOLOWER(*fmt) == 'l' || |
| 1842 | *fmt == 'Z' || *fmt == 'z') { | 1884 | TOLOWER(*fmt) == 'z') { |
| 1843 | qualifier = *fmt++; | 1885 | qualifier = *fmt++; |
| 1844 | if (unlikely(qualifier == *fmt)) { | 1886 | if (unlikely(qualifier == *fmt)) { |
| 1845 | if (qualifier == 'h') { | 1887 | if (qualifier == 'h') { |
| @@ -1851,16 +1893,17 @@ int vsscanf(const char * buf, const char * fmt, va_list args) | |||
| 1851 | } | 1893 | } |
| 1852 | } | 1894 | } |
| 1853 | } | 1895 | } |
| 1854 | base = 10; | ||
| 1855 | is_sign = 0; | ||
| 1856 | 1896 | ||
| 1857 | if (!*fmt || !*str) | 1897 | if (!*fmt || !*str) |
| 1858 | break; | 1898 | break; |
| 1859 | 1899 | ||
| 1860 | switch(*fmt++) { | 1900 | base = 10; |
| 1901 | is_sign = 0; | ||
| 1902 | |||
| 1903 | switch (*fmt++) { | ||
| 1861 | case 'c': | 1904 | case 'c': |
| 1862 | { | 1905 | { |
| 1863 | char *s = (char *) va_arg(args,char*); | 1906 | char *s = (char *)va_arg(args, char*); |
| 1864 | if (field_width == -1) | 1907 | if (field_width == -1) |
| 1865 | field_width = 1; | 1908 | field_width = 1; |
| 1866 | do { | 1909 | do { |
| @@ -1871,17 +1914,15 @@ int vsscanf(const char * buf, const char * fmt, va_list args) | |||
| 1871 | continue; | 1914 | continue; |
| 1872 | case 's': | 1915 | case 's': |
| 1873 | { | 1916 | { |
| 1874 | char *s = (char *) va_arg(args, char *); | 1917 | char *s = (char *)va_arg(args, char *); |
| 1875 | if(field_width == -1) | 1918 | if (field_width == -1) |
| 1876 | field_width = INT_MAX; | 1919 | field_width = INT_MAX; |
| 1877 | /* first, skip leading white space in buffer */ | 1920 | /* first, skip leading white space in buffer */ |
| 1878 | while (isspace(*str)) | 1921 | str = skip_spaces(str); |
| 1879 | str++; | ||
| 1880 | 1922 | ||
| 1881 | /* now copy until next white space */ | 1923 | /* now copy until next white space */ |
| 1882 | while (*str && !isspace(*str) && field_width--) { | 1924 | while (*str && !isspace(*str) && field_width--) |
| 1883 | *s++ = *str++; | 1925 | *s++ = *str++; |
| 1884 | } | ||
| 1885 | *s = '\0'; | 1926 | *s = '\0'; |
| 1886 | num++; | 1927 | num++; |
| 1887 | } | 1928 | } |
| @@ -1889,7 +1930,7 @@ int vsscanf(const char * buf, const char * fmt, va_list args) | |||
| 1889 | case 'n': | 1930 | case 'n': |
| 1890 | /* return number of characters read so far */ | 1931 | /* return number of characters read so far */ |
| 1891 | { | 1932 | { |
| 1892 | int *i = (int *)va_arg(args,int*); | 1933 | int *i = (int *)va_arg(args, int*); |
| 1893 | *i = str - buf; | 1934 | *i = str - buf; |
| 1894 | } | 1935 | } |
| 1895 | continue; | 1936 | continue; |
| @@ -1901,14 +1942,14 @@ int vsscanf(const char * buf, const char * fmt, va_list args) | |||
| 1901 | base = 16; | 1942 | base = 16; |
| 1902 | break; | 1943 | break; |
| 1903 | case 'i': | 1944 | case 'i': |
| 1904 | base = 0; | 1945 | base = 0; |
| 1905 | case 'd': | 1946 | case 'd': |
| 1906 | is_sign = 1; | 1947 | is_sign = 1; |
| 1907 | case 'u': | 1948 | case 'u': |
| 1908 | break; | 1949 | break; |
| 1909 | case '%': | 1950 | case '%': |
| 1910 | /* looking for '%' in str */ | 1951 | /* looking for '%' in str */ |
| 1911 | if (*str++ != '%') | 1952 | if (*str++ != '%') |
| 1912 | return num; | 1953 | return num; |
| 1913 | continue; | 1954 | continue; |
| 1914 | default: | 1955 | default: |
| @@ -1919,71 +1960,70 @@ int vsscanf(const char * buf, const char * fmt, va_list args) | |||
| 1919 | /* have some sort of integer conversion. | 1960 | /* have some sort of integer conversion. |
| 1920 | * first, skip white space in buffer. | 1961 | * first, skip white space in buffer. |
| 1921 | */ | 1962 | */ |
| 1922 | while (isspace(*str)) | 1963 | str = skip_spaces(str); |
| 1923 | str++; | ||
| 1924 | 1964 | ||
| 1925 | digit = *str; | 1965 | digit = *str; |
| 1926 | if (is_sign && digit == '-') | 1966 | if (is_sign && digit == '-') |
| 1927 | digit = *(str + 1); | 1967 | digit = *(str + 1); |
| 1928 | 1968 | ||
| 1929 | if (!digit | 1969 | if (!digit |
| 1930 | || (base == 16 && !isxdigit(digit)) | 1970 | || (base == 16 && !isxdigit(digit)) |
| 1931 | || (base == 10 && !isdigit(digit)) | 1971 | || (base == 10 && !isdigit(digit)) |
| 1932 | || (base == 8 && (!isdigit(digit) || digit > '7')) | 1972 | || (base == 8 && (!isdigit(digit) || digit > '7')) |
| 1933 | || (base == 0 && !isdigit(digit))) | 1973 | || (base == 0 && !isdigit(digit))) |
| 1934 | break; | 1974 | break; |
| 1935 | 1975 | ||
| 1936 | switch(qualifier) { | 1976 | switch (qualifier) { |
| 1937 | case 'H': /* that's 'hh' in format */ | 1977 | case 'H': /* that's 'hh' in format */ |
| 1938 | if (is_sign) { | 1978 | if (is_sign) { |
| 1939 | signed char *s = (signed char *) va_arg(args,signed char *); | 1979 | signed char *s = (signed char *)va_arg(args, signed char *); |
| 1940 | *s = (signed char) simple_strtol(str,&next,base); | 1980 | *s = (signed char)simple_strtol(str, &next, base); |
| 1941 | } else { | 1981 | } else { |
| 1942 | unsigned char *s = (unsigned char *) va_arg(args, unsigned char *); | 1982 | unsigned char *s = (unsigned char *)va_arg(args, unsigned char *); |
| 1943 | *s = (unsigned char) simple_strtoul(str, &next, base); | 1983 | *s = (unsigned char)simple_strtoul(str, &next, base); |
| 1944 | } | 1984 | } |
| 1945 | break; | 1985 | break; |
| 1946 | case 'h': | 1986 | case 'h': |
| 1947 | if (is_sign) { | 1987 | if (is_sign) { |
| 1948 | short *s = (short *) va_arg(args,short *); | 1988 | short *s = (short *)va_arg(args, short *); |
| 1949 | *s = (short) simple_strtol(str,&next,base); | 1989 | *s = (short)simple_strtol(str, &next, base); |
| 1950 | } else { | 1990 | } else { |
| 1951 | unsigned short *s = (unsigned short *) va_arg(args, unsigned short *); | 1991 | unsigned short *s = (unsigned short *)va_arg(args, unsigned short *); |
| 1952 | *s = (unsigned short) simple_strtoul(str, &next, base); | 1992 | *s = (unsigned short)simple_strtoul(str, &next, base); |
| 1953 | } | 1993 | } |
| 1954 | break; | 1994 | break; |
| 1955 | case 'l': | 1995 | case 'l': |
| 1956 | if (is_sign) { | 1996 | if (is_sign) { |
| 1957 | long *l = (long *) va_arg(args,long *); | 1997 | long *l = (long *)va_arg(args, long *); |
| 1958 | *l = simple_strtol(str,&next,base); | 1998 | *l = simple_strtol(str, &next, base); |
| 1959 | } else { | 1999 | } else { |
| 1960 | unsigned long *l = (unsigned long*) va_arg(args,unsigned long*); | 2000 | unsigned long *l = (unsigned long *)va_arg(args, unsigned long *); |
| 1961 | *l = simple_strtoul(str,&next,base); | 2001 | *l = simple_strtoul(str, &next, base); |
| 1962 | } | 2002 | } |
| 1963 | break; | 2003 | break; |
| 1964 | case 'L': | 2004 | case 'L': |
| 1965 | if (is_sign) { | 2005 | if (is_sign) { |
| 1966 | long long *l = (long long*) va_arg(args,long long *); | 2006 | long long *l = (long long *)va_arg(args, long long *); |
| 1967 | *l = simple_strtoll(str,&next,base); | 2007 | *l = simple_strtoll(str, &next, base); |
| 1968 | } else { | 2008 | } else { |
| 1969 | unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*); | 2009 | unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *); |
| 1970 | *l = simple_strtoull(str,&next,base); | 2010 | *l = simple_strtoull(str, &next, base); |
| 1971 | } | 2011 | } |
| 1972 | break; | 2012 | break; |
| 1973 | case 'Z': | 2013 | case 'Z': |
| 1974 | case 'z': | 2014 | case 'z': |
| 1975 | { | 2015 | { |
| 1976 | size_t *s = (size_t*) va_arg(args,size_t*); | 2016 | size_t *s = (size_t *)va_arg(args, size_t *); |
| 1977 | *s = (size_t) simple_strtoul(str,&next,base); | 2017 | *s = (size_t)simple_strtoul(str, &next, base); |
| 1978 | } | 2018 | } |
| 1979 | break; | 2019 | break; |
| 1980 | default: | 2020 | default: |
| 1981 | if (is_sign) { | 2021 | if (is_sign) { |
| 1982 | int *i = (int *) va_arg(args, int*); | 2022 | int *i = (int *)va_arg(args, int *); |
| 1983 | *i = (int) simple_strtol(str,&next,base); | 2023 | *i = (int)simple_strtol(str, &next, base); |
| 1984 | } else { | 2024 | } else { |
| 1985 | unsigned int *i = (unsigned int*) va_arg(args, unsigned int*); | 2025 | unsigned int *i = (unsigned int *)va_arg(args, unsigned int*); |
| 1986 | *i = (unsigned int) simple_strtoul(str,&next,base); | 2026 | *i = (unsigned int)simple_strtoul(str, &next, base); |
| 1987 | } | 2027 | } |
| 1988 | break; | 2028 | break; |
| 1989 | } | 2029 | } |
| @@ -2014,14 +2054,15 @@ EXPORT_SYMBOL(vsscanf); | |||
| 2014 | * @fmt: formatting of buffer | 2054 | * @fmt: formatting of buffer |
| 2015 | * @...: resulting arguments | 2055 | * @...: resulting arguments |
| 2016 | */ | 2056 | */ |
| 2017 | int sscanf(const char * buf, const char * fmt, ...) | 2057 | int sscanf(const char *buf, const char *fmt, ...) |
| 2018 | { | 2058 | { |
| 2019 | va_list args; | 2059 | va_list args; |
| 2020 | int i; | 2060 | int i; |
| 2021 | 2061 | ||
| 2022 | va_start(args,fmt); | 2062 | va_start(args, fmt); |
| 2023 | i = vsscanf(buf,fmt,args); | 2063 | i = vsscanf(buf, fmt, args); |
| 2024 | va_end(args); | 2064 | va_end(args); |
| 2065 | |||
| 2025 | return i; | 2066 | return i; |
| 2026 | } | 2067 | } |
| 2027 | EXPORT_SYMBOL(sscanf); | 2068 | EXPORT_SYMBOL(sscanf); |
diff --git a/mm/Kconfig b/mm/Kconfig index 44cf6f0a3a6d..2310984591ed 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
| @@ -158,11 +158,13 @@ config PAGEFLAGS_EXTENDED | |||
| 158 | # Default to 4 for wider testing, though 8 might be more appropriate. | 158 | # Default to 4 for wider testing, though 8 might be more appropriate. |
| 159 | # ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. | 159 | # ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. |
| 160 | # PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. | 160 | # PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. |
| 161 | # DEBUG_SPINLOCK and DEBUG_LOCK_ALLOC spinlock_t also enlarge struct page. | ||
| 161 | # | 162 | # |
| 162 | config SPLIT_PTLOCK_CPUS | 163 | config SPLIT_PTLOCK_CPUS |
| 163 | int | 164 | int |
| 164 | default "4096" if ARM && !CPU_CACHE_VIPT | 165 | default "999999" if ARM && !CPU_CACHE_VIPT |
| 165 | default "4096" if PARISC && !PA20 | 166 | default "999999" if PARISC && !PA20 |
| 167 | default "999999" if DEBUG_SPINLOCK || DEBUG_LOCK_ALLOC | ||
| 166 | default "4" | 168 | default "4" |
| 167 | 169 | ||
| 168 | # | 170 | # |
| @@ -200,14 +202,6 @@ config VIRT_TO_BUS | |||
| 200 | def_bool y | 202 | def_bool y |
| 201 | depends on !ARCH_NO_VIRT_TO_BUS | 203 | depends on !ARCH_NO_VIRT_TO_BUS |
| 202 | 204 | ||
| 203 | config HAVE_MLOCK | ||
| 204 | bool | ||
| 205 | default y if MMU=y | ||
| 206 | |||
| 207 | config HAVE_MLOCKED_PAGE_BIT | ||
| 208 | bool | ||
| 209 | default y if HAVE_MLOCK=y | ||
| 210 | |||
| 211 | config MMU_NOTIFIER | 205 | config MMU_NOTIFIER |
| 212 | bool | 206 | bool |
| 213 | 207 | ||
| @@ -218,7 +212,7 @@ config KSM | |||
| 218 | Enable Kernel Samepage Merging: KSM periodically scans those areas | 212 | Enable Kernel Samepage Merging: KSM periodically scans those areas |
| 219 | of an application's address space that an app has advised may be | 213 | of an application's address space that an app has advised may be |
| 220 | mergeable. When it finds pages of identical content, it replaces | 214 | mergeable. When it finds pages of identical content, it replaces |
| 221 | the many instances by a single resident page with that content, so | 215 | the many instances by a single page with that content, so |
| 222 | saving memory until one or another app needs to modify the content. | 216 | saving memory until one or another app needs to modify the content. |
| 223 | Recommended for use with KVM, or with other duplicative applications. | 217 | Recommended for use with KVM, or with other duplicative applications. |
| 224 | See Documentation/vm/ksm.txt for more information: KSM is inactive | 218 | See Documentation/vm/ksm.txt for more information: KSM is inactive |
diff --git a/mm/bootmem.c b/mm/bootmem.c index d1dc23cc7f10..7d1486875e1c 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
| @@ -432,8 +432,8 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size, | |||
| 432 | return mark_bootmem(start, end, 1, flags); | 432 | return mark_bootmem(start, end, 1, flags); |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, | 435 | static unsigned long __init align_idx(struct bootmem_data *bdata, |
| 436 | unsigned long step) | 436 | unsigned long idx, unsigned long step) |
| 437 | { | 437 | { |
| 438 | unsigned long base = bdata->node_min_pfn; | 438 | unsigned long base = bdata->node_min_pfn; |
| 439 | 439 | ||
| @@ -445,8 +445,8 @@ static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, | |||
| 445 | return ALIGN(base + idx, step) - base; | 445 | return ALIGN(base + idx, step) - base; |
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | static unsigned long align_off(struct bootmem_data *bdata, unsigned long off, | 448 | static unsigned long __init align_off(struct bootmem_data *bdata, |
| 449 | unsigned long align) | 449 | unsigned long off, unsigned long align) |
| 450 | { | 450 | { |
| 451 | unsigned long base = PFN_PHYS(bdata->node_min_pfn); | 451 | unsigned long base = PFN_PHYS(bdata->node_min_pfn); |
| 452 | 452 | ||
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 5d7601b02874..65f38c218207 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 25 | 25 | ||
| 26 | #include <linux/hugetlb.h> | 26 | #include <linux/hugetlb.h> |
| 27 | #include <linux/node.h> | ||
| 27 | #include "internal.h" | 28 | #include "internal.h" |
| 28 | 29 | ||
| 29 | const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; | 30 | const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; |
| @@ -622,42 +623,66 @@ static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid) | |||
| 622 | } | 623 | } |
| 623 | 624 | ||
| 624 | /* | 625 | /* |
| 625 | * Use a helper variable to find the next node and then | 626 | * common helper functions for hstate_next_node_to_{alloc|free}. |
| 626 | * copy it back to next_nid_to_alloc afterwards: | 627 | * We may have allocated or freed a huge page based on a different |
| 627 | * otherwise there's a window in which a racer might | 628 | * nodes_allowed previously, so h->next_node_to_{alloc|free} might |
| 628 | * pass invalid nid MAX_NUMNODES to alloc_pages_exact_node. | 629 | * be outside of *nodes_allowed. Ensure that we use an allowed |
| 629 | * But we don't need to use a spin_lock here: it really | 630 | * node for alloc or free. |
| 630 | * doesn't matter if occasionally a racer chooses the | ||
| 631 | * same nid as we do. Move nid forward in the mask even | ||
| 632 | * if we just successfully allocated a hugepage so that | ||
| 633 | * the next caller gets hugepages on the next node. | ||
| 634 | */ | 631 | */ |
| 635 | static int hstate_next_node_to_alloc(struct hstate *h) | 632 | static int next_node_allowed(int nid, nodemask_t *nodes_allowed) |
| 636 | { | 633 | { |
| 637 | int next_nid; | 634 | nid = next_node(nid, *nodes_allowed); |
| 638 | next_nid = next_node(h->next_nid_to_alloc, node_online_map); | 635 | if (nid == MAX_NUMNODES) |
| 639 | if (next_nid == MAX_NUMNODES) | 636 | nid = first_node(*nodes_allowed); |
| 640 | next_nid = first_node(node_online_map); | 637 | VM_BUG_ON(nid >= MAX_NUMNODES); |
| 641 | h->next_nid_to_alloc = next_nid; | 638 | |
| 642 | return next_nid; | 639 | return nid; |
| 640 | } | ||
| 641 | |||
| 642 | static int get_valid_node_allowed(int nid, nodemask_t *nodes_allowed) | ||
| 643 | { | ||
| 644 | if (!node_isset(nid, *nodes_allowed)) | ||
| 645 | nid = next_node_allowed(nid, nodes_allowed); | ||
| 646 | return nid; | ||
| 647 | } | ||
| 648 | |||
| 649 | /* | ||
| 650 | * returns the previously saved node ["this node"] from which to | ||
| 651 | * allocate a persistent huge page for the pool and advance the | ||
| 652 | * next node from which to allocate, handling wrap at end of node | ||
| 653 | * mask. | ||
| 654 | */ | ||
| 655 | static int hstate_next_node_to_alloc(struct hstate *h, | ||
| 656 | nodemask_t *nodes_allowed) | ||
| 657 | { | ||
| 658 | int nid; | ||
| 659 | |||
| 660 | VM_BUG_ON(!nodes_allowed); | ||
| 661 | |||
| 662 | nid = get_valid_node_allowed(h->next_nid_to_alloc, nodes_allowed); | ||
| 663 | h->next_nid_to_alloc = next_node_allowed(nid, nodes_allowed); | ||
| 664 | |||
| 665 | return nid; | ||
| 643 | } | 666 | } |
| 644 | 667 | ||
| 645 | static int alloc_fresh_huge_page(struct hstate *h) | 668 | static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed) |
| 646 | { | 669 | { |
| 647 | struct page *page; | 670 | struct page *page; |
| 648 | int start_nid; | 671 | int start_nid; |
| 649 | int next_nid; | 672 | int next_nid; |
| 650 | int ret = 0; | 673 | int ret = 0; |
| 651 | 674 | ||
| 652 | start_nid = h->next_nid_to_alloc; | 675 | start_nid = hstate_next_node_to_alloc(h, nodes_allowed); |
| 653 | next_nid = start_nid; | 676 | next_nid = start_nid; |
| 654 | 677 | ||
| 655 | do { | 678 | do { |
| 656 | page = alloc_fresh_huge_page_node(h, next_nid); | 679 | page = alloc_fresh_huge_page_node(h, next_nid); |
| 657 | if (page) | 680 | if (page) { |
| 658 | ret = 1; | 681 | ret = 1; |
| 659 | next_nid = hstate_next_node_to_alloc(h); | 682 | break; |
| 660 | } while (!page && next_nid != start_nid); | 683 | } |
| 684 | next_nid = hstate_next_node_to_alloc(h, nodes_allowed); | ||
| 685 | } while (next_nid != start_nid); | ||
| 661 | 686 | ||
| 662 | if (ret) | 687 | if (ret) |
| 663 | count_vm_event(HTLB_BUDDY_PGALLOC); | 688 | count_vm_event(HTLB_BUDDY_PGALLOC); |
| @@ -668,17 +693,21 @@ static int alloc_fresh_huge_page(struct hstate *h) | |||
| 668 | } | 693 | } |
| 669 | 694 | ||
| 670 | /* | 695 | /* |
| 671 | * helper for free_pool_huge_page() - find next node | 696 | * helper for free_pool_huge_page() - return the previously saved |
| 672 | * from which to free a huge page | 697 | * node ["this node"] from which to free a huge page. Advance the |
| 698 | * next node id whether or not we find a free huge page to free so | ||
| 699 | * that the next attempt to free addresses the next node. | ||
| 673 | */ | 700 | */ |
| 674 | static int hstate_next_node_to_free(struct hstate *h) | 701 | static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed) |
| 675 | { | 702 | { |
| 676 | int next_nid; | 703 | int nid; |
| 677 | next_nid = next_node(h->next_nid_to_free, node_online_map); | 704 | |
| 678 | if (next_nid == MAX_NUMNODES) | 705 | VM_BUG_ON(!nodes_allowed); |
| 679 | next_nid = first_node(node_online_map); | 706 | |
| 680 | h->next_nid_to_free = next_nid; | 707 | nid = get_valid_node_allowed(h->next_nid_to_free, nodes_allowed); |
| 681 | return next_nid; | 708 | h->next_nid_to_free = next_node_allowed(nid, nodes_allowed); |
| 709 | |||
| 710 | return nid; | ||
| 682 | } | 711 | } |
| 683 | 712 | ||
| 684 | /* | 713 | /* |
| @@ -687,13 +716,14 @@ static int hstate_next_node_to_free(struct hstate *h) | |||
| 687 | * balanced over allowed nodes. | 716 | * balanced over allowed nodes. |
| 688 | * Called with hugetlb_lock locked. | 717 | * Called with hugetlb_lock locked. |
| 689 | */ | 718 | */ |
| 690 | static int free_pool_huge_page(struct hstate *h, bool acct_surplus) | 719 | static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed, |
| 720 | bool acct_surplus) | ||
| 691 | { | 721 | { |
| 692 | int start_nid; | 722 | int start_nid; |
| 693 | int next_nid; | 723 | int next_nid; |
| 694 | int ret = 0; | 724 | int ret = 0; |
| 695 | 725 | ||
| 696 | start_nid = h->next_nid_to_free; | 726 | start_nid = hstate_next_node_to_free(h, nodes_allowed); |
| 697 | next_nid = start_nid; | 727 | next_nid = start_nid; |
| 698 | 728 | ||
| 699 | do { | 729 | do { |
| @@ -715,9 +745,10 @@ static int free_pool_huge_page(struct hstate *h, bool acct_surplus) | |||
| 715 | } | 745 | } |
| 716 | update_and_free_page(h, page); | 746 | update_and_free_page(h, page); |
| 717 | ret = 1; | 747 | ret = 1; |
| 748 | break; | ||
| 718 | } | 749 | } |
| 719 | next_nid = hstate_next_node_to_free(h); | 750 | next_nid = hstate_next_node_to_free(h, nodes_allowed); |
| 720 | } while (!ret && next_nid != start_nid); | 751 | } while (next_nid != start_nid); |
| 721 | 752 | ||
| 722 | return ret; | 753 | return ret; |
| 723 | } | 754 | } |
| @@ -911,14 +942,14 @@ static void return_unused_surplus_pages(struct hstate *h, | |||
| 911 | 942 | ||
| 912 | /* | 943 | /* |
| 913 | * We want to release as many surplus pages as possible, spread | 944 | * We want to release as many surplus pages as possible, spread |
| 914 | * evenly across all nodes. Iterate across all nodes until we | 945 | * evenly across all nodes with memory. Iterate across these nodes |
| 915 | * can no longer free unreserved surplus pages. This occurs when | 946 | * until we can no longer free unreserved surplus pages. This occurs |
| 916 | * the nodes with surplus pages have no free pages. | 947 | * when the nodes with surplus pages have no free pages. |
| 917 | * free_pool_huge_page() will balance the the frees across the | 948 | * free_pool_huge_page() will balance the the freed pages across the |
| 918 | * on-line nodes for us and will handle the hstate accounting. | 949 | * on-line nodes with memory and will handle the hstate accounting. |
| 919 | */ | 950 | */ |
| 920 | while (nr_pages--) { | 951 | while (nr_pages--) { |
| 921 | if (!free_pool_huge_page(h, 1)) | 952 | if (!free_pool_huge_page(h, &node_states[N_HIGH_MEMORY], 1)) |
| 922 | break; | 953 | break; |
| 923 | } | 954 | } |
| 924 | } | 955 | } |
| @@ -1022,16 +1053,16 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, | |||
| 1022 | int __weak alloc_bootmem_huge_page(struct hstate *h) | 1053 | int __weak alloc_bootmem_huge_page(struct hstate *h) |
| 1023 | { | 1054 | { |
| 1024 | struct huge_bootmem_page *m; | 1055 | struct huge_bootmem_page *m; |
| 1025 | int nr_nodes = nodes_weight(node_online_map); | 1056 | int nr_nodes = nodes_weight(node_states[N_HIGH_MEMORY]); |
| 1026 | 1057 | ||
| 1027 | while (nr_nodes) { | 1058 | while (nr_nodes) { |
| 1028 | void *addr; | 1059 | void *addr; |
| 1029 | 1060 | ||
| 1030 | addr = __alloc_bootmem_node_nopanic( | 1061 | addr = __alloc_bootmem_node_nopanic( |
| 1031 | NODE_DATA(h->next_nid_to_alloc), | 1062 | NODE_DATA(hstate_next_node_to_alloc(h, |
| 1063 | &node_states[N_HIGH_MEMORY])), | ||
| 1032 | huge_page_size(h), huge_page_size(h), 0); | 1064 | huge_page_size(h), huge_page_size(h), 0); |
| 1033 | 1065 | ||
| 1034 | hstate_next_node_to_alloc(h); | ||
| 1035 | if (addr) { | 1066 | if (addr) { |
| 1036 | /* | 1067 | /* |
| 1037 | * Use the beginning of the huge page to store the | 1068 | * Use the beginning of the huge page to store the |
| @@ -1084,7 +1115,8 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h) | |||
| 1084 | if (h->order >= MAX_ORDER) { | 1115 | if (h->order >= MAX_ORDER) { |
| 1085 | if (!alloc_bootmem_huge_page(h)) | 1116 | if (!alloc_bootmem_huge_page(h)) |
| 1086 | break; | 1117 | break; |
| 1087 | } else if (!alloc_fresh_huge_page(h)) | 1118 | } else if (!alloc_fresh_huge_page(h, |
| 1119 | &node_states[N_HIGH_MEMORY])) | ||
| 1088 | break; | 1120 | break; |
| 1089 | } | 1121 | } |
| 1090 | h->max_huge_pages = i; | 1122 | h->max_huge_pages = i; |
| @@ -1126,14 +1158,15 @@ static void __init report_hugepages(void) | |||
| 1126 | } | 1158 | } |
| 1127 | 1159 | ||
| 1128 | #ifdef CONFIG_HIGHMEM | 1160 | #ifdef CONFIG_HIGHMEM |
| 1129 | static void try_to_free_low(struct hstate *h, unsigned long count) | 1161 | static void try_to_free_low(struct hstate *h, unsigned long count, |
| 1162 | nodemask_t *nodes_allowed) | ||
| 1130 | { | 1163 | { |
| 1131 | int i; | 1164 | int i; |
| 1132 | 1165 | ||
| 1133 | if (h->order >= MAX_ORDER) | 1166 | if (h->order >= MAX_ORDER) |
| 1134 | return; | 1167 | return; |
| 1135 | 1168 | ||
| 1136 | for (i = 0; i < MAX_NUMNODES; ++i) { | 1169 | for_each_node_mask(i, *nodes_allowed) { |
| 1137 | struct page *page, *next; | 1170 | struct page *page, *next; |
| 1138 | struct list_head *freel = &h->hugepage_freelists[i]; | 1171 | struct list_head *freel = &h->hugepage_freelists[i]; |
| 1139 | list_for_each_entry_safe(page, next, freel, lru) { | 1172 | list_for_each_entry_safe(page, next, freel, lru) { |
| @@ -1149,7 +1182,8 @@ static void try_to_free_low(struct hstate *h, unsigned long count) | |||
| 1149 | } | 1182 | } |
| 1150 | } | 1183 | } |
| 1151 | #else | 1184 | #else |
| 1152 | static inline void try_to_free_low(struct hstate *h, unsigned long count) | 1185 | static inline void try_to_free_low(struct hstate *h, unsigned long count, |
| 1186 | nodemask_t *nodes_allowed) | ||
| 1153 | { | 1187 | { |
| 1154 | } | 1188 | } |
| 1155 | #endif | 1189 | #endif |
| @@ -1159,7 +1193,8 @@ static inline void try_to_free_low(struct hstate *h, unsigned long count) | |||
| 1159 | * balanced by operating on them in a round-robin fashion. | 1193 | * balanced by operating on them in a round-robin fashion. |
| 1160 | * Returns 1 if an adjustment was made. | 1194 | * Returns 1 if an adjustment was made. |
| 1161 | */ | 1195 | */ |
| 1162 | static int adjust_pool_surplus(struct hstate *h, int delta) | 1196 | static int adjust_pool_surplus(struct hstate *h, nodemask_t *nodes_allowed, |
| 1197 | int delta) | ||
| 1163 | { | 1198 | { |
| 1164 | int start_nid, next_nid; | 1199 | int start_nid, next_nid; |
| 1165 | int ret = 0; | 1200 | int ret = 0; |
| @@ -1167,29 +1202,33 @@ static int adjust_pool_surplus(struct hstate *h, int delta) | |||
| 1167 | VM_BUG_ON(delta != -1 && delta != 1); | 1202 | VM_BUG_ON(delta != -1 && delta != 1); |
| 1168 | 1203 | ||
| 1169 | if (delta < 0) | 1204 | if (delta < 0) |
| 1170 | start_nid = h->next_nid_to_alloc; | 1205 | start_nid = hstate_next_node_to_alloc(h, nodes_allowed); |
| 1171 | else | 1206 | else |
| 1172 | start_nid = h->next_nid_to_free; | 1207 | start_nid = hstate_next_node_to_free(h, nodes_allowed); |
| 1173 | next_nid = start_nid; | 1208 | next_nid = start_nid; |
| 1174 | 1209 | ||
| 1175 | do { | 1210 | do { |
| 1176 | int nid = next_nid; | 1211 | int nid = next_nid; |
| 1177 | if (delta < 0) { | 1212 | if (delta < 0) { |
| 1178 | next_nid = hstate_next_node_to_alloc(h); | ||
| 1179 | /* | 1213 | /* |
| 1180 | * To shrink on this node, there must be a surplus page | 1214 | * To shrink on this node, there must be a surplus page |
| 1181 | */ | 1215 | */ |
| 1182 | if (!h->surplus_huge_pages_node[nid]) | 1216 | if (!h->surplus_huge_pages_node[nid]) { |
| 1217 | next_nid = hstate_next_node_to_alloc(h, | ||
| 1218 | nodes_allowed); | ||
| 1183 | continue; | 1219 | continue; |
| 1220 | } | ||
| 1184 | } | 1221 | } |
| 1185 | if (delta > 0) { | 1222 | if (delta > 0) { |
| 1186 | next_nid = hstate_next_node_to_free(h); | ||
| 1187 | /* | 1223 | /* |
| 1188 | * Surplus cannot exceed the total number of pages | 1224 | * Surplus cannot exceed the total number of pages |
| 1189 | */ | 1225 | */ |
| 1190 | if (h->surplus_huge_pages_node[nid] >= | 1226 | if (h->surplus_huge_pages_node[nid] >= |
| 1191 | h->nr_huge_pages_node[nid]) | 1227 | h->nr_huge_pages_node[nid]) { |
| 1228 | next_nid = hstate_next_node_to_free(h, | ||
| 1229 | nodes_allowed); | ||
| 1192 | continue; | 1230 | continue; |
| 1231 | } | ||
| 1193 | } | 1232 | } |
| 1194 | 1233 | ||
| 1195 | h->surplus_huge_pages += delta; | 1234 | h->surplus_huge_pages += delta; |
| @@ -1202,7 +1241,8 @@ static int adjust_pool_surplus(struct hstate *h, int delta) | |||
| 1202 | } | 1241 | } |
| 1203 | 1242 | ||
| 1204 | #define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages) | 1243 | #define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages) |
| 1205 | static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count) | 1244 | static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count, |
| 1245 | nodemask_t *nodes_allowed) | ||
| 1206 | { | 1246 | { |
| 1207 | unsigned long min_count, ret; | 1247 | unsigned long min_count, ret; |
| 1208 | 1248 | ||
| @@ -1222,7 +1262,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count) | |||
| 1222 | */ | 1262 | */ |
| 1223 | spin_lock(&hugetlb_lock); | 1263 | spin_lock(&hugetlb_lock); |
| 1224 | while (h->surplus_huge_pages && count > persistent_huge_pages(h)) { | 1264 | while (h->surplus_huge_pages && count > persistent_huge_pages(h)) { |
| 1225 | if (!adjust_pool_surplus(h, -1)) | 1265 | if (!adjust_pool_surplus(h, nodes_allowed, -1)) |
| 1226 | break; | 1266 | break; |
| 1227 | } | 1267 | } |
| 1228 | 1268 | ||
| @@ -1233,11 +1273,14 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count) | |||
| 1233 | * and reducing the surplus. | 1273 | * and reducing the surplus. |
| 1234 | */ | 1274 | */ |
| 1235 | spin_unlock(&hugetlb_lock); | 1275 | spin_unlock(&hugetlb_lock); |
| 1236 | ret = alloc_fresh_huge_page(h); | 1276 | ret = alloc_fresh_huge_page(h, nodes_allowed); |
| 1237 | spin_lock(&hugetlb_lock); | 1277 | spin_lock(&hugetlb_lock); |
| 1238 | if (!ret) | 1278 | if (!ret) |
| 1239 | goto out; | 1279 | goto out; |
| 1240 | 1280 | ||
| 1281 | /* Bail for signals. Probably ctrl-c from user */ | ||
| 1282 | if (signal_pending(current)) | ||
| 1283 | goto out; | ||
| 1241 | } | 1284 | } |
| 1242 | 1285 | ||
| 1243 | /* | 1286 | /* |
| @@ -1257,13 +1300,13 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count) | |||
| 1257 | */ | 1300 | */ |
| 1258 | min_count = h->resv_huge_pages + h->nr_huge_pages - h->free_huge_pages; | 1301 | min_count = h->resv_huge_pages + h->nr_huge_pages - h->free_huge_pages; |
| 1259 | min_count = max(count, min_count); | 1302 | min_count = max(count, min_count); |
| 1260 | try_to_free_low(h, min_count); | 1303 | try_to_free_low(h, min_count, nodes_allowed); |
| 1261 | while (min_count < persistent_huge_pages(h)) { | 1304 | while (min_count < persistent_huge_pages(h)) { |
| 1262 | if (!free_pool_huge_page(h, 0)) | 1305 | if (!free_pool_huge_page(h, nodes_allowed, 0)) |
| 1263 | break; | 1306 | break; |
| 1264 | } | 1307 | } |
| 1265 | while (count < persistent_huge_pages(h)) { | 1308 | while (count < persistent_huge_pages(h)) { |
| 1266 | if (!adjust_pool_surplus(h, 1)) | 1309 | if (!adjust_pool_surplus(h, nodes_allowed, 1)) |
| 1267 | break; | 1310 | break; |
| 1268 | } | 1311 | } |
| 1269 | out: | 1312 | out: |
| @@ -1282,43 +1325,117 @@ out: | |||
| 1282 | static struct kobject *hugepages_kobj; | 1325 | static struct kobject *hugepages_kobj; |
| 1283 | static struct kobject *hstate_kobjs[HUGE_MAX_HSTATE]; | 1326 | static struct kobject *hstate_kobjs[HUGE_MAX_HSTATE]; |
| 1284 | 1327 | ||
| 1285 | static struct hstate *kobj_to_hstate(struct kobject *kobj) | 1328 | static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp); |
| 1329 | |||
| 1330 | static struct hstate *kobj_to_hstate(struct kobject *kobj, int *nidp) | ||
| 1286 | { | 1331 | { |
| 1287 | int i; | 1332 | int i; |
| 1333 | |||
| 1288 | for (i = 0; i < HUGE_MAX_HSTATE; i++) | 1334 | for (i = 0; i < HUGE_MAX_HSTATE; i++) |
| 1289 | if (hstate_kobjs[i] == kobj) | 1335 | if (hstate_kobjs[i] == kobj) { |
| 1336 | if (nidp) | ||
| 1337 | *nidp = NUMA_NO_NODE; | ||
| 1290 | return &hstates[i]; | 1338 | return &hstates[i]; |
| 1291 | BUG(); | 1339 | } |
| 1292 | return NULL; | 1340 | |
| 1341 | return kobj_to_node_hstate(kobj, nidp); | ||
| 1293 | } | 1342 | } |
| 1294 | 1343 | ||
| 1295 | static ssize_t nr_hugepages_show(struct kobject *kobj, | 1344 | static ssize_t nr_hugepages_show_common(struct kobject *kobj, |
| 1296 | struct kobj_attribute *attr, char *buf) | 1345 | struct kobj_attribute *attr, char *buf) |
| 1297 | { | 1346 | { |
| 1298 | struct hstate *h = kobj_to_hstate(kobj); | 1347 | struct hstate *h; |
| 1299 | return sprintf(buf, "%lu\n", h->nr_huge_pages); | 1348 | unsigned long nr_huge_pages; |
| 1349 | int nid; | ||
| 1350 | |||
| 1351 | h = kobj_to_hstate(kobj, &nid); | ||
| 1352 | if (nid == NUMA_NO_NODE) | ||
| 1353 | nr_huge_pages = h->nr_huge_pages; | ||
| 1354 | else | ||
| 1355 | nr_huge_pages = h->nr_huge_pages_node[nid]; | ||
| 1356 | |||
| 1357 | return sprintf(buf, "%lu\n", nr_huge_pages); | ||
| 1300 | } | 1358 | } |
| 1301 | static ssize_t nr_hugepages_store(struct kobject *kobj, | 1359 | static ssize_t nr_hugepages_store_common(bool obey_mempolicy, |
| 1302 | struct kobj_attribute *attr, const char *buf, size_t count) | 1360 | struct kobject *kobj, struct kobj_attribute *attr, |
| 1361 | const char *buf, size_t len) | ||
| 1303 | { | 1362 | { |
| 1304 | int err; | 1363 | int err; |
| 1305 | unsigned long input; | 1364 | int nid; |
| 1306 | struct hstate *h = kobj_to_hstate(kobj); | 1365 | unsigned long count; |
| 1366 | struct hstate *h; | ||
| 1367 | NODEMASK_ALLOC(nodemask_t, nodes_allowed, GFP_KERNEL | __GFP_NORETRY); | ||
| 1307 | 1368 | ||
| 1308 | err = strict_strtoul(buf, 10, &input); | 1369 | err = strict_strtoul(buf, 10, &count); |
| 1309 | if (err) | 1370 | if (err) |
| 1310 | return 0; | 1371 | return 0; |
| 1311 | 1372 | ||
| 1312 | h->max_huge_pages = set_max_huge_pages(h, input); | 1373 | h = kobj_to_hstate(kobj, &nid); |
| 1374 | if (nid == NUMA_NO_NODE) { | ||
| 1375 | /* | ||
| 1376 | * global hstate attribute | ||
| 1377 | */ | ||
| 1378 | if (!(obey_mempolicy && | ||
| 1379 | init_nodemask_of_mempolicy(nodes_allowed))) { | ||
| 1380 | NODEMASK_FREE(nodes_allowed); | ||
| 1381 | nodes_allowed = &node_states[N_HIGH_MEMORY]; | ||
| 1382 | } | ||
| 1383 | } else if (nodes_allowed) { | ||
| 1384 | /* | ||
| 1385 | * per node hstate attribute: adjust count to global, | ||
| 1386 | * but restrict alloc/free to the specified node. | ||
| 1387 | */ | ||
| 1388 | count += h->nr_huge_pages - h->nr_huge_pages_node[nid]; | ||
| 1389 | init_nodemask_of_node(nodes_allowed, nid); | ||
| 1390 | } else | ||
| 1391 | nodes_allowed = &node_states[N_HIGH_MEMORY]; | ||
| 1392 | |||
| 1393 | h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed); | ||
| 1313 | 1394 | ||
| 1314 | return count; | 1395 | if (nodes_allowed != &node_states[N_HIGH_MEMORY]) |
| 1396 | NODEMASK_FREE(nodes_allowed); | ||
| 1397 | |||
| 1398 | return len; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | static ssize_t nr_hugepages_show(struct kobject *kobj, | ||
| 1402 | struct kobj_attribute *attr, char *buf) | ||
| 1403 | { | ||
| 1404 | return nr_hugepages_show_common(kobj, attr, buf); | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | static ssize_t nr_hugepages_store(struct kobject *kobj, | ||
| 1408 | struct kobj_attribute *attr, const char *buf, size_t len) | ||
| 1409 | { | ||
| 1410 | return nr_hugepages_store_common(false, kobj, attr, buf, len); | ||
| 1315 | } | 1411 | } |
| 1316 | HSTATE_ATTR(nr_hugepages); | 1412 | HSTATE_ATTR(nr_hugepages); |
| 1317 | 1413 | ||
| 1414 | #ifdef CONFIG_NUMA | ||
| 1415 | |||
| 1416 | /* | ||
| 1417 | * hstate attribute for optionally mempolicy-based constraint on persistent | ||
| 1418 | * huge page alloc/free. | ||
| 1419 | */ | ||
| 1420 | static ssize_t nr_hugepages_mempolicy_show(struct kobject *kobj, | ||
| 1421 | struct kobj_attribute *attr, char *buf) | ||
| 1422 | { | ||
| 1423 | return nr_hugepages_show_common(kobj, attr, buf); | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | static ssize_t nr_hugepages_mempolicy_store(struct kobject *kobj, | ||
| 1427 | struct kobj_attribute *attr, const char *buf, size_t len) | ||
| 1428 | { | ||
| 1429 | return nr_hugepages_store_common(true, kobj, attr, buf, len); | ||
| 1430 | } | ||
| 1431 | HSTATE_ATTR(nr_hugepages_mempolicy); | ||
| 1432 | #endif | ||
| 1433 | |||
| 1434 | |||
| 1318 | static ssize_t nr_overcommit_hugepages_show(struct kobject *kobj, | 1435 | static ssize_t nr_overcommit_hugepages_show(struct kobject *kobj, |
| 1319 | struct kobj_attribute *attr, char *buf) | 1436 | struct kobj_attribute *attr, char *buf) |
| 1320 | { | 1437 | { |
| 1321 | struct hstate *h = kobj_to_hstate(kobj); | 1438 | struct hstate *h = kobj_to_hstate(kobj, NULL); |
| 1322 | return sprintf(buf, "%lu\n", h->nr_overcommit_huge_pages); | 1439 | return sprintf(buf, "%lu\n", h->nr_overcommit_huge_pages); |
| 1323 | } | 1440 | } |
| 1324 | static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj, | 1441 | static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj, |
| @@ -1326,7 +1443,7 @@ static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj, | |||
| 1326 | { | 1443 | { |
| 1327 | int err; | 1444 | int err; |
| 1328 | unsigned long input; | 1445 | unsigned long input; |
| 1329 | struct hstate *h = kobj_to_hstate(kobj); | 1446 | struct hstate *h = kobj_to_hstate(kobj, NULL); |
| 1330 | 1447 | ||
| 1331 | err = strict_strtoul(buf, 10, &input); | 1448 | err = strict_strtoul(buf, 10, &input); |
| 1332 | if (err) | 1449 | if (err) |
| @@ -1343,15 +1460,24 @@ HSTATE_ATTR(nr_overcommit_hugepages); | |||
| 1343 | static ssize_t free_hugepages_show(struct kobject *kobj, | 1460 | static ssize_t free_hugepages_show(struct kobject *kobj, |
| 1344 | struct kobj_attribute *attr, char *buf) | 1461 | struct kobj_attribute *attr, char *buf) |
| 1345 | { | 1462 | { |
| 1346 | struct hstate *h = kobj_to_hstate(kobj); | 1463 | struct hstate *h; |
| 1347 | return sprintf(buf, "%lu\n", h->free_huge_pages); | 1464 | unsigned long free_huge_pages; |
| 1465 | int nid; | ||
| 1466 | |||
| 1467 | h = kobj_to_hstate(kobj, &nid); | ||
| 1468 | if (nid == NUMA_NO_NODE) | ||
| 1469 | free_huge_pages = h->free_huge_pages; | ||
| 1470 | else | ||
| 1471 | free_huge_pages = h->free_huge_pages_node[nid]; | ||
| 1472 | |||
| 1473 | return sprintf(buf, "%lu\n", free_huge_pages); | ||
| 1348 | } | 1474 | } |
| 1349 | HSTATE_ATTR_RO(free_hugepages); | 1475 | HSTATE_ATTR_RO(free_hugepages); |
| 1350 | 1476 | ||
| 1351 | static ssize_t resv_hugepages_show(struct kobject *kobj, | 1477 | static ssize_t resv_hugepages_show(struct kobject *kobj, |
| 1352 | struct kobj_attribute *attr, char *buf) | 1478 | struct kobj_attribute *attr, char *buf) |
| 1353 | { | 1479 | { |
| 1354 | struct hstate *h = kobj_to_hstate(kobj); | 1480 | struct hstate *h = kobj_to_hstate(kobj, NULL); |
| 1355 | return sprintf(buf, "%lu\n", h->resv_huge_pages); | 1481 | return sprintf(buf, "%lu\n", h->resv_huge_pages); |
| 1356 | } | 1482 | } |
| 1357 | HSTATE_ATTR_RO(resv_hugepages); | 1483 | HSTATE_ATTR_RO(resv_hugepages); |
| @@ -1359,8 +1485,17 @@ HSTATE_ATTR_RO(resv_hugepages); | |||
| 1359 | static ssize_t surplus_hugepages_show(struct kobject *kobj, | 1485 | static ssize_t surplus_hugepages_show(struct kobject *kobj, |
| 1360 | struct kobj_attribute *attr, char *buf) | 1486 | struct kobj_attribute *attr, char *buf) |
| 1361 | { | 1487 | { |
| 1362 | struct hstate *h = kobj_to_hstate(kobj); | 1488 | struct hstate *h; |
| 1363 | return sprintf(buf, "%lu\n", h->surplus_huge_pages); | 1489 | unsigned long surplus_huge_pages; |
| 1490 | int nid; | ||
| 1491 | |||
| 1492 | h = kobj_to_hstate(kobj, &nid); | ||
| 1493 | if (nid == NUMA_NO_NODE) | ||
| 1494 | surplus_huge_pages = h->surplus_huge_pages; | ||
| 1495 | else | ||
| 1496 | surplus_huge_pages = h->surplus_huge_pages_node[nid]; | ||
| 1497 | |||
| 1498 | return sprintf(buf, "%lu\n", surplus_huge_pages); | ||
| 1364 | } | 1499 | } |
| 1365 | HSTATE_ATTR_RO(surplus_hugepages); | 1500 | HSTATE_ATTR_RO(surplus_hugepages); |
| 1366 | 1501 | ||
| @@ -1370,6 +1505,9 @@ static struct attribute *hstate_attrs[] = { | |||
| 1370 | &free_hugepages_attr.attr, | 1505 | &free_hugepages_attr.attr, |
| 1371 | &resv_hugepages_attr.attr, | 1506 | &resv_hugepages_attr.attr, |
| 1372 | &surplus_hugepages_attr.attr, | 1507 | &surplus_hugepages_attr.attr, |
| 1508 | #ifdef CONFIG_NUMA | ||
| 1509 | &nr_hugepages_mempolicy_attr.attr, | ||
| 1510 | #endif | ||
| 1373 | NULL, | 1511 | NULL, |
| 1374 | }; | 1512 | }; |
| 1375 | 1513 | ||
| @@ -1377,19 +1515,21 @@ static struct attribute_group hstate_attr_group = { | |||
| 1377 | .attrs = hstate_attrs, | 1515 | .attrs = hstate_attrs, |
| 1378 | }; | 1516 | }; |
| 1379 | 1517 | ||
| 1380 | static int __init hugetlb_sysfs_add_hstate(struct hstate *h) | 1518 | static int __init hugetlb_sysfs_add_hstate(struct hstate *h, |
| 1519 | struct kobject *parent, | ||
| 1520 | struct kobject **hstate_kobjs, | ||
| 1521 | struct attribute_group *hstate_attr_group) | ||
| 1381 | { | 1522 | { |
| 1382 | int retval; | 1523 | int retval; |
| 1524 | int hi = h - hstates; | ||
| 1383 | 1525 | ||
| 1384 | hstate_kobjs[h - hstates] = kobject_create_and_add(h->name, | 1526 | hstate_kobjs[hi] = kobject_create_and_add(h->name, parent); |
| 1385 | hugepages_kobj); | 1527 | if (!hstate_kobjs[hi]) |
| 1386 | if (!hstate_kobjs[h - hstates]) | ||
| 1387 | return -ENOMEM; | 1528 | return -ENOMEM; |
| 1388 | 1529 | ||
| 1389 | retval = sysfs_create_group(hstate_kobjs[h - hstates], | 1530 | retval = sysfs_create_group(hstate_kobjs[hi], hstate_attr_group); |
| 1390 | &hstate_attr_group); | ||
| 1391 | if (retval) | 1531 | if (retval) |
| 1392 | kobject_put(hstate_kobjs[h - hstates]); | 1532 | kobject_put(hstate_kobjs[hi]); |
| 1393 | 1533 | ||
| 1394 | return retval; | 1534 | return retval; |
| 1395 | } | 1535 | } |
| @@ -1404,17 +1544,184 @@ static void __init hugetlb_sysfs_init(void) | |||
| 1404 | return; | 1544 | return; |
| 1405 | 1545 | ||
| 1406 | for_each_hstate(h) { | 1546 | for_each_hstate(h) { |
| 1407 | err = hugetlb_sysfs_add_hstate(h); | 1547 | err = hugetlb_sysfs_add_hstate(h, hugepages_kobj, |
| 1548 | hstate_kobjs, &hstate_attr_group); | ||
| 1408 | if (err) | 1549 | if (err) |
| 1409 | printk(KERN_ERR "Hugetlb: Unable to add hstate %s", | 1550 | printk(KERN_ERR "Hugetlb: Unable to add hstate %s", |
| 1410 | h->name); | 1551 | h->name); |
| 1411 | } | 1552 | } |
| 1412 | } | 1553 | } |
| 1413 | 1554 | ||
| 1555 | #ifdef CONFIG_NUMA | ||
| 1556 | |||
| 1557 | /* | ||
| 1558 | * node_hstate/s - associate per node hstate attributes, via their kobjects, | ||
| 1559 | * with node sysdevs in node_devices[] using a parallel array. The array | ||
| 1560 | * index of a node sysdev or _hstate == node id. | ||
| 1561 | * This is here to avoid any static dependency of the node sysdev driver, in | ||
| 1562 | * the base kernel, on the hugetlb module. | ||
| 1563 | */ | ||
| 1564 | struct node_hstate { | ||
| 1565 | struct kobject *hugepages_kobj; | ||
| 1566 | struct kobject *hstate_kobjs[HUGE_MAX_HSTATE]; | ||
| 1567 | }; | ||
| 1568 | struct node_hstate node_hstates[MAX_NUMNODES]; | ||
| 1569 | |||
| 1570 | /* | ||
| 1571 | * A subset of global hstate attributes for node sysdevs | ||
| 1572 | */ | ||
| 1573 | static struct attribute *per_node_hstate_attrs[] = { | ||
| 1574 | &nr_hugepages_attr.attr, | ||
| 1575 | &free_hugepages_attr.attr, | ||
| 1576 | &surplus_hugepages_attr.attr, | ||
| 1577 | NULL, | ||
| 1578 | }; | ||
| 1579 | |||
| 1580 | static struct attribute_group per_node_hstate_attr_group = { | ||
| 1581 | .attrs = per_node_hstate_attrs, | ||
| 1582 | }; | ||
| 1583 | |||
| 1584 | /* | ||
| 1585 | * kobj_to_node_hstate - lookup global hstate for node sysdev hstate attr kobj. | ||
| 1586 | * Returns node id via non-NULL nidp. | ||
| 1587 | */ | ||
| 1588 | static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp) | ||
| 1589 | { | ||
| 1590 | int nid; | ||
| 1591 | |||
| 1592 | for (nid = 0; nid < nr_node_ids; nid++) { | ||
| 1593 | struct node_hstate *nhs = &node_hstates[nid]; | ||
| 1594 | int i; | ||
| 1595 | for (i = 0; i < HUGE_MAX_HSTATE; i++) | ||
| 1596 | if (nhs->hstate_kobjs[i] == kobj) { | ||
| 1597 | if (nidp) | ||
| 1598 | *nidp = nid; | ||
| 1599 | return &hstates[i]; | ||
| 1600 | } | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | BUG(); | ||
| 1604 | return NULL; | ||
| 1605 | } | ||
| 1606 | |||
| 1607 | /* | ||
| 1608 | * Unregister hstate attributes from a single node sysdev. | ||
| 1609 | * No-op if no hstate attributes attached. | ||
| 1610 | */ | ||
| 1611 | void hugetlb_unregister_node(struct node *node) | ||
| 1612 | { | ||
| 1613 | struct hstate *h; | ||
| 1614 | struct node_hstate *nhs = &node_hstates[node->sysdev.id]; | ||
| 1615 | |||
| 1616 | if (!nhs->hugepages_kobj) | ||
| 1617 | return; /* no hstate attributes */ | ||
| 1618 | |||
| 1619 | for_each_hstate(h) | ||
| 1620 | if (nhs->hstate_kobjs[h - hstates]) { | ||
| 1621 | kobject_put(nhs->hstate_kobjs[h - hstates]); | ||
| 1622 | nhs->hstate_kobjs[h - hstates] = NULL; | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | kobject_put(nhs->hugepages_kobj); | ||
| 1626 | nhs->hugepages_kobj = NULL; | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | /* | ||
| 1630 | * hugetlb module exit: unregister hstate attributes from node sysdevs | ||
| 1631 | * that have them. | ||
| 1632 | */ | ||
| 1633 | static void hugetlb_unregister_all_nodes(void) | ||
| 1634 | { | ||
| 1635 | int nid; | ||
| 1636 | |||
| 1637 | /* | ||
| 1638 | * disable node sysdev registrations. | ||
| 1639 | */ | ||
| 1640 | register_hugetlbfs_with_node(NULL, NULL); | ||
| 1641 | |||
| 1642 | /* | ||
| 1643 | * remove hstate attributes from any nodes that have them. | ||
| 1644 | */ | ||
| 1645 | for (nid = 0; nid < nr_node_ids; nid++) | ||
| 1646 | hugetlb_unregister_node(&node_devices[nid]); | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | /* | ||
| 1650 | * Register hstate attributes for a single node sysdev. | ||
| 1651 | * No-op if attributes already registered. | ||
| 1652 | */ | ||
| 1653 | void hugetlb_register_node(struct node *node) | ||
| 1654 | { | ||
| 1655 | struct hstate *h; | ||
| 1656 | struct node_hstate *nhs = &node_hstates[node->sysdev.id]; | ||
| 1657 | int err; | ||
| 1658 | |||
| 1659 | if (nhs->hugepages_kobj) | ||
| 1660 | return; /* already allocated */ | ||
| 1661 | |||
| 1662 | nhs->hugepages_kobj = kobject_create_and_add("hugepages", | ||
| 1663 | &node->sysdev.kobj); | ||
| 1664 | if (!nhs->hugepages_kobj) | ||
| 1665 | return; | ||
| 1666 | |||
| 1667 | for_each_hstate(h) { | ||
| 1668 | err = hugetlb_sysfs_add_hstate(h, nhs->hugepages_kobj, | ||
| 1669 | nhs->hstate_kobjs, | ||
| 1670 | &per_node_hstate_attr_group); | ||
| 1671 | if (err) { | ||
| 1672 | printk(KERN_ERR "Hugetlb: Unable to add hstate %s" | ||
| 1673 | " for node %d\n", | ||
| 1674 | h->name, node->sysdev.id); | ||
| 1675 | hugetlb_unregister_node(node); | ||
| 1676 | break; | ||
| 1677 | } | ||
| 1678 | } | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | /* | ||
| 1682 | * hugetlb init time: register hstate attributes for all registered node | ||
| 1683 | * sysdevs of nodes that have memory. All on-line nodes should have | ||
| 1684 | * registered their associated sysdev by this time. | ||
| 1685 | */ | ||
| 1686 | static void hugetlb_register_all_nodes(void) | ||
| 1687 | { | ||
| 1688 | int nid; | ||
| 1689 | |||
| 1690 | for_each_node_state(nid, N_HIGH_MEMORY) { | ||
| 1691 | struct node *node = &node_devices[nid]; | ||
| 1692 | if (node->sysdev.id == nid) | ||
| 1693 | hugetlb_register_node(node); | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | /* | ||
| 1697 | * Let the node sysdev driver know we're here so it can | ||
| 1698 | * [un]register hstate attributes on node hotplug. | ||
| 1699 | */ | ||
| 1700 | register_hugetlbfs_with_node(hugetlb_register_node, | ||
| 1701 | hugetlb_unregister_node); | ||
| 1702 | } | ||
| 1703 | #else /* !CONFIG_NUMA */ | ||
| 1704 | |||
| 1705 | static struct hstate *kobj_to_node_hstate(struct kobject *kobj, int *nidp) | ||
| 1706 | { | ||
| 1707 | BUG(); | ||
| 1708 | if (nidp) | ||
| 1709 | *nidp = -1; | ||
| 1710 | return NULL; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | static void hugetlb_unregister_all_nodes(void) { } | ||
| 1714 | |||
| 1715 | static void hugetlb_register_all_nodes(void) { } | ||
| 1716 | |||
| 1717 | #endif | ||
| 1718 | |||
| 1414 | static void __exit hugetlb_exit(void) | 1719 | static void __exit hugetlb_exit(void) |
| 1415 | { | 1720 | { |
| 1416 | struct hstate *h; | 1721 | struct hstate *h; |
| 1417 | 1722 | ||
| 1723 | hugetlb_unregister_all_nodes(); | ||
| 1724 | |||
| 1418 | for_each_hstate(h) { | 1725 | for_each_hstate(h) { |
| 1419 | kobject_put(hstate_kobjs[h - hstates]); | 1726 | kobject_put(hstate_kobjs[h - hstates]); |
| 1420 | } | 1727 | } |
| @@ -1449,6 +1756,8 @@ static int __init hugetlb_init(void) | |||
| 1449 | 1756 | ||
| 1450 | hugetlb_sysfs_init(); | 1757 | hugetlb_sysfs_init(); |
| 1451 | 1758 | ||
| 1759 | hugetlb_register_all_nodes(); | ||
| 1760 | |||
| 1452 | return 0; | 1761 | return 0; |
| 1453 | } | 1762 | } |
| 1454 | module_init(hugetlb_init); | 1763 | module_init(hugetlb_init); |
| @@ -1472,8 +1781,8 @@ void __init hugetlb_add_hstate(unsigned order) | |||
| 1472 | h->free_huge_pages = 0; | 1781 | h->free_huge_pages = 0; |
| 1473 | for (i = 0; i < MAX_NUMNODES; ++i) | 1782 | for (i = 0; i < MAX_NUMNODES; ++i) |
| 1474 | INIT_LIST_HEAD(&h->hugepage_freelists[i]); | 1783 | INIT_LIST_HEAD(&h->hugepage_freelists[i]); |
| 1475 | h->next_nid_to_alloc = first_node(node_online_map); | 1784 | h->next_nid_to_alloc = first_node(node_states[N_HIGH_MEMORY]); |
| 1476 | h->next_nid_to_free = first_node(node_online_map); | 1785 | h->next_nid_to_free = first_node(node_states[N_HIGH_MEMORY]); |
| 1477 | snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", | 1786 | snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", |
| 1478 | huge_page_size(h)/1024); | 1787 | huge_page_size(h)/1024); |
| 1479 | 1788 | ||
| @@ -1536,9 +1845,9 @@ static unsigned int cpuset_mems_nr(unsigned int *array) | |||
| 1536 | } | 1845 | } |
| 1537 | 1846 | ||
| 1538 | #ifdef CONFIG_SYSCTL | 1847 | #ifdef CONFIG_SYSCTL |
| 1539 | int hugetlb_sysctl_handler(struct ctl_table *table, int write, | 1848 | static int hugetlb_sysctl_handler_common(bool obey_mempolicy, |
| 1540 | void __user *buffer, | 1849 | struct ctl_table *table, int write, |
| 1541 | size_t *length, loff_t *ppos) | 1850 | void __user *buffer, size_t *length, loff_t *ppos) |
| 1542 | { | 1851 | { |
| 1543 | struct hstate *h = &default_hstate; | 1852 | struct hstate *h = &default_hstate; |
| 1544 | unsigned long tmp; | 1853 | unsigned long tmp; |
| @@ -1550,12 +1859,40 @@ int hugetlb_sysctl_handler(struct ctl_table *table, int write, | |||
| 1550 | table->maxlen = sizeof(unsigned long); | 1859 | table->maxlen = sizeof(unsigned long); |
| 1551 | proc_doulongvec_minmax(table, write, buffer, length, ppos); | 1860 | proc_doulongvec_minmax(table, write, buffer, length, ppos); |
| 1552 | 1861 | ||
| 1553 | if (write) | 1862 | if (write) { |
| 1554 | h->max_huge_pages = set_max_huge_pages(h, tmp); | 1863 | NODEMASK_ALLOC(nodemask_t, nodes_allowed, |
| 1864 | GFP_KERNEL | __GFP_NORETRY); | ||
| 1865 | if (!(obey_mempolicy && | ||
| 1866 | init_nodemask_of_mempolicy(nodes_allowed))) { | ||
| 1867 | NODEMASK_FREE(nodes_allowed); | ||
| 1868 | nodes_allowed = &node_states[N_HIGH_MEMORY]; | ||
| 1869 | } | ||
| 1870 | h->max_huge_pages = set_max_huge_pages(h, tmp, nodes_allowed); | ||
| 1871 | |||
| 1872 | if (nodes_allowed != &node_states[N_HIGH_MEMORY]) | ||
| 1873 | NODEMASK_FREE(nodes_allowed); | ||
| 1874 | } | ||
| 1555 | 1875 | ||
| 1556 | return 0; | 1876 | return 0; |
| 1557 | } | 1877 | } |
| 1558 | 1878 | ||
| 1879 | int hugetlb_sysctl_handler(struct ctl_table *table, int write, | ||
| 1880 | void __user *buffer, size_t *length, loff_t *ppos) | ||
| 1881 | { | ||
| 1882 | |||
| 1883 | return hugetlb_sysctl_handler_common(false, table, write, | ||
| 1884 | buffer, length, ppos); | ||
| 1885 | } | ||
| 1886 | |||
| 1887 | #ifdef CONFIG_NUMA | ||
| 1888 | int hugetlb_mempolicy_sysctl_handler(struct ctl_table *table, int write, | ||
| 1889 | void __user *buffer, size_t *length, loff_t *ppos) | ||
| 1890 | { | ||
| 1891 | return hugetlb_sysctl_handler_common(true, table, write, | ||
| 1892 | buffer, length, ppos); | ||
| 1893 | } | ||
| 1894 | #endif /* CONFIG_NUMA */ | ||
| 1895 | |||
| 1559 | int hugetlb_treat_movable_handler(struct ctl_table *table, int write, | 1896 | int hugetlb_treat_movable_handler(struct ctl_table *table, int write, |
| 1560 | void __user *buffer, | 1897 | void __user *buffer, |
| 1561 | size_t *length, loff_t *ppos) | 1898 | size_t *length, loff_t *ppos) |
| @@ -1903,6 +2240,12 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1903 | + (vma->vm_pgoff >> PAGE_SHIFT); | 2240 | + (vma->vm_pgoff >> PAGE_SHIFT); |
| 1904 | mapping = (struct address_space *)page_private(page); | 2241 | mapping = (struct address_space *)page_private(page); |
| 1905 | 2242 | ||
| 2243 | /* | ||
| 2244 | * Take the mapping lock for the duration of the table walk. As | ||
| 2245 | * this mapping should be shared between all the VMAs, | ||
| 2246 | * __unmap_hugepage_range() is called as the lock is already held | ||
| 2247 | */ | ||
| 2248 | spin_lock(&mapping->i_mmap_lock); | ||
| 1906 | vma_prio_tree_foreach(iter_vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 2249 | vma_prio_tree_foreach(iter_vma, &iter, &mapping->i_mmap, pgoff, pgoff) { |
| 1907 | /* Do not unmap the current VMA */ | 2250 | /* Do not unmap the current VMA */ |
| 1908 | if (iter_vma == vma) | 2251 | if (iter_vma == vma) |
| @@ -1916,10 +2259,11 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1916 | * from the time of fork. This would look like data corruption | 2259 | * from the time of fork. This would look like data corruption |
| 1917 | */ | 2260 | */ |
| 1918 | if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER)) | 2261 | if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER)) |
| 1919 | unmap_hugepage_range(iter_vma, | 2262 | __unmap_hugepage_range(iter_vma, |
| 1920 | address, address + huge_page_size(h), | 2263 | address, address + huge_page_size(h), |
| 1921 | page); | 2264 | page); |
| 1922 | } | 2265 | } |
| 2266 | spin_unlock(&mapping->i_mmap_lock); | ||
| 1923 | 2267 | ||
| 1924 | return 1; | 2268 | return 1; |
| 1925 | } | 2269 | } |
| @@ -1959,6 +2303,9 @@ retry_avoidcopy: | |||
| 1959 | outside_reserve = 1; | 2303 | outside_reserve = 1; |
| 1960 | 2304 | ||
| 1961 | page_cache_get(old_page); | 2305 | page_cache_get(old_page); |
| 2306 | |||
| 2307 | /* Drop page_table_lock as buddy allocator may be called */ | ||
| 2308 | spin_unlock(&mm->page_table_lock); | ||
| 1962 | new_page = alloc_huge_page(vma, address, outside_reserve); | 2309 | new_page = alloc_huge_page(vma, address, outside_reserve); |
| 1963 | 2310 | ||
| 1964 | if (IS_ERR(new_page)) { | 2311 | if (IS_ERR(new_page)) { |
| @@ -1976,19 +2323,25 @@ retry_avoidcopy: | |||
| 1976 | if (unmap_ref_private(mm, vma, old_page, address)) { | 2323 | if (unmap_ref_private(mm, vma, old_page, address)) { |
| 1977 | BUG_ON(page_count(old_page) != 1); | 2324 | BUG_ON(page_count(old_page) != 1); |
| 1978 | BUG_ON(huge_pte_none(pte)); | 2325 | BUG_ON(huge_pte_none(pte)); |
| 2326 | spin_lock(&mm->page_table_lock); | ||
| 1979 | goto retry_avoidcopy; | 2327 | goto retry_avoidcopy; |
| 1980 | } | 2328 | } |
| 1981 | WARN_ON_ONCE(1); | 2329 | WARN_ON_ONCE(1); |
| 1982 | } | 2330 | } |
| 1983 | 2331 | ||
| 2332 | /* Caller expects lock to be held */ | ||
| 2333 | spin_lock(&mm->page_table_lock); | ||
| 1984 | return -PTR_ERR(new_page); | 2334 | return -PTR_ERR(new_page); |
| 1985 | } | 2335 | } |
| 1986 | 2336 | ||
| 1987 | spin_unlock(&mm->page_table_lock); | ||
| 1988 | copy_huge_page(new_page, old_page, address, vma); | 2337 | copy_huge_page(new_page, old_page, address, vma); |
| 1989 | __SetPageUptodate(new_page); | 2338 | __SetPageUptodate(new_page); |
| 1990 | spin_lock(&mm->page_table_lock); | ||
| 1991 | 2339 | ||
| 2340 | /* | ||
| 2341 | * Retake the page_table_lock to check for racing updates | ||
| 2342 | * before the page tables are altered | ||
| 2343 | */ | ||
| 2344 | spin_lock(&mm->page_table_lock); | ||
| 1992 | ptep = huge_pte_offset(mm, address & huge_page_mask(h)); | 2345 | ptep = huge_pte_offset(mm, address & huge_page_mask(h)); |
| 1993 | if (likely(pte_same(huge_ptep_get(ptep), pte))) { | 2346 | if (likely(pte_same(huge_ptep_get(ptep), pte))) { |
| 1994 | /* Break COW */ | 2347 | /* Break COW */ |
diff --git a/mm/internal.h b/mm/internal.h index 22ec8d2b0fb8..4fe67a162cb4 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
| @@ -63,7 +63,7 @@ static inline unsigned long page_order(struct page *page) | |||
| 63 | return page_private(page); | 63 | return page_private(page); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | #ifdef CONFIG_HAVE_MLOCK | 66 | #ifdef CONFIG_MMU |
| 67 | extern long mlock_vma_pages_range(struct vm_area_struct *vma, | 67 | extern long mlock_vma_pages_range(struct vm_area_struct *vma, |
| 68 | unsigned long start, unsigned long end); | 68 | unsigned long start, unsigned long end); |
| 69 | extern void munlock_vma_pages_range(struct vm_area_struct *vma, | 69 | extern void munlock_vma_pages_range(struct vm_area_struct *vma, |
| @@ -72,21 +72,7 @@ static inline void munlock_vma_pages_all(struct vm_area_struct *vma) | |||
| 72 | { | 72 | { |
| 73 | munlock_vma_pages_range(vma, vma->vm_start, vma->vm_end); | 73 | munlock_vma_pages_range(vma, vma->vm_start, vma->vm_end); |
| 74 | } | 74 | } |
| 75 | #endif | ||
| 76 | |||
| 77 | /* | ||
| 78 | * unevictable_migrate_page() called only from migrate_page_copy() to | ||
| 79 | * migrate unevictable flag to new page. | ||
| 80 | * Note that the old page has been isolated from the LRU lists at this | ||
| 81 | * point so we don't need to worry about LRU statistics. | ||
| 82 | */ | ||
| 83 | static inline void unevictable_migrate_page(struct page *new, struct page *old) | ||
| 84 | { | ||
| 85 | if (TestClearPageUnevictable(old)) | ||
| 86 | SetPageUnevictable(new); | ||
| 87 | } | ||
| 88 | 75 | ||
| 89 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | ||
| 90 | /* | 76 | /* |
| 91 | * Called only in fault path via page_evictable() for a new page | 77 | * Called only in fault path via page_evictable() for a new page |
| 92 | * to determine if it's being mapped into a LOCKED vma. | 78 | * to determine if it's being mapped into a LOCKED vma. |
| @@ -107,9 +93,10 @@ static inline int is_mlocked_vma(struct vm_area_struct *vma, struct page *page) | |||
| 107 | } | 93 | } |
| 108 | 94 | ||
| 109 | /* | 95 | /* |
| 110 | * must be called with vma's mmap_sem held for read, and page locked. | 96 | * must be called with vma's mmap_sem held for read or write, and page locked. |
| 111 | */ | 97 | */ |
| 112 | extern void mlock_vma_page(struct page *page); | 98 | extern void mlock_vma_page(struct page *page); |
| 99 | extern void munlock_vma_page(struct page *page); | ||
| 113 | 100 | ||
| 114 | /* | 101 | /* |
| 115 | * Clear the page's PageMlocked(). This can be useful in a situation where | 102 | * Clear the page's PageMlocked(). This can be useful in a situation where |
| @@ -144,7 +131,7 @@ static inline void mlock_migrate_page(struct page *newpage, struct page *page) | |||
| 144 | } | 131 | } |
| 145 | } | 132 | } |
| 146 | 133 | ||
| 147 | #else /* CONFIG_HAVE_MLOCKED_PAGE_BIT */ | 134 | #else /* !CONFIG_MMU */ |
| 148 | static inline int is_mlocked_vma(struct vm_area_struct *v, struct page *p) | 135 | static inline int is_mlocked_vma(struct vm_area_struct *v, struct page *p) |
| 149 | { | 136 | { |
| 150 | return 0; | 137 | return 0; |
| @@ -153,7 +140,7 @@ static inline void clear_page_mlock(struct page *page) { } | |||
| 153 | static inline void mlock_vma_page(struct page *page) { } | 140 | static inline void mlock_vma_page(struct page *page) { } |
| 154 | static inline void mlock_migrate_page(struct page *new, struct page *old) { } | 141 | static inline void mlock_migrate_page(struct page *new, struct page *old) { } |
| 155 | 142 | ||
| 156 | #endif /* CONFIG_HAVE_MLOCKED_PAGE_BIT */ | 143 | #endif /* !CONFIG_MMU */ |
| 157 | 144 | ||
| 158 | /* | 145 | /* |
| 159 | * Return the mem_map entry representing the 'offset' subpage within | 146 | * Return the mem_map entry representing the 'offset' subpage within |
| @@ -29,11 +29,13 @@ | |||
| 29 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/rbtree.h> | 31 | #include <linux/rbtree.h> |
| 32 | #include <linux/memory.h> | ||
| 32 | #include <linux/mmu_notifier.h> | 33 | #include <linux/mmu_notifier.h> |
| 33 | #include <linux/swap.h> | 34 | #include <linux/swap.h> |
| 34 | #include <linux/ksm.h> | 35 | #include <linux/ksm.h> |
| 35 | 36 | ||
| 36 | #include <asm/tlbflush.h> | 37 | #include <asm/tlbflush.h> |
| 38 | #include "internal.h" | ||
| 37 | 39 | ||
| 38 | /* | 40 | /* |
| 39 | * A few notes about the KSM scanning process, | 41 | * A few notes about the KSM scanning process, |
| @@ -79,13 +81,13 @@ | |||
| 79 | * struct mm_slot - ksm information per mm that is being scanned | 81 | * struct mm_slot - ksm information per mm that is being scanned |
| 80 | * @link: link to the mm_slots hash list | 82 | * @link: link to the mm_slots hash list |
| 81 | * @mm_list: link into the mm_slots list, rooted in ksm_mm_head | 83 | * @mm_list: link into the mm_slots list, rooted in ksm_mm_head |
| 82 | * @rmap_list: head for this mm_slot's list of rmap_items | 84 | * @rmap_list: head for this mm_slot's singly-linked list of rmap_items |
| 83 | * @mm: the mm that this information is valid for | 85 | * @mm: the mm that this information is valid for |
| 84 | */ | 86 | */ |
| 85 | struct mm_slot { | 87 | struct mm_slot { |
| 86 | struct hlist_node link; | 88 | struct hlist_node link; |
| 87 | struct list_head mm_list; | 89 | struct list_head mm_list; |
| 88 | struct list_head rmap_list; | 90 | struct rmap_item *rmap_list; |
| 89 | struct mm_struct *mm; | 91 | struct mm_struct *mm; |
| 90 | }; | 92 | }; |
| 91 | 93 | ||
| @@ -93,7 +95,7 @@ struct mm_slot { | |||
| 93 | * struct ksm_scan - cursor for scanning | 95 | * struct ksm_scan - cursor for scanning |
| 94 | * @mm_slot: the current mm_slot we are scanning | 96 | * @mm_slot: the current mm_slot we are scanning |
| 95 | * @address: the next address inside that to be scanned | 97 | * @address: the next address inside that to be scanned |
| 96 | * @rmap_item: the current rmap that we are scanning inside the rmap_list | 98 | * @rmap_list: link to the next rmap to be scanned in the rmap_list |
| 97 | * @seqnr: count of completed full scans (needed when removing unstable node) | 99 | * @seqnr: count of completed full scans (needed when removing unstable node) |
| 98 | * | 100 | * |
| 99 | * There is only the one ksm_scan instance of this cursor structure. | 101 | * There is only the one ksm_scan instance of this cursor structure. |
| @@ -101,37 +103,51 @@ struct mm_slot { | |||
| 101 | struct ksm_scan { | 103 | struct ksm_scan { |
| 102 | struct mm_slot *mm_slot; | 104 | struct mm_slot *mm_slot; |
| 103 | unsigned long address; | 105 | unsigned long address; |
| 104 | struct rmap_item *rmap_item; | 106 | struct rmap_item **rmap_list; |
| 105 | unsigned long seqnr; | 107 | unsigned long seqnr; |
| 106 | }; | 108 | }; |
| 107 | 109 | ||
| 108 | /** | 110 | /** |
| 111 | * struct stable_node - node of the stable rbtree | ||
| 112 | * @node: rb node of this ksm page in the stable tree | ||
| 113 | * @hlist: hlist head of rmap_items using this ksm page | ||
| 114 | * @kpfn: page frame number of this ksm page | ||
| 115 | */ | ||
| 116 | struct stable_node { | ||
| 117 | struct rb_node node; | ||
| 118 | struct hlist_head hlist; | ||
| 119 | unsigned long kpfn; | ||
| 120 | }; | ||
| 121 | |||
| 122 | /** | ||
| 109 | * struct rmap_item - reverse mapping item for virtual addresses | 123 | * struct rmap_item - reverse mapping item for virtual addresses |
| 110 | * @link: link into mm_slot's rmap_list (rmap_list is per mm) | 124 | * @rmap_list: next rmap_item in mm_slot's singly-linked rmap_list |
| 125 | * @anon_vma: pointer to anon_vma for this mm,address, when in stable tree | ||
| 111 | * @mm: the memory structure this rmap_item is pointing into | 126 | * @mm: the memory structure this rmap_item is pointing into |
| 112 | * @address: the virtual address this rmap_item tracks (+ flags in low bits) | 127 | * @address: the virtual address this rmap_item tracks (+ flags in low bits) |
| 113 | * @oldchecksum: previous checksum of the page at that virtual address | 128 | * @oldchecksum: previous checksum of the page at that virtual address |
| 114 | * @node: rb_node of this rmap_item in either unstable or stable tree | 129 | * @node: rb node of this rmap_item in the unstable tree |
| 115 | * @next: next rmap_item hanging off the same node of the stable tree | 130 | * @head: pointer to stable_node heading this list in the stable tree |
| 116 | * @prev: previous rmap_item hanging off the same node of the stable tree | 131 | * @hlist: link into hlist of rmap_items hanging off that stable_node |
| 117 | */ | 132 | */ |
| 118 | struct rmap_item { | 133 | struct rmap_item { |
| 119 | struct list_head link; | 134 | struct rmap_item *rmap_list; |
| 135 | struct anon_vma *anon_vma; /* when stable */ | ||
| 120 | struct mm_struct *mm; | 136 | struct mm_struct *mm; |
| 121 | unsigned long address; /* + low bits used for flags below */ | 137 | unsigned long address; /* + low bits used for flags below */ |
| 138 | unsigned int oldchecksum; /* when unstable */ | ||
| 122 | union { | 139 | union { |
| 123 | unsigned int oldchecksum; /* when unstable */ | 140 | struct rb_node node; /* when node of unstable tree */ |
| 124 | struct rmap_item *next; /* when stable */ | 141 | struct { /* when listed from stable tree */ |
| 125 | }; | 142 | struct stable_node *head; |
| 126 | union { | 143 | struct hlist_node hlist; |
| 127 | struct rb_node node; /* when tree node */ | 144 | }; |
| 128 | struct rmap_item *prev; /* in stable list */ | ||
| 129 | }; | 145 | }; |
| 130 | }; | 146 | }; |
| 131 | 147 | ||
| 132 | #define SEQNR_MASK 0x0ff /* low bits of unstable tree seqnr */ | 148 | #define SEQNR_MASK 0x0ff /* low bits of unstable tree seqnr */ |
| 133 | #define NODE_FLAG 0x100 /* is a node of unstable or stable tree */ | 149 | #define UNSTABLE_FLAG 0x100 /* is a node of the unstable tree */ |
| 134 | #define STABLE_FLAG 0x200 /* is a node or list item of stable tree */ | 150 | #define STABLE_FLAG 0x200 /* is listed from the stable tree */ |
| 135 | 151 | ||
| 136 | /* The stable and unstable tree heads */ | 152 | /* The stable and unstable tree heads */ |
| 137 | static struct rb_root root_stable_tree = RB_ROOT; | 153 | static struct rb_root root_stable_tree = RB_ROOT; |
| @@ -148,6 +164,7 @@ static struct ksm_scan ksm_scan = { | |||
| 148 | }; | 164 | }; |
| 149 | 165 | ||
| 150 | static struct kmem_cache *rmap_item_cache; | 166 | static struct kmem_cache *rmap_item_cache; |
| 167 | static struct kmem_cache *stable_node_cache; | ||
| 151 | static struct kmem_cache *mm_slot_cache; | 168 | static struct kmem_cache *mm_slot_cache; |
| 152 | 169 | ||
| 153 | /* The number of nodes in the stable tree */ | 170 | /* The number of nodes in the stable tree */ |
| @@ -162,9 +179,6 @@ static unsigned long ksm_pages_unshared; | |||
| 162 | /* The number of rmap_items in use: to calculate pages_volatile */ | 179 | /* The number of rmap_items in use: to calculate pages_volatile */ |
| 163 | static unsigned long ksm_rmap_items; | 180 | static unsigned long ksm_rmap_items; |
| 164 | 181 | ||
| 165 | /* Limit on the number of unswappable pages used */ | ||
| 166 | static unsigned long ksm_max_kernel_pages; | ||
| 167 | |||
| 168 | /* Number of pages ksmd should scan in one batch */ | 182 | /* Number of pages ksmd should scan in one batch */ |
| 169 | static unsigned int ksm_thread_pages_to_scan = 100; | 183 | static unsigned int ksm_thread_pages_to_scan = 100; |
| 170 | 184 | ||
| @@ -190,13 +204,19 @@ static int __init ksm_slab_init(void) | |||
| 190 | if (!rmap_item_cache) | 204 | if (!rmap_item_cache) |
| 191 | goto out; | 205 | goto out; |
| 192 | 206 | ||
| 207 | stable_node_cache = KSM_KMEM_CACHE(stable_node, 0); | ||
| 208 | if (!stable_node_cache) | ||
| 209 | goto out_free1; | ||
| 210 | |||
| 193 | mm_slot_cache = KSM_KMEM_CACHE(mm_slot, 0); | 211 | mm_slot_cache = KSM_KMEM_CACHE(mm_slot, 0); |
| 194 | if (!mm_slot_cache) | 212 | if (!mm_slot_cache) |
| 195 | goto out_free; | 213 | goto out_free2; |
| 196 | 214 | ||
| 197 | return 0; | 215 | return 0; |
| 198 | 216 | ||
| 199 | out_free: | 217 | out_free2: |
| 218 | kmem_cache_destroy(stable_node_cache); | ||
| 219 | out_free1: | ||
| 200 | kmem_cache_destroy(rmap_item_cache); | 220 | kmem_cache_destroy(rmap_item_cache); |
| 201 | out: | 221 | out: |
| 202 | return -ENOMEM; | 222 | return -ENOMEM; |
| @@ -205,6 +225,7 @@ out: | |||
| 205 | static void __init ksm_slab_free(void) | 225 | static void __init ksm_slab_free(void) |
| 206 | { | 226 | { |
| 207 | kmem_cache_destroy(mm_slot_cache); | 227 | kmem_cache_destroy(mm_slot_cache); |
| 228 | kmem_cache_destroy(stable_node_cache); | ||
| 208 | kmem_cache_destroy(rmap_item_cache); | 229 | kmem_cache_destroy(rmap_item_cache); |
| 209 | mm_slot_cache = NULL; | 230 | mm_slot_cache = NULL; |
| 210 | } | 231 | } |
| @@ -226,6 +247,16 @@ static inline void free_rmap_item(struct rmap_item *rmap_item) | |||
| 226 | kmem_cache_free(rmap_item_cache, rmap_item); | 247 | kmem_cache_free(rmap_item_cache, rmap_item); |
| 227 | } | 248 | } |
| 228 | 249 | ||
| 250 | static inline struct stable_node *alloc_stable_node(void) | ||
| 251 | { | ||
| 252 | return kmem_cache_alloc(stable_node_cache, GFP_KERNEL); | ||
| 253 | } | ||
| 254 | |||
| 255 | static inline void free_stable_node(struct stable_node *stable_node) | ||
| 256 | { | ||
| 257 | kmem_cache_free(stable_node_cache, stable_node); | ||
| 258 | } | ||
| 259 | |||
| 229 | static inline struct mm_slot *alloc_mm_slot(void) | 260 | static inline struct mm_slot *alloc_mm_slot(void) |
| 230 | { | 261 | { |
| 231 | if (!mm_slot_cache) /* initialization failed */ | 262 | if (!mm_slot_cache) /* initialization failed */ |
| @@ -275,7 +306,6 @@ static void insert_to_mm_slots_hash(struct mm_struct *mm, | |||
| 275 | bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct)) | 306 | bucket = &mm_slots_hash[((unsigned long)mm / sizeof(struct mm_struct)) |
| 276 | % MM_SLOTS_HASH_HEADS]; | 307 | % MM_SLOTS_HASH_HEADS]; |
| 277 | mm_slot->mm = mm; | 308 | mm_slot->mm = mm; |
| 278 | INIT_LIST_HEAD(&mm_slot->rmap_list); | ||
| 279 | hlist_add_head(&mm_slot->link, bucket); | 309 | hlist_add_head(&mm_slot->link, bucket); |
| 280 | } | 310 | } |
| 281 | 311 | ||
| @@ -284,6 +314,25 @@ static inline int in_stable_tree(struct rmap_item *rmap_item) | |||
| 284 | return rmap_item->address & STABLE_FLAG; | 314 | return rmap_item->address & STABLE_FLAG; |
| 285 | } | 315 | } |
| 286 | 316 | ||
| 317 | static void hold_anon_vma(struct rmap_item *rmap_item, | ||
| 318 | struct anon_vma *anon_vma) | ||
| 319 | { | ||
| 320 | rmap_item->anon_vma = anon_vma; | ||
| 321 | atomic_inc(&anon_vma->ksm_refcount); | ||
| 322 | } | ||
| 323 | |||
| 324 | static void drop_anon_vma(struct rmap_item *rmap_item) | ||
| 325 | { | ||
| 326 | struct anon_vma *anon_vma = rmap_item->anon_vma; | ||
| 327 | |||
| 328 | if (atomic_dec_and_lock(&anon_vma->ksm_refcount, &anon_vma->lock)) { | ||
| 329 | int empty = list_empty(&anon_vma->head); | ||
| 330 | spin_unlock(&anon_vma->lock); | ||
| 331 | if (empty) | ||
| 332 | anon_vma_free(anon_vma); | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 287 | /* | 336 | /* |
| 288 | * ksmd, and unmerge_and_remove_all_rmap_items(), must not touch an mm's | 337 | * ksmd, and unmerge_and_remove_all_rmap_items(), must not touch an mm's |
| 289 | * page tables after it has passed through ksm_exit() - which, if necessary, | 338 | * page tables after it has passed through ksm_exit() - which, if necessary, |
| @@ -356,10 +405,18 @@ static int break_ksm(struct vm_area_struct *vma, unsigned long addr) | |||
| 356 | return (ret & VM_FAULT_OOM) ? -ENOMEM : 0; | 405 | return (ret & VM_FAULT_OOM) ? -ENOMEM : 0; |
| 357 | } | 406 | } |
| 358 | 407 | ||
| 359 | static void break_cow(struct mm_struct *mm, unsigned long addr) | 408 | static void break_cow(struct rmap_item *rmap_item) |
| 360 | { | 409 | { |
| 410 | struct mm_struct *mm = rmap_item->mm; | ||
| 411 | unsigned long addr = rmap_item->address; | ||
| 361 | struct vm_area_struct *vma; | 412 | struct vm_area_struct *vma; |
| 362 | 413 | ||
| 414 | /* | ||
| 415 | * It is not an accident that whenever we want to break COW | ||
| 416 | * to undo, we also need to drop a reference to the anon_vma. | ||
| 417 | */ | ||
| 418 | drop_anon_vma(rmap_item); | ||
| 419 | |||
| 363 | down_read(&mm->mmap_sem); | 420 | down_read(&mm->mmap_sem); |
| 364 | if (ksm_test_exit(mm)) | 421 | if (ksm_test_exit(mm)) |
| 365 | goto out; | 422 | goto out; |
| @@ -403,21 +460,77 @@ out: page = NULL; | |||
| 403 | return page; | 460 | return page; |
| 404 | } | 461 | } |
| 405 | 462 | ||
| 463 | static void remove_node_from_stable_tree(struct stable_node *stable_node) | ||
| 464 | { | ||
| 465 | struct rmap_item *rmap_item; | ||
| 466 | struct hlist_node *hlist; | ||
| 467 | |||
| 468 | hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) { | ||
| 469 | if (rmap_item->hlist.next) | ||
| 470 | ksm_pages_sharing--; | ||
| 471 | else | ||
| 472 | ksm_pages_shared--; | ||
| 473 | drop_anon_vma(rmap_item); | ||
| 474 | rmap_item->address &= PAGE_MASK; | ||
| 475 | cond_resched(); | ||
| 476 | } | ||
| 477 | |||
| 478 | rb_erase(&stable_node->node, &root_stable_tree); | ||
| 479 | free_stable_node(stable_node); | ||
| 480 | } | ||
| 481 | |||
| 406 | /* | 482 | /* |
| 407 | * get_ksm_page: checks if the page at the virtual address in rmap_item | 483 | * get_ksm_page: checks if the page indicated by the stable node |
| 408 | * is still PageKsm, in which case we can trust the content of the page, | 484 | * is still its ksm page, despite having held no reference to it. |
| 409 | * and it returns the gotten page; but NULL if the page has been zapped. | 485 | * In which case we can trust the content of the page, and it |
| 486 | * returns the gotten page; but if the page has now been zapped, | ||
| 487 | * remove the stale node from the stable tree and return NULL. | ||
| 488 | * | ||
| 489 | * You would expect the stable_node to hold a reference to the ksm page. | ||
| 490 | * But if it increments the page's count, swapping out has to wait for | ||
| 491 | * ksmd to come around again before it can free the page, which may take | ||
| 492 | * seconds or even minutes: much too unresponsive. So instead we use a | ||
| 493 | * "keyhole reference": access to the ksm page from the stable node peeps | ||
| 494 | * out through its keyhole to see if that page still holds the right key, | ||
| 495 | * pointing back to this stable node. This relies on freeing a PageAnon | ||
| 496 | * page to reset its page->mapping to NULL, and relies on no other use of | ||
| 497 | * a page to put something that might look like our key in page->mapping. | ||
| 498 | * | ||
| 499 | * include/linux/pagemap.h page_cache_get_speculative() is a good reference, | ||
| 500 | * but this is different - made simpler by ksm_thread_mutex being held, but | ||
| 501 | * interesting for assuming that no other use of the struct page could ever | ||
| 502 | * put our expected_mapping into page->mapping (or a field of the union which | ||
| 503 | * coincides with page->mapping). The RCU calls are not for KSM at all, but | ||
| 504 | * to keep the page_count protocol described with page_cache_get_speculative. | ||
| 505 | * | ||
| 506 | * Note: it is possible that get_ksm_page() will return NULL one moment, | ||
| 507 | * then page the next, if the page is in between page_freeze_refs() and | ||
| 508 | * page_unfreeze_refs(): this shouldn't be a problem anywhere, the page | ||
| 509 | * is on its way to being freed; but it is an anomaly to bear in mind. | ||
| 410 | */ | 510 | */ |
| 411 | static struct page *get_ksm_page(struct rmap_item *rmap_item) | 511 | static struct page *get_ksm_page(struct stable_node *stable_node) |
| 412 | { | 512 | { |
| 413 | struct page *page; | 513 | struct page *page; |
| 414 | 514 | void *expected_mapping; | |
| 415 | page = get_mergeable_page(rmap_item); | 515 | |
| 416 | if (page && !PageKsm(page)) { | 516 | page = pfn_to_page(stable_node->kpfn); |
| 517 | expected_mapping = (void *)stable_node + | ||
| 518 | (PAGE_MAPPING_ANON | PAGE_MAPPING_KSM); | ||
| 519 | rcu_read_lock(); | ||
| 520 | if (page->mapping != expected_mapping) | ||
| 521 | goto stale; | ||
| 522 | if (!get_page_unless_zero(page)) | ||
| 523 | goto stale; | ||
| 524 | if (page->mapping != expected_mapping) { | ||
| 417 | put_page(page); | 525 | put_page(page); |
| 418 | page = NULL; | 526 | goto stale; |
| 419 | } | 527 | } |
| 528 | rcu_read_unlock(); | ||
| 420 | return page; | 529 | return page; |
| 530 | stale: | ||
| 531 | rcu_read_unlock(); | ||
| 532 | remove_node_from_stable_tree(stable_node); | ||
| 533 | return NULL; | ||
| 421 | } | 534 | } |
| 422 | 535 | ||
| 423 | /* | 536 | /* |
| @@ -426,35 +539,29 @@ static struct page *get_ksm_page(struct rmap_item *rmap_item) | |||
| 426 | */ | 539 | */ |
| 427 | static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) | 540 | static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) |
| 428 | { | 541 | { |
| 429 | if (in_stable_tree(rmap_item)) { | 542 | if (rmap_item->address & STABLE_FLAG) { |
| 430 | struct rmap_item *next_item = rmap_item->next; | 543 | struct stable_node *stable_node; |
| 431 | 544 | struct page *page; | |
| 432 | if (rmap_item->address & NODE_FLAG) { | ||
| 433 | if (next_item) { | ||
| 434 | rb_replace_node(&rmap_item->node, | ||
| 435 | &next_item->node, | ||
| 436 | &root_stable_tree); | ||
| 437 | next_item->address |= NODE_FLAG; | ||
| 438 | ksm_pages_sharing--; | ||
| 439 | } else { | ||
| 440 | rb_erase(&rmap_item->node, &root_stable_tree); | ||
| 441 | ksm_pages_shared--; | ||
| 442 | } | ||
| 443 | } else { | ||
| 444 | struct rmap_item *prev_item = rmap_item->prev; | ||
| 445 | 545 | ||
| 446 | BUG_ON(prev_item->next != rmap_item); | 546 | stable_node = rmap_item->head; |
| 447 | prev_item->next = next_item; | 547 | page = get_ksm_page(stable_node); |
| 448 | if (next_item) { | 548 | if (!page) |
| 449 | BUG_ON(next_item->prev != rmap_item); | 549 | goto out; |
| 450 | next_item->prev = rmap_item->prev; | 550 | |
| 451 | } | 551 | lock_page(page); |
| 552 | hlist_del(&rmap_item->hlist); | ||
| 553 | unlock_page(page); | ||
| 554 | put_page(page); | ||
| 555 | |||
| 556 | if (stable_node->hlist.first) | ||
| 452 | ksm_pages_sharing--; | 557 | ksm_pages_sharing--; |
| 453 | } | 558 | else |
| 559 | ksm_pages_shared--; | ||
| 454 | 560 | ||
| 455 | rmap_item->next = NULL; | 561 | drop_anon_vma(rmap_item); |
| 562 | rmap_item->address &= PAGE_MASK; | ||
| 456 | 563 | ||
| 457 | } else if (rmap_item->address & NODE_FLAG) { | 564 | } else if (rmap_item->address & UNSTABLE_FLAG) { |
| 458 | unsigned char age; | 565 | unsigned char age; |
| 459 | /* | 566 | /* |
| 460 | * Usually ksmd can and must skip the rb_erase, because | 567 | * Usually ksmd can and must skip the rb_erase, because |
| @@ -467,24 +574,21 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) | |||
| 467 | BUG_ON(age > 1); | 574 | BUG_ON(age > 1); |
| 468 | if (!age) | 575 | if (!age) |
| 469 | rb_erase(&rmap_item->node, &root_unstable_tree); | 576 | rb_erase(&rmap_item->node, &root_unstable_tree); |
| 577 | |||
| 470 | ksm_pages_unshared--; | 578 | ksm_pages_unshared--; |
| 579 | rmap_item->address &= PAGE_MASK; | ||
| 471 | } | 580 | } |
| 472 | 581 | out: | |
| 473 | rmap_item->address &= PAGE_MASK; | ||
| 474 | |||
| 475 | cond_resched(); /* we're called from many long loops */ | 582 | cond_resched(); /* we're called from many long loops */ |
| 476 | } | 583 | } |
| 477 | 584 | ||
| 478 | static void remove_trailing_rmap_items(struct mm_slot *mm_slot, | 585 | static void remove_trailing_rmap_items(struct mm_slot *mm_slot, |
| 479 | struct list_head *cur) | 586 | struct rmap_item **rmap_list) |
| 480 | { | 587 | { |
| 481 | struct rmap_item *rmap_item; | 588 | while (*rmap_list) { |
| 482 | 589 | struct rmap_item *rmap_item = *rmap_list; | |
| 483 | while (cur != &mm_slot->rmap_list) { | 590 | *rmap_list = rmap_item->rmap_list; |
| 484 | rmap_item = list_entry(cur, struct rmap_item, link); | ||
| 485 | cur = cur->next; | ||
| 486 | remove_rmap_item_from_tree(rmap_item); | 591 | remove_rmap_item_from_tree(rmap_item); |
| 487 | list_del(&rmap_item->link); | ||
| 488 | free_rmap_item(rmap_item); | 592 | free_rmap_item(rmap_item); |
| 489 | } | 593 | } |
| 490 | } | 594 | } |
| @@ -550,7 +654,7 @@ static int unmerge_and_remove_all_rmap_items(void) | |||
| 550 | goto error; | 654 | goto error; |
| 551 | } | 655 | } |
| 552 | 656 | ||
| 553 | remove_trailing_rmap_items(mm_slot, mm_slot->rmap_list.next); | 657 | remove_trailing_rmap_items(mm_slot, &mm_slot->rmap_list); |
| 554 | 658 | ||
| 555 | spin_lock(&ksm_mmlist_lock); | 659 | spin_lock(&ksm_mmlist_lock); |
| 556 | ksm_scan.mm_slot = list_entry(mm_slot->mm_list.next, | 660 | ksm_scan.mm_slot = list_entry(mm_slot->mm_list.next, |
| @@ -646,7 +750,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, | |||
| 646 | * Check that no O_DIRECT or similar I/O is in progress on the | 750 | * Check that no O_DIRECT or similar I/O is in progress on the |
| 647 | * page | 751 | * page |
| 648 | */ | 752 | */ |
| 649 | if ((page_mapcount(page) + 2 + swapped) != page_count(page)) { | 753 | if (page_mapcount(page) + 1 + swapped != page_count(page)) { |
| 650 | set_pte_at_notify(mm, addr, ptep, entry); | 754 | set_pte_at_notify(mm, addr, ptep, entry); |
| 651 | goto out_unlock; | 755 | goto out_unlock; |
| 652 | } | 756 | } |
| @@ -664,15 +768,15 @@ out: | |||
| 664 | 768 | ||
| 665 | /** | 769 | /** |
| 666 | * replace_page - replace page in vma by new ksm page | 770 | * replace_page - replace page in vma by new ksm page |
| 667 | * @vma: vma that holds the pte pointing to oldpage | 771 | * @vma: vma that holds the pte pointing to page |
| 668 | * @oldpage: the page we are replacing by newpage | 772 | * @page: the page we are replacing by kpage |
| 669 | * @newpage: the ksm page we replace oldpage by | 773 | * @kpage: the ksm page we replace page by |
| 670 | * @orig_pte: the original value of the pte | 774 | * @orig_pte: the original value of the pte |
| 671 | * | 775 | * |
| 672 | * Returns 0 on success, -EFAULT on failure. | 776 | * Returns 0 on success, -EFAULT on failure. |
| 673 | */ | 777 | */ |
| 674 | static int replace_page(struct vm_area_struct *vma, struct page *oldpage, | 778 | static int replace_page(struct vm_area_struct *vma, struct page *page, |
| 675 | struct page *newpage, pte_t orig_pte) | 779 | struct page *kpage, pte_t orig_pte) |
| 676 | { | 780 | { |
| 677 | struct mm_struct *mm = vma->vm_mm; | 781 | struct mm_struct *mm = vma->vm_mm; |
| 678 | pgd_t *pgd; | 782 | pgd_t *pgd; |
| @@ -681,12 +785,9 @@ static int replace_page(struct vm_area_struct *vma, struct page *oldpage, | |||
| 681 | pte_t *ptep; | 785 | pte_t *ptep; |
| 682 | spinlock_t *ptl; | 786 | spinlock_t *ptl; |
| 683 | unsigned long addr; | 787 | unsigned long addr; |
| 684 | pgprot_t prot; | ||
| 685 | int err = -EFAULT; | 788 | int err = -EFAULT; |
| 686 | 789 | ||
| 687 | prot = vm_get_page_prot(vma->vm_flags & ~VM_WRITE); | 790 | addr = page_address_in_vma(page, vma); |
| 688 | |||
| 689 | addr = page_address_in_vma(oldpage, vma); | ||
| 690 | if (addr == -EFAULT) | 791 | if (addr == -EFAULT) |
| 691 | goto out; | 792 | goto out; |
| 692 | 793 | ||
| @@ -708,15 +809,15 @@ static int replace_page(struct vm_area_struct *vma, struct page *oldpage, | |||
| 708 | goto out; | 809 | goto out; |
| 709 | } | 810 | } |
| 710 | 811 | ||
| 711 | get_page(newpage); | 812 | get_page(kpage); |
| 712 | page_add_ksm_rmap(newpage); | 813 | page_add_anon_rmap(kpage, vma, addr); |
| 713 | 814 | ||
| 714 | flush_cache_page(vma, addr, pte_pfn(*ptep)); | 815 | flush_cache_page(vma, addr, pte_pfn(*ptep)); |
| 715 | ptep_clear_flush(vma, addr, ptep); | 816 | ptep_clear_flush(vma, addr, ptep); |
| 716 | set_pte_at_notify(mm, addr, ptep, mk_pte(newpage, prot)); | 817 | set_pte_at_notify(mm, addr, ptep, mk_pte(kpage, vma->vm_page_prot)); |
| 717 | 818 | ||
| 718 | page_remove_rmap(oldpage); | 819 | page_remove_rmap(page); |
| 719 | put_page(oldpage); | 820 | put_page(page); |
| 720 | 821 | ||
| 721 | pte_unmap_unlock(ptep, ptl); | 822 | pte_unmap_unlock(ptep, ptl); |
| 722 | err = 0; | 823 | err = 0; |
| @@ -726,32 +827,27 @@ out: | |||
| 726 | 827 | ||
| 727 | /* | 828 | /* |
| 728 | * try_to_merge_one_page - take two pages and merge them into one | 829 | * try_to_merge_one_page - take two pages and merge them into one |
| 729 | * @vma: the vma that hold the pte pointing into oldpage | 830 | * @vma: the vma that holds the pte pointing to page |
| 730 | * @oldpage: the page that we want to replace with newpage | 831 | * @page: the PageAnon page that we want to replace with kpage |
| 731 | * @newpage: the page that we want to map instead of oldpage | 832 | * @kpage: the PageKsm page that we want to map instead of page, |
| 732 | * | 833 | * or NULL the first time when we want to use page as kpage. |
| 733 | * Note: | ||
| 734 | * oldpage should be a PageAnon page, while newpage should be a PageKsm page, | ||
| 735 | * or a newly allocated kernel page which page_add_ksm_rmap will make PageKsm. | ||
| 736 | * | 834 | * |
| 737 | * This function returns 0 if the pages were merged, -EFAULT otherwise. | 835 | * This function returns 0 if the pages were merged, -EFAULT otherwise. |
| 738 | */ | 836 | */ |
| 739 | static int try_to_merge_one_page(struct vm_area_struct *vma, | 837 | static int try_to_merge_one_page(struct vm_area_struct *vma, |
| 740 | struct page *oldpage, | 838 | struct page *page, struct page *kpage) |
| 741 | struct page *newpage) | ||
| 742 | { | 839 | { |
| 743 | pte_t orig_pte = __pte(0); | 840 | pte_t orig_pte = __pte(0); |
| 744 | int err = -EFAULT; | 841 | int err = -EFAULT; |
| 745 | 842 | ||
| 843 | if (page == kpage) /* ksm page forked */ | ||
| 844 | return 0; | ||
| 845 | |||
| 746 | if (!(vma->vm_flags & VM_MERGEABLE)) | 846 | if (!(vma->vm_flags & VM_MERGEABLE)) |
| 747 | goto out; | 847 | goto out; |
| 748 | 848 | if (!PageAnon(page)) | |
| 749 | if (!PageAnon(oldpage)) | ||
| 750 | goto out; | 849 | goto out; |
| 751 | 850 | ||
| 752 | get_page(newpage); | ||
| 753 | get_page(oldpage); | ||
| 754 | |||
| 755 | /* | 851 | /* |
| 756 | * We need the page lock to read a stable PageSwapCache in | 852 | * We need the page lock to read a stable PageSwapCache in |
| 757 | * write_protect_page(). We use trylock_page() instead of | 853 | * write_protect_page(). We use trylock_page() instead of |
| @@ -759,26 +855,39 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, | |||
| 759 | * prefer to continue scanning and merging different pages, | 855 | * prefer to continue scanning and merging different pages, |
| 760 | * then come back to this page when it is unlocked. | 856 | * then come back to this page when it is unlocked. |
| 761 | */ | 857 | */ |
| 762 | if (!trylock_page(oldpage)) | 858 | if (!trylock_page(page)) |
| 763 | goto out_putpage; | 859 | goto out; |
| 764 | /* | 860 | /* |
| 765 | * If this anonymous page is mapped only here, its pte may need | 861 | * If this anonymous page is mapped only here, its pte may need |
| 766 | * to be write-protected. If it's mapped elsewhere, all of its | 862 | * to be write-protected. If it's mapped elsewhere, all of its |
| 767 | * ptes are necessarily already write-protected. But in either | 863 | * ptes are necessarily already write-protected. But in either |
| 768 | * case, we need to lock and check page_count is not raised. | 864 | * case, we need to lock and check page_count is not raised. |
| 769 | */ | 865 | */ |
| 770 | if (write_protect_page(vma, oldpage, &orig_pte)) { | 866 | if (write_protect_page(vma, page, &orig_pte) == 0) { |
| 771 | unlock_page(oldpage); | 867 | if (!kpage) { |
| 772 | goto out_putpage; | 868 | /* |
| 869 | * While we hold page lock, upgrade page from | ||
| 870 | * PageAnon+anon_vma to PageKsm+NULL stable_node: | ||
| 871 | * stable_tree_insert() will update stable_node. | ||
| 872 | */ | ||
| 873 | set_page_stable_node(page, NULL); | ||
| 874 | mark_page_accessed(page); | ||
| 875 | err = 0; | ||
| 876 | } else if (pages_identical(page, kpage)) | ||
| 877 | err = replace_page(vma, page, kpage, orig_pte); | ||
| 773 | } | 878 | } |
| 774 | unlock_page(oldpage); | ||
| 775 | 879 | ||
| 776 | if (pages_identical(oldpage, newpage)) | 880 | if ((vma->vm_flags & VM_LOCKED) && kpage && !err) { |
| 777 | err = replace_page(vma, oldpage, newpage, orig_pte); | 881 | munlock_vma_page(page); |
| 882 | if (!PageMlocked(kpage)) { | ||
| 883 | unlock_page(page); | ||
| 884 | lock_page(kpage); | ||
| 885 | mlock_vma_page(kpage); | ||
| 886 | page = kpage; /* for final unlock */ | ||
| 887 | } | ||
| 888 | } | ||
| 778 | 889 | ||
| 779 | out_putpage: | 890 | unlock_page(page); |
| 780 | put_page(oldpage); | ||
| 781 | put_page(newpage); | ||
| 782 | out: | 891 | out: |
| 783 | return err; | 892 | return err; |
| 784 | } | 893 | } |
| @@ -786,26 +895,31 @@ out: | |||
| 786 | /* | 895 | /* |
| 787 | * try_to_merge_with_ksm_page - like try_to_merge_two_pages, | 896 | * try_to_merge_with_ksm_page - like try_to_merge_two_pages, |
| 788 | * but no new kernel page is allocated: kpage must already be a ksm page. | 897 | * but no new kernel page is allocated: kpage must already be a ksm page. |
| 898 | * | ||
| 899 | * This function returns 0 if the pages were merged, -EFAULT otherwise. | ||
| 789 | */ | 900 | */ |
| 790 | static int try_to_merge_with_ksm_page(struct mm_struct *mm1, | 901 | static int try_to_merge_with_ksm_page(struct rmap_item *rmap_item, |
| 791 | unsigned long addr1, | 902 | struct page *page, struct page *kpage) |
| 792 | struct page *page1, | ||
| 793 | struct page *kpage) | ||
| 794 | { | 903 | { |
| 904 | struct mm_struct *mm = rmap_item->mm; | ||
| 795 | struct vm_area_struct *vma; | 905 | struct vm_area_struct *vma; |
| 796 | int err = -EFAULT; | 906 | int err = -EFAULT; |
| 797 | 907 | ||
| 798 | down_read(&mm1->mmap_sem); | 908 | down_read(&mm->mmap_sem); |
| 799 | if (ksm_test_exit(mm1)) | 909 | if (ksm_test_exit(mm)) |
| 910 | goto out; | ||
| 911 | vma = find_vma(mm, rmap_item->address); | ||
| 912 | if (!vma || vma->vm_start > rmap_item->address) | ||
| 800 | goto out; | 913 | goto out; |
| 801 | 914 | ||
| 802 | vma = find_vma(mm1, addr1); | 915 | err = try_to_merge_one_page(vma, page, kpage); |
| 803 | if (!vma || vma->vm_start > addr1) | 916 | if (err) |
| 804 | goto out; | 917 | goto out; |
| 805 | 918 | ||
| 806 | err = try_to_merge_one_page(vma, page1, kpage); | 919 | /* Must get reference to anon_vma while still holding mmap_sem */ |
| 920 | hold_anon_vma(rmap_item, vma->anon_vma); | ||
| 807 | out: | 921 | out: |
| 808 | up_read(&mm1->mmap_sem); | 922 | up_read(&mm->mmap_sem); |
| 809 | return err; | 923 | return err; |
| 810 | } | 924 | } |
| 811 | 925 | ||
| @@ -813,109 +927,73 @@ out: | |||
| 813 | * try_to_merge_two_pages - take two identical pages and prepare them | 927 | * try_to_merge_two_pages - take two identical pages and prepare them |
| 814 | * to be merged into one page. | 928 | * to be merged into one page. |
| 815 | * | 929 | * |
| 816 | * This function returns 0 if we successfully mapped two identical pages | 930 | * This function returns the kpage if we successfully merged two identical |
| 817 | * into one page, -EFAULT otherwise. | 931 | * pages into one ksm page, NULL otherwise. |
| 818 | * | 932 | * |
| 819 | * Note that this function allocates a new kernel page: if one of the pages | 933 | * Note that this function upgrades page to ksm page: if one of the pages |
| 820 | * is already a ksm page, try_to_merge_with_ksm_page should be used. | 934 | * is already a ksm page, try_to_merge_with_ksm_page should be used. |
| 821 | */ | 935 | */ |
| 822 | static int try_to_merge_two_pages(struct mm_struct *mm1, unsigned long addr1, | 936 | static struct page *try_to_merge_two_pages(struct rmap_item *rmap_item, |
| 823 | struct page *page1, struct mm_struct *mm2, | 937 | struct page *page, |
| 824 | unsigned long addr2, struct page *page2) | 938 | struct rmap_item *tree_rmap_item, |
| 939 | struct page *tree_page) | ||
| 825 | { | 940 | { |
| 826 | struct vm_area_struct *vma; | 941 | int err; |
| 827 | struct page *kpage; | ||
| 828 | int err = -EFAULT; | ||
| 829 | |||
| 830 | /* | ||
| 831 | * The number of nodes in the stable tree | ||
| 832 | * is the number of kernel pages that we hold. | ||
| 833 | */ | ||
| 834 | if (ksm_max_kernel_pages && | ||
| 835 | ksm_max_kernel_pages <= ksm_pages_shared) | ||
| 836 | return err; | ||
| 837 | |||
| 838 | kpage = alloc_page(GFP_HIGHUSER); | ||
| 839 | if (!kpage) | ||
| 840 | return err; | ||
| 841 | |||
| 842 | down_read(&mm1->mmap_sem); | ||
| 843 | if (ksm_test_exit(mm1)) { | ||
| 844 | up_read(&mm1->mmap_sem); | ||
| 845 | goto out; | ||
| 846 | } | ||
| 847 | vma = find_vma(mm1, addr1); | ||
| 848 | if (!vma || vma->vm_start > addr1) { | ||
| 849 | up_read(&mm1->mmap_sem); | ||
| 850 | goto out; | ||
| 851 | } | ||
| 852 | |||
| 853 | copy_user_highpage(kpage, page1, addr1, vma); | ||
| 854 | err = try_to_merge_one_page(vma, page1, kpage); | ||
| 855 | up_read(&mm1->mmap_sem); | ||
| 856 | 942 | ||
| 943 | err = try_to_merge_with_ksm_page(rmap_item, page, NULL); | ||
| 857 | if (!err) { | 944 | if (!err) { |
| 858 | err = try_to_merge_with_ksm_page(mm2, addr2, page2, kpage); | 945 | err = try_to_merge_with_ksm_page(tree_rmap_item, |
| 946 | tree_page, page); | ||
| 859 | /* | 947 | /* |
| 860 | * If that fails, we have a ksm page with only one pte | 948 | * If that fails, we have a ksm page with only one pte |
| 861 | * pointing to it: so break it. | 949 | * pointing to it: so break it. |
| 862 | */ | 950 | */ |
| 863 | if (err) | 951 | if (err) |
| 864 | break_cow(mm1, addr1); | 952 | break_cow(rmap_item); |
| 865 | } | 953 | } |
| 866 | out: | 954 | return err ? NULL : page; |
| 867 | put_page(kpage); | ||
| 868 | return err; | ||
| 869 | } | 955 | } |
| 870 | 956 | ||
| 871 | /* | 957 | /* |
| 872 | * stable_tree_search - search page inside the stable tree | 958 | * stable_tree_search - search for page inside the stable tree |
| 873 | * @page: the page that we are searching identical pages to. | ||
| 874 | * @page2: pointer into identical page that we are holding inside the stable | ||
| 875 | * tree that we have found. | ||
| 876 | * @rmap_item: the reverse mapping item | ||
| 877 | * | 959 | * |
| 878 | * This function checks if there is a page inside the stable tree | 960 | * This function checks if there is a page inside the stable tree |
| 879 | * with identical content to the page that we are scanning right now. | 961 | * with identical content to the page that we are scanning right now. |
| 880 | * | 962 | * |
| 881 | * This function return rmap_item pointer to the identical item if found, | 963 | * This function returns the stable tree node of identical content if found, |
| 882 | * NULL otherwise. | 964 | * NULL otherwise. |
| 883 | */ | 965 | */ |
| 884 | static struct rmap_item *stable_tree_search(struct page *page, | 966 | static struct page *stable_tree_search(struct page *page) |
| 885 | struct page **page2, | ||
| 886 | struct rmap_item *rmap_item) | ||
| 887 | { | 967 | { |
| 888 | struct rb_node *node = root_stable_tree.rb_node; | 968 | struct rb_node *node = root_stable_tree.rb_node; |
| 969 | struct stable_node *stable_node; | ||
| 970 | |||
| 971 | stable_node = page_stable_node(page); | ||
| 972 | if (stable_node) { /* ksm page forked */ | ||
| 973 | get_page(page); | ||
| 974 | return page; | ||
| 975 | } | ||
| 889 | 976 | ||
| 890 | while (node) { | 977 | while (node) { |
| 891 | struct rmap_item *tree_rmap_item, *next_rmap_item; | 978 | struct page *tree_page; |
| 892 | int ret; | 979 | int ret; |
| 893 | 980 | ||
| 894 | tree_rmap_item = rb_entry(node, struct rmap_item, node); | 981 | cond_resched(); |
| 895 | while (tree_rmap_item) { | 982 | stable_node = rb_entry(node, struct stable_node, node); |
| 896 | BUG_ON(!in_stable_tree(tree_rmap_item)); | 983 | tree_page = get_ksm_page(stable_node); |
| 897 | cond_resched(); | 984 | if (!tree_page) |
| 898 | page2[0] = get_ksm_page(tree_rmap_item); | ||
| 899 | if (page2[0]) | ||
| 900 | break; | ||
| 901 | next_rmap_item = tree_rmap_item->next; | ||
| 902 | remove_rmap_item_from_tree(tree_rmap_item); | ||
| 903 | tree_rmap_item = next_rmap_item; | ||
| 904 | } | ||
| 905 | if (!tree_rmap_item) | ||
| 906 | return NULL; | 985 | return NULL; |
| 907 | 986 | ||
| 908 | ret = memcmp_pages(page, page2[0]); | 987 | ret = memcmp_pages(page, tree_page); |
| 909 | 988 | ||
| 910 | if (ret < 0) { | 989 | if (ret < 0) { |
| 911 | put_page(page2[0]); | 990 | put_page(tree_page); |
| 912 | node = node->rb_left; | 991 | node = node->rb_left; |
| 913 | } else if (ret > 0) { | 992 | } else if (ret > 0) { |
| 914 | put_page(page2[0]); | 993 | put_page(tree_page); |
| 915 | node = node->rb_right; | 994 | node = node->rb_right; |
| 916 | } else { | 995 | } else |
| 917 | return tree_rmap_item; | 996 | return tree_page; |
| 918 | } | ||
| 919 | } | 997 | } |
| 920 | 998 | ||
| 921 | return NULL; | 999 | return NULL; |
| @@ -925,38 +1003,26 @@ static struct rmap_item *stable_tree_search(struct page *page, | |||
| 925 | * stable_tree_insert - insert rmap_item pointing to new ksm page | 1003 | * stable_tree_insert - insert rmap_item pointing to new ksm page |
| 926 | * into the stable tree. | 1004 | * into the stable tree. |
| 927 | * | 1005 | * |
| 928 | * @page: the page that we are searching identical page to inside the stable | 1006 | * This function returns the stable tree node just allocated on success, |
| 929 | * tree. | 1007 | * NULL otherwise. |
| 930 | * @rmap_item: pointer to the reverse mapping item. | ||
| 931 | * | ||
| 932 | * This function returns rmap_item if success, NULL otherwise. | ||
| 933 | */ | 1008 | */ |
| 934 | static struct rmap_item *stable_tree_insert(struct page *page, | 1009 | static struct stable_node *stable_tree_insert(struct page *kpage) |
| 935 | struct rmap_item *rmap_item) | ||
| 936 | { | 1010 | { |
| 937 | struct rb_node **new = &root_stable_tree.rb_node; | 1011 | struct rb_node **new = &root_stable_tree.rb_node; |
| 938 | struct rb_node *parent = NULL; | 1012 | struct rb_node *parent = NULL; |
| 1013 | struct stable_node *stable_node; | ||
| 939 | 1014 | ||
| 940 | while (*new) { | 1015 | while (*new) { |
| 941 | struct rmap_item *tree_rmap_item, *next_rmap_item; | ||
| 942 | struct page *tree_page; | 1016 | struct page *tree_page; |
| 943 | int ret; | 1017 | int ret; |
| 944 | 1018 | ||
| 945 | tree_rmap_item = rb_entry(*new, struct rmap_item, node); | 1019 | cond_resched(); |
| 946 | while (tree_rmap_item) { | 1020 | stable_node = rb_entry(*new, struct stable_node, node); |
| 947 | BUG_ON(!in_stable_tree(tree_rmap_item)); | 1021 | tree_page = get_ksm_page(stable_node); |
| 948 | cond_resched(); | 1022 | if (!tree_page) |
| 949 | tree_page = get_ksm_page(tree_rmap_item); | ||
| 950 | if (tree_page) | ||
| 951 | break; | ||
| 952 | next_rmap_item = tree_rmap_item->next; | ||
| 953 | remove_rmap_item_from_tree(tree_rmap_item); | ||
| 954 | tree_rmap_item = next_rmap_item; | ||
| 955 | } | ||
| 956 | if (!tree_rmap_item) | ||
| 957 | return NULL; | 1023 | return NULL; |
| 958 | 1024 | ||
| 959 | ret = memcmp_pages(page, tree_page); | 1025 | ret = memcmp_pages(kpage, tree_page); |
| 960 | put_page(tree_page); | 1026 | put_page(tree_page); |
| 961 | 1027 | ||
| 962 | parent = *new; | 1028 | parent = *new; |
| @@ -974,22 +1040,24 @@ static struct rmap_item *stable_tree_insert(struct page *page, | |||
| 974 | } | 1040 | } |
| 975 | } | 1041 | } |
| 976 | 1042 | ||
| 977 | rmap_item->address |= NODE_FLAG | STABLE_FLAG; | 1043 | stable_node = alloc_stable_node(); |
| 978 | rmap_item->next = NULL; | 1044 | if (!stable_node) |
| 979 | rb_link_node(&rmap_item->node, parent, new); | 1045 | return NULL; |
| 980 | rb_insert_color(&rmap_item->node, &root_stable_tree); | ||
| 981 | 1046 | ||
| 982 | ksm_pages_shared++; | 1047 | rb_link_node(&stable_node->node, parent, new); |
| 983 | return rmap_item; | 1048 | rb_insert_color(&stable_node->node, &root_stable_tree); |
| 1049 | |||
| 1050 | INIT_HLIST_HEAD(&stable_node->hlist); | ||
| 1051 | |||
| 1052 | stable_node->kpfn = page_to_pfn(kpage); | ||
| 1053 | set_page_stable_node(kpage, stable_node); | ||
| 1054 | |||
| 1055 | return stable_node; | ||
| 984 | } | 1056 | } |
| 985 | 1057 | ||
| 986 | /* | 1058 | /* |
| 987 | * unstable_tree_search_insert - search and insert items into the unstable tree. | 1059 | * unstable_tree_search_insert - search for identical page, |
| 988 | * | 1060 | * else insert rmap_item into the unstable tree. |
| 989 | * @page: the page that we are going to search for identical page or to insert | ||
| 990 | * into the unstable tree | ||
| 991 | * @page2: pointer into identical page that was found inside the unstable tree | ||
| 992 | * @rmap_item: the reverse mapping item of page | ||
| 993 | * | 1061 | * |
| 994 | * This function searches for a page in the unstable tree identical to the | 1062 | * This function searches for a page in the unstable tree identical to the |
| 995 | * page currently being scanned; and if no identical page is found in the | 1063 | * page currently being scanned; and if no identical page is found in the |
| @@ -1001,47 +1069,50 @@ static struct rmap_item *stable_tree_insert(struct page *page, | |||
| 1001 | * This function does both searching and inserting, because they share | 1069 | * This function does both searching and inserting, because they share |
| 1002 | * the same walking algorithm in an rbtree. | 1070 | * the same walking algorithm in an rbtree. |
| 1003 | */ | 1071 | */ |
| 1004 | static struct rmap_item *unstable_tree_search_insert(struct page *page, | 1072 | static |
| 1005 | struct page **page2, | 1073 | struct rmap_item *unstable_tree_search_insert(struct rmap_item *rmap_item, |
| 1006 | struct rmap_item *rmap_item) | 1074 | struct page *page, |
| 1075 | struct page **tree_pagep) | ||
| 1076 | |||
| 1007 | { | 1077 | { |
| 1008 | struct rb_node **new = &root_unstable_tree.rb_node; | 1078 | struct rb_node **new = &root_unstable_tree.rb_node; |
| 1009 | struct rb_node *parent = NULL; | 1079 | struct rb_node *parent = NULL; |
| 1010 | 1080 | ||
| 1011 | while (*new) { | 1081 | while (*new) { |
| 1012 | struct rmap_item *tree_rmap_item; | 1082 | struct rmap_item *tree_rmap_item; |
| 1083 | struct page *tree_page; | ||
| 1013 | int ret; | 1084 | int ret; |
| 1014 | 1085 | ||
| 1015 | cond_resched(); | 1086 | cond_resched(); |
| 1016 | tree_rmap_item = rb_entry(*new, struct rmap_item, node); | 1087 | tree_rmap_item = rb_entry(*new, struct rmap_item, node); |
| 1017 | page2[0] = get_mergeable_page(tree_rmap_item); | 1088 | tree_page = get_mergeable_page(tree_rmap_item); |
| 1018 | if (!page2[0]) | 1089 | if (!tree_page) |
| 1019 | return NULL; | 1090 | return NULL; |
| 1020 | 1091 | ||
| 1021 | /* | 1092 | /* |
| 1022 | * Don't substitute an unswappable ksm page | 1093 | * Don't substitute a ksm page for a forked page. |
| 1023 | * just for one good swappable forked page. | ||
| 1024 | */ | 1094 | */ |
| 1025 | if (page == page2[0]) { | 1095 | if (page == tree_page) { |
| 1026 | put_page(page2[0]); | 1096 | put_page(tree_page); |
| 1027 | return NULL; | 1097 | return NULL; |
| 1028 | } | 1098 | } |
| 1029 | 1099 | ||
| 1030 | ret = memcmp_pages(page, page2[0]); | 1100 | ret = memcmp_pages(page, tree_page); |
| 1031 | 1101 | ||
| 1032 | parent = *new; | 1102 | parent = *new; |
| 1033 | if (ret < 0) { | 1103 | if (ret < 0) { |
| 1034 | put_page(page2[0]); | 1104 | put_page(tree_page); |
| 1035 | new = &parent->rb_left; | 1105 | new = &parent->rb_left; |
| 1036 | } else if (ret > 0) { | 1106 | } else if (ret > 0) { |
| 1037 | put_page(page2[0]); | 1107 | put_page(tree_page); |
| 1038 | new = &parent->rb_right; | 1108 | new = &parent->rb_right; |
| 1039 | } else { | 1109 | } else { |
| 1110 | *tree_pagep = tree_page; | ||
| 1040 | return tree_rmap_item; | 1111 | return tree_rmap_item; |
| 1041 | } | 1112 | } |
| 1042 | } | 1113 | } |
| 1043 | 1114 | ||
| 1044 | rmap_item->address |= NODE_FLAG; | 1115 | rmap_item->address |= UNSTABLE_FLAG; |
| 1045 | rmap_item->address |= (ksm_scan.seqnr & SEQNR_MASK); | 1116 | rmap_item->address |= (ksm_scan.seqnr & SEQNR_MASK); |
| 1046 | rb_link_node(&rmap_item->node, parent, new); | 1117 | rb_link_node(&rmap_item->node, parent, new); |
| 1047 | rb_insert_color(&rmap_item->node, &root_unstable_tree); | 1118 | rb_insert_color(&rmap_item->node, &root_unstable_tree); |
| @@ -1056,18 +1127,16 @@ static struct rmap_item *unstable_tree_search_insert(struct page *page, | |||
| 1056 | * the same ksm page. | 1127 | * the same ksm page. |
| 1057 | */ | 1128 | */ |
| 1058 | static void stable_tree_append(struct rmap_item *rmap_item, | 1129 | static void stable_tree_append(struct rmap_item *rmap_item, |
| 1059 | struct rmap_item *tree_rmap_item) | 1130 | struct stable_node *stable_node) |
| 1060 | { | 1131 | { |
| 1061 | rmap_item->next = tree_rmap_item->next; | 1132 | rmap_item->head = stable_node; |
| 1062 | rmap_item->prev = tree_rmap_item; | ||
| 1063 | |||
| 1064 | if (tree_rmap_item->next) | ||
| 1065 | tree_rmap_item->next->prev = rmap_item; | ||
| 1066 | |||
| 1067 | tree_rmap_item->next = rmap_item; | ||
| 1068 | rmap_item->address |= STABLE_FLAG; | 1133 | rmap_item->address |= STABLE_FLAG; |
| 1134 | hlist_add_head(&rmap_item->hlist, &stable_node->hlist); | ||
| 1069 | 1135 | ||
| 1070 | ksm_pages_sharing++; | 1136 | if (rmap_item->hlist.next) |
| 1137 | ksm_pages_sharing++; | ||
| 1138 | else | ||
| 1139 | ksm_pages_shared++; | ||
| 1071 | } | 1140 | } |
| 1072 | 1141 | ||
| 1073 | /* | 1142 | /* |
| @@ -1081,49 +1150,37 @@ static void stable_tree_append(struct rmap_item *rmap_item, | |||
| 1081 | */ | 1150 | */ |
| 1082 | static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item) | 1151 | static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item) |
| 1083 | { | 1152 | { |
| 1084 | struct page *page2[1]; | ||
| 1085 | struct rmap_item *tree_rmap_item; | 1153 | struct rmap_item *tree_rmap_item; |
| 1154 | struct page *tree_page = NULL; | ||
| 1155 | struct stable_node *stable_node; | ||
| 1156 | struct page *kpage; | ||
| 1086 | unsigned int checksum; | 1157 | unsigned int checksum; |
| 1087 | int err; | 1158 | int err; |
| 1088 | 1159 | ||
| 1089 | if (in_stable_tree(rmap_item)) | 1160 | remove_rmap_item_from_tree(rmap_item); |
| 1090 | remove_rmap_item_from_tree(rmap_item); | ||
| 1091 | 1161 | ||
| 1092 | /* We first start with searching the page inside the stable tree */ | 1162 | /* We first start with searching the page inside the stable tree */ |
| 1093 | tree_rmap_item = stable_tree_search(page, page2, rmap_item); | 1163 | kpage = stable_tree_search(page); |
| 1094 | if (tree_rmap_item) { | 1164 | if (kpage) { |
| 1095 | if (page == page2[0]) /* forked */ | 1165 | err = try_to_merge_with_ksm_page(rmap_item, page, kpage); |
| 1096 | err = 0; | ||
| 1097 | else | ||
| 1098 | err = try_to_merge_with_ksm_page(rmap_item->mm, | ||
| 1099 | rmap_item->address, | ||
| 1100 | page, page2[0]); | ||
| 1101 | put_page(page2[0]); | ||
| 1102 | |||
| 1103 | if (!err) { | 1166 | if (!err) { |
| 1104 | /* | 1167 | /* |
| 1105 | * The page was successfully merged: | 1168 | * The page was successfully merged: |
| 1106 | * add its rmap_item to the stable tree. | 1169 | * add its rmap_item to the stable tree. |
| 1107 | */ | 1170 | */ |
| 1108 | stable_tree_append(rmap_item, tree_rmap_item); | 1171 | lock_page(kpage); |
| 1172 | stable_tree_append(rmap_item, page_stable_node(kpage)); | ||
| 1173 | unlock_page(kpage); | ||
| 1109 | } | 1174 | } |
| 1175 | put_page(kpage); | ||
| 1110 | return; | 1176 | return; |
| 1111 | } | 1177 | } |
| 1112 | 1178 | ||
| 1113 | /* | 1179 | /* |
| 1114 | * A ksm page might have got here by fork, but its other | 1180 | * If the hash value of the page has changed from the last time |
| 1115 | * references have already been removed from the stable tree. | 1181 | * we calculated it, this page is changing frequently: therefore we |
| 1116 | * Or it might be left over from a break_ksm which failed | 1182 | * don't want to insert it in the unstable tree, and we don't want |
| 1117 | * when the mem_cgroup had reached its limit: try again now. | 1183 | * to waste our time searching for something identical to it there. |
| 1118 | */ | ||
| 1119 | if (PageKsm(page)) | ||
| 1120 | break_cow(rmap_item->mm, rmap_item->address); | ||
| 1121 | |||
| 1122 | /* | ||
| 1123 | * In case the hash value of the page was changed from the last time we | ||
| 1124 | * have calculated it, this page to be changed frequely, therefore we | ||
| 1125 | * don't want to insert it to the unstable tree, and we don't want to | ||
| 1126 | * waste our time to search if there is something identical to it there. | ||
| 1127 | */ | 1184 | */ |
| 1128 | checksum = calc_checksum(page); | 1185 | checksum = calc_checksum(page); |
| 1129 | if (rmap_item->oldchecksum != checksum) { | 1186 | if (rmap_item->oldchecksum != checksum) { |
| @@ -1131,21 +1188,27 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item) | |||
| 1131 | return; | 1188 | return; |
| 1132 | } | 1189 | } |
| 1133 | 1190 | ||
| 1134 | tree_rmap_item = unstable_tree_search_insert(page, page2, rmap_item); | 1191 | tree_rmap_item = |
| 1192 | unstable_tree_search_insert(rmap_item, page, &tree_page); | ||
| 1135 | if (tree_rmap_item) { | 1193 | if (tree_rmap_item) { |
| 1136 | err = try_to_merge_two_pages(rmap_item->mm, | 1194 | kpage = try_to_merge_two_pages(rmap_item, page, |
| 1137 | rmap_item->address, page, | 1195 | tree_rmap_item, tree_page); |
| 1138 | tree_rmap_item->mm, | 1196 | put_page(tree_page); |
| 1139 | tree_rmap_item->address, page2[0]); | ||
| 1140 | /* | 1197 | /* |
| 1141 | * As soon as we merge this page, we want to remove the | 1198 | * As soon as we merge this page, we want to remove the |
| 1142 | * rmap_item of the page we have merged with from the unstable | 1199 | * rmap_item of the page we have merged with from the unstable |
| 1143 | * tree, and insert it instead as new node in the stable tree. | 1200 | * tree, and insert it instead as new node in the stable tree. |
| 1144 | */ | 1201 | */ |
| 1145 | if (!err) { | 1202 | if (kpage) { |
| 1146 | rb_erase(&tree_rmap_item->node, &root_unstable_tree); | 1203 | remove_rmap_item_from_tree(tree_rmap_item); |
| 1147 | tree_rmap_item->address &= ~NODE_FLAG; | 1204 | |
| 1148 | ksm_pages_unshared--; | 1205 | lock_page(kpage); |
| 1206 | stable_node = stable_tree_insert(kpage); | ||
| 1207 | if (stable_node) { | ||
| 1208 | stable_tree_append(tree_rmap_item, stable_node); | ||
| 1209 | stable_tree_append(rmap_item, stable_node); | ||
| 1210 | } | ||
| 1211 | unlock_page(kpage); | ||
| 1149 | 1212 | ||
| 1150 | /* | 1213 | /* |
| 1151 | * If we fail to insert the page into the stable tree, | 1214 | * If we fail to insert the page into the stable tree, |
| @@ -1153,37 +1216,28 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item) | |||
| 1153 | * to a ksm page left outside the stable tree, | 1216 | * to a ksm page left outside the stable tree, |
| 1154 | * in which case we need to break_cow on both. | 1217 | * in which case we need to break_cow on both. |
| 1155 | */ | 1218 | */ |
| 1156 | if (stable_tree_insert(page2[0], tree_rmap_item)) | 1219 | if (!stable_node) { |
| 1157 | stable_tree_append(rmap_item, tree_rmap_item); | 1220 | break_cow(tree_rmap_item); |
| 1158 | else { | 1221 | break_cow(rmap_item); |
| 1159 | break_cow(tree_rmap_item->mm, | ||
| 1160 | tree_rmap_item->address); | ||
| 1161 | break_cow(rmap_item->mm, rmap_item->address); | ||
| 1162 | } | 1222 | } |
| 1163 | } | 1223 | } |
| 1164 | |||
| 1165 | put_page(page2[0]); | ||
| 1166 | } | 1224 | } |
| 1167 | } | 1225 | } |
| 1168 | 1226 | ||
| 1169 | static struct rmap_item *get_next_rmap_item(struct mm_slot *mm_slot, | 1227 | static struct rmap_item *get_next_rmap_item(struct mm_slot *mm_slot, |
| 1170 | struct list_head *cur, | 1228 | struct rmap_item **rmap_list, |
| 1171 | unsigned long addr) | 1229 | unsigned long addr) |
| 1172 | { | 1230 | { |
| 1173 | struct rmap_item *rmap_item; | 1231 | struct rmap_item *rmap_item; |
| 1174 | 1232 | ||
| 1175 | while (cur != &mm_slot->rmap_list) { | 1233 | while (*rmap_list) { |
| 1176 | rmap_item = list_entry(cur, struct rmap_item, link); | 1234 | rmap_item = *rmap_list; |
| 1177 | if ((rmap_item->address & PAGE_MASK) == addr) { | 1235 | if ((rmap_item->address & PAGE_MASK) == addr) |
| 1178 | if (!in_stable_tree(rmap_item)) | ||
| 1179 | remove_rmap_item_from_tree(rmap_item); | ||
| 1180 | return rmap_item; | 1236 | return rmap_item; |
| 1181 | } | ||
| 1182 | if (rmap_item->address > addr) | 1237 | if (rmap_item->address > addr) |
| 1183 | break; | 1238 | break; |
| 1184 | cur = cur->next; | 1239 | *rmap_list = rmap_item->rmap_list; |
| 1185 | remove_rmap_item_from_tree(rmap_item); | 1240 | remove_rmap_item_from_tree(rmap_item); |
| 1186 | list_del(&rmap_item->link); | ||
| 1187 | free_rmap_item(rmap_item); | 1241 | free_rmap_item(rmap_item); |
| 1188 | } | 1242 | } |
| 1189 | 1243 | ||
| @@ -1192,7 +1246,8 @@ static struct rmap_item *get_next_rmap_item(struct mm_slot *mm_slot, | |||
| 1192 | /* It has already been zeroed */ | 1246 | /* It has already been zeroed */ |
| 1193 | rmap_item->mm = mm_slot->mm; | 1247 | rmap_item->mm = mm_slot->mm; |
| 1194 | rmap_item->address = addr; | 1248 | rmap_item->address = addr; |
| 1195 | list_add_tail(&rmap_item->link, cur); | 1249 | rmap_item->rmap_list = *rmap_list; |
| 1250 | *rmap_list = rmap_item; | ||
| 1196 | } | 1251 | } |
| 1197 | return rmap_item; | 1252 | return rmap_item; |
| 1198 | } | 1253 | } |
| @@ -1217,8 +1272,7 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page) | |||
| 1217 | spin_unlock(&ksm_mmlist_lock); | 1272 | spin_unlock(&ksm_mmlist_lock); |
| 1218 | next_mm: | 1273 | next_mm: |
| 1219 | ksm_scan.address = 0; | 1274 | ksm_scan.address = 0; |
| 1220 | ksm_scan.rmap_item = list_entry(&slot->rmap_list, | 1275 | ksm_scan.rmap_list = &slot->rmap_list; |
| 1221 | struct rmap_item, link); | ||
| 1222 | } | 1276 | } |
| 1223 | 1277 | ||
| 1224 | mm = slot->mm; | 1278 | mm = slot->mm; |
| @@ -1244,10 +1298,10 @@ next_mm: | |||
| 1244 | flush_anon_page(vma, *page, ksm_scan.address); | 1298 | flush_anon_page(vma, *page, ksm_scan.address); |
| 1245 | flush_dcache_page(*page); | 1299 | flush_dcache_page(*page); |
| 1246 | rmap_item = get_next_rmap_item(slot, | 1300 | rmap_item = get_next_rmap_item(slot, |
| 1247 | ksm_scan.rmap_item->link.next, | 1301 | ksm_scan.rmap_list, ksm_scan.address); |
| 1248 | ksm_scan.address); | ||
| 1249 | if (rmap_item) { | 1302 | if (rmap_item) { |
| 1250 | ksm_scan.rmap_item = rmap_item; | 1303 | ksm_scan.rmap_list = |
| 1304 | &rmap_item->rmap_list; | ||
| 1251 | ksm_scan.address += PAGE_SIZE; | 1305 | ksm_scan.address += PAGE_SIZE; |
| 1252 | } else | 1306 | } else |
| 1253 | put_page(*page); | 1307 | put_page(*page); |
| @@ -1263,14 +1317,13 @@ next_mm: | |||
| 1263 | 1317 | ||
| 1264 | if (ksm_test_exit(mm)) { | 1318 | if (ksm_test_exit(mm)) { |
| 1265 | ksm_scan.address = 0; | 1319 | ksm_scan.address = 0; |
| 1266 | ksm_scan.rmap_item = list_entry(&slot->rmap_list, | 1320 | ksm_scan.rmap_list = &slot->rmap_list; |
| 1267 | struct rmap_item, link); | ||
| 1268 | } | 1321 | } |
| 1269 | /* | 1322 | /* |
| 1270 | * Nuke all the rmap_items that are above this current rmap: | 1323 | * Nuke all the rmap_items that are above this current rmap: |
| 1271 | * because there were no VM_MERGEABLE vmas with such addresses. | 1324 | * because there were no VM_MERGEABLE vmas with such addresses. |
| 1272 | */ | 1325 | */ |
| 1273 | remove_trailing_rmap_items(slot, ksm_scan.rmap_item->link.next); | 1326 | remove_trailing_rmap_items(slot, ksm_scan.rmap_list); |
| 1274 | 1327 | ||
| 1275 | spin_lock(&ksm_mmlist_lock); | 1328 | spin_lock(&ksm_mmlist_lock); |
| 1276 | ksm_scan.mm_slot = list_entry(slot->mm_list.next, | 1329 | ksm_scan.mm_slot = list_entry(slot->mm_list.next, |
| @@ -1323,14 +1376,6 @@ static void ksm_do_scan(unsigned int scan_npages) | |||
| 1323 | return; | 1376 | return; |
| 1324 | if (!PageKsm(page) || !in_stable_tree(rmap_item)) | 1377 | if (!PageKsm(page) || !in_stable_tree(rmap_item)) |
| 1325 | cmp_and_merge_page(page, rmap_item); | 1378 | cmp_and_merge_page(page, rmap_item); |
| 1326 | else if (page_mapcount(page) == 1) { | ||
| 1327 | /* | ||
| 1328 | * Replace now-unshared ksm page by ordinary page. | ||
| 1329 | */ | ||
| 1330 | break_cow(rmap_item->mm, rmap_item->address); | ||
| 1331 | remove_rmap_item_from_tree(rmap_item); | ||
| 1332 | rmap_item->oldchecksum = calc_checksum(page); | ||
| 1333 | } | ||
| 1334 | put_page(page); | 1379 | put_page(page); |
| 1335 | } | 1380 | } |
| 1336 | } | 1381 | } |
| @@ -1375,7 +1420,7 @@ int ksm_madvise(struct vm_area_struct *vma, unsigned long start, | |||
| 1375 | if (*vm_flags & (VM_MERGEABLE | VM_SHARED | VM_MAYSHARE | | 1420 | if (*vm_flags & (VM_MERGEABLE | VM_SHARED | VM_MAYSHARE | |
| 1376 | VM_PFNMAP | VM_IO | VM_DONTEXPAND | | 1421 | VM_PFNMAP | VM_IO | VM_DONTEXPAND | |
| 1377 | VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE | | 1422 | VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE | |
| 1378 | VM_MIXEDMAP | VM_SAO)) | 1423 | VM_NONLINEAR | VM_MIXEDMAP | VM_SAO)) |
| 1379 | return 0; /* just ignore the advice */ | 1424 | return 0; /* just ignore the advice */ |
| 1380 | 1425 | ||
| 1381 | if (!test_bit(MMF_VM_MERGEABLE, &mm->flags)) { | 1426 | if (!test_bit(MMF_VM_MERGEABLE, &mm->flags)) { |
| @@ -1452,7 +1497,7 @@ void __ksm_exit(struct mm_struct *mm) | |||
| 1452 | spin_lock(&ksm_mmlist_lock); | 1497 | spin_lock(&ksm_mmlist_lock); |
| 1453 | mm_slot = get_mm_slot(mm); | 1498 | mm_slot = get_mm_slot(mm); |
| 1454 | if (mm_slot && ksm_scan.mm_slot != mm_slot) { | 1499 | if (mm_slot && ksm_scan.mm_slot != mm_slot) { |
| 1455 | if (list_empty(&mm_slot->rmap_list)) { | 1500 | if (!mm_slot->rmap_list) { |
| 1456 | hlist_del(&mm_slot->link); | 1501 | hlist_del(&mm_slot->link); |
| 1457 | list_del(&mm_slot->mm_list); | 1502 | list_del(&mm_slot->mm_list); |
| 1458 | easy_to_free = 1; | 1503 | easy_to_free = 1; |
| @@ -1473,6 +1518,249 @@ void __ksm_exit(struct mm_struct *mm) | |||
| 1473 | } | 1518 | } |
| 1474 | } | 1519 | } |
| 1475 | 1520 | ||
| 1521 | struct page *ksm_does_need_to_copy(struct page *page, | ||
| 1522 | struct vm_area_struct *vma, unsigned long address) | ||
| 1523 | { | ||
| 1524 | struct page *new_page; | ||
| 1525 | |||
| 1526 | unlock_page(page); /* any racers will COW it, not modify it */ | ||
| 1527 | |||
| 1528 | new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); | ||
| 1529 | if (new_page) { | ||
| 1530 | copy_user_highpage(new_page, page, address, vma); | ||
| 1531 | |||
| 1532 | SetPageDirty(new_page); | ||
| 1533 | __SetPageUptodate(new_page); | ||
| 1534 | SetPageSwapBacked(new_page); | ||
| 1535 | __set_page_locked(new_page); | ||
| 1536 | |||
| 1537 | if (page_evictable(new_page, vma)) | ||
| 1538 | lru_cache_add_lru(new_page, LRU_ACTIVE_ANON); | ||
| 1539 | else | ||
| 1540 | add_page_to_unevictable_list(new_page); | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | page_cache_release(page); | ||
| 1544 | return new_page; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | int page_referenced_ksm(struct page *page, struct mem_cgroup *memcg, | ||
| 1548 | unsigned long *vm_flags) | ||
| 1549 | { | ||
| 1550 | struct stable_node *stable_node; | ||
| 1551 | struct rmap_item *rmap_item; | ||
| 1552 | struct hlist_node *hlist; | ||
| 1553 | unsigned int mapcount = page_mapcount(page); | ||
| 1554 | int referenced = 0; | ||
| 1555 | int search_new_forks = 0; | ||
| 1556 | |||
| 1557 | VM_BUG_ON(!PageKsm(page)); | ||
| 1558 | VM_BUG_ON(!PageLocked(page)); | ||
| 1559 | |||
| 1560 | stable_node = page_stable_node(page); | ||
| 1561 | if (!stable_node) | ||
| 1562 | return 0; | ||
| 1563 | again: | ||
| 1564 | hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) { | ||
| 1565 | struct anon_vma *anon_vma = rmap_item->anon_vma; | ||
| 1566 | struct vm_area_struct *vma; | ||
| 1567 | |||
| 1568 | spin_lock(&anon_vma->lock); | ||
| 1569 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | ||
| 1570 | if (rmap_item->address < vma->vm_start || | ||
| 1571 | rmap_item->address >= vma->vm_end) | ||
| 1572 | continue; | ||
| 1573 | /* | ||
| 1574 | * Initially we examine only the vma which covers this | ||
| 1575 | * rmap_item; but later, if there is still work to do, | ||
| 1576 | * we examine covering vmas in other mms: in case they | ||
| 1577 | * were forked from the original since ksmd passed. | ||
| 1578 | */ | ||
| 1579 | if ((rmap_item->mm == vma->vm_mm) == search_new_forks) | ||
| 1580 | continue; | ||
| 1581 | |||
| 1582 | if (memcg && !mm_match_cgroup(vma->vm_mm, memcg)) | ||
| 1583 | continue; | ||
| 1584 | |||
| 1585 | referenced += page_referenced_one(page, vma, | ||
| 1586 | rmap_item->address, &mapcount, vm_flags); | ||
| 1587 | if (!search_new_forks || !mapcount) | ||
| 1588 | break; | ||
| 1589 | } | ||
| 1590 | spin_unlock(&anon_vma->lock); | ||
| 1591 | if (!mapcount) | ||
| 1592 | goto out; | ||
| 1593 | } | ||
| 1594 | if (!search_new_forks++) | ||
| 1595 | goto again; | ||
| 1596 | out: | ||
| 1597 | return referenced; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | int try_to_unmap_ksm(struct page *page, enum ttu_flags flags) | ||
| 1601 | { | ||
| 1602 | struct stable_node *stable_node; | ||
| 1603 | struct hlist_node *hlist; | ||
| 1604 | struct rmap_item *rmap_item; | ||
| 1605 | int ret = SWAP_AGAIN; | ||
| 1606 | int search_new_forks = 0; | ||
| 1607 | |||
| 1608 | VM_BUG_ON(!PageKsm(page)); | ||
| 1609 | VM_BUG_ON(!PageLocked(page)); | ||
| 1610 | |||
| 1611 | stable_node = page_stable_node(page); | ||
| 1612 | if (!stable_node) | ||
| 1613 | return SWAP_FAIL; | ||
| 1614 | again: | ||
| 1615 | hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) { | ||
| 1616 | struct anon_vma *anon_vma = rmap_item->anon_vma; | ||
| 1617 | struct vm_area_struct *vma; | ||
| 1618 | |||
| 1619 | spin_lock(&anon_vma->lock); | ||
| 1620 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | ||
| 1621 | if (rmap_item->address < vma->vm_start || | ||
| 1622 | rmap_item->address >= vma->vm_end) | ||
| 1623 | continue; | ||
| 1624 | /* | ||
| 1625 | * Initially we examine only the vma which covers this | ||
| 1626 | * rmap_item; but later, if there is still work to do, | ||
| 1627 | * we examine covering vmas in other mms: in case they | ||
| 1628 | * were forked from the original since ksmd passed. | ||
| 1629 | */ | ||
| 1630 | if ((rmap_item->mm == vma->vm_mm) == search_new_forks) | ||
| 1631 | continue; | ||
| 1632 | |||
| 1633 | ret = try_to_unmap_one(page, vma, | ||
| 1634 | rmap_item->address, flags); | ||
| 1635 | if (ret != SWAP_AGAIN || !page_mapped(page)) { | ||
| 1636 | spin_unlock(&anon_vma->lock); | ||
| 1637 | goto out; | ||
| 1638 | } | ||
| 1639 | } | ||
| 1640 | spin_unlock(&anon_vma->lock); | ||
| 1641 | } | ||
| 1642 | if (!search_new_forks++) | ||
| 1643 | goto again; | ||
| 1644 | out: | ||
| 1645 | return ret; | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | #ifdef CONFIG_MIGRATION | ||
| 1649 | int rmap_walk_ksm(struct page *page, int (*rmap_one)(struct page *, | ||
| 1650 | struct vm_area_struct *, unsigned long, void *), void *arg) | ||
| 1651 | { | ||
| 1652 | struct stable_node *stable_node; | ||
| 1653 | struct hlist_node *hlist; | ||
| 1654 | struct rmap_item *rmap_item; | ||
| 1655 | int ret = SWAP_AGAIN; | ||
| 1656 | int search_new_forks = 0; | ||
| 1657 | |||
| 1658 | VM_BUG_ON(!PageKsm(page)); | ||
| 1659 | VM_BUG_ON(!PageLocked(page)); | ||
| 1660 | |||
| 1661 | stable_node = page_stable_node(page); | ||
| 1662 | if (!stable_node) | ||
| 1663 | return ret; | ||
| 1664 | again: | ||
| 1665 | hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) { | ||
| 1666 | struct anon_vma *anon_vma = rmap_item->anon_vma; | ||
| 1667 | struct vm_area_struct *vma; | ||
| 1668 | |||
| 1669 | spin_lock(&anon_vma->lock); | ||
| 1670 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | ||
| 1671 | if (rmap_item->address < vma->vm_start || | ||
| 1672 | rmap_item->address >= vma->vm_end) | ||
| 1673 | continue; | ||
| 1674 | /* | ||
| 1675 | * Initially we examine only the vma which covers this | ||
| 1676 | * rmap_item; but later, if there is still work to do, | ||
| 1677 | * we examine covering vmas in other mms: in case they | ||
| 1678 | * were forked from the original since ksmd passed. | ||
| 1679 | */ | ||
| 1680 | if ((rmap_item->mm == vma->vm_mm) == search_new_forks) | ||
| 1681 | continue; | ||
| 1682 | |||
| 1683 | ret = rmap_one(page, vma, rmap_item->address, arg); | ||
| 1684 | if (ret != SWAP_AGAIN) { | ||
| 1685 | spin_unlock(&anon_vma->lock); | ||
| 1686 | goto out; | ||
| 1687 | } | ||
| 1688 | } | ||
| 1689 | spin_unlock(&anon_vma->lock); | ||
| 1690 | } | ||
| 1691 | if (!search_new_forks++) | ||
| 1692 | goto again; | ||
| 1693 | out: | ||
| 1694 | return ret; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | void ksm_migrate_page(struct page *newpage, struct page *oldpage) | ||
| 1698 | { | ||
| 1699 | struct stable_node *stable_node; | ||
| 1700 | |||
| 1701 | VM_BUG_ON(!PageLocked(oldpage)); | ||
| 1702 | VM_BUG_ON(!PageLocked(newpage)); | ||
| 1703 | VM_BUG_ON(newpage->mapping != oldpage->mapping); | ||
| 1704 | |||
| 1705 | stable_node = page_stable_node(newpage); | ||
| 1706 | if (stable_node) { | ||
| 1707 | VM_BUG_ON(stable_node->kpfn != page_to_pfn(oldpage)); | ||
| 1708 | stable_node->kpfn = page_to_pfn(newpage); | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | #endif /* CONFIG_MIGRATION */ | ||
| 1712 | |||
| 1713 | #ifdef CONFIG_MEMORY_HOTREMOVE | ||
| 1714 | static struct stable_node *ksm_check_stable_tree(unsigned long start_pfn, | ||
| 1715 | unsigned long end_pfn) | ||
| 1716 | { | ||
| 1717 | struct rb_node *node; | ||
| 1718 | |||
| 1719 | for (node = rb_first(&root_stable_tree); node; node = rb_next(node)) { | ||
| 1720 | struct stable_node *stable_node; | ||
| 1721 | |||
| 1722 | stable_node = rb_entry(node, struct stable_node, node); | ||
| 1723 | if (stable_node->kpfn >= start_pfn && | ||
| 1724 | stable_node->kpfn < end_pfn) | ||
| 1725 | return stable_node; | ||
| 1726 | } | ||
| 1727 | return NULL; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | static int ksm_memory_callback(struct notifier_block *self, | ||
| 1731 | unsigned long action, void *arg) | ||
| 1732 | { | ||
| 1733 | struct memory_notify *mn = arg; | ||
| 1734 | struct stable_node *stable_node; | ||
| 1735 | |||
| 1736 | switch (action) { | ||
| 1737 | case MEM_GOING_OFFLINE: | ||
| 1738 | /* | ||
| 1739 | * Keep it very simple for now: just lock out ksmd and | ||
| 1740 | * MADV_UNMERGEABLE while any memory is going offline. | ||
| 1741 | */ | ||
| 1742 | mutex_lock(&ksm_thread_mutex); | ||
| 1743 | break; | ||
| 1744 | |||
| 1745 | case MEM_OFFLINE: | ||
| 1746 | /* | ||
| 1747 | * Most of the work is done by page migration; but there might | ||
| 1748 | * be a few stable_nodes left over, still pointing to struct | ||
| 1749 | * pages which have been offlined: prune those from the tree. | ||
| 1750 | */ | ||
| 1751 | while ((stable_node = ksm_check_stable_tree(mn->start_pfn, | ||
| 1752 | mn->start_pfn + mn->nr_pages)) != NULL) | ||
| 1753 | remove_node_from_stable_tree(stable_node); | ||
| 1754 | /* fallthrough */ | ||
| 1755 | |||
| 1756 | case MEM_CANCEL_OFFLINE: | ||
| 1757 | mutex_unlock(&ksm_thread_mutex); | ||
| 1758 | break; | ||
| 1759 | } | ||
| 1760 | return NOTIFY_OK; | ||
| 1761 | } | ||
| 1762 | #endif /* CONFIG_MEMORY_HOTREMOVE */ | ||
| 1763 | |||
| 1476 | #ifdef CONFIG_SYSFS | 1764 | #ifdef CONFIG_SYSFS |
| 1477 | /* | 1765 | /* |
| 1478 | * This all compiles without CONFIG_SYSFS, but is a waste of space. | 1766 | * This all compiles without CONFIG_SYSFS, but is a waste of space. |
| @@ -1551,8 +1839,8 @@ static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
| 1551 | /* | 1839 | /* |
| 1552 | * KSM_RUN_MERGE sets ksmd running, and 0 stops it running. | 1840 | * KSM_RUN_MERGE sets ksmd running, and 0 stops it running. |
| 1553 | * KSM_RUN_UNMERGE stops it running and unmerges all rmap_items, | 1841 | * KSM_RUN_UNMERGE stops it running and unmerges all rmap_items, |
| 1554 | * breaking COW to free the unswappable pages_shared (but leaves | 1842 | * breaking COW to free the pages_shared (but leaves mm_slots |
| 1555 | * mm_slots on the list for when ksmd may be set running again). | 1843 | * on the list for when ksmd may be set running again). |
| 1556 | */ | 1844 | */ |
| 1557 | 1845 | ||
| 1558 | mutex_lock(&ksm_thread_mutex); | 1846 | mutex_lock(&ksm_thread_mutex); |
| @@ -1577,29 +1865,6 @@ static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
| 1577 | } | 1865 | } |
| 1578 | KSM_ATTR(run); | 1866 | KSM_ATTR(run); |
| 1579 | 1867 | ||
| 1580 | static ssize_t max_kernel_pages_store(struct kobject *kobj, | ||
| 1581 | struct kobj_attribute *attr, | ||
| 1582 | const char *buf, size_t count) | ||
| 1583 | { | ||
| 1584 | int err; | ||
| 1585 | unsigned long nr_pages; | ||
| 1586 | |||
| 1587 | err = strict_strtoul(buf, 10, &nr_pages); | ||
| 1588 | if (err) | ||
| 1589 | return -EINVAL; | ||
| 1590 | |||
| 1591 | ksm_max_kernel_pages = nr_pages; | ||
| 1592 | |||
| 1593 | return count; | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | static ssize_t max_kernel_pages_show(struct kobject *kobj, | ||
| 1597 | struct kobj_attribute *attr, char *buf) | ||
| 1598 | { | ||
| 1599 | return sprintf(buf, "%lu\n", ksm_max_kernel_pages); | ||
| 1600 | } | ||
| 1601 | KSM_ATTR(max_kernel_pages); | ||
| 1602 | |||
| 1603 | static ssize_t pages_shared_show(struct kobject *kobj, | 1868 | static ssize_t pages_shared_show(struct kobject *kobj, |
| 1604 | struct kobj_attribute *attr, char *buf) | 1869 | struct kobj_attribute *attr, char *buf) |
| 1605 | { | 1870 | { |
| @@ -1649,7 +1914,6 @@ static struct attribute *ksm_attrs[] = { | |||
| 1649 | &sleep_millisecs_attr.attr, | 1914 | &sleep_millisecs_attr.attr, |
| 1650 | &pages_to_scan_attr.attr, | 1915 | &pages_to_scan_attr.attr, |
| 1651 | &run_attr.attr, | 1916 | &run_attr.attr, |
| 1652 | &max_kernel_pages_attr.attr, | ||
| 1653 | &pages_shared_attr.attr, | 1917 | &pages_shared_attr.attr, |
| 1654 | &pages_sharing_attr.attr, | 1918 | &pages_sharing_attr.attr, |
| 1655 | &pages_unshared_attr.attr, | 1919 | &pages_unshared_attr.attr, |
| @@ -1669,8 +1933,6 @@ static int __init ksm_init(void) | |||
| 1669 | struct task_struct *ksm_thread; | 1933 | struct task_struct *ksm_thread; |
| 1670 | int err; | 1934 | int err; |
| 1671 | 1935 | ||
| 1672 | ksm_max_kernel_pages = totalram_pages / 4; | ||
| 1673 | |||
| 1674 | err = ksm_slab_init(); | 1936 | err = ksm_slab_init(); |
| 1675 | if (err) | 1937 | if (err) |
| 1676 | goto out; | 1938 | goto out; |
| @@ -1698,6 +1960,13 @@ static int __init ksm_init(void) | |||
| 1698 | 1960 | ||
| 1699 | #endif /* CONFIG_SYSFS */ | 1961 | #endif /* CONFIG_SYSFS */ |
| 1700 | 1962 | ||
| 1963 | #ifdef CONFIG_MEMORY_HOTREMOVE | ||
| 1964 | /* | ||
| 1965 | * Choose a high priority since the callback takes ksm_thread_mutex: | ||
| 1966 | * later callbacks could only be taking locks which nest within that. | ||
| 1967 | */ | ||
| 1968 | hotplug_memory_notifier(ksm_memory_callback, 100); | ||
| 1969 | #endif | ||
| 1701 | return 0; | 1970 | return 0; |
| 1702 | 1971 | ||
| 1703 | out_free2: | 1972 | out_free2: |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index c31a310aa146..e0c2066495e3 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -1737,11 +1737,12 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm, | |||
| 1737 | goto charge_cur_mm; | 1737 | goto charge_cur_mm; |
| 1738 | /* | 1738 | /* |
| 1739 | * A racing thread's fault, or swapoff, may have already updated | 1739 | * A racing thread's fault, or swapoff, may have already updated |
| 1740 | * the pte, and even removed page from swap cache: return success | 1740 | * the pte, and even removed page from swap cache: in those cases |
| 1741 | * to go on to do_swap_page()'s pte_same() test, which should fail. | 1741 | * do_swap_page()'s pte_same() test will fail; but there's also a |
| 1742 | * KSM case which does need to charge the page. | ||
| 1742 | */ | 1743 | */ |
| 1743 | if (!PageSwapCache(page)) | 1744 | if (!PageSwapCache(page)) |
| 1744 | return 0; | 1745 | goto charge_cur_mm; |
| 1745 | mem = try_get_mem_cgroup_from_swapcache(page); | 1746 | mem = try_get_mem_cgroup_from_swapcache(page); |
| 1746 | if (!mem) | 1747 | if (!mem) |
| 1747 | goto charge_cur_mm; | 1748 | goto charge_cur_mm; |
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 1ac49fef95ab..50d4f8d7024a 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -582,10 +582,8 @@ static struct page_state { | |||
| 582 | { unevict|dirty, unevict|dirty, "unevictable LRU", me_pagecache_dirty}, | 582 | { unevict|dirty, unevict|dirty, "unevictable LRU", me_pagecache_dirty}, |
| 583 | { unevict, unevict, "unevictable LRU", me_pagecache_clean}, | 583 | { unevict, unevict, "unevictable LRU", me_pagecache_clean}, |
| 584 | 584 | ||
| 585 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | ||
| 586 | { mlock|dirty, mlock|dirty, "mlocked LRU", me_pagecache_dirty }, | 585 | { mlock|dirty, mlock|dirty, "mlocked LRU", me_pagecache_dirty }, |
| 587 | { mlock, mlock, "mlocked LRU", me_pagecache_clean }, | 586 | { mlock, mlock, "mlocked LRU", me_pagecache_clean }, |
| 588 | #endif | ||
| 589 | 587 | ||
| 590 | { lru|dirty, lru|dirty, "LRU", me_pagecache_dirty }, | 588 | { lru|dirty, lru|dirty, "LRU", me_pagecache_dirty }, |
| 591 | { lru|dirty, lru, "clean LRU", me_pagecache_clean }, | 589 | { lru|dirty, lru, "clean LRU", me_pagecache_clean }, |
diff --git a/mm/memory.c b/mm/memory.c index 6ab19dd4a199..a54b2c498444 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -572,7 +572,7 @@ out: | |||
| 572 | * covered by this vma. | 572 | * covered by this vma. |
| 573 | */ | 573 | */ |
| 574 | 574 | ||
| 575 | static inline void | 575 | static inline unsigned long |
| 576 | copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | 576 | copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, |
| 577 | pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma, | 577 | pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma, |
| 578 | unsigned long addr, int *rss) | 578 | unsigned long addr, int *rss) |
| @@ -586,7 +586,9 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 586 | if (!pte_file(pte)) { | 586 | if (!pte_file(pte)) { |
| 587 | swp_entry_t entry = pte_to_swp_entry(pte); | 587 | swp_entry_t entry = pte_to_swp_entry(pte); |
| 588 | 588 | ||
| 589 | swap_duplicate(entry); | 589 | if (swap_duplicate(entry) < 0) |
| 590 | return entry.val; | ||
| 591 | |||
| 590 | /* make sure dst_mm is on swapoff's mmlist. */ | 592 | /* make sure dst_mm is on swapoff's mmlist. */ |
| 591 | if (unlikely(list_empty(&dst_mm->mmlist))) { | 593 | if (unlikely(list_empty(&dst_mm->mmlist))) { |
| 592 | spin_lock(&mmlist_lock); | 594 | spin_lock(&mmlist_lock); |
| @@ -635,6 +637,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 635 | 637 | ||
| 636 | out_set_pte: | 638 | out_set_pte: |
| 637 | set_pte_at(dst_mm, addr, dst_pte, pte); | 639 | set_pte_at(dst_mm, addr, dst_pte, pte); |
| 640 | return 0; | ||
| 638 | } | 641 | } |
| 639 | 642 | ||
| 640 | static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | 643 | static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, |
| @@ -646,6 +649,7 @@ static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
| 646 | spinlock_t *src_ptl, *dst_ptl; | 649 | spinlock_t *src_ptl, *dst_ptl; |
| 647 | int progress = 0; | 650 | int progress = 0; |
| 648 | int rss[2]; | 651 | int rss[2]; |
| 652 | swp_entry_t entry = (swp_entry_t){0}; | ||
| 649 | 653 | ||
| 650 | again: | 654 | again: |
| 651 | rss[1] = rss[0] = 0; | 655 | rss[1] = rss[0] = 0; |
| @@ -674,7 +678,10 @@ again: | |||
| 674 | progress++; | 678 | progress++; |
| 675 | continue; | 679 | continue; |
| 676 | } | 680 | } |
| 677 | copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, vma, addr, rss); | 681 | entry.val = copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, |
| 682 | vma, addr, rss); | ||
| 683 | if (entry.val) | ||
| 684 | break; | ||
| 678 | progress += 8; | 685 | progress += 8; |
| 679 | } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); | 686 | } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); |
| 680 | 687 | ||
| @@ -684,6 +691,12 @@ again: | |||
| 684 | add_mm_rss(dst_mm, rss[0], rss[1]); | 691 | add_mm_rss(dst_mm, rss[0], rss[1]); |
| 685 | pte_unmap_unlock(orig_dst_pte, dst_ptl); | 692 | pte_unmap_unlock(orig_dst_pte, dst_ptl); |
| 686 | cond_resched(); | 693 | cond_resched(); |
| 694 | |||
| 695 | if (entry.val) { | ||
| 696 | if (add_swap_count_continuation(entry, GFP_KERNEL) < 0) | ||
| 697 | return -ENOMEM; | ||
| 698 | progress = 0; | ||
| 699 | } | ||
| 687 | if (addr != end) | 700 | if (addr != end) |
| 688 | goto again; | 701 | goto again; |
| 689 | return 0; | 702 | return 0; |
| @@ -2514,7 +2527,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2514 | ret = VM_FAULT_HWPOISON; | 2527 | ret = VM_FAULT_HWPOISON; |
| 2515 | } else { | 2528 | } else { |
| 2516 | print_bad_pte(vma, address, orig_pte, NULL); | 2529 | print_bad_pte(vma, address, orig_pte, NULL); |
| 2517 | ret = VM_FAULT_OOM; | 2530 | ret = VM_FAULT_SIGBUS; |
| 2518 | } | 2531 | } |
| 2519 | goto out; | 2532 | goto out; |
| 2520 | } | 2533 | } |
| @@ -2548,6 +2561,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2548 | lock_page(page); | 2561 | lock_page(page); |
| 2549 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | 2562 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); |
| 2550 | 2563 | ||
| 2564 | page = ksm_might_need_to_copy(page, vma, address); | ||
| 2565 | if (!page) { | ||
| 2566 | ret = VM_FAULT_OOM; | ||
| 2567 | goto out; | ||
| 2568 | } | ||
| 2569 | |||
| 2551 | if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { | 2570 | if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { |
| 2552 | ret = VM_FAULT_OOM; | 2571 | ret = VM_FAULT_OOM; |
| 2553 | goto out_page; | 2572 | goto out_page; |
| @@ -2910,7 +2929,7 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2910 | * Page table corrupted: show pte and kill process. | 2929 | * Page table corrupted: show pte and kill process. |
| 2911 | */ | 2930 | */ |
| 2912 | print_bad_pte(vma, address, orig_pte, NULL); | 2931 | print_bad_pte(vma, address, orig_pte, NULL); |
| 2913 | return VM_FAULT_OOM; | 2932 | return VM_FAULT_SIGBUS; |
| 2914 | } | 2933 | } |
| 2915 | 2934 | ||
| 2916 | pgoff = pte_to_pgoff(orig_pte); | 2935 | pgoff = pte_to_pgoff(orig_pte); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 2047465cd27c..030ce8a5bb0e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/page-isolation.h> | 27 | #include <linux/page-isolation.h> |
| 28 | #include <linux/pfn.h> | 28 | #include <linux/pfn.h> |
| 29 | #include <linux/suspend.h> | 29 | #include <linux/suspend.h> |
| 30 | #include <linux/mm_inline.h> | ||
| 30 | 31 | ||
| 31 | #include <asm/tlbflush.h> | 32 | #include <asm/tlbflush.h> |
| 32 | 33 | ||
| @@ -71,7 +72,9 @@ static void get_page_bootmem(unsigned long info, struct page *page, int type) | |||
| 71 | atomic_inc(&page->_count); | 72 | atomic_inc(&page->_count); |
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | void put_page_bootmem(struct page *page) | 75 | /* reference to __meminit __free_pages_bootmem is valid |
| 76 | * so use __ref to tell modpost not to generate a warning */ | ||
| 77 | void __ref put_page_bootmem(struct page *page) | ||
| 75 | { | 78 | { |
| 76 | int type; | 79 | int type; |
| 77 | 80 | ||
| @@ -672,6 +675,9 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) | |||
| 672 | if (!ret) { /* Success */ | 675 | if (!ret) { /* Success */ |
| 673 | list_add_tail(&page->lru, &source); | 676 | list_add_tail(&page->lru, &source); |
| 674 | move_pages--; | 677 | move_pages--; |
| 678 | inc_zone_page_state(page, NR_ISOLATED_ANON + | ||
| 679 | page_is_file_cache(page)); | ||
| 680 | |||
| 675 | } else { | 681 | } else { |
| 676 | /* Becasue we don't have big zone->lock. we should | 682 | /* Becasue we don't have big zone->lock. we should |
| 677 | check this again here. */ | 683 | check this again here. */ |
| @@ -694,7 +700,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) | |||
| 694 | if (list_empty(&source)) | 700 | if (list_empty(&source)) |
| 695 | goto out; | 701 | goto out; |
| 696 | /* this function returns # of failed pages */ | 702 | /* this function returns # of failed pages */ |
| 697 | ret = migrate_pages(&source, hotremove_migrate_alloc, 0); | 703 | ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1); |
| 698 | 704 | ||
| 699 | out: | 705 | out: |
| 700 | return ret; | 706 | return ret; |
| @@ -747,7 +753,7 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn) | |||
| 747 | return offlined; | 753 | return offlined; |
| 748 | } | 754 | } |
| 749 | 755 | ||
| 750 | int offline_pages(unsigned long start_pfn, | 756 | static int offline_pages(unsigned long start_pfn, |
| 751 | unsigned long end_pfn, unsigned long timeout) | 757 | unsigned long end_pfn, unsigned long timeout) |
| 752 | { | 758 | { |
| 753 | unsigned long pfn, nr_pages, expire; | 759 | unsigned long pfn, nr_pages, expire; |
| @@ -849,6 +855,10 @@ repeat: | |||
| 849 | 855 | ||
| 850 | setup_per_zone_wmarks(); | 856 | setup_per_zone_wmarks(); |
| 851 | calculate_zone_inactive_ratio(zone); | 857 | calculate_zone_inactive_ratio(zone); |
| 858 | if (!node_present_pages(node)) { | ||
| 859 | node_clear_state(node, N_HIGH_MEMORY); | ||
| 860 | kswapd_stop(node); | ||
| 861 | } | ||
| 852 | 862 | ||
| 853 | vm_total_pages = nr_free_pagecache_pages(); | 863 | vm_total_pages = nr_free_pagecache_pages(); |
| 854 | writeback_set_ratelimit(); | 864 | writeback_set_ratelimit(); |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 4545d5944243..290fb5bf0440 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
| @@ -85,10 +85,12 @@ | |||
| 85 | #include <linux/seq_file.h> | 85 | #include <linux/seq_file.h> |
| 86 | #include <linux/proc_fs.h> | 86 | #include <linux/proc_fs.h> |
| 87 | #include <linux/migrate.h> | 87 | #include <linux/migrate.h> |
| 88 | #include <linux/ksm.h> | ||
| 88 | #include <linux/rmap.h> | 89 | #include <linux/rmap.h> |
| 89 | #include <linux/security.h> | 90 | #include <linux/security.h> |
| 90 | #include <linux/syscalls.h> | 91 | #include <linux/syscalls.h> |
| 91 | #include <linux/ctype.h> | 92 | #include <linux/ctype.h> |
| 93 | #include <linux/mm_inline.h> | ||
| 92 | 94 | ||
| 93 | #include <asm/tlbflush.h> | 95 | #include <asm/tlbflush.h> |
| 94 | #include <asm/uaccess.h> | 96 | #include <asm/uaccess.h> |
| @@ -412,17 +414,11 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, | |||
| 412 | if (!page) | 414 | if (!page) |
| 413 | continue; | 415 | continue; |
| 414 | /* | 416 | /* |
| 415 | * The check for PageReserved here is important to avoid | 417 | * vm_normal_page() filters out zero pages, but there might |
| 416 | * handling zero pages and other pages that may have been | 418 | * still be PageReserved pages to skip, perhaps in a VDSO. |
| 417 | * marked special by the system. | 419 | * And we cannot move PageKsm pages sensibly or safely yet. |
| 418 | * | ||
| 419 | * If the PageReserved would not be checked here then f.e. | ||
| 420 | * the location of the zero page could have an influence | ||
| 421 | * on MPOL_MF_STRICT, zero pages would be counted for | ||
| 422 | * the per node stats, and there would be useless attempts | ||
| 423 | * to put zero pages on the migration list. | ||
| 424 | */ | 420 | */ |
| 425 | if (PageReserved(page)) | 421 | if (PageReserved(page) || PageKsm(page)) |
| 426 | continue; | 422 | continue; |
| 427 | nid = page_to_nid(page); | 423 | nid = page_to_nid(page); |
| 428 | if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT)) | 424 | if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT)) |
| @@ -809,6 +805,8 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist, | |||
| 809 | if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) { | 805 | if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) { |
| 810 | if (!isolate_lru_page(page)) { | 806 | if (!isolate_lru_page(page)) { |
| 811 | list_add_tail(&page->lru, pagelist); | 807 | list_add_tail(&page->lru, pagelist); |
| 808 | inc_zone_page_state(page, NR_ISOLATED_ANON + | ||
| 809 | page_is_file_cache(page)); | ||
| 812 | } | 810 | } |
| 813 | } | 811 | } |
| 814 | } | 812 | } |
| @@ -836,7 +834,7 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest, | |||
| 836 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); | 834 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); |
| 837 | 835 | ||
| 838 | if (!list_empty(&pagelist)) | 836 | if (!list_empty(&pagelist)) |
| 839 | err = migrate_pages(&pagelist, new_node_page, dest); | 837 | err = migrate_pages(&pagelist, new_node_page, dest, 0); |
| 840 | 838 | ||
| 841 | return err; | 839 | return err; |
| 842 | } | 840 | } |
| @@ -1053,7 +1051,7 @@ static long do_mbind(unsigned long start, unsigned long len, | |||
| 1053 | 1051 | ||
| 1054 | if (!list_empty(&pagelist)) | 1052 | if (!list_empty(&pagelist)) |
| 1055 | nr_failed = migrate_pages(&pagelist, new_vma_page, | 1053 | nr_failed = migrate_pages(&pagelist, new_vma_page, |
| 1056 | (unsigned long)vma); | 1054 | (unsigned long)vma, 0); |
| 1057 | 1055 | ||
| 1058 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) | 1056 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) |
| 1059 | err = -EIO; | 1057 | err = -EIO; |
| @@ -1565,6 +1563,53 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, | |||
| 1565 | } | 1563 | } |
| 1566 | return zl; | 1564 | return zl; |
| 1567 | } | 1565 | } |
| 1566 | |||
| 1567 | /* | ||
| 1568 | * init_nodemask_of_mempolicy | ||
| 1569 | * | ||
| 1570 | * If the current task's mempolicy is "default" [NULL], return 'false' | ||
| 1571 | * to indicate default policy. Otherwise, extract the policy nodemask | ||
| 1572 | * for 'bind' or 'interleave' policy into the argument nodemask, or | ||
| 1573 | * initialize the argument nodemask to contain the single node for | ||
| 1574 | * 'preferred' or 'local' policy and return 'true' to indicate presence | ||
| 1575 | * of non-default mempolicy. | ||
| 1576 | * | ||
| 1577 | * We don't bother with reference counting the mempolicy [mpol_get/put] | ||
| 1578 | * because the current task is examining it's own mempolicy and a task's | ||
| 1579 | * mempolicy is only ever changed by the task itself. | ||
| 1580 | * | ||
| 1581 | * N.B., it is the caller's responsibility to free a returned nodemask. | ||
| 1582 | */ | ||
| 1583 | bool init_nodemask_of_mempolicy(nodemask_t *mask) | ||
| 1584 | { | ||
| 1585 | struct mempolicy *mempolicy; | ||
| 1586 | int nid; | ||
| 1587 | |||
| 1588 | if (!(mask && current->mempolicy)) | ||
| 1589 | return false; | ||
| 1590 | |||
| 1591 | mempolicy = current->mempolicy; | ||
| 1592 | switch (mempolicy->mode) { | ||
| 1593 | case MPOL_PREFERRED: | ||
| 1594 | if (mempolicy->flags & MPOL_F_LOCAL) | ||
| 1595 | nid = numa_node_id(); | ||
| 1596 | else | ||
| 1597 | nid = mempolicy->v.preferred_node; | ||
| 1598 | init_nodemask_of_node(mask, nid); | ||
| 1599 | break; | ||
| 1600 | |||
| 1601 | case MPOL_BIND: | ||
| 1602 | /* Fall through */ | ||
| 1603 | case MPOL_INTERLEAVE: | ||
| 1604 | *mask = mempolicy->v.nodes; | ||
| 1605 | break; | ||
| 1606 | |||
| 1607 | default: | ||
| 1608 | BUG(); | ||
| 1609 | } | ||
| 1610 | |||
| 1611 | return true; | ||
| 1612 | } | ||
| 1568 | #endif | 1613 | #endif |
| 1569 | 1614 | ||
| 1570 | /* Allocate a page in interleaved policy. | 1615 | /* Allocate a page in interleaved policy. |
diff --git a/mm/migrate.c b/mm/migrate.c index 0bc640fd68fa..efddbf0926b2 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/mm_inline.h> | 21 | #include <linux/mm_inline.h> |
| 22 | #include <linux/nsproxy.h> | 22 | #include <linux/nsproxy.h> |
| 23 | #include <linux/pagevec.h> | 23 | #include <linux/pagevec.h> |
| 24 | #include <linux/ksm.h> | ||
| 24 | #include <linux/rmap.h> | 25 | #include <linux/rmap.h> |
| 25 | #include <linux/topology.h> | 26 | #include <linux/topology.h> |
| 26 | #include <linux/cpu.h> | 27 | #include <linux/cpu.h> |
| @@ -78,8 +79,8 @@ int putback_lru_pages(struct list_head *l) | |||
| 78 | /* | 79 | /* |
| 79 | * Restore a potential migration pte to a working pte entry | 80 | * Restore a potential migration pte to a working pte entry |
| 80 | */ | 81 | */ |
| 81 | static void remove_migration_pte(struct vm_area_struct *vma, | 82 | static int remove_migration_pte(struct page *new, struct vm_area_struct *vma, |
| 82 | struct page *old, struct page *new) | 83 | unsigned long addr, void *old) |
| 83 | { | 84 | { |
| 84 | struct mm_struct *mm = vma->vm_mm; | 85 | struct mm_struct *mm = vma->vm_mm; |
| 85 | swp_entry_t entry; | 86 | swp_entry_t entry; |
| @@ -88,40 +89,37 @@ static void remove_migration_pte(struct vm_area_struct *vma, | |||
| 88 | pmd_t *pmd; | 89 | pmd_t *pmd; |
| 89 | pte_t *ptep, pte; | 90 | pte_t *ptep, pte; |
| 90 | spinlock_t *ptl; | 91 | spinlock_t *ptl; |
| 91 | unsigned long addr = page_address_in_vma(new, vma); | ||
| 92 | |||
| 93 | if (addr == -EFAULT) | ||
| 94 | return; | ||
| 95 | 92 | ||
| 96 | pgd = pgd_offset(mm, addr); | 93 | pgd = pgd_offset(mm, addr); |
| 97 | if (!pgd_present(*pgd)) | 94 | if (!pgd_present(*pgd)) |
| 98 | return; | 95 | goto out; |
| 99 | 96 | ||
| 100 | pud = pud_offset(pgd, addr); | 97 | pud = pud_offset(pgd, addr); |
| 101 | if (!pud_present(*pud)) | 98 | if (!pud_present(*pud)) |
| 102 | return; | 99 | goto out; |
| 103 | 100 | ||
| 104 | pmd = pmd_offset(pud, addr); | 101 | pmd = pmd_offset(pud, addr); |
| 105 | if (!pmd_present(*pmd)) | 102 | if (!pmd_present(*pmd)) |
| 106 | return; | 103 | goto out; |
| 107 | 104 | ||
| 108 | ptep = pte_offset_map(pmd, addr); | 105 | ptep = pte_offset_map(pmd, addr); |
| 109 | 106 | ||
| 110 | if (!is_swap_pte(*ptep)) { | 107 | if (!is_swap_pte(*ptep)) { |
| 111 | pte_unmap(ptep); | 108 | pte_unmap(ptep); |
| 112 | return; | 109 | goto out; |
| 113 | } | 110 | } |
| 114 | 111 | ||
| 115 | ptl = pte_lockptr(mm, pmd); | 112 | ptl = pte_lockptr(mm, pmd); |
| 116 | spin_lock(ptl); | 113 | spin_lock(ptl); |
| 117 | pte = *ptep; | 114 | pte = *ptep; |
| 118 | if (!is_swap_pte(pte)) | 115 | if (!is_swap_pte(pte)) |
| 119 | goto out; | 116 | goto unlock; |
| 120 | 117 | ||
| 121 | entry = pte_to_swp_entry(pte); | 118 | entry = pte_to_swp_entry(pte); |
| 122 | 119 | ||
| 123 | if (!is_migration_entry(entry) || migration_entry_to_page(entry) != old) | 120 | if (!is_migration_entry(entry) || |
| 124 | goto out; | 121 | migration_entry_to_page(entry) != old) |
| 122 | goto unlock; | ||
| 125 | 123 | ||
| 126 | get_page(new); | 124 | get_page(new); |
| 127 | pte = pte_mkold(mk_pte(new, vma->vm_page_prot)); | 125 | pte = pte_mkold(mk_pte(new, vma->vm_page_prot)); |
| @@ -137,58 +135,10 @@ static void remove_migration_pte(struct vm_area_struct *vma, | |||
| 137 | 135 | ||
| 138 | /* No need to invalidate - it was non-present before */ | 136 | /* No need to invalidate - it was non-present before */ |
| 139 | update_mmu_cache(vma, addr, pte); | 137 | update_mmu_cache(vma, addr, pte); |
| 140 | 138 | unlock: | |
| 141 | out: | ||
| 142 | pte_unmap_unlock(ptep, ptl); | 139 | pte_unmap_unlock(ptep, ptl); |
| 143 | } | 140 | out: |
| 144 | 141 | return SWAP_AGAIN; | |
| 145 | /* | ||
| 146 | * Note that remove_file_migration_ptes will only work on regular mappings, | ||
| 147 | * Nonlinear mappings do not use migration entries. | ||
| 148 | */ | ||
| 149 | static void remove_file_migration_ptes(struct page *old, struct page *new) | ||
| 150 | { | ||
| 151 | struct vm_area_struct *vma; | ||
| 152 | struct address_space *mapping = new->mapping; | ||
| 153 | struct prio_tree_iter iter; | ||
| 154 | pgoff_t pgoff = new->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | ||
| 155 | |||
| 156 | if (!mapping) | ||
| 157 | return; | ||
| 158 | |||
| 159 | spin_lock(&mapping->i_mmap_lock); | ||
| 160 | |||
| 161 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) | ||
| 162 | remove_migration_pte(vma, old, new); | ||
| 163 | |||
| 164 | spin_unlock(&mapping->i_mmap_lock); | ||
| 165 | } | ||
| 166 | |||
| 167 | /* | ||
| 168 | * Must hold mmap_sem lock on at least one of the vmas containing | ||
| 169 | * the page so that the anon_vma cannot vanish. | ||
| 170 | */ | ||
| 171 | static void remove_anon_migration_ptes(struct page *old, struct page *new) | ||
| 172 | { | ||
| 173 | struct anon_vma *anon_vma; | ||
| 174 | struct vm_area_struct *vma; | ||
| 175 | unsigned long mapping; | ||
| 176 | |||
| 177 | mapping = (unsigned long)new->mapping; | ||
| 178 | |||
| 179 | if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0) | ||
| 180 | return; | ||
| 181 | |||
| 182 | /* | ||
| 183 | * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. | ||
| 184 | */ | ||
| 185 | anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); | ||
| 186 | spin_lock(&anon_vma->lock); | ||
| 187 | |||
| 188 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) | ||
| 189 | remove_migration_pte(vma, old, new); | ||
| 190 | |||
| 191 | spin_unlock(&anon_vma->lock); | ||
| 192 | } | 142 | } |
| 193 | 143 | ||
| 194 | /* | 144 | /* |
| @@ -197,10 +147,7 @@ static void remove_anon_migration_ptes(struct page *old, struct page *new) | |||
| 197 | */ | 147 | */ |
| 198 | static void remove_migration_ptes(struct page *old, struct page *new) | 148 | static void remove_migration_ptes(struct page *old, struct page *new) |
| 199 | { | 149 | { |
| 200 | if (PageAnon(new)) | 150 | rmap_walk(new, remove_migration_pte, old); |
| 201 | remove_anon_migration_ptes(old, new); | ||
| 202 | else | ||
| 203 | remove_file_migration_ptes(old, new); | ||
| 204 | } | 151 | } |
| 205 | 152 | ||
| 206 | /* | 153 | /* |
| @@ -341,8 +288,8 @@ static void migrate_page_copy(struct page *newpage, struct page *page) | |||
| 341 | if (TestClearPageActive(page)) { | 288 | if (TestClearPageActive(page)) { |
| 342 | VM_BUG_ON(PageUnevictable(page)); | 289 | VM_BUG_ON(PageUnevictable(page)); |
| 343 | SetPageActive(newpage); | 290 | SetPageActive(newpage); |
| 344 | } else | 291 | } else if (TestClearPageUnevictable(page)) |
| 345 | unevictable_migrate_page(newpage, page); | 292 | SetPageUnevictable(newpage); |
| 346 | if (PageChecked(page)) | 293 | if (PageChecked(page)) |
| 347 | SetPageChecked(newpage); | 294 | SetPageChecked(newpage); |
| 348 | if (PageMappedToDisk(page)) | 295 | if (PageMappedToDisk(page)) |
| @@ -361,6 +308,7 @@ static void migrate_page_copy(struct page *newpage, struct page *page) | |||
| 361 | } | 308 | } |
| 362 | 309 | ||
| 363 | mlock_migrate_page(newpage, page); | 310 | mlock_migrate_page(newpage, page); |
| 311 | ksm_migrate_page(newpage, page); | ||
| 364 | 312 | ||
| 365 | ClearPageSwapCache(page); | 313 | ClearPageSwapCache(page); |
| 366 | ClearPagePrivate(page); | 314 | ClearPagePrivate(page); |
| @@ -580,9 +528,9 @@ static int move_to_new_page(struct page *newpage, struct page *page) | |||
| 580 | else | 528 | else |
| 581 | rc = fallback_migrate_page(mapping, newpage, page); | 529 | rc = fallback_migrate_page(mapping, newpage, page); |
| 582 | 530 | ||
| 583 | if (!rc) { | 531 | if (!rc) |
| 584 | remove_migration_ptes(page, newpage); | 532 | remove_migration_ptes(page, newpage); |
| 585 | } else | 533 | else |
| 586 | newpage->mapping = NULL; | 534 | newpage->mapping = NULL; |
| 587 | 535 | ||
| 588 | unlock_page(newpage); | 536 | unlock_page(newpage); |
| @@ -595,7 +543,7 @@ static int move_to_new_page(struct page *newpage, struct page *page) | |||
| 595 | * to the newly allocated page in newpage. | 543 | * to the newly allocated page in newpage. |
| 596 | */ | 544 | */ |
| 597 | static int unmap_and_move(new_page_t get_new_page, unsigned long private, | 545 | static int unmap_and_move(new_page_t get_new_page, unsigned long private, |
| 598 | struct page *page, int force) | 546 | struct page *page, int force, int offlining) |
| 599 | { | 547 | { |
| 600 | int rc = 0; | 548 | int rc = 0; |
| 601 | int *result = NULL; | 549 | int *result = NULL; |
| @@ -621,6 +569,20 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
| 621 | lock_page(page); | 569 | lock_page(page); |
| 622 | } | 570 | } |
| 623 | 571 | ||
| 572 | /* | ||
| 573 | * Only memory hotplug's offline_pages() caller has locked out KSM, | ||
| 574 | * and can safely migrate a KSM page. The other cases have skipped | ||
| 575 | * PageKsm along with PageReserved - but it is only now when we have | ||
| 576 | * the page lock that we can be certain it will not go KSM beneath us | ||
| 577 | * (KSM will not upgrade a page from PageAnon to PageKsm when it sees | ||
| 578 | * its pagecount raised, but only here do we take the page lock which | ||
| 579 | * serializes that). | ||
| 580 | */ | ||
| 581 | if (PageKsm(page) && !offlining) { | ||
| 582 | rc = -EBUSY; | ||
| 583 | goto unlock; | ||
| 584 | } | ||
| 585 | |||
| 624 | /* charge against new page */ | 586 | /* charge against new page */ |
| 625 | charge = mem_cgroup_prepare_migration(page, &mem); | 587 | charge = mem_cgroup_prepare_migration(page, &mem); |
| 626 | if (charge == -ENOMEM) { | 588 | if (charge == -ENOMEM) { |
| @@ -737,7 +699,7 @@ move_newpage: | |||
| 737 | * Return: Number of pages not migrated or error code. | 699 | * Return: Number of pages not migrated or error code. |
| 738 | */ | 700 | */ |
| 739 | int migrate_pages(struct list_head *from, | 701 | int migrate_pages(struct list_head *from, |
| 740 | new_page_t get_new_page, unsigned long private) | 702 | new_page_t get_new_page, unsigned long private, int offlining) |
| 741 | { | 703 | { |
| 742 | int retry = 1; | 704 | int retry = 1; |
| 743 | int nr_failed = 0; | 705 | int nr_failed = 0; |
| @@ -746,13 +708,6 @@ int migrate_pages(struct list_head *from, | |||
| 746 | struct page *page2; | 708 | struct page *page2; |
| 747 | int swapwrite = current->flags & PF_SWAPWRITE; | 709 | int swapwrite = current->flags & PF_SWAPWRITE; |
| 748 | int rc; | 710 | int rc; |
| 749 | unsigned long flags; | ||
| 750 | |||
| 751 | local_irq_save(flags); | ||
| 752 | list_for_each_entry(page, from, lru) | ||
| 753 | __inc_zone_page_state(page, NR_ISOLATED_ANON + | ||
| 754 | page_is_file_cache(page)); | ||
| 755 | local_irq_restore(flags); | ||
| 756 | 711 | ||
| 757 | if (!swapwrite) | 712 | if (!swapwrite) |
| 758 | current->flags |= PF_SWAPWRITE; | 713 | current->flags |= PF_SWAPWRITE; |
| @@ -764,7 +719,7 @@ int migrate_pages(struct list_head *from, | |||
| 764 | cond_resched(); | 719 | cond_resched(); |
| 765 | 720 | ||
| 766 | rc = unmap_and_move(get_new_page, private, | 721 | rc = unmap_and_move(get_new_page, private, |
| 767 | page, pass > 2); | 722 | page, pass > 2, offlining); |
| 768 | 723 | ||
| 769 | switch(rc) { | 724 | switch(rc) { |
| 770 | case -ENOMEM: | 725 | case -ENOMEM: |
| @@ -860,7 +815,8 @@ static int do_move_page_to_node_array(struct mm_struct *mm, | |||
| 860 | if (!page) | 815 | if (!page) |
| 861 | goto set_status; | 816 | goto set_status; |
| 862 | 817 | ||
| 863 | if (PageReserved(page)) /* Check for zero page */ | 818 | /* Use PageReserved to check for zero page */ |
| 819 | if (PageReserved(page) || PageKsm(page)) | ||
| 864 | goto put_and_set; | 820 | goto put_and_set; |
| 865 | 821 | ||
| 866 | pp->page = page; | 822 | pp->page = page; |
| @@ -878,8 +834,11 @@ static int do_move_page_to_node_array(struct mm_struct *mm, | |||
| 878 | goto put_and_set; | 834 | goto put_and_set; |
| 879 | 835 | ||
| 880 | err = isolate_lru_page(page); | 836 | err = isolate_lru_page(page); |
| 881 | if (!err) | 837 | if (!err) { |
| 882 | list_add_tail(&page->lru, &pagelist); | 838 | list_add_tail(&page->lru, &pagelist); |
| 839 | inc_zone_page_state(page, NR_ISOLATED_ANON + | ||
| 840 | page_is_file_cache(page)); | ||
| 841 | } | ||
| 883 | put_and_set: | 842 | put_and_set: |
| 884 | /* | 843 | /* |
| 885 | * Either remove the duplicate refcount from | 844 | * Either remove the duplicate refcount from |
| @@ -894,7 +853,7 @@ set_status: | |||
| 894 | err = 0; | 853 | err = 0; |
| 895 | if (!list_empty(&pagelist)) | 854 | if (!list_empty(&pagelist)) |
| 896 | err = migrate_pages(&pagelist, new_page_node, | 855 | err = migrate_pages(&pagelist, new_page_node, |
| 897 | (unsigned long)pm); | 856 | (unsigned long)pm, 0); |
| 898 | 857 | ||
| 899 | up_read(&mm->mmap_sem); | 858 | up_read(&mm->mmap_sem); |
| 900 | return err; | 859 | return err; |
| @@ -1015,7 +974,7 @@ static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages, | |||
| 1015 | 974 | ||
| 1016 | err = -ENOENT; | 975 | err = -ENOENT; |
| 1017 | /* Use PageReserved to check for zero page */ | 976 | /* Use PageReserved to check for zero page */ |
| 1018 | if (!page || PageReserved(page)) | 977 | if (!page || PageReserved(page) || PageKsm(page)) |
| 1019 | goto set_status; | 978 | goto set_status; |
| 1020 | 979 | ||
| 1021 | err = page_to_nid(page); | 980 | err = page_to_nid(page); |
diff --git a/mm/mincore.c b/mm/mincore.c index 8cb508f84ea4..7a3436ef39eb 100644 --- a/mm/mincore.c +++ b/mm/mincore.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/syscalls.h> | 14 | #include <linux/syscalls.h> |
| 15 | #include <linux/swap.h> | 15 | #include <linux/swap.h> |
| 16 | #include <linux/swapops.h> | 16 | #include <linux/swapops.h> |
| 17 | #include <linux/hugetlb.h> | ||
| 17 | 18 | ||
| 18 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
| 19 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
| @@ -72,6 +73,42 @@ static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pag | |||
| 72 | if (!vma || addr < vma->vm_start) | 73 | if (!vma || addr < vma->vm_start) |
| 73 | return -ENOMEM; | 74 | return -ENOMEM; |
| 74 | 75 | ||
| 76 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 77 | if (is_vm_hugetlb_page(vma)) { | ||
| 78 | struct hstate *h; | ||
| 79 | unsigned long nr_huge; | ||
| 80 | unsigned char present; | ||
| 81 | |||
| 82 | i = 0; | ||
| 83 | nr = min(pages, (vma->vm_end - addr) >> PAGE_SHIFT); | ||
| 84 | h = hstate_vma(vma); | ||
| 85 | nr_huge = ((addr + pages * PAGE_SIZE - 1) >> huge_page_shift(h)) | ||
| 86 | - (addr >> huge_page_shift(h)) + 1; | ||
| 87 | nr_huge = min(nr_huge, | ||
| 88 | (vma->vm_end - addr) >> huge_page_shift(h)); | ||
| 89 | while (1) { | ||
| 90 | /* hugepage always in RAM for now, | ||
| 91 | * but generally it needs to be check */ | ||
| 92 | ptep = huge_pte_offset(current->mm, | ||
| 93 | addr & huge_page_mask(h)); | ||
| 94 | present = !!(ptep && | ||
| 95 | !huge_pte_none(huge_ptep_get(ptep))); | ||
| 96 | while (1) { | ||
| 97 | vec[i++] = present; | ||
| 98 | addr += PAGE_SIZE; | ||
| 99 | /* reach buffer limit */ | ||
| 100 | if (i == nr) | ||
| 101 | return nr; | ||
| 102 | /* check hugepage border */ | ||
| 103 | if (!((addr & ~huge_page_mask(h)) | ||
| 104 | >> PAGE_SHIFT)) | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | return nr; | ||
| 109 | } | ||
| 110 | #endif | ||
| 111 | |||
| 75 | /* | 112 | /* |
| 76 | * Calculate how many pages there are left in the last level of the | 113 | * Calculate how many pages there are left in the last level of the |
| 77 | * PTE array for our address. | 114 | * PTE array for our address. |
diff --git a/mm/mlock.c b/mm/mlock.c index bd6f0e466f6c..2b8335a89400 100644 --- a/mm/mlock.c +++ b/mm/mlock.c | |||
| @@ -88,25 +88,22 @@ void mlock_vma_page(struct page *page) | |||
| 88 | } | 88 | } |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | /* | 91 | /** |
| 92 | * called from munlock()/munmap() path with page supposedly on the LRU. | 92 | * munlock_vma_page - munlock a vma page |
| 93 | * @page - page to be unlocked | ||
| 93 | * | 94 | * |
| 94 | * Note: unlike mlock_vma_page(), we can't just clear the PageMlocked | 95 | * called from munlock()/munmap() path with page supposedly on the LRU. |
| 95 | * [in try_to_munlock()] and then attempt to isolate the page. We must | 96 | * When we munlock a page, because the vma where we found the page is being |
| 96 | * isolate the page to keep others from messing with its unevictable | 97 | * munlock()ed or munmap()ed, we want to check whether other vmas hold the |
| 97 | * and mlocked state while trying to munlock. However, we pre-clear the | 98 | * page locked so that we can leave it on the unevictable lru list and not |
| 98 | * mlocked state anyway as we might lose the isolation race and we might | 99 | * bother vmscan with it. However, to walk the page's rmap list in |
| 99 | * not get another chance to clear PageMlocked. If we successfully | 100 | * try_to_munlock() we must isolate the page from the LRU. If some other |
| 100 | * isolate the page and try_to_munlock() detects other VM_LOCKED vmas | 101 | * task has removed the page from the LRU, we won't be able to do that. |
| 101 | * mapping the page, it will restore the PageMlocked state, unless the page | 102 | * So we clear the PageMlocked as we might not get another chance. If we |
| 102 | * is mapped in a non-linear vma. So, we go ahead and SetPageMlocked(), | 103 | * can't isolate the page, we leave it for putback_lru_page() and vmscan |
| 103 | * perhaps redundantly. | 104 | * [page_referenced()/try_to_unmap()] to deal with. |
| 104 | * If we lose the isolation race, and the page is mapped by other VM_LOCKED | ||
| 105 | * vmas, we'll detect this in vmscan--via try_to_munlock() or try_to_unmap() | ||
| 106 | * either of which will restore the PageMlocked state by calling | ||
| 107 | * mlock_vma_page() above, if it can grab the vma's mmap sem. | ||
| 108 | */ | 105 | */ |
| 109 | static void munlock_vma_page(struct page *page) | 106 | void munlock_vma_page(struct page *page) |
| 110 | { | 107 | { |
| 111 | BUG_ON(!PageLocked(page)); | 108 | BUG_ON(!PageLocked(page)); |
| 112 | 109 | ||
| @@ -117,18 +114,18 @@ static void munlock_vma_page(struct page *page) | |||
| 117 | /* | 114 | /* |
| 118 | * did try_to_unlock() succeed or punt? | 115 | * did try_to_unlock() succeed or punt? |
| 119 | */ | 116 | */ |
| 120 | if (ret == SWAP_SUCCESS || ret == SWAP_AGAIN) | 117 | if (ret != SWAP_MLOCK) |
| 121 | count_vm_event(UNEVICTABLE_PGMUNLOCKED); | 118 | count_vm_event(UNEVICTABLE_PGMUNLOCKED); |
| 122 | 119 | ||
| 123 | putback_lru_page(page); | 120 | putback_lru_page(page); |
| 124 | } else { | 121 | } else { |
| 125 | /* | 122 | /* |
| 126 | * We lost the race. let try_to_unmap() deal | 123 | * Some other task has removed the page from the LRU. |
| 127 | * with it. At least we get the page state and | 124 | * putback_lru_page() will take care of removing the |
| 128 | * mlock stats right. However, page is still on | 125 | * page from the unevictable list, if necessary. |
| 129 | * the noreclaim list. We'll fix that up when | 126 | * vmscan [page_referenced()] will move the page back |
| 130 | * the page is eventually freed or we scan the | 127 | * to the unevictable list if some other vma has it |
| 131 | * noreclaim list. | 128 | * mlocked. |
| 132 | */ | 129 | */ |
| 133 | if (PageUnevictable(page)) | 130 | if (PageUnevictable(page)) |
| 134 | count_vm_event(UNEVICTABLE_PGSTRANDED); | 131 | count_vm_event(UNEVICTABLE_PGSTRANDED); |
| @@ -1198,8 +1198,20 @@ munmap_back: | |||
| 1198 | goto free_vma; | 1198 | goto free_vma; |
| 1199 | } | 1199 | } |
| 1200 | 1200 | ||
| 1201 | if (vma_wants_writenotify(vma)) | 1201 | if (vma_wants_writenotify(vma)) { |
| 1202 | pgprot_t pprot = vma->vm_page_prot; | ||
| 1203 | |||
| 1204 | /* Can vma->vm_page_prot have changed?? | ||
| 1205 | * | ||
| 1206 | * Answer: Yes, drivers may have changed it in their | ||
| 1207 | * f_op->mmap method. | ||
| 1208 | * | ||
| 1209 | * Ensures that vmas marked as uncached stay that way. | ||
| 1210 | */ | ||
| 1202 | vma->vm_page_prot = vm_get_page_prot(vm_flags & ~VM_SHARED); | 1211 | vma->vm_page_prot = vm_get_page_prot(vm_flags & ~VM_SHARED); |
| 1212 | if (pgprot_val(pprot) == pgprot_val(pgprot_noncached(pprot))) | ||
| 1213 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
| 1214 | } | ||
| 1203 | 1215 | ||
| 1204 | vma_link(mm, vma, prev, rb_link, rb_parent); | 1216 | vma_link(mm, vma, prev, rb_link, rb_parent); |
| 1205 | file = vma->vm_file; | 1217 | file = vma->vm_file; |
| @@ -1811,10 +1823,10 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1811 | } | 1823 | } |
| 1812 | 1824 | ||
| 1813 | /* | 1825 | /* |
| 1814 | * Split a vma into two pieces at address 'addr', a new vma is allocated | 1826 | * __split_vma() bypasses sysctl_max_map_count checking. We use this on the |
| 1815 | * either for the first part or the tail. | 1827 | * munmap path where it doesn't make sense to fail. |
| 1816 | */ | 1828 | */ |
| 1817 | int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, | 1829 | static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, |
| 1818 | unsigned long addr, int new_below) | 1830 | unsigned long addr, int new_below) |
| 1819 | { | 1831 | { |
| 1820 | struct mempolicy *pol; | 1832 | struct mempolicy *pol; |
| @@ -1824,9 +1836,6 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, | |||
| 1824 | ~(huge_page_mask(hstate_vma(vma))))) | 1836 | ~(huge_page_mask(hstate_vma(vma))))) |
| 1825 | return -EINVAL; | 1837 | return -EINVAL; |
| 1826 | 1838 | ||
| 1827 | if (mm->map_count >= sysctl_max_map_count) | ||
| 1828 | return -ENOMEM; | ||
| 1829 | |||
| 1830 | new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); | 1839 | new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); |
| 1831 | if (!new) | 1840 | if (!new) |
| 1832 | return -ENOMEM; | 1841 | return -ENOMEM; |
| @@ -1866,6 +1875,19 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, | |||
| 1866 | return 0; | 1875 | return 0; |
| 1867 | } | 1876 | } |
| 1868 | 1877 | ||
| 1878 | /* | ||
| 1879 | * Split a vma into two pieces at address 'addr', a new vma is allocated | ||
| 1880 | * either for the first part or the tail. | ||
| 1881 | */ | ||
| 1882 | int split_vma(struct mm_struct *mm, struct vm_area_struct *vma, | ||
| 1883 | unsigned long addr, int new_below) | ||
| 1884 | { | ||
| 1885 | if (mm->map_count >= sysctl_max_map_count) | ||
| 1886 | return -ENOMEM; | ||
| 1887 | |||
| 1888 | return __split_vma(mm, vma, addr, new_below); | ||
| 1889 | } | ||
| 1890 | |||
| 1869 | /* Munmap is split into 2 main parts -- this part which finds | 1891 | /* Munmap is split into 2 main parts -- this part which finds |
| 1870 | * what needs doing, and the areas themselves, which do the | 1892 | * what needs doing, and the areas themselves, which do the |
| 1871 | * work. This now handles partial unmappings. | 1893 | * work. This now handles partial unmappings. |
| @@ -1901,7 +1923,17 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) | |||
| 1901 | * places tmp vma above, and higher split_vma places tmp vma below. | 1923 | * places tmp vma above, and higher split_vma places tmp vma below. |
| 1902 | */ | 1924 | */ |
| 1903 | if (start > vma->vm_start) { | 1925 | if (start > vma->vm_start) { |
| 1904 | int error = split_vma(mm, vma, start, 0); | 1926 | int error; |
| 1927 | |||
| 1928 | /* | ||
| 1929 | * Make sure that map_count on return from munmap() will | ||
| 1930 | * not exceed its limit; but let map_count go just above | ||
| 1931 | * its limit temporarily, to help free resources as expected. | ||
| 1932 | */ | ||
| 1933 | if (end < vma->vm_end && mm->map_count >= sysctl_max_map_count) | ||
| 1934 | return -ENOMEM; | ||
| 1935 | |||
| 1936 | error = __split_vma(mm, vma, start, 0); | ||
| 1905 | if (error) | 1937 | if (error) |
| 1906 | return error; | 1938 | return error; |
| 1907 | prev = vma; | 1939 | prev = vma; |
| @@ -1910,7 +1942,7 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) | |||
| 1910 | /* Does it split the last one? */ | 1942 | /* Does it split the last one? */ |
| 1911 | last = find_vma(mm, end); | 1943 | last = find_vma(mm, end); |
| 1912 | if (last && end > last->vm_start) { | 1944 | if (last && end > last->vm_start) { |
| 1913 | int error = split_vma(mm, last, end, 1); | 1945 | int error = __split_vma(mm, last, end, 1); |
| 1914 | if (error) | 1946 | if (error) |
| 1915 | return error; | 1947 | return error; |
| 1916 | } | 1948 | } |
diff --git a/mm/nommu.c b/mm/nommu.c index 9876fa0c3ad3..8687973462bb 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -1143,9 +1143,6 @@ static int do_mmap_private(struct vm_area_struct *vma, | |||
| 1143 | if (ret < rlen) | 1143 | if (ret < rlen) |
| 1144 | memset(base + ret, 0, rlen - ret); | 1144 | memset(base + ret, 0, rlen - ret); |
| 1145 | 1145 | ||
| 1146 | } else { | ||
| 1147 | /* if it's an anonymous mapping, then just clear it */ | ||
| 1148 | memset(base, 0, rlen); | ||
| 1149 | } | 1146 | } |
| 1150 | 1147 | ||
| 1151 | return 0; | 1148 | return 0; |
| @@ -1343,6 +1340,11 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
| 1343 | goto error_just_free; | 1340 | goto error_just_free; |
| 1344 | add_nommu_region(region); | 1341 | add_nommu_region(region); |
| 1345 | 1342 | ||
| 1343 | /* clear anonymous mappings that don't ask for uninitialized data */ | ||
| 1344 | if (!vma->vm_file && !(flags & MAP_UNINITIALIZED)) | ||
| 1345 | memset((void *)region->vm_start, 0, | ||
| 1346 | region->vm_end - region->vm_start); | ||
| 1347 | |||
| 1346 | /* okay... we have a mapping; now we have to register it */ | 1348 | /* okay... we have a mapping; now we have to register it */ |
| 1347 | result = vma->vm_start; | 1349 | result = vma->vm_start; |
| 1348 | 1350 | ||
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index ea2147dabba6..492c98624fc1 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
| @@ -337,6 +337,21 @@ static void dump_tasks(const struct mem_cgroup *mem) | |||
| 337 | } while_each_thread(g, p); | 337 | } while_each_thread(g, p); |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static void dump_header(gfp_t gfp_mask, int order, struct mem_cgroup *mem) | ||
| 341 | { | ||
| 342 | pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, " | ||
| 343 | "oom_adj=%d\n", | ||
| 344 | current->comm, gfp_mask, order, current->signal->oom_adj); | ||
| 345 | task_lock(current); | ||
| 346 | cpuset_print_task_mems_allowed(current); | ||
| 347 | task_unlock(current); | ||
| 348 | dump_stack(); | ||
| 349 | mem_cgroup_print_oom_info(mem, current); | ||
| 350 | show_mem(); | ||
| 351 | if (sysctl_oom_dump_tasks) | ||
| 352 | dump_tasks(mem); | ||
| 353 | } | ||
| 354 | |||
| 340 | /* | 355 | /* |
| 341 | * Send SIGKILL to the selected process irrespective of CAP_SYS_RAW_IO | 356 | * Send SIGKILL to the selected process irrespective of CAP_SYS_RAW_IO |
| 342 | * flag though it's unlikely that we select a process with CAP_SYS_RAW_IO | 357 | * flag though it's unlikely that we select a process with CAP_SYS_RAW_IO |
| @@ -395,20 +410,8 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
| 395 | { | 410 | { |
| 396 | struct task_struct *c; | 411 | struct task_struct *c; |
| 397 | 412 | ||
| 398 | if (printk_ratelimit()) { | 413 | if (printk_ratelimit()) |
| 399 | printk(KERN_WARNING "%s invoked oom-killer: " | 414 | dump_header(gfp_mask, order, mem); |
| 400 | "gfp_mask=0x%x, order=%d, oom_adj=%d\n", | ||
| 401 | current->comm, gfp_mask, order, | ||
| 402 | current->signal->oom_adj); | ||
| 403 | task_lock(current); | ||
| 404 | cpuset_print_task_mems_allowed(current); | ||
| 405 | task_unlock(current); | ||
| 406 | dump_stack(); | ||
| 407 | mem_cgroup_print_oom_info(mem, current); | ||
| 408 | show_mem(); | ||
| 409 | if (sysctl_oom_dump_tasks) | ||
| 410 | dump_tasks(mem); | ||
| 411 | } | ||
| 412 | 415 | ||
| 413 | /* | 416 | /* |
| 414 | * If the task is already exiting, don't alarm the sysadmin or kill | 417 | * If the task is already exiting, don't alarm the sysadmin or kill |
| @@ -544,6 +547,7 @@ retry: | |||
| 544 | /* Found nothing?!?! Either we hang forever, or we panic. */ | 547 | /* Found nothing?!?! Either we hang forever, or we panic. */ |
| 545 | if (!p) { | 548 | if (!p) { |
| 546 | read_unlock(&tasklist_lock); | 549 | read_unlock(&tasklist_lock); |
| 550 | dump_header(gfp_mask, order, NULL); | ||
| 547 | panic("Out of memory and no killable processes...\n"); | 551 | panic("Out of memory and no killable processes...\n"); |
| 548 | } | 552 | } |
| 549 | 553 | ||
| @@ -609,8 +613,10 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order) | |||
| 609 | /* Got some memory back in the last second. */ | 613 | /* Got some memory back in the last second. */ |
| 610 | return; | 614 | return; |
| 611 | 615 | ||
| 612 | if (sysctl_panic_on_oom == 2) | 616 | if (sysctl_panic_on_oom == 2) { |
| 617 | dump_header(gfp_mask, order, NULL); | ||
| 613 | panic("out of memory. Compulsory panic_on_oom is selected.\n"); | 618 | panic("out of memory. Compulsory panic_on_oom is selected.\n"); |
| 619 | } | ||
| 614 | 620 | ||
| 615 | /* | 621 | /* |
| 616 | * Check if there were limitations on the allocation (only relevant for | 622 | * Check if there were limitations on the allocation (only relevant for |
| @@ -626,8 +632,10 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order) | |||
| 626 | break; | 632 | break; |
| 627 | 633 | ||
| 628 | case CONSTRAINT_NONE: | 634 | case CONSTRAINT_NONE: |
| 629 | if (sysctl_panic_on_oom) | 635 | if (sysctl_panic_on_oom) { |
| 636 | dump_header(gfp_mask, order, NULL); | ||
| 630 | panic("out of memory. panic_on_oom is selected\n"); | 637 | panic("out of memory. panic_on_oom is selected\n"); |
| 638 | } | ||
| 631 | /* Fall-through */ | 639 | /* Fall-through */ |
| 632 | case CONSTRAINT_CPUSET: | 640 | case CONSTRAINT_CPUSET: |
| 633 | __out_of_memory(gfp_mask, order); | 641 | __out_of_memory(gfp_mask, order); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2bc2ac63f41e..59d2e88fb47c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -486,7 +486,6 @@ static inline void __free_one_page(struct page *page, | |||
| 486 | zone->free_area[order].nr_free++; | 486 | zone->free_area[order].nr_free++; |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | ||
| 490 | /* | 489 | /* |
| 491 | * free_page_mlock() -- clean up attempts to free and mlocked() page. | 490 | * free_page_mlock() -- clean up attempts to free and mlocked() page. |
| 492 | * Page should not be on lru, so no need to fix that up. | 491 | * Page should not be on lru, so no need to fix that up. |
| @@ -497,9 +496,6 @@ static inline void free_page_mlock(struct page *page) | |||
| 497 | __dec_zone_page_state(page, NR_MLOCK); | 496 | __dec_zone_page_state(page, NR_MLOCK); |
| 498 | __count_vm_event(UNEVICTABLE_MLOCKFREED); | 497 | __count_vm_event(UNEVICTABLE_MLOCKFREED); |
| 499 | } | 498 | } |
| 500 | #else | ||
| 501 | static void free_page_mlock(struct page *page) { } | ||
| 502 | #endif | ||
| 503 | 499 | ||
| 504 | static inline int free_pages_check(struct page *page) | 500 | static inline int free_pages_check(struct page *page) |
| 505 | { | 501 | { |
diff --git a/mm/page_io.c b/mm/page_io.c index c6f3e5071de3..a19af956ee1b 100644 --- a/mm/page_io.c +++ b/mm/page_io.c | |||
| @@ -19,20 +19,15 @@ | |||
| 19 | #include <linux/writeback.h> | 19 | #include <linux/writeback.h> |
| 20 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
| 21 | 21 | ||
| 22 | static struct bio *get_swap_bio(gfp_t gfp_flags, pgoff_t index, | 22 | static struct bio *get_swap_bio(gfp_t gfp_flags, |
| 23 | struct page *page, bio_end_io_t end_io) | 23 | struct page *page, bio_end_io_t end_io) |
| 24 | { | 24 | { |
| 25 | struct bio *bio; | 25 | struct bio *bio; |
| 26 | 26 | ||
| 27 | bio = bio_alloc(gfp_flags, 1); | 27 | bio = bio_alloc(gfp_flags, 1); |
| 28 | if (bio) { | 28 | if (bio) { |
| 29 | struct swap_info_struct *sis; | 29 | bio->bi_sector = map_swap_page(page, &bio->bi_bdev); |
| 30 | swp_entry_t entry = { .val = index, }; | 30 | bio->bi_sector <<= PAGE_SHIFT - 9; |
| 31 | |||
| 32 | sis = get_swap_info_struct(swp_type(entry)); | ||
| 33 | bio->bi_sector = map_swap_page(sis, swp_offset(entry)) * | ||
| 34 | (PAGE_SIZE >> 9); | ||
| 35 | bio->bi_bdev = sis->bdev; | ||
| 36 | bio->bi_io_vec[0].bv_page = page; | 31 | bio->bi_io_vec[0].bv_page = page; |
| 37 | bio->bi_io_vec[0].bv_len = PAGE_SIZE; | 32 | bio->bi_io_vec[0].bv_len = PAGE_SIZE; |
| 38 | bio->bi_io_vec[0].bv_offset = 0; | 33 | bio->bi_io_vec[0].bv_offset = 0; |
| @@ -102,8 +97,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) | |||
| 102 | unlock_page(page); | 97 | unlock_page(page); |
| 103 | goto out; | 98 | goto out; |
| 104 | } | 99 | } |
| 105 | bio = get_swap_bio(GFP_NOIO, page_private(page), page, | 100 | bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write); |
| 106 | end_swap_bio_write); | ||
| 107 | if (bio == NULL) { | 101 | if (bio == NULL) { |
| 108 | set_page_dirty(page); | 102 | set_page_dirty(page); |
| 109 | unlock_page(page); | 103 | unlock_page(page); |
| @@ -127,8 +121,7 @@ int swap_readpage(struct page *page) | |||
| 127 | 121 | ||
| 128 | VM_BUG_ON(!PageLocked(page)); | 122 | VM_BUG_ON(!PageLocked(page)); |
| 129 | VM_BUG_ON(PageUptodate(page)); | 123 | VM_BUG_ON(PageUptodate(page)); |
| 130 | bio = get_swap_bio(GFP_KERNEL, page_private(page), page, | 124 | bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); |
| 131 | end_swap_bio_read); | ||
| 132 | if (bio == NULL) { | 125 | if (bio == NULL) { |
| 133 | unlock_page(page); | 126 | unlock_page(page); |
| 134 | ret = -ENOMEM; | 127 | ret = -ENOMEM; |
diff --git a/mm/pagewalk.c b/mm/pagewalk.c index d5878bed7841..7b47a57b6646 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/mm.h> | 1 | #include <linux/mm.h> |
| 2 | #include <linux/highmem.h> | 2 | #include <linux/highmem.h> |
| 3 | #include <linux/sched.h> | 3 | #include <linux/sched.h> |
| 4 | #include <linux/hugetlb.h> | ||
| 4 | 5 | ||
| 5 | static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | 6 | static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, |
| 6 | struct mm_walk *walk) | 7 | struct mm_walk *walk) |
| @@ -107,6 +108,7 @@ int walk_page_range(unsigned long addr, unsigned long end, | |||
| 107 | pgd_t *pgd; | 108 | pgd_t *pgd; |
| 108 | unsigned long next; | 109 | unsigned long next; |
| 109 | int err = 0; | 110 | int err = 0; |
| 111 | struct vm_area_struct *vma; | ||
| 110 | 112 | ||
| 111 | if (addr >= end) | 113 | if (addr >= end) |
| 112 | return err; | 114 | return err; |
| @@ -117,11 +119,38 @@ int walk_page_range(unsigned long addr, unsigned long end, | |||
| 117 | pgd = pgd_offset(walk->mm, addr); | 119 | pgd = pgd_offset(walk->mm, addr); |
| 118 | do { | 120 | do { |
| 119 | next = pgd_addr_end(addr, end); | 121 | next = pgd_addr_end(addr, end); |
| 122 | |||
| 123 | /* | ||
| 124 | * handle hugetlb vma individually because pagetable walk for | ||
| 125 | * the hugetlb page is dependent on the architecture and | ||
| 126 | * we can't handled it in the same manner as non-huge pages. | ||
| 127 | */ | ||
| 128 | vma = find_vma(walk->mm, addr); | ||
| 129 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 130 | if (vma && is_vm_hugetlb_page(vma)) { | ||
| 131 | pte_t *pte; | ||
| 132 | struct hstate *hs; | ||
| 133 | |||
| 134 | if (vma->vm_end < next) | ||
| 135 | next = vma->vm_end; | ||
| 136 | hs = hstate_vma(vma); | ||
| 137 | pte = huge_pte_offset(walk->mm, | ||
| 138 | addr & huge_page_mask(hs)); | ||
| 139 | if (pte && !huge_pte_none(huge_ptep_get(pte)) | ||
| 140 | && walk->hugetlb_entry) | ||
| 141 | err = walk->hugetlb_entry(pte, addr, | ||
| 142 | next, walk); | ||
| 143 | if (err) | ||
| 144 | break; | ||
| 145 | continue; | ||
| 146 | } | ||
| 147 | #endif | ||
| 120 | if (pgd_none_or_clear_bad(pgd)) { | 148 | if (pgd_none_or_clear_bad(pgd)) { |
| 121 | if (walk->pte_hole) | 149 | if (walk->pte_hole) |
| 122 | err = walk->pte_hole(addr, next, walk); | 150 | err = walk->pte_hole(addr, next, walk); |
| 123 | if (err) | 151 | if (err) |
| 124 | break; | 152 | break; |
| 153 | pgd++; | ||
| 125 | continue; | 154 | continue; |
| 126 | } | 155 | } |
| 127 | if (walk->pgd_entry) | 156 | if (walk->pgd_entry) |
| @@ -131,7 +160,8 @@ int walk_page_range(unsigned long addr, unsigned long end, | |||
| 131 | err = walk_pud_range(pgd, addr, next, walk); | 160 | err = walk_pud_range(pgd, addr, next, walk); |
| 132 | if (err) | 161 | if (err) |
| 133 | break; | 162 | break; |
| 134 | } while (pgd++, addr = next, addr != end); | 163 | pgd++; |
| 164 | } while (addr = next, addr != end); | ||
| 135 | 165 | ||
| 136 | return err; | 166 | return err; |
| 137 | } | 167 | } |
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <linux/swapops.h> | 49 | #include <linux/swapops.h> |
| 50 | #include <linux/slab.h> | 50 | #include <linux/slab.h> |
| 51 | #include <linux/init.h> | 51 | #include <linux/init.h> |
| 52 | #include <linux/ksm.h> | ||
| 52 | #include <linux/rmap.h> | 53 | #include <linux/rmap.h> |
| 53 | #include <linux/rcupdate.h> | 54 | #include <linux/rcupdate.h> |
| 54 | #include <linux/module.h> | 55 | #include <linux/module.h> |
| @@ -67,7 +68,7 @@ static inline struct anon_vma *anon_vma_alloc(void) | |||
| 67 | return kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL); | 68 | return kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL); |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | static inline void anon_vma_free(struct anon_vma *anon_vma) | 71 | void anon_vma_free(struct anon_vma *anon_vma) |
| 71 | { | 72 | { |
| 72 | kmem_cache_free(anon_vma_cachep, anon_vma); | 73 | kmem_cache_free(anon_vma_cachep, anon_vma); |
| 73 | } | 74 | } |
| @@ -171,7 +172,7 @@ void anon_vma_unlink(struct vm_area_struct *vma) | |||
| 171 | list_del(&vma->anon_vma_node); | 172 | list_del(&vma->anon_vma_node); |
| 172 | 173 | ||
| 173 | /* We must garbage collect the anon_vma if it's empty */ | 174 | /* We must garbage collect the anon_vma if it's empty */ |
| 174 | empty = list_empty(&anon_vma->head); | 175 | empty = list_empty(&anon_vma->head) && !ksm_refcount(anon_vma); |
| 175 | spin_unlock(&anon_vma->lock); | 176 | spin_unlock(&anon_vma->lock); |
| 176 | 177 | ||
| 177 | if (empty) | 178 | if (empty) |
| @@ -183,6 +184,7 @@ static void anon_vma_ctor(void *data) | |||
| 183 | struct anon_vma *anon_vma = data; | 184 | struct anon_vma *anon_vma = data; |
| 184 | 185 | ||
| 185 | spin_lock_init(&anon_vma->lock); | 186 | spin_lock_init(&anon_vma->lock); |
| 187 | ksm_refcount_init(anon_vma); | ||
| 186 | INIT_LIST_HEAD(&anon_vma->head); | 188 | INIT_LIST_HEAD(&anon_vma->head); |
| 187 | } | 189 | } |
| 188 | 190 | ||
| @@ -202,8 +204,8 @@ struct anon_vma *page_lock_anon_vma(struct page *page) | |||
| 202 | unsigned long anon_mapping; | 204 | unsigned long anon_mapping; |
| 203 | 205 | ||
| 204 | rcu_read_lock(); | 206 | rcu_read_lock(); |
| 205 | anon_mapping = (unsigned long) page->mapping; | 207 | anon_mapping = (unsigned long) ACCESS_ONCE(page->mapping); |
| 206 | if (!(anon_mapping & PAGE_MAPPING_ANON)) | 208 | if ((anon_mapping & PAGE_MAPPING_FLAGS) != PAGE_MAPPING_ANON) |
| 207 | goto out; | 209 | goto out; |
| 208 | if (!page_mapped(page)) | 210 | if (!page_mapped(page)) |
| 209 | goto out; | 211 | goto out; |
| @@ -248,8 +250,7 @@ vma_address(struct page *page, struct vm_area_struct *vma) | |||
| 248 | unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) | 250 | unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) |
| 249 | { | 251 | { |
| 250 | if (PageAnon(page)) { | 252 | if (PageAnon(page)) { |
| 251 | if ((void *)vma->anon_vma != | 253 | if (vma->anon_vma != page_anon_vma(page)) |
| 252 | (void *)page->mapping - PAGE_MAPPING_ANON) | ||
| 253 | return -EFAULT; | 254 | return -EFAULT; |
| 254 | } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) { | 255 | } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) { |
| 255 | if (!vma->vm_file || | 256 | if (!vma->vm_file || |
| @@ -337,21 +338,15 @@ int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma) | |||
| 337 | * Subfunctions of page_referenced: page_referenced_one called | 338 | * Subfunctions of page_referenced: page_referenced_one called |
| 338 | * repeatedly from either page_referenced_anon or page_referenced_file. | 339 | * repeatedly from either page_referenced_anon or page_referenced_file. |
| 339 | */ | 340 | */ |
| 340 | static int page_referenced_one(struct page *page, | 341 | int page_referenced_one(struct page *page, struct vm_area_struct *vma, |
| 341 | struct vm_area_struct *vma, | 342 | unsigned long address, unsigned int *mapcount, |
| 342 | unsigned int *mapcount, | 343 | unsigned long *vm_flags) |
| 343 | unsigned long *vm_flags) | ||
| 344 | { | 344 | { |
| 345 | struct mm_struct *mm = vma->vm_mm; | 345 | struct mm_struct *mm = vma->vm_mm; |
| 346 | unsigned long address; | ||
| 347 | pte_t *pte; | 346 | pte_t *pte; |
| 348 | spinlock_t *ptl; | 347 | spinlock_t *ptl; |
| 349 | int referenced = 0; | 348 | int referenced = 0; |
| 350 | 349 | ||
| 351 | address = vma_address(page, vma); | ||
| 352 | if (address == -EFAULT) | ||
| 353 | goto out; | ||
| 354 | |||
| 355 | pte = page_check_address(page, mm, address, &ptl, 0); | 350 | pte = page_check_address(page, mm, address, &ptl, 0); |
| 356 | if (!pte) | 351 | if (!pte) |
| 357 | goto out; | 352 | goto out; |
| @@ -388,9 +383,10 @@ static int page_referenced_one(struct page *page, | |||
| 388 | out_unmap: | 383 | out_unmap: |
| 389 | (*mapcount)--; | 384 | (*mapcount)--; |
| 390 | pte_unmap_unlock(pte, ptl); | 385 | pte_unmap_unlock(pte, ptl); |
| 391 | out: | 386 | |
| 392 | if (referenced) | 387 | if (referenced) |
| 393 | *vm_flags |= vma->vm_flags; | 388 | *vm_flags |= vma->vm_flags; |
| 389 | out: | ||
| 394 | return referenced; | 390 | return referenced; |
| 395 | } | 391 | } |
| 396 | 392 | ||
| @@ -409,6 +405,9 @@ static int page_referenced_anon(struct page *page, | |||
| 409 | 405 | ||
| 410 | mapcount = page_mapcount(page); | 406 | mapcount = page_mapcount(page); |
| 411 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | 407 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { |
| 408 | unsigned long address = vma_address(page, vma); | ||
| 409 | if (address == -EFAULT) | ||
| 410 | continue; | ||
| 412 | /* | 411 | /* |
| 413 | * If we are reclaiming on behalf of a cgroup, skip | 412 | * If we are reclaiming on behalf of a cgroup, skip |
| 414 | * counting on behalf of references from different | 413 | * counting on behalf of references from different |
| @@ -416,7 +415,7 @@ static int page_referenced_anon(struct page *page, | |||
| 416 | */ | 415 | */ |
| 417 | if (mem_cont && !mm_match_cgroup(vma->vm_mm, mem_cont)) | 416 | if (mem_cont && !mm_match_cgroup(vma->vm_mm, mem_cont)) |
| 418 | continue; | 417 | continue; |
| 419 | referenced += page_referenced_one(page, vma, | 418 | referenced += page_referenced_one(page, vma, address, |
| 420 | &mapcount, vm_flags); | 419 | &mapcount, vm_flags); |
| 421 | if (!mapcount) | 420 | if (!mapcount) |
| 422 | break; | 421 | break; |
| @@ -474,6 +473,9 @@ static int page_referenced_file(struct page *page, | |||
| 474 | mapcount = page_mapcount(page); | 473 | mapcount = page_mapcount(page); |
| 475 | 474 | ||
| 476 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 475 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { |
| 476 | unsigned long address = vma_address(page, vma); | ||
| 477 | if (address == -EFAULT) | ||
| 478 | continue; | ||
| 477 | /* | 479 | /* |
| 478 | * If we are reclaiming on behalf of a cgroup, skip | 480 | * If we are reclaiming on behalf of a cgroup, skip |
| 479 | * counting on behalf of references from different | 481 | * counting on behalf of references from different |
| @@ -481,7 +483,7 @@ static int page_referenced_file(struct page *page, | |||
| 481 | */ | 483 | */ |
| 482 | if (mem_cont && !mm_match_cgroup(vma->vm_mm, mem_cont)) | 484 | if (mem_cont && !mm_match_cgroup(vma->vm_mm, mem_cont)) |
| 483 | continue; | 485 | continue; |
| 484 | referenced += page_referenced_one(page, vma, | 486 | referenced += page_referenced_one(page, vma, address, |
| 485 | &mapcount, vm_flags); | 487 | &mapcount, vm_flags); |
| 486 | if (!mapcount) | 488 | if (!mapcount) |
| 487 | break; | 489 | break; |
| @@ -507,46 +509,47 @@ int page_referenced(struct page *page, | |||
| 507 | unsigned long *vm_flags) | 509 | unsigned long *vm_flags) |
| 508 | { | 510 | { |
| 509 | int referenced = 0; | 511 | int referenced = 0; |
| 512 | int we_locked = 0; | ||
| 510 | 513 | ||
| 511 | if (TestClearPageReferenced(page)) | 514 | if (TestClearPageReferenced(page)) |
| 512 | referenced++; | 515 | referenced++; |
| 513 | 516 | ||
| 514 | *vm_flags = 0; | 517 | *vm_flags = 0; |
| 515 | if (page_mapped(page) && page->mapping) { | 518 | if (page_mapped(page) && page_rmapping(page)) { |
| 516 | if (PageAnon(page)) | 519 | if (!is_locked && (!PageAnon(page) || PageKsm(page))) { |
| 520 | we_locked = trylock_page(page); | ||
| 521 | if (!we_locked) { | ||
| 522 | referenced++; | ||
| 523 | goto out; | ||
| 524 | } | ||
| 525 | } | ||
| 526 | if (unlikely(PageKsm(page))) | ||
| 527 | referenced += page_referenced_ksm(page, mem_cont, | ||
| 528 | vm_flags); | ||
| 529 | else if (PageAnon(page)) | ||
| 517 | referenced += page_referenced_anon(page, mem_cont, | 530 | referenced += page_referenced_anon(page, mem_cont, |
| 518 | vm_flags); | 531 | vm_flags); |
| 519 | else if (is_locked) | 532 | else if (page->mapping) |
| 520 | referenced += page_referenced_file(page, mem_cont, | 533 | referenced += page_referenced_file(page, mem_cont, |
| 521 | vm_flags); | 534 | vm_flags); |
| 522 | else if (!trylock_page(page)) | 535 | if (we_locked) |
| 523 | referenced++; | ||
| 524 | else { | ||
| 525 | if (page->mapping) | ||
| 526 | referenced += page_referenced_file(page, | ||
| 527 | mem_cont, vm_flags); | ||
| 528 | unlock_page(page); | 536 | unlock_page(page); |
| 529 | } | ||
| 530 | } | 537 | } |
| 531 | 538 | out: | |
| 532 | if (page_test_and_clear_young(page)) | 539 | if (page_test_and_clear_young(page)) |
| 533 | referenced++; | 540 | referenced++; |
| 534 | 541 | ||
| 535 | return referenced; | 542 | return referenced; |
| 536 | } | 543 | } |
| 537 | 544 | ||
| 538 | static int page_mkclean_one(struct page *page, struct vm_area_struct *vma) | 545 | static int page_mkclean_one(struct page *page, struct vm_area_struct *vma, |
| 546 | unsigned long address) | ||
| 539 | { | 547 | { |
| 540 | struct mm_struct *mm = vma->vm_mm; | 548 | struct mm_struct *mm = vma->vm_mm; |
| 541 | unsigned long address; | ||
| 542 | pte_t *pte; | 549 | pte_t *pte; |
| 543 | spinlock_t *ptl; | 550 | spinlock_t *ptl; |
| 544 | int ret = 0; | 551 | int ret = 0; |
| 545 | 552 | ||
| 546 | address = vma_address(page, vma); | ||
| 547 | if (address == -EFAULT) | ||
| 548 | goto out; | ||
| 549 | |||
| 550 | pte = page_check_address(page, mm, address, &ptl, 1); | 553 | pte = page_check_address(page, mm, address, &ptl, 1); |
| 551 | if (!pte) | 554 | if (!pte) |
| 552 | goto out; | 555 | goto out; |
| @@ -578,8 +581,12 @@ static int page_mkclean_file(struct address_space *mapping, struct page *page) | |||
| 578 | 581 | ||
| 579 | spin_lock(&mapping->i_mmap_lock); | 582 | spin_lock(&mapping->i_mmap_lock); |
| 580 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 583 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { |
| 581 | if (vma->vm_flags & VM_SHARED) | 584 | if (vma->vm_flags & VM_SHARED) { |
| 582 | ret += page_mkclean_one(page, vma); | 585 | unsigned long address = vma_address(page, vma); |
| 586 | if (address == -EFAULT) | ||
| 587 | continue; | ||
| 588 | ret += page_mkclean_one(page, vma, address); | ||
| 589 | } | ||
| 583 | } | 590 | } |
| 584 | spin_unlock(&mapping->i_mmap_lock); | 591 | spin_unlock(&mapping->i_mmap_lock); |
| 585 | return ret; | 592 | return ret; |
| @@ -620,14 +627,7 @@ static void __page_set_anon_rmap(struct page *page, | |||
| 620 | BUG_ON(!anon_vma); | 627 | BUG_ON(!anon_vma); |
| 621 | anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; | 628 | anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; |
| 622 | page->mapping = (struct address_space *) anon_vma; | 629 | page->mapping = (struct address_space *) anon_vma; |
| 623 | |||
| 624 | page->index = linear_page_index(vma, address); | 630 | page->index = linear_page_index(vma, address); |
| 625 | |||
| 626 | /* | ||
| 627 | * nr_mapped state can be updated without turning off | ||
| 628 | * interrupts because it is not modified via interrupt. | ||
| 629 | */ | ||
| 630 | __inc_zone_page_state(page, NR_ANON_PAGES); | ||
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | /** | 633 | /** |
| @@ -665,14 +665,23 @@ static void __page_check_anon_rmap(struct page *page, | |||
| 665 | * @vma: the vm area in which the mapping is added | 665 | * @vma: the vm area in which the mapping is added |
| 666 | * @address: the user virtual address mapped | 666 | * @address: the user virtual address mapped |
| 667 | * | 667 | * |
| 668 | * The caller needs to hold the pte lock and the page must be locked. | 668 | * The caller needs to hold the pte lock, and the page must be locked in |
| 669 | * the anon_vma case: to serialize mapping,index checking after setting, | ||
| 670 | * and to ensure that PageAnon is not being upgraded racily to PageKsm | ||
| 671 | * (but PageKsm is never downgraded to PageAnon). | ||
| 669 | */ | 672 | */ |
| 670 | void page_add_anon_rmap(struct page *page, | 673 | void page_add_anon_rmap(struct page *page, |
| 671 | struct vm_area_struct *vma, unsigned long address) | 674 | struct vm_area_struct *vma, unsigned long address) |
| 672 | { | 675 | { |
| 676 | int first = atomic_inc_and_test(&page->_mapcount); | ||
| 677 | if (first) | ||
| 678 | __inc_zone_page_state(page, NR_ANON_PAGES); | ||
| 679 | if (unlikely(PageKsm(page))) | ||
| 680 | return; | ||
| 681 | |||
| 673 | VM_BUG_ON(!PageLocked(page)); | 682 | VM_BUG_ON(!PageLocked(page)); |
| 674 | VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); | 683 | VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); |
| 675 | if (atomic_inc_and_test(&page->_mapcount)) | 684 | if (first) |
| 676 | __page_set_anon_rmap(page, vma, address); | 685 | __page_set_anon_rmap(page, vma, address); |
| 677 | else | 686 | else |
| 678 | __page_check_anon_rmap(page, vma, address); | 687 | __page_check_anon_rmap(page, vma, address); |
| @@ -694,6 +703,7 @@ void page_add_new_anon_rmap(struct page *page, | |||
| 694 | VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); | 703 | VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); |
| 695 | SetPageSwapBacked(page); | 704 | SetPageSwapBacked(page); |
| 696 | atomic_set(&page->_mapcount, 0); /* increment count (starts at -1) */ | 705 | atomic_set(&page->_mapcount, 0); /* increment count (starts at -1) */ |
| 706 | __inc_zone_page_state(page, NR_ANON_PAGES); | ||
| 697 | __page_set_anon_rmap(page, vma, address); | 707 | __page_set_anon_rmap(page, vma, address); |
| 698 | if (page_evictable(page, vma)) | 708 | if (page_evictable(page, vma)) |
| 699 | lru_cache_add_lru(page, LRU_ACTIVE_ANON); | 709 | lru_cache_add_lru(page, LRU_ACTIVE_ANON); |
| @@ -760,20 +770,15 @@ void page_remove_rmap(struct page *page) | |||
| 760 | * Subfunctions of try_to_unmap: try_to_unmap_one called | 770 | * Subfunctions of try_to_unmap: try_to_unmap_one called |
| 761 | * repeatedly from either try_to_unmap_anon or try_to_unmap_file. | 771 | * repeatedly from either try_to_unmap_anon or try_to_unmap_file. |
| 762 | */ | 772 | */ |
| 763 | static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | 773 | int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, |
| 764 | enum ttu_flags flags) | 774 | unsigned long address, enum ttu_flags flags) |
| 765 | { | 775 | { |
| 766 | struct mm_struct *mm = vma->vm_mm; | 776 | struct mm_struct *mm = vma->vm_mm; |
| 767 | unsigned long address; | ||
| 768 | pte_t *pte; | 777 | pte_t *pte; |
| 769 | pte_t pteval; | 778 | pte_t pteval; |
| 770 | spinlock_t *ptl; | 779 | spinlock_t *ptl; |
| 771 | int ret = SWAP_AGAIN; | 780 | int ret = SWAP_AGAIN; |
| 772 | 781 | ||
| 773 | address = vma_address(page, vma); | ||
| 774 | if (address == -EFAULT) | ||
| 775 | goto out; | ||
| 776 | |||
| 777 | pte = page_check_address(page, mm, address, &ptl, 0); | 782 | pte = page_check_address(page, mm, address, &ptl, 0); |
| 778 | if (!pte) | 783 | if (!pte) |
| 779 | goto out; | 784 | goto out; |
| @@ -784,10 +789,11 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
| 784 | * skipped over this mm) then we should reactivate it. | 789 | * skipped over this mm) then we should reactivate it. |
| 785 | */ | 790 | */ |
| 786 | if (!(flags & TTU_IGNORE_MLOCK)) { | 791 | if (!(flags & TTU_IGNORE_MLOCK)) { |
| 787 | if (vma->vm_flags & VM_LOCKED) { | 792 | if (vma->vm_flags & VM_LOCKED) |
| 788 | ret = SWAP_MLOCK; | 793 | goto out_mlock; |
| 794 | |||
| 795 | if (TTU_ACTION(flags) == TTU_MUNLOCK) | ||
| 789 | goto out_unmap; | 796 | goto out_unmap; |
| 790 | } | ||
| 791 | } | 797 | } |
| 792 | if (!(flags & TTU_IGNORE_ACCESS)) { | 798 | if (!(flags & TTU_IGNORE_ACCESS)) { |
| 793 | if (ptep_clear_flush_young_notify(vma, address, pte)) { | 799 | if (ptep_clear_flush_young_notify(vma, address, pte)) { |
| @@ -822,7 +828,11 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
| 822 | * Store the swap location in the pte. | 828 | * Store the swap location in the pte. |
| 823 | * See handle_pte_fault() ... | 829 | * See handle_pte_fault() ... |
| 824 | */ | 830 | */ |
| 825 | swap_duplicate(entry); | 831 | if (swap_duplicate(entry) < 0) { |
| 832 | set_pte_at(mm, address, pte, pteval); | ||
| 833 | ret = SWAP_FAIL; | ||
| 834 | goto out_unmap; | ||
| 835 | } | ||
| 826 | if (list_empty(&mm->mmlist)) { | 836 | if (list_empty(&mm->mmlist)) { |
| 827 | spin_lock(&mmlist_lock); | 837 | spin_lock(&mmlist_lock); |
| 828 | if (list_empty(&mm->mmlist)) | 838 | if (list_empty(&mm->mmlist)) |
| @@ -849,7 +859,6 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
| 849 | } else | 859 | } else |
| 850 | dec_mm_counter(mm, file_rss); | 860 | dec_mm_counter(mm, file_rss); |
| 851 | 861 | ||
| 852 | |||
| 853 | page_remove_rmap(page); | 862 | page_remove_rmap(page); |
| 854 | page_cache_release(page); | 863 | page_cache_release(page); |
| 855 | 864 | ||
| @@ -857,6 +866,27 @@ out_unmap: | |||
| 857 | pte_unmap_unlock(pte, ptl); | 866 | pte_unmap_unlock(pte, ptl); |
| 858 | out: | 867 | out: |
| 859 | return ret; | 868 | return ret; |
| 869 | |||
| 870 | out_mlock: | ||
| 871 | pte_unmap_unlock(pte, ptl); | ||
| 872 | |||
| 873 | |||
| 874 | /* | ||
| 875 | * We need mmap_sem locking, Otherwise VM_LOCKED check makes | ||
| 876 | * unstable result and race. Plus, We can't wait here because | ||
| 877 | * we now hold anon_vma->lock or mapping->i_mmap_lock. | ||
| 878 | * if trylock failed, the page remain in evictable lru and later | ||
| 879 | * vmscan could retry to move the page to unevictable lru if the | ||
| 880 | * page is actually mlocked. | ||
| 881 | */ | ||
| 882 | if (down_read_trylock(&vma->vm_mm->mmap_sem)) { | ||
| 883 | if (vma->vm_flags & VM_LOCKED) { | ||
| 884 | mlock_vma_page(page); | ||
| 885 | ret = SWAP_MLOCK; | ||
| 886 | } | ||
| 887 | up_read(&vma->vm_mm->mmap_sem); | ||
| 888 | } | ||
| 889 | return ret; | ||
| 860 | } | 890 | } |
| 861 | 891 | ||
| 862 | /* | 892 | /* |
| @@ -922,11 +952,10 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, | |||
| 922 | return ret; | 952 | return ret; |
| 923 | 953 | ||
| 924 | /* | 954 | /* |
| 925 | * MLOCK_PAGES => feature is configured. | 955 | * If we can acquire the mmap_sem for read, and vma is VM_LOCKED, |
| 926 | * if we can acquire the mmap_sem for read, and vma is VM_LOCKED, | ||
| 927 | * keep the sem while scanning the cluster for mlocking pages. | 956 | * keep the sem while scanning the cluster for mlocking pages. |
| 928 | */ | 957 | */ |
| 929 | if (MLOCK_PAGES && down_read_trylock(&vma->vm_mm->mmap_sem)) { | 958 | if (down_read_trylock(&vma->vm_mm->mmap_sem)) { |
| 930 | locked_vma = (vma->vm_flags & VM_LOCKED); | 959 | locked_vma = (vma->vm_flags & VM_LOCKED); |
| 931 | if (!locked_vma) | 960 | if (!locked_vma) |
| 932 | up_read(&vma->vm_mm->mmap_sem); /* don't need it */ | 961 | up_read(&vma->vm_mm->mmap_sem); /* don't need it */ |
| @@ -976,29 +1005,11 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, | |||
| 976 | return ret; | 1005 | return ret; |
| 977 | } | 1006 | } |
| 978 | 1007 | ||
| 979 | /* | ||
| 980 | * common handling for pages mapped in VM_LOCKED vmas | ||
| 981 | */ | ||
| 982 | static int try_to_mlock_page(struct page *page, struct vm_area_struct *vma) | ||
| 983 | { | ||
| 984 | int mlocked = 0; | ||
| 985 | |||
| 986 | if (down_read_trylock(&vma->vm_mm->mmap_sem)) { | ||
| 987 | if (vma->vm_flags & VM_LOCKED) { | ||
| 988 | mlock_vma_page(page); | ||
| 989 | mlocked++; /* really mlocked the page */ | ||
| 990 | } | ||
| 991 | up_read(&vma->vm_mm->mmap_sem); | ||
| 992 | } | ||
| 993 | return mlocked; | ||
| 994 | } | ||
| 995 | |||
| 996 | /** | 1008 | /** |
| 997 | * try_to_unmap_anon - unmap or unlock anonymous page using the object-based | 1009 | * try_to_unmap_anon - unmap or unlock anonymous page using the object-based |
| 998 | * rmap method | 1010 | * rmap method |
| 999 | * @page: the page to unmap/unlock | 1011 | * @page: the page to unmap/unlock |
| 1000 | * @unlock: request for unlock rather than unmap [unlikely] | 1012 | * @flags: action and flags |
| 1001 | * @migration: unmapping for migration - ignored if @unlock | ||
| 1002 | * | 1013 | * |
| 1003 | * Find all the mappings of a page using the mapping pointer and the vma chains | 1014 | * Find all the mappings of a page using the mapping pointer and the vma chains |
| 1004 | * contained in the anon_vma struct it points to. | 1015 | * contained in the anon_vma struct it points to. |
| @@ -1014,42 +1025,22 @@ static int try_to_unmap_anon(struct page *page, enum ttu_flags flags) | |||
| 1014 | { | 1025 | { |
| 1015 | struct anon_vma *anon_vma; | 1026 | struct anon_vma *anon_vma; |
| 1016 | struct vm_area_struct *vma; | 1027 | struct vm_area_struct *vma; |
| 1017 | unsigned int mlocked = 0; | ||
| 1018 | int ret = SWAP_AGAIN; | 1028 | int ret = SWAP_AGAIN; |
| 1019 | int unlock = TTU_ACTION(flags) == TTU_MUNLOCK; | ||
| 1020 | |||
| 1021 | if (MLOCK_PAGES && unlikely(unlock)) | ||
| 1022 | ret = SWAP_SUCCESS; /* default for try_to_munlock() */ | ||
| 1023 | 1029 | ||
| 1024 | anon_vma = page_lock_anon_vma(page); | 1030 | anon_vma = page_lock_anon_vma(page); |
| 1025 | if (!anon_vma) | 1031 | if (!anon_vma) |
| 1026 | return ret; | 1032 | return ret; |
| 1027 | 1033 | ||
| 1028 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | 1034 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { |
| 1029 | if (MLOCK_PAGES && unlikely(unlock)) { | 1035 | unsigned long address = vma_address(page, vma); |
| 1030 | if (!((vma->vm_flags & VM_LOCKED) && | 1036 | if (address == -EFAULT) |
| 1031 | page_mapped_in_vma(page, vma))) | 1037 | continue; |
| 1032 | continue; /* must visit all unlocked vmas */ | 1038 | ret = try_to_unmap_one(page, vma, address, flags); |
| 1033 | ret = SWAP_MLOCK; /* saw at least one mlocked vma */ | 1039 | if (ret != SWAP_AGAIN || !page_mapped(page)) |
| 1034 | } else { | 1040 | break; |
| 1035 | ret = try_to_unmap_one(page, vma, flags); | ||
| 1036 | if (ret == SWAP_FAIL || !page_mapped(page)) | ||
| 1037 | break; | ||
| 1038 | } | ||
| 1039 | if (ret == SWAP_MLOCK) { | ||
| 1040 | mlocked = try_to_mlock_page(page, vma); | ||
| 1041 | if (mlocked) | ||
| 1042 | break; /* stop if actually mlocked page */ | ||
| 1043 | } | ||
| 1044 | } | 1041 | } |
| 1045 | 1042 | ||
| 1046 | page_unlock_anon_vma(anon_vma); | 1043 | page_unlock_anon_vma(anon_vma); |
| 1047 | |||
| 1048 | if (mlocked) | ||
| 1049 | ret = SWAP_MLOCK; /* actually mlocked the page */ | ||
| 1050 | else if (ret == SWAP_MLOCK) | ||
| 1051 | ret = SWAP_AGAIN; /* saw VM_LOCKED vma */ | ||
| 1052 | |||
| 1053 | return ret; | 1044 | return ret; |
| 1054 | } | 1045 | } |
| 1055 | 1046 | ||
| @@ -1079,48 +1070,30 @@ static int try_to_unmap_file(struct page *page, enum ttu_flags flags) | |||
| 1079 | unsigned long max_nl_cursor = 0; | 1070 | unsigned long max_nl_cursor = 0; |
| 1080 | unsigned long max_nl_size = 0; | 1071 | unsigned long max_nl_size = 0; |
| 1081 | unsigned int mapcount; | 1072 | unsigned int mapcount; |
| 1082 | unsigned int mlocked = 0; | ||
| 1083 | int unlock = TTU_ACTION(flags) == TTU_MUNLOCK; | ||
| 1084 | |||
| 1085 | if (MLOCK_PAGES && unlikely(unlock)) | ||
| 1086 | ret = SWAP_SUCCESS; /* default for try_to_munlock() */ | ||
| 1087 | 1073 | ||
| 1088 | spin_lock(&mapping->i_mmap_lock); | 1074 | spin_lock(&mapping->i_mmap_lock); |
| 1089 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | 1075 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { |
| 1090 | if (MLOCK_PAGES && unlikely(unlock)) { | 1076 | unsigned long address = vma_address(page, vma); |
| 1091 | if (!((vma->vm_flags & VM_LOCKED) && | 1077 | if (address == -EFAULT) |
| 1092 | page_mapped_in_vma(page, vma))) | 1078 | continue; |
| 1093 | continue; /* must visit all vmas */ | 1079 | ret = try_to_unmap_one(page, vma, address, flags); |
| 1094 | ret = SWAP_MLOCK; | 1080 | if (ret != SWAP_AGAIN || !page_mapped(page)) |
| 1095 | } else { | 1081 | goto out; |
| 1096 | ret = try_to_unmap_one(page, vma, flags); | ||
| 1097 | if (ret == SWAP_FAIL || !page_mapped(page)) | ||
| 1098 | goto out; | ||
| 1099 | } | ||
| 1100 | if (ret == SWAP_MLOCK) { | ||
| 1101 | mlocked = try_to_mlock_page(page, vma); | ||
| 1102 | if (mlocked) | ||
| 1103 | break; /* stop if actually mlocked page */ | ||
| 1104 | } | ||
| 1105 | } | 1082 | } |
| 1106 | 1083 | ||
| 1107 | if (mlocked) | 1084 | if (list_empty(&mapping->i_mmap_nonlinear)) |
| 1108 | goto out; | 1085 | goto out; |
| 1109 | 1086 | ||
| 1110 | if (list_empty(&mapping->i_mmap_nonlinear)) | 1087 | /* |
| 1088 | * We don't bother to try to find the munlocked page in nonlinears. | ||
| 1089 | * It's costly. Instead, later, page reclaim logic may call | ||
| 1090 | * try_to_unmap(TTU_MUNLOCK) and recover PG_mlocked lazily. | ||
| 1091 | */ | ||
| 1092 | if (TTU_ACTION(flags) == TTU_MUNLOCK) | ||
| 1111 | goto out; | 1093 | goto out; |
| 1112 | 1094 | ||
| 1113 | list_for_each_entry(vma, &mapping->i_mmap_nonlinear, | 1095 | list_for_each_entry(vma, &mapping->i_mmap_nonlinear, |
| 1114 | shared.vm_set.list) { | 1096 | shared.vm_set.list) { |
| 1115 | if (MLOCK_PAGES && unlikely(unlock)) { | ||
| 1116 | if (!(vma->vm_flags & VM_LOCKED)) | ||
| 1117 | continue; /* must visit all vmas */ | ||
| 1118 | ret = SWAP_MLOCK; /* leave mlocked == 0 */ | ||
| 1119 | goto out; /* no need to look further */ | ||
| 1120 | } | ||
| 1121 | if (!MLOCK_PAGES && !(flags & TTU_IGNORE_MLOCK) && | ||
| 1122 | (vma->vm_flags & VM_LOCKED)) | ||
| 1123 | continue; | ||
| 1124 | cursor = (unsigned long) vma->vm_private_data; | 1097 | cursor = (unsigned long) vma->vm_private_data; |
| 1125 | if (cursor > max_nl_cursor) | 1098 | if (cursor > max_nl_cursor) |
| 1126 | max_nl_cursor = cursor; | 1099 | max_nl_cursor = cursor; |
| @@ -1153,16 +1126,12 @@ static int try_to_unmap_file(struct page *page, enum ttu_flags flags) | |||
| 1153 | do { | 1126 | do { |
| 1154 | list_for_each_entry(vma, &mapping->i_mmap_nonlinear, | 1127 | list_for_each_entry(vma, &mapping->i_mmap_nonlinear, |
| 1155 | shared.vm_set.list) { | 1128 | shared.vm_set.list) { |
| 1156 | if (!MLOCK_PAGES && !(flags & TTU_IGNORE_MLOCK) && | ||
| 1157 | (vma->vm_flags & VM_LOCKED)) | ||
| 1158 | continue; | ||
| 1159 | cursor = (unsigned long) vma->vm_private_data; | 1129 | cursor = (unsigned long) vma->vm_private_data; |
| 1160 | while ( cursor < max_nl_cursor && | 1130 | while ( cursor < max_nl_cursor && |
| 1161 | cursor < vma->vm_end - vma->vm_start) { | 1131 | cursor < vma->vm_end - vma->vm_start) { |
| 1162 | ret = try_to_unmap_cluster(cursor, &mapcount, | 1132 | if (try_to_unmap_cluster(cursor, &mapcount, |
| 1163 | vma, page); | 1133 | vma, page) == SWAP_MLOCK) |
| 1164 | if (ret == SWAP_MLOCK) | 1134 | ret = SWAP_MLOCK; |
| 1165 | mlocked = 2; /* to return below */ | ||
| 1166 | cursor += CLUSTER_SIZE; | 1135 | cursor += CLUSTER_SIZE; |
| 1167 | vma->vm_private_data = (void *) cursor; | 1136 | vma->vm_private_data = (void *) cursor; |
| 1168 | if ((int)mapcount <= 0) | 1137 | if ((int)mapcount <= 0) |
| @@ -1183,10 +1152,6 @@ static int try_to_unmap_file(struct page *page, enum ttu_flags flags) | |||
| 1183 | vma->vm_private_data = NULL; | 1152 | vma->vm_private_data = NULL; |
| 1184 | out: | 1153 | out: |
| 1185 | spin_unlock(&mapping->i_mmap_lock); | 1154 | spin_unlock(&mapping->i_mmap_lock); |
| 1186 | if (mlocked) | ||
| 1187 | ret = SWAP_MLOCK; /* actually mlocked the page */ | ||
| 1188 | else if (ret == SWAP_MLOCK) | ||
| 1189 | ret = SWAP_AGAIN; /* saw VM_LOCKED vma */ | ||
| 1190 | return ret; | 1155 | return ret; |
| 1191 | } | 1156 | } |
| 1192 | 1157 | ||
| @@ -1210,7 +1175,9 @@ int try_to_unmap(struct page *page, enum ttu_flags flags) | |||
| 1210 | 1175 | ||
| 1211 | BUG_ON(!PageLocked(page)); | 1176 | BUG_ON(!PageLocked(page)); |
| 1212 | 1177 | ||
| 1213 | if (PageAnon(page)) | 1178 | if (unlikely(PageKsm(page))) |
| 1179 | ret = try_to_unmap_ksm(page, flags); | ||
| 1180 | else if (PageAnon(page)) | ||
| 1214 | ret = try_to_unmap_anon(page, flags); | 1181 | ret = try_to_unmap_anon(page, flags); |
| 1215 | else | 1182 | else |
| 1216 | ret = try_to_unmap_file(page, flags); | 1183 | ret = try_to_unmap_file(page, flags); |
| @@ -1229,17 +1196,98 @@ int try_to_unmap(struct page *page, enum ttu_flags flags) | |||
| 1229 | * | 1196 | * |
| 1230 | * Return values are: | 1197 | * Return values are: |
| 1231 | * | 1198 | * |
| 1232 | * SWAP_SUCCESS - no vma's holding page mlocked. | 1199 | * SWAP_AGAIN - no vma is holding page mlocked, or, |
| 1233 | * SWAP_AGAIN - page mapped in mlocked vma -- couldn't acquire mmap sem | 1200 | * SWAP_AGAIN - page mapped in mlocked vma -- couldn't acquire mmap sem |
| 1201 | * SWAP_FAIL - page cannot be located at present | ||
| 1234 | * SWAP_MLOCK - page is now mlocked. | 1202 | * SWAP_MLOCK - page is now mlocked. |
| 1235 | */ | 1203 | */ |
| 1236 | int try_to_munlock(struct page *page) | 1204 | int try_to_munlock(struct page *page) |
| 1237 | { | 1205 | { |
| 1238 | VM_BUG_ON(!PageLocked(page) || PageLRU(page)); | 1206 | VM_BUG_ON(!PageLocked(page) || PageLRU(page)); |
| 1239 | 1207 | ||
| 1240 | if (PageAnon(page)) | 1208 | if (unlikely(PageKsm(page))) |
| 1209 | return try_to_unmap_ksm(page, TTU_MUNLOCK); | ||
| 1210 | else if (PageAnon(page)) | ||
| 1241 | return try_to_unmap_anon(page, TTU_MUNLOCK); | 1211 | return try_to_unmap_anon(page, TTU_MUNLOCK); |
| 1242 | else | 1212 | else |
| 1243 | return try_to_unmap_file(page, TTU_MUNLOCK); | 1213 | return try_to_unmap_file(page, TTU_MUNLOCK); |
| 1244 | } | 1214 | } |
| 1245 | 1215 | ||
| 1216 | #ifdef CONFIG_MIGRATION | ||
| 1217 | /* | ||
| 1218 | * rmap_walk() and its helpers rmap_walk_anon() and rmap_walk_file(): | ||
| 1219 | * Called by migrate.c to remove migration ptes, but might be used more later. | ||
| 1220 | */ | ||
| 1221 | static int rmap_walk_anon(struct page *page, int (*rmap_one)(struct page *, | ||
| 1222 | struct vm_area_struct *, unsigned long, void *), void *arg) | ||
| 1223 | { | ||
| 1224 | struct anon_vma *anon_vma; | ||
| 1225 | struct vm_area_struct *vma; | ||
| 1226 | int ret = SWAP_AGAIN; | ||
| 1227 | |||
| 1228 | /* | ||
| 1229 | * Note: remove_migration_ptes() cannot use page_lock_anon_vma() | ||
| 1230 | * because that depends on page_mapped(); but not all its usages | ||
| 1231 | * are holding mmap_sem, which also gave the necessary guarantee | ||
| 1232 | * (that this anon_vma's slab has not already been destroyed). | ||
| 1233 | * This needs to be reviewed later: avoiding page_lock_anon_vma() | ||
| 1234 | * is risky, and currently limits the usefulness of rmap_walk(). | ||
| 1235 | */ | ||
| 1236 | anon_vma = page_anon_vma(page); | ||
| 1237 | if (!anon_vma) | ||
| 1238 | return ret; | ||
| 1239 | spin_lock(&anon_vma->lock); | ||
| 1240 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { | ||
| 1241 | unsigned long address = vma_address(page, vma); | ||
| 1242 | if (address == -EFAULT) | ||
| 1243 | continue; | ||
| 1244 | ret = rmap_one(page, vma, address, arg); | ||
| 1245 | if (ret != SWAP_AGAIN) | ||
| 1246 | break; | ||
| 1247 | } | ||
| 1248 | spin_unlock(&anon_vma->lock); | ||
| 1249 | return ret; | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | static int rmap_walk_file(struct page *page, int (*rmap_one)(struct page *, | ||
| 1253 | struct vm_area_struct *, unsigned long, void *), void *arg) | ||
| 1254 | { | ||
| 1255 | struct address_space *mapping = page->mapping; | ||
| 1256 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | ||
| 1257 | struct vm_area_struct *vma; | ||
| 1258 | struct prio_tree_iter iter; | ||
| 1259 | int ret = SWAP_AGAIN; | ||
| 1260 | |||
| 1261 | if (!mapping) | ||
| 1262 | return ret; | ||
| 1263 | spin_lock(&mapping->i_mmap_lock); | ||
| 1264 | vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { | ||
| 1265 | unsigned long address = vma_address(page, vma); | ||
| 1266 | if (address == -EFAULT) | ||
| 1267 | continue; | ||
| 1268 | ret = rmap_one(page, vma, address, arg); | ||
| 1269 | if (ret != SWAP_AGAIN) | ||
| 1270 | break; | ||
| 1271 | } | ||
| 1272 | /* | ||
| 1273 | * No nonlinear handling: being always shared, nonlinear vmas | ||
| 1274 | * never contain migration ptes. Decide what to do about this | ||
| 1275 | * limitation to linear when we need rmap_walk() on nonlinear. | ||
| 1276 | */ | ||
| 1277 | spin_unlock(&mapping->i_mmap_lock); | ||
| 1278 | return ret; | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | int rmap_walk(struct page *page, int (*rmap_one)(struct page *, | ||
| 1282 | struct vm_area_struct *, unsigned long, void *), void *arg) | ||
| 1283 | { | ||
| 1284 | VM_BUG_ON(!PageLocked(page)); | ||
| 1285 | |||
| 1286 | if (unlikely(PageKsm(page))) | ||
| 1287 | return rmap_walk_ksm(page, rmap_one, arg); | ||
| 1288 | else if (PageAnon(page)) | ||
| 1289 | return rmap_walk_anon(page, rmap_one, arg); | ||
| 1290 | else | ||
| 1291 | return rmap_walk_file(page, rmap_one, arg); | ||
| 1292 | } | ||
| 1293 | #endif /* CONFIG_MIGRATION */ | ||
diff --git a/mm/shmem.c b/mm/shmem.c index 356dd99566ec..4fb41c83daca 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -1017,7 +1017,14 @@ int shmem_unuse(swp_entry_t entry, struct page *page) | |||
| 1017 | goto out; | 1017 | goto out; |
| 1018 | } | 1018 | } |
| 1019 | mutex_unlock(&shmem_swaplist_mutex); | 1019 | mutex_unlock(&shmem_swaplist_mutex); |
| 1020 | out: return found; /* 0 or 1 or -ENOMEM */ | 1020 | /* |
| 1021 | * Can some race bring us here? We've been holding page lock, | ||
| 1022 | * so I think not; but would rather try again later than BUG() | ||
| 1023 | */ | ||
| 1024 | unlock_page(page); | ||
| 1025 | page_cache_release(page); | ||
| 1026 | out: | ||
| 1027 | return (found < 0) ? found : 0; | ||
| 1021 | } | 1028 | } |
| 1022 | 1029 | ||
| 1023 | /* | 1030 | /* |
| @@ -1080,7 +1087,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
| 1080 | else | 1087 | else |
| 1081 | inode = NULL; | 1088 | inode = NULL; |
| 1082 | spin_unlock(&info->lock); | 1089 | spin_unlock(&info->lock); |
| 1083 | swap_duplicate(swap); | 1090 | swap_shmem_alloc(swap); |
| 1084 | BUG_ON(page_mapped(page)); | 1091 | BUG_ON(page_mapped(page)); |
| 1085 | page_cache_release(page); /* pagecache ref */ | 1092 | page_cache_release(page); /* pagecache ref */ |
| 1086 | swap_writepage(page, wbc); | 1093 | swap_writepage(page, wbc); |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 9c590eef7912..6c0585b16418 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/ksm.h> | ||
| 25 | #include <linux/rmap.h> | 26 | #include <linux/rmap.h> |
| 26 | #include <linux/security.h> | 27 | #include <linux/security.h> |
| 27 | #include <linux/backing-dev.h> | 28 | #include <linux/backing-dev.h> |
| @@ -35,11 +36,15 @@ | |||
| 35 | #include <linux/swapops.h> | 36 | #include <linux/swapops.h> |
| 36 | #include <linux/page_cgroup.h> | 37 | #include <linux/page_cgroup.h> |
| 37 | 38 | ||
| 39 | static bool swap_count_continued(struct swap_info_struct *, pgoff_t, | ||
| 40 | unsigned char); | ||
| 41 | static void free_swap_count_continuations(struct swap_info_struct *); | ||
| 42 | static sector_t map_swap_entry(swp_entry_t, struct block_device**); | ||
| 43 | |||
| 38 | static DEFINE_SPINLOCK(swap_lock); | 44 | static DEFINE_SPINLOCK(swap_lock); |
| 39 | static unsigned int nr_swapfiles; | 45 | static unsigned int nr_swapfiles; |
| 40 | long nr_swap_pages; | 46 | long nr_swap_pages; |
| 41 | long total_swap_pages; | 47 | long total_swap_pages; |
| 42 | static int swap_overflow; | ||
| 43 | static int least_priority; | 48 | static int least_priority; |
| 44 | 49 | ||
| 45 | static const char Bad_file[] = "Bad swap file entry "; | 50 | static const char Bad_file[] = "Bad swap file entry "; |
| @@ -49,42 +54,20 @@ static const char Unused_offset[] = "Unused swap offset entry "; | |||
| 49 | 54 | ||
| 50 | static struct swap_list_t swap_list = {-1, -1}; | 55 | static struct swap_list_t swap_list = {-1, -1}; |
| 51 | 56 | ||
| 52 | static struct swap_info_struct swap_info[MAX_SWAPFILES]; | 57 | static struct swap_info_struct *swap_info[MAX_SWAPFILES]; |
| 53 | 58 | ||
| 54 | static DEFINE_MUTEX(swapon_mutex); | 59 | static DEFINE_MUTEX(swapon_mutex); |
| 55 | 60 | ||
| 56 | /* For reference count accounting in swap_map */ | 61 | static inline unsigned char swap_count(unsigned char ent) |
| 57 | /* enum for swap_map[] handling. internal use only */ | ||
| 58 | enum { | ||
| 59 | SWAP_MAP = 0, /* ops for reference from swap users */ | ||
| 60 | SWAP_CACHE, /* ops for reference from swap cache */ | ||
| 61 | }; | ||
| 62 | |||
| 63 | static inline int swap_count(unsigned short ent) | ||
| 64 | { | ||
| 65 | return ent & SWAP_COUNT_MASK; | ||
| 66 | } | ||
| 67 | |||
| 68 | static inline bool swap_has_cache(unsigned short ent) | ||
| 69 | { | 62 | { |
| 70 | return !!(ent & SWAP_HAS_CACHE); | 63 | return ent & ~SWAP_HAS_CACHE; /* may include SWAP_HAS_CONT flag */ |
| 71 | } | 64 | } |
| 72 | 65 | ||
| 73 | static inline unsigned short encode_swapmap(int count, bool has_cache) | 66 | /* returns 1 if swap entry is freed */ |
| 74 | { | ||
| 75 | unsigned short ret = count; | ||
| 76 | |||
| 77 | if (has_cache) | ||
| 78 | return SWAP_HAS_CACHE | ret; | ||
| 79 | return ret; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* returnes 1 if swap entry is freed */ | ||
| 83 | static int | 67 | static int |
| 84 | __try_to_reclaim_swap(struct swap_info_struct *si, unsigned long offset) | 68 | __try_to_reclaim_swap(struct swap_info_struct *si, unsigned long offset) |
| 85 | { | 69 | { |
| 86 | int type = si - swap_info; | 70 | swp_entry_t entry = swp_entry(si->type, offset); |
| 87 | swp_entry_t entry = swp_entry(type, offset); | ||
| 88 | struct page *page; | 71 | struct page *page; |
| 89 | int ret = 0; | 72 | int ret = 0; |
| 90 | 73 | ||
| @@ -120,7 +103,7 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) | |||
| 120 | down_read(&swap_unplug_sem); | 103 | down_read(&swap_unplug_sem); |
| 121 | entry.val = page_private(page); | 104 | entry.val = page_private(page); |
| 122 | if (PageSwapCache(page)) { | 105 | if (PageSwapCache(page)) { |
| 123 | struct block_device *bdev = swap_info[swp_type(entry)].bdev; | 106 | struct block_device *bdev = swap_info[swp_type(entry)]->bdev; |
| 124 | struct backing_dev_info *bdi; | 107 | struct backing_dev_info *bdi; |
| 125 | 108 | ||
| 126 | /* | 109 | /* |
| @@ -146,23 +129,28 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) | |||
| 146 | static int discard_swap(struct swap_info_struct *si) | 129 | static int discard_swap(struct swap_info_struct *si) |
| 147 | { | 130 | { |
| 148 | struct swap_extent *se; | 131 | struct swap_extent *se; |
| 132 | sector_t start_block; | ||
| 133 | sector_t nr_blocks; | ||
| 149 | int err = 0; | 134 | int err = 0; |
| 150 | 135 | ||
| 151 | list_for_each_entry(se, &si->extent_list, list) { | 136 | /* Do not discard the swap header page! */ |
| 152 | sector_t start_block = se->start_block << (PAGE_SHIFT - 9); | 137 | se = &si->first_swap_extent; |
| 153 | sector_t nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9); | 138 | start_block = (se->start_block + 1) << (PAGE_SHIFT - 9); |
| 139 | nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9); | ||
| 140 | if (nr_blocks) { | ||
| 141 | err = blkdev_issue_discard(si->bdev, start_block, | ||
| 142 | nr_blocks, GFP_KERNEL, DISCARD_FL_BARRIER); | ||
| 143 | if (err) | ||
| 144 | return err; | ||
| 145 | cond_resched(); | ||
| 146 | } | ||
| 154 | 147 | ||
| 155 | if (se->start_page == 0) { | 148 | list_for_each_entry(se, &si->first_swap_extent.list, list) { |
| 156 | /* Do not discard the swap header page! */ | 149 | start_block = se->start_block << (PAGE_SHIFT - 9); |
| 157 | start_block += 1 << (PAGE_SHIFT - 9); | 150 | nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9); |
| 158 | nr_blocks -= 1 << (PAGE_SHIFT - 9); | ||
| 159 | if (!nr_blocks) | ||
| 160 | continue; | ||
| 161 | } | ||
| 162 | 151 | ||
| 163 | err = blkdev_issue_discard(si->bdev, start_block, | 152 | err = blkdev_issue_discard(si->bdev, start_block, |
| 164 | nr_blocks, GFP_KERNEL, | 153 | nr_blocks, GFP_KERNEL, DISCARD_FL_BARRIER); |
| 165 | DISCARD_FL_BARRIER); | ||
| 166 | if (err) | 154 | if (err) |
| 167 | break; | 155 | break; |
| 168 | 156 | ||
| @@ -201,14 +189,11 @@ static void discard_swap_cluster(struct swap_info_struct *si, | |||
| 201 | start_block <<= PAGE_SHIFT - 9; | 189 | start_block <<= PAGE_SHIFT - 9; |
| 202 | nr_blocks <<= PAGE_SHIFT - 9; | 190 | nr_blocks <<= PAGE_SHIFT - 9; |
| 203 | if (blkdev_issue_discard(si->bdev, start_block, | 191 | if (blkdev_issue_discard(si->bdev, start_block, |
| 204 | nr_blocks, GFP_NOIO, | 192 | nr_blocks, GFP_NOIO, DISCARD_FL_BARRIER)) |
| 205 | DISCARD_FL_BARRIER)) | ||
| 206 | break; | 193 | break; |
| 207 | } | 194 | } |
| 208 | 195 | ||
| 209 | lh = se->list.next; | 196 | lh = se->list.next; |
| 210 | if (lh == &si->extent_list) | ||
| 211 | lh = lh->next; | ||
| 212 | se = list_entry(lh, struct swap_extent, list); | 197 | se = list_entry(lh, struct swap_extent, list); |
| 213 | } | 198 | } |
| 214 | } | 199 | } |
| @@ -223,7 +208,7 @@ static int wait_for_discard(void *word) | |||
| 223 | #define LATENCY_LIMIT 256 | 208 | #define LATENCY_LIMIT 256 |
| 224 | 209 | ||
| 225 | static inline unsigned long scan_swap_map(struct swap_info_struct *si, | 210 | static inline unsigned long scan_swap_map(struct swap_info_struct *si, |
| 226 | int cache) | 211 | unsigned char usage) |
| 227 | { | 212 | { |
| 228 | unsigned long offset; | 213 | unsigned long offset; |
| 229 | unsigned long scan_base; | 214 | unsigned long scan_base; |
| @@ -354,10 +339,7 @@ checks: | |||
| 354 | si->lowest_bit = si->max; | 339 | si->lowest_bit = si->max; |
| 355 | si->highest_bit = 0; | 340 | si->highest_bit = 0; |
| 356 | } | 341 | } |
| 357 | if (cache == SWAP_CACHE) /* at usual swap-out via vmscan.c */ | 342 | si->swap_map[offset] = usage; |
| 358 | si->swap_map[offset] = encode_swapmap(0, true); | ||
| 359 | else /* at suspend */ | ||
| 360 | si->swap_map[offset] = encode_swapmap(1, false); | ||
| 361 | si->cluster_next = offset + 1; | 343 | si->cluster_next = offset + 1; |
| 362 | si->flags -= SWP_SCANNING; | 344 | si->flags -= SWP_SCANNING; |
| 363 | 345 | ||
| @@ -467,10 +449,10 @@ swp_entry_t get_swap_page(void) | |||
| 467 | nr_swap_pages--; | 449 | nr_swap_pages--; |
| 468 | 450 | ||
| 469 | for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) { | 451 | for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) { |
| 470 | si = swap_info + type; | 452 | si = swap_info[type]; |
| 471 | next = si->next; | 453 | next = si->next; |
| 472 | if (next < 0 || | 454 | if (next < 0 || |
| 473 | (!wrapped && si->prio != swap_info[next].prio)) { | 455 | (!wrapped && si->prio != swap_info[next]->prio)) { |
| 474 | next = swap_list.head; | 456 | next = swap_list.head; |
| 475 | wrapped++; | 457 | wrapped++; |
| 476 | } | 458 | } |
| @@ -482,7 +464,7 @@ swp_entry_t get_swap_page(void) | |||
| 482 | 464 | ||
| 483 | swap_list.next = next; | 465 | swap_list.next = next; |
| 484 | /* This is called for allocating swap entry for cache */ | 466 | /* This is called for allocating swap entry for cache */ |
| 485 | offset = scan_swap_map(si, SWAP_CACHE); | 467 | offset = scan_swap_map(si, SWAP_HAS_CACHE); |
| 486 | if (offset) { | 468 | if (offset) { |
| 487 | spin_unlock(&swap_lock); | 469 | spin_unlock(&swap_lock); |
| 488 | return swp_entry(type, offset); | 470 | return swp_entry(type, offset); |
| @@ -503,11 +485,11 @@ swp_entry_t get_swap_page_of_type(int type) | |||
| 503 | pgoff_t offset; | 485 | pgoff_t offset; |
| 504 | 486 | ||
| 505 | spin_lock(&swap_lock); | 487 | spin_lock(&swap_lock); |
| 506 | si = swap_info + type; | 488 | si = swap_info[type]; |
| 507 | if (si->flags & SWP_WRITEOK) { | 489 | if (si && (si->flags & SWP_WRITEOK)) { |
| 508 | nr_swap_pages--; | 490 | nr_swap_pages--; |
| 509 | /* This is called for allocating swap entry, not cache */ | 491 | /* This is called for allocating swap entry, not cache */ |
| 510 | offset = scan_swap_map(si, SWAP_MAP); | 492 | offset = scan_swap_map(si, 1); |
| 511 | if (offset) { | 493 | if (offset) { |
| 512 | spin_unlock(&swap_lock); | 494 | spin_unlock(&swap_lock); |
| 513 | return swp_entry(type, offset); | 495 | return swp_entry(type, offset); |
| @@ -518,9 +500,9 @@ swp_entry_t get_swap_page_of_type(int type) | |||
| 518 | return (swp_entry_t) {0}; | 500 | return (swp_entry_t) {0}; |
| 519 | } | 501 | } |
| 520 | 502 | ||
| 521 | static struct swap_info_struct * swap_info_get(swp_entry_t entry) | 503 | static struct swap_info_struct *swap_info_get(swp_entry_t entry) |
| 522 | { | 504 | { |
| 523 | struct swap_info_struct * p; | 505 | struct swap_info_struct *p; |
| 524 | unsigned long offset, type; | 506 | unsigned long offset, type; |
| 525 | 507 | ||
| 526 | if (!entry.val) | 508 | if (!entry.val) |
| @@ -528,7 +510,7 @@ static struct swap_info_struct * swap_info_get(swp_entry_t entry) | |||
| 528 | type = swp_type(entry); | 510 | type = swp_type(entry); |
| 529 | if (type >= nr_swapfiles) | 511 | if (type >= nr_swapfiles) |
| 530 | goto bad_nofile; | 512 | goto bad_nofile; |
| 531 | p = & swap_info[type]; | 513 | p = swap_info[type]; |
| 532 | if (!(p->flags & SWP_USED)) | 514 | if (!(p->flags & SWP_USED)) |
| 533 | goto bad_device; | 515 | goto bad_device; |
| 534 | offset = swp_offset(entry); | 516 | offset = swp_offset(entry); |
| @@ -554,41 +536,56 @@ out: | |||
| 554 | return NULL; | 536 | return NULL; |
| 555 | } | 537 | } |
| 556 | 538 | ||
| 557 | static int swap_entry_free(struct swap_info_struct *p, | 539 | static unsigned char swap_entry_free(struct swap_info_struct *p, |
| 558 | swp_entry_t ent, int cache) | 540 | swp_entry_t entry, unsigned char usage) |
| 559 | { | 541 | { |
| 560 | unsigned long offset = swp_offset(ent); | 542 | unsigned long offset = swp_offset(entry); |
| 561 | int count = swap_count(p->swap_map[offset]); | 543 | unsigned char count; |
| 562 | bool has_cache; | 544 | unsigned char has_cache; |
| 563 | 545 | ||
| 564 | has_cache = swap_has_cache(p->swap_map[offset]); | 546 | count = p->swap_map[offset]; |
| 547 | has_cache = count & SWAP_HAS_CACHE; | ||
| 548 | count &= ~SWAP_HAS_CACHE; | ||
| 565 | 549 | ||
| 566 | if (cache == SWAP_MAP) { /* dropping usage count of swap */ | 550 | if (usage == SWAP_HAS_CACHE) { |
| 567 | if (count < SWAP_MAP_MAX) { | ||
| 568 | count--; | ||
| 569 | p->swap_map[offset] = encode_swapmap(count, has_cache); | ||
| 570 | } | ||
| 571 | } else { /* dropping swap cache flag */ | ||
| 572 | VM_BUG_ON(!has_cache); | 551 | VM_BUG_ON(!has_cache); |
| 573 | p->swap_map[offset] = encode_swapmap(count, false); | 552 | has_cache = 0; |
| 574 | 553 | } else if (count == SWAP_MAP_SHMEM) { | |
| 554 | /* | ||
| 555 | * Or we could insist on shmem.c using a special | ||
| 556 | * swap_shmem_free() and free_shmem_swap_and_cache()... | ||
| 557 | */ | ||
| 558 | count = 0; | ||
| 559 | } else if ((count & ~COUNT_CONTINUED) <= SWAP_MAP_MAX) { | ||
| 560 | if (count == COUNT_CONTINUED) { | ||
| 561 | if (swap_count_continued(p, offset, count)) | ||
| 562 | count = SWAP_MAP_MAX | COUNT_CONTINUED; | ||
| 563 | else | ||
| 564 | count = SWAP_MAP_MAX; | ||
| 565 | } else | ||
| 566 | count--; | ||
| 575 | } | 567 | } |
| 576 | /* return code. */ | 568 | |
| 577 | count = p->swap_map[offset]; | 569 | if (!count) |
| 570 | mem_cgroup_uncharge_swap(entry); | ||
| 571 | |||
| 572 | usage = count | has_cache; | ||
| 573 | p->swap_map[offset] = usage; | ||
| 574 | |||
| 578 | /* free if no reference */ | 575 | /* free if no reference */ |
| 579 | if (!count) { | 576 | if (!usage) { |
| 580 | if (offset < p->lowest_bit) | 577 | if (offset < p->lowest_bit) |
| 581 | p->lowest_bit = offset; | 578 | p->lowest_bit = offset; |
| 582 | if (offset > p->highest_bit) | 579 | if (offset > p->highest_bit) |
| 583 | p->highest_bit = offset; | 580 | p->highest_bit = offset; |
| 584 | if (p->prio > swap_info[swap_list.next].prio) | 581 | if (swap_list.next >= 0 && |
| 585 | swap_list.next = p - swap_info; | 582 | p->prio > swap_info[swap_list.next]->prio) |
| 583 | swap_list.next = p->type; | ||
| 586 | nr_swap_pages++; | 584 | nr_swap_pages++; |
| 587 | p->inuse_pages--; | 585 | p->inuse_pages--; |
| 588 | } | 586 | } |
| 589 | if (!swap_count(count)) | 587 | |
| 590 | mem_cgroup_uncharge_swap(ent); | 588 | return usage; |
| 591 | return count; | ||
| 592 | } | 589 | } |
| 593 | 590 | ||
| 594 | /* | 591 | /* |
| @@ -597,11 +594,11 @@ static int swap_entry_free(struct swap_info_struct *p, | |||
| 597 | */ | 594 | */ |
| 598 | void swap_free(swp_entry_t entry) | 595 | void swap_free(swp_entry_t entry) |
| 599 | { | 596 | { |
| 600 | struct swap_info_struct * p; | 597 | struct swap_info_struct *p; |
| 601 | 598 | ||
| 602 | p = swap_info_get(entry); | 599 | p = swap_info_get(entry); |
| 603 | if (p) { | 600 | if (p) { |
| 604 | swap_entry_free(p, entry, SWAP_MAP); | 601 | swap_entry_free(p, entry, 1); |
| 605 | spin_unlock(&swap_lock); | 602 | spin_unlock(&swap_lock); |
| 606 | } | 603 | } |
| 607 | } | 604 | } |
| @@ -612,26 +609,21 @@ void swap_free(swp_entry_t entry) | |||
| 612 | void swapcache_free(swp_entry_t entry, struct page *page) | 609 | void swapcache_free(swp_entry_t entry, struct page *page) |
| 613 | { | 610 | { |
| 614 | struct swap_info_struct *p; | 611 | struct swap_info_struct *p; |
| 615 | int ret; | 612 | unsigned char count; |
| 616 | 613 | ||
| 617 | p = swap_info_get(entry); | 614 | p = swap_info_get(entry); |
| 618 | if (p) { | 615 | if (p) { |
| 619 | ret = swap_entry_free(p, entry, SWAP_CACHE); | 616 | count = swap_entry_free(p, entry, SWAP_HAS_CACHE); |
| 620 | if (page) { | 617 | if (page) |
| 621 | bool swapout; | 618 | mem_cgroup_uncharge_swapcache(page, entry, count != 0); |
| 622 | if (ret) | ||
| 623 | swapout = true; /* the end of swap out */ | ||
| 624 | else | ||
| 625 | swapout = false; /* no more swap users! */ | ||
| 626 | mem_cgroup_uncharge_swapcache(page, entry, swapout); | ||
| 627 | } | ||
| 628 | spin_unlock(&swap_lock); | 619 | spin_unlock(&swap_lock); |
| 629 | } | 620 | } |
| 630 | return; | ||
| 631 | } | 621 | } |
| 632 | 622 | ||
| 633 | /* | 623 | /* |
| 634 | * How many references to page are currently swapped out? | 624 | * How many references to page are currently swapped out? |
| 625 | * This does not give an exact answer when swap count is continued, | ||
| 626 | * but does include the high COUNT_CONTINUED flag to allow for that. | ||
| 635 | */ | 627 | */ |
| 636 | static inline int page_swapcount(struct page *page) | 628 | static inline int page_swapcount(struct page *page) |
| 637 | { | 629 | { |
| @@ -659,6 +651,8 @@ int reuse_swap_page(struct page *page) | |||
| 659 | int count; | 651 | int count; |
| 660 | 652 | ||
| 661 | VM_BUG_ON(!PageLocked(page)); | 653 | VM_BUG_ON(!PageLocked(page)); |
| 654 | if (unlikely(PageKsm(page))) | ||
| 655 | return 0; | ||
| 662 | count = page_mapcount(page); | 656 | count = page_mapcount(page); |
| 663 | if (count <= 1 && PageSwapCache(page)) { | 657 | if (count <= 1 && PageSwapCache(page)) { |
| 664 | count += page_swapcount(page); | 658 | count += page_swapcount(page); |
| @@ -667,7 +661,7 @@ int reuse_swap_page(struct page *page) | |||
| 667 | SetPageDirty(page); | 661 | SetPageDirty(page); |
| 668 | } | 662 | } |
| 669 | } | 663 | } |
| 670 | return count == 1; | 664 | return count <= 1; |
| 671 | } | 665 | } |
| 672 | 666 | ||
| 673 | /* | 667 | /* |
| @@ -704,7 +698,7 @@ int free_swap_and_cache(swp_entry_t entry) | |||
| 704 | 698 | ||
| 705 | p = swap_info_get(entry); | 699 | p = swap_info_get(entry); |
| 706 | if (p) { | 700 | if (p) { |
| 707 | if (swap_entry_free(p, entry, SWAP_MAP) == SWAP_HAS_CACHE) { | 701 | if (swap_entry_free(p, entry, 1) == SWAP_HAS_CACHE) { |
| 708 | page = find_get_page(&swapper_space, entry.val); | 702 | page = find_get_page(&swapper_space, entry.val); |
| 709 | if (page && !trylock_page(page)) { | 703 | if (page && !trylock_page(page)) { |
| 710 | page_cache_release(page); | 704 | page_cache_release(page); |
| @@ -741,14 +735,14 @@ int free_swap_and_cache(swp_entry_t entry) | |||
| 741 | int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) | 735 | int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) |
| 742 | { | 736 | { |
| 743 | struct block_device *bdev = NULL; | 737 | struct block_device *bdev = NULL; |
| 744 | int i; | 738 | int type; |
| 745 | 739 | ||
| 746 | if (device) | 740 | if (device) |
| 747 | bdev = bdget(device); | 741 | bdev = bdget(device); |
| 748 | 742 | ||
| 749 | spin_lock(&swap_lock); | 743 | spin_lock(&swap_lock); |
| 750 | for (i = 0; i < nr_swapfiles; i++) { | 744 | for (type = 0; type < nr_swapfiles; type++) { |
| 751 | struct swap_info_struct *sis = swap_info + i; | 745 | struct swap_info_struct *sis = swap_info[type]; |
| 752 | 746 | ||
| 753 | if (!(sis->flags & SWP_WRITEOK)) | 747 | if (!(sis->flags & SWP_WRITEOK)) |
| 754 | continue; | 748 | continue; |
| @@ -758,20 +752,18 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) | |||
| 758 | *bdev_p = bdgrab(sis->bdev); | 752 | *bdev_p = bdgrab(sis->bdev); |
| 759 | 753 | ||
| 760 | spin_unlock(&swap_lock); | 754 | spin_unlock(&swap_lock); |
| 761 | return i; | 755 | return type; |
| 762 | } | 756 | } |
| 763 | if (bdev == sis->bdev) { | 757 | if (bdev == sis->bdev) { |
| 764 | struct swap_extent *se; | 758 | struct swap_extent *se = &sis->first_swap_extent; |
| 765 | 759 | ||
| 766 | se = list_entry(sis->extent_list.next, | ||
| 767 | struct swap_extent, list); | ||
| 768 | if (se->start_block == offset) { | 760 | if (se->start_block == offset) { |
| 769 | if (bdev_p) | 761 | if (bdev_p) |
| 770 | *bdev_p = bdgrab(sis->bdev); | 762 | *bdev_p = bdgrab(sis->bdev); |
| 771 | 763 | ||
| 772 | spin_unlock(&swap_lock); | 764 | spin_unlock(&swap_lock); |
| 773 | bdput(bdev); | 765 | bdput(bdev); |
| 774 | return i; | 766 | return type; |
| 775 | } | 767 | } |
| 776 | } | 768 | } |
| 777 | } | 769 | } |
| @@ -783,6 +775,21 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) | |||
| 783 | } | 775 | } |
| 784 | 776 | ||
| 785 | /* | 777 | /* |
| 778 | * Get the (PAGE_SIZE) block corresponding to given offset on the swapdev | ||
| 779 | * corresponding to given index in swap_info (swap type). | ||
| 780 | */ | ||
| 781 | sector_t swapdev_block(int type, pgoff_t offset) | ||
| 782 | { | ||
| 783 | struct block_device *bdev; | ||
| 784 | |||
| 785 | if ((unsigned int)type >= nr_swapfiles) | ||
| 786 | return 0; | ||
| 787 | if (!(swap_info[type]->flags & SWP_WRITEOK)) | ||
| 788 | return 0; | ||
| 789 | return map_swap_entry(swp_entry(type, offset), &bdev); | ||
| 790 | } | ||
| 791 | |||
| 792 | /* | ||
| 786 | * Return either the total number of swap pages of given type, or the number | 793 | * Return either the total number of swap pages of given type, or the number |
| 787 | * of free pages of that type (depending on @free) | 794 | * of free pages of that type (depending on @free) |
| 788 | * | 795 | * |
| @@ -792,18 +799,20 @@ unsigned int count_swap_pages(int type, int free) | |||
| 792 | { | 799 | { |
| 793 | unsigned int n = 0; | 800 | unsigned int n = 0; |
| 794 | 801 | ||
| 795 | if (type < nr_swapfiles) { | 802 | spin_lock(&swap_lock); |
| 796 | spin_lock(&swap_lock); | 803 | if ((unsigned int)type < nr_swapfiles) { |
| 797 | if (swap_info[type].flags & SWP_WRITEOK) { | 804 | struct swap_info_struct *sis = swap_info[type]; |
| 798 | n = swap_info[type].pages; | 805 | |
| 806 | if (sis->flags & SWP_WRITEOK) { | ||
| 807 | n = sis->pages; | ||
| 799 | if (free) | 808 | if (free) |
| 800 | n -= swap_info[type].inuse_pages; | 809 | n -= sis->inuse_pages; |
| 801 | } | 810 | } |
| 802 | spin_unlock(&swap_lock); | ||
| 803 | } | 811 | } |
| 812 | spin_unlock(&swap_lock); | ||
| 804 | return n; | 813 | return n; |
| 805 | } | 814 | } |
| 806 | #endif | 815 | #endif /* CONFIG_HIBERNATION */ |
| 807 | 816 | ||
| 808 | /* | 817 | /* |
| 809 | * No need to decide whether this PTE shares the swap entry with others, | 818 | * No need to decide whether this PTE shares the swap entry with others, |
| @@ -932,7 +941,7 @@ static int unuse_vma(struct vm_area_struct *vma, | |||
| 932 | unsigned long addr, end, next; | 941 | unsigned long addr, end, next; |
| 933 | int ret; | 942 | int ret; |
| 934 | 943 | ||
| 935 | if (page->mapping) { | 944 | if (page_anon_vma(page)) { |
| 936 | addr = page_address_in_vma(page, vma); | 945 | addr = page_address_in_vma(page, vma); |
| 937 | if (addr == -EFAULT) | 946 | if (addr == -EFAULT) |
| 938 | return 0; | 947 | return 0; |
| @@ -988,7 +997,7 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si, | |||
| 988 | { | 997 | { |
| 989 | unsigned int max = si->max; | 998 | unsigned int max = si->max; |
| 990 | unsigned int i = prev; | 999 | unsigned int i = prev; |
| 991 | int count; | 1000 | unsigned char count; |
| 992 | 1001 | ||
| 993 | /* | 1002 | /* |
| 994 | * No need for swap_lock here: we're just looking | 1003 | * No need for swap_lock here: we're just looking |
| @@ -1024,16 +1033,14 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si, | |||
| 1024 | */ | 1033 | */ |
| 1025 | static int try_to_unuse(unsigned int type) | 1034 | static int try_to_unuse(unsigned int type) |
| 1026 | { | 1035 | { |
| 1027 | struct swap_info_struct * si = &swap_info[type]; | 1036 | struct swap_info_struct *si = swap_info[type]; |
| 1028 | struct mm_struct *start_mm; | 1037 | struct mm_struct *start_mm; |
| 1029 | unsigned short *swap_map; | 1038 | unsigned char *swap_map; |
| 1030 | unsigned short swcount; | 1039 | unsigned char swcount; |
| 1031 | struct page *page; | 1040 | struct page *page; |
| 1032 | swp_entry_t entry; | 1041 | swp_entry_t entry; |
| 1033 | unsigned int i = 0; | 1042 | unsigned int i = 0; |
| 1034 | int retval = 0; | 1043 | int retval = 0; |
| 1035 | int reset_overflow = 0; | ||
| 1036 | int shmem; | ||
| 1037 | 1044 | ||
| 1038 | /* | 1045 | /* |
| 1039 | * When searching mms for an entry, a good strategy is to | 1046 | * When searching mms for an entry, a good strategy is to |
| @@ -1047,8 +1054,7 @@ static int try_to_unuse(unsigned int type) | |||
| 1047 | * together, child after parent. If we race with dup_mmap(), we | 1054 | * together, child after parent. If we race with dup_mmap(), we |
| 1048 | * prefer to resolve parent before child, lest we miss entries | 1055 | * prefer to resolve parent before child, lest we miss entries |
| 1049 | * duplicated after we scanned child: using last mm would invert | 1056 | * duplicated after we scanned child: using last mm would invert |
| 1050 | * that. Though it's only a serious concern when an overflowed | 1057 | * that. |
| 1051 | * swap count is reset from SWAP_MAP_MAX, preventing a rescan. | ||
| 1052 | */ | 1058 | */ |
| 1053 | start_mm = &init_mm; | 1059 | start_mm = &init_mm; |
| 1054 | atomic_inc(&init_mm.mm_users); | 1060 | atomic_inc(&init_mm.mm_users); |
| @@ -1110,17 +1116,18 @@ static int try_to_unuse(unsigned int type) | |||
| 1110 | 1116 | ||
| 1111 | /* | 1117 | /* |
| 1112 | * Remove all references to entry. | 1118 | * Remove all references to entry. |
| 1113 | * Whenever we reach init_mm, there's no address space | ||
| 1114 | * to search, but use it as a reminder to search shmem. | ||
| 1115 | */ | 1119 | */ |
| 1116 | shmem = 0; | ||
| 1117 | swcount = *swap_map; | 1120 | swcount = *swap_map; |
| 1118 | if (swap_count(swcount)) { | 1121 | if (swap_count(swcount) == SWAP_MAP_SHMEM) { |
| 1119 | if (start_mm == &init_mm) | 1122 | retval = shmem_unuse(entry, page); |
| 1120 | shmem = shmem_unuse(entry, page); | 1123 | /* page has already been unlocked and released */ |
| 1121 | else | 1124 | if (retval < 0) |
| 1122 | retval = unuse_mm(start_mm, entry, page); | 1125 | break; |
| 1126 | continue; | ||
| 1123 | } | 1127 | } |
| 1128 | if (swap_count(swcount) && start_mm != &init_mm) | ||
| 1129 | retval = unuse_mm(start_mm, entry, page); | ||
| 1130 | |||
| 1124 | if (swap_count(*swap_map)) { | 1131 | if (swap_count(*swap_map)) { |
| 1125 | int set_start_mm = (*swap_map >= swcount); | 1132 | int set_start_mm = (*swap_map >= swcount); |
| 1126 | struct list_head *p = &start_mm->mmlist; | 1133 | struct list_head *p = &start_mm->mmlist; |
| @@ -1131,7 +1138,7 @@ static int try_to_unuse(unsigned int type) | |||
| 1131 | atomic_inc(&new_start_mm->mm_users); | 1138 | atomic_inc(&new_start_mm->mm_users); |
| 1132 | atomic_inc(&prev_mm->mm_users); | 1139 | atomic_inc(&prev_mm->mm_users); |
| 1133 | spin_lock(&mmlist_lock); | 1140 | spin_lock(&mmlist_lock); |
| 1134 | while (swap_count(*swap_map) && !retval && !shmem && | 1141 | while (swap_count(*swap_map) && !retval && |
| 1135 | (p = p->next) != &start_mm->mmlist) { | 1142 | (p = p->next) != &start_mm->mmlist) { |
| 1136 | mm = list_entry(p, struct mm_struct, mmlist); | 1143 | mm = list_entry(p, struct mm_struct, mmlist); |
| 1137 | if (!atomic_inc_not_zero(&mm->mm_users)) | 1144 | if (!atomic_inc_not_zero(&mm->mm_users)) |
| @@ -1145,10 +1152,9 @@ static int try_to_unuse(unsigned int type) | |||
| 1145 | swcount = *swap_map; | 1152 | swcount = *swap_map; |
| 1146 | if (!swap_count(swcount)) /* any usage ? */ | 1153 | if (!swap_count(swcount)) /* any usage ? */ |
| 1147 | ; | 1154 | ; |
| 1148 | else if (mm == &init_mm) { | 1155 | else if (mm == &init_mm) |
| 1149 | set_start_mm = 1; | 1156 | set_start_mm = 1; |
| 1150 | shmem = shmem_unuse(entry, page); | 1157 | else |
| 1151 | } else | ||
| 1152 | retval = unuse_mm(mm, entry, page); | 1158 | retval = unuse_mm(mm, entry, page); |
| 1153 | 1159 | ||
| 1154 | if (set_start_mm && *swap_map < swcount) { | 1160 | if (set_start_mm && *swap_map < swcount) { |
| @@ -1164,13 +1170,6 @@ static int try_to_unuse(unsigned int type) | |||
| 1164 | mmput(start_mm); | 1170 | mmput(start_mm); |
| 1165 | start_mm = new_start_mm; | 1171 | start_mm = new_start_mm; |
| 1166 | } | 1172 | } |
| 1167 | if (shmem) { | ||
| 1168 | /* page has already been unlocked and released */ | ||
| 1169 | if (shmem > 0) | ||
| 1170 | continue; | ||
| 1171 | retval = shmem; | ||
| 1172 | break; | ||
| 1173 | } | ||
| 1174 | if (retval) { | 1173 | if (retval) { |
| 1175 | unlock_page(page); | 1174 | unlock_page(page); |
| 1176 | page_cache_release(page); | 1175 | page_cache_release(page); |
| @@ -1178,30 +1177,6 @@ static int try_to_unuse(unsigned int type) | |||
| 1178 | } | 1177 | } |
| 1179 | 1178 | ||
| 1180 | /* | 1179 | /* |
| 1181 | * How could swap count reach 0x7ffe ? | ||
| 1182 | * There's no way to repeat a swap page within an mm | ||
| 1183 | * (except in shmem, where it's the shared object which takes | ||
| 1184 | * the reference count)? | ||
| 1185 | * We believe SWAP_MAP_MAX cannot occur.(if occur, unsigned | ||
| 1186 | * short is too small....) | ||
| 1187 | * If that's wrong, then we should worry more about | ||
| 1188 | * exit_mmap() and do_munmap() cases described above: | ||
| 1189 | * we might be resetting SWAP_MAP_MAX too early here. | ||
| 1190 | * We know "Undead"s can happen, they're okay, so don't | ||
| 1191 | * report them; but do report if we reset SWAP_MAP_MAX. | ||
| 1192 | */ | ||
| 1193 | /* We might release the lock_page() in unuse_mm(). */ | ||
| 1194 | if (!PageSwapCache(page) || page_private(page) != entry.val) | ||
| 1195 | goto retry; | ||
| 1196 | |||
| 1197 | if (swap_count(*swap_map) == SWAP_MAP_MAX) { | ||
| 1198 | spin_lock(&swap_lock); | ||
| 1199 | *swap_map = encode_swapmap(0, true); | ||
| 1200 | spin_unlock(&swap_lock); | ||
| 1201 | reset_overflow = 1; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | /* | ||
| 1205 | * If a reference remains (rare), we would like to leave | 1180 | * If a reference remains (rare), we would like to leave |
| 1206 | * the page in the swap cache; but try_to_unmap could | 1181 | * the page in the swap cache; but try_to_unmap could |
| 1207 | * then re-duplicate the entry once we drop page lock, | 1182 | * then re-duplicate the entry once we drop page lock, |
| @@ -1213,6 +1188,12 @@ static int try_to_unuse(unsigned int type) | |||
| 1213 | * read from disk into another page. Splitting into two | 1188 | * read from disk into another page. Splitting into two |
| 1214 | * pages would be incorrect if swap supported "shared | 1189 | * pages would be incorrect if swap supported "shared |
| 1215 | * private" pages, but they are handled by tmpfs files. | 1190 | * private" pages, but they are handled by tmpfs files. |
| 1191 | * | ||
| 1192 | * Given how unuse_vma() targets one particular offset | ||
| 1193 | * in an anon_vma, once the anon_vma has been determined, | ||
| 1194 | * this splitting happens to be just what is needed to | ||
| 1195 | * handle where KSM pages have been swapped out: re-reading | ||
| 1196 | * is unnecessarily slow, but we can fix that later on. | ||
| 1216 | */ | 1197 | */ |
| 1217 | if (swap_count(*swap_map) && | 1198 | if (swap_count(*swap_map) && |
| 1218 | PageDirty(page) && PageSwapCache(page)) { | 1199 | PageDirty(page) && PageSwapCache(page)) { |
| @@ -1242,7 +1223,6 @@ static int try_to_unuse(unsigned int type) | |||
| 1242 | * mark page dirty so shrink_page_list will preserve it. | 1223 | * mark page dirty so shrink_page_list will preserve it. |
| 1243 | */ | 1224 | */ |
| 1244 | SetPageDirty(page); | 1225 | SetPageDirty(page); |
| 1245 | retry: | ||
| 1246 | unlock_page(page); | 1226 | unlock_page(page); |
| 1247 | page_cache_release(page); | 1227 | page_cache_release(page); |
| 1248 | 1228 | ||
| @@ -1254,10 +1234,6 @@ retry: | |||
| 1254 | } | 1234 | } |
| 1255 | 1235 | ||
| 1256 | mmput(start_mm); | 1236 | mmput(start_mm); |
| 1257 | if (reset_overflow) { | ||
| 1258 | printk(KERN_WARNING "swapoff: cleared swap entry overflow\n"); | ||
| 1259 | swap_overflow = 0; | ||
| 1260 | } | ||
| 1261 | return retval; | 1237 | return retval; |
| 1262 | } | 1238 | } |
| 1263 | 1239 | ||
| @@ -1270,10 +1246,10 @@ retry: | |||
| 1270 | static void drain_mmlist(void) | 1246 | static void drain_mmlist(void) |
| 1271 | { | 1247 | { |
| 1272 | struct list_head *p, *next; | 1248 | struct list_head *p, *next; |
| 1273 | unsigned int i; | 1249 | unsigned int type; |
| 1274 | 1250 | ||
| 1275 | for (i = 0; i < nr_swapfiles; i++) | 1251 | for (type = 0; type < nr_swapfiles; type++) |
| 1276 | if (swap_info[i].inuse_pages) | 1252 | if (swap_info[type]->inuse_pages) |
| 1277 | return; | 1253 | return; |
| 1278 | spin_lock(&mmlist_lock); | 1254 | spin_lock(&mmlist_lock); |
| 1279 | list_for_each_safe(p, next, &init_mm.mmlist) | 1255 | list_for_each_safe(p, next, &init_mm.mmlist) |
| @@ -1283,12 +1259,23 @@ static void drain_mmlist(void) | |||
| 1283 | 1259 | ||
| 1284 | /* | 1260 | /* |
| 1285 | * Use this swapdev's extent info to locate the (PAGE_SIZE) block which | 1261 | * Use this swapdev's extent info to locate the (PAGE_SIZE) block which |
| 1286 | * corresponds to page offset `offset'. | 1262 | * corresponds to page offset for the specified swap entry. |
| 1263 | * Note that the type of this function is sector_t, but it returns page offset | ||
| 1264 | * into the bdev, not sector offset. | ||
| 1287 | */ | 1265 | */ |
| 1288 | sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset) | 1266 | static sector_t map_swap_entry(swp_entry_t entry, struct block_device **bdev) |
| 1289 | { | 1267 | { |
| 1290 | struct swap_extent *se = sis->curr_swap_extent; | 1268 | struct swap_info_struct *sis; |
| 1291 | struct swap_extent *start_se = se; | 1269 | struct swap_extent *start_se; |
| 1270 | struct swap_extent *se; | ||
| 1271 | pgoff_t offset; | ||
| 1272 | |||
| 1273 | sis = swap_info[swp_type(entry)]; | ||
| 1274 | *bdev = sis->bdev; | ||
| 1275 | |||
| 1276 | offset = swp_offset(entry); | ||
| 1277 | start_se = sis->curr_swap_extent; | ||
| 1278 | se = start_se; | ||
| 1292 | 1279 | ||
| 1293 | for ( ; ; ) { | 1280 | for ( ; ; ) { |
| 1294 | struct list_head *lh; | 1281 | struct list_head *lh; |
| @@ -1298,40 +1285,31 @@ sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset) | |||
| 1298 | return se->start_block + (offset - se->start_page); | 1285 | return se->start_block + (offset - se->start_page); |
| 1299 | } | 1286 | } |
| 1300 | lh = se->list.next; | 1287 | lh = se->list.next; |
| 1301 | if (lh == &sis->extent_list) | ||
| 1302 | lh = lh->next; | ||
| 1303 | se = list_entry(lh, struct swap_extent, list); | 1288 | se = list_entry(lh, struct swap_extent, list); |
| 1304 | sis->curr_swap_extent = se; | 1289 | sis->curr_swap_extent = se; |
| 1305 | BUG_ON(se == start_se); /* It *must* be present */ | 1290 | BUG_ON(se == start_se); /* It *must* be present */ |
| 1306 | } | 1291 | } |
| 1307 | } | 1292 | } |
| 1308 | 1293 | ||
| 1309 | #ifdef CONFIG_HIBERNATION | ||
| 1310 | /* | 1294 | /* |
| 1311 | * Get the (PAGE_SIZE) block corresponding to given offset on the swapdev | 1295 | * Returns the page offset into bdev for the specified page's swap entry. |
| 1312 | * corresponding to given index in swap_info (swap type). | ||
| 1313 | */ | 1296 | */ |
| 1314 | sector_t swapdev_block(int swap_type, pgoff_t offset) | 1297 | sector_t map_swap_page(struct page *page, struct block_device **bdev) |
| 1315 | { | 1298 | { |
| 1316 | struct swap_info_struct *sis; | 1299 | swp_entry_t entry; |
| 1317 | 1300 | entry.val = page_private(page); | |
| 1318 | if (swap_type >= nr_swapfiles) | 1301 | return map_swap_entry(entry, bdev); |
| 1319 | return 0; | ||
| 1320 | |||
| 1321 | sis = swap_info + swap_type; | ||
| 1322 | return (sis->flags & SWP_WRITEOK) ? map_swap_page(sis, offset) : 0; | ||
| 1323 | } | 1302 | } |
| 1324 | #endif /* CONFIG_HIBERNATION */ | ||
| 1325 | 1303 | ||
| 1326 | /* | 1304 | /* |
| 1327 | * Free all of a swapdev's extent information | 1305 | * Free all of a swapdev's extent information |
| 1328 | */ | 1306 | */ |
| 1329 | static void destroy_swap_extents(struct swap_info_struct *sis) | 1307 | static void destroy_swap_extents(struct swap_info_struct *sis) |
| 1330 | { | 1308 | { |
| 1331 | while (!list_empty(&sis->extent_list)) { | 1309 | while (!list_empty(&sis->first_swap_extent.list)) { |
| 1332 | struct swap_extent *se; | 1310 | struct swap_extent *se; |
| 1333 | 1311 | ||
| 1334 | se = list_entry(sis->extent_list.next, | 1312 | se = list_entry(sis->first_swap_extent.list.next, |
| 1335 | struct swap_extent, list); | 1313 | struct swap_extent, list); |
| 1336 | list_del(&se->list); | 1314 | list_del(&se->list); |
| 1337 | kfree(se); | 1315 | kfree(se); |
| @@ -1352,8 +1330,15 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
| 1352 | struct swap_extent *new_se; | 1330 | struct swap_extent *new_se; |
| 1353 | struct list_head *lh; | 1331 | struct list_head *lh; |
| 1354 | 1332 | ||
| 1355 | lh = sis->extent_list.prev; /* The highest page extent */ | 1333 | if (start_page == 0) { |
| 1356 | if (lh != &sis->extent_list) { | 1334 | se = &sis->first_swap_extent; |
| 1335 | sis->curr_swap_extent = se; | ||
| 1336 | se->start_page = 0; | ||
| 1337 | se->nr_pages = nr_pages; | ||
| 1338 | se->start_block = start_block; | ||
| 1339 | return 1; | ||
| 1340 | } else { | ||
| 1341 | lh = sis->first_swap_extent.list.prev; /* Highest extent */ | ||
| 1357 | se = list_entry(lh, struct swap_extent, list); | 1342 | se = list_entry(lh, struct swap_extent, list); |
| 1358 | BUG_ON(se->start_page + se->nr_pages != start_page); | 1343 | BUG_ON(se->start_page + se->nr_pages != start_page); |
| 1359 | if (se->start_block + se->nr_pages == start_block) { | 1344 | if (se->start_block + se->nr_pages == start_block) { |
| @@ -1373,7 +1358,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
| 1373 | new_se->nr_pages = nr_pages; | 1358 | new_se->nr_pages = nr_pages; |
| 1374 | new_se->start_block = start_block; | 1359 | new_se->start_block = start_block; |
| 1375 | 1360 | ||
| 1376 | list_add_tail(&new_se->list, &sis->extent_list); | 1361 | list_add_tail(&new_se->list, &sis->first_swap_extent.list); |
| 1377 | return 1; | 1362 | return 1; |
| 1378 | } | 1363 | } |
| 1379 | 1364 | ||
| @@ -1425,7 +1410,7 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) | |||
| 1425 | if (S_ISBLK(inode->i_mode)) { | 1410 | if (S_ISBLK(inode->i_mode)) { |
| 1426 | ret = add_swap_extent(sis, 0, sis->max, 0); | 1411 | ret = add_swap_extent(sis, 0, sis->max, 0); |
| 1427 | *span = sis->pages; | 1412 | *span = sis->pages; |
| 1428 | goto done; | 1413 | goto out; |
| 1429 | } | 1414 | } |
| 1430 | 1415 | ||
| 1431 | blkbits = inode->i_blkbits; | 1416 | blkbits = inode->i_blkbits; |
| @@ -1496,25 +1481,22 @@ reprobe: | |||
| 1496 | sis->max = page_no; | 1481 | sis->max = page_no; |
| 1497 | sis->pages = page_no - 1; | 1482 | sis->pages = page_no - 1; |
| 1498 | sis->highest_bit = page_no - 1; | 1483 | sis->highest_bit = page_no - 1; |
| 1499 | done: | 1484 | out: |
| 1500 | sis->curr_swap_extent = list_entry(sis->extent_list.prev, | 1485 | return ret; |
| 1501 | struct swap_extent, list); | ||
| 1502 | goto out; | ||
| 1503 | bad_bmap: | 1486 | bad_bmap: |
| 1504 | printk(KERN_ERR "swapon: swapfile has holes\n"); | 1487 | printk(KERN_ERR "swapon: swapfile has holes\n"); |
| 1505 | ret = -EINVAL; | 1488 | ret = -EINVAL; |
| 1506 | out: | 1489 | goto out; |
| 1507 | return ret; | ||
| 1508 | } | 1490 | } |
| 1509 | 1491 | ||
| 1510 | SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | 1492 | SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) |
| 1511 | { | 1493 | { |
| 1512 | struct swap_info_struct * p = NULL; | 1494 | struct swap_info_struct *p = NULL; |
| 1513 | unsigned short *swap_map; | 1495 | unsigned char *swap_map; |
| 1514 | struct file *swap_file, *victim; | 1496 | struct file *swap_file, *victim; |
| 1515 | struct address_space *mapping; | 1497 | struct address_space *mapping; |
| 1516 | struct inode *inode; | 1498 | struct inode *inode; |
| 1517 | char * pathname; | 1499 | char *pathname; |
| 1518 | int i, type, prev; | 1500 | int i, type, prev; |
| 1519 | int err; | 1501 | int err; |
| 1520 | 1502 | ||
| @@ -1535,8 +1517,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
| 1535 | mapping = victim->f_mapping; | 1517 | mapping = victim->f_mapping; |
| 1536 | prev = -1; | 1518 | prev = -1; |
| 1537 | spin_lock(&swap_lock); | 1519 | spin_lock(&swap_lock); |
| 1538 | for (type = swap_list.head; type >= 0; type = swap_info[type].next) { | 1520 | for (type = swap_list.head; type >= 0; type = swap_info[type]->next) { |
| 1539 | p = swap_info + type; | 1521 | p = swap_info[type]; |
| 1540 | if (p->flags & SWP_WRITEOK) { | 1522 | if (p->flags & SWP_WRITEOK) { |
| 1541 | if (p->swap_file->f_mapping == mapping) | 1523 | if (p->swap_file->f_mapping == mapping) |
| 1542 | break; | 1524 | break; |
| @@ -1555,18 +1537,17 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
| 1555 | spin_unlock(&swap_lock); | 1537 | spin_unlock(&swap_lock); |
| 1556 | goto out_dput; | 1538 | goto out_dput; |
| 1557 | } | 1539 | } |
| 1558 | if (prev < 0) { | 1540 | if (prev < 0) |
| 1559 | swap_list.head = p->next; | 1541 | swap_list.head = p->next; |
| 1560 | } else { | 1542 | else |
| 1561 | swap_info[prev].next = p->next; | 1543 | swap_info[prev]->next = p->next; |
| 1562 | } | ||
| 1563 | if (type == swap_list.next) { | 1544 | if (type == swap_list.next) { |
| 1564 | /* just pick something that's safe... */ | 1545 | /* just pick something that's safe... */ |
| 1565 | swap_list.next = swap_list.head; | 1546 | swap_list.next = swap_list.head; |
| 1566 | } | 1547 | } |
| 1567 | if (p->prio < 0) { | 1548 | if (p->prio < 0) { |
| 1568 | for (i = p->next; i >= 0; i = swap_info[i].next) | 1549 | for (i = p->next; i >= 0; i = swap_info[i]->next) |
| 1569 | swap_info[i].prio = p->prio--; | 1550 | swap_info[i]->prio = p->prio--; |
| 1570 | least_priority++; | 1551 | least_priority++; |
| 1571 | } | 1552 | } |
| 1572 | nr_swap_pages -= p->pages; | 1553 | nr_swap_pages -= p->pages; |
| @@ -1584,16 +1565,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
| 1584 | if (p->prio < 0) | 1565 | if (p->prio < 0) |
| 1585 | p->prio = --least_priority; | 1566 | p->prio = --least_priority; |
| 1586 | prev = -1; | 1567 | prev = -1; |
| 1587 | for (i = swap_list.head; i >= 0; i = swap_info[i].next) { | 1568 | for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { |
| 1588 | if (p->prio >= swap_info[i].prio) | 1569 | if (p->prio >= swap_info[i]->prio) |
| 1589 | break; | 1570 | break; |
| 1590 | prev = i; | 1571 | prev = i; |
| 1591 | } | 1572 | } |
| 1592 | p->next = i; | 1573 | p->next = i; |
| 1593 | if (prev < 0) | 1574 | if (prev < 0) |
| 1594 | swap_list.head = swap_list.next = p - swap_info; | 1575 | swap_list.head = swap_list.next = type; |
| 1595 | else | 1576 | else |
| 1596 | swap_info[prev].next = p - swap_info; | 1577 | swap_info[prev]->next = type; |
| 1597 | nr_swap_pages += p->pages; | 1578 | nr_swap_pages += p->pages; |
| 1598 | total_swap_pages += p->pages; | 1579 | total_swap_pages += p->pages; |
| 1599 | p->flags |= SWP_WRITEOK; | 1580 | p->flags |= SWP_WRITEOK; |
| @@ -1606,6 +1587,9 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
| 1606 | up_write(&swap_unplug_sem); | 1587 | up_write(&swap_unplug_sem); |
| 1607 | 1588 | ||
| 1608 | destroy_swap_extents(p); | 1589 | destroy_swap_extents(p); |
| 1590 | if (p->flags & SWP_CONTINUED) | ||
| 1591 | free_swap_count_continuations(p); | ||
| 1592 | |||
| 1609 | mutex_lock(&swapon_mutex); | 1593 | mutex_lock(&swapon_mutex); |
| 1610 | spin_lock(&swap_lock); | 1594 | spin_lock(&swap_lock); |
| 1611 | drain_mmlist(); | 1595 | drain_mmlist(); |
| @@ -1653,8 +1637,8 @@ out: | |||
| 1653 | /* iterator */ | 1637 | /* iterator */ |
| 1654 | static void *swap_start(struct seq_file *swap, loff_t *pos) | 1638 | static void *swap_start(struct seq_file *swap, loff_t *pos) |
| 1655 | { | 1639 | { |
| 1656 | struct swap_info_struct *ptr = swap_info; | 1640 | struct swap_info_struct *si; |
| 1657 | int i; | 1641 | int type; |
| 1658 | loff_t l = *pos; | 1642 | loff_t l = *pos; |
| 1659 | 1643 | ||
| 1660 | mutex_lock(&swapon_mutex); | 1644 | mutex_lock(&swapon_mutex); |
| @@ -1662,11 +1646,13 @@ static void *swap_start(struct seq_file *swap, loff_t *pos) | |||
| 1662 | if (!l) | 1646 | if (!l) |
| 1663 | return SEQ_START_TOKEN; | 1647 | return SEQ_START_TOKEN; |
| 1664 | 1648 | ||
| 1665 | for (i = 0; i < nr_swapfiles; i++, ptr++) { | 1649 | for (type = 0; type < nr_swapfiles; type++) { |
| 1666 | if (!(ptr->flags & SWP_USED) || !ptr->swap_map) | 1650 | smp_rmb(); /* read nr_swapfiles before swap_info[type] */ |
| 1651 | si = swap_info[type]; | ||
| 1652 | if (!(si->flags & SWP_USED) || !si->swap_map) | ||
| 1667 | continue; | 1653 | continue; |
| 1668 | if (!--l) | 1654 | if (!--l) |
| 1669 | return ptr; | 1655 | return si; |
| 1670 | } | 1656 | } |
| 1671 | 1657 | ||
| 1672 | return NULL; | 1658 | return NULL; |
| @@ -1674,21 +1660,21 @@ static void *swap_start(struct seq_file *swap, loff_t *pos) | |||
| 1674 | 1660 | ||
| 1675 | static void *swap_next(struct seq_file *swap, void *v, loff_t *pos) | 1661 | static void *swap_next(struct seq_file *swap, void *v, loff_t *pos) |
| 1676 | { | 1662 | { |
| 1677 | struct swap_info_struct *ptr; | 1663 | struct swap_info_struct *si = v; |
| 1678 | struct swap_info_struct *endptr = swap_info + nr_swapfiles; | 1664 | int type; |
| 1679 | 1665 | ||
| 1680 | if (v == SEQ_START_TOKEN) | 1666 | if (v == SEQ_START_TOKEN) |
| 1681 | ptr = swap_info; | 1667 | type = 0; |
| 1682 | else { | 1668 | else |
| 1683 | ptr = v; | 1669 | type = si->type + 1; |
| 1684 | ptr++; | ||
| 1685 | } | ||
| 1686 | 1670 | ||
| 1687 | for (; ptr < endptr; ptr++) { | 1671 | for (; type < nr_swapfiles; type++) { |
| 1688 | if (!(ptr->flags & SWP_USED) || !ptr->swap_map) | 1672 | smp_rmb(); /* read nr_swapfiles before swap_info[type] */ |
| 1673 | si = swap_info[type]; | ||
| 1674 | if (!(si->flags & SWP_USED) || !si->swap_map) | ||
| 1689 | continue; | 1675 | continue; |
| 1690 | ++*pos; | 1676 | ++*pos; |
| 1691 | return ptr; | 1677 | return si; |
| 1692 | } | 1678 | } |
| 1693 | 1679 | ||
| 1694 | return NULL; | 1680 | return NULL; |
| @@ -1701,24 +1687,24 @@ static void swap_stop(struct seq_file *swap, void *v) | |||
| 1701 | 1687 | ||
| 1702 | static int swap_show(struct seq_file *swap, void *v) | 1688 | static int swap_show(struct seq_file *swap, void *v) |
| 1703 | { | 1689 | { |
| 1704 | struct swap_info_struct *ptr = v; | 1690 | struct swap_info_struct *si = v; |
| 1705 | struct file *file; | 1691 | struct file *file; |
| 1706 | int len; | 1692 | int len; |
| 1707 | 1693 | ||
| 1708 | if (ptr == SEQ_START_TOKEN) { | 1694 | if (si == SEQ_START_TOKEN) { |
| 1709 | seq_puts(swap,"Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); | 1695 | seq_puts(swap,"Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); |
| 1710 | return 0; | 1696 | return 0; |
| 1711 | } | 1697 | } |
| 1712 | 1698 | ||
| 1713 | file = ptr->swap_file; | 1699 | file = si->swap_file; |
| 1714 | len = seq_path(swap, &file->f_path, " \t\n\\"); | 1700 | len = seq_path(swap, &file->f_path, " \t\n\\"); |
| 1715 | seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", | 1701 | seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", |
| 1716 | len < 40 ? 40 - len : 1, " ", | 1702 | len < 40 ? 40 - len : 1, " ", |
| 1717 | S_ISBLK(file->f_path.dentry->d_inode->i_mode) ? | 1703 | S_ISBLK(file->f_path.dentry->d_inode->i_mode) ? |
| 1718 | "partition" : "file\t", | 1704 | "partition" : "file\t", |
| 1719 | ptr->pages << (PAGE_SHIFT - 10), | 1705 | si->pages << (PAGE_SHIFT - 10), |
| 1720 | ptr->inuse_pages << (PAGE_SHIFT - 10), | 1706 | si->inuse_pages << (PAGE_SHIFT - 10), |
| 1721 | ptr->prio); | 1707 | si->prio); |
| 1722 | return 0; | 1708 | return 0; |
| 1723 | } | 1709 | } |
| 1724 | 1710 | ||
| @@ -1765,7 +1751,7 @@ late_initcall(max_swapfiles_check); | |||
| 1765 | */ | 1751 | */ |
| 1766 | SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | 1752 | SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) |
| 1767 | { | 1753 | { |
| 1768 | struct swap_info_struct * p; | 1754 | struct swap_info_struct *p; |
| 1769 | char *name = NULL; | 1755 | char *name = NULL; |
| 1770 | struct block_device *bdev = NULL; | 1756 | struct block_device *bdev = NULL; |
| 1771 | struct file *swap_file = NULL; | 1757 | struct file *swap_file = NULL; |
| @@ -1779,30 +1765,52 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
| 1779 | sector_t span; | 1765 | sector_t span; |
| 1780 | unsigned long maxpages = 1; | 1766 | unsigned long maxpages = 1; |
| 1781 | unsigned long swapfilepages; | 1767 | unsigned long swapfilepages; |
| 1782 | unsigned short *swap_map = NULL; | 1768 | unsigned char *swap_map = NULL; |
| 1783 | struct page *page = NULL; | 1769 | struct page *page = NULL; |
| 1784 | struct inode *inode = NULL; | 1770 | struct inode *inode = NULL; |
| 1785 | int did_down = 0; | 1771 | int did_down = 0; |
| 1786 | 1772 | ||
| 1787 | if (!capable(CAP_SYS_ADMIN)) | 1773 | if (!capable(CAP_SYS_ADMIN)) |
| 1788 | return -EPERM; | 1774 | return -EPERM; |
| 1775 | |||
| 1776 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 1777 | if (!p) | ||
| 1778 | return -ENOMEM; | ||
| 1779 | |||
| 1789 | spin_lock(&swap_lock); | 1780 | spin_lock(&swap_lock); |
| 1790 | p = swap_info; | 1781 | for (type = 0; type < nr_swapfiles; type++) { |
| 1791 | for (type = 0 ; type < nr_swapfiles ; type++,p++) | 1782 | if (!(swap_info[type]->flags & SWP_USED)) |
| 1792 | if (!(p->flags & SWP_USED)) | ||
| 1793 | break; | 1783 | break; |
| 1784 | } | ||
| 1794 | error = -EPERM; | 1785 | error = -EPERM; |
| 1795 | if (type >= MAX_SWAPFILES) { | 1786 | if (type >= MAX_SWAPFILES) { |
| 1796 | spin_unlock(&swap_lock); | 1787 | spin_unlock(&swap_lock); |
| 1788 | kfree(p); | ||
| 1797 | goto out; | 1789 | goto out; |
| 1798 | } | 1790 | } |
| 1799 | if (type >= nr_swapfiles) | 1791 | if (type >= nr_swapfiles) { |
| 1800 | nr_swapfiles = type+1; | 1792 | p->type = type; |
| 1801 | memset(p, 0, sizeof(*p)); | 1793 | swap_info[type] = p; |
| 1802 | INIT_LIST_HEAD(&p->extent_list); | 1794 | /* |
| 1795 | * Write swap_info[type] before nr_swapfiles, in case a | ||
| 1796 | * racing procfs swap_start() or swap_next() is reading them. | ||
| 1797 | * (We never shrink nr_swapfiles, we never free this entry.) | ||
| 1798 | */ | ||
| 1799 | smp_wmb(); | ||
| 1800 | nr_swapfiles++; | ||
| 1801 | } else { | ||
| 1802 | kfree(p); | ||
| 1803 | p = swap_info[type]; | ||
| 1804 | /* | ||
| 1805 | * Do not memset this entry: a racing procfs swap_next() | ||
| 1806 | * would be relying on p->type to remain valid. | ||
| 1807 | */ | ||
| 1808 | } | ||
| 1809 | INIT_LIST_HEAD(&p->first_swap_extent.list); | ||
| 1803 | p->flags = SWP_USED; | 1810 | p->flags = SWP_USED; |
| 1804 | p->next = -1; | 1811 | p->next = -1; |
| 1805 | spin_unlock(&swap_lock); | 1812 | spin_unlock(&swap_lock); |
| 1813 | |||
| 1806 | name = getname(specialfile); | 1814 | name = getname(specialfile); |
| 1807 | error = PTR_ERR(name); | 1815 | error = PTR_ERR(name); |
| 1808 | if (IS_ERR(name)) { | 1816 | if (IS_ERR(name)) { |
| @@ -1822,7 +1830,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
| 1822 | 1830 | ||
| 1823 | error = -EBUSY; | 1831 | error = -EBUSY; |
| 1824 | for (i = 0; i < nr_swapfiles; i++) { | 1832 | for (i = 0; i < nr_swapfiles; i++) { |
| 1825 | struct swap_info_struct *q = &swap_info[i]; | 1833 | struct swap_info_struct *q = swap_info[i]; |
| 1826 | 1834 | ||
| 1827 | if (i == type || !q->swap_file) | 1835 | if (i == type || !q->swap_file) |
| 1828 | continue; | 1836 | continue; |
| @@ -1897,6 +1905,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
| 1897 | 1905 | ||
| 1898 | p->lowest_bit = 1; | 1906 | p->lowest_bit = 1; |
| 1899 | p->cluster_next = 1; | 1907 | p->cluster_next = 1; |
| 1908 | p->cluster_nr = 0; | ||
| 1900 | 1909 | ||
| 1901 | /* | 1910 | /* |
| 1902 | * Find out how many pages are allowed for a single swap | 1911 | * Find out how many pages are allowed for a single swap |
| @@ -1932,13 +1941,13 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
| 1932 | goto bad_swap; | 1941 | goto bad_swap; |
| 1933 | 1942 | ||
| 1934 | /* OK, set up the swap map and apply the bad block list */ | 1943 | /* OK, set up the swap map and apply the bad block list */ |
| 1935 | swap_map = vmalloc(maxpages * sizeof(short)); | 1944 | swap_map = vmalloc(maxpages); |
| 1936 | if (!swap_map) { | 1945 | if (!swap_map) { |
| 1937 | error = -ENOMEM; | 1946 | error = -ENOMEM; |
| 1938 | goto bad_swap; | 1947 | goto bad_swap; |
| 1939 | } | 1948 | } |
| 1940 | 1949 | ||
| 1941 | memset(swap_map, 0, maxpages * sizeof(short)); | 1950 | memset(swap_map, 0, maxpages); |
| 1942 | for (i = 0; i < swap_header->info.nr_badpages; i++) { | 1951 | for (i = 0; i < swap_header->info.nr_badpages; i++) { |
| 1943 | int page_nr = swap_header->info.badpages[i]; | 1952 | int page_nr = swap_header->info.badpages[i]; |
| 1944 | if (page_nr <= 0 || page_nr >= swap_header->info.last_page) { | 1953 | if (page_nr <= 0 || page_nr >= swap_header->info.last_page) { |
| @@ -2003,18 +2012,16 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
| 2003 | 2012 | ||
| 2004 | /* insert swap space into swap_list: */ | 2013 | /* insert swap space into swap_list: */ |
| 2005 | prev = -1; | 2014 | prev = -1; |
| 2006 | for (i = swap_list.head; i >= 0; i = swap_info[i].next) { | 2015 | for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { |
| 2007 | if (p->prio >= swap_info[i].prio) { | 2016 | if (p->prio >= swap_info[i]->prio) |
| 2008 | break; | 2017 | break; |
| 2009 | } | ||
| 2010 | prev = i; | 2018 | prev = i; |
| 2011 | } | 2019 | } |
| 2012 | p->next = i; | 2020 | p->next = i; |
| 2013 | if (prev < 0) { | 2021 | if (prev < 0) |
| 2014 | swap_list.head = swap_list.next = p - swap_info; | 2022 | swap_list.head = swap_list.next = type; |
| 2015 | } else { | 2023 | else |
| 2016 | swap_info[prev].next = p - swap_info; | 2024 | swap_info[prev]->next = type; |
| 2017 | } | ||
| 2018 | spin_unlock(&swap_lock); | 2025 | spin_unlock(&swap_lock); |
| 2019 | mutex_unlock(&swapon_mutex); | 2026 | mutex_unlock(&swapon_mutex); |
| 2020 | error = 0; | 2027 | error = 0; |
| @@ -2051,15 +2058,15 @@ out: | |||
| 2051 | 2058 | ||
| 2052 | void si_swapinfo(struct sysinfo *val) | 2059 | void si_swapinfo(struct sysinfo *val) |
| 2053 | { | 2060 | { |
| 2054 | unsigned int i; | 2061 | unsigned int type; |
| 2055 | unsigned long nr_to_be_unused = 0; | 2062 | unsigned long nr_to_be_unused = 0; |
| 2056 | 2063 | ||
| 2057 | spin_lock(&swap_lock); | 2064 | spin_lock(&swap_lock); |
| 2058 | for (i = 0; i < nr_swapfiles; i++) { | 2065 | for (type = 0; type < nr_swapfiles; type++) { |
| 2059 | if (!(swap_info[i].flags & SWP_USED) || | 2066 | struct swap_info_struct *si = swap_info[type]; |
| 2060 | (swap_info[i].flags & SWP_WRITEOK)) | 2067 | |
| 2061 | continue; | 2068 | if ((si->flags & SWP_USED) && !(si->flags & SWP_WRITEOK)) |
| 2062 | nr_to_be_unused += swap_info[i].inuse_pages; | 2069 | nr_to_be_unused += si->inuse_pages; |
| 2063 | } | 2070 | } |
| 2064 | val->freeswap = nr_swap_pages + nr_to_be_unused; | 2071 | val->freeswap = nr_swap_pages + nr_to_be_unused; |
| 2065 | val->totalswap = total_swap_pages + nr_to_be_unused; | 2072 | val->totalswap = total_swap_pages + nr_to_be_unused; |
| @@ -2069,101 +2076,107 @@ void si_swapinfo(struct sysinfo *val) | |||
| 2069 | /* | 2076 | /* |
| 2070 | * Verify that a swap entry is valid and increment its swap map count. | 2077 | * Verify that a swap entry is valid and increment its swap map count. |
| 2071 | * | 2078 | * |
| 2072 | * Note: if swap_map[] reaches SWAP_MAP_MAX the entries are treated as | ||
| 2073 | * "permanent", but will be reclaimed by the next swapoff. | ||
| 2074 | * Returns error code in following case. | 2079 | * Returns error code in following case. |
| 2075 | * - success -> 0 | 2080 | * - success -> 0 |
| 2076 | * - swp_entry is invalid -> EINVAL | 2081 | * - swp_entry is invalid -> EINVAL |
| 2077 | * - swp_entry is migration entry -> EINVAL | 2082 | * - swp_entry is migration entry -> EINVAL |
| 2078 | * - swap-cache reference is requested but there is already one. -> EEXIST | 2083 | * - swap-cache reference is requested but there is already one. -> EEXIST |
| 2079 | * - swap-cache reference is requested but the entry is not used. -> ENOENT | 2084 | * - swap-cache reference is requested but the entry is not used. -> ENOENT |
| 2085 | * - swap-mapped reference requested but needs continued swap count. -> ENOMEM | ||
| 2080 | */ | 2086 | */ |
| 2081 | static int __swap_duplicate(swp_entry_t entry, bool cache) | 2087 | static int __swap_duplicate(swp_entry_t entry, unsigned char usage) |
| 2082 | { | 2088 | { |
| 2083 | struct swap_info_struct * p; | 2089 | struct swap_info_struct *p; |
| 2084 | unsigned long offset, type; | 2090 | unsigned long offset, type; |
| 2085 | int result = -EINVAL; | 2091 | unsigned char count; |
| 2086 | int count; | 2092 | unsigned char has_cache; |
| 2087 | bool has_cache; | 2093 | int err = -EINVAL; |
| 2088 | 2094 | ||
| 2089 | if (non_swap_entry(entry)) | 2095 | if (non_swap_entry(entry)) |
| 2090 | return -EINVAL; | 2096 | goto out; |
| 2091 | 2097 | ||
| 2092 | type = swp_type(entry); | 2098 | type = swp_type(entry); |
| 2093 | if (type >= nr_swapfiles) | 2099 | if (type >= nr_swapfiles) |
| 2094 | goto bad_file; | 2100 | goto bad_file; |
| 2095 | p = type + swap_info; | 2101 | p = swap_info[type]; |
| 2096 | offset = swp_offset(entry); | 2102 | offset = swp_offset(entry); |
| 2097 | 2103 | ||
| 2098 | spin_lock(&swap_lock); | 2104 | spin_lock(&swap_lock); |
| 2099 | |||
| 2100 | if (unlikely(offset >= p->max)) | 2105 | if (unlikely(offset >= p->max)) |
| 2101 | goto unlock_out; | 2106 | goto unlock_out; |
| 2102 | 2107 | ||
| 2103 | count = swap_count(p->swap_map[offset]); | 2108 | count = p->swap_map[offset]; |
| 2104 | has_cache = swap_has_cache(p->swap_map[offset]); | 2109 | has_cache = count & SWAP_HAS_CACHE; |
| 2110 | count &= ~SWAP_HAS_CACHE; | ||
| 2111 | err = 0; | ||
| 2105 | 2112 | ||
| 2106 | if (cache == SWAP_CACHE) { /* called for swapcache/swapin-readahead */ | 2113 | if (usage == SWAP_HAS_CACHE) { |
| 2107 | 2114 | ||
| 2108 | /* set SWAP_HAS_CACHE if there is no cache and entry is used */ | 2115 | /* set SWAP_HAS_CACHE if there is no cache and entry is used */ |
| 2109 | if (!has_cache && count) { | 2116 | if (!has_cache && count) |
| 2110 | p->swap_map[offset] = encode_swapmap(count, true); | 2117 | has_cache = SWAP_HAS_CACHE; |
| 2111 | result = 0; | 2118 | else if (has_cache) /* someone else added cache */ |
| 2112 | } else if (has_cache) /* someone added cache */ | 2119 | err = -EEXIST; |
| 2113 | result = -EEXIST; | 2120 | else /* no users remaining */ |
| 2114 | else if (!count) /* no users */ | 2121 | err = -ENOENT; |
| 2115 | result = -ENOENT; | ||
| 2116 | 2122 | ||
| 2117 | } else if (count || has_cache) { | 2123 | } else if (count || has_cache) { |
| 2118 | if (count < SWAP_MAP_MAX - 1) { | 2124 | |
| 2119 | p->swap_map[offset] = encode_swapmap(count + 1, | 2125 | if ((count & ~COUNT_CONTINUED) < SWAP_MAP_MAX) |
| 2120 | has_cache); | 2126 | count += usage; |
| 2121 | result = 0; | 2127 | else if ((count & ~COUNT_CONTINUED) > SWAP_MAP_MAX) |
| 2122 | } else if (count <= SWAP_MAP_MAX) { | 2128 | err = -EINVAL; |
| 2123 | if (swap_overflow++ < 5) | 2129 | else if (swap_count_continued(p, offset, count)) |
| 2124 | printk(KERN_WARNING | 2130 | count = COUNT_CONTINUED; |
| 2125 | "swap_dup: swap entry overflow\n"); | 2131 | else |
| 2126 | p->swap_map[offset] = encode_swapmap(SWAP_MAP_MAX, | 2132 | err = -ENOMEM; |
| 2127 | has_cache); | ||
| 2128 | result = 0; | ||
| 2129 | } | ||
| 2130 | } else | 2133 | } else |
| 2131 | result = -ENOENT; /* unused swap entry */ | 2134 | err = -ENOENT; /* unused swap entry */ |
| 2135 | |||
| 2136 | p->swap_map[offset] = count | has_cache; | ||
| 2137 | |||
| 2132 | unlock_out: | 2138 | unlock_out: |
| 2133 | spin_unlock(&swap_lock); | 2139 | spin_unlock(&swap_lock); |
| 2134 | out: | 2140 | out: |
| 2135 | return result; | 2141 | return err; |
| 2136 | 2142 | ||
| 2137 | bad_file: | 2143 | bad_file: |
| 2138 | printk(KERN_ERR "swap_dup: %s%08lx\n", Bad_file, entry.val); | 2144 | printk(KERN_ERR "swap_dup: %s%08lx\n", Bad_file, entry.val); |
| 2139 | goto out; | 2145 | goto out; |
| 2140 | } | 2146 | } |
| 2147 | |||
| 2148 | /* | ||
| 2149 | * Help swapoff by noting that swap entry belongs to shmem/tmpfs | ||
| 2150 | * (in which case its reference count is never incremented). | ||
| 2151 | */ | ||
| 2152 | void swap_shmem_alloc(swp_entry_t entry) | ||
| 2153 | { | ||
| 2154 | __swap_duplicate(entry, SWAP_MAP_SHMEM); | ||
| 2155 | } | ||
| 2156 | |||
| 2141 | /* | 2157 | /* |
| 2142 | * increase reference count of swap entry by 1. | 2158 | * increase reference count of swap entry by 1. |
| 2143 | */ | 2159 | */ |
| 2144 | void swap_duplicate(swp_entry_t entry) | 2160 | int swap_duplicate(swp_entry_t entry) |
| 2145 | { | 2161 | { |
| 2146 | __swap_duplicate(entry, SWAP_MAP); | 2162 | int err = 0; |
| 2163 | |||
| 2164 | while (!err && __swap_duplicate(entry, 1) == -ENOMEM) | ||
| 2165 | err = add_swap_count_continuation(entry, GFP_ATOMIC); | ||
| 2166 | return err; | ||
| 2147 | } | 2167 | } |
| 2148 | 2168 | ||
| 2149 | /* | 2169 | /* |
| 2150 | * @entry: swap entry for which we allocate swap cache. | 2170 | * @entry: swap entry for which we allocate swap cache. |
| 2151 | * | 2171 | * |
| 2152 | * Called when allocating swap cache for exising swap entry, | 2172 | * Called when allocating swap cache for existing swap entry, |
| 2153 | * This can return error codes. Returns 0 at success. | 2173 | * This can return error codes. Returns 0 at success. |
| 2154 | * -EBUSY means there is a swap cache. | 2174 | * -EBUSY means there is a swap cache. |
| 2155 | * Note: return code is different from swap_duplicate(). | 2175 | * Note: return code is different from swap_duplicate(). |
| 2156 | */ | 2176 | */ |
| 2157 | int swapcache_prepare(swp_entry_t entry) | 2177 | int swapcache_prepare(swp_entry_t entry) |
| 2158 | { | 2178 | { |
| 2159 | return __swap_duplicate(entry, SWAP_CACHE); | 2179 | return __swap_duplicate(entry, SWAP_HAS_CACHE); |
| 2160 | } | ||
| 2161 | |||
| 2162 | |||
| 2163 | struct swap_info_struct * | ||
| 2164 | get_swap_info_struct(unsigned type) | ||
| 2165 | { | ||
| 2166 | return &swap_info[type]; | ||
| 2167 | } | 2180 | } |
| 2168 | 2181 | ||
| 2169 | /* | 2182 | /* |
| @@ -2181,7 +2194,7 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset) | |||
| 2181 | if (!our_page_cluster) /* no readahead */ | 2194 | if (!our_page_cluster) /* no readahead */ |
| 2182 | return 0; | 2195 | return 0; |
| 2183 | 2196 | ||
| 2184 | si = &swap_info[swp_type(entry)]; | 2197 | si = swap_info[swp_type(entry)]; |
| 2185 | target = swp_offset(entry); | 2198 | target = swp_offset(entry); |
| 2186 | base = (target >> our_page_cluster) << our_page_cluster; | 2199 | base = (target >> our_page_cluster) << our_page_cluster; |
| 2187 | end = base + (1 << our_page_cluster); | 2200 | end = base + (1 << our_page_cluster); |
| @@ -2217,3 +2230,219 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset) | |||
| 2217 | *offset = ++toff; | 2230 | *offset = ++toff; |
| 2218 | return nr_pages? ++nr_pages: 0; | 2231 | return nr_pages? ++nr_pages: 0; |
| 2219 | } | 2232 | } |
| 2233 | |||
| 2234 | /* | ||
| 2235 | * add_swap_count_continuation - called when a swap count is duplicated | ||
| 2236 | * beyond SWAP_MAP_MAX, it allocates a new page and links that to the entry's | ||
| 2237 | * page of the original vmalloc'ed swap_map, to hold the continuation count | ||
| 2238 | * (for that entry and for its neighbouring PAGE_SIZE swap entries). Called | ||
| 2239 | * again when count is duplicated beyond SWAP_MAP_MAX * SWAP_CONT_MAX, etc. | ||
| 2240 | * | ||
| 2241 | * These continuation pages are seldom referenced: the common paths all work | ||
| 2242 | * on the original swap_map, only referring to a continuation page when the | ||
| 2243 | * low "digit" of a count is incremented or decremented through SWAP_MAP_MAX. | ||
| 2244 | * | ||
| 2245 | * add_swap_count_continuation(, GFP_ATOMIC) can be called while holding | ||
| 2246 | * page table locks; if it fails, add_swap_count_continuation(, GFP_KERNEL) | ||
| 2247 | * can be called after dropping locks. | ||
| 2248 | */ | ||
| 2249 | int add_swap_count_continuation(swp_entry_t entry, gfp_t gfp_mask) | ||
| 2250 | { | ||
| 2251 | struct swap_info_struct *si; | ||
| 2252 | struct page *head; | ||
| 2253 | struct page *page; | ||
| 2254 | struct page *list_page; | ||
| 2255 | pgoff_t offset; | ||
| 2256 | unsigned char count; | ||
| 2257 | |||
| 2258 | /* | ||
| 2259 | * When debugging, it's easier to use __GFP_ZERO here; but it's better | ||
| 2260 | * for latency not to zero a page while GFP_ATOMIC and holding locks. | ||
| 2261 | */ | ||
| 2262 | page = alloc_page(gfp_mask | __GFP_HIGHMEM); | ||
| 2263 | |||
| 2264 | si = swap_info_get(entry); | ||
| 2265 | if (!si) { | ||
| 2266 | /* | ||
| 2267 | * An acceptable race has occurred since the failing | ||
| 2268 | * __swap_duplicate(): the swap entry has been freed, | ||
| 2269 | * perhaps even the whole swap_map cleared for swapoff. | ||
| 2270 | */ | ||
| 2271 | goto outer; | ||
| 2272 | } | ||
| 2273 | |||
| 2274 | offset = swp_offset(entry); | ||
| 2275 | count = si->swap_map[offset] & ~SWAP_HAS_CACHE; | ||
| 2276 | |||
| 2277 | if ((count & ~COUNT_CONTINUED) != SWAP_MAP_MAX) { | ||
| 2278 | /* | ||
| 2279 | * The higher the swap count, the more likely it is that tasks | ||
| 2280 | * will race to add swap count continuation: we need to avoid | ||
| 2281 | * over-provisioning. | ||
| 2282 | */ | ||
| 2283 | goto out; | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | if (!page) { | ||
| 2287 | spin_unlock(&swap_lock); | ||
| 2288 | return -ENOMEM; | ||
| 2289 | } | ||
| 2290 | |||
| 2291 | /* | ||
| 2292 | * We are fortunate that although vmalloc_to_page uses pte_offset_map, | ||
| 2293 | * no architecture is using highmem pages for kernel pagetables: so it | ||
| 2294 | * will not corrupt the GFP_ATOMIC caller's atomic pagetable kmaps. | ||
| 2295 | */ | ||
| 2296 | head = vmalloc_to_page(si->swap_map + offset); | ||
| 2297 | offset &= ~PAGE_MASK; | ||
| 2298 | |||
| 2299 | /* | ||
| 2300 | * Page allocation does not initialize the page's lru field, | ||
| 2301 | * but it does always reset its private field. | ||
| 2302 | */ | ||
| 2303 | if (!page_private(head)) { | ||
| 2304 | BUG_ON(count & COUNT_CONTINUED); | ||
| 2305 | INIT_LIST_HEAD(&head->lru); | ||
| 2306 | set_page_private(head, SWP_CONTINUED); | ||
| 2307 | si->flags |= SWP_CONTINUED; | ||
| 2308 | } | ||
| 2309 | |||
| 2310 | list_for_each_entry(list_page, &head->lru, lru) { | ||
| 2311 | unsigned char *map; | ||
| 2312 | |||
| 2313 | /* | ||
| 2314 | * If the previous map said no continuation, but we've found | ||
| 2315 | * a continuation page, free our allocation and use this one. | ||
| 2316 | */ | ||
| 2317 | if (!(count & COUNT_CONTINUED)) | ||
| 2318 | goto out; | ||
| 2319 | |||
| 2320 | map = kmap_atomic(list_page, KM_USER0) + offset; | ||
| 2321 | count = *map; | ||
| 2322 | kunmap_atomic(map, KM_USER0); | ||
| 2323 | |||
| 2324 | /* | ||
| 2325 | * If this continuation count now has some space in it, | ||
| 2326 | * free our allocation and use this one. | ||
| 2327 | */ | ||
| 2328 | if ((count & ~COUNT_CONTINUED) != SWAP_CONT_MAX) | ||
| 2329 | goto out; | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | list_add_tail(&page->lru, &head->lru); | ||
| 2333 | page = NULL; /* now it's attached, don't free it */ | ||
| 2334 | out: | ||
| 2335 | spin_unlock(&swap_lock); | ||
| 2336 | outer: | ||
| 2337 | if (page) | ||
| 2338 | __free_page(page); | ||
| 2339 | return 0; | ||
| 2340 | } | ||
| 2341 | |||
| 2342 | /* | ||
| 2343 | * swap_count_continued - when the original swap_map count is incremented | ||
| 2344 | * from SWAP_MAP_MAX, check if there is already a continuation page to carry | ||
| 2345 | * into, carry if so, or else fail until a new continuation page is allocated; | ||
| 2346 | * when the original swap_map count is decremented from 0 with continuation, | ||
| 2347 | * borrow from the continuation and report whether it still holds more. | ||
| 2348 | * Called while __swap_duplicate() or swap_entry_free() holds swap_lock. | ||
| 2349 | */ | ||
| 2350 | static bool swap_count_continued(struct swap_info_struct *si, | ||
| 2351 | pgoff_t offset, unsigned char count) | ||
| 2352 | { | ||
| 2353 | struct page *head; | ||
| 2354 | struct page *page; | ||
| 2355 | unsigned char *map; | ||
| 2356 | |||
| 2357 | head = vmalloc_to_page(si->swap_map + offset); | ||
| 2358 | if (page_private(head) != SWP_CONTINUED) { | ||
| 2359 | BUG_ON(count & COUNT_CONTINUED); | ||
| 2360 | return false; /* need to add count continuation */ | ||
| 2361 | } | ||
| 2362 | |||
| 2363 | offset &= ~PAGE_MASK; | ||
| 2364 | page = list_entry(head->lru.next, struct page, lru); | ||
| 2365 | map = kmap_atomic(page, KM_USER0) + offset; | ||
| 2366 | |||
| 2367 | if (count == SWAP_MAP_MAX) /* initial increment from swap_map */ | ||
| 2368 | goto init_map; /* jump over SWAP_CONT_MAX checks */ | ||
| 2369 | |||
| 2370 | if (count == (SWAP_MAP_MAX | COUNT_CONTINUED)) { /* incrementing */ | ||
| 2371 | /* | ||
| 2372 | * Think of how you add 1 to 999 | ||
| 2373 | */ | ||
| 2374 | while (*map == (SWAP_CONT_MAX | COUNT_CONTINUED)) { | ||
| 2375 | kunmap_atomic(map, KM_USER0); | ||
| 2376 | page = list_entry(page->lru.next, struct page, lru); | ||
| 2377 | BUG_ON(page == head); | ||
| 2378 | map = kmap_atomic(page, KM_USER0) + offset; | ||
| 2379 | } | ||
| 2380 | if (*map == SWAP_CONT_MAX) { | ||
| 2381 | kunmap_atomic(map, KM_USER0); | ||
| 2382 | page = list_entry(page->lru.next, struct page, lru); | ||
| 2383 | if (page == head) | ||
| 2384 | return false; /* add count continuation */ | ||
| 2385 | map = kmap_atomic(page, KM_USER0) + offset; | ||
| 2386 | init_map: *map = 0; /* we didn't zero the page */ | ||
| 2387 | } | ||
| 2388 | *map += 1; | ||
| 2389 | kunmap_atomic(map, KM_USER0); | ||
| 2390 | page = list_entry(page->lru.prev, struct page, lru); | ||
| 2391 | while (page != head) { | ||
| 2392 | map = kmap_atomic(page, KM_USER0) + offset; | ||
| 2393 | *map = COUNT_CONTINUED; | ||
| 2394 | kunmap_atomic(map, KM_USER0); | ||
| 2395 | page = list_entry(page->lru.prev, struct page, lru); | ||
| 2396 | } | ||
| 2397 | return true; /* incremented */ | ||
| 2398 | |||
| 2399 | } else { /* decrementing */ | ||
| 2400 | /* | ||
| 2401 | * Think of how you subtract 1 from 1000 | ||
| 2402 | */ | ||
| 2403 | BUG_ON(count != COUNT_CONTINUED); | ||
| 2404 | while (*map == COUNT_CONTINUED) { | ||
| 2405 | kunmap_atomic(map, KM_USER0); | ||
| 2406 | page = list_entry(page->lru.next, struct page, lru); | ||
| 2407 | BUG_ON(page == head); | ||
| 2408 | map = kmap_atomic(page, KM_USER0) + offset; | ||
| 2409 | } | ||
| 2410 | BUG_ON(*map == 0); | ||
| 2411 | *map -= 1; | ||
| 2412 | if (*map == 0) | ||
| 2413 | count = 0; | ||
| 2414 | kunmap_atomic(map, KM_USER0); | ||
| 2415 | page = list_entry(page->lru.prev, struct page, lru); | ||
| 2416 | while (page != head) { | ||
| 2417 | map = kmap_atomic(page, KM_USER0) + offset; | ||
| 2418 | *map = SWAP_CONT_MAX | count; | ||
| 2419 | count = COUNT_CONTINUED; | ||
| 2420 | kunmap_atomic(map, KM_USER0); | ||
| 2421 | page = list_entry(page->lru.prev, struct page, lru); | ||
| 2422 | } | ||
| 2423 | return count == COUNT_CONTINUED; | ||
| 2424 | } | ||
| 2425 | } | ||
| 2426 | |||
| 2427 | /* | ||
| 2428 | * free_swap_count_continuations - swapoff free all the continuation pages | ||
| 2429 | * appended to the swap_map, after swap_map is quiesced, before vfree'ing it. | ||
| 2430 | */ | ||
| 2431 | static void free_swap_count_continuations(struct swap_info_struct *si) | ||
| 2432 | { | ||
| 2433 | pgoff_t offset; | ||
| 2434 | |||
| 2435 | for (offset = 0; offset < si->max; offset += PAGE_SIZE) { | ||
| 2436 | struct page *head; | ||
| 2437 | head = vmalloc_to_page(si->swap_map + offset); | ||
| 2438 | if (page_private(head)) { | ||
| 2439 | struct list_head *this, *next; | ||
| 2440 | list_for_each_safe(this, next, &head->lru) { | ||
| 2441 | struct page *page; | ||
| 2442 | page = list_entry(this, struct page, lru); | ||
| 2443 | list_del(this); | ||
| 2444 | __free_page(page); | ||
| 2445 | } | ||
| 2446 | } | ||
| 2447 | } | ||
| 2448 | } | ||
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 9b08d790df6f..37e69295f250 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
| @@ -1411,6 +1411,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, | |||
| 1411 | { | 1411 | { |
| 1412 | struct page **pages; | 1412 | struct page **pages; |
| 1413 | unsigned int nr_pages, array_size, i; | 1413 | unsigned int nr_pages, array_size, i; |
| 1414 | gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO; | ||
| 1414 | 1415 | ||
| 1415 | nr_pages = (area->size - PAGE_SIZE) >> PAGE_SHIFT; | 1416 | nr_pages = (area->size - PAGE_SIZE) >> PAGE_SHIFT; |
| 1416 | array_size = (nr_pages * sizeof(struct page *)); | 1417 | array_size = (nr_pages * sizeof(struct page *)); |
| @@ -1418,13 +1419,11 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, | |||
| 1418 | area->nr_pages = nr_pages; | 1419 | area->nr_pages = nr_pages; |
| 1419 | /* Please note that the recursion is strictly bounded. */ | 1420 | /* Please note that the recursion is strictly bounded. */ |
| 1420 | if (array_size > PAGE_SIZE) { | 1421 | if (array_size > PAGE_SIZE) { |
| 1421 | pages = __vmalloc_node(array_size, 1, gfp_mask | __GFP_ZERO, | 1422 | pages = __vmalloc_node(array_size, 1, nested_gfp|__GFP_HIGHMEM, |
| 1422 | PAGE_KERNEL, node, caller); | 1423 | PAGE_KERNEL, node, caller); |
| 1423 | area->flags |= VM_VPAGES; | 1424 | area->flags |= VM_VPAGES; |
| 1424 | } else { | 1425 | } else { |
| 1425 | pages = kmalloc_node(array_size, | 1426 | pages = kmalloc_node(array_size, nested_gfp, node); |
| 1426 | (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO, | ||
| 1427 | node); | ||
| 1428 | } | 1427 | } |
| 1429 | area->pages = pages; | 1428 | area->pages = pages; |
| 1430 | area->caller = caller; | 1429 | area->caller = caller; |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 777af57fd8c8..885207a6b6b7 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -55,6 +55,11 @@ struct scan_control { | |||
| 55 | /* Number of pages freed so far during a call to shrink_zones() */ | 55 | /* Number of pages freed so far during a call to shrink_zones() */ |
| 56 | unsigned long nr_reclaimed; | 56 | unsigned long nr_reclaimed; |
| 57 | 57 | ||
| 58 | /* How many pages shrink_list() should reclaim */ | ||
| 59 | unsigned long nr_to_reclaim; | ||
| 60 | |||
| 61 | unsigned long hibernation_mode; | ||
| 62 | |||
| 58 | /* This context's GFP mask */ | 63 | /* This context's GFP mask */ |
| 59 | gfp_t gfp_mask; | 64 | gfp_t gfp_mask; |
| 60 | 65 | ||
| @@ -66,12 +71,6 @@ struct scan_control { | |||
| 66 | /* Can pages be swapped as part of reclaim? */ | 71 | /* Can pages be swapped as part of reclaim? */ |
| 67 | int may_swap; | 72 | int may_swap; |
| 68 | 73 | ||
| 69 | /* This context's SWAP_CLUSTER_MAX. If freeing memory for | ||
| 70 | * suspend, we effectively ignore SWAP_CLUSTER_MAX. | ||
| 71 | * In this context, it doesn't matter that we scan the | ||
| 72 | * whole list at once. */ | ||
| 73 | int swap_cluster_max; | ||
| 74 | |||
| 75 | int swappiness; | 74 | int swappiness; |
| 76 | 75 | ||
| 77 | int all_unreclaimable; | 76 | int all_unreclaimable; |
| @@ -358,7 +357,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping, | |||
| 358 | * stalls if we need to run get_block(). We could test | 357 | * stalls if we need to run get_block(). We could test |
| 359 | * PagePrivate for that. | 358 | * PagePrivate for that. |
| 360 | * | 359 | * |
| 361 | * If this process is currently in generic_file_write() against | 360 | * If this process is currently in __generic_file_aio_write() against |
| 362 | * this page's queue, we can perform writeback even if that | 361 | * this page's queue, we can perform writeback even if that |
| 363 | * will block. | 362 | * will block. |
| 364 | * | 363 | * |
| @@ -1132,7 +1131,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, | |||
| 1132 | unsigned long nr_anon; | 1131 | unsigned long nr_anon; |
| 1133 | unsigned long nr_file; | 1132 | unsigned long nr_file; |
| 1134 | 1133 | ||
| 1135 | nr_taken = sc->isolate_pages(sc->swap_cluster_max, | 1134 | nr_taken = sc->isolate_pages(SWAP_CLUSTER_MAX, |
| 1136 | &page_list, &nr_scan, sc->order, mode, | 1135 | &page_list, &nr_scan, sc->order, mode, |
| 1137 | zone, sc->mem_cgroup, 0, file); | 1136 | zone, sc->mem_cgroup, 0, file); |
| 1138 | 1137 | ||
| @@ -1166,10 +1165,8 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, | |||
| 1166 | __mod_zone_page_state(zone, NR_ISOLATED_ANON, nr_anon); | 1165 | __mod_zone_page_state(zone, NR_ISOLATED_ANON, nr_anon); |
| 1167 | __mod_zone_page_state(zone, NR_ISOLATED_FILE, nr_file); | 1166 | __mod_zone_page_state(zone, NR_ISOLATED_FILE, nr_file); |
| 1168 | 1167 | ||
| 1169 | reclaim_stat->recent_scanned[0] += count[LRU_INACTIVE_ANON]; | 1168 | reclaim_stat->recent_scanned[0] += nr_anon; |
| 1170 | reclaim_stat->recent_scanned[0] += count[LRU_ACTIVE_ANON]; | 1169 | reclaim_stat->recent_scanned[1] += nr_file; |
| 1171 | reclaim_stat->recent_scanned[1] += count[LRU_INACTIVE_FILE]; | ||
| 1172 | reclaim_stat->recent_scanned[1] += count[LRU_ACTIVE_FILE]; | ||
| 1173 | 1170 | ||
| 1174 | spin_unlock_irq(&zone->lru_lock); | 1171 | spin_unlock_irq(&zone->lru_lock); |
| 1175 | 1172 | ||
| @@ -1464,20 +1461,26 @@ static int inactive_file_is_low(struct zone *zone, struct scan_control *sc) | |||
| 1464 | return low; | 1461 | return low; |
| 1465 | } | 1462 | } |
| 1466 | 1463 | ||
| 1464 | static int inactive_list_is_low(struct zone *zone, struct scan_control *sc, | ||
| 1465 | int file) | ||
| 1466 | { | ||
| 1467 | if (file) | ||
| 1468 | return inactive_file_is_low(zone, sc); | ||
| 1469 | else | ||
| 1470 | return inactive_anon_is_low(zone, sc); | ||
| 1471 | } | ||
| 1472 | |||
| 1467 | static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan, | 1473 | static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan, |
| 1468 | struct zone *zone, struct scan_control *sc, int priority) | 1474 | struct zone *zone, struct scan_control *sc, int priority) |
| 1469 | { | 1475 | { |
| 1470 | int file = is_file_lru(lru); | 1476 | int file = is_file_lru(lru); |
| 1471 | 1477 | ||
| 1472 | if (lru == LRU_ACTIVE_FILE && inactive_file_is_low(zone, sc)) { | 1478 | if (is_active_lru(lru)) { |
| 1473 | shrink_active_list(nr_to_scan, zone, sc, priority, file); | 1479 | if (inactive_list_is_low(zone, sc, file)) |
| 1480 | shrink_active_list(nr_to_scan, zone, sc, priority, file); | ||
| 1474 | return 0; | 1481 | return 0; |
| 1475 | } | 1482 | } |
| 1476 | 1483 | ||
| 1477 | if (lru == LRU_ACTIVE_ANON && inactive_anon_is_low(zone, sc)) { | ||
| 1478 | shrink_active_list(nr_to_scan, zone, sc, priority, file); | ||
| 1479 | return 0; | ||
| 1480 | } | ||
| 1481 | return shrink_inactive_list(nr_to_scan, zone, sc, priority, file); | 1484 | return shrink_inactive_list(nr_to_scan, zone, sc, priority, file); |
| 1482 | } | 1485 | } |
| 1483 | 1486 | ||
| @@ -1567,15 +1570,14 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc, | |||
| 1567 | * until we collected @swap_cluster_max pages to scan. | 1570 | * until we collected @swap_cluster_max pages to scan. |
| 1568 | */ | 1571 | */ |
| 1569 | static unsigned long nr_scan_try_batch(unsigned long nr_to_scan, | 1572 | static unsigned long nr_scan_try_batch(unsigned long nr_to_scan, |
| 1570 | unsigned long *nr_saved_scan, | 1573 | unsigned long *nr_saved_scan) |
| 1571 | unsigned long swap_cluster_max) | ||
| 1572 | { | 1574 | { |
| 1573 | unsigned long nr; | 1575 | unsigned long nr; |
| 1574 | 1576 | ||
| 1575 | *nr_saved_scan += nr_to_scan; | 1577 | *nr_saved_scan += nr_to_scan; |
| 1576 | nr = *nr_saved_scan; | 1578 | nr = *nr_saved_scan; |
| 1577 | 1579 | ||
| 1578 | if (nr >= swap_cluster_max) | 1580 | if (nr >= SWAP_CLUSTER_MAX) |
| 1579 | *nr_saved_scan = 0; | 1581 | *nr_saved_scan = 0; |
| 1580 | else | 1582 | else |
| 1581 | nr = 0; | 1583 | nr = 0; |
| @@ -1594,7 +1596,7 @@ static void shrink_zone(int priority, struct zone *zone, | |||
| 1594 | unsigned long percent[2]; /* anon @ 0; file @ 1 */ | 1596 | unsigned long percent[2]; /* anon @ 0; file @ 1 */ |
| 1595 | enum lru_list l; | 1597 | enum lru_list l; |
| 1596 | unsigned long nr_reclaimed = sc->nr_reclaimed; | 1598 | unsigned long nr_reclaimed = sc->nr_reclaimed; |
| 1597 | unsigned long swap_cluster_max = sc->swap_cluster_max; | 1599 | unsigned long nr_to_reclaim = sc->nr_to_reclaim; |
| 1598 | struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc); | 1600 | struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc); |
| 1599 | int noswap = 0; | 1601 | int noswap = 0; |
| 1600 | 1602 | ||
| @@ -1616,15 +1618,15 @@ static void shrink_zone(int priority, struct zone *zone, | |||
| 1616 | scan = (scan * percent[file]) / 100; | 1618 | scan = (scan * percent[file]) / 100; |
| 1617 | } | 1619 | } |
| 1618 | nr[l] = nr_scan_try_batch(scan, | 1620 | nr[l] = nr_scan_try_batch(scan, |
| 1619 | &reclaim_stat->nr_saved_scan[l], | 1621 | &reclaim_stat->nr_saved_scan[l]); |
| 1620 | swap_cluster_max); | ||
| 1621 | } | 1622 | } |
| 1622 | 1623 | ||
| 1623 | while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || | 1624 | while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || |
| 1624 | nr[LRU_INACTIVE_FILE]) { | 1625 | nr[LRU_INACTIVE_FILE]) { |
| 1625 | for_each_evictable_lru(l) { | 1626 | for_each_evictable_lru(l) { |
| 1626 | if (nr[l]) { | 1627 | if (nr[l]) { |
| 1627 | nr_to_scan = min(nr[l], swap_cluster_max); | 1628 | nr_to_scan = min_t(unsigned long, |
| 1629 | nr[l], SWAP_CLUSTER_MAX); | ||
| 1628 | nr[l] -= nr_to_scan; | 1630 | nr[l] -= nr_to_scan; |
| 1629 | 1631 | ||
| 1630 | nr_reclaimed += shrink_list(l, nr_to_scan, | 1632 | nr_reclaimed += shrink_list(l, nr_to_scan, |
| @@ -1639,8 +1641,7 @@ static void shrink_zone(int priority, struct zone *zone, | |||
| 1639 | * with multiple processes reclaiming pages, the total | 1641 | * with multiple processes reclaiming pages, the total |
| 1640 | * freeing target can get unreasonably large. | 1642 | * freeing target can get unreasonably large. |
| 1641 | */ | 1643 | */ |
| 1642 | if (nr_reclaimed > swap_cluster_max && | 1644 | if (nr_reclaimed >= nr_to_reclaim && priority < DEF_PRIORITY) |
| 1643 | priority < DEF_PRIORITY && !current_is_kswapd()) | ||
| 1644 | break; | 1645 | break; |
| 1645 | } | 1646 | } |
| 1646 | 1647 | ||
| @@ -1738,6 +1739,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
| 1738 | struct zoneref *z; | 1739 | struct zoneref *z; |
| 1739 | struct zone *zone; | 1740 | struct zone *zone; |
| 1740 | enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask); | 1741 | enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask); |
| 1742 | unsigned long writeback_threshold; | ||
| 1741 | 1743 | ||
| 1742 | delayacct_freepages_start(); | 1744 | delayacct_freepages_start(); |
| 1743 | 1745 | ||
| @@ -1773,7 +1775,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
| 1773 | } | 1775 | } |
| 1774 | } | 1776 | } |
| 1775 | total_scanned += sc->nr_scanned; | 1777 | total_scanned += sc->nr_scanned; |
| 1776 | if (sc->nr_reclaimed >= sc->swap_cluster_max) { | 1778 | if (sc->nr_reclaimed >= sc->nr_to_reclaim) { |
| 1777 | ret = sc->nr_reclaimed; | 1779 | ret = sc->nr_reclaimed; |
| 1778 | goto out; | 1780 | goto out; |
| 1779 | } | 1781 | } |
| @@ -1785,14 +1787,15 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
| 1785 | * that's undesirable in laptop mode, where we *want* lumpy | 1787 | * that's undesirable in laptop mode, where we *want* lumpy |
| 1786 | * writeout. So in laptop mode, write out the whole world. | 1788 | * writeout. So in laptop mode, write out the whole world. |
| 1787 | */ | 1789 | */ |
| 1788 | if (total_scanned > sc->swap_cluster_max + | 1790 | writeback_threshold = sc->nr_to_reclaim + sc->nr_to_reclaim / 2; |
| 1789 | sc->swap_cluster_max / 2) { | 1791 | if (total_scanned > writeback_threshold) { |
| 1790 | wakeup_flusher_threads(laptop_mode ? 0 : total_scanned); | 1792 | wakeup_flusher_threads(laptop_mode ? 0 : total_scanned); |
| 1791 | sc->may_writepage = 1; | 1793 | sc->may_writepage = 1; |
| 1792 | } | 1794 | } |
| 1793 | 1795 | ||
| 1794 | /* Take a nap, wait for some writeback to complete */ | 1796 | /* Take a nap, wait for some writeback to complete */ |
| 1795 | if (sc->nr_scanned && priority < DEF_PRIORITY - 2) | 1797 | if (!sc->hibernation_mode && sc->nr_scanned && |
| 1798 | priority < DEF_PRIORITY - 2) | ||
| 1796 | congestion_wait(BLK_RW_ASYNC, HZ/10); | 1799 | congestion_wait(BLK_RW_ASYNC, HZ/10); |
| 1797 | } | 1800 | } |
| 1798 | /* top priority shrink_zones still had more to do? don't OOM, then */ | 1801 | /* top priority shrink_zones still had more to do? don't OOM, then */ |
| @@ -1831,7 +1834,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order, | |||
| 1831 | struct scan_control sc = { | 1834 | struct scan_control sc = { |
| 1832 | .gfp_mask = gfp_mask, | 1835 | .gfp_mask = gfp_mask, |
| 1833 | .may_writepage = !laptop_mode, | 1836 | .may_writepage = !laptop_mode, |
| 1834 | .swap_cluster_max = SWAP_CLUSTER_MAX, | 1837 | .nr_to_reclaim = SWAP_CLUSTER_MAX, |
| 1835 | .may_unmap = 1, | 1838 | .may_unmap = 1, |
| 1836 | .may_swap = 1, | 1839 | .may_swap = 1, |
| 1837 | .swappiness = vm_swappiness, | 1840 | .swappiness = vm_swappiness, |
| @@ -1855,7 +1858,6 @@ unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem, | |||
| 1855 | .may_writepage = !laptop_mode, | 1858 | .may_writepage = !laptop_mode, |
| 1856 | .may_unmap = 1, | 1859 | .may_unmap = 1, |
| 1857 | .may_swap = !noswap, | 1860 | .may_swap = !noswap, |
| 1858 | .swap_cluster_max = SWAP_CLUSTER_MAX, | ||
| 1859 | .swappiness = swappiness, | 1861 | .swappiness = swappiness, |
| 1860 | .order = 0, | 1862 | .order = 0, |
| 1861 | .mem_cgroup = mem, | 1863 | .mem_cgroup = mem, |
| @@ -1889,7 +1891,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
| 1889 | .may_writepage = !laptop_mode, | 1891 | .may_writepage = !laptop_mode, |
| 1890 | .may_unmap = 1, | 1892 | .may_unmap = 1, |
| 1891 | .may_swap = !noswap, | 1893 | .may_swap = !noswap, |
| 1892 | .swap_cluster_max = SWAP_CLUSTER_MAX, | 1894 | .nr_to_reclaim = SWAP_CLUSTER_MAX, |
| 1893 | .swappiness = swappiness, | 1895 | .swappiness = swappiness, |
| 1894 | .order = 0, | 1896 | .order = 0, |
| 1895 | .mem_cgroup = mem_cont, | 1897 | .mem_cgroup = mem_cont, |
| @@ -1904,6 +1906,30 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
| 1904 | } | 1906 | } |
| 1905 | #endif | 1907 | #endif |
| 1906 | 1908 | ||
| 1909 | /* is kswapd sleeping prematurely? */ | ||
| 1910 | static int sleeping_prematurely(pg_data_t *pgdat, int order, long remaining) | ||
| 1911 | { | ||
| 1912 | int i; | ||
| 1913 | |||
| 1914 | /* If a direct reclaimer woke kswapd within HZ/10, it's premature */ | ||
| 1915 | if (remaining) | ||
| 1916 | return 1; | ||
| 1917 | |||
| 1918 | /* If after HZ/10, a zone is below the high mark, it's premature */ | ||
| 1919 | for (i = 0; i < pgdat->nr_zones; i++) { | ||
| 1920 | struct zone *zone = pgdat->node_zones + i; | ||
| 1921 | |||
| 1922 | if (!populated_zone(zone)) | ||
| 1923 | continue; | ||
| 1924 | |||
| 1925 | if (!zone_watermark_ok(zone, order, high_wmark_pages(zone), | ||
| 1926 | 0, 0)) | ||
| 1927 | return 1; | ||
| 1928 | } | ||
| 1929 | |||
| 1930 | return 0; | ||
| 1931 | } | ||
| 1932 | |||
| 1907 | /* | 1933 | /* |
| 1908 | * For kswapd, balance_pgdat() will work across all this node's zones until | 1934 | * For kswapd, balance_pgdat() will work across all this node's zones until |
| 1909 | * they are all at high_wmark_pages(zone). | 1935 | * they are all at high_wmark_pages(zone). |
| @@ -1936,7 +1962,11 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order) | |||
| 1936 | .gfp_mask = GFP_KERNEL, | 1962 | .gfp_mask = GFP_KERNEL, |
| 1937 | .may_unmap = 1, | 1963 | .may_unmap = 1, |
| 1938 | .may_swap = 1, | 1964 | .may_swap = 1, |
| 1939 | .swap_cluster_max = SWAP_CLUSTER_MAX, | 1965 | /* |
| 1966 | * kswapd doesn't want to be bailed out while reclaim. because | ||
| 1967 | * we want to put equal scanning pressure on each zone. | ||
| 1968 | */ | ||
| 1969 | .nr_to_reclaim = ULONG_MAX, | ||
| 1940 | .swappiness = vm_swappiness, | 1970 | .swappiness = vm_swappiness, |
| 1941 | .order = order, | 1971 | .order = order, |
| 1942 | .mem_cgroup = NULL, | 1972 | .mem_cgroup = NULL, |
| @@ -1961,6 +1991,7 @@ loop_again: | |||
| 1961 | for (priority = DEF_PRIORITY; priority >= 0; priority--) { | 1991 | for (priority = DEF_PRIORITY; priority >= 0; priority--) { |
| 1962 | int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ | 1992 | int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ |
| 1963 | unsigned long lru_pages = 0; | 1993 | unsigned long lru_pages = 0; |
| 1994 | int has_under_min_watermark_zone = 0; | ||
| 1964 | 1995 | ||
| 1965 | /* The swap token gets in the way of swapout... */ | 1996 | /* The swap token gets in the way of swapout... */ |
| 1966 | if (!priority) | 1997 | if (!priority) |
| @@ -2067,6 +2098,15 @@ loop_again: | |||
| 2067 | if (total_scanned > SWAP_CLUSTER_MAX * 2 && | 2098 | if (total_scanned > SWAP_CLUSTER_MAX * 2 && |
| 2068 | total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2) | 2099 | total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2) |
| 2069 | sc.may_writepage = 1; | 2100 | sc.may_writepage = 1; |
| 2101 | |||
| 2102 | /* | ||
| 2103 | * We are still under min water mark. it mean we have | ||
| 2104 | * GFP_ATOMIC allocation failure risk. Hurry up! | ||
| 2105 | */ | ||
| 2106 | if (!zone_watermark_ok(zone, order, min_wmark_pages(zone), | ||
| 2107 | end_zone, 0)) | ||
| 2108 | has_under_min_watermark_zone = 1; | ||
| 2109 | |||
| 2070 | } | 2110 | } |
| 2071 | if (all_zones_ok) | 2111 | if (all_zones_ok) |
| 2072 | break; /* kswapd: all done */ | 2112 | break; /* kswapd: all done */ |
| @@ -2074,8 +2114,12 @@ loop_again: | |||
| 2074 | * OK, kswapd is getting into trouble. Take a nap, then take | 2114 | * OK, kswapd is getting into trouble. Take a nap, then take |
| 2075 | * another pass across the zones. | 2115 | * another pass across the zones. |
| 2076 | */ | 2116 | */ |
| 2077 | if (total_scanned && priority < DEF_PRIORITY - 2) | 2117 | if (total_scanned && (priority < DEF_PRIORITY - 2)) { |
| 2078 | congestion_wait(BLK_RW_ASYNC, HZ/10); | 2118 | if (has_under_min_watermark_zone) |
| 2119 | count_vm_event(KSWAPD_SKIP_CONGESTION_WAIT); | ||
| 2120 | else | ||
| 2121 | congestion_wait(BLK_RW_ASYNC, HZ/10); | ||
| 2122 | } | ||
| 2079 | 2123 | ||
| 2080 | /* | 2124 | /* |
| 2081 | * We do this so kswapd doesn't build up large priorities for | 2125 | * We do this so kswapd doesn't build up large priorities for |
| @@ -2173,6 +2217,7 @@ static int kswapd(void *p) | |||
| 2173 | order = 0; | 2217 | order = 0; |
| 2174 | for ( ; ; ) { | 2218 | for ( ; ; ) { |
| 2175 | unsigned long new_order; | 2219 | unsigned long new_order; |
| 2220 | int ret; | ||
| 2176 | 2221 | ||
| 2177 | prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); | 2222 | prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); |
| 2178 | new_order = pgdat->kswapd_max_order; | 2223 | new_order = pgdat->kswapd_max_order; |
| @@ -2184,19 +2229,45 @@ static int kswapd(void *p) | |||
| 2184 | */ | 2229 | */ |
| 2185 | order = new_order; | 2230 | order = new_order; |
| 2186 | } else { | 2231 | } else { |
| 2187 | if (!freezing(current)) | 2232 | if (!freezing(current) && !kthread_should_stop()) { |
| 2188 | schedule(); | 2233 | long remaining = 0; |
| 2234 | |||
| 2235 | /* Try to sleep for a short interval */ | ||
| 2236 | if (!sleeping_prematurely(pgdat, order, remaining)) { | ||
| 2237 | remaining = schedule_timeout(HZ/10); | ||
| 2238 | finish_wait(&pgdat->kswapd_wait, &wait); | ||
| 2239 | prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); | ||
| 2240 | } | ||
| 2241 | |||
| 2242 | /* | ||
| 2243 | * After a short sleep, check if it was a | ||
| 2244 | * premature sleep. If not, then go fully | ||
| 2245 | * to sleep until explicitly woken up | ||
| 2246 | */ | ||
| 2247 | if (!sleeping_prematurely(pgdat, order, remaining)) | ||
| 2248 | schedule(); | ||
| 2249 | else { | ||
| 2250 | if (remaining) | ||
| 2251 | count_vm_event(KSWAPD_LOW_WMARK_HIT_QUICKLY); | ||
| 2252 | else | ||
| 2253 | count_vm_event(KSWAPD_HIGH_WMARK_HIT_QUICKLY); | ||
| 2254 | } | ||
| 2255 | } | ||
| 2189 | 2256 | ||
| 2190 | order = pgdat->kswapd_max_order; | 2257 | order = pgdat->kswapd_max_order; |
| 2191 | } | 2258 | } |
| 2192 | finish_wait(&pgdat->kswapd_wait, &wait); | 2259 | finish_wait(&pgdat->kswapd_wait, &wait); |
| 2193 | 2260 | ||
| 2194 | if (!try_to_freeze()) { | 2261 | ret = try_to_freeze(); |
| 2195 | /* We can speed up thawing tasks if we don't call | 2262 | if (kthread_should_stop()) |
| 2196 | * balance_pgdat after returning from the refrigerator | 2263 | break; |
| 2197 | */ | 2264 | |
| 2265 | /* | ||
| 2266 | * We can speed up thawing tasks if we don't call balance_pgdat | ||
| 2267 | * after returning from the refrigerator | ||
| 2268 | */ | ||
| 2269 | if (!ret) | ||
| 2198 | balance_pgdat(pgdat, order); | 2270 | balance_pgdat(pgdat, order); |
| 2199 | } | ||
| 2200 | } | 2271 | } |
| 2201 | return 0; | 2272 | return 0; |
| 2202 | } | 2273 | } |
| @@ -2260,148 +2331,43 @@ unsigned long zone_reclaimable_pages(struct zone *zone) | |||
| 2260 | 2331 | ||
| 2261 | #ifdef CONFIG_HIBERNATION | 2332 | #ifdef CONFIG_HIBERNATION |
| 2262 | /* | 2333 | /* |
| 2263 | * Helper function for shrink_all_memory(). Tries to reclaim 'nr_pages' pages | 2334 | * Try to free `nr_to_reclaim' of memory, system-wide, and return the number of |
| 2264 | * from LRU lists system-wide, for given pass and priority. | ||
| 2265 | * | ||
| 2266 | * For pass > 3 we also try to shrink the LRU lists that contain a few pages | ||
| 2267 | */ | ||
| 2268 | static void shrink_all_zones(unsigned long nr_pages, int prio, | ||
| 2269 | int pass, struct scan_control *sc) | ||
| 2270 | { | ||
| 2271 | struct zone *zone; | ||
| 2272 | unsigned long nr_reclaimed = 0; | ||
| 2273 | struct zone_reclaim_stat *reclaim_stat; | ||
| 2274 | |||
| 2275 | for_each_populated_zone(zone) { | ||
| 2276 | enum lru_list l; | ||
| 2277 | |||
| 2278 | if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY) | ||
| 2279 | continue; | ||
| 2280 | |||
| 2281 | for_each_evictable_lru(l) { | ||
| 2282 | enum zone_stat_item ls = NR_LRU_BASE + l; | ||
| 2283 | unsigned long lru_pages = zone_page_state(zone, ls); | ||
| 2284 | |||
| 2285 | /* For pass = 0, we don't shrink the active list */ | ||
| 2286 | if (pass == 0 && (l == LRU_ACTIVE_ANON || | ||
| 2287 | l == LRU_ACTIVE_FILE)) | ||
| 2288 | continue; | ||
| 2289 | |||
| 2290 | reclaim_stat = get_reclaim_stat(zone, sc); | ||
| 2291 | reclaim_stat->nr_saved_scan[l] += | ||
| 2292 | (lru_pages >> prio) + 1; | ||
| 2293 | if (reclaim_stat->nr_saved_scan[l] | ||
| 2294 | >= nr_pages || pass > 3) { | ||
| 2295 | unsigned long nr_to_scan; | ||
| 2296 | |||
| 2297 | reclaim_stat->nr_saved_scan[l] = 0; | ||
| 2298 | nr_to_scan = min(nr_pages, lru_pages); | ||
| 2299 | nr_reclaimed += shrink_list(l, nr_to_scan, zone, | ||
| 2300 | sc, prio); | ||
| 2301 | if (nr_reclaimed >= nr_pages) { | ||
| 2302 | sc->nr_reclaimed += nr_reclaimed; | ||
| 2303 | return; | ||
| 2304 | } | ||
| 2305 | } | ||
| 2306 | } | ||
| 2307 | } | ||
| 2308 | sc->nr_reclaimed += nr_reclaimed; | ||
| 2309 | } | ||
| 2310 | |||
| 2311 | /* | ||
| 2312 | * Try to free `nr_pages' of memory, system-wide, and return the number of | ||
| 2313 | * freed pages. | 2335 | * freed pages. |
| 2314 | * | 2336 | * |
| 2315 | * Rather than trying to age LRUs the aim is to preserve the overall | 2337 | * Rather than trying to age LRUs the aim is to preserve the overall |
| 2316 | * LRU order by reclaiming preferentially | 2338 | * LRU order by reclaiming preferentially |
| 2317 | * inactive > active > active referenced > active mapped | 2339 | * inactive > active > active referenced > active mapped |
| 2318 | */ | 2340 | */ |
| 2319 | unsigned long shrink_all_memory(unsigned long nr_pages) | 2341 | unsigned long shrink_all_memory(unsigned long nr_to_reclaim) |
| 2320 | { | 2342 | { |
| 2321 | unsigned long lru_pages, nr_slab; | ||
| 2322 | int pass; | ||
| 2323 | struct reclaim_state reclaim_state; | 2343 | struct reclaim_state reclaim_state; |
| 2324 | struct scan_control sc = { | 2344 | struct scan_control sc = { |
| 2325 | .gfp_mask = GFP_KERNEL, | 2345 | .gfp_mask = GFP_HIGHUSER_MOVABLE, |
| 2326 | .may_unmap = 0, | 2346 | .may_swap = 1, |
| 2347 | .may_unmap = 1, | ||
| 2327 | .may_writepage = 1, | 2348 | .may_writepage = 1, |
| 2349 | .nr_to_reclaim = nr_to_reclaim, | ||
| 2350 | .hibernation_mode = 1, | ||
| 2351 | .swappiness = vm_swappiness, | ||
| 2352 | .order = 0, | ||
| 2328 | .isolate_pages = isolate_pages_global, | 2353 | .isolate_pages = isolate_pages_global, |
| 2329 | .nr_reclaimed = 0, | ||
| 2330 | }; | 2354 | }; |
| 2355 | struct zonelist * zonelist = node_zonelist(numa_node_id(), sc.gfp_mask); | ||
| 2356 | struct task_struct *p = current; | ||
| 2357 | unsigned long nr_reclaimed; | ||
| 2331 | 2358 | ||
| 2332 | current->reclaim_state = &reclaim_state; | 2359 | p->flags |= PF_MEMALLOC; |
| 2333 | 2360 | lockdep_set_current_reclaim_state(sc.gfp_mask); | |
| 2334 | lru_pages = global_reclaimable_pages(); | 2361 | reclaim_state.reclaimed_slab = 0; |
| 2335 | nr_slab = global_page_state(NR_SLAB_RECLAIMABLE); | 2362 | p->reclaim_state = &reclaim_state; |
| 2336 | /* If slab caches are huge, it's better to hit them first */ | ||
| 2337 | while (nr_slab >= lru_pages) { | ||
| 2338 | reclaim_state.reclaimed_slab = 0; | ||
| 2339 | shrink_slab(nr_pages, sc.gfp_mask, lru_pages); | ||
| 2340 | if (!reclaim_state.reclaimed_slab) | ||
| 2341 | break; | ||
| 2342 | |||
| 2343 | sc.nr_reclaimed += reclaim_state.reclaimed_slab; | ||
| 2344 | if (sc.nr_reclaimed >= nr_pages) | ||
| 2345 | goto out; | ||
| 2346 | |||
| 2347 | nr_slab -= reclaim_state.reclaimed_slab; | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | /* | ||
| 2351 | * We try to shrink LRUs in 5 passes: | ||
| 2352 | * 0 = Reclaim from inactive_list only | ||
| 2353 | * 1 = Reclaim from active list but don't reclaim mapped | ||
| 2354 | * 2 = 2nd pass of type 1 | ||
| 2355 | * 3 = Reclaim mapped (normal reclaim) | ||
| 2356 | * 4 = 2nd pass of type 3 | ||
| 2357 | */ | ||
| 2358 | for (pass = 0; pass < 5; pass++) { | ||
| 2359 | int prio; | ||
| 2360 | |||
| 2361 | /* Force reclaiming mapped pages in the passes #3 and #4 */ | ||
| 2362 | if (pass > 2) | ||
| 2363 | sc.may_unmap = 1; | ||
| 2364 | |||
| 2365 | for (prio = DEF_PRIORITY; prio >= 0; prio--) { | ||
| 2366 | unsigned long nr_to_scan = nr_pages - sc.nr_reclaimed; | ||
| 2367 | |||
| 2368 | sc.nr_scanned = 0; | ||
| 2369 | sc.swap_cluster_max = nr_to_scan; | ||
| 2370 | shrink_all_zones(nr_to_scan, prio, pass, &sc); | ||
| 2371 | if (sc.nr_reclaimed >= nr_pages) | ||
| 2372 | goto out; | ||
| 2373 | |||
| 2374 | reclaim_state.reclaimed_slab = 0; | ||
| 2375 | shrink_slab(sc.nr_scanned, sc.gfp_mask, | ||
| 2376 | global_reclaimable_pages()); | ||
| 2377 | sc.nr_reclaimed += reclaim_state.reclaimed_slab; | ||
| 2378 | if (sc.nr_reclaimed >= nr_pages) | ||
| 2379 | goto out; | ||
| 2380 | |||
| 2381 | if (sc.nr_scanned && prio < DEF_PRIORITY - 2) | ||
| 2382 | congestion_wait(BLK_RW_ASYNC, HZ / 10); | ||
| 2383 | } | ||
| 2384 | } | ||
| 2385 | |||
| 2386 | /* | ||
| 2387 | * If sc.nr_reclaimed = 0, we could not shrink LRUs, but there may be | ||
| 2388 | * something in slab caches | ||
| 2389 | */ | ||
| 2390 | if (!sc.nr_reclaimed) { | ||
| 2391 | do { | ||
| 2392 | reclaim_state.reclaimed_slab = 0; | ||
| 2393 | shrink_slab(nr_pages, sc.gfp_mask, | ||
| 2394 | global_reclaimable_pages()); | ||
| 2395 | sc.nr_reclaimed += reclaim_state.reclaimed_slab; | ||
| 2396 | } while (sc.nr_reclaimed < nr_pages && | ||
| 2397 | reclaim_state.reclaimed_slab > 0); | ||
| 2398 | } | ||
| 2399 | 2363 | ||
| 2364 | nr_reclaimed = do_try_to_free_pages(zonelist, &sc); | ||
| 2400 | 2365 | ||
| 2401 | out: | 2366 | p->reclaim_state = NULL; |
| 2402 | current->reclaim_state = NULL; | 2367 | lockdep_clear_current_reclaim_state(); |
| 2368 | p->flags &= ~PF_MEMALLOC; | ||
| 2403 | 2369 | ||
| 2404 | return sc.nr_reclaimed; | 2370 | return nr_reclaimed; |
| 2405 | } | 2371 | } |
| 2406 | #endif /* CONFIG_HIBERNATION */ | 2372 | #endif /* CONFIG_HIBERNATION */ |
| 2407 | 2373 | ||
| @@ -2451,6 +2417,17 @@ int kswapd_run(int nid) | |||
| 2451 | return ret; | 2417 | return ret; |
| 2452 | } | 2418 | } |
| 2453 | 2419 | ||
| 2420 | /* | ||
| 2421 | * Called by memory hotplug when all memory in a node is offlined. | ||
| 2422 | */ | ||
| 2423 | void kswapd_stop(int nid) | ||
| 2424 | { | ||
| 2425 | struct task_struct *kswapd = NODE_DATA(nid)->kswapd; | ||
| 2426 | |||
| 2427 | if (kswapd) | ||
| 2428 | kthread_stop(kswapd); | ||
| 2429 | } | ||
| 2430 | |||
| 2454 | static int __init kswapd_init(void) | 2431 | static int __init kswapd_init(void) |
| 2455 | { | 2432 | { |
| 2456 | int nid; | 2433 | int nid; |
| @@ -2553,8 +2530,8 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | |||
| 2553 | .may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE), | 2530 | .may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE), |
| 2554 | .may_unmap = !!(zone_reclaim_mode & RECLAIM_SWAP), | 2531 | .may_unmap = !!(zone_reclaim_mode & RECLAIM_SWAP), |
| 2555 | .may_swap = 1, | 2532 | .may_swap = 1, |
| 2556 | .swap_cluster_max = max_t(unsigned long, nr_pages, | 2533 | .nr_to_reclaim = max_t(unsigned long, nr_pages, |
| 2557 | SWAP_CLUSTER_MAX), | 2534 | SWAP_CLUSTER_MAX), |
| 2558 | .gfp_mask = gfp_mask, | 2535 | .gfp_mask = gfp_mask, |
| 2559 | .swappiness = vm_swappiness, | 2536 | .swappiness = vm_swappiness, |
| 2560 | .order = order, | 2537 | .order = order, |
diff --git a/mm/vmstat.c b/mm/vmstat.c index dad2327e4580..6051fbab67ba 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
| @@ -683,6 +683,9 @@ static const char * const vmstat_text[] = { | |||
| 683 | "slabs_scanned", | 683 | "slabs_scanned", |
| 684 | "kswapd_steal", | 684 | "kswapd_steal", |
| 685 | "kswapd_inodesteal", | 685 | "kswapd_inodesteal", |
| 686 | "kswapd_low_wmark_hit_quickly", | ||
| 687 | "kswapd_high_wmark_hit_quickly", | ||
| 688 | "kswapd_skip_congestion_wait", | ||
| 686 | "pageoutrun", | 689 | "pageoutrun", |
| 687 | "allocstall", | 690 | "allocstall", |
| 688 | 691 | ||
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index b001c361ad30..4300df35d37d 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h | |||
| @@ -249,6 +249,7 @@ | |||
| 249 | #include <linux/poll.h> | 249 | #include <linux/poll.h> |
| 250 | #include <linux/capability.h> | 250 | #include <linux/capability.h> |
| 251 | #include <linux/ctype.h> /* isspace() */ | 251 | #include <linux/ctype.h> /* isspace() */ |
| 252 | #include <linux/string.h> /* skip_spaces() */ | ||
| 252 | #include <asm/uaccess.h> | 253 | #include <asm/uaccess.h> |
| 253 | #include <linux/init.h> | 254 | #include <linux/init.h> |
| 254 | 255 | ||
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 7dea882dbb75..156020d138b5 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c | |||
| @@ -76,9 +76,8 @@ irnet_ctrl_write(irnet_socket * ap, | |||
| 76 | /* Look at the next command */ | 76 | /* Look at the next command */ |
| 77 | start = next; | 77 | start = next; |
| 78 | 78 | ||
| 79 | /* Scrap whitespaces before the command */ | 79 | /* Scrap whitespaces before the command */ |
| 80 | while(isspace(*start)) | 80 | start = skip_spaces(start); |
| 81 | start++; | ||
| 82 | 81 | ||
| 83 | /* ',' is our command separator */ | 82 | /* ',' is our command separator */ |
| 84 | next = strchr(start, ','); | 83 | next = strchr(start, ','); |
| @@ -133,8 +132,7 @@ irnet_ctrl_write(irnet_socket * ap, | |||
| 133 | char * endp; | 132 | char * endp; |
| 134 | 133 | ||
| 135 | /* Scrap whitespaces before the command */ | 134 | /* Scrap whitespaces before the command */ |
| 136 | while(isspace(*begp)) | 135 | begp = skip_spaces(begp); |
| 137 | begp++; | ||
| 138 | 136 | ||
| 139 | /* Convert argument to a number (last arg is the base) */ | 137 | /* Convert argument to a number (last arg is the base) */ |
| 140 | addr = simple_strtoul(begp, &endp, 16); | 138 | addr = simple_strtoul(begp, &endp, 16); |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 1e428863574f..c18286a2167b 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
| @@ -221,7 +221,7 @@ static int afiucv_pm_restore_thaw(struct device *dev) | |||
| 221 | return 0; | 221 | return 0; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static struct dev_pm_ops afiucv_pm_ops = { | 224 | static const struct dev_pm_ops afiucv_pm_ops = { |
| 225 | .prepare = afiucv_pm_prepare, | 225 | .prepare = afiucv_pm_prepare, |
| 226 | .complete = afiucv_pm_complete, | 226 | .complete = afiucv_pm_complete, |
| 227 | .freeze = afiucv_pm_freeze, | 227 | .freeze = afiucv_pm_freeze, |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 3b1f5f5f8de7..fd8b28361a64 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
| @@ -93,7 +93,7 @@ static int iucv_pm_freeze(struct device *); | |||
| 93 | static int iucv_pm_thaw(struct device *); | 93 | static int iucv_pm_thaw(struct device *); |
| 94 | static int iucv_pm_restore(struct device *); | 94 | static int iucv_pm_restore(struct device *); |
| 95 | 95 | ||
| 96 | static struct dev_pm_ops iucv_pm_ops = { | 96 | static const struct dev_pm_ops iucv_pm_ops = { |
| 97 | .prepare = iucv_pm_prepare, | 97 | .prepare = iucv_pm_prepare, |
| 98 | .complete = iucv_pm_complete, | 98 | .complete = iucv_pm_complete, |
| 99 | .freeze = iucv_pm_freeze, | 99 | .freeze = iucv_pm_freeze, |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index eb0ceb846527..fc70a49c0afd 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
| @@ -482,8 +482,7 @@ static ssize_t recent_old_proc_write(struct file *file, | |||
| 482 | if (copy_from_user(buf, input, size)) | 482 | if (copy_from_user(buf, input, size)) |
| 483 | return -EFAULT; | 483 | return -EFAULT; |
| 484 | 484 | ||
| 485 | while (isspace(*c)) | 485 | c = skip_spaces(c); |
| 486 | c++; | ||
| 487 | 486 | ||
| 488 | if (size - (c - buf) < 5) | 487 | if (size - (c - buf) < 5) |
| 489 | return c - buf; | 488 | return c - buf; |
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 81a67a458e78..445e8845f0a4 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | use strict; | 13 | use strict; |
| 14 | 14 | ||
| 15 | my $P = $0; | 15 | my $P = $0; |
| 16 | my $V = '0.21'; | 16 | my $V = '0.23'; |
| 17 | 17 | ||
| 18 | use Getopt::Long qw(:config no_auto_abbrev); | 18 | use Getopt::Long qw(:config no_auto_abbrev); |
| 19 | 19 | ||
| @@ -23,16 +23,19 @@ my $email_usename = 1; | |||
| 23 | my $email_maintainer = 1; | 23 | my $email_maintainer = 1; |
| 24 | my $email_list = 1; | 24 | my $email_list = 1; |
| 25 | my $email_subscriber_list = 0; | 25 | my $email_subscriber_list = 0; |
| 26 | my $email_git = 1; | ||
| 27 | my $email_git_penguin_chiefs = 0; | 26 | my $email_git_penguin_chiefs = 0; |
| 27 | my $email_git = 1; | ||
| 28 | my $email_git_blame = 0; | ||
| 28 | my $email_git_min_signatures = 1; | 29 | my $email_git_min_signatures = 1; |
| 29 | my $email_git_max_maintainers = 5; | 30 | my $email_git_max_maintainers = 5; |
| 30 | my $email_git_min_percent = 5; | 31 | my $email_git_min_percent = 5; |
| 31 | my $email_git_since = "1-year-ago"; | 32 | my $email_git_since = "1-year-ago"; |
| 32 | my $email_git_blame = 0; | 33 | my $email_hg_since = "-365"; |
| 33 | my $email_remove_duplicates = 1; | 34 | my $email_remove_duplicates = 1; |
| 34 | my $output_multiline = 1; | 35 | my $output_multiline = 1; |
| 35 | my $output_separator = ", "; | 36 | my $output_separator = ", "; |
| 37 | my $output_roles = 0; | ||
| 38 | my $output_rolestats = 0; | ||
| 36 | my $scm = 0; | 39 | my $scm = 0; |
| 37 | my $web = 0; | 40 | my $web = 0; |
| 38 | my $subsystem = 0; | 41 | my $subsystem = 0; |
| @@ -64,21 +67,52 @@ my $penguin_chiefs = "\(" . join("|",@penguin_chief_names) . "\)"; | |||
| 64 | my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; | 67 | my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; |
| 65 | my $rfc822_char = '[\\000-\\377]'; | 68 | my $rfc822_char = '[\\000-\\377]'; |
| 66 | 69 | ||
| 70 | # VCS command support: class-like functions and strings | ||
| 71 | |||
| 72 | my %VCS_cmds; | ||
| 73 | |||
| 74 | my %VCS_cmds_git = ( | ||
| 75 | "execute_cmd" => \&git_execute_cmd, | ||
| 76 | "available" => '(which("git") ne "") && (-d ".git")', | ||
| 77 | "find_signers_cmd" => "git log --since=\$email_git_since -- \$file", | ||
| 78 | "find_commit_signers_cmd" => "git log -1 \$commit", | ||
| 79 | "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file", | ||
| 80 | "blame_file_cmd" => "git blame -l \$file", | ||
| 81 | "commit_pattern" => "^commit [0-9a-f]{40,40}", | ||
| 82 | "blame_commit_pattern" => "^([0-9a-f]+) " | ||
| 83 | ); | ||
| 84 | |||
| 85 | my %VCS_cmds_hg = ( | ||
| 86 | "execute_cmd" => \&hg_execute_cmd, | ||
| 87 | "available" => '(which("hg") ne "") && (-d ".hg")', | ||
| 88 | "find_signers_cmd" => | ||
| 89 | "hg log --date=\$email_hg_since" . | ||
| 90 | " --template='commit {node}\\n{desc}\\n' -- \$file", | ||
| 91 | "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit", | ||
| 92 | "blame_range_cmd" => "", # not supported | ||
| 93 | "blame_file_cmd" => "hg blame -c \$file", | ||
| 94 | "commit_pattern" => "^commit [0-9a-f]{40,40}", | ||
| 95 | "blame_commit_pattern" => "^([0-9a-f]+):" | ||
| 96 | ); | ||
| 97 | |||
| 67 | if (!GetOptions( | 98 | if (!GetOptions( |
| 68 | 'email!' => \$email, | 99 | 'email!' => \$email, |
| 69 | 'git!' => \$email_git, | 100 | 'git!' => \$email_git, |
| 101 | 'git-blame!' => \$email_git_blame, | ||
| 70 | 'git-chief-penguins!' => \$email_git_penguin_chiefs, | 102 | 'git-chief-penguins!' => \$email_git_penguin_chiefs, |
| 71 | 'git-min-signatures=i' => \$email_git_min_signatures, | 103 | 'git-min-signatures=i' => \$email_git_min_signatures, |
| 72 | 'git-max-maintainers=i' => \$email_git_max_maintainers, | 104 | 'git-max-maintainers=i' => \$email_git_max_maintainers, |
| 73 | 'git-min-percent=i' => \$email_git_min_percent, | 105 | 'git-min-percent=i' => \$email_git_min_percent, |
| 74 | 'git-since=s' => \$email_git_since, | 106 | 'git-since=s' => \$email_git_since, |
| 75 | 'git-blame!' => \$email_git_blame, | 107 | 'hg-since=s' => \$email_hg_since, |
| 76 | 'remove-duplicates!' => \$email_remove_duplicates, | 108 | 'remove-duplicates!' => \$email_remove_duplicates, |
| 77 | 'm!' => \$email_maintainer, | 109 | 'm!' => \$email_maintainer, |
| 78 | 'n!' => \$email_usename, | 110 | 'n!' => \$email_usename, |
| 79 | 'l!' => \$email_list, | 111 | 'l!' => \$email_list, |
| 80 | 's!' => \$email_subscriber_list, | 112 | 's!' => \$email_subscriber_list, |
| 81 | 'multiline!' => \$output_multiline, | 113 | 'multiline!' => \$output_multiline, |
| 114 | 'roles!' => \$output_roles, | ||
| 115 | 'rolestats!' => \$output_rolestats, | ||
| 82 | 'separator=s' => \$output_separator, | 116 | 'separator=s' => \$output_separator, |
| 83 | 'subsystem!' => \$subsystem, | 117 | 'subsystem!' => \$subsystem, |
| 84 | 'status!' => \$status, | 118 | 'status!' => \$status, |
| @@ -90,8 +124,7 @@ if (!GetOptions( | |||
| 90 | 'v|version' => \$version, | 124 | 'v|version' => \$version, |
| 91 | 'h|help' => \$help, | 125 | 'h|help' => \$help, |
| 92 | )) { | 126 | )) { |
| 93 | usage(); | 127 | die "$P: invalid argument - use --help if necessary\n"; |
| 94 | die "$P: invalid argument\n"; | ||
| 95 | } | 128 | } |
| 96 | 129 | ||
| 97 | if ($help != 0) { | 130 | if ($help != 0) { |
| @@ -113,6 +146,10 @@ if ($output_separator ne ", ") { | |||
| 113 | $output_multiline = 0; | 146 | $output_multiline = 0; |
| 114 | } | 147 | } |
| 115 | 148 | ||
| 149 | if ($output_rolestats) { | ||
| 150 | $output_roles = 1; | ||
| 151 | } | ||
| 152 | |||
| 116 | my $selections = $email + $scm + $status + $subsystem + $web; | 153 | my $selections = $email + $scm + $status + $subsystem + $web; |
| 117 | if ($selections == 0) { | 154 | if ($selections == 0) { |
| 118 | usage(); | 155 | usage(); |
| @@ -175,7 +212,7 @@ if ($email_remove_duplicates) { | |||
| 175 | next if ($line =~ m/^\s*$/); | 212 | next if ($line =~ m/^\s*$/); |
| 176 | 213 | ||
| 177 | my ($name, $address) = parse_email($line); | 214 | my ($name, $address) = parse_email($line); |
| 178 | $line = format_email($name, $address); | 215 | $line = format_email($name, $address, $email_usename); |
| 179 | 216 | ||
| 180 | next if ($line =~ m/^\s*$/); | 217 | next if ($line =~ m/^\s*$/); |
| 181 | 218 | ||
| @@ -207,12 +244,10 @@ foreach my $file (@ARGV) { | |||
| 207 | push(@files, $file); | 244 | push(@files, $file); |
| 208 | if (-f $file && $keywords) { | 245 | if (-f $file && $keywords) { |
| 209 | open(FILE, "<$file") or die "$P: Can't open ${file}\n"; | 246 | open(FILE, "<$file") or die "$P: Can't open ${file}\n"; |
| 210 | while (<FILE>) { | 247 | my $text = do { local($/) ; <FILE> }; |
| 211 | my $patch_line = $_; | 248 | foreach my $line (keys %keyword_hash) { |
| 212 | foreach my $line (keys %keyword_hash) { | 249 | if ($text =~ m/$keyword_hash{$line}/x) { |
| 213 | if ($patch_line =~ m/^.*$keyword_hash{$line}/x) { | 250 | push(@keyword_tvi, $line); |
| 214 | push(@keyword_tvi, $line); | ||
| 215 | } | ||
| 216 | } | 251 | } |
| 217 | } | 252 | } |
| 218 | close(FILE); | 253 | close(FILE); |
| @@ -304,11 +339,11 @@ foreach my $file (@files) { | |||
| 304 | } | 339 | } |
| 305 | 340 | ||
| 306 | if ($email && $email_git) { | 341 | if ($email && $email_git) { |
| 307 | recent_git_signoffs($file); | 342 | vcs_file_signoffs($file); |
| 308 | } | 343 | } |
| 309 | 344 | ||
| 310 | if ($email && $email_git_blame) { | 345 | if ($email && $email_git_blame) { |
| 311 | git_assign_blame($file); | 346 | vcs_file_blame($file); |
| 312 | } | 347 | } |
| 313 | } | 348 | } |
| 314 | 349 | ||
| @@ -324,11 +359,11 @@ if ($email) { | |||
| 324 | if ($chief =~ m/^(.*):(.*)/) { | 359 | if ($chief =~ m/^(.*):(.*)/) { |
| 325 | my $email_address; | 360 | my $email_address; |
| 326 | 361 | ||
| 327 | $email_address = format_email($1, $2); | 362 | $email_address = format_email($1, $2, $email_usename); |
| 328 | if ($email_git_penguin_chiefs) { | 363 | if ($email_git_penguin_chiefs) { |
| 329 | push(@email_to, $email_address); | 364 | push(@email_to, [$email_address, 'chief penguin']); |
| 330 | } else { | 365 | } else { |
| 331 | @email_to = grep(!/${email_address}/, @email_to); | 366 | @email_to = grep($_->[0] !~ /${email_address}/, @email_to); |
| 332 | } | 367 | } |
| 333 | } | 368 | } |
| 334 | } | 369 | } |
| @@ -342,7 +377,7 @@ if ($email || $email_list) { | |||
| 342 | if ($email_list) { | 377 | if ($email_list) { |
| 343 | @to = (@to, @list_to); | 378 | @to = (@to, @list_to); |
| 344 | } | 379 | } |
| 345 | output(uniq(@to)); | 380 | output(merge_email(@to)); |
| 346 | } | 381 | } |
| 347 | 382 | ||
| 348 | if ($scm) { | 383 | if ($scm) { |
| @@ -398,13 +433,16 @@ MAINTAINER field selection options: | |||
| 398 | --git-min-signatures => number of signatures required (default: 1) | 433 | --git-min-signatures => number of signatures required (default: 1) |
| 399 | --git-max-maintainers => maximum maintainers to add (default: 5) | 434 | --git-max-maintainers => maximum maintainers to add (default: 5) |
| 400 | --git-min-percent => minimum percentage of commits required (default: 5) | 435 | --git-min-percent => minimum percentage of commits required (default: 5) |
| 401 | --git-since => git history to use (default: 1-year-ago) | ||
| 402 | --git-blame => use git blame to find modified commits for patch or file | 436 | --git-blame => use git blame to find modified commits for patch or file |
| 437 | --git-since => git history to use (default: 1-year-ago) | ||
| 438 | --hg-since => hg history to use (default: -365) | ||
| 403 | --m => include maintainer(s) if any | 439 | --m => include maintainer(s) if any |
| 404 | --n => include name 'Full Name <addr\@domain.tld>' | 440 | --n => include name 'Full Name <addr\@domain.tld>' |
| 405 | --l => include list(s) if any | 441 | --l => include list(s) if any |
| 406 | --s => include subscriber only list(s) if any | 442 | --s => include subscriber only list(s) if any |
| 407 | --remove-duplicates => minimize duplicate email names/addresses | 443 | --remove-duplicates => minimize duplicate email names/addresses |
| 444 | --roles => show roles (status:subsystem, git-signer, list, etc...) | ||
| 445 | --rolestats => show roles and statistics (commits/total_commits, %) | ||
| 408 | --scm => print SCM tree(s) if any | 446 | --scm => print SCM tree(s) if any |
| 409 | --status => print status if any | 447 | --status => print status if any |
| 410 | --subsystem => print subsystem name if any | 448 | --subsystem => print subsystem name if any |
| @@ -430,11 +468,24 @@ Notes: | |||
| 430 | directory are examined as git recurses directories. | 468 | directory are examined as git recurses directories. |
| 431 | Any specified X: (exclude) pattern matches are _not_ ignored. | 469 | Any specified X: (exclude) pattern matches are _not_ ignored. |
| 432 | Used with "--nogit", directory is used as a pattern match, | 470 | Used with "--nogit", directory is used as a pattern match, |
| 433 | no individual file within the directory or subdirectory | 471 | no individual file within the directory or subdirectory |
| 434 | is matched. | 472 | is matched. |
| 435 | Used with "--git-blame", does not iterate all files in directory | 473 | Used with "--git-blame", does not iterate all files in directory |
| 436 | Using "--git-blame" is slow and may add old committers and authors | 474 | Using "--git-blame" is slow and may add old committers and authors |
| 437 | that are no longer active maintainers to the output. | 475 | that are no longer active maintainers to the output. |
| 476 | Using "--roles" or "--rolestats" with git send-email --cc-cmd or any | ||
| 477 | other automated tools that expect only ["name"] <email address> | ||
| 478 | may not work because of additional output after <email address>. | ||
| 479 | Using "--rolestats" and "--git-blame" shows the #/total=% commits, | ||
| 480 | not the percentage of the entire file authored. # of commits is | ||
| 481 | not a good measure of amount of code authored. 1 major commit may | ||
| 482 | contain a thousand lines, 5 trivial commits may modify a single line. | ||
| 483 | If git is not installed, but mercurial (hg) is installed and an .hg | ||
| 484 | repository exists, the following options apply to mercurial: | ||
| 485 | --git, | ||
| 486 | --git-min-signatures, --git-max-maintainers, --git-min-percent, and | ||
| 487 | --git-blame | ||
| 488 | Use --hg-since not --git-since to control date selection | ||
| 438 | EOT | 489 | EOT |
| 439 | } | 490 | } |
| 440 | 491 | ||
| @@ -493,7 +544,7 @@ sub parse_email { | |||
| 493 | } | 544 | } |
| 494 | 545 | ||
| 495 | sub format_email { | 546 | sub format_email { |
| 496 | my ($name, $address) = @_; | 547 | my ($name, $address, $usename) = @_; |
| 497 | 548 | ||
| 498 | my $formatted_email; | 549 | my $formatted_email; |
| 499 | 550 | ||
| @@ -506,11 +557,11 @@ sub format_email { | |||
| 506 | $name = "\"$name\""; | 557 | $name = "\"$name\""; |
| 507 | } | 558 | } |
| 508 | 559 | ||
| 509 | if ($email_usename) { | 560 | if ($usename) { |
| 510 | if ("$name" eq "") { | 561 | if ("$name" eq "") { |
| 511 | $formatted_email = "$address"; | 562 | $formatted_email = "$address"; |
| 512 | } else { | 563 | } else { |
| 513 | $formatted_email = "$name <${address}>"; | 564 | $formatted_email = "$name <$address>"; |
| 514 | } | 565 | } |
| 515 | } else { | 566 | } else { |
| 516 | $formatted_email = $address; | 567 | $formatted_email = $address; |
| @@ -547,6 +598,71 @@ sub find_ending_index { | |||
| 547 | return $index; | 598 | return $index; |
| 548 | } | 599 | } |
| 549 | 600 | ||
| 601 | sub get_maintainer_role { | ||
| 602 | my ($index) = @_; | ||
| 603 | |||
| 604 | my $i; | ||
| 605 | my $start = find_starting_index($index); | ||
| 606 | my $end = find_ending_index($index); | ||
| 607 | |||
| 608 | my $role; | ||
| 609 | my $subsystem = $typevalue[$start]; | ||
| 610 | if (length($subsystem) > 20) { | ||
| 611 | $subsystem = substr($subsystem, 0, 17); | ||
| 612 | $subsystem =~ s/\s*$//; | ||
| 613 | $subsystem = $subsystem . "..."; | ||
| 614 | } | ||
| 615 | |||
| 616 | for ($i = $start + 1; $i < $end; $i++) { | ||
| 617 | my $tv = $typevalue[$i]; | ||
| 618 | if ($tv =~ m/^(\C):\s*(.*)/) { | ||
| 619 | my $ptype = $1; | ||
| 620 | my $pvalue = $2; | ||
| 621 | if ($ptype eq "S") { | ||
| 622 | $role = $pvalue; | ||
| 623 | } | ||
| 624 | } | ||
| 625 | } | ||
| 626 | |||
| 627 | $role = lc($role); | ||
| 628 | if ($role eq "supported") { | ||
| 629 | $role = "supporter"; | ||
| 630 | } elsif ($role eq "maintained") { | ||
| 631 | $role = "maintainer"; | ||
| 632 | } elsif ($role eq "odd fixes") { | ||
| 633 | $role = "odd fixer"; | ||
| 634 | } elsif ($role eq "orphan") { | ||
| 635 | $role = "orphan minder"; | ||
| 636 | } elsif ($role eq "obsolete") { | ||
| 637 | $role = "obsolete minder"; | ||
| 638 | } elsif ($role eq "buried alive in reporters") { | ||
| 639 | $role = "chief penguin"; | ||
| 640 | } | ||
| 641 | |||
| 642 | return $role . ":" . $subsystem; | ||
| 643 | } | ||
| 644 | |||
| 645 | sub get_list_role { | ||
| 646 | my ($index) = @_; | ||
| 647 | |||
| 648 | my $i; | ||
| 649 | my $start = find_starting_index($index); | ||
| 650 | my $end = find_ending_index($index); | ||
| 651 | |||
| 652 | my $subsystem = $typevalue[$start]; | ||
| 653 | if (length($subsystem) > 20) { | ||
| 654 | $subsystem = substr($subsystem, 0, 17); | ||
| 655 | $subsystem =~ s/\s*$//; | ||
| 656 | $subsystem = $subsystem . "..."; | ||
| 657 | } | ||
| 658 | |||
| 659 | if ($subsystem eq "THE REST") { | ||
| 660 | $subsystem = ""; | ||
| 661 | } | ||
| 662 | |||
| 663 | return $subsystem; | ||
| 664 | } | ||
| 665 | |||
| 550 | sub add_categories { | 666 | sub add_categories { |
| 551 | my ($index) = @_; | 667 | my ($index) = @_; |
| 552 | 668 | ||
| @@ -564,17 +680,22 @@ sub add_categories { | |||
| 564 | if ($ptype eq "L") { | 680 | if ($ptype eq "L") { |
| 565 | my $list_address = $pvalue; | 681 | my $list_address = $pvalue; |
| 566 | my $list_additional = ""; | 682 | my $list_additional = ""; |
| 683 | my $list_role = get_list_role($i); | ||
| 684 | |||
| 685 | if ($list_role ne "") { | ||
| 686 | $list_role = ":" . $list_role; | ||
| 687 | } | ||
| 567 | if ($list_address =~ m/([^\s]+)\s+(.*)$/) { | 688 | if ($list_address =~ m/([^\s]+)\s+(.*)$/) { |
| 568 | $list_address = $1; | 689 | $list_address = $1; |
| 569 | $list_additional = $2; | 690 | $list_additional = $2; |
| 570 | } | 691 | } |
| 571 | if ($list_additional =~ m/subscribers-only/) { | 692 | if ($list_additional =~ m/subscribers-only/) { |
| 572 | if ($email_subscriber_list) { | 693 | if ($email_subscriber_list) { |
| 573 | push(@list_to, $list_address); | 694 | push(@list_to, [$list_address, "subscriber list${list_role}"]); |
| 574 | } | 695 | } |
| 575 | } else { | 696 | } else { |
| 576 | if ($email_list) { | 697 | if ($email_list) { |
| 577 | push(@list_to, $list_address); | 698 | push(@list_to, [$list_address, "open list${list_role}"]); |
| 578 | } | 699 | } |
| 579 | } | 700 | } |
| 580 | } elsif ($ptype eq "M") { | 701 | } elsif ($ptype eq "M") { |
| @@ -585,13 +706,14 @@ sub add_categories { | |||
| 585 | if ($tv =~ m/^(\C):\s*(.*)/) { | 706 | if ($tv =~ m/^(\C):\s*(.*)/) { |
| 586 | if ($1 eq "P") { | 707 | if ($1 eq "P") { |
| 587 | $name = $2; | 708 | $name = $2; |
| 588 | $pvalue = format_email($name, $address); | 709 | $pvalue = format_email($name, $address, $email_usename); |
| 589 | } | 710 | } |
| 590 | } | 711 | } |
| 591 | } | 712 | } |
| 592 | } | 713 | } |
| 593 | if ($email_maintainer) { | 714 | if ($email_maintainer) { |
| 594 | push_email_addresses($pvalue); | 715 | my $role = get_maintainer_role($i); |
| 716 | push_email_addresses($pvalue, $role); | ||
| 595 | } | 717 | } |
| 596 | } elsif ($ptype eq "T") { | 718 | } elsif ($ptype eq "T") { |
| 597 | push(@scm, $pvalue); | 719 | push(@scm, $pvalue); |
| @@ -618,7 +740,7 @@ sub email_inuse { | |||
| 618 | } | 740 | } |
| 619 | 741 | ||
| 620 | sub push_email_address { | 742 | sub push_email_address { |
| 621 | my ($line) = @_; | 743 | my ($line, $role) = @_; |
| 622 | 744 | ||
| 623 | my ($name, $address) = parse_email($line); | 745 | my ($name, $address) = parse_email($line); |
| 624 | 746 | ||
| @@ -627,9 +749,9 @@ sub push_email_address { | |||
| 627 | } | 749 | } |
| 628 | 750 | ||
| 629 | if (!$email_remove_duplicates) { | 751 | if (!$email_remove_duplicates) { |
| 630 | push(@email_to, format_email($name, $address)); | 752 | push(@email_to, [format_email($name, $address, $email_usename), $role]); |
| 631 | } elsif (!email_inuse($name, $address)) { | 753 | } elsif (!email_inuse($name, $address)) { |
| 632 | push(@email_to, format_email($name, $address)); | 754 | push(@email_to, [format_email($name, $address, $email_usename), $role]); |
| 633 | $email_hash_name{$name}++; | 755 | $email_hash_name{$name}++; |
| 634 | $email_hash_address{$address}++; | 756 | $email_hash_address{$address}++; |
| 635 | } | 757 | } |
| @@ -638,24 +760,52 @@ sub push_email_address { | |||
| 638 | } | 760 | } |
| 639 | 761 | ||
| 640 | sub push_email_addresses { | 762 | sub push_email_addresses { |
| 641 | my ($address) = @_; | 763 | my ($address, $role) = @_; |
| 642 | 764 | ||
| 643 | my @address_list = (); | 765 | my @address_list = (); |
| 644 | 766 | ||
| 645 | if (rfc822_valid($address)) { | 767 | if (rfc822_valid($address)) { |
| 646 | push_email_address($address); | 768 | push_email_address($address, $role); |
| 647 | } elsif (@address_list = rfc822_validlist($address)) { | 769 | } elsif (@address_list = rfc822_validlist($address)) { |
| 648 | my $array_count = shift(@address_list); | 770 | my $array_count = shift(@address_list); |
| 649 | while (my $entry = shift(@address_list)) { | 771 | while (my $entry = shift(@address_list)) { |
| 650 | push_email_address($entry); | 772 | push_email_address($entry, $role); |
| 651 | } | 773 | } |
| 652 | } else { | 774 | } else { |
| 653 | if (!push_email_address($address)) { | 775 | if (!push_email_address($address, $role)) { |
| 654 | warn("Invalid MAINTAINERS address: '" . $address . "'\n"); | 776 | warn("Invalid MAINTAINERS address: '" . $address . "'\n"); |
| 655 | } | 777 | } |
| 656 | } | 778 | } |
| 657 | } | 779 | } |
| 658 | 780 | ||
| 781 | sub add_role { | ||
| 782 | my ($line, $role) = @_; | ||
| 783 | |||
| 784 | my ($name, $address) = parse_email($line); | ||
| 785 | my $email = format_email($name, $address, $email_usename); | ||
| 786 | |||
| 787 | foreach my $entry (@email_to) { | ||
| 788 | if ($email_remove_duplicates) { | ||
| 789 | my ($entry_name, $entry_address) = parse_email($entry->[0]); | ||
| 790 | if ($name eq $entry_name || $address eq $entry_address) { | ||
| 791 | if ($entry->[1] eq "") { | ||
| 792 | $entry->[1] = "$role"; | ||
| 793 | } else { | ||
| 794 | $entry->[1] = "$entry->[1],$role"; | ||
| 795 | } | ||
| 796 | } | ||
| 797 | } else { | ||
| 798 | if ($email eq $entry->[0]) { | ||
| 799 | if ($entry->[1] eq "") { | ||
| 800 | $entry->[1] = "$role"; | ||
| 801 | } else { | ||
| 802 | $entry->[1] = "$entry->[1],$role"; | ||
| 803 | } | ||
| 804 | } | ||
| 805 | } | ||
| 806 | } | ||
| 807 | } | ||
| 808 | |||
| 659 | sub which { | 809 | sub which { |
| 660 | my ($bin) = @_; | 810 | my ($bin) = @_; |
| 661 | 811 | ||
| @@ -669,7 +819,7 @@ sub which { | |||
| 669 | } | 819 | } |
| 670 | 820 | ||
| 671 | sub mailmap { | 821 | sub mailmap { |
| 672 | my @lines = @_; | 822 | my (@lines) = @_; |
| 673 | my %hash; | 823 | my %hash; |
| 674 | 824 | ||
| 675 | foreach my $line (@lines) { | 825 | foreach my $line (@lines) { |
| @@ -678,14 +828,14 @@ sub mailmap { | |||
| 678 | $hash{$name} = $address; | 828 | $hash{$name} = $address; |
| 679 | } elsif ($address ne $hash{$name}) { | 829 | } elsif ($address ne $hash{$name}) { |
| 680 | $address = $hash{$name}; | 830 | $address = $hash{$name}; |
| 681 | $line = format_email($name, $address); | 831 | $line = format_email($name, $address, $email_usename); |
| 682 | } | 832 | } |
| 683 | if (exists($mailmap{$name})) { | 833 | if (exists($mailmap{$name})) { |
| 684 | my $obj = $mailmap{$name}; | 834 | my $obj = $mailmap{$name}; |
| 685 | foreach my $map_address (@$obj) { | 835 | foreach my $map_address (@$obj) { |
| 686 | if (($map_address eq $address) && | 836 | if (($map_address eq $address) && |
| 687 | ($map_address ne $hash{$name})) { | 837 | ($map_address ne $hash{$name})) { |
| 688 | $line = format_email($name, $hash{$name}); | 838 | $line = format_email($name, $hash{$name}, $email_usename); |
| 689 | } | 839 | } |
| 690 | } | 840 | } |
| 691 | } | 841 | } |
| @@ -694,34 +844,38 @@ sub mailmap { | |||
| 694 | return @lines; | 844 | return @lines; |
| 695 | } | 845 | } |
| 696 | 846 | ||
| 697 | sub recent_git_signoffs { | 847 | sub git_execute_cmd { |
| 698 | my ($file) = @_; | 848 | my ($cmd) = @_; |
| 699 | |||
| 700 | my $sign_offs = ""; | ||
| 701 | my $cmd = ""; | ||
| 702 | my $output = ""; | ||
| 703 | my $count = 0; | ||
| 704 | my @lines = (); | 849 | my @lines = (); |
| 705 | my %hash; | ||
| 706 | my $total_sign_offs; | ||
| 707 | 850 | ||
| 708 | if (which("git") eq "") { | 851 | my $output = `$cmd`; |
| 709 | warn("$P: git not found. Add --nogit to options?\n"); | 852 | $output =~ s/^\s*//gm; |
| 710 | return; | 853 | @lines = split("\n", $output); |
| 711 | } | ||
| 712 | if (!(-d ".git")) { | ||
| 713 | warn("$P: .git directory not found. Use a git repository for better results.\n"); | ||
| 714 | warn("$P: perhaps 'git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git'\n"); | ||
| 715 | return; | ||
| 716 | } | ||
| 717 | 854 | ||
| 718 | $cmd = "git log --since=${email_git_since} -- ${file}"; | 855 | return @lines; |
| 856 | } | ||
| 719 | 857 | ||
| 720 | $output = `${cmd}`; | 858 | sub hg_execute_cmd { |
| 721 | $output =~ s/^\s*//gm; | 859 | my ($cmd) = @_; |
| 860 | my @lines = (); | ||
| 722 | 861 | ||
| 862 | my $output = `$cmd`; | ||
| 723 | @lines = split("\n", $output); | 863 | @lines = split("\n", $output); |
| 724 | 864 | ||
| 865 | return @lines; | ||
| 866 | } | ||
| 867 | |||
| 868 | sub vcs_find_signers { | ||
| 869 | my ($cmd) = @_; | ||
| 870 | my @lines = (); | ||
| 871 | my $commits; | ||
| 872 | |||
| 873 | @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); | ||
| 874 | |||
| 875 | my $pattern = $VCS_cmds{"commit_pattern"}; | ||
| 876 | |||
| 877 | $commits = grep(/$pattern/, @lines); # of commits | ||
| 878 | |||
| 725 | @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); | 879 | @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); |
| 726 | if (!$email_git_penguin_chiefs) { | 880 | if (!$email_git_penguin_chiefs) { |
| 727 | @lines = grep(!/${penguin_chiefs}/i, @lines); | 881 | @lines = grep(!/${penguin_chiefs}/i, @lines); |
| @@ -729,111 +883,183 @@ sub recent_git_signoffs { | |||
| 729 | # cut -f2- -d":" | 883 | # cut -f2- -d":" |
| 730 | s/.*:\s*(.+)\s*/$1/ for (@lines); | 884 | s/.*:\s*(.+)\s*/$1/ for (@lines); |
| 731 | 885 | ||
| 732 | $total_sign_offs = @lines; | 886 | ## Reformat email addresses (with names) to avoid badly written signatures |
| 733 | 887 | ||
| 734 | if ($email_remove_duplicates) { | 888 | foreach my $line (@lines) { |
| 735 | @lines = mailmap(@lines); | 889 | my ($name, $address) = parse_email($line); |
| 890 | $line = format_email($name, $address, 1); | ||
| 736 | } | 891 | } |
| 737 | 892 | ||
| 738 | @lines = sort(@lines); | 893 | return ($commits, @lines); |
| 739 | |||
| 740 | # uniq -c | ||
| 741 | $hash{$_}++ for @lines; | ||
| 742 | |||
| 743 | # sort -rn | ||
| 744 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { | ||
| 745 | my $sign_offs = $hash{$line}; | ||
| 746 | $count++; | ||
| 747 | last if ($sign_offs < $email_git_min_signatures || | ||
| 748 | $count > $email_git_max_maintainers || | ||
| 749 | $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); | ||
| 750 | push_email_address($line); | ||
| 751 | } | ||
| 752 | } | 894 | } |
| 753 | 895 | ||
| 754 | sub save_commits { | 896 | sub vcs_save_commits { |
| 755 | my ($cmd, @commits) = @_; | 897 | my ($cmd) = @_; |
| 756 | my $output; | ||
| 757 | my @lines = (); | 898 | my @lines = (); |
| 899 | my @commits = (); | ||
| 758 | 900 | ||
| 759 | $output = `${cmd}`; | 901 | @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); |
| 760 | 902 | ||
| 761 | @lines = split("\n", $output); | ||
| 762 | foreach my $line (@lines) { | 903 | foreach my $line (@lines) { |
| 763 | if ($line =~ m/^(\w+) /) { | 904 | if ($line =~ m/$VCS_cmds{"blame_commit_pattern"}/) { |
| 764 | push (@commits, $1); | 905 | push(@commits, $1); |
| 765 | } | 906 | } |
| 766 | } | 907 | } |
| 908 | |||
| 767 | return @commits; | 909 | return @commits; |
| 768 | } | 910 | } |
| 769 | 911 | ||
| 770 | sub git_assign_blame { | 912 | sub vcs_blame { |
| 771 | my ($file) = @_; | 913 | my ($file) = @_; |
| 772 | |||
| 773 | my @lines = (); | ||
| 774 | my @commits = (); | ||
| 775 | my $cmd; | 914 | my $cmd; |
| 776 | my $output; | 915 | my @commits = (); |
| 777 | my %hash; | 916 | |
| 778 | my $total_sign_offs; | 917 | return @commits if (!(-f $file)); |
| 779 | my $count; | 918 | |
| 919 | if (@range && $VCS_cmds{"blame_range_cmd"} eq "") { | ||
| 920 | my @all_commits = (); | ||
| 921 | |||
| 922 | $cmd = $VCS_cmds{"blame_file_cmd"}; | ||
| 923 | $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd | ||
| 924 | @all_commits = vcs_save_commits($cmd); | ||
| 780 | 925 | ||
| 781 | if (@range) { | ||
| 782 | foreach my $file_range_diff (@range) { | 926 | foreach my $file_range_diff (@range) { |
| 783 | next if (!($file_range_diff =~ m/(.+):(.+):(.+)/)); | 927 | next if (!($file_range_diff =~ m/(.+):(.+):(.+)/)); |
| 784 | my $diff_file = $1; | 928 | my $diff_file = $1; |
| 785 | my $diff_start = $2; | 929 | my $diff_start = $2; |
| 786 | my $diff_length = $3; | 930 | my $diff_length = $3; |
| 787 | next if (!("$file" eq "$diff_file")); | 931 | next if ("$file" ne "$diff_file"); |
| 788 | $cmd = "git blame -l -L $diff_start,+$diff_length $file"; | 932 | for (my $i = $diff_start; $i < $diff_start + $diff_length; $i++) { |
| 789 | @commits = save_commits($cmd, @commits); | 933 | push(@commits, $all_commits[$i]); |
| 934 | } | ||
| 790 | } | 935 | } |
| 791 | } else { | 936 | } elsif (@range) { |
| 792 | if (-f $file) { | 937 | foreach my $file_range_diff (@range) { |
| 793 | $cmd = "git blame -l $file"; | 938 | next if (!($file_range_diff =~ m/(.+):(.+):(.+)/)); |
| 794 | @commits = save_commits($cmd, @commits); | 939 | my $diff_file = $1; |
| 940 | my $diff_start = $2; | ||
| 941 | my $diff_length = $3; | ||
| 942 | next if ("$file" ne "$diff_file"); | ||
| 943 | $cmd = $VCS_cmds{"blame_range_cmd"}; | ||
| 944 | $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd | ||
| 945 | push(@commits, vcs_save_commits($cmd)); | ||
| 795 | } | 946 | } |
| 947 | } else { | ||
| 948 | $cmd = $VCS_cmds{"blame_file_cmd"}; | ||
| 949 | $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd | ||
| 950 | @commits = vcs_save_commits($cmd); | ||
| 796 | } | 951 | } |
| 797 | 952 | ||
| 798 | $total_sign_offs = 0; | 953 | return @commits; |
| 799 | @commits = uniq(@commits); | 954 | } |
| 800 | foreach my $commit (@commits) { | ||
| 801 | $cmd = "git log -1 ${commit}"; | ||
| 802 | 955 | ||
| 803 | $output = `${cmd}`; | 956 | my $printed_novcs = 0; |
| 804 | $output =~ s/^\s*//gm; | 957 | sub vcs_exists { |
| 805 | @lines = split("\n", $output); | 958 | %VCS_cmds = %VCS_cmds_git; |
| 959 | return 1 if eval $VCS_cmds{"available"}; | ||
| 960 | %VCS_cmds = %VCS_cmds_hg; | ||
| 961 | return 1 if eval $VCS_cmds{"available"}; | ||
| 962 | %VCS_cmds = (); | ||
| 963 | if (!$printed_novcs) { | ||
| 964 | warn("$P: No supported VCS found. Add --nogit to options?\n"); | ||
| 965 | warn("Using a git repository produces better results.\n"); | ||
| 966 | warn("Try Linus Torvalds' latest git repository using:\n"); | ||
| 967 | warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n"); | ||
| 968 | $printed_novcs = 1; | ||
| 969 | } | ||
| 970 | return 0; | ||
| 971 | } | ||
| 806 | 972 | ||
| 807 | @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); | 973 | sub vcs_assign { |
| 808 | if (!$email_git_penguin_chiefs) { | 974 | my ($role, $divisor, @lines) = @_; |
| 809 | @lines = grep(!/${penguin_chiefs}/i, @lines); | ||
| 810 | } | ||
| 811 | 975 | ||
| 812 | # cut -f2- -d":" | 976 | my %hash; |
| 813 | s/.*:\s*(.+)\s*/$1/ for (@lines); | 977 | my $count = 0; |
| 814 | 978 | ||
| 815 | $total_sign_offs += @lines; | 979 | return if (@lines <= 0); |
| 816 | 980 | ||
| 817 | if ($email_remove_duplicates) { | 981 | if ($divisor <= 0) { |
| 818 | @lines = mailmap(@lines); | 982 | warn("Bad divisor in " . (caller(0))[3] . ": $divisor\n"); |
| 819 | } | 983 | $divisor = 1; |
| 984 | } | ||
| 820 | 985 | ||
| 821 | $hash{$_}++ for @lines; | 986 | if ($email_remove_duplicates) { |
| 987 | @lines = mailmap(@lines); | ||
| 822 | } | 988 | } |
| 823 | 989 | ||
| 824 | $count = 0; | 990 | @lines = sort(@lines); |
| 991 | |||
| 992 | # uniq -c | ||
| 993 | $hash{$_}++ for @lines; | ||
| 994 | |||
| 995 | # sort -rn | ||
| 825 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { | 996 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { |
| 826 | my $sign_offs = $hash{$line}; | 997 | my $sign_offs = $hash{$line}; |
| 998 | my $percent = $sign_offs * 100 / $divisor; | ||
| 999 | |||
| 1000 | $percent = 100 if ($percent > 100); | ||
| 827 | $count++; | 1001 | $count++; |
| 828 | last if ($sign_offs < $email_git_min_signatures || | 1002 | last if ($sign_offs < $email_git_min_signatures || |
| 829 | $count > $email_git_max_maintainers || | 1003 | $count > $email_git_max_maintainers || |
| 830 | $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); | 1004 | $percent < $email_git_min_percent); |
| 831 | push_email_address($line); | 1005 | push_email_address($line, ''); |
| 1006 | if ($output_rolestats) { | ||
| 1007 | my $fmt_percent = sprintf("%.0f", $percent); | ||
| 1008 | add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%"); | ||
| 1009 | } else { | ||
| 1010 | add_role($line, $role); | ||
| 1011 | } | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | sub vcs_file_signoffs { | ||
| 1016 | my ($file) = @_; | ||
| 1017 | |||
| 1018 | my @signers = (); | ||
| 1019 | my $commits; | ||
| 1020 | |||
| 1021 | return if (!vcs_exists()); | ||
| 1022 | |||
| 1023 | my $cmd = $VCS_cmds{"find_signers_cmd"}; | ||
| 1024 | $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd | ||
| 1025 | |||
| 1026 | ($commits, @signers) = vcs_find_signers($cmd); | ||
| 1027 | vcs_assign("commit_signer", $commits, @signers); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | sub vcs_file_blame { | ||
| 1031 | my ($file) = @_; | ||
| 1032 | |||
| 1033 | my @signers = (); | ||
| 1034 | my @commits = (); | ||
| 1035 | my $total_commits; | ||
| 1036 | |||
| 1037 | return if (!vcs_exists()); | ||
| 1038 | |||
| 1039 | @commits = vcs_blame($file); | ||
| 1040 | @commits = uniq(@commits); | ||
| 1041 | $total_commits = @commits; | ||
| 1042 | |||
| 1043 | foreach my $commit (@commits) { | ||
| 1044 | my $commit_count; | ||
| 1045 | my @commit_signers = (); | ||
| 1046 | |||
| 1047 | my $cmd = $VCS_cmds{"find_commit_signers_cmd"}; | ||
| 1048 | $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd | ||
| 1049 | |||
| 1050 | ($commit_count, @commit_signers) = vcs_find_signers($cmd); | ||
| 1051 | push(@signers, @commit_signers); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | if ($from_filename) { | ||
| 1055 | vcs_assign("commits", $total_commits, @signers); | ||
| 1056 | } else { | ||
| 1057 | vcs_assign("modified commits", $total_commits, @signers); | ||
| 832 | } | 1058 | } |
| 833 | } | 1059 | } |
| 834 | 1060 | ||
| 835 | sub uniq { | 1061 | sub uniq { |
| 836 | my @parms = @_; | 1062 | my (@parms) = @_; |
| 837 | 1063 | ||
| 838 | my %saw; | 1064 | my %saw; |
| 839 | @parms = grep(!$saw{$_}++, @parms); | 1065 | @parms = grep(!$saw{$_}++, @parms); |
| @@ -841,7 +1067,7 @@ sub uniq { | |||
| 841 | } | 1067 | } |
| 842 | 1068 | ||
| 843 | sub sort_and_uniq { | 1069 | sub sort_and_uniq { |
| 844 | my @parms = @_; | 1070 | my (@parms) = @_; |
| 845 | 1071 | ||
| 846 | my %saw; | 1072 | my %saw; |
| 847 | @parms = sort @parms; | 1073 | @parms = sort @parms; |
| @@ -849,8 +1075,27 @@ sub sort_and_uniq { | |||
| 849 | return @parms; | 1075 | return @parms; |
| 850 | } | 1076 | } |
| 851 | 1077 | ||
| 1078 | sub merge_email { | ||
| 1079 | my @lines; | ||
| 1080 | my %saw; | ||
| 1081 | |||
| 1082 | for (@_) { | ||
| 1083 | my ($address, $role) = @$_; | ||
| 1084 | if (!$saw{$address}) { | ||
| 1085 | if ($output_roles) { | ||
| 1086 | push(@lines, "$address ($role)"); | ||
| 1087 | } else { | ||
| 1088 | push(@lines, $address); | ||
| 1089 | } | ||
| 1090 | $saw{$address} = 1; | ||
| 1091 | } | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | return @lines; | ||
| 1095 | } | ||
| 1096 | |||
| 852 | sub output { | 1097 | sub output { |
| 853 | my @parms = @_; | 1098 | my (@parms) = @_; |
| 854 | 1099 | ||
| 855 | if ($output_multiline) { | 1100 | if ($output_multiline) { |
| 856 | foreach my $line (@parms) { | 1101 | foreach my $line (@parms) { |
| @@ -947,11 +1192,9 @@ sub rfc822_validlist ($) { | |||
| 947 | if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so && | 1192 | if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so && |
| 948 | $s =~ m/^$rfc822_char*$/) { | 1193 | $s =~ m/^$rfc822_char*$/) { |
| 949 | while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) { | 1194 | while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) { |
| 950 | push @r, $1; | 1195 | push(@r, $1); |
| 951 | } | 1196 | } |
| 952 | return wantarray ? (scalar(@r), @r) : 1; | 1197 | return wantarray ? (scalar(@r), @r) : 1; |
| 953 | } | 1198 | } |
| 954 | else { | 1199 | return wantarray ? () : 0; |
| 955 | return wantarray ? () : 0; | ||
| 956 | } | ||
| 957 | } | 1200 | } |
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index b4b48afb6de6..5d9411839cd7 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
| @@ -159,7 +159,7 @@ static int pxa2xx_ac97_resume(struct device *dev) | |||
| 159 | return ret; | 159 | return ret; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | static struct dev_pm_ops pxa2xx_ac97_pm_ops = { | 162 | static const struct dev_pm_ops pxa2xx_ac97_pm_ops = { |
| 163 | .suspend = pxa2xx_ac97_suspend, | 163 | .suspend = pxa2xx_ac97_suspend, |
| 164 | .resume = pxa2xx_ac97_resume, | 164 | .resume = pxa2xx_ac97_resume, |
| 165 | }; | 165 | }; |
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index fda7a94c992f..ccc642269b9e 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile | |||
| @@ -4,9 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o | 5 | snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o |
| 6 | snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o | 6 | snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o |
| 7 | ifdef CONFIG_MGEODE_LX | ||
| 8 | snd-cs5535audio-$(CONFIG_OLPC) += cs5535audio_olpc.o | 7 | snd-cs5535audio-$(CONFIG_OLPC) += cs5535audio_olpc.o |
| 9 | endif | ||
| 10 | 8 | ||
| 11 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
| 12 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o | 10 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 05f56e04849b..91e7faf69bbb 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
| @@ -389,6 +389,7 @@ probefail_out: | |||
| 389 | 389 | ||
| 390 | static void __devexit snd_cs5535audio_remove(struct pci_dev *pci) | 390 | static void __devexit snd_cs5535audio_remove(struct pci_dev *pci) |
| 391 | { | 391 | { |
| 392 | olpc_quirks_cleanup(); | ||
| 392 | snd_card_free(pci_get_drvdata(pci)); | 393 | snd_card_free(pci_get_drvdata(pci)); |
| 393 | pci_set_drvdata(pci, NULL); | 394 | pci_set_drvdata(pci, NULL); |
| 394 | } | 395 | } |
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 7a298ac662e3..51966d782a3c 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h | |||
| @@ -99,10 +99,11 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state); | |||
| 99 | int snd_cs5535audio_resume(struct pci_dev *pci); | 99 | int snd_cs5535audio_resume(struct pci_dev *pci); |
| 100 | #endif | 100 | #endif |
| 101 | 101 | ||
| 102 | #if defined(CONFIG_OLPC) && defined(CONFIG_MGEODE_LX) | 102 | #ifdef CONFIG_OLPC |
| 103 | void __devinit olpc_prequirks(struct snd_card *card, | 103 | void __devinit olpc_prequirks(struct snd_card *card, |
| 104 | struct snd_ac97_template *ac97); | 104 | struct snd_ac97_template *ac97); |
| 105 | int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97); | 105 | int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97); |
| 106 | void __devexit olpc_quirks_cleanup(void); | ||
| 106 | void olpc_analog_input(struct snd_ac97 *ac97, int on); | 107 | void olpc_analog_input(struct snd_ac97 *ac97, int on); |
| 107 | void olpc_mic_bias(struct snd_ac97 *ac97, int on); | 108 | void olpc_mic_bias(struct snd_ac97 *ac97, int on); |
| 108 | 109 | ||
| @@ -128,6 +129,7 @@ static inline int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) | |||
| 128 | { | 129 | { |
| 129 | return 0; | 130 | return 0; |
| 130 | } | 131 | } |
| 132 | static inline void olpc_quirks_cleanup(void) { } | ||
| 131 | static inline void olpc_analog_input(struct snd_ac97 *ac97, int on) { } | 133 | static inline void olpc_analog_input(struct snd_ac97 *ac97, int on) { } |
| 132 | static inline void olpc_mic_bias(struct snd_ac97 *ac97, int on) { } | 134 | static inline void olpc_mic_bias(struct snd_ac97 *ac97, int on) { } |
| 133 | static inline void olpc_capture_open(struct snd_ac97 *ac97) { } | 135 | static inline void olpc_capture_open(struct snd_ac97 *ac97) { } |
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c index 5c6814335cd7..50da49be9ae5 100644 --- a/sound/pci/cs5535audio/cs5535audio_olpc.c +++ b/sound/pci/cs5535audio/cs5535audio_olpc.c | |||
| @@ -13,10 +13,13 @@ | |||
| 13 | #include <sound/info.h> | 13 | #include <sound/info.h> |
| 14 | #include <sound/control.h> | 14 | #include <sound/control.h> |
| 15 | #include <sound/ac97_codec.h> | 15 | #include <sound/ac97_codec.h> |
| 16 | #include <linux/gpio.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/olpc.h> | 18 | #include <asm/olpc.h> |
| 18 | #include "cs5535audio.h" | 19 | #include "cs5535audio.h" |
| 19 | 20 | ||
| 21 | #define DRV_NAME "cs5535audio-olpc" | ||
| 22 | |||
| 20 | /* | 23 | /* |
| 21 | * OLPC has an additional feature on top of the regular AD1888 codec features. | 24 | * OLPC has an additional feature on top of the regular AD1888 codec features. |
| 22 | * It has an Analog Input mode that is switched into (after disabling the | 25 | * It has an Analog Input mode that is switched into (after disabling the |
| @@ -38,10 +41,7 @@ void olpc_analog_input(struct snd_ac97 *ac97, int on) | |||
| 38 | } | 41 | } |
| 39 | 42 | ||
| 40 | /* set Analog Input through GPIO */ | 43 | /* set Analog Input through GPIO */ |
| 41 | if (on) | 44 | gpio_set_value(OLPC_GPIO_MIC_AC, on); |
| 42 | geode_gpio_set(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); | ||
| 43 | else | ||
| 44 | geode_gpio_clear(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); | ||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | /* | 47 | /* |
| @@ -73,8 +73,7 @@ static int olpc_dc_info(struct snd_kcontrol *kctl, | |||
| 73 | 73 | ||
| 74 | static int olpc_dc_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v) | 74 | static int olpc_dc_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v) |
| 75 | { | 75 | { |
| 76 | v->value.integer.value[0] = geode_gpio_isset(OLPC_GPIO_MIC_AC, | 76 | v->value.integer.value[0] = gpio_get_value(OLPC_GPIO_MIC_AC); |
| 77 | GPIO_OUTPUT_VAL); | ||
| 78 | return 0; | 77 | return 0; |
| 79 | } | 78 | } |
| 80 | 79 | ||
| @@ -153,6 +152,12 @@ int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) | |||
| 153 | if (!machine_is_olpc()) | 152 | if (!machine_is_olpc()) |
| 154 | return 0; | 153 | return 0; |
| 155 | 154 | ||
| 155 | if (gpio_request(OLPC_GPIO_MIC_AC, DRV_NAME)) { | ||
| 156 | printk(KERN_ERR DRV_NAME ": unable to allocate MIC GPIO\n"); | ||
| 157 | return -EIO; | ||
| 158 | } | ||
| 159 | gpio_direction_output(OLPC_GPIO_MIC_AC, 0); | ||
| 160 | |||
| 156 | /* drop the original AD1888 HPF control */ | 161 | /* drop the original AD1888 HPF control */ |
| 157 | memset(&elem, 0, sizeof(elem)); | 162 | memset(&elem, 0, sizeof(elem)); |
| 158 | elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 163 | elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
| @@ -169,11 +174,18 @@ int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) | |||
| 169 | for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) { | 174 | for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) { |
| 170 | err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i], | 175 | err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i], |
| 171 | ac97->private_data)); | 176 | ac97->private_data)); |
| 172 | if (err < 0) | 177 | if (err < 0) { |
| 178 | gpio_free(OLPC_GPIO_MIC_AC); | ||
| 173 | return err; | 179 | return err; |
| 180 | } | ||
| 174 | } | 181 | } |
| 175 | 182 | ||
| 176 | /* turn off the mic by default */ | 183 | /* turn off the mic by default */ |
| 177 | olpc_mic_bias(ac97, 0); | 184 | olpc_mic_bias(ac97, 0); |
| 178 | return 0; | 185 | return 0; |
| 179 | } | 186 | } |
| 187 | |||
| 188 | void __devexit olpc_quirks_cleanup(void) | ||
| 189 | { | ||
| 190 | gpio_free(OLPC_GPIO_MIC_AC); | ||
| 191 | } | ||
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index d24328661c6a..40ccb419b6e9 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/compat.h> | 24 | #include <linux/compat.h> |
| 25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
| 27 | #include <linux/string.h> | ||
| 27 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
| 28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
| 29 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
| @@ -428,8 +429,7 @@ static int parse_hints(struct hda_codec *codec, const char *buf) | |||
| 428 | char *key, *val; | 429 | char *key, *val; |
| 429 | struct hda_hint *hint; | 430 | struct hda_hint *hint; |
| 430 | 431 | ||
| 431 | while (isspace(*buf)) | 432 | buf = skip_spaces(buf); |
| 432 | buf++; | ||
| 433 | if (!*buf || *buf == '#' || *buf == '\n') | 433 | if (!*buf || *buf == '#' || *buf == '\n') |
| 434 | return 0; | 434 | return 0; |
| 435 | if (*buf == '=') | 435 | if (*buf == '=') |
| @@ -444,8 +444,7 @@ static int parse_hints(struct hda_codec *codec, const char *buf) | |||
| 444 | return -EINVAL; | 444 | return -EINVAL; |
| 445 | } | 445 | } |
| 446 | *val++ = 0; | 446 | *val++ = 0; |
| 447 | while (isspace(*val)) | 447 | val = skip_spaces(val); |
| 448 | val++; | ||
| 449 | remove_trail_spaces(key); | 448 | remove_trail_spaces(key); |
| 450 | remove_trail_spaces(val); | 449 | remove_trail_spaces(val); |
| 451 | hint = get_hint(codec, key); | 450 | hint = get_hint(codec, key); |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c index d441c3b64631..4984754f3298 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec.c | |||
| @@ -312,7 +312,7 @@ int simtec_audio_resume(struct device *dev) | |||
| 312 | return 0; | 312 | return 0; |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | struct dev_pm_ops simtec_audio_pmops = { | 315 | const struct dev_pm_ops simtec_audio_pmops = { |
| 316 | .resume = simtec_audio_resume, | 316 | .resume = simtec_audio_resume, |
| 317 | }; | 317 | }; |
| 318 | EXPORT_SYMBOL_GPL(simtec_audio_pmops); | 318 | EXPORT_SYMBOL_GPL(simtec_audio_pmops); |
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h index 2714203af161..e18faee30cce 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.h +++ b/sound/soc/s3c24xx/s3c24xx_simtec.h | |||
| @@ -15,7 +15,7 @@ extern int simtec_audio_core_probe(struct platform_device *pdev, | |||
| 15 | extern int simtec_audio_remove(struct platform_device *pdev); | 15 | extern int simtec_audio_remove(struct platform_device *pdev); |
| 16 | 16 | ||
| 17 | #ifdef CONFIG_PM | 17 | #ifdef CONFIG_PM |
| 18 | extern struct dev_pm_ops simtec_audio_pmops; | 18 | extern const struct dev_pm_ops simtec_audio_pmops; |
| 19 | #define simtec_audio_pm &simtec_audio_pmops | 19 | #define simtec_audio_pm &simtec_audio_pmops |
| 20 | #else | 20 | #else |
| 21 | #define simtec_audio_pm NULL | 21 | #define simtec_audio_pm NULL |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ef8f28284cb9..0a6440c6f54a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -1236,7 +1236,7 @@ static int soc_poweroff(struct device *dev) | |||
| 1236 | return 0; | 1236 | return 0; |
| 1237 | } | 1237 | } |
| 1238 | 1238 | ||
| 1239 | static struct dev_pm_ops soc_pm_ops = { | 1239 | static const struct dev_pm_ops soc_pm_ops = { |
| 1240 | .suspend = soc_suspend, | 1240 | .suspend = soc_suspend, |
| 1241 | .resume = soc_resume, | 1241 | .resume = soc_resume, |
| 1242 | .poweroff = soc_poweroff, | 1242 | .poweroff = soc_poweroff, |
