diff options
256 files changed, 2930 insertions, 1671 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index ecd35e9d4410..feca0758391e 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl | |||
| @@ -46,7 +46,6 @@ | |||
| 46 | 46 | ||
| 47 | <sect1><title>Atomic and pointer manipulation</title> | 47 | <sect1><title>Atomic and pointer manipulation</title> |
| 48 | !Iarch/x86/include/asm/atomic.h | 48 | !Iarch/x86/include/asm/atomic.h |
| 49 | !Iarch/x86/include/asm/unaligned.h | ||
| 50 | </sect1> | 49 | </sect1> |
| 51 | 50 | ||
| 52 | <sect1><title>Delaying, scheduling, and timer routines</title> | 51 | <sect1><title>Delaying, scheduling, and timer routines</title> |
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index a20c6f6fffc3..6899f471fb15 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl | |||
| @@ -57,7 +57,6 @@ | |||
| 57 | </para> | 57 | </para> |
| 58 | 58 | ||
| 59 | <sect1><title>String Conversions</title> | 59 | <sect1><title>String Conversions</title> |
| 60 | !Ilib/vsprintf.c | ||
| 61 | !Elib/vsprintf.c | 60 | !Elib/vsprintf.c |
| 62 | </sect1> | 61 | </sect1> |
| 63 | <sect1><title>String Manipulation</title> | 62 | <sect1><title>String Manipulation</title> |
diff --git a/Documentation/block/cfq-iosched.txt b/Documentation/block/cfq-iosched.txt new file mode 100644 index 000000000000..e578feed6d81 --- /dev/null +++ b/Documentation/block/cfq-iosched.txt | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | CFQ ioscheduler tunables | ||
| 2 | ======================== | ||
| 3 | |||
| 4 | slice_idle | ||
| 5 | ---------- | ||
| 6 | This specifies how long CFQ should idle for next request on certain cfq queues | ||
| 7 | (for sequential workloads) and service trees (for random workloads) before | ||
| 8 | queue is expired and CFQ selects next queue to dispatch from. | ||
| 9 | |||
| 10 | By default slice_idle is a non-zero value. That means by default we idle on | ||
| 11 | queues/service trees. This can be very helpful on highly seeky media like | ||
| 12 | single spindle SATA/SAS disks where we can cut down on overall number of | ||
| 13 | seeks and see improved throughput. | ||
| 14 | |||
| 15 | Setting slice_idle to 0 will remove all the idling on queues/service tree | ||
| 16 | level and one should see an overall improved throughput on faster storage | ||
| 17 | devices like multiple SATA/SAS disks in hardware RAID configuration. The down | ||
| 18 | side is that isolation provided from WRITES also goes down and notion of | ||
| 19 | IO priority becomes weaker. | ||
| 20 | |||
| 21 | So depending on storage and workload, it might be useful to set slice_idle=0. | ||
| 22 | In general I think for SATA/SAS disks and software RAID of SATA/SAS disks | ||
| 23 | keeping slice_idle enabled should be useful. For any configurations where | ||
| 24 | there are multiple spindles behind single LUN (Host based hardware RAID | ||
| 25 | controller or for storage arrays), setting slice_idle=0 might end up in better | ||
| 26 | throughput and acceptable latencies. | ||
| 27 | |||
| 28 | CFQ IOPS Mode for group scheduling | ||
| 29 | =================================== | ||
| 30 | Basic CFQ design is to provide priority based time slices. Higher priority | ||
| 31 | process gets bigger time slice and lower priority process gets smaller time | ||
| 32 | slice. Measuring time becomes harder if storage is fast and supports NCQ and | ||
| 33 | it would be better to dispatch multiple requests from multiple cfq queues in | ||
| 34 | request queue at a time. In such scenario, it is not possible to measure time | ||
| 35 | consumed by single queue accurately. | ||
| 36 | |||
| 37 | What is possible though is to measure number of requests dispatched from a | ||
| 38 | single queue and also allow dispatch from multiple cfq queue at the same time. | ||
| 39 | This effectively becomes the fairness in terms of IOPS (IO operations per | ||
| 40 | second). | ||
| 41 | |||
| 42 | If one sets slice_idle=0 and if storage supports NCQ, CFQ internally switches | ||
| 43 | to IOPS mode and starts providing fairness in terms of number of requests | ||
| 44 | dispatched. Note that this mode switching takes effect only for group | ||
| 45 | scheduling. For non-cgroup users nothing should change. | ||
diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index 48e0b21b0059..6919d62591d9 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt | |||
| @@ -217,6 +217,7 @@ Details of cgroup files | |||
| 217 | CFQ sysfs tunable | 217 | CFQ sysfs tunable |
| 218 | ================= | 218 | ================= |
| 219 | /sys/block/<disk>/queue/iosched/group_isolation | 219 | /sys/block/<disk>/queue/iosched/group_isolation |
| 220 | ----------------------------------------------- | ||
| 220 | 221 | ||
| 221 | If group_isolation=1, it provides stronger isolation between groups at the | 222 | If group_isolation=1, it provides stronger isolation between groups at the |
| 222 | expense of throughput. By default group_isolation is 0. In general that | 223 | expense of throughput. By default group_isolation is 0. In general that |
| @@ -243,6 +244,33 @@ By default one should run with group_isolation=0. If that is not sufficient | |||
| 243 | and one wants stronger isolation between groups, then set group_isolation=1 | 244 | and one wants stronger isolation between groups, then set group_isolation=1 |
| 244 | but this will come at cost of reduced throughput. | 245 | but this will come at cost of reduced throughput. |
| 245 | 246 | ||
| 247 | /sys/block/<disk>/queue/iosched/slice_idle | ||
| 248 | ------------------------------------------ | ||
| 249 | On a faster hardware CFQ can be slow, especially with sequential workload. | ||
| 250 | This happens because CFQ idles on a single queue and single queue might not | ||
| 251 | drive deeper request queue depths to keep the storage busy. In such scenarios | ||
| 252 | one can try setting slice_idle=0 and that would switch CFQ to IOPS | ||
| 253 | (IO operations per second) mode on NCQ supporting hardware. | ||
| 254 | |||
| 255 | That means CFQ will not idle between cfq queues of a cfq group and hence be | ||
| 256 | able to driver higher queue depth and achieve better throughput. That also | ||
| 257 | means that cfq provides fairness among groups in terms of IOPS and not in | ||
| 258 | terms of disk time. | ||
| 259 | |||
| 260 | /sys/block/<disk>/queue/iosched/group_idle | ||
| 261 | ------------------------------------------ | ||
| 262 | If one disables idling on individual cfq queues and cfq service trees by | ||
| 263 | setting slice_idle=0, group_idle kicks in. That means CFQ will still idle | ||
| 264 | on the group in an attempt to provide fairness among groups. | ||
| 265 | |||
| 266 | By default group_idle is same as slice_idle and does not do anything if | ||
| 267 | slice_idle is enabled. | ||
| 268 | |||
| 269 | One can experience an overall throughput drop if you have created multiple | ||
| 270 | groups and put applications in that group which are not driving enough | ||
| 271 | IO to keep disk busy. In that case set group_idle=0, and CFQ will not idle | ||
| 272 | on individual groups and throughput should improve. | ||
| 273 | |||
| 246 | What works | 274 | What works |
| 247 | ========== | 275 | ========== |
| 248 | - Currently only sync IO queues are support. All the buffered writes are | 276 | - Currently only sync IO queues are support. All the buffered writes are |
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index 27a52b35d55b..3d8a97747f77 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt | |||
| @@ -345,5 +345,10 @@ documentation, in <filename>, for the functions listed. | |||
| 345 | section titled <section title> from <filename>. | 345 | section titled <section title> from <filename>. |
| 346 | Spaces are allowed in <section title>; do not quote the <section title>. | 346 | Spaces are allowed in <section title>; do not quote the <section title>. |
| 347 | 347 | ||
| 348 | !C<filename> is replaced by nothing, but makes the tools check that | ||
| 349 | all DOC: sections and documented functions, symbols, etc. are used. | ||
| 350 | This makes sense to use when you use !F/!P only and want to verify | ||
| 351 | that all documentation is included. | ||
| 352 | |||
| 348 | Tim. | 353 | Tim. |
| 349 | */ <twaugh@redhat.com> | 354 | */ <twaugh@redhat.com> |
diff --git a/Documentation/power/regulator/overview.txt b/Documentation/power/regulator/overview.txt index 9363e056188a..8ed17587a74b 100644 --- a/Documentation/power/regulator/overview.txt +++ b/Documentation/power/regulator/overview.txt | |||
| @@ -13,7 +13,7 @@ regulators (where voltage output is controllable) and current sinks (where | |||
| 13 | current limit is controllable). | 13 | current limit is controllable). |
| 14 | 14 | ||
| 15 | (C) 2008 Wolfson Microelectronics PLC. | 15 | (C) 2008 Wolfson Microelectronics PLC. |
| 16 | Author: Liam Girdwood <lg@opensource.wolfsonmicro.com> | 16 | Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | Nomenclature | 19 | Nomenclature |
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index ce46fa1e643e..37c6aad5e590 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt | |||
| @@ -296,6 +296,7 @@ Conexant 5051 | |||
| 296 | Conexant 5066 | 296 | Conexant 5066 |
| 297 | ============= | 297 | ============= |
| 298 | laptop Basic Laptop config (default) | 298 | laptop Basic Laptop config (default) |
| 299 | hp-laptop HP laptops, e g G60 | ||
| 299 | dell-laptop Dell laptops | 300 | dell-laptop Dell laptops |
| 300 | dell-vostro Dell Vostro | 301 | dell-vostro Dell Vostro |
| 301 | olpc-xo-1_5 OLPC XO 1.5 | 302 | olpc-xo-1_5 OLPC XO 1.5 |
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt new file mode 100644 index 000000000000..e4498a2872c3 --- /dev/null +++ b/Documentation/workqueue.txt | |||
| @@ -0,0 +1,380 @@ | |||
| 1 | |||
| 2 | Concurrency Managed Workqueue (cmwq) | ||
| 3 | |||
| 4 | September, 2010 Tejun Heo <tj@kernel.org> | ||
| 5 | Florian Mickler <florian@mickler.org> | ||
| 6 | |||
| 7 | CONTENTS | ||
| 8 | |||
| 9 | 1. Introduction | ||
| 10 | 2. Why cmwq? | ||
| 11 | 3. The Design | ||
| 12 | 4. Application Programming Interface (API) | ||
| 13 | 5. Example Execution Scenarios | ||
| 14 | 6. Guidelines | ||
| 15 | |||
| 16 | |||
| 17 | 1. Introduction | ||
| 18 | |||
| 19 | There are many cases where an asynchronous process execution context | ||
| 20 | is needed and the workqueue (wq) API is the most commonly used | ||
| 21 | mechanism for such cases. | ||
| 22 | |||
| 23 | When such an asynchronous execution context is needed, a work item | ||
| 24 | describing which function to execute is put on a queue. An | ||
| 25 | independent thread serves as the asynchronous execution context. The | ||
| 26 | queue is called workqueue and the thread is called worker. | ||
| 27 | |||
| 28 | While there are work items on the workqueue the worker executes the | ||
| 29 | functions associated with the work items one after the other. When | ||
| 30 | there is no work item left on the workqueue the worker becomes idle. | ||
| 31 | When a new work item gets queued, the worker begins executing again. | ||
| 32 | |||
| 33 | |||
| 34 | 2. Why cmwq? | ||
| 35 | |||
| 36 | In the original wq implementation, a multi threaded (MT) wq had one | ||
| 37 | worker thread per CPU and a single threaded (ST) wq had one worker | ||
| 38 | thread system-wide. A single MT wq needed to keep around the same | ||
| 39 | number of workers as the number of CPUs. The kernel grew a lot of MT | ||
| 40 | wq users over the years and with the number of CPU cores continuously | ||
| 41 | rising, some systems saturated the default 32k PID space just booting | ||
| 42 | up. | ||
| 43 | |||
| 44 | Although MT wq wasted a lot of resource, the level of concurrency | ||
| 45 | provided was unsatisfactory. The limitation was common to both ST and | ||
| 46 | MT wq albeit less severe on MT. Each wq maintained its own separate | ||
| 47 | worker pool. A MT wq could provide only one execution context per CPU | ||
| 48 | while a ST wq one for the whole system. Work items had to compete for | ||
| 49 | those very limited execution contexts leading to various problems | ||
| 50 | including proneness to deadlocks around the single execution context. | ||
| 51 | |||
| 52 | The tension between the provided level of concurrency and resource | ||
| 53 | usage also forced its users to make unnecessary tradeoffs like libata | ||
| 54 | choosing to use ST wq for polling PIOs and accepting an unnecessary | ||
| 55 | limitation that no two polling PIOs can progress at the same time. As | ||
| 56 | MT wq don't provide much better concurrency, users which require | ||
| 57 | higher level of concurrency, like async or fscache, had to implement | ||
| 58 | their own thread pool. | ||
| 59 | |||
| 60 | Concurrency Managed Workqueue (cmwq) is a reimplementation of wq with | ||
| 61 | focus on the following goals. | ||
| 62 | |||
| 63 | * Maintain compatibility with the original workqueue API. | ||
| 64 | |||
| 65 | * Use per-CPU unified worker pools shared by all wq to provide | ||
| 66 | flexible level of concurrency on demand without wasting a lot of | ||
| 67 | resource. | ||
| 68 | |||
| 69 | * Automatically regulate worker pool and level of concurrency so that | ||
| 70 | the API users don't need to worry about such details. | ||
| 71 | |||
| 72 | |||
| 73 | 3. The Design | ||
| 74 | |||
| 75 | In order to ease the asynchronous execution of functions a new | ||
| 76 | abstraction, the work item, is introduced. | ||
| 77 | |||
| 78 | A work item is a simple struct that holds a pointer to the function | ||
| 79 | that is to be executed asynchronously. Whenever a driver or subsystem | ||
| 80 | wants a function to be executed asynchronously it has to set up a work | ||
| 81 | item pointing to that function and queue that work item on a | ||
| 82 | workqueue. | ||
| 83 | |||
| 84 | Special purpose threads, called worker threads, execute the functions | ||
| 85 | off of the queue, one after the other. If no work is queued, the | ||
| 86 | worker threads become idle. These worker threads are managed in so | ||
| 87 | called thread-pools. | ||
| 88 | |||
| 89 | The cmwq design differentiates between the user-facing workqueues that | ||
| 90 | subsystems and drivers queue work items on and the backend mechanism | ||
| 91 | which manages thread-pool and processes the queued work items. | ||
| 92 | |||
| 93 | The backend is called gcwq. There is one gcwq for each possible CPU | ||
| 94 | and one gcwq to serve work items queued on unbound workqueues. | ||
| 95 | |||
| 96 | Subsystems and drivers can create and queue work items through special | ||
| 97 | workqueue API functions as they see fit. They can influence some | ||
| 98 | aspects of the way the work items are executed by setting flags on the | ||
| 99 | workqueue they are putting the work item on. These flags include | ||
| 100 | things like CPU locality, reentrancy, concurrency limits and more. To | ||
| 101 | get a detailed overview refer to the API description of | ||
| 102 | alloc_workqueue() below. | ||
| 103 | |||
| 104 | When a work item is queued to a workqueue, the target gcwq is | ||
| 105 | determined according to the queue parameters and workqueue attributes | ||
| 106 | and appended on the shared worklist of the gcwq. For example, unless | ||
| 107 | specifically overridden, a work item of a bound workqueue will be | ||
| 108 | queued on the worklist of exactly that gcwq that is associated to the | ||
| 109 | CPU the issuer is running on. | ||
| 110 | |||
| 111 | For any worker pool implementation, managing the concurrency level | ||
| 112 | (how many execution contexts are active) is an important issue. cmwq | ||
| 113 | tries to keep the concurrency at a minimal but sufficient level. | ||
| 114 | Minimal to save resources and sufficient in that the system is used at | ||
| 115 | its full capacity. | ||
| 116 | |||
| 117 | Each gcwq bound to an actual CPU implements concurrency management by | ||
| 118 | hooking into the scheduler. The gcwq is notified whenever an active | ||
| 119 | worker wakes up or sleeps and keeps track of the number of the | ||
| 120 | currently runnable workers. Generally, work items are not expected to | ||
| 121 | hog a CPU and consume many cycles. That means maintaining just enough | ||
| 122 | concurrency to prevent work processing from stalling should be | ||
| 123 | optimal. As long as there are one or more runnable workers on the | ||
| 124 | CPU, the gcwq doesn't start execution of a new work, but, when the | ||
| 125 | last running worker goes to sleep, it immediately schedules a new | ||
| 126 | worker so that the CPU doesn't sit idle while there are pending work | ||
| 127 | items. This allows using a minimal number of workers without losing | ||
| 128 | execution bandwidth. | ||
| 129 | |||
| 130 | Keeping idle workers around doesn't cost other than the memory space | ||
| 131 | for kthreads, so cmwq holds onto idle ones for a while before killing | ||
| 132 | them. | ||
| 133 | |||
| 134 | For an unbound wq, the above concurrency management doesn't apply and | ||
| 135 | the gcwq for the pseudo unbound CPU tries to start executing all work | ||
| 136 | items as soon as possible. The responsibility of regulating | ||
| 137 | concurrency level is on the users. There is also a flag to mark a | ||
| 138 | bound wq to ignore the concurrency management. Please refer to the | ||
| 139 | API section for details. | ||
| 140 | |||
| 141 | Forward progress guarantee relies on that workers can be created when | ||
| 142 | more execution contexts are necessary, which in turn is guaranteed | ||
| 143 | through the use of rescue workers. All work items which might be used | ||
| 144 | on code paths that handle memory reclaim are required to be queued on | ||
| 145 | wq's that have a rescue-worker reserved for execution under memory | ||
| 146 | pressure. Else it is possible that the thread-pool deadlocks waiting | ||
| 147 | for execution contexts to free up. | ||
| 148 | |||
| 149 | |||
| 150 | 4. Application Programming Interface (API) | ||
| 151 | |||
| 152 | alloc_workqueue() allocates a wq. The original create_*workqueue() | ||
| 153 | functions are deprecated and scheduled for removal. alloc_workqueue() | ||
| 154 | takes three arguments - @name, @flags and @max_active. @name is the | ||
| 155 | name of the wq and also used as the name of the rescuer thread if | ||
| 156 | there is one. | ||
| 157 | |||
| 158 | A wq no longer manages execution resources but serves as a domain for | ||
| 159 | forward progress guarantee, flush and work item attributes. @flags | ||
| 160 | and @max_active control how work items are assigned execution | ||
| 161 | resources, scheduled and executed. | ||
| 162 | |||
| 163 | @flags: | ||
| 164 | |||
| 165 | WQ_NON_REENTRANT | ||
| 166 | |||
| 167 | By default, a wq guarantees non-reentrance only on the same | ||
| 168 | CPU. A work item may not be executed concurrently on the same | ||
| 169 | CPU by multiple workers but is allowed to be executed | ||
| 170 | concurrently on multiple CPUs. This flag makes sure | ||
| 171 | non-reentrance is enforced across all CPUs. Work items queued | ||
| 172 | to a non-reentrant wq are guaranteed to be executed by at most | ||
| 173 | one worker system-wide at any given time. | ||
| 174 | |||
| 175 | WQ_UNBOUND | ||
| 176 | |||
| 177 | Work items queued to an unbound wq are served by a special | ||
| 178 | gcwq which hosts workers which are not bound to any specific | ||
| 179 | CPU. This makes the wq behave as a simple execution context | ||
| 180 | provider without concurrency management. The unbound gcwq | ||
| 181 | tries to start execution of work items as soon as possible. | ||
| 182 | Unbound wq sacrifices locality but is useful for the following | ||
| 183 | cases. | ||
| 184 | |||
| 185 | * Wide fluctuation in the concurrency level requirement is | ||
| 186 | expected and using bound wq may end up creating large number | ||
| 187 | of mostly unused workers across different CPUs as the issuer | ||
| 188 | hops through different CPUs. | ||
| 189 | |||
| 190 | * Long running CPU intensive workloads which can be better | ||
| 191 | managed by the system scheduler. | ||
| 192 | |||
| 193 | WQ_FREEZEABLE | ||
| 194 | |||
| 195 | A freezeable wq participates in the freeze phase of the system | ||
| 196 | suspend operations. Work items on the wq are drained and no | ||
| 197 | new work item starts execution until thawed. | ||
| 198 | |||
| 199 | WQ_RESCUER | ||
| 200 | |||
| 201 | All wq which might be used in the memory reclaim paths _MUST_ | ||
| 202 | have this flag set. This reserves one worker exclusively for | ||
| 203 | the execution of this wq under memory pressure. | ||
| 204 | |||
| 205 | WQ_HIGHPRI | ||
| 206 | |||
| 207 | Work items of a highpri wq are queued at the head of the | ||
| 208 | worklist of the target gcwq and start execution regardless of | ||
| 209 | the current concurrency level. In other words, highpri work | ||
| 210 | items will always start execution as soon as execution | ||
| 211 | resource is available. | ||
| 212 | |||
| 213 | Ordering among highpri work items is preserved - a highpri | ||
| 214 | work item queued after another highpri work item will start | ||
| 215 | execution after the earlier highpri work item starts. | ||
| 216 | |||
| 217 | Although highpri work items are not held back by other | ||
| 218 | runnable work items, they still contribute to the concurrency | ||
| 219 | level. Highpri work items in runnable state will prevent | ||
| 220 | non-highpri work items from starting execution. | ||
| 221 | |||
| 222 | This flag is meaningless for unbound wq. | ||
| 223 | |||
| 224 | WQ_CPU_INTENSIVE | ||
| 225 | |||
| 226 | Work items of a CPU intensive wq do not contribute to the | ||
| 227 | concurrency level. In other words, runnable CPU intensive | ||
| 228 | work items will not prevent other work items from starting | ||
| 229 | execution. This is useful for bound work items which are | ||
| 230 | expected to hog CPU cycles so that their execution is | ||
| 231 | regulated by the system scheduler. | ||
| 232 | |||
| 233 | Although CPU intensive work items don't contribute to the | ||
| 234 | concurrency level, start of their executions is still | ||
| 235 | regulated by the concurrency management and runnable | ||
| 236 | non-CPU-intensive work items can delay execution of CPU | ||
| 237 | intensive work items. | ||
| 238 | |||
| 239 | This flag is meaningless for unbound wq. | ||
| 240 | |||
| 241 | WQ_HIGHPRI | WQ_CPU_INTENSIVE | ||
| 242 | |||
| 243 | This combination makes the wq avoid interaction with | ||
| 244 | concurrency management completely and behave as a simple | ||
| 245 | per-CPU execution context provider. Work items queued on a | ||
| 246 | highpri CPU-intensive wq start execution as soon as resources | ||
| 247 | are available and don't affect execution of other work items. | ||
| 248 | |||
| 249 | @max_active: | ||
| 250 | |||
| 251 | @max_active determines the maximum number of execution contexts per | ||
| 252 | CPU which can be assigned to the work items of a wq. For example, | ||
| 253 | with @max_active of 16, at most 16 work items of the wq can be | ||
| 254 | executing at the same time per CPU. | ||
| 255 | |||
| 256 | Currently, for a bound wq, the maximum limit for @max_active is 512 | ||
| 257 | and the default value used when 0 is specified is 256. For an unbound | ||
| 258 | wq, the limit is higher of 512 and 4 * num_possible_cpus(). These | ||
| 259 | values are chosen sufficiently high such that they are not the | ||
| 260 | limiting factor while providing protection in runaway cases. | ||
| 261 | |||
| 262 | The number of active work items of a wq is usually regulated by the | ||
| 263 | users of the wq, more specifically, by how many work items the users | ||
| 264 | may queue at the same time. Unless there is a specific need for | ||
| 265 | throttling the number of active work items, specifying '0' is | ||
| 266 | recommended. | ||
| 267 | |||
| 268 | Some users depend on the strict execution ordering of ST wq. The | ||
| 269 | combination of @max_active of 1 and WQ_UNBOUND is used to achieve this | ||
| 270 | behavior. Work items on such wq are always queued to the unbound gcwq | ||
| 271 | and only one work item can be active at any given time thus achieving | ||
| 272 | the same ordering property as ST wq. | ||
| 273 | |||
| 274 | |||
| 275 | 5. Example Execution Scenarios | ||
| 276 | |||
| 277 | The following example execution scenarios try to illustrate how cmwq | ||
| 278 | behave under different configurations. | ||
| 279 | |||
| 280 | Work items w0, w1, w2 are queued to a bound wq q0 on the same CPU. | ||
| 281 | w0 burns CPU for 5ms then sleeps for 10ms then burns CPU for 5ms | ||
| 282 | again before finishing. w1 and w2 burn CPU for 5ms then sleep for | ||
| 283 | 10ms. | ||
| 284 | |||
| 285 | Ignoring all other tasks, works and processing overhead, and assuming | ||
| 286 | simple FIFO scheduling, the following is one highly simplified version | ||
| 287 | of possible sequences of events with the original wq. | ||
| 288 | |||
| 289 | TIME IN MSECS EVENT | ||
| 290 | 0 w0 starts and burns CPU | ||
| 291 | 5 w0 sleeps | ||
| 292 | 15 w0 wakes up and burns CPU | ||
| 293 | 20 w0 finishes | ||
| 294 | 20 w1 starts and burns CPU | ||
| 295 | 25 w1 sleeps | ||
| 296 | 35 w1 wakes up and finishes | ||
| 297 | 35 w2 starts and burns CPU | ||
| 298 | 40 w2 sleeps | ||
| 299 | 50 w2 wakes up and finishes | ||
| 300 | |||
| 301 | And with cmwq with @max_active >= 3, | ||
| 302 | |||
| 303 | TIME IN MSECS EVENT | ||
| 304 | 0 w0 starts and burns CPU | ||
| 305 | 5 w0 sleeps | ||
| 306 | 5 w1 starts and burns CPU | ||
| 307 | 10 w1 sleeps | ||
| 308 | 10 w2 starts and burns CPU | ||
| 309 | 15 w2 sleeps | ||
| 310 | 15 w0 wakes up and burns CPU | ||
| 311 | 20 w0 finishes | ||
| 312 | 20 w1 wakes up and finishes | ||
| 313 | 25 w2 wakes up and finishes | ||
| 314 | |||
| 315 | If @max_active == 2, | ||
| 316 | |||
| 317 | TIME IN MSECS EVENT | ||
| 318 | 0 w0 starts and burns CPU | ||
| 319 | 5 w0 sleeps | ||
| 320 | 5 w1 starts and burns CPU | ||
| 321 | 10 w1 sleeps | ||
| 322 | 15 w0 wakes up and burns CPU | ||
| 323 | 20 w0 finishes | ||
| 324 | 20 w1 wakes up and finishes | ||
| 325 | 20 w2 starts and burns CPU | ||
| 326 | 25 w2 sleeps | ||
| 327 | 35 w2 wakes up and finishes | ||
| 328 | |||
| 329 | Now, let's assume w1 and w2 are queued to a different wq q1 which has | ||
| 330 | WQ_HIGHPRI set, | ||
| 331 | |||
| 332 | TIME IN MSECS EVENT | ||
| 333 | 0 w1 and w2 start and burn CPU | ||
| 334 | 5 w1 sleeps | ||
| 335 | 10 w2 sleeps | ||
| 336 | 10 w0 starts and burns CPU | ||
| 337 | 15 w0 sleeps | ||
| 338 | 15 w1 wakes up and finishes | ||
| 339 | 20 w2 wakes up and finishes | ||
| 340 | 25 w0 wakes up and burns CPU | ||
| 341 | 30 w0 finishes | ||
| 342 | |||
| 343 | If q1 has WQ_CPU_INTENSIVE set, | ||
| 344 | |||
| 345 | TIME IN MSECS EVENT | ||
| 346 | 0 w0 starts and burns CPU | ||
| 347 | 5 w0 sleeps | ||
| 348 | 5 w1 and w2 start and burn CPU | ||
| 349 | 10 w1 sleeps | ||
| 350 | 15 w2 sleeps | ||
| 351 | 15 w0 wakes up and burns CPU | ||
| 352 | 20 w0 finishes | ||
| 353 | 20 w1 wakes up and finishes | ||
| 354 | 25 w2 wakes up and finishes | ||
| 355 | |||
| 356 | |||
| 357 | 6. Guidelines | ||
| 358 | |||
| 359 | * Do not forget to use WQ_RESCUER if a wq may process work items which | ||
| 360 | are used during memory reclaim. Each wq with WQ_RESCUER set has one | ||
| 361 | rescuer thread reserved for it. If there is dependency among | ||
| 362 | multiple work items used during memory reclaim, they should be | ||
| 363 | queued to separate wq each with WQ_RESCUER. | ||
| 364 | |||
| 365 | * Unless strict ordering is required, there is no need to use ST wq. | ||
| 366 | |||
| 367 | * Unless there is a specific need, using 0 for @max_active is | ||
| 368 | recommended. In most use cases, concurrency level usually stays | ||
| 369 | well under the default limit. | ||
| 370 | |||
| 371 | * A wq serves as a domain for forward progress guarantee (WQ_RESCUER), | ||
| 372 | flush and work item attributes. Work items which are not involved | ||
| 373 | in memory reclaim and don't need to be flushed as a part of a group | ||
| 374 | of work items, and don't require any special attribute, can use one | ||
| 375 | of the system wq. There is no difference in execution | ||
| 376 | characteristics between using a dedicated wq and a system wq. | ||
| 377 | |||
| 378 | * Unless work items are expected to consume a huge amount of CPU | ||
| 379 | cycles, using a bound wq is usually beneficial due to the increased | ||
| 380 | level of locality in wq operations and work item execution. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 9800de5ec222..e7c528ff1013 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -1445,6 +1445,16 @@ S: Maintained | |||
| 1445 | F: Documentation/video4linux/cafe_ccic | 1445 | F: Documentation/video4linux/cafe_ccic |
| 1446 | F: drivers/media/video/cafe_ccic* | 1446 | F: drivers/media/video/cafe_ccic* |
| 1447 | 1447 | ||
| 1448 | CAIF NETWORK LAYER | ||
| 1449 | M: Sjur Braendeland <sjur.brandeland@stericsson.com> | ||
| 1450 | L: netdev@vger.kernel.org | ||
| 1451 | S: Supported | ||
| 1452 | F: Documentation/networking/caif/ | ||
| 1453 | F: drivers/net/caif/ | ||
| 1454 | F: include/linux/caif/ | ||
| 1455 | F: include/net/caif/ | ||
| 1456 | F: net/caif/ | ||
| 1457 | |||
| 1448 | CALGARY x86-64 IOMMU | 1458 | CALGARY x86-64 IOMMU |
| 1449 | M: Muli Ben-Yehuda <muli@il.ibm.com> | 1459 | M: Muli Ben-Yehuda <muli@il.ibm.com> |
| 1450 | M: "Jon D. Mason" <jdmason@kudzu.us> | 1460 | M: "Jon D. Mason" <jdmason@kudzu.us> |
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 2 | 1 | VERSION = 2 |
| 2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
| 3 | SUBLEVEL = 36 | 3 | SUBLEVEL = 36 |
| 4 | EXTRAVERSION = -rc3 | 4 | EXTRAVERSION = -rc4 |
| 5 | NAME = Sheep on Meth | 5 | NAME = Sheep on Meth |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 753c0d31a3d3..c67b47f1c0fd 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c | |||
| @@ -121,8 +121,8 @@ static struct clk ssc1_clk = { | |||
| 121 | .pmc_mask = 1 << AT91SAM9G45_ID_SSC1, | 121 | .pmc_mask = 1 << AT91SAM9G45_ID_SSC1, |
| 122 | .type = CLK_TYPE_PERIPHERAL, | 122 | .type = CLK_TYPE_PERIPHERAL, |
| 123 | }; | 123 | }; |
| 124 | static struct clk tcb_clk = { | 124 | static struct clk tcb0_clk = { |
| 125 | .name = "tcb_clk", | 125 | .name = "tcb0_clk", |
| 126 | .pmc_mask = 1 << AT91SAM9G45_ID_TCB, | 126 | .pmc_mask = 1 << AT91SAM9G45_ID_TCB, |
| 127 | .type = CLK_TYPE_PERIPHERAL, | 127 | .type = CLK_TYPE_PERIPHERAL, |
| 128 | }; | 128 | }; |
| @@ -192,6 +192,14 @@ static struct clk ohci_clk = { | |||
| 192 | .parent = &uhphs_clk, | 192 | .parent = &uhphs_clk, |
| 193 | }; | 193 | }; |
| 194 | 194 | ||
| 195 | /* One additional fake clock for second TC block */ | ||
| 196 | static struct clk tcb1_clk = { | ||
| 197 | .name = "tcb1_clk", | ||
| 198 | .pmc_mask = 0, | ||
| 199 | .type = CLK_TYPE_PERIPHERAL, | ||
| 200 | .parent = &tcb0_clk, | ||
| 201 | }; | ||
| 202 | |||
| 195 | static struct clk *periph_clocks[] __initdata = { | 203 | static struct clk *periph_clocks[] __initdata = { |
| 196 | &pioA_clk, | 204 | &pioA_clk, |
| 197 | &pioB_clk, | 205 | &pioB_clk, |
| @@ -208,7 +216,7 @@ static struct clk *periph_clocks[] __initdata = { | |||
| 208 | &spi1_clk, | 216 | &spi1_clk, |
| 209 | &ssc0_clk, | 217 | &ssc0_clk, |
| 210 | &ssc1_clk, | 218 | &ssc1_clk, |
| 211 | &tcb_clk, | 219 | &tcb0_clk, |
| 212 | &pwm_clk, | 220 | &pwm_clk, |
| 213 | &tsc_clk, | 221 | &tsc_clk, |
| 214 | &dma_clk, | 222 | &dma_clk, |
| @@ -221,6 +229,7 @@ static struct clk *periph_clocks[] __initdata = { | |||
| 221 | &mmc1_clk, | 229 | &mmc1_clk, |
| 222 | // irq0 | 230 | // irq0 |
| 223 | &ohci_clk, | 231 | &ohci_clk, |
| 232 | &tcb1_clk, | ||
| 224 | }; | 233 | }; |
| 225 | 234 | ||
| 226 | /* | 235 | /* |
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 809114d5a5a6..5e71ccd5e7d3 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c | |||
| @@ -46,7 +46,7 @@ static struct resource hdmac_resources[] = { | |||
| 46 | .end = AT91_BASE_SYS + AT91_DMA + SZ_512 - 1, | 46 | .end = AT91_BASE_SYS + AT91_DMA + SZ_512 - 1, |
| 47 | .flags = IORESOURCE_MEM, | 47 | .flags = IORESOURCE_MEM, |
| 48 | }, | 48 | }, |
| 49 | [2] = { | 49 | [1] = { |
| 50 | .start = AT91SAM9G45_ID_DMA, | 50 | .start = AT91SAM9G45_ID_DMA, |
| 51 | .end = AT91SAM9G45_ID_DMA, | 51 | .end = AT91SAM9G45_ID_DMA, |
| 52 | .flags = IORESOURCE_IRQ, | 52 | .flags = IORESOURCE_IRQ, |
| @@ -835,9 +835,9 @@ static struct platform_device at91sam9g45_tcb1_device = { | |||
| 835 | static void __init at91_add_device_tc(void) | 835 | static void __init at91_add_device_tc(void) |
| 836 | { | 836 | { |
| 837 | /* this chip has one clock and irq for all six TC channels */ | 837 | /* this chip has one clock and irq for all six TC channels */ |
| 838 | at91_clock_associate("tcb_clk", &at91sam9g45_tcb0_device.dev, "t0_clk"); | 838 | at91_clock_associate("tcb0_clk", &at91sam9g45_tcb0_device.dev, "t0_clk"); |
| 839 | platform_device_register(&at91sam9g45_tcb0_device); | 839 | platform_device_register(&at91sam9g45_tcb0_device); |
| 840 | at91_clock_associate("tcb_clk", &at91sam9g45_tcb1_device.dev, "t0_clk"); | 840 | at91_clock_associate("tcb1_clk", &at91sam9g45_tcb1_device.dev, "t0_clk"); |
| 841 | platform_device_register(&at91sam9g45_tcb1_device); | 841 | platform_device_register(&at91sam9g45_tcb1_device); |
| 842 | } | 842 | } |
| 843 | #else | 843 | #else |
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index c4c8865d52d7..65eb0943194f 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c | |||
| @@ -93,11 +93,12 @@ static struct resource dm9000_resource[] = { | |||
| 93 | .start = AT91_PIN_PC11, | 93 | .start = AT91_PIN_PC11, |
| 94 | .end = AT91_PIN_PC11, | 94 | .end = AT91_PIN_PC11, |
| 95 | .flags = IORESOURCE_IRQ | 95 | .flags = IORESOURCE_IRQ |
| 96 | | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE, | ||
| 96 | } | 97 | } |
| 97 | }; | 98 | }; |
| 98 | 99 | ||
| 99 | static struct dm9000_plat_data dm9000_platdata = { | 100 | static struct dm9000_plat_data dm9000_platdata = { |
| 100 | .flags = DM9000_PLATF_16BITONLY, | 101 | .flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM, |
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | static struct platform_device dm9000_device = { | 104 | static struct platform_device dm9000_device = { |
| @@ -168,17 +169,6 @@ static struct at91_udc_data __initdata ek_udc_data = { | |||
| 168 | 169 | ||
| 169 | 170 | ||
| 170 | /* | 171 | /* |
| 171 | * MCI (SD/MMC) | ||
| 172 | */ | ||
| 173 | static struct at91_mmc_data __initdata ek_mmc_data = { | ||
| 174 | .wire4 = 1, | ||
| 175 | // .det_pin = ... not connected | ||
| 176 | // .wp_pin = ... not connected | ||
| 177 | // .vcc_pin = ... not connected | ||
| 178 | }; | ||
| 179 | |||
| 180 | |||
| 181 | /* | ||
| 182 | * NAND flash | 172 | * NAND flash |
| 183 | */ | 173 | */ |
| 184 | static struct mtd_partition __initdata ek_nand_partition[] = { | 174 | static struct mtd_partition __initdata ek_nand_partition[] = { |
| @@ -246,6 +236,10 @@ static void __init ek_add_device_nand(void) | |||
| 246 | at91_add_device_nand(&ek_nand_data); | 236 | at91_add_device_nand(&ek_nand_data); |
| 247 | } | 237 | } |
| 248 | 238 | ||
| 239 | /* | ||
| 240 | * SPI related devices | ||
| 241 | */ | ||
| 242 | #if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) | ||
| 249 | 243 | ||
| 250 | /* | 244 | /* |
| 251 | * ADS7846 Touchscreen | 245 | * ADS7846 Touchscreen |
| @@ -356,6 +350,19 @@ static struct spi_board_info ek_spi_devices[] = { | |||
| 356 | #endif | 350 | #endif |
| 357 | }; | 351 | }; |
| 358 | 352 | ||
| 353 | #else /* CONFIG_SPI_ATMEL_* */ | ||
| 354 | /* spi0 and mmc/sd share the same PIO pins: cannot be used at the same time */ | ||
| 355 | |||
| 356 | /* | ||
| 357 | * MCI (SD/MMC) | ||
| 358 | * det_pin, wp_pin and vcc_pin are not connected | ||
| 359 | */ | ||
| 360 | static struct at91_mmc_data __initdata ek_mmc_data = { | ||
| 361 | .wire4 = 1, | ||
| 362 | }; | ||
| 363 | |||
| 364 | #endif /* CONFIG_SPI_ATMEL_* */ | ||
| 365 | |||
| 359 | 366 | ||
| 360 | /* | 367 | /* |
| 361 | * LCD Controller | 368 | * LCD Controller |
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 7f7da439341f..7525cee3983f 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c | |||
| @@ -501,7 +501,8 @@ postcore_initcall(at91_clk_debugfs_init); | |||
| 501 | int __init clk_register(struct clk *clk) | 501 | int __init clk_register(struct clk *clk) |
| 502 | { | 502 | { |
| 503 | if (clk_is_peripheral(clk)) { | 503 | if (clk_is_peripheral(clk)) { |
| 504 | clk->parent = &mck; | 504 | if (!clk->parent) |
| 505 | clk->parent = &mck; | ||
| 505 | clk->mode = pmc_periph_mode; | 506 | clk->mode = pmc_periph_mode; |
| 506 | list_add_tail(&clk->node, &clocks); | 507 | list_add_tail(&clk->node, &clocks); |
| 507 | } | 508 | } |
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h index f90edc85b509..9301a2821615 100644 --- a/arch/ia64/include/asm/compat.h +++ b/arch/ia64/include/asm/compat.h | |||
| @@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr) | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | static __inline__ void __user * | 201 | static __inline__ void __user * |
| 202 | compat_alloc_user_space (long len) | 202 | arch_compat_alloc_user_space (long len) |
| 203 | { | 203 | { |
| 204 | struct pt_regs *regs = task_pt_regs(current); | 204 | struct pt_regs *regs = task_pt_regs(current); |
| 205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); | 205 | return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len); |
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 3567d54f8cee..331d42bda77a 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
| @@ -420,22 +420,31 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | |||
| 420 | ;; | 420 | ;; |
| 421 | 421 | ||
| 422 | RSM_PSR_I(p0, r18, r19) // mask interrupt delivery | 422 | RSM_PSR_I(p0, r18, r19) // mask interrupt delivery |
| 423 | mov ar.ccv=0 | ||
| 424 | andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP | 423 | andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP |
| 424 | mov r8=EINVAL // default to EINVAL | ||
| 425 | 425 | ||
| 426 | #ifdef CONFIG_SMP | 426 | #ifdef CONFIG_SMP |
| 427 | mov r17=1 | 427 | // __ticket_spin_trylock(r31) |
| 428 | ld4 r17=[r31] | ||
| 428 | ;; | 429 | ;; |
| 429 | cmpxchg4.acq r18=[r31],r17,ar.ccv // try to acquire the lock | 430 | mov.m ar.ccv=r17 |
| 430 | mov r8=EINVAL // default to EINVAL | 431 | extr.u r9=r17,17,15 |
| 432 | adds r19=1,r17 | ||
| 433 | extr.u r18=r17,0,15 | ||
| 434 | ;; | ||
| 435 | cmp.eq p6,p7=r9,r18 | ||
| 431 | ;; | 436 | ;; |
| 437 | (p6) cmpxchg4.acq r9=[r31],r19,ar.ccv | ||
| 438 | (p6) dep.z r20=r19,1,15 // next serving ticket for unlock | ||
| 439 | (p7) br.cond.spnt.many .lock_contention | ||
| 440 | ;; | ||
| 441 | cmp4.eq p0,p7=r9,r17 | ||
| 442 | adds r31=2,r31 | ||
| 443 | (p7) br.cond.spnt.many .lock_contention | ||
| 432 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock | 444 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock |
| 433 | cmp4.ne p6,p0=r18,r0 | ||
| 434 | (p6) br.cond.spnt.many .lock_contention | ||
| 435 | ;; | 445 | ;; |
| 436 | #else | 446 | #else |
| 437 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock | 447 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock |
| 438 | mov r8=EINVAL // default to EINVAL | ||
| 439 | #endif | 448 | #endif |
| 440 | add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16 | 449 | add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16 |
| 441 | add r19=IA64_TASK_SIGNAL_OFFSET,r16 | 450 | add r19=IA64_TASK_SIGNAL_OFFSET,r16 |
| @@ -490,7 +499,9 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | |||
| 490 | (p6) br.cond.spnt.few 1b // yes -> retry | 499 | (p6) br.cond.spnt.few 1b // yes -> retry |
| 491 | 500 | ||
| 492 | #ifdef CONFIG_SMP | 501 | #ifdef CONFIG_SMP |
| 493 | st4.rel [r31]=r0 // release the lock | 502 | // __ticket_spin_unlock(r31) |
| 503 | st2.rel [r31]=r20 | ||
| 504 | mov r20=0 // i must not leak kernel bits... | ||
| 494 | #endif | 505 | #endif |
| 495 | SSM_PSR_I(p0, p9, r31) | 506 | SSM_PSR_I(p0, p9, r31) |
| 496 | ;; | 507 | ;; |
| @@ -512,7 +523,8 @@ EX(.fail_efault, (p15) st8 [r34]=r3) | |||
| 512 | 523 | ||
| 513 | .sig_pending: | 524 | .sig_pending: |
| 514 | #ifdef CONFIG_SMP | 525 | #ifdef CONFIG_SMP |
| 515 | st4.rel [r31]=r0 // release the lock | 526 | // __ticket_spin_unlock(r31) |
| 527 | st2.rel [r31]=r20 // release the lock | ||
| 516 | #endif | 528 | #endif |
| 517 | SSM_PSR_I(p0, p9, r17) | 529 | SSM_PSR_I(p0, p9, r17) |
| 518 | ;; | 530 | ;; |
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 60b15d0aa072..b43b36beafe3 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h | |||
| @@ -340,10 +340,13 @@ | |||
| 340 | #define __NR_set_thread_area 334 | 340 | #define __NR_set_thread_area 334 |
| 341 | #define __NR_atomic_cmpxchg_32 335 | 341 | #define __NR_atomic_cmpxchg_32 335 |
| 342 | #define __NR_atomic_barrier 336 | 342 | #define __NR_atomic_barrier 336 |
| 343 | #define __NR_fanotify_init 337 | ||
| 344 | #define __NR_fanotify_mark 338 | ||
| 345 | #define __NR_prlimit64 339 | ||
| 343 | 346 | ||
| 344 | #ifdef __KERNEL__ | 347 | #ifdef __KERNEL__ |
| 345 | 348 | ||
| 346 | #define NR_syscalls 337 | 349 | #define NR_syscalls 340 |
| 347 | 350 | ||
| 348 | #define __ARCH_WANT_IPC_PARSE_VERSION | 351 | #define __ARCH_WANT_IPC_PARSE_VERSION |
| 349 | #define __ARCH_WANT_OLD_READDIR | 352 | #define __ARCH_WANT_OLD_READDIR |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 2391bdff0996..6360c437dcf5 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
| @@ -765,4 +765,7 @@ sys_call_table: | |||
| 765 | .long sys_set_thread_area | 765 | .long sys_set_thread_area |
| 766 | .long sys_atomic_cmpxchg_32 /* 335 */ | 766 | .long sys_atomic_cmpxchg_32 /* 335 */ |
| 767 | .long sys_atomic_barrier | 767 | .long sys_atomic_barrier |
| 768 | .long sys_fanotify_init | ||
| 769 | .long sys_fanotify_mark | ||
| 770 | .long sys_prlimit64 | ||
| 768 | 771 | ||
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index b30b3eb197a5..79b1ed198c07 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S | |||
| @@ -355,6 +355,9 @@ ENTRY(sys_call_table) | |||
| 355 | .long sys_set_thread_area | 355 | .long sys_set_thread_area |
| 356 | .long sys_atomic_cmpxchg_32 /* 335 */ | 356 | .long sys_atomic_cmpxchg_32 /* 335 */ |
| 357 | .long sys_atomic_barrier | 357 | .long sys_atomic_barrier |
| 358 | .long sys_fanotify_init | ||
| 359 | .long sys_fanotify_mark | ||
| 360 | .long sys_prlimit64 | ||
| 358 | 361 | ||
| 359 | .rept NR_syscalls-(.-sys_call_table)/4 | 362 | .rept NR_syscalls-(.-sys_call_table)/4 |
| 360 | .long sys_ni_syscall | 363 | .long sys_ni_syscall |
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 613f6912dfc1..dbc51065df5b 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h | |||
| @@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 145 | return (u32)(unsigned long)uptr; | 145 | return (u32)(unsigned long)uptr; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static inline void __user *compat_alloc_user_space(long len) | 148 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 149 | { | 149 | { |
| 150 | struct pt_regs *regs = (struct pt_regs *) | 150 | struct pt_regs *regs = (struct pt_regs *) |
| 151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; | 151 | ((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1; |
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 9d49073e827a..db509dd80565 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
| @@ -156,17 +156,17 @@ struct mn10300_serial_port mn10300_serial_port_sif0 = { | |||
| 156 | ._intr = &SC0ICR, | 156 | ._intr = &SC0ICR, |
| 157 | ._rxb = &SC0RXB, | 157 | ._rxb = &SC0RXB, |
| 158 | ._txb = &SC0TXB, | 158 | ._txb = &SC0TXB, |
| 159 | .rx_name = "ttySM0/Rx", | 159 | .rx_name = "ttySM0:Rx", |
| 160 | .tx_name = "ttySM0/Tx", | 160 | .tx_name = "ttySM0:Tx", |
| 161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 | 161 | #ifdef CONFIG_MN10300_TTYSM0_TIMER8 |
| 162 | .tm_name = "ttySM0/Timer8", | 162 | .tm_name = "ttySM0:Timer8", |
| 163 | ._tmxmd = &TM8MD, | 163 | ._tmxmd = &TM8MD, |
| 164 | ._tmxbr = &TM8BR, | 164 | ._tmxbr = &TM8BR, |
| 165 | ._tmicr = &TM8ICR, | 165 | ._tmicr = &TM8ICR, |
| 166 | .tm_irq = TM8IRQ, | 166 | .tm_irq = TM8IRQ, |
| 167 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 167 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
| 168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ | 168 | #else /* CONFIG_MN10300_TTYSM0_TIMER2 */ |
| 169 | .tm_name = "ttySM0/Timer2", | 169 | .tm_name = "ttySM0:Timer2", |
| 170 | ._tmxmd = &TM2MD, | 170 | ._tmxmd = &TM2MD, |
| 171 | ._tmxbr = (volatile u16 *) &TM2BR, | 171 | ._tmxbr = (volatile u16 *) &TM2BR, |
| 172 | ._tmicr = &TM2ICR, | 172 | ._tmicr = &TM2ICR, |
| @@ -209,17 +209,17 @@ struct mn10300_serial_port mn10300_serial_port_sif1 = { | |||
| 209 | ._intr = &SC1ICR, | 209 | ._intr = &SC1ICR, |
| 210 | ._rxb = &SC1RXB, | 210 | ._rxb = &SC1RXB, |
| 211 | ._txb = &SC1TXB, | 211 | ._txb = &SC1TXB, |
| 212 | .rx_name = "ttySM1/Rx", | 212 | .rx_name = "ttySM1:Rx", |
| 213 | .tx_name = "ttySM1/Tx", | 213 | .tx_name = "ttySM1:Tx", |
| 214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 | 214 | #ifdef CONFIG_MN10300_TTYSM1_TIMER9 |
| 215 | .tm_name = "ttySM1/Timer9", | 215 | .tm_name = "ttySM1:Timer9", |
| 216 | ._tmxmd = &TM9MD, | 216 | ._tmxmd = &TM9MD, |
| 217 | ._tmxbr = &TM9BR, | 217 | ._tmxbr = &TM9BR, |
| 218 | ._tmicr = &TM9ICR, | 218 | ._tmicr = &TM9ICR, |
| 219 | .tm_irq = TM9IRQ, | 219 | .tm_irq = TM9IRQ, |
| 220 | .div_timer = MNSCx_DIV_TIMER_16BIT, | 220 | .div_timer = MNSCx_DIV_TIMER_16BIT, |
| 221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ | 221 | #else /* CONFIG_MN10300_TTYSM1_TIMER3 */ |
| 222 | .tm_name = "ttySM1/Timer3", | 222 | .tm_name = "ttySM1:Timer3", |
| 223 | ._tmxmd = &TM3MD, | 223 | ._tmxmd = &TM3MD, |
| 224 | ._tmxbr = (volatile u16 *) &TM3BR, | 224 | ._tmxbr = (volatile u16 *) &TM3BR, |
| 225 | ._tmicr = &TM3ICR, | 225 | ._tmicr = &TM3ICR, |
| @@ -260,9 +260,9 @@ struct mn10300_serial_port mn10300_serial_port_sif2 = { | |||
| 260 | .uart.lock = | 260 | .uart.lock = |
| 261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), | 261 | __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock), |
| 262 | .name = "ttySM2", | 262 | .name = "ttySM2", |
| 263 | .rx_name = "ttySM2/Rx", | 263 | .rx_name = "ttySM2:Rx", |
| 264 | .tx_name = "ttySM2/Tx", | 264 | .tx_name = "ttySM2:Tx", |
| 265 | .tm_name = "ttySM2/Timer10", | 265 | .tm_name = "ttySM2:Timer10", |
| 266 | ._iobase = &SC2CTR, | 266 | ._iobase = &SC2CTR, |
| 267 | ._control = &SC2CTR, | 267 | ._control = &SC2CTR, |
| 268 | ._status = &SC2STR, | 268 | ._status = &SC2STR, |
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 02b77baa5da6..efa0b60c63fe 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h | |||
| @@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 147 | return (u32)(unsigned long)uptr; | 147 | return (u32)(unsigned long)uptr; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | static __inline__ void __user *compat_alloc_user_space(long len) | 150 | static __inline__ void __user *arch_compat_alloc_user_space(long len) |
| 151 | { | 151 | { |
| 152 | struct pt_regs *regs = ¤t->thread.regs; | 152 | struct pt_regs *regs = ¤t->thread.regs; |
| 153 | return (void __user *)regs->gr[30]; | 153 | return (void __user *)regs->gr[30]; |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 396d21a80058..a11d4eac4f97 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
| @@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 134 | return (u32)(unsigned long)uptr; | 134 | return (u32)(unsigned long)uptr; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static inline void __user *compat_alloc_user_space(long len) | 137 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 138 | { | 138 | { |
| 139 | struct pt_regs *regs = current->thread.regs; | 139 | struct pt_regs *regs = current->thread.regs; |
| 140 | unsigned long usp = regs->gpr[1]; | 140 | unsigned long usp = regs->gpr[1]; |
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 104f2007f097..a875c2f542e1 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h | |||
| @@ -181,7 +181,7 @@ static inline int is_compat_task(void) | |||
| 181 | 181 | ||
| 182 | #endif | 182 | #endif |
| 183 | 183 | ||
| 184 | static inline void __user *compat_alloc_user_space(long len) | 184 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 185 | { | 185 | { |
| 186 | unsigned long stack; | 186 | unsigned long stack; |
| 187 | 187 | ||
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index 5016f76ea98a..6f57325bb883 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h | |||
| @@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 167 | return (u32)(unsigned long)uptr; | 167 | return (u32)(unsigned long)uptr; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static inline void __user *compat_alloc_user_space(long len) | 170 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 171 | { | 171 | { |
| 172 | struct pt_regs *regs = current_thread_info()->kregs; | 172 | struct pt_regs *regs = current_thread_info()->kregs; |
| 173 | unsigned long usp = regs->u_regs[UREG_I6]; | 173 | unsigned long usp = regs->u_regs[UREG_I6]; |
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 50794137d710..675c9e11ada5 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c | |||
| @@ -166,7 +166,6 @@ sparc_breakpoint (struct pt_regs *regs) | |||
| 166 | { | 166 | { |
| 167 | siginfo_t info; | 167 | siginfo_t info; |
| 168 | 168 | ||
| 169 | lock_kernel(); | ||
| 170 | #ifdef DEBUG_SPARC_BREAKPOINT | 169 | #ifdef DEBUG_SPARC_BREAKPOINT |
| 171 | printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc); | 170 | printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc); |
| 172 | #endif | 171 | #endif |
| @@ -180,7 +179,6 @@ sparc_breakpoint (struct pt_regs *regs) | |||
| 180 | #ifdef DEBUG_SPARC_BREAKPOINT | 179 | #ifdef DEBUG_SPARC_BREAKPOINT |
| 181 | printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc); | 180 | printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc); |
| 182 | #endif | 181 | #endif |
| 183 | unlock_kernel(); | ||
| 184 | } | 182 | } |
| 185 | 183 | ||
| 186 | asmlinkage int | 184 | asmlinkage int |
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c index f8514e291e15..12b9f352595f 100644 --- a/arch/sparc/kernel/unaligned_32.c +++ b/arch/sparc/kernel/unaligned_32.c | |||
| @@ -323,7 +323,6 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn) | |||
| 323 | { | 323 | { |
| 324 | enum direction dir; | 324 | enum direction dir; |
| 325 | 325 | ||
| 326 | lock_kernel(); | ||
| 327 | if(!(current->thread.flags & SPARC_FLAG_UNALIGNED) || | 326 | if(!(current->thread.flags & SPARC_FLAG_UNALIGNED) || |
| 328 | (((insn >> 30) & 3) != 3)) | 327 | (((insn >> 30) & 3) != 3)) |
| 329 | goto kill_user; | 328 | goto kill_user; |
| @@ -377,5 +376,5 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn) | |||
| 377 | kill_user: | 376 | kill_user: |
| 378 | user_mna_trap_fault(regs, insn); | 377 | user_mna_trap_fault(regs, insn); |
| 379 | out: | 378 | out: |
| 380 | unlock_kernel(); | 379 | ; |
| 381 | } | 380 | } |
diff --git a/arch/sparc/kernel/windows.c b/arch/sparc/kernel/windows.c index f24d298bda29..b351770cbdd6 100644 --- a/arch/sparc/kernel/windows.c +++ b/arch/sparc/kernel/windows.c | |||
| @@ -112,7 +112,6 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who) | |||
| 112 | struct thread_info *tp = current_thread_info(); | 112 | struct thread_info *tp = current_thread_info(); |
| 113 | int window; | 113 | int window; |
| 114 | 114 | ||
| 115 | lock_kernel(); | ||
| 116 | flush_user_windows(); | 115 | flush_user_windows(); |
| 117 | for(window = 0; window < tp->w_saved; window++) { | 116 | for(window = 0; window < tp->w_saved; window++) { |
| 118 | unsigned long sp = tp->rwbuf_stkptrs[window]; | 117 | unsigned long sp = tp->rwbuf_stkptrs[window]; |
| @@ -123,5 +122,4 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who) | |||
| 123 | do_exit(SIGILL); | 122 | do_exit(SIGILL); |
| 124 | } | 123 | } |
| 125 | tp->w_saved = 0; | 124 | tp->w_saved = 0; |
| 126 | unlock_kernel(); | ||
| 127 | } | 125 | } |
diff --git a/arch/tile/include/arch/chip_tile64.h b/arch/tile/include/arch/chip_tile64.h index 1246573be59e..261aaba092d4 100644 --- a/arch/tile/include/arch/chip_tile64.h +++ b/arch/tile/include/arch/chip_tile64.h | |||
| @@ -150,6 +150,9 @@ | |||
| 150 | /** Is the PROC_STATUS SPR supported? */ | 150 | /** Is the PROC_STATUS SPR supported? */ |
| 151 | #define CHIP_HAS_PROC_STATUS_SPR() 0 | 151 | #define CHIP_HAS_PROC_STATUS_SPR() 0 |
| 152 | 152 | ||
| 153 | /** Is the DSTREAM_PF SPR supported? */ | ||
| 154 | #define CHIP_HAS_DSTREAM_PF() 0 | ||
| 155 | |||
| 153 | /** Log of the number of mshims we have. */ | 156 | /** Log of the number of mshims we have. */ |
| 154 | #define CHIP_LOG_NUM_MSHIMS() 2 | 157 | #define CHIP_LOG_NUM_MSHIMS() 2 |
| 155 | 158 | ||
diff --git a/arch/tile/include/arch/chip_tilepro.h b/arch/tile/include/arch/chip_tilepro.h index e864c47fc89c..70017699a74c 100644 --- a/arch/tile/include/arch/chip_tilepro.h +++ b/arch/tile/include/arch/chip_tilepro.h | |||
| @@ -150,6 +150,9 @@ | |||
| 150 | /** Is the PROC_STATUS SPR supported? */ | 150 | /** Is the PROC_STATUS SPR supported? */ |
| 151 | #define CHIP_HAS_PROC_STATUS_SPR() 1 | 151 | #define CHIP_HAS_PROC_STATUS_SPR() 1 |
| 152 | 152 | ||
| 153 | /** Is the DSTREAM_PF SPR supported? */ | ||
| 154 | #define CHIP_HAS_DSTREAM_PF() 0 | ||
| 155 | |||
| 153 | /** Log of the number of mshims we have. */ | 156 | /** Log of the number of mshims we have. */ |
| 154 | #define CHIP_LOG_NUM_MSHIMS() 2 | 157 | #define CHIP_LOG_NUM_MSHIMS() 2 |
| 155 | 158 | ||
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 5a34da6cdd79..8b60ec8b2d19 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h | |||
| @@ -195,7 +195,7 @@ static inline unsigned long ptr_to_compat_reg(void __user *uptr) | |||
| 195 | return (long)(int)(long __force)uptr; | 195 | return (long)(int)(long __force)uptr; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static inline void __user *compat_alloc_user_space(long len) | 198 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 199 | { | 199 | { |
| 200 | struct pt_regs *regs = task_pt_regs(current); | 200 | struct pt_regs *regs = task_pt_regs(current); |
| 201 | return (void __user *)regs->sp - len; | 201 | return (void __user *)regs->sp - len; |
| @@ -214,8 +214,9 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
| 214 | struct compat_sigaction; | 214 | struct compat_sigaction; |
| 215 | struct compat_siginfo; | 215 | struct compat_siginfo; |
| 216 | struct compat_sigaltstack; | 216 | struct compat_sigaltstack; |
| 217 | long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 217 | long compat_sys_execve(const char __user *path, |
| 218 | compat_uptr_t __user *envp); | 218 | const compat_uptr_t __user *argv, |
| 219 | const compat_uptr_t __user *envp); | ||
| 219 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, | 220 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, |
| 220 | struct compat_sigaction __user *oact, | 221 | struct compat_sigaction __user *oact, |
| 221 | size_t sigsetsize); | 222 | size_t sigsetsize); |
diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h index 8c95bef3fa45..ee43328713ab 100644 --- a/arch/tile/include/asm/io.h +++ b/arch/tile/include/asm/io.h | |||
| @@ -164,22 +164,22 @@ static inline void _tile_writeq(u64 val, unsigned long addr) | |||
| 164 | #define iowrite32 writel | 164 | #define iowrite32 writel |
| 165 | #define iowrite64 writeq | 165 | #define iowrite64 writeq |
| 166 | 166 | ||
| 167 | static inline void *memcpy_fromio(void *dst, void *src, int len) | 167 | static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, |
| 168 | size_t len) | ||
| 168 | { | 169 | { |
| 169 | int x; | 170 | int x; |
| 170 | BUG_ON((unsigned long)src & 0x3); | 171 | BUG_ON((unsigned long)src & 0x3); |
| 171 | for (x = 0; x < len; x += 4) | 172 | for (x = 0; x < len; x += 4) |
| 172 | *(u32 *)(dst + x) = readl(src + x); | 173 | *(u32 *)(dst + x) = readl(src + x); |
| 173 | return dst; | ||
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | static inline void *memcpy_toio(void *dst, void *src, int len) | 176 | static inline void memcpy_toio(volatile void __iomem *dst, const void *src, |
| 177 | size_t len) | ||
| 177 | { | 178 | { |
| 178 | int x; | 179 | int x; |
| 179 | BUG_ON((unsigned long)dst & 0x3); | 180 | BUG_ON((unsigned long)dst & 0x3); |
| 180 | for (x = 0; x < len; x += 4) | 181 | for (x = 0; x < len; x += 4) |
| 181 | writel(*(u32 *)(src + x), dst + x); | 182 | writel(*(u32 *)(src + x), dst + x); |
| 182 | return dst; | ||
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | /* | 185 | /* |
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index d942d09b252e..ccd5f8425688 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h | |||
| @@ -103,6 +103,18 @@ struct thread_struct { | |||
| 103 | /* Any other miscellaneous processor state bits */ | 103 | /* Any other miscellaneous processor state bits */ |
| 104 | unsigned long proc_status; | 104 | unsigned long proc_status; |
| 105 | #endif | 105 | #endif |
| 106 | #if !CHIP_HAS_FIXED_INTVEC_BASE() | ||
| 107 | /* Interrupt base for PL0 interrupts */ | ||
| 108 | unsigned long interrupt_vector_base; | ||
| 109 | #endif | ||
| 110 | #if CHIP_HAS_TILE_RTF_HWM() | ||
| 111 | /* Tile cache retry fifo high-water mark */ | ||
| 112 | unsigned long tile_rtf_hwm; | ||
| 113 | #endif | ||
| 114 | #if CHIP_HAS_DSTREAM_PF() | ||
| 115 | /* Data stream prefetch control */ | ||
| 116 | unsigned long dstream_pf; | ||
| 117 | #endif | ||
| 106 | #ifdef CONFIG_HARDWALL | 118 | #ifdef CONFIG_HARDWALL |
| 107 | /* Is this task tied to an activated hardwall? */ | 119 | /* Is this task tied to an activated hardwall? */ |
| 108 | struct hardwall_info *hardwall; | 120 | struct hardwall_info *hardwall; |
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h index acdae814e016..4a02bb073979 100644 --- a/arch/tile/include/asm/ptrace.h +++ b/arch/tile/include/asm/ptrace.h | |||
| @@ -51,10 +51,7 @@ typedef uint_reg_t pt_reg_t; | |||
| 51 | 51 | ||
| 52 | /* | 52 | /* |
| 53 | * This struct defines the way the registers are stored on the stack during a | 53 | * This struct defines the way the registers are stored on the stack during a |
| 54 | * system call/exception. It should be a multiple of 8 bytes to preserve | 54 | * system call or exception. "struct sigcontext" has the same shape. |
| 55 | * normal stack alignment rules. | ||
| 56 | * | ||
| 57 | * Must track <sys/ucontext.h> and <sys/procfs.h> | ||
| 58 | */ | 55 | */ |
| 59 | struct pt_regs { | 56 | struct pt_regs { |
| 60 | /* Saved main processor registers; 56..63 are special. */ | 57 | /* Saved main processor registers; 56..63 are special. */ |
| @@ -80,11 +77,6 @@ struct pt_regs { | |||
| 80 | 77 | ||
| 81 | #endif /* __ASSEMBLY__ */ | 78 | #endif /* __ASSEMBLY__ */ |
| 82 | 79 | ||
| 83 | /* Flag bits in pt_regs.flags */ | ||
| 84 | #define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ | ||
| 85 | #define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ | ||
| 86 | #define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ | ||
| 87 | |||
| 88 | #define PTRACE_GETREGS 12 | 80 | #define PTRACE_GETREGS 12 |
| 89 | #define PTRACE_SETREGS 13 | 81 | #define PTRACE_SETREGS 13 |
| 90 | #define PTRACE_GETFPREGS 14 | 82 | #define PTRACE_GETFPREGS 14 |
| @@ -101,6 +93,11 @@ struct pt_regs { | |||
| 101 | 93 | ||
| 102 | #ifdef __KERNEL__ | 94 | #ifdef __KERNEL__ |
| 103 | 95 | ||
| 96 | /* Flag bits in pt_regs.flags */ | ||
| 97 | #define PT_FLAGS_DISABLE_IRQ 1 /* on return to kernel, disable irqs */ | ||
| 98 | #define PT_FLAGS_CALLER_SAVES 2 /* caller-save registers are valid */ | ||
| 99 | #define PT_FLAGS_RESTORE_REGS 4 /* restore callee-save regs on return */ | ||
| 100 | |||
| 104 | #ifndef __ASSEMBLY__ | 101 | #ifndef __ASSEMBLY__ |
| 105 | 102 | ||
| 106 | #define instruction_pointer(regs) ((regs)->pc) | 103 | #define instruction_pointer(regs) ((regs)->pc) |
diff --git a/arch/tile/include/asm/sigcontext.h b/arch/tile/include/asm/sigcontext.h index 7cd7672e3ad4..5e2d03336f53 100644 --- a/arch/tile/include/asm/sigcontext.h +++ b/arch/tile/include/asm/sigcontext.h | |||
| @@ -15,13 +15,21 @@ | |||
| 15 | #ifndef _ASM_TILE_SIGCONTEXT_H | 15 | #ifndef _ASM_TILE_SIGCONTEXT_H |
| 16 | #define _ASM_TILE_SIGCONTEXT_H | 16 | #define _ASM_TILE_SIGCONTEXT_H |
| 17 | 17 | ||
| 18 | /* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */ | 18 | #include <arch/abi.h> |
| 19 | #include <asm/ptrace.h> | ||
| 20 | |||
| 21 | /* Must track <sys/ucontext.h> */ | ||
| 22 | 19 | ||
| 20 | /* | ||
| 21 | * struct sigcontext has the same shape as struct pt_regs, | ||
| 22 | * but is simplified since we know the fault is from userspace. | ||
| 23 | */ | ||
| 23 | struct sigcontext { | 24 | struct sigcontext { |
| 24 | struct pt_regs regs; | 25 | uint_reg_t gregs[53]; /* General-purpose registers. */ |
| 26 | uint_reg_t tp; /* Aliases gregs[TREG_TP]. */ | ||
| 27 | uint_reg_t sp; /* Aliases gregs[TREG_SP]. */ | ||
| 28 | uint_reg_t lr; /* Aliases gregs[TREG_LR]. */ | ||
| 29 | uint_reg_t pc; /* Program counter. */ | ||
| 30 | uint_reg_t ics; /* In Interrupt Critical Section? */ | ||
| 31 | uint_reg_t faultnum; /* Fault number. */ | ||
| 32 | uint_reg_t pad[5]; | ||
| 25 | }; | 33 | }; |
| 26 | 34 | ||
| 27 | #endif /* _ASM_TILE_SIGCONTEXT_H */ | 35 | #endif /* _ASM_TILE_SIGCONTEXT_H */ |
diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index eb0253f32202..c1ee1d61d44c 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <asm-generic/signal.h> | 24 | #include <asm-generic/signal.h> |
| 25 | 25 | ||
| 26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) | 26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) |
| 27 | struct pt_regs; | ||
| 27 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); | 28 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); |
| 28 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); | 29 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); |
| 29 | void do_signal(struct pt_regs *regs); | 30 | void do_signal(struct pt_regs *regs); |
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h index af165a74537f..ce99ffefeacf 100644 --- a/arch/tile/include/asm/syscalls.h +++ b/arch/tile/include/asm/syscalls.h | |||
| @@ -62,10 +62,12 @@ long sys_fork(void); | |||
| 62 | long _sys_fork(struct pt_regs *regs); | 62 | long _sys_fork(struct pt_regs *regs); |
| 63 | long sys_vfork(void); | 63 | long sys_vfork(void); |
| 64 | long _sys_vfork(struct pt_regs *regs); | 64 | long _sys_vfork(struct pt_regs *regs); |
| 65 | long sys_execve(char __user *filename, char __user * __user *argv, | 65 | long sys_execve(const char __user *filename, |
| 66 | char __user * __user *envp); | 66 | const char __user *const __user *argv, |
| 67 | long _sys_execve(char __user *filename, char __user * __user *argv, | 67 | const char __user *const __user *envp); |
| 68 | char __user * __user *envp, struct pt_regs *regs); | 68 | long _sys_execve(const char __user *filename, |
| 69 | const char __user *const __user *argv, | ||
| 70 | const char __user *const __user *envp, struct pt_regs *regs); | ||
| 69 | 71 | ||
| 70 | /* kernel/signal.c */ | 72 | /* kernel/signal.c */ |
| 71 | long sys_sigaltstack(const stack_t __user *, stack_t __user *); | 73 | long sys_sigaltstack(const stack_t __user *, stack_t __user *); |
| @@ -86,10 +88,13 @@ int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); | |||
| 86 | #endif | 88 | #endif |
| 87 | 89 | ||
| 88 | #ifdef CONFIG_COMPAT | 90 | #ifdef CONFIG_COMPAT |
| 89 | long compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 91 | long compat_sys_execve(const char __user *path, |
| 90 | compat_uptr_t __user *envp); | 92 | const compat_uptr_t __user *argv, |
| 91 | long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 93 | const compat_uptr_t __user *envp); |
| 92 | compat_uptr_t __user *envp, struct pt_regs *regs); | 94 | long _compat_sys_execve(const char __user *path, |
| 95 | const compat_uptr_t __user *argv, | ||
| 96 | const compat_uptr_t __user *envp, | ||
| 97 | struct pt_regs *regs); | ||
| 93 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 98 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
| 94 | struct compat_sigaltstack __user *uoss_ptr); | 99 | struct compat_sigaltstack __user *uoss_ptr); |
| 95 | long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 100 | long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 985cc28c74c5..84c29111756c 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
| @@ -408,6 +408,15 @@ static void save_arch_state(struct thread_struct *t) | |||
| 408 | #if CHIP_HAS_PROC_STATUS_SPR() | 408 | #if CHIP_HAS_PROC_STATUS_SPR() |
| 409 | t->proc_status = __insn_mfspr(SPR_PROC_STATUS); | 409 | t->proc_status = __insn_mfspr(SPR_PROC_STATUS); |
| 410 | #endif | 410 | #endif |
| 411 | #if !CHIP_HAS_FIXED_INTVEC_BASE() | ||
| 412 | t->interrupt_vector_base = __insn_mfspr(SPR_INTERRUPT_VECTOR_BASE_0); | ||
| 413 | #endif | ||
| 414 | #if CHIP_HAS_TILE_RTF_HWM() | ||
| 415 | t->tile_rtf_hwm = __insn_mfspr(SPR_TILE_RTF_HWM); | ||
| 416 | #endif | ||
| 417 | #if CHIP_HAS_DSTREAM_PF() | ||
| 418 | t->dstream_pf = __insn_mfspr(SPR_DSTREAM_PF); | ||
| 419 | #endif | ||
| 411 | } | 420 | } |
| 412 | 421 | ||
| 413 | static void restore_arch_state(const struct thread_struct *t) | 422 | static void restore_arch_state(const struct thread_struct *t) |
| @@ -428,14 +437,14 @@ static void restore_arch_state(const struct thread_struct *t) | |||
| 428 | #if CHIP_HAS_PROC_STATUS_SPR() | 437 | #if CHIP_HAS_PROC_STATUS_SPR() |
| 429 | __insn_mtspr(SPR_PROC_STATUS, t->proc_status); | 438 | __insn_mtspr(SPR_PROC_STATUS, t->proc_status); |
| 430 | #endif | 439 | #endif |
| 440 | #if !CHIP_HAS_FIXED_INTVEC_BASE() | ||
| 441 | __insn_mtspr(SPR_INTERRUPT_VECTOR_BASE_0, t->interrupt_vector_base); | ||
| 442 | #endif | ||
| 431 | #if CHIP_HAS_TILE_RTF_HWM() | 443 | #if CHIP_HAS_TILE_RTF_HWM() |
| 432 | /* | 444 | __insn_mtspr(SPR_TILE_RTF_HWM, t->tile_rtf_hwm); |
| 433 | * Clear this whenever we switch back to a process in case | 445 | #endif |
| 434 | * the previous process was monkeying with it. Even if enabled | 446 | #if CHIP_HAS_DSTREAM_PF() |
| 435 | * in CBOX_MSR1 via TILE_RTF_HWM_MIN, it's still just a | 447 | __insn_mtspr(SPR_DSTREAM_PF, t->dstream_pf); |
| 436 | * performance hint, so isn't worth a full save/restore. | ||
| 437 | */ | ||
| 438 | __insn_mtspr(SPR_TILE_RTF_HWM, 0); | ||
| 439 | #endif | 448 | #endif |
| 440 | } | 449 | } |
| 441 | 450 | ||
| @@ -561,8 +570,9 @@ out: | |||
| 561 | } | 570 | } |
| 562 | 571 | ||
| 563 | #ifdef CONFIG_COMPAT | 572 | #ifdef CONFIG_COMPAT |
| 564 | long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 573 | long _compat_sys_execve(const char __user *path, |
| 565 | compat_uptr_t __user *envp, struct pt_regs *regs) | 574 | const compat_uptr_t __user *argv, |
| 575 | const compat_uptr_t __user *envp, struct pt_regs *regs) | ||
| 566 | { | 576 | { |
| 567 | long error; | 577 | long error; |
| 568 | char *filename; | 578 | char *filename; |
| @@ -657,7 +667,7 @@ void show_regs(struct pt_regs *regs) | |||
| 657 | regs->regs[51], regs->regs[52], regs->tp); | 667 | regs->regs[51], regs->regs[52], regs->tp); |
| 658 | pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr); | 668 | pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr); |
| 659 | #else | 669 | #else |
| 660 | for (i = 0; i < 52; i += 3) | 670 | for (i = 0; i < 52; i += 4) |
| 661 | pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT | 671 | pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT |
| 662 | " r%-2d: "REGFMT" r%-2d: "REGFMT"\n", | 672 | " r%-2d: "REGFMT" r%-2d: "REGFMT"\n", |
| 663 | i, regs->regs[i], i+1, regs->regs[i+1], | 673 | i, regs->regs[i], i+1, regs->regs[i+1], |
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 45b66a3c991f..ce183aa1492c 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c | |||
| @@ -61,13 +61,19 @@ int restore_sigcontext(struct pt_regs *regs, | |||
| 61 | /* Always make any pending restarted system calls return -EINTR */ | 61 | /* Always make any pending restarted system calls return -EINTR */ |
| 62 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 62 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 63 | 63 | ||
| 64 | /* | ||
| 65 | * Enforce that sigcontext is like pt_regs, and doesn't mess | ||
| 66 | * up our stack alignment rules. | ||
| 67 | */ | ||
| 68 | BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs)); | ||
| 69 | BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0); | ||
| 70 | |||
| 64 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) | 71 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) |
| 65 | err |= __get_user(((long *)regs)[i], | 72 | err |= __get_user(regs->regs[i], &sc->gregs[i]); |
| 66 | &((long __user *)(&sc->regs))[i]); | ||
| 67 | 73 | ||
| 68 | regs->faultnum = INT_SWINT_1_SIGRETURN; | 74 | regs->faultnum = INT_SWINT_1_SIGRETURN; |
| 69 | 75 | ||
| 70 | err |= __get_user(*pr0, &sc->regs.regs[0]); | 76 | err |= __get_user(*pr0, &sc->gregs[0]); |
| 71 | return err; | 77 | return err; |
| 72 | } | 78 | } |
| 73 | 79 | ||
| @@ -112,8 +118,7 @@ int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) | |||
| 112 | int i, err = 0; | 118 | int i, err = 0; |
| 113 | 119 | ||
| 114 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) | 120 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) |
| 115 | err |= __put_user(((long *)regs)[i], | 121 | err |= __put_user(regs->regs[i], &sc->gregs[i]); |
| 116 | &((long __user *)(&sc->regs))[i]); | ||
| 117 | 122 | ||
| 118 | return err; | 123 | return err; |
| 119 | } | 124 | } |
| @@ -203,19 +208,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 203 | * Set up registers for signal handler. | 208 | * Set up registers for signal handler. |
| 204 | * Registers that we don't modify keep the value they had from | 209 | * Registers that we don't modify keep the value they had from |
| 205 | * user-space at the time we took the signal. | 210 | * user-space at the time we took the signal. |
| 211 | * We always pass siginfo and mcontext, regardless of SA_SIGINFO, | ||
| 212 | * since some things rely on this (e.g. glibc's debug/segfault.c). | ||
| 206 | */ | 213 | */ |
| 207 | regs->pc = (unsigned long) ka->sa.sa_handler; | 214 | regs->pc = (unsigned long) ka->sa.sa_handler; |
| 208 | regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ | 215 | regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ |
| 209 | regs->sp = (unsigned long) frame; | 216 | regs->sp = (unsigned long) frame; |
| 210 | regs->lr = restorer; | 217 | regs->lr = restorer; |
| 211 | regs->regs[0] = (unsigned long) usig; | 218 | regs->regs[0] = (unsigned long) usig; |
| 212 | 219 | regs->regs[1] = (unsigned long) &frame->info; | |
| 213 | if (ka->sa.sa_flags & SA_SIGINFO) { | 220 | regs->regs[2] = (unsigned long) &frame->uc; |
| 214 | /* Need extra arguments, so mark to restore caller-saves. */ | 221 | regs->flags |= PT_FLAGS_CALLER_SAVES; |
| 215 | regs->regs[1] = (unsigned long) &frame->info; | ||
| 216 | regs->regs[2] = (unsigned long) &frame->uc; | ||
| 217 | regs->flags |= PT_FLAGS_CALLER_SAVES; | ||
| 218 | } | ||
| 219 | 222 | ||
| 220 | /* | 223 | /* |
| 221 | * Notify any tracer that was single-stepping it. | 224 | * Notify any tracer that was single-stepping it. |
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index 38a68b0b4581..ea2e0ce28380 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c | |||
| @@ -175,7 +175,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt) | |||
| 175 | pr_err(" <received signal %d>\n", | 175 | pr_err(" <received signal %d>\n", |
| 176 | frame->info.si_signo); | 176 | frame->info.si_signo); |
| 177 | } | 177 | } |
| 178 | return &frame->uc.uc_mcontext.regs; | 178 | return (struct pt_regs *)&frame->uc.uc_mcontext; |
| 179 | } | 179 | } |
| 180 | return NULL; | 180 | return NULL; |
| 181 | } | 181 | } |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index b86feabed69b..518bb99c3394 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
| @@ -50,7 +50,12 @@ | |||
| 50 | /* | 50 | /* |
| 51 | * Reload arg registers from stack in case ptrace changed them. | 51 | * Reload arg registers from stack in case ptrace changed them. |
| 52 | * We don't reload %eax because syscall_trace_enter() returned | 52 | * We don't reload %eax because syscall_trace_enter() returned |
| 53 | * the value it wants us to use in the table lookup. | 53 | * the %rax value we should see. Instead, we just truncate that |
| 54 | * value to 32 bits again as we did on entry from user mode. | ||
| 55 | * If it's a new value set by user_regset during entry tracing, | ||
| 56 | * this matches the normal truncation of the user-mode value. | ||
| 57 | * If it's -1 to make us punt the syscall, then (u32)-1 is still | ||
| 58 | * an appropriately invalid value. | ||
| 54 | */ | 59 | */ |
| 55 | .macro LOAD_ARGS32 offset, _r9=0 | 60 | .macro LOAD_ARGS32 offset, _r9=0 |
| 56 | .if \_r9 | 61 | .if \_r9 |
| @@ -60,6 +65,7 @@ | |||
| 60 | movl \offset+48(%rsp),%edx | 65 | movl \offset+48(%rsp),%edx |
| 61 | movl \offset+56(%rsp),%esi | 66 | movl \offset+56(%rsp),%esi |
| 62 | movl \offset+64(%rsp),%edi | 67 | movl \offset+64(%rsp),%edi |
| 68 | movl %eax,%eax /* zero extension */ | ||
| 63 | .endm | 69 | .endm |
| 64 | 70 | ||
| 65 | .macro CFI_STARTPROC32 simple | 71 | .macro CFI_STARTPROC32 simple |
| @@ -153,7 +159,7 @@ ENTRY(ia32_sysenter_target) | |||
| 153 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 159 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
| 154 | CFI_REMEMBER_STATE | 160 | CFI_REMEMBER_STATE |
| 155 | jnz sysenter_tracesys | 161 | jnz sysenter_tracesys |
| 156 | cmpl $(IA32_NR_syscalls-1),%eax | 162 | cmpq $(IA32_NR_syscalls-1),%rax |
| 157 | ja ia32_badsys | 163 | ja ia32_badsys |
| 158 | sysenter_do_call: | 164 | sysenter_do_call: |
| 159 | IA32_ARG_FIXUP | 165 | IA32_ARG_FIXUP |
| @@ -195,7 +201,7 @@ sysexit_from_sys_call: | |||
| 195 | movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ | 201 | movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ |
| 196 | call audit_syscall_entry | 202 | call audit_syscall_entry |
| 197 | movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ | 203 | movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ |
| 198 | cmpl $(IA32_NR_syscalls-1),%eax | 204 | cmpq $(IA32_NR_syscalls-1),%rax |
| 199 | ja ia32_badsys | 205 | ja ia32_badsys |
| 200 | movl %ebx,%edi /* reload 1st syscall arg */ | 206 | movl %ebx,%edi /* reload 1st syscall arg */ |
| 201 | movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ | 207 | movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */ |
| @@ -248,7 +254,7 @@ sysenter_tracesys: | |||
| 248 | call syscall_trace_enter | 254 | call syscall_trace_enter |
| 249 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 255 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
| 250 | RESTORE_REST | 256 | RESTORE_REST |
| 251 | cmpl $(IA32_NR_syscalls-1),%eax | 257 | cmpq $(IA32_NR_syscalls-1),%rax |
| 252 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ | 258 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ |
| 253 | jmp sysenter_do_call | 259 | jmp sysenter_do_call |
| 254 | CFI_ENDPROC | 260 | CFI_ENDPROC |
| @@ -314,7 +320,7 @@ ENTRY(ia32_cstar_target) | |||
| 314 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 320 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
| 315 | CFI_REMEMBER_STATE | 321 | CFI_REMEMBER_STATE |
| 316 | jnz cstar_tracesys | 322 | jnz cstar_tracesys |
| 317 | cmpl $IA32_NR_syscalls-1,%eax | 323 | cmpq $IA32_NR_syscalls-1,%rax |
| 318 | ja ia32_badsys | 324 | ja ia32_badsys |
| 319 | cstar_do_call: | 325 | cstar_do_call: |
| 320 | IA32_ARG_FIXUP 1 | 326 | IA32_ARG_FIXUP 1 |
| @@ -367,7 +373,7 @@ cstar_tracesys: | |||
| 367 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ | 373 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ |
| 368 | RESTORE_REST | 374 | RESTORE_REST |
| 369 | xchgl %ebp,%r9d | 375 | xchgl %ebp,%r9d |
| 370 | cmpl $(IA32_NR_syscalls-1),%eax | 376 | cmpq $(IA32_NR_syscalls-1),%rax |
| 371 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ | 377 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ |
| 372 | jmp cstar_do_call | 378 | jmp cstar_do_call |
| 373 | END(ia32_cstar_target) | 379 | END(ia32_cstar_target) |
| @@ -425,7 +431,7 @@ ENTRY(ia32_syscall) | |||
| 425 | orl $TS_COMPAT,TI_status(%r10) | 431 | orl $TS_COMPAT,TI_status(%r10) |
| 426 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 432 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
| 427 | jnz ia32_tracesys | 433 | jnz ia32_tracesys |
| 428 | cmpl $(IA32_NR_syscalls-1),%eax | 434 | cmpq $(IA32_NR_syscalls-1),%rax |
| 429 | ja ia32_badsys | 435 | ja ia32_badsys |
| 430 | ia32_do_call: | 436 | ia32_do_call: |
| 431 | IA32_ARG_FIXUP | 437 | IA32_ARG_FIXUP |
| @@ -444,7 +450,7 @@ ia32_tracesys: | |||
| 444 | call syscall_trace_enter | 450 | call syscall_trace_enter |
| 445 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 451 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
| 446 | RESTORE_REST | 452 | RESTORE_REST |
| 447 | cmpl $(IA32_NR_syscalls-1),%eax | 453 | cmpq $(IA32_NR_syscalls-1),%rax |
| 448 | ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ | 454 | ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ |
| 449 | jmp ia32_do_call | 455 | jmp ia32_do_call |
| 450 | END(ia32_syscall) | 456 | END(ia32_syscall) |
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 306160e58b48..1d9cd27c2920 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h | |||
| @@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) | |||
| 205 | return (u32)(unsigned long)uptr; | 205 | return (u32)(unsigned long)uptr; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static inline void __user *compat_alloc_user_space(long len) | 208 | static inline void __user *arch_compat_alloc_user_space(long len) |
| 209 | { | 209 | { |
| 210 | struct pt_regs *regs = task_pt_regs(current); | 210 | struct pt_regs *regs = task_pt_regs(current); |
| 211 | return (void __user *)regs->sp - len; | 211 | return (void __user *)regs->sp - len; |
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 51cfd730ac5d..1f99ecfc48e1 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h | |||
| @@ -152,9 +152,14 @@ struct x86_emulate_ops { | |||
| 152 | struct operand { | 152 | struct operand { |
| 153 | enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; | 153 | enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; |
| 154 | unsigned int bytes; | 154 | unsigned int bytes; |
| 155 | unsigned long orig_val, *ptr; | 155 | union { |
| 156 | unsigned long orig_val; | ||
| 157 | u64 orig_val64; | ||
| 158 | }; | ||
| 159 | unsigned long *ptr; | ||
| 156 | union { | 160 | union { |
| 157 | unsigned long val; | 161 | unsigned long val; |
| 162 | u64 val64; | ||
| 158 | char valptr[sizeof(unsigned long) + 2]; | 163 | char valptr[sizeof(unsigned long) + 2]; |
| 159 | }; | 164 | }; |
| 160 | }; | 165 | }; |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index d632934cb638..26a863a9c2a8 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
| @@ -655,7 +655,7 @@ void restore_sched_clock_state(void) | |||
| 655 | 655 | ||
| 656 | local_irq_save(flags); | 656 | local_irq_save(flags); |
| 657 | 657 | ||
| 658 | get_cpu_var(cyc2ns_offset) = 0; | 658 | __get_cpu_var(cyc2ns_offset) = 0; |
| 659 | offset = cyc2ns_suspend - sched_clock(); | 659 | offset = cyc2ns_suspend - sched_clock(); |
| 660 | 660 | ||
| 661 | for_each_possible_cpu(cpu) | 661 | for_each_possible_cpu(cpu) |
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index b38bd8b92aa6..66ca98aafdd6 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
| @@ -1870,17 +1870,16 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | |||
| 1870 | struct x86_emulate_ops *ops) | 1870 | struct x86_emulate_ops *ops) |
| 1871 | { | 1871 | { |
| 1872 | struct decode_cache *c = &ctxt->decode; | 1872 | struct decode_cache *c = &ctxt->decode; |
| 1873 | u64 old = c->dst.orig_val; | 1873 | u64 old = c->dst.orig_val64; |
| 1874 | 1874 | ||
| 1875 | if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || | 1875 | if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || |
| 1876 | ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { | 1876 | ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { |
| 1877 | |||
| 1878 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); | 1877 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); |
| 1879 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); | 1878 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); |
| 1880 | ctxt->eflags &= ~EFLG_ZF; | 1879 | ctxt->eflags &= ~EFLG_ZF; |
| 1881 | } else { | 1880 | } else { |
| 1882 | c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) | | 1881 | c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) | |
| 1883 | (u32) c->regs[VCPU_REGS_RBX]; | 1882 | (u32) c->regs[VCPU_REGS_RBX]; |
| 1884 | 1883 | ||
| 1885 | ctxt->eflags |= EFLG_ZF; | 1884 | ctxt->eflags |= EFLG_ZF; |
| 1886 | } | 1885 | } |
| @@ -2616,7 +2615,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
| 2616 | c->src.valptr, c->src.bytes); | 2615 | c->src.valptr, c->src.bytes); |
| 2617 | if (rc != X86EMUL_CONTINUE) | 2616 | if (rc != X86EMUL_CONTINUE) |
| 2618 | goto done; | 2617 | goto done; |
| 2619 | c->src.orig_val = c->src.val; | 2618 | c->src.orig_val64 = c->src.val64; |
| 2620 | } | 2619 | } |
| 2621 | 2620 | ||
| 2622 | if (c->src2.type == OP_MEM) { | 2621 | if (c->src2.type == OP_MEM) { |
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 8d10c063d7f2..4b7b73ce2098 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
| @@ -64,6 +64,9 @@ static void pic_unlock(struct kvm_pic *s) | |||
| 64 | if (!found) | 64 | if (!found) |
| 65 | found = s->kvm->bsp_vcpu; | 65 | found = s->kvm->bsp_vcpu; |
| 66 | 66 | ||
| 67 | if (!found) | ||
| 68 | return; | ||
| 69 | |||
| 67 | kvm_vcpu_kick(found); | 70 | kvm_vcpu_kick(found); |
| 68 | } | 71 | } |
| 69 | } | 72 | } |
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h index ffed06871c5c..63c314502993 100644 --- a/arch/x86/kvm/irq.h +++ b/arch/x86/kvm/irq.h | |||
| @@ -43,7 +43,6 @@ struct kvm_kpic_state { | |||
| 43 | u8 irr; /* interrupt request register */ | 43 | u8 irr; /* interrupt request register */ |
| 44 | u8 imr; /* interrupt mask register */ | 44 | u8 imr; /* interrupt mask register */ |
| 45 | u8 isr; /* interrupt service register */ | 45 | u8 isr; /* interrupt service register */ |
| 46 | u8 isr_ack; /* interrupt ack detection */ | ||
| 47 | u8 priority_add; /* highest irq priority */ | 46 | u8 priority_add; /* highest irq priority */ |
| 48 | u8 irq_base; | 47 | u8 irq_base; |
| 49 | u8 read_reg_select; | 48 | u8 read_reg_select; |
| @@ -56,6 +55,7 @@ struct kvm_kpic_state { | |||
| 56 | u8 init4; /* true if 4 byte init */ | 55 | u8 init4; /* true if 4 byte init */ |
| 57 | u8 elcr; /* PIIX edge/trigger selection */ | 56 | u8 elcr; /* PIIX edge/trigger selection */ |
| 58 | u8 elcr_mask; | 57 | u8 elcr_mask; |
| 58 | u8 isr_ack; /* interrupt ack detection */ | ||
| 59 | struct kvm_pic *pics_state; | 59 | struct kvm_pic *pics_state; |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index a6809645d212..2fef1ef931a0 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
| @@ -966,7 +966,7 @@ blkiocg_create(struct cgroup_subsys *subsys, struct cgroup *cgroup) | |||
| 966 | 966 | ||
| 967 | /* Currently we do not support hierarchy deeper than two level (0,1) */ | 967 | /* Currently we do not support hierarchy deeper than two level (0,1) */ |
| 968 | if (parent != cgroup->top_cgroup) | 968 | if (parent != cgroup->top_cgroup) |
| 969 | return ERR_PTR(-EINVAL); | 969 | return ERR_PTR(-EPERM); |
| 970 | 970 | ||
| 971 | blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL); | 971 | blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL); |
| 972 | if (!blkcg) | 972 | if (!blkcg) |
diff --git a/block/blk-core.c b/block/blk-core.c index ee1a1e7e63cc..32a1c123dfb3 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -1198,9 +1198,9 @@ static int __make_request(struct request_queue *q, struct bio *bio) | |||
| 1198 | int el_ret; | 1198 | int el_ret; |
| 1199 | unsigned int bytes = bio->bi_size; | 1199 | unsigned int bytes = bio->bi_size; |
| 1200 | const unsigned short prio = bio_prio(bio); | 1200 | const unsigned short prio = bio_prio(bio); |
| 1201 | const bool sync = (bio->bi_rw & REQ_SYNC); | 1201 | const bool sync = !!(bio->bi_rw & REQ_SYNC); |
| 1202 | const bool unplug = (bio->bi_rw & REQ_UNPLUG); | 1202 | const bool unplug = !!(bio->bi_rw & REQ_UNPLUG); |
| 1203 | const unsigned int ff = bio->bi_rw & REQ_FAILFAST_MASK; | 1203 | const unsigned long ff = bio->bi_rw & REQ_FAILFAST_MASK; |
| 1204 | int rw_flags; | 1204 | int rw_flags; |
| 1205 | 1205 | ||
| 1206 | if ((bio->bi_rw & REQ_HARDBARRIER) && | 1206 | if ((bio->bi_rw & REQ_HARDBARRIER) && |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 001ab18078f5..0749b89c6885 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
| @@ -511,6 +511,7 @@ int blk_register_queue(struct gendisk *disk) | |||
| 511 | kobject_uevent(&q->kobj, KOBJ_REMOVE); | 511 | kobject_uevent(&q->kobj, KOBJ_REMOVE); |
| 512 | kobject_del(&q->kobj); | 512 | kobject_del(&q->kobj); |
| 513 | blk_trace_remove_sysfs(disk_to_dev(disk)); | 513 | blk_trace_remove_sysfs(disk_to_dev(disk)); |
| 514 | kobject_put(&dev->kobj); | ||
| 514 | return ret; | 515 | return ret; |
| 515 | } | 516 | } |
| 516 | 517 | ||
diff --git a/block/blk.h b/block/blk.h index 6e7dc87141e4..d6b911ac002c 100644 --- a/block/blk.h +++ b/block/blk.h | |||
| @@ -142,14 +142,18 @@ static inline int queue_congestion_off_threshold(struct request_queue *q) | |||
| 142 | 142 | ||
| 143 | static inline int blk_cpu_to_group(int cpu) | 143 | static inline int blk_cpu_to_group(int cpu) |
| 144 | { | 144 | { |
| 145 | int group = NR_CPUS; | ||
| 145 | #ifdef CONFIG_SCHED_MC | 146 | #ifdef CONFIG_SCHED_MC |
| 146 | const struct cpumask *mask = cpu_coregroup_mask(cpu); | 147 | const struct cpumask *mask = cpu_coregroup_mask(cpu); |
| 147 | return cpumask_first(mask); | 148 | group = cpumask_first(mask); |
| 148 | #elif defined(CONFIG_SCHED_SMT) | 149 | #elif defined(CONFIG_SCHED_SMT) |
| 149 | return cpumask_first(topology_thread_cpumask(cpu)); | 150 | group = cpumask_first(topology_thread_cpumask(cpu)); |
| 150 | #else | 151 | #else |
| 151 | return cpu; | 152 | return cpu; |
| 152 | #endif | 153 | #endif |
| 154 | if (likely(group < NR_CPUS)) | ||
| 155 | return group; | ||
| 156 | return cpu; | ||
| 153 | } | 157 | } |
| 154 | 158 | ||
| 155 | /* | 159 | /* |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index eb4086f7dfef..f65c6f01c475 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -30,6 +30,7 @@ static const int cfq_slice_sync = HZ / 10; | |||
| 30 | static int cfq_slice_async = HZ / 25; | 30 | static int cfq_slice_async = HZ / 25; |
| 31 | static const int cfq_slice_async_rq = 2; | 31 | static const int cfq_slice_async_rq = 2; |
| 32 | static int cfq_slice_idle = HZ / 125; | 32 | static int cfq_slice_idle = HZ / 125; |
| 33 | static int cfq_group_idle = HZ / 125; | ||
| 33 | static const int cfq_target_latency = HZ * 3/10; /* 300 ms */ | 34 | static const int cfq_target_latency = HZ * 3/10; /* 300 ms */ |
| 34 | static const int cfq_hist_divisor = 4; | 35 | static const int cfq_hist_divisor = 4; |
| 35 | 36 | ||
| @@ -147,6 +148,8 @@ struct cfq_queue { | |||
| 147 | struct cfq_queue *new_cfqq; | 148 | struct cfq_queue *new_cfqq; |
| 148 | struct cfq_group *cfqg; | 149 | struct cfq_group *cfqg; |
| 149 | struct cfq_group *orig_cfqg; | 150 | struct cfq_group *orig_cfqg; |
| 151 | /* Number of sectors dispatched from queue in single dispatch round */ | ||
| 152 | unsigned long nr_sectors; | ||
| 150 | }; | 153 | }; |
| 151 | 154 | ||
| 152 | /* | 155 | /* |
| @@ -198,6 +201,8 @@ struct cfq_group { | |||
| 198 | struct hlist_node cfqd_node; | 201 | struct hlist_node cfqd_node; |
| 199 | atomic_t ref; | 202 | atomic_t ref; |
| 200 | #endif | 203 | #endif |
| 204 | /* number of requests that are on the dispatch list or inside driver */ | ||
| 205 | int dispatched; | ||
| 201 | }; | 206 | }; |
| 202 | 207 | ||
| 203 | /* | 208 | /* |
| @@ -271,6 +276,7 @@ struct cfq_data { | |||
| 271 | unsigned int cfq_slice[2]; | 276 | unsigned int cfq_slice[2]; |
| 272 | unsigned int cfq_slice_async_rq; | 277 | unsigned int cfq_slice_async_rq; |
| 273 | unsigned int cfq_slice_idle; | 278 | unsigned int cfq_slice_idle; |
| 279 | unsigned int cfq_group_idle; | ||
| 274 | unsigned int cfq_latency; | 280 | unsigned int cfq_latency; |
| 275 | unsigned int cfq_group_isolation; | 281 | unsigned int cfq_group_isolation; |
| 276 | 282 | ||
| @@ -378,6 +384,21 @@ CFQ_CFQQ_FNS(wait_busy); | |||
| 378 | &cfqg->service_trees[i][j]: NULL) \ | 384 | &cfqg->service_trees[i][j]: NULL) \ |
| 379 | 385 | ||
| 380 | 386 | ||
| 387 | static inline bool iops_mode(struct cfq_data *cfqd) | ||
| 388 | { | ||
| 389 | /* | ||
| 390 | * If we are not idling on queues and it is a NCQ drive, parallel | ||
| 391 | * execution of requests is on and measuring time is not possible | ||
| 392 | * in most of the cases until and unless we drive shallower queue | ||
| 393 | * depths and that becomes a performance bottleneck. In such cases | ||
| 394 | * switch to start providing fairness in terms of number of IOs. | ||
| 395 | */ | ||
| 396 | if (!cfqd->cfq_slice_idle && cfqd->hw_tag) | ||
| 397 | return true; | ||
| 398 | else | ||
| 399 | return false; | ||
| 400 | } | ||
| 401 | |||
| 381 | static inline enum wl_prio_t cfqq_prio(struct cfq_queue *cfqq) | 402 | static inline enum wl_prio_t cfqq_prio(struct cfq_queue *cfqq) |
| 382 | { | 403 | { |
| 383 | if (cfq_class_idle(cfqq)) | 404 | if (cfq_class_idle(cfqq)) |
| @@ -906,7 +927,6 @@ static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq) | |||
| 906 | slice_used = cfqq->allocated_slice; | 927 | slice_used = cfqq->allocated_slice; |
| 907 | } | 928 | } |
| 908 | 929 | ||
| 909 | cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u", slice_used); | ||
| 910 | return slice_used; | 930 | return slice_used; |
| 911 | } | 931 | } |
| 912 | 932 | ||
| @@ -914,19 +934,21 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, | |||
| 914 | struct cfq_queue *cfqq) | 934 | struct cfq_queue *cfqq) |
| 915 | { | 935 | { |
| 916 | struct cfq_rb_root *st = &cfqd->grp_service_tree; | 936 | struct cfq_rb_root *st = &cfqd->grp_service_tree; |
| 917 | unsigned int used_sl, charge_sl; | 937 | unsigned int used_sl, charge; |
| 918 | int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg) | 938 | int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg) |
| 919 | - cfqg->service_tree_idle.count; | 939 | - cfqg->service_tree_idle.count; |
| 920 | 940 | ||
| 921 | BUG_ON(nr_sync < 0); | 941 | BUG_ON(nr_sync < 0); |
| 922 | used_sl = charge_sl = cfq_cfqq_slice_usage(cfqq); | 942 | used_sl = charge = cfq_cfqq_slice_usage(cfqq); |
| 923 | 943 | ||
| 924 | if (!cfq_cfqq_sync(cfqq) && !nr_sync) | 944 | if (iops_mode(cfqd)) |
| 925 | charge_sl = cfqq->allocated_slice; | 945 | charge = cfqq->slice_dispatch; |
| 946 | else if (!cfq_cfqq_sync(cfqq) && !nr_sync) | ||
| 947 | charge = cfqq->allocated_slice; | ||
| 926 | 948 | ||
| 927 | /* Can't update vdisktime while group is on service tree */ | 949 | /* Can't update vdisktime while group is on service tree */ |
| 928 | cfq_rb_erase(&cfqg->rb_node, st); | 950 | cfq_rb_erase(&cfqg->rb_node, st); |
| 929 | cfqg->vdisktime += cfq_scale_slice(charge_sl, cfqg); | 951 | cfqg->vdisktime += cfq_scale_slice(charge, cfqg); |
| 930 | __cfq_group_service_tree_add(st, cfqg); | 952 | __cfq_group_service_tree_add(st, cfqg); |
| 931 | 953 | ||
| 932 | /* This group is being expired. Save the context */ | 954 | /* This group is being expired. Save the context */ |
| @@ -940,6 +962,9 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg, | |||
| 940 | 962 | ||
| 941 | cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime, | 963 | cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime, |
| 942 | st->min_vdisktime); | 964 | st->min_vdisktime); |
| 965 | cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u" | ||
| 966 | " sect=%u", used_sl, cfqq->slice_dispatch, charge, | ||
| 967 | iops_mode(cfqd), cfqq->nr_sectors); | ||
| 943 | cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); | 968 | cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); |
| 944 | cfq_blkiocg_set_start_empty_time(&cfqg->blkg); | 969 | cfq_blkiocg_set_start_empty_time(&cfqg->blkg); |
| 945 | } | 970 | } |
| @@ -1587,6 +1612,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd, | |||
| 1587 | cfqq->allocated_slice = 0; | 1612 | cfqq->allocated_slice = 0; |
| 1588 | cfqq->slice_end = 0; | 1613 | cfqq->slice_end = 0; |
| 1589 | cfqq->slice_dispatch = 0; | 1614 | cfqq->slice_dispatch = 0; |
| 1615 | cfqq->nr_sectors = 0; | ||
| 1590 | 1616 | ||
| 1591 | cfq_clear_cfqq_wait_request(cfqq); | 1617 | cfq_clear_cfqq_wait_request(cfqq); |
| 1592 | cfq_clear_cfqq_must_dispatch(cfqq); | 1618 | cfq_clear_cfqq_must_dispatch(cfqq); |
| @@ -1839,6 +1865,9 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 1839 | BUG_ON(!service_tree); | 1865 | BUG_ON(!service_tree); |
| 1840 | BUG_ON(!service_tree->count); | 1866 | BUG_ON(!service_tree->count); |
| 1841 | 1867 | ||
| 1868 | if (!cfqd->cfq_slice_idle) | ||
| 1869 | return false; | ||
| 1870 | |||
| 1842 | /* We never do for idle class queues. */ | 1871 | /* We never do for idle class queues. */ |
| 1843 | if (prio == IDLE_WORKLOAD) | 1872 | if (prio == IDLE_WORKLOAD) |
| 1844 | return false; | 1873 | return false; |
| @@ -1863,7 +1892,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
| 1863 | { | 1892 | { |
| 1864 | struct cfq_queue *cfqq = cfqd->active_queue; | 1893 | struct cfq_queue *cfqq = cfqd->active_queue; |
| 1865 | struct cfq_io_context *cic; | 1894 | struct cfq_io_context *cic; |
| 1866 | unsigned long sl; | 1895 | unsigned long sl, group_idle = 0; |
| 1867 | 1896 | ||
| 1868 | /* | 1897 | /* |
| 1869 | * SSD device without seek penalty, disable idling. But only do so | 1898 | * SSD device without seek penalty, disable idling. But only do so |
| @@ -1879,8 +1908,13 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
| 1879 | /* | 1908 | /* |
| 1880 | * idle is disabled, either manually or by past process history | 1909 | * idle is disabled, either manually or by past process history |
| 1881 | */ | 1910 | */ |
| 1882 | if (!cfqd->cfq_slice_idle || !cfq_should_idle(cfqd, cfqq)) | 1911 | if (!cfq_should_idle(cfqd, cfqq)) { |
| 1883 | return; | 1912 | /* no queue idling. Check for group idling */ |
| 1913 | if (cfqd->cfq_group_idle) | ||
| 1914 | group_idle = cfqd->cfq_group_idle; | ||
| 1915 | else | ||
| 1916 | return; | ||
| 1917 | } | ||
| 1884 | 1918 | ||
| 1885 | /* | 1919 | /* |
| 1886 | * still active requests from this queue, don't idle | 1920 | * still active requests from this queue, don't idle |
| @@ -1907,13 +1941,21 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
| 1907 | return; | 1941 | return; |
| 1908 | } | 1942 | } |
| 1909 | 1943 | ||
| 1944 | /* There are other queues in the group, don't do group idle */ | ||
| 1945 | if (group_idle && cfqq->cfqg->nr_cfqq > 1) | ||
| 1946 | return; | ||
| 1947 | |||
| 1910 | cfq_mark_cfqq_wait_request(cfqq); | 1948 | cfq_mark_cfqq_wait_request(cfqq); |
| 1911 | 1949 | ||
| 1912 | sl = cfqd->cfq_slice_idle; | 1950 | if (group_idle) |
| 1951 | sl = cfqd->cfq_group_idle; | ||
| 1952 | else | ||
| 1953 | sl = cfqd->cfq_slice_idle; | ||
| 1913 | 1954 | ||
| 1914 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); | 1955 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); |
| 1915 | cfq_blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg); | 1956 | cfq_blkiocg_update_set_idle_time_stats(&cfqq->cfqg->blkg); |
| 1916 | cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu", sl); | 1957 | cfq_log_cfqq(cfqd, cfqq, "arm_idle: %lu group_idle: %d", sl, |
| 1958 | group_idle ? 1 : 0); | ||
| 1917 | } | 1959 | } |
| 1918 | 1960 | ||
| 1919 | /* | 1961 | /* |
| @@ -1929,9 +1971,11 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq) | |||
| 1929 | cfqq->next_rq = cfq_find_next_rq(cfqd, cfqq, rq); | 1971 | cfqq->next_rq = cfq_find_next_rq(cfqd, cfqq, rq); |
| 1930 | cfq_remove_request(rq); | 1972 | cfq_remove_request(rq); |
| 1931 | cfqq->dispatched++; | 1973 | cfqq->dispatched++; |
| 1974 | (RQ_CFQG(rq))->dispatched++; | ||
| 1932 | elv_dispatch_sort(q, rq); | 1975 | elv_dispatch_sort(q, rq); |
| 1933 | 1976 | ||
| 1934 | cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++; | 1977 | cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++; |
| 1978 | cfqq->nr_sectors += blk_rq_sectors(rq); | ||
| 1935 | cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq), | 1979 | cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq), |
| 1936 | rq_data_dir(rq), rq_is_sync(rq)); | 1980 | rq_data_dir(rq), rq_is_sync(rq)); |
| 1937 | } | 1981 | } |
| @@ -2198,7 +2242,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | |||
| 2198 | cfqq = NULL; | 2242 | cfqq = NULL; |
| 2199 | goto keep_queue; | 2243 | goto keep_queue; |
| 2200 | } else | 2244 | } else |
| 2201 | goto expire; | 2245 | goto check_group_idle; |
| 2202 | } | 2246 | } |
| 2203 | 2247 | ||
| 2204 | /* | 2248 | /* |
| @@ -2226,8 +2270,23 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) | |||
| 2226 | * flight or is idling for a new request, allow either of these | 2270 | * flight or is idling for a new request, allow either of these |
| 2227 | * conditions to happen (or time out) before selecting a new queue. | 2271 | * conditions to happen (or time out) before selecting a new queue. |
| 2228 | */ | 2272 | */ |
| 2229 | if (timer_pending(&cfqd->idle_slice_timer) || | 2273 | if (timer_pending(&cfqd->idle_slice_timer)) { |
| 2230 | (cfqq->dispatched && cfq_should_idle(cfqd, cfqq))) { | 2274 | cfqq = NULL; |
| 2275 | goto keep_queue; | ||
| 2276 | } | ||
| 2277 | |||
| 2278 | if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) { | ||
| 2279 | cfqq = NULL; | ||
| 2280 | goto keep_queue; | ||
| 2281 | } | ||
| 2282 | |||
| 2283 | /* | ||
| 2284 | * If group idle is enabled and there are requests dispatched from | ||
| 2285 | * this group, wait for requests to complete. | ||
| 2286 | */ | ||
| 2287 | check_group_idle: | ||
| 2288 | if (cfqd->cfq_group_idle && cfqq->cfqg->nr_cfqq == 1 | ||
| 2289 | && cfqq->cfqg->dispatched) { | ||
| 2231 | cfqq = NULL; | 2290 | cfqq = NULL; |
| 2232 | goto keep_queue; | 2291 | goto keep_queue; |
| 2233 | } | 2292 | } |
| @@ -3375,6 +3434,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
| 3375 | WARN_ON(!cfqq->dispatched); | 3434 | WARN_ON(!cfqq->dispatched); |
| 3376 | cfqd->rq_in_driver--; | 3435 | cfqd->rq_in_driver--; |
| 3377 | cfqq->dispatched--; | 3436 | cfqq->dispatched--; |
| 3437 | (RQ_CFQG(rq))->dispatched--; | ||
| 3378 | cfq_blkiocg_update_completion_stats(&cfqq->cfqg->blkg, | 3438 | cfq_blkiocg_update_completion_stats(&cfqq->cfqg->blkg, |
| 3379 | rq_start_time_ns(rq), rq_io_start_time_ns(rq), | 3439 | rq_start_time_ns(rq), rq_io_start_time_ns(rq), |
| 3380 | rq_data_dir(rq), rq_is_sync(rq)); | 3440 | rq_data_dir(rq), rq_is_sync(rq)); |
| @@ -3404,7 +3464,10 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
| 3404 | * the queue. | 3464 | * the queue. |
| 3405 | */ | 3465 | */ |
| 3406 | if (cfq_should_wait_busy(cfqd, cfqq)) { | 3466 | if (cfq_should_wait_busy(cfqd, cfqq)) { |
| 3407 | cfqq->slice_end = jiffies + cfqd->cfq_slice_idle; | 3467 | unsigned long extend_sl = cfqd->cfq_slice_idle; |
| 3468 | if (!cfqd->cfq_slice_idle) | ||
| 3469 | extend_sl = cfqd->cfq_group_idle; | ||
| 3470 | cfqq->slice_end = jiffies + extend_sl; | ||
| 3408 | cfq_mark_cfqq_wait_busy(cfqq); | 3471 | cfq_mark_cfqq_wait_busy(cfqq); |
| 3409 | cfq_log_cfqq(cfqd, cfqq, "will busy wait"); | 3472 | cfq_log_cfqq(cfqd, cfqq, "will busy wait"); |
| 3410 | } | 3473 | } |
| @@ -3850,6 +3913,7 @@ static void *cfq_init_queue(struct request_queue *q) | |||
| 3850 | cfqd->cfq_slice[1] = cfq_slice_sync; | 3913 | cfqd->cfq_slice[1] = cfq_slice_sync; |
| 3851 | cfqd->cfq_slice_async_rq = cfq_slice_async_rq; | 3914 | cfqd->cfq_slice_async_rq = cfq_slice_async_rq; |
| 3852 | cfqd->cfq_slice_idle = cfq_slice_idle; | 3915 | cfqd->cfq_slice_idle = cfq_slice_idle; |
| 3916 | cfqd->cfq_group_idle = cfq_group_idle; | ||
| 3853 | cfqd->cfq_latency = 1; | 3917 | cfqd->cfq_latency = 1; |
| 3854 | cfqd->cfq_group_isolation = 0; | 3918 | cfqd->cfq_group_isolation = 0; |
| 3855 | cfqd->hw_tag = -1; | 3919 | cfqd->hw_tag = -1; |
| @@ -3922,6 +3986,7 @@ SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); | |||
| 3922 | SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0); | 3986 | SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0); |
| 3923 | SHOW_FUNCTION(cfq_back_seek_penalty_show, cfqd->cfq_back_penalty, 0); | 3987 | SHOW_FUNCTION(cfq_back_seek_penalty_show, cfqd->cfq_back_penalty, 0); |
| 3924 | SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); | 3988 | SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); |
| 3989 | SHOW_FUNCTION(cfq_group_idle_show, cfqd->cfq_group_idle, 1); | ||
| 3925 | SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); | 3990 | SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); |
| 3926 | SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); | 3991 | SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); |
| 3927 | SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); | 3992 | SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); |
| @@ -3954,6 +4019,7 @@ STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); | |||
| 3954 | STORE_FUNCTION(cfq_back_seek_penalty_store, &cfqd->cfq_back_penalty, 1, | 4019 | STORE_FUNCTION(cfq_back_seek_penalty_store, &cfqd->cfq_back_penalty, 1, |
| 3955 | UINT_MAX, 0); | 4020 | UINT_MAX, 0); |
| 3956 | STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); | 4021 | STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); |
| 4022 | STORE_FUNCTION(cfq_group_idle_store, &cfqd->cfq_group_idle, 0, UINT_MAX, 1); | ||
| 3957 | STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); | 4023 | STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); |
| 3958 | STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); | 4024 | STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); |
| 3959 | STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, | 4025 | STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, |
| @@ -3975,6 +4041,7 @@ static struct elv_fs_entry cfq_attrs[] = { | |||
| 3975 | CFQ_ATTR(slice_async), | 4041 | CFQ_ATTR(slice_async), |
| 3976 | CFQ_ATTR(slice_async_rq), | 4042 | CFQ_ATTR(slice_async_rq), |
| 3977 | CFQ_ATTR(slice_idle), | 4043 | CFQ_ATTR(slice_idle), |
| 4044 | CFQ_ATTR(group_idle), | ||
| 3978 | CFQ_ATTR(low_latency), | 4045 | CFQ_ATTR(low_latency), |
| 3979 | CFQ_ATTR(group_isolation), | 4046 | CFQ_ATTR(group_isolation), |
| 3980 | __ATTR_NULL | 4047 | __ATTR_NULL |
| @@ -4028,6 +4095,12 @@ static int __init cfq_init(void) | |||
| 4028 | if (!cfq_slice_idle) | 4095 | if (!cfq_slice_idle) |
| 4029 | cfq_slice_idle = 1; | 4096 | cfq_slice_idle = 1; |
| 4030 | 4097 | ||
| 4098 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | ||
| 4099 | if (!cfq_group_idle) | ||
| 4100 | cfq_group_idle = 1; | ||
| 4101 | #else | ||
| 4102 | cfq_group_idle = 0; | ||
| 4103 | #endif | ||
| 4031 | if (cfq_slab_setup()) | 4104 | if (cfq_slab_setup()) |
| 4032 | return -ENOMEM; | 4105 | return -ENOMEM; |
| 4033 | 4106 | ||
diff --git a/block/elevator.c b/block/elevator.c index ec585c9554d3..205b09a5bd9e 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -1009,18 +1009,19 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) | |||
| 1009 | { | 1009 | { |
| 1010 | struct elevator_queue *old_elevator, *e; | 1010 | struct elevator_queue *old_elevator, *e; |
| 1011 | void *data; | 1011 | void *data; |
| 1012 | int err; | ||
| 1012 | 1013 | ||
| 1013 | /* | 1014 | /* |
| 1014 | * Allocate new elevator | 1015 | * Allocate new elevator |
| 1015 | */ | 1016 | */ |
| 1016 | e = elevator_alloc(q, new_e); | 1017 | e = elevator_alloc(q, new_e); |
| 1017 | if (!e) | 1018 | if (!e) |
| 1018 | return 0; | 1019 | return -ENOMEM; |
| 1019 | 1020 | ||
| 1020 | data = elevator_init_queue(q, e); | 1021 | data = elevator_init_queue(q, e); |
| 1021 | if (!data) { | 1022 | if (!data) { |
| 1022 | kobject_put(&e->kobj); | 1023 | kobject_put(&e->kobj); |
| 1023 | return 0; | 1024 | return -ENOMEM; |
| 1024 | } | 1025 | } |
| 1025 | 1026 | ||
| 1026 | /* | 1027 | /* |
| @@ -1043,7 +1044,8 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) | |||
| 1043 | 1044 | ||
| 1044 | __elv_unregister_queue(old_elevator); | 1045 | __elv_unregister_queue(old_elevator); |
| 1045 | 1046 | ||
| 1046 | if (elv_register_queue(q)) | 1047 | err = elv_register_queue(q); |
| 1048 | if (err) | ||
| 1047 | goto fail_register; | 1049 | goto fail_register; |
| 1048 | 1050 | ||
| 1049 | /* | 1051 | /* |
| @@ -1056,7 +1058,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) | |||
| 1056 | 1058 | ||
| 1057 | blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); | 1059 | blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); |
| 1058 | 1060 | ||
| 1059 | return 1; | 1061 | return 0; |
| 1060 | 1062 | ||
| 1061 | fail_register: | 1063 | fail_register: |
| 1062 | /* | 1064 | /* |
| @@ -1071,17 +1073,19 @@ fail_register: | |||
| 1071 | queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); | 1073 | queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); |
| 1072 | spin_unlock_irq(q->queue_lock); | 1074 | spin_unlock_irq(q->queue_lock); |
| 1073 | 1075 | ||
| 1074 | return 0; | 1076 | return err; |
| 1075 | } | 1077 | } |
| 1076 | 1078 | ||
| 1077 | ssize_t elv_iosched_store(struct request_queue *q, const char *name, | 1079 | /* |
| 1078 | size_t count) | 1080 | * Switch this queue to the given IO scheduler. |
| 1081 | */ | ||
| 1082 | int elevator_change(struct request_queue *q, const char *name) | ||
| 1079 | { | 1083 | { |
| 1080 | char elevator_name[ELV_NAME_MAX]; | 1084 | char elevator_name[ELV_NAME_MAX]; |
| 1081 | struct elevator_type *e; | 1085 | struct elevator_type *e; |
| 1082 | 1086 | ||
| 1083 | if (!q->elevator) | 1087 | if (!q->elevator) |
| 1084 | return count; | 1088 | return -ENXIO; |
| 1085 | 1089 | ||
| 1086 | strlcpy(elevator_name, name, sizeof(elevator_name)); | 1090 | strlcpy(elevator_name, name, sizeof(elevator_name)); |
| 1087 | e = elevator_get(strstrip(elevator_name)); | 1091 | e = elevator_get(strstrip(elevator_name)); |
| @@ -1092,13 +1096,27 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, | |||
| 1092 | 1096 | ||
| 1093 | if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { | 1097 | if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { |
| 1094 | elevator_put(e); | 1098 | elevator_put(e); |
| 1095 | return count; | 1099 | return 0; |
| 1096 | } | 1100 | } |
| 1097 | 1101 | ||
| 1098 | if (!elevator_switch(q, e)) | 1102 | return elevator_switch(q, e); |
| 1099 | printk(KERN_ERR "elevator: switch to %s failed\n", | 1103 | } |
| 1100 | elevator_name); | 1104 | EXPORT_SYMBOL(elevator_change); |
| 1101 | return count; | 1105 | |
| 1106 | ssize_t elv_iosched_store(struct request_queue *q, const char *name, | ||
| 1107 | size_t count) | ||
| 1108 | { | ||
| 1109 | int ret; | ||
| 1110 | |||
| 1111 | if (!q->elevator) | ||
| 1112 | return count; | ||
| 1113 | |||
| 1114 | ret = elevator_change(q, name); | ||
| 1115 | if (!ret) | ||
| 1116 | return count; | ||
| 1117 | |||
| 1118 | printk(KERN_ERR "elevator: switch to %s failed\n", name); | ||
| 1119 | return ret; | ||
| 1102 | } | 1120 | } |
| 1103 | 1121 | ||
| 1104 | ssize_t elv_iosched_show(struct request_queue *q, char *name) | 1122 | ssize_t elv_iosched_show(struct request_queue *q, char *name) |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 5419a49ff135..276d5a701dc3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -59,6 +59,7 @@ void device_pm_init(struct device *dev) | |||
| 59 | { | 59 | { |
| 60 | dev->power.status = DPM_ON; | 60 | dev->power.status = DPM_ON; |
| 61 | init_completion(&dev->power.completion); | 61 | init_completion(&dev->power.completion); |
| 62 | complete_all(&dev->power.completion); | ||
| 62 | dev->power.wakeup_count = 0; | 63 | dev->power.wakeup_count = 0; |
| 63 | pm_runtime_init(dev); | 64 | pm_runtime_init(dev); |
| 64 | } | 65 | } |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 31064df1370a..6124c2fd2d33 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -297,6 +297,8 @@ static void enqueue_cmd_and_start_io(ctlr_info_t *h, | |||
| 297 | spin_lock_irqsave(&h->lock, flags); | 297 | spin_lock_irqsave(&h->lock, flags); |
| 298 | addQ(&h->reqQ, c); | 298 | addQ(&h->reqQ, c); |
| 299 | h->Qdepth++; | 299 | h->Qdepth++; |
| 300 | if (h->Qdepth > h->maxQsinceinit) | ||
| 301 | h->maxQsinceinit = h->Qdepth; | ||
| 300 | start_io(h); | 302 | start_io(h); |
| 301 | spin_unlock_irqrestore(&h->lock, flags); | 303 | spin_unlock_irqrestore(&h->lock, flags); |
| 302 | } | 304 | } |
| @@ -4519,6 +4521,12 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) | |||
| 4519 | misc_fw_support = readl(&cfgtable->misc_fw_support); | 4521 | misc_fw_support = readl(&cfgtable->misc_fw_support); |
| 4520 | use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; | 4522 | use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; |
| 4521 | 4523 | ||
| 4524 | /* The doorbell reset seems to cause lockups on some Smart | ||
| 4525 | * Arrays (e.g. P410, P410i, maybe others). Until this is | ||
| 4526 | * fixed or at least isolated, avoid the doorbell reset. | ||
| 4527 | */ | ||
| 4528 | use_doorbell = 0; | ||
| 4529 | |||
| 4522 | rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); | 4530 | rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); |
| 4523 | if (rc) | 4531 | if (rc) |
| 4524 | goto unmap_cfgtable; | 4532 | goto unmap_cfgtable; |
| @@ -4712,6 +4720,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 4712 | h->scatter_list = kmalloc(h->max_commands * | 4720 | h->scatter_list = kmalloc(h->max_commands * |
| 4713 | sizeof(struct scatterlist *), | 4721 | sizeof(struct scatterlist *), |
| 4714 | GFP_KERNEL); | 4722 | GFP_KERNEL); |
| 4723 | if (!h->scatter_list) | ||
| 4724 | goto clean4; | ||
| 4725 | |||
| 4715 | for (k = 0; k < h->nr_cmds; k++) { | 4726 | for (k = 0; k < h->nr_cmds; k++) { |
| 4716 | h->scatter_list[k] = kmalloc(sizeof(struct scatterlist) * | 4727 | h->scatter_list[k] = kmalloc(sizeof(struct scatterlist) * |
| 4717 | h->maxsgentries, | 4728 | h->maxsgentries, |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f3c636d23718..91797bbbe702 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -477,7 +477,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) | |||
| 477 | pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; | 477 | pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; |
| 478 | 478 | ||
| 479 | if (bio_rw(bio) == WRITE) { | 479 | if (bio_rw(bio) == WRITE) { |
| 480 | bool barrier = (bio->bi_rw & REQ_HARDBARRIER); | 480 | bool barrier = !!(bio->bi_rw & REQ_HARDBARRIER); |
| 481 | struct file *file = lo->lo_backing_file; | 481 | struct file *file = lo->lo_backing_file; |
| 482 | 482 | ||
| 483 | if (barrier) { | 483 | if (barrier) { |
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index b82c5ce5e9df..76fa3deaee84 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c | |||
| @@ -974,8 +974,7 @@ static int mg_probe(struct platform_device *plat_dev) | |||
| 974 | host->breq->queuedata = host; | 974 | host->breq->queuedata = host; |
| 975 | 975 | ||
| 976 | /* mflash is random device, thanx for the noop */ | 976 | /* mflash is random device, thanx for the noop */ |
| 977 | elevator_exit(host->breq->elevator); | 977 | err = elevator_change(host->breq, "noop"); |
| 978 | err = elevator_init(host->breq, "noop"); | ||
| 979 | if (err) { | 978 | if (err) { |
| 980 | printk(KERN_ERR "%s:%d (elevator_init) fail\n", | 979 | printk(KERN_ERR "%s:%d (elevator_init) fail\n", |
| 981 | __func__, __LINE__); | 980 | __func__, __LINE__); |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d2ab01e90a96..dcbeb98f195a 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -103,8 +103,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
| 103 | if (connector->funcs->force) | 103 | if (connector->funcs->force) |
| 104 | connector->funcs->force(connector); | 104 | connector->funcs->force(connector); |
| 105 | } else { | 105 | } else { |
| 106 | connector->status = connector->funcs->detect(connector); | 106 | connector->status = connector->funcs->detect(connector, true); |
| 107 | drm_helper_hpd_irq_event(dev); | 107 | drm_kms_helper_poll_enable(dev); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | if (connector->status == connector_status_disconnected) { | 110 | if (connector->status == connector_status_disconnected) { |
| @@ -637,13 +637,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 637 | mode_changed = true; | 637 | mode_changed = true; |
| 638 | 638 | ||
| 639 | if (mode_changed) { | 639 | if (mode_changed) { |
| 640 | old_fb = set->crtc->fb; | ||
| 641 | set->crtc->fb = set->fb; | ||
| 642 | set->crtc->enabled = (set->mode != NULL); | 640 | set->crtc->enabled = (set->mode != NULL); |
| 643 | if (set->mode != NULL) { | 641 | if (set->mode != NULL) { |
| 644 | DRM_DEBUG_KMS("attempting to set mode from" | 642 | DRM_DEBUG_KMS("attempting to set mode from" |
| 645 | " userspace\n"); | 643 | " userspace\n"); |
| 646 | drm_mode_debug_printmodeline(set->mode); | 644 | drm_mode_debug_printmodeline(set->mode); |
| 645 | old_fb = set->crtc->fb; | ||
| 646 | set->crtc->fb = set->fb; | ||
| 647 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, | 647 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
| 648 | set->x, set->y, | 648 | set->x, set->y, |
| 649 | old_fb)) { | 649 | old_fb)) { |
| @@ -866,7 +866,7 @@ static void output_poll_execute(struct work_struct *work) | |||
| 866 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) | 866 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) |
| 867 | continue; | 867 | continue; |
| 868 | 868 | ||
| 869 | status = connector->funcs->detect(connector); | 869 | status = connector->funcs->detect(connector, false); |
| 870 | if (old_status != status) | 870 | if (old_status != status) |
| 871 | changed = true; | 871 | changed = true; |
| 872 | } | 872 | } |
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e20f78b542a7..f5bd9e590c80 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
| @@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
| 164 | dev->hose = pdev->sysdata; | 164 | dev->hose = pdev->sysdata; |
| 165 | #endif | 165 | #endif |
| 166 | 166 | ||
| 167 | mutex_lock(&drm_global_mutex); | ||
| 168 | |||
| 167 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { | 169 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { |
| 168 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); | 170 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
| 169 | goto err_g2; | 171 | goto err_g2; |
| @@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
| 199 | driver->name, driver->major, driver->minor, driver->patchlevel, | 201 | driver->name, driver->major, driver->minor, driver->patchlevel, |
| 200 | driver->date, pci_name(pdev), dev->primary->index); | 202 | driver->date, pci_name(pdev), dev->primary->index); |
| 201 | 203 | ||
| 204 | mutex_unlock(&drm_global_mutex); | ||
| 202 | return 0; | 205 | return 0; |
| 203 | 206 | ||
| 204 | err_g4: | 207 | err_g4: |
| @@ -210,6 +213,7 @@ err_g2: | |||
| 210 | pci_disable_device(pdev); | 213 | pci_disable_device(pdev); |
| 211 | err_g1: | 214 | err_g1: |
| 212 | kfree(dev); | 215 | kfree(dev); |
| 216 | mutex_unlock(&drm_global_mutex); | ||
| 213 | return ret; | 217 | return ret; |
| 214 | } | 218 | } |
| 215 | EXPORT_SYMBOL(drm_get_pci_dev); | 219 | EXPORT_SYMBOL(drm_get_pci_dev); |
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 460e9a3afa8d..92d1d0fb7b75 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c | |||
| @@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev, | |||
| 53 | dev->platformdev = platdev; | 53 | dev->platformdev = platdev; |
| 54 | dev->dev = &platdev->dev; | 54 | dev->dev = &platdev->dev; |
| 55 | 55 | ||
| 56 | mutex_lock(&drm_global_mutex); | ||
| 57 | |||
| 56 | ret = drm_fill_in_dev(dev, NULL, driver); | 58 | ret = drm_fill_in_dev(dev, NULL, driver); |
| 57 | 59 | ||
| 58 | if (ret) { | 60 | if (ret) { |
| @@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev, | |||
| 87 | 89 | ||
| 88 | list_add_tail(&dev->driver_item, &driver->device_list); | 90 | list_add_tail(&dev->driver_item, &driver->device_list); |
| 89 | 91 | ||
| 92 | mutex_unlock(&drm_global_mutex); | ||
| 93 | |||
| 90 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", | 94 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", |
| 91 | driver->name, driver->major, driver->minor, driver->patchlevel, | 95 | driver->name, driver->major, driver->minor, driver->patchlevel, |
| 92 | driver->date, dev->primary->index); | 96 | driver->date, dev->primary->index); |
| @@ -100,6 +104,7 @@ err_g2: | |||
| 100 | drm_put_minor(&dev->control); | 104 | drm_put_minor(&dev->control); |
| 101 | err_g1: | 105 | err_g1: |
| 102 | kfree(dev); | 106 | kfree(dev); |
| 107 | mutex_unlock(&drm_global_mutex); | ||
| 103 | return ret; | 108 | return ret; |
| 104 | } | 109 | } |
| 105 | EXPORT_SYMBOL(drm_get_platform_dev); | 110 | EXPORT_SYMBOL(drm_get_platform_dev); |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 86118a742231..85da4c40694c 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
| @@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device, | |||
| 159 | struct drm_connector *connector = to_drm_connector(device); | 159 | struct drm_connector *connector = to_drm_connector(device); |
| 160 | enum drm_connector_status status; | 160 | enum drm_connector_status status; |
| 161 | 161 | ||
| 162 | status = connector->funcs->detect(connector); | 162 | status = connector->funcs->detect(connector, true); |
| 163 | return snprintf(buf, PAGE_SIZE, "%s\n", | 163 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 164 | drm_get_connector_status_name(status)); | 164 | drm_get_connector_status_name(status)); |
| 165 | } | 165 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 59457e83b011..744225ebb4b2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -1350,17 +1350,25 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
| 1350 | i915_seqno_passed(i915_get_gem_seqno(dev, | 1350 | i915_seqno_passed(i915_get_gem_seqno(dev, |
| 1351 | &dev_priv->render_ring), | 1351 | &dev_priv->render_ring), |
| 1352 | i915_get_tail_request(dev)->seqno)) { | 1352 | i915_get_tail_request(dev)->seqno)) { |
| 1353 | bool missed_wakeup = false; | ||
| 1354 | |||
| 1353 | dev_priv->hangcheck_count = 0; | 1355 | dev_priv->hangcheck_count = 0; |
| 1354 | 1356 | ||
| 1355 | /* Issue a wake-up to catch stuck h/w. */ | 1357 | /* Issue a wake-up to catch stuck h/w. */ |
| 1356 | if (dev_priv->render_ring.waiting_gem_seqno | | 1358 | if (dev_priv->render_ring.waiting_gem_seqno && |
| 1357 | dev_priv->bsd_ring.waiting_gem_seqno) { | 1359 | waitqueue_active(&dev_priv->render_ring.irq_queue)) { |
| 1358 | DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n"); | 1360 | DRM_WAKEUP(&dev_priv->render_ring.irq_queue); |
| 1359 | if (dev_priv->render_ring.waiting_gem_seqno) | 1361 | missed_wakeup = true; |
| 1360 | DRM_WAKEUP(&dev_priv->render_ring.irq_queue); | 1362 | } |
| 1361 | if (dev_priv->bsd_ring.waiting_gem_seqno) | 1363 | |
| 1362 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); | 1364 | if (dev_priv->bsd_ring.waiting_gem_seqno && |
| 1365 | waitqueue_active(&dev_priv->bsd_ring.irq_queue)) { | ||
| 1366 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); | ||
| 1367 | missed_wakeup = true; | ||
| 1363 | } | 1368 | } |
| 1369 | |||
| 1370 | if (missed_wakeup) | ||
| 1371 | DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n"); | ||
| 1364 | return; | 1372 | return; |
| 1365 | } | 1373 | } |
| 1366 | 1374 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d094e9129223..4f5e15577e89 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -2206,9 +2206,17 @@ | |||
| 2206 | #define WM1_LP_SR_EN (1<<31) | 2206 | #define WM1_LP_SR_EN (1<<31) |
| 2207 | #define WM1_LP_LATENCY_SHIFT 24 | 2207 | #define WM1_LP_LATENCY_SHIFT 24 |
| 2208 | #define WM1_LP_LATENCY_MASK (0x7f<<24) | 2208 | #define WM1_LP_LATENCY_MASK (0x7f<<24) |
| 2209 | #define WM1_LP_FBC_LP1_MASK (0xf<<20) | ||
| 2210 | #define WM1_LP_FBC_LP1_SHIFT 20 | ||
| 2209 | #define WM1_LP_SR_MASK (0x1ff<<8) | 2211 | #define WM1_LP_SR_MASK (0x1ff<<8) |
| 2210 | #define WM1_LP_SR_SHIFT 8 | 2212 | #define WM1_LP_SR_SHIFT 8 |
| 2211 | #define WM1_LP_CURSOR_MASK (0x3f) | 2213 | #define WM1_LP_CURSOR_MASK (0x3f) |
| 2214 | #define WM2_LP_ILK 0x4510c | ||
| 2215 | #define WM2_LP_EN (1<<31) | ||
| 2216 | #define WM3_LP_ILK 0x45110 | ||
| 2217 | #define WM3_LP_EN (1<<31) | ||
| 2218 | #define WM1S_LP_ILK 0x45120 | ||
| 2219 | #define WM1S_LP_EN (1<<31) | ||
| 2212 | 2220 | ||
| 2213 | /* Memory latency timer register */ | 2221 | /* Memory latency timer register */ |
| 2214 | #define MLTR_ILK 0x11222 | 2222 | #define MLTR_ILK 0x11222 |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 4b7735196cd5..a02a8df73727 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -400,7 +400,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder | |||
| 400 | return status; | 400 | return status; |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) | 403 | static enum drm_connector_status |
| 404 | intel_crt_detect(struct drm_connector *connector, bool force) | ||
| 404 | { | 405 | { |
| 405 | struct drm_device *dev = connector->dev; | 406 | struct drm_device *dev = connector->dev; |
| 406 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 407 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| @@ -419,6 +420,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto | |||
| 419 | if (intel_crt_detect_ddc(encoder)) | 420 | if (intel_crt_detect_ddc(encoder)) |
| 420 | return connector_status_connected; | 421 | return connector_status_connected; |
| 421 | 422 | ||
| 423 | if (!force) | ||
| 424 | return connector->status; | ||
| 425 | |||
| 422 | /* for pre-945g platforms use load detect */ | 426 | /* for pre-945g platforms use load detect */ |
| 423 | if (encoder->crtc && encoder->crtc->enabled) { | 427 | if (encoder->crtc && encoder->crtc->enabled) { |
| 424 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); | 428 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40cc5da264a9..19daead5b525 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -2767,14 +2767,8 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | |||
| 2767 | /* Don't promote wm_size to unsigned... */ | 2767 | /* Don't promote wm_size to unsigned... */ |
| 2768 | if (wm_size > (long)wm->max_wm) | 2768 | if (wm_size > (long)wm->max_wm) |
| 2769 | wm_size = wm->max_wm; | 2769 | wm_size = wm->max_wm; |
| 2770 | if (wm_size <= 0) { | 2770 | if (wm_size <= 0) |
| 2771 | wm_size = wm->default_wm; | 2771 | wm_size = wm->default_wm; |
| 2772 | DRM_ERROR("Insufficient FIFO for plane, expect flickering:" | ||
| 2773 | " entries required = %ld, available = %lu.\n", | ||
| 2774 | entries_required + wm->guard_size, | ||
| 2775 | wm->fifo_size); | ||
| 2776 | } | ||
| 2777 | |||
| 2778 | return wm_size; | 2772 | return wm_size; |
| 2779 | } | 2773 | } |
| 2780 | 2774 | ||
| @@ -3388,8 +3382,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | |||
| 3388 | reg_value = I915_READ(WM1_LP_ILK); | 3382 | reg_value = I915_READ(WM1_LP_ILK); |
| 3389 | reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK | | 3383 | reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK | |
| 3390 | WM1_LP_CURSOR_MASK); | 3384 | WM1_LP_CURSOR_MASK); |
| 3391 | reg_value |= WM1_LP_SR_EN | | 3385 | reg_value |= (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | |
| 3392 | (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | | ||
| 3393 | (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm; | 3386 | (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm; |
| 3394 | 3387 | ||
| 3395 | I915_WRITE(WM1_LP_ILK, reg_value); | 3388 | I915_WRITE(WM1_LP_ILK, reg_value); |
| @@ -5675,6 +5668,9 @@ void intel_init_clock_gating(struct drm_device *dev) | |||
| 5675 | I915_WRITE(DISP_ARB_CTL, | 5668 | I915_WRITE(DISP_ARB_CTL, |
| 5676 | (I915_READ(DISP_ARB_CTL) | | 5669 | (I915_READ(DISP_ARB_CTL) | |
| 5677 | DISP_FBC_WM_DIS)); | 5670 | DISP_FBC_WM_DIS)); |
| 5671 | I915_WRITE(WM3_LP_ILK, 0); | ||
| 5672 | I915_WRITE(WM2_LP_ILK, 0); | ||
| 5673 | I915_WRITE(WM1_LP_ILK, 0); | ||
| 5678 | } | 5674 | } |
| 5679 | /* | 5675 | /* |
| 5680 | * Based on the document from hardware guys the following bits | 5676 | * Based on the document from hardware guys the following bits |
| @@ -5696,8 +5692,7 @@ void intel_init_clock_gating(struct drm_device *dev) | |||
| 5696 | ILK_DPFC_DIS2 | | 5692 | ILK_DPFC_DIS2 | |
| 5697 | ILK_CLK_FBC); | 5693 | ILK_CLK_FBC); |
| 5698 | } | 5694 | } |
| 5699 | if (IS_GEN6(dev)) | 5695 | return; |
| 5700 | return; | ||
| 5701 | } else if (IS_G4X(dev)) { | 5696 | } else if (IS_G4X(dev)) { |
| 5702 | uint32_t dspclk_gate; | 5697 | uint32_t dspclk_gate; |
| 5703 | I915_WRITE(RENCLK_GATE_D1, 0); | 5698 | I915_WRITE(RENCLK_GATE_D1, 0); |
| @@ -5758,11 +5753,9 @@ void intel_init_clock_gating(struct drm_device *dev) | |||
| 5758 | OUT_RING(MI_FLUSH); | 5753 | OUT_RING(MI_FLUSH); |
| 5759 | ADVANCE_LP_RING(); | 5754 | ADVANCE_LP_RING(); |
| 5760 | } | 5755 | } |
| 5761 | } else { | 5756 | } else |
| 5762 | DRM_DEBUG_KMS("Failed to allocate render context." | 5757 | DRM_DEBUG_KMS("Failed to allocate render context." |
| 5763 | "Disable RC6\n"); | 5758 | "Disable RC6\n"); |
| 5764 | return; | ||
| 5765 | } | ||
| 5766 | } | 5759 | } |
| 5767 | 5760 | ||
| 5768 | if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { | 5761 | if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 51d142939a26..1a51ee07de3e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -1386,7 +1386,7 @@ ironlake_dp_detect(struct drm_connector *connector) | |||
| 1386 | * \return false if DP port is disconnected. | 1386 | * \return false if DP port is disconnected. |
| 1387 | */ | 1387 | */ |
| 1388 | static enum drm_connector_status | 1388 | static enum drm_connector_status |
| 1389 | intel_dp_detect(struct drm_connector *connector) | 1389 | intel_dp_detect(struct drm_connector *connector, bool force) |
| 1390 | { | 1390 | { |
| 1391 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1391 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| 1392 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1392 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index a399f4b2c1c5..7c9ec1472d46 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -221,7 +221,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, | |||
| 221 | * | 221 | * |
| 222 | * Unimplemented. | 222 | * Unimplemented. |
| 223 | */ | 223 | */ |
| 224 | static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) | 224 | static enum drm_connector_status |
| 225 | intel_dvo_detect(struct drm_connector *connector, bool force) | ||
| 225 | { | 226 | { |
| 226 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 227 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| 227 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | 228 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ccd4c97e6524..926934a482ec 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -139,7 +139,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static enum drm_connector_status | 141 | static enum drm_connector_status |
| 142 | intel_hdmi_detect(struct drm_connector *connector) | 142 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
| 143 | { | 143 | { |
| 144 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 144 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| 145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b819c1081147..6ec39a86ed06 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -445,7 +445,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 445 | * connected and closed means disconnected. We also send hotplug events as | 445 | * connected and closed means disconnected. We also send hotplug events as |
| 446 | * needed, using lid status notification from the input layer. | 446 | * needed, using lid status notification from the input layer. |
| 447 | */ | 447 | */ |
| 448 | static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) | 448 | static enum drm_connector_status |
| 449 | intel_lvds_detect(struct drm_connector *connector, bool force) | ||
| 449 | { | 450 | { |
| 450 | struct drm_device *dev = connector->dev; | 451 | struct drm_device *dev = connector->dev; |
| 451 | enum drm_connector_status status = connector_status_connected; | 452 | enum drm_connector_status status = connector_status_connected; |
| @@ -540,7 +541,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
| 540 | * the LID nofication event. | 541 | * the LID nofication event. |
| 541 | */ | 542 | */ |
| 542 | if (connector) | 543 | if (connector) |
| 543 | connector->status = connector->funcs->detect(connector); | 544 | connector->status = connector->funcs->detect(connector, |
| 545 | false); | ||
| 546 | |||
| 544 | /* Don't force modeset on machines where it causes a GPU lockup */ | 547 | /* Don't force modeset on machines where it causes a GPU lockup */ |
| 545 | if (dmi_check_system(intel_no_modeset_on_lid)) | 548 | if (dmi_check_system(intel_no_modeset_on_lid)) |
| 546 | return NOTIFY_OK; | 549 | return NOTIFY_OK; |
| @@ -875,8 +878,6 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 875 | 878 | ||
| 876 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); | 879 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); |
| 877 | intel_encoder->crtc_mask = (1 << 1); | 880 | intel_encoder->crtc_mask = (1 << 1); |
| 878 | if (IS_I965G(dev)) | ||
| 879 | intel_encoder->crtc_mask |= (1 << 0); | ||
| 880 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); | 881 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); |
| 881 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); | 882 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); |
| 882 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 883 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e3b7a7ee39cb..e8e902d614ed 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -1417,7 +1417,7 @@ intel_analog_is_connected(struct drm_device *dev) | |||
| 1417 | if (!analog_connector) | 1417 | if (!analog_connector) |
| 1418 | return false; | 1418 | return false; |
| 1419 | 1419 | ||
| 1420 | if (analog_connector->funcs->detect(analog_connector) == | 1420 | if (analog_connector->funcs->detect(analog_connector, false) == |
| 1421 | connector_status_disconnected) | 1421 | connector_status_disconnected) |
| 1422 | return false; | 1422 | return false; |
| 1423 | 1423 | ||
| @@ -1486,7 +1486,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1486 | return status; | 1486 | return status; |
| 1487 | } | 1487 | } |
| 1488 | 1488 | ||
| 1489 | static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) | 1489 | static enum drm_connector_status |
| 1490 | intel_sdvo_detect(struct drm_connector *connector, bool force) | ||
| 1490 | { | 1491 | { |
| 1491 | uint16_t response; | 1492 | uint16_t response; |
| 1492 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1493 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index c671f60ce80b..4a117e318a73 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -1341,7 +1341,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector) | |||
| 1341 | * we have a pipe programmed in order to probe the TV. | 1341 | * we have a pipe programmed in order to probe the TV. |
| 1342 | */ | 1342 | */ |
| 1343 | static enum drm_connector_status | 1343 | static enum drm_connector_status |
| 1344 | intel_tv_detect(struct drm_connector *connector) | 1344 | intel_tv_detect(struct drm_connector *connector, bool force) |
| 1345 | { | 1345 | { |
| 1346 | struct drm_display_mode mode; | 1346 | struct drm_display_mode mode; |
| 1347 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1347 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
| @@ -1353,7 +1353,7 @@ intel_tv_detect(struct drm_connector *connector) | |||
| 1353 | 1353 | ||
| 1354 | if (encoder->crtc && encoder->crtc->enabled) { | 1354 | if (encoder->crtc && encoder->crtc->enabled) { |
| 1355 | type = intel_tv_detect_type(intel_tv); | 1355 | type = intel_tv_detect_type(intel_tv); |
| 1356 | } else { | 1356 | } else if (force) { |
| 1357 | struct drm_crtc *crtc; | 1357 | struct drm_crtc *crtc; |
| 1358 | int dpms_mode; | 1358 | int dpms_mode; |
| 1359 | 1359 | ||
| @@ -1364,10 +1364,9 @@ intel_tv_detect(struct drm_connector *connector) | |||
| 1364 | intel_release_load_detect_pipe(&intel_tv->base, connector, | 1364 | intel_release_load_detect_pipe(&intel_tv->base, connector, |
| 1365 | dpms_mode); | 1365 | dpms_mode); |
| 1366 | } else | 1366 | } else |
| 1367 | type = -1; | 1367 | return connector_status_unknown; |
| 1368 | } | 1368 | } else |
| 1369 | 1369 | return connector->status; | |
| 1370 | intel_tv->type = type; | ||
| 1371 | 1370 | ||
| 1372 | if (type < 0) | 1371 | if (type < 0) |
| 1373 | return connector_status_disconnected; | 1372 | return connector_status_disconnected; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index a1473fff06ac..87186a4bbf03 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
| @@ -168,7 +168,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static enum drm_connector_status | 170 | static enum drm_connector_status |
| 171 | nouveau_connector_detect(struct drm_connector *connector) | 171 | nouveau_connector_detect(struct drm_connector *connector, bool force) |
| 172 | { | 172 | { |
| 173 | struct drm_device *dev = connector->dev; | 173 | struct drm_device *dev = connector->dev; |
| 174 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 174 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
| @@ -246,7 +246,7 @@ detect_analog: | |||
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | static enum drm_connector_status | 248 | static enum drm_connector_status |
| 249 | nouveau_connector_detect_lvds(struct drm_connector *connector) | 249 | nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) |
| 250 | { | 250 | { |
| 251 | struct drm_device *dev = connector->dev; | 251 | struct drm_device *dev = connector->dev; |
| 252 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 252 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| @@ -267,7 +267,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector) | |||
| 267 | 267 | ||
| 268 | /* Try retrieving EDID via DDC */ | 268 | /* Try retrieving EDID via DDC */ |
| 269 | if (!dev_priv->vbios.fp_no_ddc) { | 269 | if (!dev_priv->vbios.fp_no_ddc) { |
| 270 | status = nouveau_connector_detect(connector); | 270 | status = nouveau_connector_detect(connector, force); |
| 271 | if (status == connector_status_connected) | 271 | if (status == connector_status_connected) |
| 272 | goto out; | 272 | goto out; |
| 273 | } | 273 | } |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 464a81a1990f..cd0290f946cf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -539,14 +539,15 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
| 539 | pll->algo = PLL_ALGO_LEGACY; | 539 | pll->algo = PLL_ALGO_LEGACY; |
| 540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; | 540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; |
| 541 | } | 541 | } |
| 542 | /* There is some evidence (often anecdotal) that RV515 LVDS | 542 | /* There is some evidence (often anecdotal) that RV515/RV620 LVDS |
| 543 | * (on some boards at least) prefers the legacy algo. I'm not | 543 | * (on some boards at least) prefers the legacy algo. I'm not |
| 544 | * sure whether this should handled generically or on a | 544 | * sure whether this should handled generically or on a |
| 545 | * case-by-case quirk basis. Both algos should work fine in the | 545 | * case-by-case quirk basis. Both algos should work fine in the |
| 546 | * majority of cases. | 546 | * majority of cases. |
| 547 | */ | 547 | */ |
| 548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && | 548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && |
| 549 | (rdev->family == CHIP_RV515)) { | 549 | ((rdev->family == CHIP_RV515) || |
| 550 | (rdev->family == CHIP_RV620))) { | ||
| 550 | /* allow the user to overrride just in case */ | 551 | /* allow the user to overrride just in case */ |
| 551 | if (radeon_new_pll == 1) | 552 | if (radeon_new_pll == 1) |
| 552 | pll->algo = PLL_ALGO_NEW; | 553 | pll->algo = PLL_ALGO_NEW; |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b8b7f010b25f..79082d4398ae 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -1160,14 +1160,25 @@ static void evergreen_gpu_init(struct radeon_device *rdev) | |||
| 1160 | EVERGREEN_MAX_BACKENDS_MASK)); | 1160 | EVERGREEN_MAX_BACKENDS_MASK)); |
| 1161 | break; | 1161 | break; |
| 1162 | } | 1162 | } |
| 1163 | } else | 1163 | } else { |
| 1164 | gb_backend_map = | 1164 | switch (rdev->family) { |
| 1165 | evergreen_get_tile_pipe_to_backend_map(rdev, | 1165 | case CHIP_CYPRESS: |
| 1166 | rdev->config.evergreen.max_tile_pipes, | 1166 | case CHIP_HEMLOCK: |
| 1167 | rdev->config.evergreen.max_backends, | 1167 | gb_backend_map = 0x66442200; |
| 1168 | ((EVERGREEN_MAX_BACKENDS_MASK << | 1168 | break; |
| 1169 | rdev->config.evergreen.max_backends) & | 1169 | case CHIP_JUNIPER: |
| 1170 | EVERGREEN_MAX_BACKENDS_MASK)); | 1170 | gb_backend_map = 0x00006420; |
| 1171 | break; | ||
| 1172 | default: | ||
| 1173 | gb_backend_map = | ||
| 1174 | evergreen_get_tile_pipe_to_backend_map(rdev, | ||
| 1175 | rdev->config.evergreen.max_tile_pipes, | ||
| 1176 | rdev->config.evergreen.max_backends, | ||
| 1177 | ((EVERGREEN_MAX_BACKENDS_MASK << | ||
| 1178 | rdev->config.evergreen.max_backends) & | ||
| 1179 | EVERGREEN_MAX_BACKENDS_MASK)); | ||
| 1180 | } | ||
| 1181 | } | ||
| 1171 | 1182 | ||
| 1172 | rdev->config.evergreen.tile_config = gb_addr_config; | 1183 | rdev->config.evergreen.tile_config = gb_addr_config; |
| 1173 | WREG32(GB_BACKEND_MAP, gb_backend_map); | 1184 | WREG32(GB_BACKEND_MAP, gb_backend_map); |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index e817a0bb5eb4..e151f16a8f86 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -2020,18 +2020,7 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l | |||
| 2020 | return false; | 2020 | return false; |
| 2021 | } | 2021 | } |
| 2022 | elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); | 2022 | elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); |
| 2023 | if (elapsed >= 3000) { | 2023 | if (elapsed >= 10000) { |
| 2024 | /* very likely the improbable case where current | ||
| 2025 | * rptr is equal to last recorded, a while ago, rptr | ||
| 2026 | * this is more likely a false positive update tracking | ||
| 2027 | * information which should force us to be recall at | ||
| 2028 | * latter point | ||
| 2029 | */ | ||
| 2030 | lockup->last_cp_rptr = cp->rptr; | ||
| 2031 | lockup->last_jiffies = jiffies; | ||
| 2032 | return false; | ||
| 2033 | } | ||
| 2034 | if (elapsed >= 1000) { | ||
| 2035 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); | 2024 | dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); |
| 2036 | return true; | 2025 | return true; |
| 2037 | } | 2026 | } |
| @@ -3308,13 +3297,14 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) | |||
| 3308 | unsigned long size; | 3297 | unsigned long size; |
| 3309 | unsigned prim_walk; | 3298 | unsigned prim_walk; |
| 3310 | unsigned nverts; | 3299 | unsigned nverts; |
| 3300 | unsigned num_cb = track->num_cb; | ||
| 3311 | 3301 | ||
| 3312 | for (i = 0; i < track->num_cb; i++) { | 3302 | if (!track->zb_cb_clear && !track->color_channel_mask && |
| 3303 | !track->blend_read_enable) | ||
| 3304 | num_cb = 0; | ||
| 3305 | |||
| 3306 | for (i = 0; i < num_cb; i++) { | ||
| 3313 | if (track->cb[i].robj == NULL) { | 3307 | if (track->cb[i].robj == NULL) { |
| 3314 | if (!(track->zb_cb_clear || track->color_channel_mask || | ||
| 3315 | track->blend_read_enable)) { | ||
| 3316 | continue; | ||
| 3317 | } | ||
| 3318 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | 3308 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); |
| 3319 | return -EINVAL; | 3309 | return -EINVAL; |
| 3320 | } | 3310 | } |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d13622ae74e9..9ceb2a1ce799 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
| @@ -1,3 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2009 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice (including the next | ||
| 13 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 14 | * Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 22 | * DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | |||
| 1 | #include "drmP.h" | 26 | #include "drmP.h" |
| 2 | #include "drm.h" | 27 | #include "drm.h" |
| 3 | #include "radeon_drm.h" | 28 | #include "radeon_drm.h" |
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.h b/drivers/gpu/drm/radeon/r600_blit_shaders.h index fdc3b378cbb0..f437d36dd98c 100644 --- a/drivers/gpu/drm/radeon/r600_blit_shaders.h +++ b/drivers/gpu/drm/radeon/r600_blit_shaders.h | |||
| @@ -1,3 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2009 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice (including the next | ||
| 13 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 14 | * Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 22 | * DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | */ | ||
| 1 | 25 | ||
| 2 | #ifndef R600_BLIT_SHADERS_H | 26 | #ifndef R600_BLIT_SHADERS_H |
| 3 | #define R600_BLIT_SHADERS_H | 27 | #define R600_BLIT_SHADERS_H |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index d8864949e387..250a3a918193 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
| @@ -1170,9 +1170,8 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
| 1170 | /* using get ib will give us the offset into the mipmap bo */ | 1170 | /* using get ib will give us the offset into the mipmap bo */ |
| 1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; | 1171 | word0 = radeon_get_ib_value(p, idx + 3) << 8; |
| 1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { | 1172 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { |
| 1173 | dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", | 1173 | /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", |
| 1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); | 1174 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ |
| 1175 | return -EINVAL; | ||
| 1176 | } | 1175 | } |
| 1177 | return 0; | 1176 | return 0; |
| 1178 | } | 1177 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index bd74e428bd14..a04b7a6ad95f 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
| @@ -1485,6 +1485,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
| 1485 | /* PowerMac8,1 ? */ | 1485 | /* PowerMac8,1 ? */ |
| 1486 | /* imac g5 isight */ | 1486 | /* imac g5 isight */ |
| 1487 | rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; | 1487 | rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; |
| 1488 | } else if ((rdev->pdev->device == 0x4a48) && | ||
| 1489 | (rdev->pdev->subsystem_vendor == 0x1002) && | ||
| 1490 | (rdev->pdev->subsystem_device == 0x4a48)) { | ||
| 1491 | /* Mac X800 */ | ||
| 1492 | rdev->mode_info.connector_table = CT_MAC_X800; | ||
| 1488 | } else | 1493 | } else |
| 1489 | #endif /* CONFIG_PPC_PMAC */ | 1494 | #endif /* CONFIG_PPC_PMAC */ |
| 1490 | #ifdef CONFIG_PPC64 | 1495 | #ifdef CONFIG_PPC64 |
| @@ -1961,6 +1966,48 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | |||
| 1961 | CONNECTOR_OBJECT_ID_VGA, | 1966 | CONNECTOR_OBJECT_ID_VGA, |
| 1962 | &hpd); | 1967 | &hpd); |
| 1963 | break; | 1968 | break; |
| 1969 | case CT_MAC_X800: | ||
| 1970 | DRM_INFO("Connector Table: %d (mac x800)\n", | ||
| 1971 | rdev->mode_info.connector_table); | ||
| 1972 | /* DVI - primary dac, internal tmds */ | ||
| 1973 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); | ||
| 1974 | hpd.hpd = RADEON_HPD_1; /* ??? */ | ||
| 1975 | radeon_add_legacy_encoder(dev, | ||
| 1976 | radeon_get_encoder_enum(dev, | ||
| 1977 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1978 | 0), | ||
| 1979 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1980 | radeon_add_legacy_encoder(dev, | ||
| 1981 | radeon_get_encoder_enum(dev, | ||
| 1982 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1983 | 1), | ||
| 1984 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1985 | radeon_add_legacy_connector(dev, 0, | ||
| 1986 | ATOM_DEVICE_DFP1_SUPPORT | | ||
| 1987 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1988 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c, | ||
| 1989 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, | ||
| 1990 | &hpd); | ||
| 1991 | /* DVI - tv dac, dvo */ | ||
| 1992 | ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); | ||
| 1993 | hpd.hpd = RADEON_HPD_2; /* ??? */ | ||
| 1994 | radeon_add_legacy_encoder(dev, | ||
| 1995 | radeon_get_encoder_enum(dev, | ||
| 1996 | ATOM_DEVICE_DFP2_SUPPORT, | ||
| 1997 | 0), | ||
| 1998 | ATOM_DEVICE_DFP2_SUPPORT); | ||
| 1999 | radeon_add_legacy_encoder(dev, | ||
| 2000 | radeon_get_encoder_enum(dev, | ||
| 2001 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 2002 | 2), | ||
| 2003 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 2004 | radeon_add_legacy_connector(dev, 1, | ||
| 2005 | ATOM_DEVICE_DFP2_SUPPORT | | ||
| 2006 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 2007 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c, | ||
| 2008 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, | ||
| 2009 | &hpd); | ||
| 2010 | break; | ||
| 1964 | default: | 2011 | default: |
| 1965 | DRM_INFO("Connector table: %d (invalid)\n", | 2012 | DRM_INFO("Connector table: %d (invalid)\n", |
| 1966 | rdev->mode_info.connector_table); | 2013 | rdev->mode_info.connector_table); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index a9dd7847d96e..ecc1a8fafbfd 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -481,7 +481,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, | |||
| 481 | return MODE_OK; | 481 | return MODE_OK; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) | 484 | static enum drm_connector_status |
| 485 | radeon_lvds_detect(struct drm_connector *connector, bool force) | ||
| 485 | { | 486 | { |
| 486 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 487 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 487 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); | 488 | struct drm_encoder *encoder = radeon_best_single_encoder(connector); |
| @@ -594,7 +595,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector, | |||
| 594 | return MODE_OK; | 595 | return MODE_OK; |
| 595 | } | 596 | } |
| 596 | 597 | ||
| 597 | static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) | 598 | static enum drm_connector_status |
| 599 | radeon_vga_detect(struct drm_connector *connector, bool force) | ||
| 598 | { | 600 | { |
| 599 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 601 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 600 | struct drm_encoder *encoder; | 602 | struct drm_encoder *encoder; |
| @@ -691,7 +693,8 @@ static int radeon_tv_mode_valid(struct drm_connector *connector, | |||
| 691 | return MODE_OK; | 693 | return MODE_OK; |
| 692 | } | 694 | } |
| 693 | 695 | ||
| 694 | static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) | 696 | static enum drm_connector_status |
| 697 | radeon_tv_detect(struct drm_connector *connector, bool force) | ||
| 695 | { | 698 | { |
| 696 | struct drm_encoder *encoder; | 699 | struct drm_encoder *encoder; |
| 697 | struct drm_encoder_helper_funcs *encoder_funcs; | 700 | struct drm_encoder_helper_funcs *encoder_funcs; |
| @@ -748,7 +751,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector) | |||
| 748 | * we have to check if this analog encoder is shared with anyone else (TV) | 751 | * we have to check if this analog encoder is shared with anyone else (TV) |
| 749 | * if its shared we have to set the other connector to disconnected. | 752 | * if its shared we have to set the other connector to disconnected. |
| 750 | */ | 753 | */ |
| 751 | static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) | 754 | static enum drm_connector_status |
| 755 | radeon_dvi_detect(struct drm_connector *connector, bool force) | ||
| 752 | { | 756 | { |
| 753 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 757 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 754 | struct drm_encoder *encoder = NULL; | 758 | struct drm_encoder *encoder = NULL; |
| @@ -972,7 +976,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) | |||
| 972 | return ret; | 976 | return ret; |
| 973 | } | 977 | } |
| 974 | 978 | ||
| 975 | static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) | 979 | static enum drm_connector_status |
| 980 | radeon_dp_detect(struct drm_connector *connector, bool force) | ||
| 976 | { | 981 | { |
| 977 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 982 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 978 | enum drm_connector_status ret = connector_status_disconnected; | 983 | enum drm_connector_status ret = connector_status_disconnected; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 6dd434ad2429..127a395f70fb 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -1140,17 +1140,18 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
| 1140 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; | 1140 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; |
| 1141 | else | 1141 | else |
| 1142 | radeon_crtc->rmx_type = RMX_OFF; | 1142 | radeon_crtc->rmx_type = RMX_OFF; |
| 1143 | src_v = crtc->mode.vdisplay; | ||
| 1144 | dst_v = radeon_crtc->native_mode.vdisplay; | ||
| 1145 | src_h = crtc->mode.hdisplay; | ||
| 1146 | dst_h = radeon_crtc->native_mode.vdisplay; | ||
| 1147 | /* copy native mode */ | 1143 | /* copy native mode */ |
| 1148 | memcpy(&radeon_crtc->native_mode, | 1144 | memcpy(&radeon_crtc->native_mode, |
| 1149 | &radeon_encoder->native_mode, | 1145 | &radeon_encoder->native_mode, |
| 1150 | sizeof(struct drm_display_mode)); | 1146 | sizeof(struct drm_display_mode)); |
| 1147 | src_v = crtc->mode.vdisplay; | ||
| 1148 | dst_v = radeon_crtc->native_mode.vdisplay; | ||
| 1149 | src_h = crtc->mode.hdisplay; | ||
| 1150 | dst_h = radeon_crtc->native_mode.hdisplay; | ||
| 1151 | 1151 | ||
| 1152 | /* fix up for overscan on hdmi */ | 1152 | /* fix up for overscan on hdmi */ |
| 1153 | if (ASIC_IS_AVIVO(rdev) && | 1153 | if (ASIC_IS_AVIVO(rdev) && |
| 1154 | (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) && | ||
| 1154 | ((radeon_encoder->underscan_type == UNDERSCAN_ON) || | 1155 | ((radeon_encoder->underscan_type == UNDERSCAN_ON) || |
| 1155 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && | 1156 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && |
| 1156 | drm_detect_hdmi_monitor(radeon_connector->edid) && | 1157 | drm_detect_hdmi_monitor(radeon_connector->edid) && |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index efbe975312dc..17a6602b5885 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -204,7 +204,7 @@ struct radeon_i2c_chan { | |||
| 204 | 204 | ||
| 205 | /* mostly for macs, but really any system without connector tables */ | 205 | /* mostly for macs, but really any system without connector tables */ |
| 206 | enum radeon_connector_table { | 206 | enum radeon_connector_table { |
| 207 | CT_NONE, | 207 | CT_NONE = 0, |
| 208 | CT_GENERIC, | 208 | CT_GENERIC, |
| 209 | CT_IBOOK, | 209 | CT_IBOOK, |
| 210 | CT_POWERBOOK_EXTERNAL, | 210 | CT_POWERBOOK_EXTERNAL, |
| @@ -215,6 +215,7 @@ enum radeon_connector_table { | |||
| 215 | CT_IMAC_G5_ISIGHT, | 215 | CT_IMAC_G5_ISIGHT, |
| 216 | CT_EMAC, | 216 | CT_EMAC, |
| 217 | CT_RN50_POWER, | 217 | CT_RN50_POWER, |
| 218 | CT_MAC_X800, | ||
| 218 | }; | 219 | }; |
| 219 | 220 | ||
| 220 | enum radeon_dvo_chip { | 221 | enum radeon_dvo_chip { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 2ff5cf78235f..7083b1a24df3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
| @@ -335,7 +335,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector) | |||
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static enum drm_connector_status | 337 | static enum drm_connector_status |
| 338 | vmw_ldu_connector_detect(struct drm_connector *connector) | 338 | vmw_ldu_connector_detect(struct drm_connector *connector, |
| 339 | bool force) | ||
| 339 | { | 340 | { |
| 340 | if (vmw_connector_to_ldu(connector)->pref_active) | 341 | if (vmw_connector_to_ldu(connector)->pref_active) |
| 341 | return connector_status_connected; | 342 | return connector_status_connected; |
| @@ -516,7 +517,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) | |||
| 516 | 517 | ||
| 517 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, | 518 | drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, |
| 518 | DRM_MODE_CONNECTOR_LVDS); | 519 | DRM_MODE_CONNECTOR_LVDS); |
| 519 | connector->status = vmw_ldu_connector_detect(connector); | 520 | connector->status = vmw_ldu_connector_detect(connector, true); |
| 520 | 521 | ||
| 521 | drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, | 522 | drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, |
| 522 | DRM_MODE_ENCODER_LVDS); | 523 | DRM_MODE_ENCODER_LVDS); |
| @@ -610,7 +611,7 @@ int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num, | |||
| 610 | ldu->pref_height = 600; | 611 | ldu->pref_height = 600; |
| 611 | ldu->pref_active = false; | 612 | ldu->pref_active = false; |
| 612 | } | 613 | } |
| 613 | con->status = vmw_ldu_connector_detect(con); | 614 | con->status = vmw_ldu_connector_detect(con, true); |
| 614 | } | 615 | } |
| 615 | 616 | ||
| 616 | mutex_unlock(&dev->mode_config.mutex); | 617 | mutex_unlock(&dev->mode_config.mutex); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0c52899be964..3f7292486024 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1285,8 +1285,11 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1285 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, | 1285 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, |
| 1286 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1286 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1287 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1287 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1288 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | ||
| 1289 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
| 1288 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1290 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1289 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 1291 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
| 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | ||
| 1290 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
| 1291 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
| 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
| @@ -1578,7 +1581,6 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, | 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, |
| 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, | 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, |
| 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, | 1583 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, |
| 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)}, | ||
| 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, | 1584 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, |
| 1583 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, | 1585 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, |
| 1584 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, | 1586 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 85c6d13c9ffa..765a4f53eb5c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -105,6 +105,7 @@ | |||
| 105 | 105 | ||
| 106 | #define USB_VENDOR_ID_ASUS 0x0486 | 106 | #define USB_VENDOR_ID_ASUS 0x0486 |
| 107 | #define USB_DEVICE_ID_ASUS_T91MT 0x0185 | 107 | #define USB_DEVICE_ID_ASUS_T91MT 0x0185 |
| 108 | #define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186 | ||
| 108 | 109 | ||
| 109 | #define USB_VENDOR_ID_ASUSTEK 0x0b05 | 110 | #define USB_VENDOR_ID_ASUSTEK 0x0b05 |
| 110 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 | 111 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 |
| @@ -128,6 +129,7 @@ | |||
| 128 | 129 | ||
| 129 | #define USB_VENDOR_ID_BTC 0x046e | 130 | #define USB_VENDOR_ID_BTC 0x046e |
| 130 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 | 131 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 |
| 132 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 | ||
| 131 | 133 | ||
| 132 | #define USB_VENDOR_ID_CANDO 0x2087 | 134 | #define USB_VENDOR_ID_CANDO 0x2087 |
| 133 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
| @@ -149,6 +151,7 @@ | |||
| 149 | 151 | ||
| 150 | #define USB_VENDOR_ID_CHICONY 0x04f2 | 152 | #define USB_VENDOR_ID_CHICONY 0x04f2 |
| 151 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 | 153 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 |
| 154 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d | ||
| 152 | 155 | ||
| 153 | #define USB_VENDOR_ID_CIDC 0x1677 | 156 | #define USB_VENDOR_ID_CIDC 0x1677 |
| 154 | 157 | ||
| @@ -507,6 +510,7 @@ | |||
| 507 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 510 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
| 508 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 511 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
| 509 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | 512 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 |
| 513 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 | ||
| 510 | 514 | ||
| 511 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 515 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
| 512 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 516 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c index e91437c18906..ac5421d568f1 100644 --- a/drivers/hid/hid-mosart.c +++ b/drivers/hid/hid-mosart.c | |||
| @@ -239,6 +239,7 @@ static void mosart_remove(struct hid_device *hdev) | |||
| 239 | 239 | ||
| 240 | static const struct hid_device_id mosart_devices[] = { | 240 | static const struct hid_device_id mosart_devices[] = { |
| 241 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | 241 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, |
| 242 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
| 242 | { } | 243 | { } |
| 243 | }; | 244 | }; |
| 244 | MODULE_DEVICE_TABLE(hid, mosart_devices); | 245 | MODULE_DEVICE_TABLE(hid, mosart_devices); |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 5771f851f856..956ed9ac19d4 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c | |||
| @@ -64,6 +64,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 64 | static const struct hid_device_id ts_devices[] = { | 64 | static const struct hid_device_id ts_devices[] = { |
| 65 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 65 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
| 66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
| 67 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | ||
| 67 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | 68 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, |
| 68 | { } | 69 | { } |
| 69 | }; | 70 | }; |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b729c0286679..599041a7f670 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -828,6 +828,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
| 828 | } | 828 | } |
| 829 | } else { | 829 | } else { |
| 830 | int skipped_report_id = 0; | 830 | int skipped_report_id = 0; |
| 831 | int report_id = buf[0]; | ||
| 831 | if (buf[0] == 0x0) { | 832 | if (buf[0] == 0x0) { |
| 832 | /* Don't send the Report ID */ | 833 | /* Don't send the Report ID */ |
| 833 | buf++; | 834 | buf++; |
| @@ -837,7 +838,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
| 837 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 838 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| 838 | HID_REQ_SET_REPORT, | 839 | HID_REQ_SET_REPORT, |
| 839 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 840 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
| 840 | ((report_type + 1) << 8) | *buf, | 841 | ((report_type + 1) << 8) | report_id, |
| 841 | interface->desc.bInterfaceNumber, buf, count, | 842 | interface->desc.bInterfaceNumber, buf, count, |
| 842 | USB_CTRL_SET_TIMEOUT); | 843 | USB_CTRL_SET_TIMEOUT); |
| 843 | /* count also the report id, if this was a numbered report. */ | 844 | /* count also the report id, if this was a numbered report. */ |
| @@ -1445,6 +1446,11 @@ static const struct hid_device_id hid_usb_table[] = { | |||
| 1445 | { } | 1446 | { } |
| 1446 | }; | 1447 | }; |
| 1447 | 1448 | ||
| 1449 | struct usb_interface *usbhid_find_interface(int minor) | ||
| 1450 | { | ||
| 1451 | return usb_find_interface(&hid_driver, minor); | ||
| 1452 | } | ||
| 1453 | |||
| 1448 | static struct hid_driver hid_usb_driver = { | 1454 | static struct hid_driver hid_usb_driver = { |
| 1449 | .name = "generic-usb", | 1455 | .name = "generic-usb", |
| 1450 | .id_table = hid_usb_table, | 1456 | .id_table = hid_usb_table, |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2643d3147621..70da3181c8a0 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -33,6 +33,7 @@ static const struct hid_blacklist { | |||
| 33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | 33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, |
| 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, |
| 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, |
| 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | ||
| 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, |
| 37 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
| 38 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
| @@ -69,6 +70,7 @@ static const struct hid_blacklist { | |||
| 69 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | 70 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, |
| 70 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | 71 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, |
| 71 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, | 72 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, |
| 73 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, | ||
| 72 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 74 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
| 73 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 75 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
| 74 | 76 | ||
| @@ -77,6 +79,8 @@ static const struct hid_blacklist { | |||
| 77 | 79 | ||
| 78 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, | 80 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, |
| 79 | 81 | ||
| 82 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, | ||
| 83 | |||
| 80 | { 0, 0 } | 84 | { 0, 0 } |
| 81 | }; | 85 | }; |
| 82 | 86 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 0a29c51114aa..681e620eb95b 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
| @@ -270,7 +270,7 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
| 270 | struct hiddev *hiddev; | 270 | struct hiddev *hiddev; |
| 271 | int res; | 271 | int res; |
| 272 | 272 | ||
| 273 | intf = usb_find_interface(&hiddev_driver, iminor(inode)); | 273 | intf = usbhid_find_interface(iminor(inode)); |
| 274 | if (!intf) | 274 | if (!intf) |
| 275 | return -ENODEV; | 275 | return -ENODEV; |
| 276 | hid = usb_get_intfdata(intf); | 276 | hid = usb_get_intfdata(intf); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 693fd3e720df..89d2e847dcc6 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
| @@ -42,6 +42,7 @@ void usbhid_submit_report | |||
| 42 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); | 42 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); |
| 43 | int usbhid_get_power(struct hid_device *hid); | 43 | int usbhid_get_power(struct hid_device *hid); |
| 44 | void usbhid_put_power(struct hid_device *hid); | 44 | void usbhid_put_power(struct hid_device *hid); |
| 45 | struct usb_interface *usbhid_find_interface(int minor); | ||
| 45 | 46 | ||
| 46 | /* iofl flags */ | 47 | /* iofl flags */ |
| 47 | #define HID_CTRL_RUNNING 1 | 48 | #define HID_CTRL_RUNNING 1 |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index a382e3dd0a5d..6fbeefa3a766 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
| @@ -682,7 +682,6 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) | |||
| 682 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | 682 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) |
| 683 | { | 683 | { |
| 684 | struct bf5xx_nand_info *info = to_nand_info(pdev); | 684 | struct bf5xx_nand_info *info = to_nand_info(pdev); |
| 685 | struct mtd_info *mtd = NULL; | ||
| 686 | 685 | ||
| 687 | platform_set_drvdata(pdev, NULL); | 686 | platform_set_drvdata(pdev, NULL); |
| 688 | 687 | ||
| @@ -690,11 +689,7 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | |||
| 690 | * and their partitions, then go through freeing the | 689 | * and their partitions, then go through freeing the |
| 691 | * resources used | 690 | * resources used |
| 692 | */ | 691 | */ |
| 693 | mtd = &info->mtd; | 692 | nand_release(&info->mtd); |
| 694 | if (mtd) { | ||
| 695 | nand_release(mtd); | ||
| 696 | kfree(mtd); | ||
| 697 | } | ||
| 698 | 693 | ||
| 699 | peripheral_free_list(bfin_nfc_pin_req); | 694 | peripheral_free_list(bfin_nfc_pin_req); |
| 700 | bf5xx_nand_dma_remove(info); | 695 | bf5xx_nand_dma_remove(info); |
| @@ -710,7 +705,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd) | |||
| 710 | struct nand_chip *chip = mtd->priv; | 705 | struct nand_chip *chip = mtd->priv; |
| 711 | int ret; | 706 | int ret; |
| 712 | 707 | ||
| 713 | ret = nand_scan_ident(mtd, 1); | 708 | ret = nand_scan_ident(mtd, 1, NULL); |
| 714 | if (ret) | 709 | if (ret) |
| 715 | return ret; | 710 | return ret; |
| 716 | 711 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index fcf8ceb277d4..b2828e84d243 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
| @@ -67,7 +67,9 @@ | |||
| 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) | 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) |
| 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) | 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) |
| 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) | 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) |
| 70 | #define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) | 70 | #define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) |
| 71 | #define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9) | ||
| 72 | #define NFC_V2_CONFIG1_FP_INT (1 << 11) | ||
| 71 | 73 | ||
| 72 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) | 74 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) |
| 73 | 75 | ||
| @@ -402,16 +404,16 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
| 402 | /* Wait for operation to complete */ | 404 | /* Wait for operation to complete */ |
| 403 | wait_op_done(host, true); | 405 | wait_op_done(host, true); |
| 404 | 406 | ||
| 407 | memcpy(host->data_buf, host->main_area0, 16); | ||
| 408 | |||
| 405 | if (this->options & NAND_BUSWIDTH_16) { | 409 | if (this->options & NAND_BUSWIDTH_16) { |
| 406 | void __iomem *main_buf = host->main_area0; | ||
| 407 | /* compress the ID info */ | 410 | /* compress the ID info */ |
| 408 | writeb(readb(main_buf + 2), main_buf + 1); | 411 | host->data_buf[1] = host->data_buf[2]; |
| 409 | writeb(readb(main_buf + 4), main_buf + 2); | 412 | host->data_buf[2] = host->data_buf[4]; |
| 410 | writeb(readb(main_buf + 6), main_buf + 3); | 413 | host->data_buf[3] = host->data_buf[6]; |
| 411 | writeb(readb(main_buf + 8), main_buf + 4); | 414 | host->data_buf[4] = host->data_buf[8]; |
| 412 | writeb(readb(main_buf + 10), main_buf + 5); | 415 | host->data_buf[5] = host->data_buf[10]; |
| 413 | } | 416 | } |
| 414 | memcpy(host->data_buf, host->main_area0, 16); | ||
| 415 | } | 417 | } |
| 416 | 418 | ||
| 417 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) | 419 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) |
| @@ -729,27 +731,30 @@ static void preset_v1_v2(struct mtd_info *mtd) | |||
| 729 | { | 731 | { |
| 730 | struct nand_chip *nand_chip = mtd->priv; | 732 | struct nand_chip *nand_chip = mtd->priv; |
| 731 | struct mxc_nand_host *host = nand_chip->priv; | 733 | struct mxc_nand_host *host = nand_chip->priv; |
| 732 | uint16_t tmp; | 734 | uint16_t config1 = 0; |
| 733 | 735 | ||
| 734 | /* enable interrupt, disable spare enable */ | 736 | if (nand_chip->ecc.mode == NAND_ECC_HW) |
| 735 | tmp = readw(NFC_V1_V2_CONFIG1); | 737 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; |
| 736 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; | 738 | |
| 737 | tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; | 739 | if (nfc_is_v21()) |
| 738 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 740 | config1 |= NFC_V2_CONFIG1_FP_INT; |
| 739 | tmp |= NFC_V1_V2_CONFIG1_ECC_EN; | 741 | |
| 740 | } else { | 742 | if (!cpu_is_mx21()) |
| 741 | tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; | 743 | config1 |= NFC_V1_V2_CONFIG1_INT_MSK; |
| 742 | } | ||
| 743 | 744 | ||
| 744 | if (nfc_is_v21() && mtd->writesize) { | 745 | if (nfc_is_v21() && mtd->writesize) { |
| 746 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; | ||
| 747 | |||
| 745 | host->eccsize = get_eccsize(mtd); | 748 | host->eccsize = get_eccsize(mtd); |
| 746 | if (host->eccsize == 4) | 749 | if (host->eccsize == 4) |
| 747 | tmp |= NFC_V2_CONFIG1_ECC_MODE_4; | 750 | config1 |= NFC_V2_CONFIG1_ECC_MODE_4; |
| 751 | |||
| 752 | config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6); | ||
| 748 | } else { | 753 | } else { |
| 749 | host->eccsize = 1; | 754 | host->eccsize = 1; |
| 750 | } | 755 | } |
| 751 | 756 | ||
| 752 | writew(tmp, NFC_V1_V2_CONFIG1); | 757 | writew(config1, NFC_V1_V2_CONFIG1); |
| 753 | /* preset operation */ | 758 | /* preset operation */ |
| 754 | 759 | ||
| 755 | /* Unlock the internal RAM Buffer */ | 760 | /* Unlock the internal RAM Buffer */ |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4d89f3780207..4d01cda68844 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
| @@ -1320,6 +1320,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
| 1320 | goto fail_free_irq; | 1320 | goto fail_free_irq; |
| 1321 | } | 1321 | } |
| 1322 | 1322 | ||
| 1323 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 1323 | if (mtd_has_cmdlinepart()) { | 1324 | if (mtd_has_cmdlinepart()) { |
| 1324 | static const char *probes[] = { "cmdlinepart", NULL }; | 1325 | static const char *probes[] = { "cmdlinepart", NULL }; |
| 1325 | struct mtd_partition *parts; | 1326 | struct mtd_partition *parts; |
| @@ -1332,6 +1333,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
| 1332 | } | 1333 | } |
| 1333 | 1334 | ||
| 1334 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1335 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); |
| 1336 | #else | ||
| 1337 | return 0; | ||
| 1338 | #endif | ||
| 1335 | 1339 | ||
| 1336 | fail_free_irq: | 1340 | fail_free_irq: |
| 1337 | free_irq(irq, info); | 1341 | free_irq(irq, info); |
| @@ -1364,7 +1368,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
| 1364 | platform_set_drvdata(pdev, NULL); | 1368 | platform_set_drvdata(pdev, NULL); |
| 1365 | 1369 | ||
| 1366 | del_mtd_device(mtd); | 1370 | del_mtd_device(mtd); |
| 1371 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 1367 | del_mtd_partitions(mtd); | 1372 | del_mtd_partitions(mtd); |
| 1373 | #endif | ||
| 1368 | irq = platform_get_irq(pdev, 0); | 1374 | irq = platform_get_irq(pdev, 0); |
| 1369 | if (irq >= 0) | 1375 | if (irq >= 0) |
| 1370 | free_irq(irq, info); | 1376 | free_irq(irq, info); |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index cb443af3d45f..a460f1b748c2 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
| @@ -554,14 +554,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | |||
| 554 | 554 | ||
| 555 | do { | 555 | do { |
| 556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); | 556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); |
| 557 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | ||
| 558 | writel(S5PC110_DMA_TRANS_CMD_TEC, | ||
| 559 | base + S5PC110_DMA_TRANS_CMD); | ||
| 560 | return -EIO; | ||
| 561 | } | ||
| 557 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); | 562 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); |
| 558 | 563 | ||
| 559 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | ||
| 560 | writel(S5PC110_DMA_TRANS_CMD_TEC, base + S5PC110_DMA_TRANS_CMD); | ||
| 561 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | ||
| 562 | return -EIO; | ||
| 563 | } | ||
| 564 | |||
| 565 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | 564 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); |
| 566 | 565 | ||
| 567 | return 0; | 566 | return 0; |
| @@ -571,13 +570,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
| 571 | unsigned char *buffer, int offset, size_t count) | 570 | unsigned char *buffer, int offset, size_t count) |
| 572 | { | 571 | { |
| 573 | struct onenand_chip *this = mtd->priv; | 572 | struct onenand_chip *this = mtd->priv; |
| 574 | void __iomem *bufferram; | ||
| 575 | void __iomem *p; | 573 | void __iomem *p; |
| 576 | void *buf = (void *) buffer; | 574 | void *buf = (void *) buffer; |
| 577 | dma_addr_t dma_src, dma_dst; | 575 | dma_addr_t dma_src, dma_dst; |
| 578 | int err; | 576 | int err; |
| 579 | 577 | ||
| 580 | p = bufferram = this->base + area; | 578 | p = this->base + area; |
| 581 | if (ONENAND_CURRENT_BUFFERRAM(this)) { | 579 | if (ONENAND_CURRENT_BUFFERRAM(this)) { |
| 582 | if (area == ONENAND_DATARAM) | 580 | if (area == ONENAND_DATARAM) |
| 583 | p += this->writesize; | 581 | p += this->writesize; |
| @@ -621,7 +619,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
| 621 | normal: | 619 | normal: |
| 622 | if (count != mtd->writesize) { | 620 | if (count != mtd->writesize) { |
| 623 | /* Copy the bufferram to memory to prevent unaligned access */ | 621 | /* Copy the bufferram to memory to prevent unaligned access */ |
| 624 | memcpy(this->page_buf, bufferram, mtd->writesize); | 622 | memcpy(this->page_buf, p, mtd->writesize); |
| 625 | p = this->page_buf + offset; | 623 | p = this->page_buf + offset; |
| 626 | } | 624 | } |
| 627 | 625 | ||
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index a045559c81cf..85671adae455 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c | |||
| @@ -1994,10 +1994,9 @@ vortex_error(struct net_device *dev, int status) | |||
| 1994 | } | 1994 | } |
| 1995 | } | 1995 | } |
| 1996 | 1996 | ||
| 1997 | if (status & RxEarly) { /* Rx early is unused. */ | 1997 | if (status & RxEarly) /* Rx early is unused. */ |
| 1998 | vortex_rx(dev); | ||
| 1999 | iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD); | 1998 | iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD); |
| 2000 | } | 1999 | |
| 2001 | if (status & StatsFull) { /* Empty statistics. */ | 2000 | if (status & StatsFull) { /* Empty statistics. */ |
| 2002 | static int DoneDidThat; | 2001 | static int DoneDidThat; |
| 2003 | if (vortex_debug > 4) | 2002 | if (vortex_debug > 4) |
| @@ -2298,7 +2297,12 @@ vortex_interrupt(int irq, void *dev_id) | |||
| 2298 | if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) { | 2297 | if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) { |
| 2299 | if (status == 0xffff) | 2298 | if (status == 0xffff) |
| 2300 | break; | 2299 | break; |
| 2300 | if (status & RxEarly) | ||
| 2301 | vortex_rx(dev); | ||
| 2302 | spin_unlock(&vp->window_lock); | ||
| 2301 | vortex_error(dev, status); | 2303 | vortex_error(dev, status); |
| 2304 | spin_lock(&vp->window_lock); | ||
| 2305 | window_set(vp, 7); | ||
| 2302 | } | 2306 | } |
| 2303 | 2307 | ||
| 2304 | if (--work_done < 0) { | 2308 | if (--work_done < 0) { |
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 37617abc1647..1e620e287ae0 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
| @@ -848,6 +848,15 @@ static int b44_poll(struct napi_struct *napi, int budget) | |||
| 848 | b44_tx(bp); | 848 | b44_tx(bp); |
| 849 | /* spin_unlock(&bp->tx_lock); */ | 849 | /* spin_unlock(&bp->tx_lock); */ |
| 850 | } | 850 | } |
| 851 | if (bp->istat & ISTAT_RFO) { /* fast recovery, in ~20msec */ | ||
| 852 | bp->istat &= ~ISTAT_RFO; | ||
| 853 | b44_disable_ints(bp); | ||
| 854 | ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */ | ||
| 855 | b44_init_rings(bp); | ||
| 856 | b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY); | ||
| 857 | netif_wake_queue(bp->dev); | ||
| 858 | } | ||
| 859 | |||
| 851 | spin_unlock_irqrestore(&bp->lock, flags); | 860 | spin_unlock_irqrestore(&bp->lock, flags); |
| 852 | 861 | ||
| 853 | work_done = 0; | 862 | work_done = 0; |
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 99197bd54da5..53306bf3f401 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
| @@ -181,6 +181,7 @@ struct be_drvr_stats { | |||
| 181 | u64 be_rx_bytes_prev; | 181 | u64 be_rx_bytes_prev; |
| 182 | u64 be_rx_pkts; | 182 | u64 be_rx_pkts; |
| 183 | u32 be_rx_rate; | 183 | u32 be_rx_rate; |
| 184 | u32 be_rx_mcast_pkt; | ||
| 184 | /* number of non ether type II frames dropped where | 185 | /* number of non ether type II frames dropped where |
| 185 | * frame len > length field of Mac Hdr */ | 186 | * frame len > length field of Mac Hdr */ |
| 186 | u32 be_802_3_dropped_frames; | 187 | u32 be_802_3_dropped_frames; |
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 3d305494a606..34abcc9403d6 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
| @@ -140,10 +140,8 @@ int be_process_mcc(struct be_adapter *adapter, int *status) | |||
| 140 | while ((compl = be_mcc_compl_get(adapter))) { | 140 | while ((compl = be_mcc_compl_get(adapter))) { |
| 141 | if (compl->flags & CQE_FLAGS_ASYNC_MASK) { | 141 | if (compl->flags & CQE_FLAGS_ASYNC_MASK) { |
| 142 | /* Interpret flags as an async trailer */ | 142 | /* Interpret flags as an async trailer */ |
| 143 | BUG_ON(!is_link_state_evt(compl->flags)); | 143 | if (is_link_state_evt(compl->flags)) |
| 144 | 144 | be_async_link_state_process(adapter, | |
| 145 | /* Interpret compl as a async link evt */ | ||
| 146 | be_async_link_state_process(adapter, | ||
| 147 | (struct be_async_event_link_state *) compl); | 145 | (struct be_async_event_link_state *) compl); |
| 148 | } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { | 146 | } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { |
| 149 | *status = be_mcc_compl_process(adapter, compl); | 147 | *status = be_mcc_compl_process(adapter, compl); |
| @@ -207,7 +205,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) | |||
| 207 | 205 | ||
| 208 | if (msecs > 4000) { | 206 | if (msecs > 4000) { |
| 209 | dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); | 207 | dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); |
| 210 | be_dump_ue(adapter); | 208 | be_detect_dump_ue(adapter); |
| 211 | return -1; | 209 | return -1; |
| 212 | } | 210 | } |
| 213 | 211 | ||
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index bdc10a28cfda..ad1e6fac60c5 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h | |||
| @@ -992,5 +992,5 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, | |||
| 992 | extern int be_cmd_get_phy_info(struct be_adapter *adapter, | 992 | extern int be_cmd_get_phy_info(struct be_adapter *adapter, |
| 993 | struct be_dma_mem *cmd); | 993 | struct be_dma_mem *cmd); |
| 994 | extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); | 994 | extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); |
| 995 | extern void be_dump_ue(struct be_adapter *adapter); | 995 | extern void be_detect_dump_ue(struct be_adapter *adapter); |
| 996 | 996 | ||
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index cd16243c7c36..13f0abbc5205 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c | |||
| @@ -60,6 +60,7 @@ static const struct be_ethtool_stat et_stats[] = { | |||
| 60 | {DRVSTAT_INFO(be_rx_events)}, | 60 | {DRVSTAT_INFO(be_rx_events)}, |
| 61 | {DRVSTAT_INFO(be_tx_compl)}, | 61 | {DRVSTAT_INFO(be_tx_compl)}, |
| 62 | {DRVSTAT_INFO(be_rx_compl)}, | 62 | {DRVSTAT_INFO(be_rx_compl)}, |
| 63 | {DRVSTAT_INFO(be_rx_mcast_pkt)}, | ||
| 63 | {DRVSTAT_INFO(be_ethrx_post_fail)}, | 64 | {DRVSTAT_INFO(be_ethrx_post_fail)}, |
| 64 | {DRVSTAT_INFO(be_802_3_dropped_frames)}, | 65 | {DRVSTAT_INFO(be_802_3_dropped_frames)}, |
| 65 | {DRVSTAT_INFO(be_802_3_malformed_frames)}, | 66 | {DRVSTAT_INFO(be_802_3_malformed_frames)}, |
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 5d38046402b2..a2ec5df0d733 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h | |||
| @@ -167,8 +167,11 @@ | |||
| 167 | #define FLASH_FCoE_BIOS_START_g3 (13631488) | 167 | #define FLASH_FCoE_BIOS_START_g3 (13631488) |
| 168 | #define FLASH_REDBOOT_START_g3 (262144) | 168 | #define FLASH_REDBOOT_START_g3 (262144) |
| 169 | 169 | ||
| 170 | 170 | /************* Rx Packet Type Encoding **************/ | |
| 171 | 171 | #define BE_UNICAST_PACKET 0 | |
| 172 | #define BE_MULTICAST_PACKET 1 | ||
| 173 | #define BE_BROADCAST_PACKET 2 | ||
| 174 | #define BE_RSVD_PACKET 3 | ||
| 172 | 175 | ||
| 173 | /* | 176 | /* |
| 174 | * BE descriptors: host memory data structures whose formats | 177 | * BE descriptors: host memory data structures whose formats |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 74e146f470c6..6eda7a022256 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
| @@ -247,6 +247,7 @@ void netdev_stats_update(struct be_adapter *adapter) | |||
| 247 | dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts; | 247 | dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts; |
| 248 | dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes; | 248 | dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes; |
| 249 | dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes; | 249 | dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes; |
| 250 | dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt; | ||
| 250 | 251 | ||
| 251 | /* bad pkts received */ | 252 | /* bad pkts received */ |
| 252 | dev_stats->rx_errors = port_stats->rx_crc_errors + | 253 | dev_stats->rx_errors = port_stats->rx_crc_errors + |
| @@ -294,7 +295,6 @@ void netdev_stats_update(struct be_adapter *adapter) | |||
| 294 | /* no space available in linux */ | 295 | /* no space available in linux */ |
| 295 | dev_stats->tx_dropped = 0; | 296 | dev_stats->tx_dropped = 0; |
| 296 | 297 | ||
| 297 | dev_stats->multicast = port_stats->rx_multicast_frames; | ||
| 298 | dev_stats->collisions = 0; | 298 | dev_stats->collisions = 0; |
| 299 | 299 | ||
| 300 | /* detailed tx_errors */ | 300 | /* detailed tx_errors */ |
| @@ -848,7 +848,7 @@ static void be_rx_rate_update(struct be_adapter *adapter) | |||
| 848 | } | 848 | } |
| 849 | 849 | ||
| 850 | static void be_rx_stats_update(struct be_adapter *adapter, | 850 | static void be_rx_stats_update(struct be_adapter *adapter, |
| 851 | u32 pktsize, u16 numfrags) | 851 | u32 pktsize, u16 numfrags, u8 pkt_type) |
| 852 | { | 852 | { |
| 853 | struct be_drvr_stats *stats = drvr_stats(adapter); | 853 | struct be_drvr_stats *stats = drvr_stats(adapter); |
| 854 | 854 | ||
| @@ -856,6 +856,9 @@ static void be_rx_stats_update(struct be_adapter *adapter, | |||
| 856 | stats->be_rx_frags += numfrags; | 856 | stats->be_rx_frags += numfrags; |
| 857 | stats->be_rx_bytes += pktsize; | 857 | stats->be_rx_bytes += pktsize; |
| 858 | stats->be_rx_pkts++; | 858 | stats->be_rx_pkts++; |
| 859 | |||
| 860 | if (pkt_type == BE_MULTICAST_PACKET) | ||
| 861 | stats->be_rx_mcast_pkt++; | ||
| 859 | } | 862 | } |
| 860 | 863 | ||
| 861 | static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) | 864 | static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) |
| @@ -925,9 +928,11 @@ static void skb_fill_rx_data(struct be_adapter *adapter, | |||
| 925 | u16 rxq_idx, i, j; | 928 | u16 rxq_idx, i, j; |
| 926 | u32 pktsize, hdr_len, curr_frag_len, size; | 929 | u32 pktsize, hdr_len, curr_frag_len, size; |
| 927 | u8 *start; | 930 | u8 *start; |
| 931 | u8 pkt_type; | ||
| 928 | 932 | ||
| 929 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 933 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
| 930 | pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); | 934 | pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); |
| 935 | pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp); | ||
| 931 | 936 | ||
| 932 | page_info = get_rx_page_info(adapter, rxq_idx); | 937 | page_info = get_rx_page_info(adapter, rxq_idx); |
| 933 | 938 | ||
| @@ -993,7 +998,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, | |||
| 993 | BUG_ON(j > MAX_SKB_FRAGS); | 998 | BUG_ON(j > MAX_SKB_FRAGS); |
| 994 | 999 | ||
| 995 | done: | 1000 | done: |
| 996 | be_rx_stats_update(adapter, pktsize, num_rcvd); | 1001 | be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type); |
| 997 | } | 1002 | } |
| 998 | 1003 | ||
| 999 | /* Process the RX completion indicated by rxcp when GRO is disabled */ | 1004 | /* Process the RX completion indicated by rxcp when GRO is disabled */ |
| @@ -1060,6 +1065,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
| 1060 | u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; | 1065 | u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; |
| 1061 | u16 i, rxq_idx = 0, vid, j; | 1066 | u16 i, rxq_idx = 0, vid, j; |
| 1062 | u8 vtm; | 1067 | u8 vtm; |
| 1068 | u8 pkt_type; | ||
| 1063 | 1069 | ||
| 1064 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); | 1070 | num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); |
| 1065 | /* Is it a flush compl that has no data */ | 1071 | /* Is it a flush compl that has no data */ |
| @@ -1070,6 +1076,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
| 1070 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); | 1076 | vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); |
| 1071 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); | 1077 | rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); |
| 1072 | vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); | 1078 | vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); |
| 1079 | pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp); | ||
| 1073 | 1080 | ||
| 1074 | /* vlanf could be wrongly set in some cards. | 1081 | /* vlanf could be wrongly set in some cards. |
| 1075 | * ignore if vtm is not set */ | 1082 | * ignore if vtm is not set */ |
| @@ -1125,7 +1132,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, | |||
| 1125 | vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); | 1132 | vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); |
| 1126 | } | 1133 | } |
| 1127 | 1134 | ||
| 1128 | be_rx_stats_update(adapter, pkt_size, num_rcvd); | 1135 | be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type); |
| 1129 | } | 1136 | } |
| 1130 | 1137 | ||
| 1131 | static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) | 1138 | static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) |
| @@ -1743,26 +1750,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) | |||
| 1743 | return 1; | 1750 | return 1; |
| 1744 | } | 1751 | } |
| 1745 | 1752 | ||
| 1746 | static inline bool be_detect_ue(struct be_adapter *adapter) | 1753 | void be_detect_dump_ue(struct be_adapter *adapter) |
| 1747 | { | ||
| 1748 | u32 online0 = 0, online1 = 0; | ||
| 1749 | |||
| 1750 | pci_read_config_dword(adapter->pdev, PCICFG_ONLINE0, &online0); | ||
| 1751 | |||
| 1752 | pci_read_config_dword(adapter->pdev, PCICFG_ONLINE1, &online1); | ||
| 1753 | |||
| 1754 | if (!online0 || !online1) { | ||
| 1755 | adapter->ue_detected = true; | ||
| 1756 | dev_err(&adapter->pdev->dev, | ||
| 1757 | "UE Detected!! online0=%d online1=%d\n", | ||
| 1758 | online0, online1); | ||
| 1759 | return true; | ||
| 1760 | } | ||
| 1761 | |||
| 1762 | return false; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | void be_dump_ue(struct be_adapter *adapter) | ||
| 1766 | { | 1754 | { |
| 1767 | u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask; | 1755 | u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask; |
| 1768 | u32 i; | 1756 | u32 i; |
| @@ -1779,6 +1767,11 @@ void be_dump_ue(struct be_adapter *adapter) | |||
| 1779 | ue_status_lo = (ue_status_lo & (~ue_status_lo_mask)); | 1767 | ue_status_lo = (ue_status_lo & (~ue_status_lo_mask)); |
| 1780 | ue_status_hi = (ue_status_hi & (~ue_status_hi_mask)); | 1768 | ue_status_hi = (ue_status_hi & (~ue_status_hi_mask)); |
| 1781 | 1769 | ||
| 1770 | if (ue_status_lo || ue_status_hi) { | ||
| 1771 | adapter->ue_detected = true; | ||
| 1772 | dev_err(&adapter->pdev->dev, "UE Detected!!\n"); | ||
| 1773 | } | ||
| 1774 | |||
| 1782 | if (ue_status_lo) { | 1775 | if (ue_status_lo) { |
| 1783 | for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) { | 1776 | for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) { |
| 1784 | if (ue_status_lo & 1) | 1777 | if (ue_status_lo & 1) |
| @@ -1814,10 +1807,8 @@ static void be_worker(struct work_struct *work) | |||
| 1814 | adapter->rx_post_starved = false; | 1807 | adapter->rx_post_starved = false; |
| 1815 | be_post_rx_frags(adapter); | 1808 | be_post_rx_frags(adapter); |
| 1816 | } | 1809 | } |
| 1817 | if (!adapter->ue_detected) { | 1810 | if (!adapter->ue_detected) |
| 1818 | if (be_detect_ue(adapter)) | 1811 | be_detect_dump_ue(adapter); |
| 1819 | be_dump_ue(adapter); | ||
| 1820 | } | ||
| 1821 | 1812 | ||
| 1822 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); | 1813 | schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); |
| 1823 | } | 1814 | } |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2cc4cfc31892..3b16f62d5606 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -2797,9 +2797,15 @@ void bond_loadbalance_arp_mon(struct work_struct *work) | |||
| 2797 | * so it can wait | 2797 | * so it can wait |
| 2798 | */ | 2798 | */ |
| 2799 | bond_for_each_slave(bond, slave, i) { | 2799 | bond_for_each_slave(bond, slave, i) { |
| 2800 | unsigned long trans_start = dev_trans_start(slave->dev); | ||
| 2801 | |||
| 2800 | if (slave->link != BOND_LINK_UP) { | 2802 | if (slave->link != BOND_LINK_UP) { |
| 2801 | if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) && | 2803 | if (time_in_range(jiffies, |
| 2802 | time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) { | 2804 | trans_start - delta_in_ticks, |
| 2805 | trans_start + delta_in_ticks) && | ||
| 2806 | time_in_range(jiffies, | ||
| 2807 | slave->dev->last_rx - delta_in_ticks, | ||
| 2808 | slave->dev->last_rx + delta_in_ticks)) { | ||
| 2803 | 2809 | ||
| 2804 | slave->link = BOND_LINK_UP; | 2810 | slave->link = BOND_LINK_UP; |
| 2805 | slave->state = BOND_STATE_ACTIVE; | 2811 | slave->state = BOND_STATE_ACTIVE; |
| @@ -2827,8 +2833,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work) | |||
| 2827 | * when the source ip is 0, so don't take the link down | 2833 | * when the source ip is 0, so don't take the link down |
| 2828 | * if we don't know our ip yet | 2834 | * if we don't know our ip yet |
| 2829 | */ | 2835 | */ |
| 2830 | if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) || | 2836 | if (!time_in_range(jiffies, |
| 2831 | (time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) { | 2837 | trans_start - delta_in_ticks, |
| 2838 | trans_start + 2 * delta_in_ticks) || | ||
| 2839 | !time_in_range(jiffies, | ||
| 2840 | slave->dev->last_rx - delta_in_ticks, | ||
| 2841 | slave->dev->last_rx + 2 * delta_in_ticks)) { | ||
| 2832 | 2842 | ||
| 2833 | slave->link = BOND_LINK_DOWN; | 2843 | slave->link = BOND_LINK_DOWN; |
| 2834 | slave->state = BOND_STATE_BACKUP; | 2844 | slave->state = BOND_STATE_BACKUP; |
| @@ -2883,13 +2893,16 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) | |||
| 2883 | { | 2893 | { |
| 2884 | struct slave *slave; | 2894 | struct slave *slave; |
| 2885 | int i, commit = 0; | 2895 | int i, commit = 0; |
| 2896 | unsigned long trans_start; | ||
| 2886 | 2897 | ||
| 2887 | bond_for_each_slave(bond, slave, i) { | 2898 | bond_for_each_slave(bond, slave, i) { |
| 2888 | slave->new_link = BOND_LINK_NOCHANGE; | 2899 | slave->new_link = BOND_LINK_NOCHANGE; |
| 2889 | 2900 | ||
| 2890 | if (slave->link != BOND_LINK_UP) { | 2901 | if (slave->link != BOND_LINK_UP) { |
| 2891 | if (time_before_eq(jiffies, slave_last_rx(bond, slave) + | 2902 | if (time_in_range(jiffies, |
| 2892 | delta_in_ticks)) { | 2903 | slave_last_rx(bond, slave) - delta_in_ticks, |
| 2904 | slave_last_rx(bond, slave) + delta_in_ticks)) { | ||
| 2905 | |||
| 2893 | slave->new_link = BOND_LINK_UP; | 2906 | slave->new_link = BOND_LINK_UP; |
| 2894 | commit++; | 2907 | commit++; |
| 2895 | } | 2908 | } |
| @@ -2902,8 +2915,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) | |||
| 2902 | * active. This avoids bouncing, as the last receive | 2915 | * active. This avoids bouncing, as the last receive |
| 2903 | * times need a full ARP monitor cycle to be updated. | 2916 | * times need a full ARP monitor cycle to be updated. |
| 2904 | */ | 2917 | */ |
| 2905 | if (!time_after_eq(jiffies, slave->jiffies + | 2918 | if (time_in_range(jiffies, |
| 2906 | 2 * delta_in_ticks)) | 2919 | slave->jiffies - delta_in_ticks, |
| 2920 | slave->jiffies + 2 * delta_in_ticks)) | ||
| 2907 | continue; | 2921 | continue; |
| 2908 | 2922 | ||
| 2909 | /* | 2923 | /* |
| @@ -2921,8 +2935,10 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) | |||
| 2921 | */ | 2935 | */ |
| 2922 | if (slave->state == BOND_STATE_BACKUP && | 2936 | if (slave->state == BOND_STATE_BACKUP && |
| 2923 | !bond->current_arp_slave && | 2937 | !bond->current_arp_slave && |
| 2924 | time_after(jiffies, slave_last_rx(bond, slave) + | 2938 | !time_in_range(jiffies, |
| 2925 | 3 * delta_in_ticks)) { | 2939 | slave_last_rx(bond, slave) - delta_in_ticks, |
| 2940 | slave_last_rx(bond, slave) + 3 * delta_in_ticks)) { | ||
| 2941 | |||
| 2926 | slave->new_link = BOND_LINK_DOWN; | 2942 | slave->new_link = BOND_LINK_DOWN; |
| 2927 | commit++; | 2943 | commit++; |
| 2928 | } | 2944 | } |
| @@ -2933,11 +2949,15 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) | |||
| 2933 | * - (more than 2*delta since receive AND | 2949 | * - (more than 2*delta since receive AND |
| 2934 | * the bond has an IP address) | 2950 | * the bond has an IP address) |
| 2935 | */ | 2951 | */ |
| 2952 | trans_start = dev_trans_start(slave->dev); | ||
| 2936 | if ((slave->state == BOND_STATE_ACTIVE) && | 2953 | if ((slave->state == BOND_STATE_ACTIVE) && |
| 2937 | (time_after_eq(jiffies, dev_trans_start(slave->dev) + | 2954 | (!time_in_range(jiffies, |
| 2938 | 2 * delta_in_ticks) || | 2955 | trans_start - delta_in_ticks, |
| 2939 | (time_after_eq(jiffies, slave_last_rx(bond, slave) | 2956 | trans_start + 2 * delta_in_ticks) || |
| 2940 | + 2 * delta_in_ticks)))) { | 2957 | !time_in_range(jiffies, |
| 2958 | slave_last_rx(bond, slave) - delta_in_ticks, | ||
| 2959 | slave_last_rx(bond, slave) + 2 * delta_in_ticks))) { | ||
| 2960 | |||
| 2941 | slave->new_link = BOND_LINK_DOWN; | 2961 | slave->new_link = BOND_LINK_DOWN; |
| 2942 | commit++; | 2962 | commit++; |
| 2943 | } | 2963 | } |
| @@ -2956,6 +2976,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) | |||
| 2956 | { | 2976 | { |
| 2957 | struct slave *slave; | 2977 | struct slave *slave; |
| 2958 | int i; | 2978 | int i; |
| 2979 | unsigned long trans_start; | ||
| 2959 | 2980 | ||
| 2960 | bond_for_each_slave(bond, slave, i) { | 2981 | bond_for_each_slave(bond, slave, i) { |
| 2961 | switch (slave->new_link) { | 2982 | switch (slave->new_link) { |
| @@ -2963,10 +2984,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) | |||
| 2963 | continue; | 2984 | continue; |
| 2964 | 2985 | ||
| 2965 | case BOND_LINK_UP: | 2986 | case BOND_LINK_UP: |
| 2987 | trans_start = dev_trans_start(slave->dev); | ||
| 2966 | if ((!bond->curr_active_slave && | 2988 | if ((!bond->curr_active_slave && |
| 2967 | time_before_eq(jiffies, | 2989 | time_in_range(jiffies, |
| 2968 | dev_trans_start(slave->dev) + | 2990 | trans_start - delta_in_ticks, |
| 2969 | delta_in_ticks)) || | 2991 | trans_start + delta_in_ticks)) || |
| 2970 | bond->curr_active_slave != slave) { | 2992 | bond->curr_active_slave != slave) { |
| 2971 | slave->link = BOND_LINK_UP; | 2993 | slave->link = BOND_LINK_UP; |
| 2972 | bond->current_arp_slave = NULL; | 2994 | bond->current_arp_slave = NULL; |
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index b4fb07a6f13f..51919fcd50c2 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c | |||
| @@ -503,30 +503,33 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) | |||
| 503 | ks8851_wrreg16(ks, KS_RXQCR, | 503 | ks8851_wrreg16(ks, KS_RXQCR, |
| 504 | ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); | 504 | ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); |
| 505 | 505 | ||
| 506 | if (rxlen > 0) { | 506 | if (rxlen > 4) { |
| 507 | skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8); | 507 | unsigned int rxalign; |
| 508 | if (!skb) { | 508 | |
| 509 | /* todo - dump frame and move on */ | 509 | rxlen -= 4; |
| 510 | } | 510 | rxalign = ALIGN(rxlen, 4); |
| 511 | skb = netdev_alloc_skb_ip_align(ks->netdev, rxalign); | ||
| 512 | if (skb) { | ||
| 511 | 513 | ||
| 512 | /* two bytes to ensure ip is aligned, and four bytes | 514 | /* 4 bytes of status header + 4 bytes of |
| 513 | * for the status header and 4 bytes of garbage */ | 515 | * garbage: we put them before ethernet |
| 514 | skb_reserve(skb, 2 + 4 + 4); | 516 | * header, so that they are copied, |
| 517 | * but ignored. | ||
| 518 | */ | ||
| 515 | 519 | ||
| 516 | rxpkt = skb_put(skb, rxlen - 4) - 8; | 520 | rxpkt = skb_put(skb, rxlen) - 8; |
| 517 | 521 | ||
| 518 | /* align the packet length to 4 bytes, and add 4 bytes | 522 | ks8851_rdfifo(ks, rxpkt, rxalign + 8); |
| 519 | * as we're getting the rx status header as well */ | ||
| 520 | ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8); | ||
| 521 | 523 | ||
| 522 | if (netif_msg_pktdata(ks)) | 524 | if (netif_msg_pktdata(ks)) |
| 523 | ks8851_dbg_dumpkkt(ks, rxpkt); | 525 | ks8851_dbg_dumpkkt(ks, rxpkt); |
| 524 | 526 | ||
| 525 | skb->protocol = eth_type_trans(skb, ks->netdev); | 527 | skb->protocol = eth_type_trans(skb, ks->netdev); |
| 526 | netif_rx(skb); | 528 | netif_rx(skb); |
| 527 | 529 | ||
| 528 | ks->netdev->stats.rx_packets++; | 530 | ks->netdev->stats.rx_packets++; |
| 529 | ks->netdev->stats.rx_bytes += rxlen - 4; | 531 | ks->netdev->stats.rx_bytes += rxlen; |
| 532 | } | ||
| 530 | } | 533 | } |
| 531 | 534 | ||
| 532 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); | 535 | ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); |
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index bdf2149e5296..87f0a93b165c 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/of_device.h> | 38 | #include <linux/of_device.h> |
| 39 | #include <linux/of_mdio.h> | 39 | #include <linux/of_mdio.h> |
| 40 | #include <linux/of_platform.h> | 40 | #include <linux/of_platform.h> |
| 41 | #include <linux/of_address.h> | ||
| 41 | #include <linux/skbuff.h> | 42 | #include <linux/skbuff.h> |
| 42 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
| 43 | #include <linux/tcp.h> /* needed for sizeof(tcphdr) */ | 44 | #include <linux/tcp.h> /* needed for sizeof(tcphdr) */ |
diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ll_temac_mdio.c index 5ae28c975b38..8cf9d4f56bb2 100644 --- a/drivers/net/ll_temac_mdio.c +++ b/drivers/net/ll_temac_mdio.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/phy.h> | 10 | #include <linux/phy.h> |
| 11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
| 12 | #include <linux/of_device.h> | 12 | #include <linux/of_device.h> |
| 13 | #include <linux/of_address.h> | ||
| 13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 14 | #include <linux/of_mdio.h> | 15 | #include <linux/of_mdio.h> |
| 15 | 16 | ||
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index bc695d53cdcc..fe6983af6918 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
| @@ -7269,32 +7269,28 @@ static int niu_get_ethtool_tcam_all(struct niu *np, | |||
| 7269 | struct niu_parent *parent = np->parent; | 7269 | struct niu_parent *parent = np->parent; |
| 7270 | struct niu_tcam_entry *tp; | 7270 | struct niu_tcam_entry *tp; |
| 7271 | int i, idx, cnt; | 7271 | int i, idx, cnt; |
| 7272 | u16 n_entries; | ||
| 7273 | unsigned long flags; | 7272 | unsigned long flags; |
| 7274 | 7273 | int ret = 0; | |
| 7275 | 7274 | ||
| 7276 | /* put the tcam size here */ | 7275 | /* put the tcam size here */ |
| 7277 | nfc->data = tcam_get_size(np); | 7276 | nfc->data = tcam_get_size(np); |
| 7278 | 7277 | ||
| 7279 | niu_lock_parent(np, flags); | 7278 | niu_lock_parent(np, flags); |
| 7280 | n_entries = nfc->rule_cnt; | ||
| 7281 | for (cnt = 0, i = 0; i < nfc->data; i++) { | 7279 | for (cnt = 0, i = 0; i < nfc->data; i++) { |
| 7282 | idx = tcam_get_index(np, i); | 7280 | idx = tcam_get_index(np, i); |
| 7283 | tp = &parent->tcam[idx]; | 7281 | tp = &parent->tcam[idx]; |
| 7284 | if (!tp->valid) | 7282 | if (!tp->valid) |
| 7285 | continue; | 7283 | continue; |
| 7284 | if (cnt == nfc->rule_cnt) { | ||
| 7285 | ret = -EMSGSIZE; | ||
| 7286 | break; | ||
| 7287 | } | ||
| 7286 | rule_locs[cnt] = i; | 7288 | rule_locs[cnt] = i; |
| 7287 | cnt++; | 7289 | cnt++; |
| 7288 | } | 7290 | } |
| 7289 | niu_unlock_parent(np, flags); | 7291 | niu_unlock_parent(np, flags); |
| 7290 | 7292 | ||
| 7291 | if (n_entries != cnt) { | 7293 | return ret; |
| 7292 | /* print warning, this should not happen */ | ||
| 7293 | netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n", | ||
| 7294 | np->parent->index, __func__, n_entries, cnt); | ||
| 7295 | } | ||
| 7296 | |||
| 7297 | return 0; | ||
| 7298 | } | 7294 | } |
| 7299 | 7295 | ||
| 7300 | static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | 7296 | static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 49279b0ee526..f9b509a6b09a 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
| @@ -508,7 +508,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, | |||
| 508 | unsigned int vcc, | 508 | unsigned int vcc, |
| 509 | void *priv_data) | 509 | void *priv_data) |
| 510 | { | 510 | { |
| 511 | int *has_shmem = priv_data; | 511 | int *priv = priv_data; |
| 512 | int try = (*priv & 0x1); | ||
| 512 | int i; | 513 | int i; |
| 513 | cistpl_io_t *io = &cfg->io; | 514 | cistpl_io_t *io = &cfg->io; |
| 514 | 515 | ||
| @@ -525,77 +526,103 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, | |||
| 525 | i = p_dev->resource[1]->end = 0; | 526 | i = p_dev->resource[1]->end = 0; |
| 526 | } | 527 | } |
| 527 | 528 | ||
| 528 | *has_shmem = ((cfg->mem.nwin == 1) && | 529 | *priv &= ((cfg->mem.nwin == 1) && |
| 529 | (cfg->mem.win[0].len >= 0x4000)); | 530 | (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10; |
| 531 | |||
| 530 | p_dev->resource[0]->start = io->win[i].base; | 532 | p_dev->resource[0]->start = io->win[i].base; |
| 531 | p_dev->resource[0]->end = io->win[i].len; | 533 | p_dev->resource[0]->end = io->win[i].len; |
| 532 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | 534 | if (!try) |
| 535 | p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; | ||
| 536 | else | ||
| 537 | p_dev->io_lines = 16; | ||
| 533 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) | 538 | if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) |
| 534 | return try_io_port(p_dev); | 539 | return try_io_port(p_dev); |
| 535 | 540 | ||
| 536 | return 0; | 541 | return -EINVAL; |
| 542 | } | ||
| 543 | |||
| 544 | static hw_info_t *pcnet_try_config(struct pcmcia_device *link, | ||
| 545 | int *has_shmem, int try) | ||
| 546 | { | ||
| 547 | struct net_device *dev = link->priv; | ||
| 548 | hw_info_t *local_hw_info; | ||
| 549 | pcnet_dev_t *info = PRIV(dev); | ||
| 550 | int priv = try; | ||
| 551 | int ret; | ||
| 552 | |||
| 553 | ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); | ||
| 554 | if (ret) { | ||
| 555 | dev_warn(&link->dev, "no useable port range found\n"); | ||
| 556 | return NULL; | ||
| 557 | } | ||
| 558 | *has_shmem = (priv & 0x10); | ||
| 559 | |||
| 560 | if (!link->irq) | ||
| 561 | return NULL; | ||
| 562 | |||
| 563 | if (resource_size(link->resource[1]) == 8) { | ||
| 564 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
| 565 | link->conf.Status = CCSR_AUDIO_ENA; | ||
| 566 | } | ||
| 567 | if ((link->manf_id == MANFID_IBM) && | ||
| 568 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) | ||
| 569 | link->conf.ConfigIndex |= 0x10; | ||
| 570 | |||
| 571 | ret = pcmcia_request_configuration(link, &link->conf); | ||
| 572 | if (ret) | ||
| 573 | return NULL; | ||
| 574 | |||
| 575 | dev->irq = link->irq; | ||
| 576 | dev->base_addr = link->resource[0]->start; | ||
| 577 | |||
| 578 | if (info->flags & HAS_MISC_REG) { | ||
| 579 | if ((if_port == 1) || (if_port == 2)) | ||
| 580 | dev->if_port = if_port; | ||
| 581 | else | ||
| 582 | dev_notice(&link->dev, "invalid if_port requested\n"); | ||
| 583 | } else | ||
| 584 | dev->if_port = 0; | ||
| 585 | |||
| 586 | if ((link->conf.ConfigBase == 0x03c0) && | ||
| 587 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { | ||
| 588 | dev_info(&link->dev, | ||
| 589 | "this is an AX88190 card - use axnet_cs instead.\n"); | ||
| 590 | return NULL; | ||
| 591 | } | ||
| 592 | |||
| 593 | local_hw_info = get_hwinfo(link); | ||
| 594 | if (!local_hw_info) | ||
| 595 | local_hw_info = get_prom(link); | ||
| 596 | if (!local_hw_info) | ||
| 597 | local_hw_info = get_dl10019(link); | ||
| 598 | if (!local_hw_info) | ||
| 599 | local_hw_info = get_ax88190(link); | ||
| 600 | if (!local_hw_info) | ||
| 601 | local_hw_info = get_hwired(link); | ||
| 602 | |||
| 603 | return local_hw_info; | ||
| 537 | } | 604 | } |
| 538 | 605 | ||
| 539 | static int pcnet_config(struct pcmcia_device *link) | 606 | static int pcnet_config(struct pcmcia_device *link) |
| 540 | { | 607 | { |
| 541 | struct net_device *dev = link->priv; | 608 | struct net_device *dev = link->priv; |
| 542 | pcnet_dev_t *info = PRIV(dev); | 609 | pcnet_dev_t *info = PRIV(dev); |
| 543 | int ret, start_pg, stop_pg, cm_offset; | 610 | int start_pg, stop_pg, cm_offset; |
| 544 | int has_shmem = 0; | 611 | int has_shmem = 0; |
| 545 | hw_info_t *local_hw_info; | 612 | hw_info_t *local_hw_info; |
| 546 | 613 | ||
| 547 | dev_dbg(&link->dev, "pcnet_config\n"); | 614 | dev_dbg(&link->dev, "pcnet_config\n"); |
| 548 | 615 | ||
| 549 | ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); | 616 | local_hw_info = pcnet_try_config(link, &has_shmem, 0); |
| 550 | if (ret) | 617 | if (!local_hw_info) { |
| 551 | goto failed; | 618 | /* check whether forcing io_lines to 16 helps... */ |
| 552 | 619 | pcmcia_disable_device(link); | |
| 553 | if (!link->irq) | 620 | local_hw_info = pcnet_try_config(link, &has_shmem, 1); |
| 554 | goto failed; | 621 | if (local_hw_info == NULL) { |
| 555 | 622 | dev_notice(&link->dev, "unable to read hardware net" | |
| 556 | if (resource_size(link->resource[1]) == 8) { | 623 | " address for io base %#3lx\n", dev->base_addr); |
| 557 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 624 | goto failed; |
| 558 | link->conf.Status = CCSR_AUDIO_ENA; | 625 | } |
| 559 | } | ||
| 560 | if ((link->manf_id == MANFID_IBM) && | ||
| 561 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) | ||
| 562 | link->conf.ConfigIndex |= 0x10; | ||
| 563 | |||
| 564 | ret = pcmcia_request_configuration(link, &link->conf); | ||
| 565 | if (ret) | ||
| 566 | goto failed; | ||
| 567 | dev->irq = link->irq; | ||
| 568 | dev->base_addr = link->resource[0]->start; | ||
| 569 | if (info->flags & HAS_MISC_REG) { | ||
| 570 | if ((if_port == 1) || (if_port == 2)) | ||
| 571 | dev->if_port = if_port; | ||
| 572 | else | ||
| 573 | printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); | ||
| 574 | } else { | ||
| 575 | dev->if_port = 0; | ||
| 576 | } | ||
| 577 | |||
| 578 | if ((link->conf.ConfigBase == 0x03c0) && | ||
| 579 | (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { | ||
| 580 | printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); | ||
| 581 | printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); | ||
| 582 | goto failed; | ||
| 583 | } | ||
| 584 | |||
| 585 | local_hw_info = get_hwinfo(link); | ||
| 586 | if (local_hw_info == NULL) | ||
| 587 | local_hw_info = get_prom(link); | ||
| 588 | if (local_hw_info == NULL) | ||
| 589 | local_hw_info = get_dl10019(link); | ||
| 590 | if (local_hw_info == NULL) | ||
| 591 | local_hw_info = get_ax88190(link); | ||
| 592 | if (local_hw_info == NULL) | ||
| 593 | local_hw_info = get_hwired(link); | ||
| 594 | |||
| 595 | if (local_hw_info == NULL) { | ||
| 596 | printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" | ||
| 597 | " address for io base %#3lx\n", dev->base_addr); | ||
| 598 | goto failed; | ||
| 599 | } | 626 | } |
| 600 | 627 | ||
| 601 | info->flags = local_hw_info->flags; | 628 | info->flags = local_hw_info->flags; |
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index bbb7951b9c4c..ea0461eb2dbe 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c | |||
| @@ -1865,15 +1865,15 @@ static int stmmac_resume(struct platform_device *pdev) | |||
| 1865 | if (!netif_running(dev)) | 1865 | if (!netif_running(dev)) |
| 1866 | return 0; | 1866 | return 0; |
| 1867 | 1867 | ||
| 1868 | spin_lock(&priv->lock); | ||
| 1869 | |||
| 1870 | if (priv->shutdown) { | 1868 | if (priv->shutdown) { |
| 1871 | /* Re-open the interface and re-init the MAC/DMA | 1869 | /* Re-open the interface and re-init the MAC/DMA |
| 1872 | and the rings. */ | 1870 | and the rings (i.e. on hibernation stage) */ |
| 1873 | stmmac_open(dev); | 1871 | stmmac_open(dev); |
| 1874 | goto out_resume; | 1872 | return 0; |
| 1875 | } | 1873 | } |
| 1876 | 1874 | ||
| 1875 | spin_lock(&priv->lock); | ||
| 1876 | |||
| 1877 | /* Power Down bit, into the PM register, is cleared | 1877 | /* Power Down bit, into the PM register, is cleared |
| 1878 | * automatically as soon as a magic packet or a Wake-up frame | 1878 | * automatically as soon as a magic packet or a Wake-up frame |
| 1879 | * is received. Anyway, it's better to manually clear | 1879 | * is received. Anyway, it's better to manually clear |
| @@ -1901,7 +1901,6 @@ static int stmmac_resume(struct platform_device *pdev) | |||
| 1901 | 1901 | ||
| 1902 | netif_start_queue(dev); | 1902 | netif_start_queue(dev); |
| 1903 | 1903 | ||
| 1904 | out_resume: | ||
| 1905 | spin_unlock(&priv->lock); | 1904 | spin_unlock(&priv->lock); |
| 1906 | return 0; | 1905 | return 0; |
| 1907 | } | 1906 | } |
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 8ed30fa35d0a..b2bcf99e6f08 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c | |||
| @@ -429,10 +429,6 @@ static const struct net_device_ops ipheth_netdev_ops = { | |||
| 429 | .ndo_get_stats = &ipheth_stats, | 429 | .ndo_get_stats = &ipheth_stats, |
| 430 | }; | 430 | }; |
| 431 | 431 | ||
| 432 | static struct device_type ipheth_type = { | ||
| 433 | .name = "wwan", | ||
| 434 | }; | ||
| 435 | |||
| 436 | static int ipheth_probe(struct usb_interface *intf, | 432 | static int ipheth_probe(struct usb_interface *intf, |
| 437 | const struct usb_device_id *id) | 433 | const struct usb_device_id *id) |
| 438 | { | 434 | { |
| @@ -450,7 +446,7 @@ static int ipheth_probe(struct usb_interface *intf, | |||
| 450 | 446 | ||
| 451 | netdev->netdev_ops = &ipheth_netdev_ops; | 447 | netdev->netdev_ops = &ipheth_netdev_ops; |
| 452 | netdev->watchdog_timeo = IPHETH_TX_TIMEOUT; | 448 | netdev->watchdog_timeo = IPHETH_TX_TIMEOUT; |
| 453 | strcpy(netdev->name, "wwan%d"); | 449 | strcpy(netdev->name, "eth%d"); |
| 454 | 450 | ||
| 455 | dev = netdev_priv(netdev); | 451 | dev = netdev_priv(netdev); |
| 456 | dev->udev = udev; | 452 | dev->udev = udev; |
| @@ -500,7 +496,6 @@ static int ipheth_probe(struct usb_interface *intf, | |||
| 500 | 496 | ||
| 501 | SET_NETDEV_DEV(netdev, &intf->dev); | 497 | SET_NETDEV_DEV(netdev, &intf->dev); |
| 502 | SET_ETHTOOL_OPS(netdev, &ops); | 498 | SET_ETHTOOL_OPS(netdev, &ops); |
| 503 | SET_NETDEV_DEVTYPE(netdev, &ipheth_type); | ||
| 504 | 499 | ||
| 505 | retval = register_netdev(netdev); | 500 | retval = register_netdev(netdev); |
| 506 | if (retval) { | 501 | if (retval) { |
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index fd69095ef6e3..f53412368ce1 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
| @@ -2824,7 +2824,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi | |||
| 2824 | netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT); | 2824 | netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT); |
| 2825 | 2825 | ||
| 2826 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | | 2826 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | |
| 2827 | NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM | NETIF_F_SG; | 2827 | NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM; |
| 2828 | 2828 | ||
| 2829 | ret = register_netdev(dev); | 2829 | ret = register_netdev(dev); |
| 2830 | if (ret < 0) | 2830 | if (ret < 0) |
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 54aa1c238cb3..a5c176598d95 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
| @@ -163,7 +163,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev, | |||
| 163 | c = p_dev->function_config; | 163 | c = p_dev->function_config; |
| 164 | 164 | ||
| 165 | if (!(c->state & CONFIG_LOCKED)) { | 165 | if (!(c->state & CONFIG_LOCKED)) { |
| 166 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 166 | dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); |
| 167 | mutex_unlock(&s->ops_mutex); | 167 | mutex_unlock(&s->ops_mutex); |
| 168 | return -EACCES; | 168 | return -EACCES; |
| 169 | } | 169 | } |
| @@ -220,7 +220,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | |||
| 220 | s->win[w].card_start = offset; | 220 | s->win[w].card_start = offset; |
| 221 | ret = s->ops->set_mem_map(s, &s->win[w]); | 221 | ret = s->ops->set_mem_map(s, &s->win[w]); |
| 222 | if (ret) | 222 | if (ret) |
| 223 | dev_warn(&s->dev, "failed to set_mem_map\n"); | 223 | dev_warn(&p_dev->dev, "failed to set_mem_map\n"); |
| 224 | mutex_unlock(&s->ops_mutex); | 224 | mutex_unlock(&s->ops_mutex); |
| 225 | return ret; | 225 | return ret; |
| 226 | } /* pcmcia_map_mem_page */ | 226 | } /* pcmcia_map_mem_page */ |
| @@ -244,18 +244,18 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 244 | c = p_dev->function_config; | 244 | c = p_dev->function_config; |
| 245 | 245 | ||
| 246 | if (!(s->state & SOCKET_PRESENT)) { | 246 | if (!(s->state & SOCKET_PRESENT)) { |
| 247 | dev_dbg(&s->dev, "No card present\n"); | 247 | dev_dbg(&p_dev->dev, "No card present\n"); |
| 248 | ret = -ENODEV; | 248 | ret = -ENODEV; |
| 249 | goto unlock; | 249 | goto unlock; |
| 250 | } | 250 | } |
| 251 | if (!(c->state & CONFIG_LOCKED)) { | 251 | if (!(c->state & CONFIG_LOCKED)) { |
| 252 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 252 | dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); |
| 253 | ret = -EACCES; | 253 | ret = -EACCES; |
| 254 | goto unlock; | 254 | goto unlock; |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { | 257 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { |
| 258 | dev_dbg(&s->dev, | 258 | dev_dbg(&p_dev->dev, |
| 259 | "changing Vcc or IRQ is not allowed at this time\n"); | 259 | "changing Vcc or IRQ is not allowed at this time\n"); |
| 260 | ret = -EINVAL; | 260 | ret = -EINVAL; |
| 261 | goto unlock; | 261 | goto unlock; |
| @@ -265,20 +265,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 265 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | 265 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && |
| 266 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 266 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
| 267 | if (mod->Vpp1 != mod->Vpp2) { | 267 | if (mod->Vpp1 != mod->Vpp2) { |
| 268 | dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); | 268 | dev_dbg(&p_dev->dev, |
| 269 | "Vpp1 and Vpp2 must be the same\n"); | ||
| 269 | ret = -EINVAL; | 270 | ret = -EINVAL; |
| 270 | goto unlock; | 271 | goto unlock; |
| 271 | } | 272 | } |
| 272 | s->socket.Vpp = mod->Vpp1; | 273 | s->socket.Vpp = mod->Vpp1; |
| 273 | if (s->ops->set_socket(s, &s->socket)) { | 274 | if (s->ops->set_socket(s, &s->socket)) { |
| 274 | dev_printk(KERN_WARNING, &s->dev, | 275 | dev_printk(KERN_WARNING, &p_dev->dev, |
| 275 | "Unable to set VPP\n"); | 276 | "Unable to set VPP\n"); |
| 276 | ret = -EIO; | 277 | ret = -EIO; |
| 277 | goto unlock; | 278 | goto unlock; |
| 278 | } | 279 | } |
| 279 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | 280 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || |
| 280 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 281 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
| 281 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); | 282 | dev_dbg(&p_dev->dev, |
| 283 | "changing Vcc is not allowed at this time\n"); | ||
| 282 | ret = -EINVAL; | 284 | ret = -EINVAL; |
| 283 | goto unlock; | 285 | goto unlock; |
| 284 | } | 286 | } |
| @@ -401,7 +403,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
| 401 | win = &s->win[w]; | 403 | win = &s->win[w]; |
| 402 | 404 | ||
| 403 | if (!(p_dev->_win & CLIENT_WIN_REQ(w))) { | 405 | if (!(p_dev->_win & CLIENT_WIN_REQ(w))) { |
| 404 | dev_dbg(&s->dev, "not releasing unknown window\n"); | 406 | dev_dbg(&p_dev->dev, "not releasing unknown window\n"); |
| 405 | mutex_unlock(&s->ops_mutex); | 407 | mutex_unlock(&s->ops_mutex); |
| 406 | return -EINVAL; | 408 | return -EINVAL; |
| 407 | } | 409 | } |
| @@ -439,7 +441,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
| 439 | return -ENODEV; | 441 | return -ENODEV; |
| 440 | 442 | ||
| 441 | if (req->IntType & INT_CARDBUS) { | 443 | if (req->IntType & INT_CARDBUS) { |
| 442 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); | 444 | dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n"); |
| 443 | return -EINVAL; | 445 | return -EINVAL; |
| 444 | } | 446 | } |
| 445 | 447 | ||
| @@ -447,7 +449,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
| 447 | c = p_dev->function_config; | 449 | c = p_dev->function_config; |
| 448 | if (c->state & CONFIG_LOCKED) { | 450 | if (c->state & CONFIG_LOCKED) { |
| 449 | mutex_unlock(&s->ops_mutex); | 451 | mutex_unlock(&s->ops_mutex); |
| 450 | dev_dbg(&s->dev, "Configuration is locked\n"); | 452 | dev_dbg(&p_dev->dev, "Configuration is locked\n"); |
| 451 | return -EACCES; | 453 | return -EACCES; |
| 452 | } | 454 | } |
| 453 | 455 | ||
| @@ -455,7 +457,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
| 455 | s->socket.Vpp = req->Vpp; | 457 | s->socket.Vpp = req->Vpp; |
| 456 | if (s->ops->set_socket(s, &s->socket)) { | 458 | if (s->ops->set_socket(s, &s->socket)) { |
| 457 | mutex_unlock(&s->ops_mutex); | 459 | mutex_unlock(&s->ops_mutex); |
| 458 | dev_printk(KERN_WARNING, &s->dev, | 460 | dev_printk(KERN_WARNING, &p_dev->dev, |
| 459 | "Unable to set socket state\n"); | 461 | "Unable to set socket state\n"); |
| 460 | return -EINVAL; | 462 | return -EINVAL; |
| 461 | } | 463 | } |
| @@ -569,19 +571,20 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) | |||
| 569 | int ret = -EINVAL; | 571 | int ret = -EINVAL; |
| 570 | 572 | ||
| 571 | mutex_lock(&s->ops_mutex); | 573 | mutex_lock(&s->ops_mutex); |
| 572 | dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]); | 574 | dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR", |
| 575 | &c->io[0], &c->io[1]); | ||
| 573 | 576 | ||
| 574 | if (!(s->state & SOCKET_PRESENT)) { | 577 | if (!(s->state & SOCKET_PRESENT)) { |
| 575 | dev_dbg(&s->dev, "pcmcia_request_io: No card present\n"); | 578 | dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n"); |
| 576 | goto out; | 579 | goto out; |
| 577 | } | 580 | } |
| 578 | 581 | ||
| 579 | if (c->state & CONFIG_LOCKED) { | 582 | if (c->state & CONFIG_LOCKED) { |
| 580 | dev_dbg(&s->dev, "Configuration is locked\n"); | 583 | dev_dbg(&p_dev->dev, "Configuration is locked\n"); |
| 581 | goto out; | 584 | goto out; |
| 582 | } | 585 | } |
| 583 | if (c->state & CONFIG_IO_REQ) { | 586 | if (c->state & CONFIG_IO_REQ) { |
| 584 | dev_dbg(&s->dev, "IO already configured\n"); | 587 | dev_dbg(&p_dev->dev, "IO already configured\n"); |
| 585 | goto out; | 588 | goto out; |
| 586 | } | 589 | } |
| 587 | 590 | ||
| @@ -601,7 +604,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) | |||
| 601 | c->state |= CONFIG_IO_REQ; | 604 | c->state |= CONFIG_IO_REQ; |
| 602 | p_dev->_io = 1; | 605 | p_dev->_io = 1; |
| 603 | 606 | ||
| 604 | dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR", | 607 | dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR", |
| 605 | &c->io[0], &c->io[1]); | 608 | &c->io[0], &c->io[1]); |
| 606 | out: | 609 | out: |
| 607 | mutex_unlock(&s->ops_mutex); | 610 | mutex_unlock(&s->ops_mutex); |
| @@ -800,7 +803,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
| 800 | int w; | 803 | int w; |
| 801 | 804 | ||
| 802 | if (!(s->state & SOCKET_PRESENT)) { | 805 | if (!(s->state & SOCKET_PRESENT)) { |
| 803 | dev_dbg(&s->dev, "No card present\n"); | 806 | dev_dbg(&p_dev->dev, "No card present\n"); |
| 804 | return -ENODEV; | 807 | return -ENODEV; |
| 805 | } | 808 | } |
| 806 | 809 | ||
| @@ -809,12 +812,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
| 809 | req->Size = s->map_size; | 812 | req->Size = s->map_size; |
| 810 | align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; | 813 | align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; |
| 811 | if (req->Size & (s->map_size-1)) { | 814 | if (req->Size & (s->map_size-1)) { |
| 812 | dev_dbg(&s->dev, "invalid map size\n"); | 815 | dev_dbg(&p_dev->dev, "invalid map size\n"); |
| 813 | return -EINVAL; | 816 | return -EINVAL; |
| 814 | } | 817 | } |
| 815 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || | 818 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || |
| 816 | (req->Base & (align-1))) { | 819 | (req->Base & (align-1))) { |
| 817 | dev_dbg(&s->dev, "invalid base address\n"); | 820 | dev_dbg(&p_dev->dev, "invalid base address\n"); |
| 818 | return -EINVAL; | 821 | return -EINVAL; |
| 819 | } | 822 | } |
| 820 | if (req->Base) | 823 | if (req->Base) |
| @@ -826,7 +829,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
| 826 | if (!(s->state & SOCKET_WIN_REQ(w))) | 829 | if (!(s->state & SOCKET_WIN_REQ(w))) |
| 827 | break; | 830 | break; |
| 828 | if (w == MAX_WIN) { | 831 | if (w == MAX_WIN) { |
| 829 | dev_dbg(&s->dev, "all windows are used already\n"); | 832 | dev_dbg(&p_dev->dev, "all windows are used already\n"); |
| 830 | mutex_unlock(&s->ops_mutex); | 833 | mutex_unlock(&s->ops_mutex); |
| 831 | return -EINVAL; | 834 | return -EINVAL; |
| 832 | } | 835 | } |
| @@ -837,7 +840,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
| 837 | win->res = pcmcia_find_mem_region(req->Base, req->Size, align, | 840 | win->res = pcmcia_find_mem_region(req->Base, req->Size, align, |
| 838 | 0, s); | 841 | 0, s); |
| 839 | if (!win->res) { | 842 | if (!win->res) { |
| 840 | dev_dbg(&s->dev, "allocating mem region failed\n"); | 843 | dev_dbg(&p_dev->dev, "allocating mem region failed\n"); |
| 841 | mutex_unlock(&s->ops_mutex); | 844 | mutex_unlock(&s->ops_mutex); |
| 842 | return -EINVAL; | 845 | return -EINVAL; |
| 843 | } | 846 | } |
| @@ -851,7 +854,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
| 851 | win->card_start = 0; | 854 | win->card_start = 0; |
| 852 | 855 | ||
| 853 | if (s->ops->set_mem_map(s, win) != 0) { | 856 | if (s->ops->set_mem_map(s, win) != 0) { |
| 854 | dev_dbg(&s->dev, "failed to set memory mapping\n"); | 857 | dev_dbg(&p_dev->dev, "failed to set memory mapping\n"); |
| 855 | mutex_unlock(&s->ops_mutex); | 858 | mutex_unlock(&s->ops_mutex); |
| 856 | return -EIO; | 859 | return -EIO; |
| 857 | } | 860 | } |
| @@ -874,7 +877,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
| 874 | if (win->res) | 877 | if (win->res) |
| 875 | request_resource(&iomem_resource, res); | 878 | request_resource(&iomem_resource, res); |
| 876 | 879 | ||
| 877 | dev_dbg(&s->dev, "request_window results in %pR\n", res); | 880 | dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); |
| 878 | 881 | ||
| 879 | mutex_unlock(&s->ops_mutex); | 882 | mutex_unlock(&s->ops_mutex); |
| 880 | *wh = res; | 883 | *wh = res; |
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 936bae560fa1..dc628cb2e762 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c | |||
| @@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_source source) | |||
| 233 | empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; | 233 | empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; |
| 234 | now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; | 234 | now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; |
| 235 | avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; | 235 | avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; |
| 236 | break; | ||
| 236 | case SOURCE_VOLTAGE: | 237 | case SOURCE_VOLTAGE: |
| 237 | full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; | 238 | full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; |
| 238 | empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; | 239 | empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; |
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index c61ffec2ff10..2a10cd361181 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c | |||
| @@ -185,8 +185,8 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) | |||
| 185 | { | 185 | { |
| 186 | u32 data[3]; | 186 | u32 data[3]; |
| 187 | u8 *p = (u8 *)&data[1]; | 187 | u8 *p = (u8 *)&data[1]; |
| 188 | int err = intel_scu_ipc_command(IPC_CMD_BATTERY_PROPERTY, | 188 | int err = intel_scu_ipc_command(IPCMSG_BATTERY, |
| 189 | IPCMSG_BATTERY, NULL, 0, data, 3); | 189 | IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3); |
| 190 | 190 | ||
| 191 | prop->capacity = data[0]; | 191 | prop->capacity = data[0]; |
| 192 | prop->crnt = *p++; | 192 | prop->crnt = *p++; |
| @@ -207,7 +207,7 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) | |||
| 207 | 207 | ||
| 208 | static int pmic_scu_ipc_set_charger(int charger) | 208 | static int pmic_scu_ipc_set_charger(int charger) |
| 209 | { | 209 | { |
| 210 | return intel_scu_ipc_simple_command(charger, IPCMSG_BATTERY); | 210 | return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | /** | 213 | /** |
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 7d149a8d8d9b..2ce2eb71d0f5 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c | |||
| @@ -215,7 +215,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) | |||
| 215 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | 215 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); |
| 216 | int ret = -EINVAL; | 216 | int ret = -EINVAL; |
| 217 | 217 | ||
| 218 | if (info->vol_table && (index < (2 << info->vol_nbits))) { | 218 | if (info->vol_table && (index < (1 << info->vol_nbits))) { |
| 219 | ret = info->vol_table[index]; | 219 | ret = info->vol_table[index]; |
| 220 | if (info->slope_double) | 220 | if (info->slope_double) |
| 221 | ret <<= 1; | 221 | ret <<= 1; |
| @@ -233,7 +233,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
| 233 | max_uV = max_uV >> 1; | 233 | max_uV = max_uV >> 1; |
| 234 | } | 234 | } |
| 235 | if (info->vol_table) { | 235 | if (info->vol_table) { |
| 236 | for (i = 0; i < (2 << info->vol_nbits); i++) { | 236 | for (i = 0; i < (1 << info->vol_nbits); i++) { |
| 237 | if (!info->vol_table[i]) | 237 | if (!info->vol_table[i]) |
| 238 | break; | 238 | break; |
| 239 | if ((min_uV <= info->vol_table[i]) | 239 | if ((min_uV <= info->vol_table[i]) |
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 11790990277a..b349266a43de 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c | |||
| @@ -634,12 +634,9 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) | |||
| 634 | "%s: failed to register regulator %s err %d\n", | 634 | "%s: failed to register regulator %s err %d\n", |
| 635 | __func__, ab3100_regulator_desc[i].name, | 635 | __func__, ab3100_regulator_desc[i].name, |
| 636 | err); | 636 | err); |
| 637 | i--; | ||
| 638 | /* remove the already registered regulators */ | 637 | /* remove the already registered regulators */ |
| 639 | while (i > 0) { | 638 | while (--i >= 0) |
| 640 | regulator_unregister(ab3100_regulators[i].rdev); | 639 | regulator_unregister(ab3100_regulators[i].rdev); |
| 641 | i--; | ||
| 642 | } | ||
| 643 | return err; | 640 | return err; |
| 644 | } | 641 | } |
| 645 | 642 | ||
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index dc3f1a491675..28c7ae67cec9 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c | |||
| @@ -157,7 +157,7 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) | |||
| 157 | if (info->fixed_uV) | 157 | if (info->fixed_uV) |
| 158 | return info->fixed_uV; | 158 | return info->fixed_uV; |
| 159 | 159 | ||
| 160 | if (selector > info->voltages_len) | 160 | if (selector >= info->voltages_len) |
| 161 | return -EINVAL; | 161 | return -EINVAL; |
| 162 | 162 | ||
| 163 | return info->supported_voltages[selector]; | 163 | return info->supported_voltages[selector]; |
| @@ -344,13 +344,14 @@ static inline struct ab8500_regulator_info *find_regulator_info(int id) | |||
| 344 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | 344 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) |
| 345 | { | 345 | { |
| 346 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | 346 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); |
| 347 | struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); | 347 | struct ab8500_platform_data *pdata; |
| 348 | int i, err; | 348 | int i, err; |
| 349 | 349 | ||
| 350 | if (!ab8500) { | 350 | if (!ab8500) { |
| 351 | dev_err(&pdev->dev, "null mfd parent\n"); | 351 | dev_err(&pdev->dev, "null mfd parent\n"); |
| 352 | return -EINVAL; | 352 | return -EINVAL; |
| 353 | } | 353 | } |
| 354 | pdata = dev_get_platdata(ab8500->dev); | ||
| 354 | 355 | ||
| 355 | /* register all regulators */ | 356 | /* register all regulators */ |
| 356 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | 357 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { |
| @@ -368,11 +369,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | |||
| 368 | dev_err(&pdev->dev, "failed to register regulator %s\n", | 369 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
| 369 | info->desc.name); | 370 | info->desc.name); |
| 370 | /* when we fail, un-register all earlier regulators */ | 371 | /* when we fail, un-register all earlier regulators */ |
| 371 | i--; | 372 | while (--i >= 0) { |
| 372 | while (i > 0) { | ||
| 373 | info = &ab8500_regulator_info[i]; | 373 | info = &ab8500_regulator_info[i]; |
| 374 | regulator_unregister(info->regulator); | 374 | regulator_unregister(info->regulator); |
| 375 | i--; | ||
| 376 | } | 375 | } |
| 377 | return err; | 376 | return err; |
| 378 | } | 377 | } |
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index d59d2f2314af..df1fb53c09d2 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c | |||
| @@ -25,7 +25,7 @@ struct ad5398_chip_info { | |||
| 25 | unsigned int current_level; | 25 | unsigned int current_level; |
| 26 | unsigned int current_mask; | 26 | unsigned int current_mask; |
| 27 | unsigned int current_offset; | 27 | unsigned int current_offset; |
| 28 | struct regulator_dev rdev; | 28 | struct regulator_dev *rdev; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static int ad5398_calc_current(struct ad5398_chip_info *chip, | 31 | static int ad5398_calc_current(struct ad5398_chip_info *chip, |
| @@ -211,7 +211,6 @@ MODULE_DEVICE_TABLE(i2c, ad5398_id); | |||
| 211 | static int __devinit ad5398_probe(struct i2c_client *client, | 211 | static int __devinit ad5398_probe(struct i2c_client *client, |
| 212 | const struct i2c_device_id *id) | 212 | const struct i2c_device_id *id) |
| 213 | { | 213 | { |
| 214 | struct regulator_dev *rdev; | ||
| 215 | struct regulator_init_data *init_data = client->dev.platform_data; | 214 | struct regulator_init_data *init_data = client->dev.platform_data; |
| 216 | struct ad5398_chip_info *chip; | 215 | struct ad5398_chip_info *chip; |
| 217 | const struct ad5398_current_data_format *df = | 216 | const struct ad5398_current_data_format *df = |
| @@ -233,9 +232,10 @@ static int __devinit ad5398_probe(struct i2c_client *client, | |||
| 233 | chip->current_offset = df->current_offset; | 232 | chip->current_offset = df->current_offset; |
| 234 | chip->current_mask = (chip->current_level - 1) << chip->current_offset; | 233 | chip->current_mask = (chip->current_level - 1) << chip->current_offset; |
| 235 | 234 | ||
| 236 | rdev = regulator_register(&ad5398_reg, &client->dev, init_data, chip); | 235 | chip->rdev = regulator_register(&ad5398_reg, &client->dev, |
| 237 | if (IS_ERR(rdev)) { | 236 | init_data, chip); |
| 238 | ret = PTR_ERR(rdev); | 237 | if (IS_ERR(chip->rdev)) { |
| 238 | ret = PTR_ERR(chip->rdev); | ||
| 239 | dev_err(&client->dev, "failed to register %s %s\n", | 239 | dev_err(&client->dev, "failed to register %s %s\n", |
| 240 | id->name, ad5398_reg.name); | 240 | id->name, ad5398_reg.name); |
| 241 | goto err; | 241 | goto err; |
| @@ -254,7 +254,7 @@ static int __devexit ad5398_remove(struct i2c_client *client) | |||
| 254 | { | 254 | { |
| 255 | struct ad5398_chip_info *chip = i2c_get_clientdata(client); | 255 | struct ad5398_chip_info *chip = i2c_get_clientdata(client); |
| 256 | 256 | ||
| 257 | regulator_unregister(&chip->rdev); | 257 | regulator_unregister(chip->rdev); |
| 258 | kfree(chip); | 258 | kfree(chip); |
| 259 | i2c_set_clientdata(client, NULL); | 259 | i2c_set_clientdata(client, NULL); |
| 260 | 260 | ||
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index e49d2bd393f2..d61ecb885a8c 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c | |||
| @@ -165,7 +165,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, | |||
| 165 | mutex_init(&pmic->mtx); | 165 | mutex_init(&pmic->mtx); |
| 166 | 166 | ||
| 167 | for (i = 0; i < 3; i++) { | 167 | for (i = 0; i < 3; i++) { |
| 168 | pmic->rdev[i] = regulator_register(&isl_rd[0], &i2c->dev, | 168 | pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, |
| 169 | init_data, pmic); | 169 | init_data, pmic); |
| 170 | if (IS_ERR(pmic->rdev[i])) { | 170 | if (IS_ERR(pmic->rdev[i])) { |
| 171 | dev_err(&i2c->dev, "failed to register %s\n", id->name); | 171 | dev_err(&i2c->dev, "failed to register %s\n", id->name); |
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 8867c2710a6d..559cfa271a44 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c | |||
| @@ -121,14 +121,14 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
| 121 | if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) | 121 | if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) |
| 122 | return -EINVAL; | 122 | return -EINVAL; |
| 123 | 123 | ||
| 124 | if (min_uV >= 3000000) | ||
| 125 | selector = 3; | ||
| 126 | if (min_uV < 3000000) | ||
| 127 | selector = 2; | ||
| 128 | if (min_uV < 2500000) | ||
| 129 | selector = 1; | ||
| 130 | if (min_uV < 1800000) | 124 | if (min_uV < 1800000) |
| 131 | selector = 0; | 125 | selector = 0; |
| 126 | else if (min_uV < 2500000) | ||
| 127 | selector = 1; | ||
| 128 | else if (min_uV < 3000000) | ||
| 129 | selector = 2; | ||
| 130 | else if (min_uV >= 3000000) | ||
| 131 | selector = 3; | ||
| 132 | 132 | ||
| 133 | if (max1586_v6_calc_voltage(selector) > max_uV) | 133 | if (max1586_v6_calc_voltage(selector) > max_uV) |
| 134 | return -EINVAL; | 134 | return -EINVAL; |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index ab67298799f9..a1baf1fbe004 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
| @@ -549,7 +549,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
| 549 | if (!max8998) | 549 | if (!max8998) |
| 550 | return -ENOMEM; | 550 | return -ENOMEM; |
| 551 | 551 | ||
| 552 | size = sizeof(struct regulator_dev *) * (pdata->num_regulators + 1); | 552 | size = sizeof(struct regulator_dev *) * pdata->num_regulators; |
| 553 | max8998->rdev = kzalloc(size, GFP_KERNEL); | 553 | max8998->rdev = kzalloc(size, GFP_KERNEL); |
| 554 | if (!max8998->rdev) { | 554 | if (!max8998->rdev) { |
| 555 | kfree(max8998); | 555 | kfree(max8998); |
| @@ -557,7 +557,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | rdev = max8998->rdev; | 559 | rdev = max8998->rdev; |
| 560 | max8998->dev = &pdev->dev; | ||
| 560 | max8998->iodev = iodev; | 561 | max8998->iodev = iodev; |
| 562 | max8998->num_regulators = pdata->num_regulators; | ||
| 561 | platform_set_drvdata(pdev, max8998); | 563 | platform_set_drvdata(pdev, max8998); |
| 562 | 564 | ||
| 563 | for (i = 0; i < pdata->num_regulators; i++) { | 565 | for (i = 0; i < pdata->num_regulators; i++) { |
| @@ -583,7 +585,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) | |||
| 583 | 585 | ||
| 584 | return 0; | 586 | return 0; |
| 585 | err: | 587 | err: |
| 586 | for (i = 0; i <= max8998->num_regulators; i++) | 588 | for (i = 0; i < max8998->num_regulators; i++) |
| 587 | if (rdev[i]) | 589 | if (rdev[i]) |
| 588 | regulator_unregister(rdev[i]); | 590 | regulator_unregister(rdev[i]); |
| 589 | 591 | ||
| @@ -599,7 +601,7 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev) | |||
| 599 | struct regulator_dev **rdev = max8998->rdev; | 601 | struct regulator_dev **rdev = max8998->rdev; |
| 600 | int i; | 602 | int i; |
| 601 | 603 | ||
| 602 | for (i = 0; i <= max8998->num_regulators; i++) | 604 | for (i = 0; i < max8998->num_regulators; i++) |
| 603 | if (rdev[i]) | 605 | if (rdev[i]) |
| 604 | regulator_unregister(rdev[i]); | 606 | regulator_unregister(rdev[i]); |
| 605 | 607 | ||
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index c239f42aa4a3..020f5878d7ff 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
| @@ -626,12 +626,6 @@ fail: | |||
| 626 | return error; | 626 | return error; |
| 627 | } | 627 | } |
| 628 | 628 | ||
| 629 | /** | ||
| 630 | * tps6507x_remove - TPS6507x driver i2c remove handler | ||
| 631 | * @client: i2c driver client device structure | ||
| 632 | * | ||
| 633 | * Unregister TPS driver as an i2c client device driver | ||
| 634 | */ | ||
| 635 | static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) | 629 | static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) |
| 636 | { | 630 | { |
| 637 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); | 631 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); |
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 8cff1413a147..51237fbb1bbb 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c | |||
| @@ -133,7 +133,7 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) | |||
| 133 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; | 133 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; |
| 134 | val = (val & mask) >> ri->volt_shift; | 134 | val = (val & mask) >> ri->volt_shift; |
| 135 | 135 | ||
| 136 | if (val > ri->desc.n_voltages) | 136 | if (val >= ri->desc.n_voltages) |
| 137 | BUG(); | 137 | BUG(); |
| 138 | 138 | ||
| 139 | return ri->voltages[val] * 1000; | 139 | return ri->voltages[val] * 1000; |
| @@ -150,7 +150,7 @@ static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, | |||
| 150 | if (ret) | 150 | if (ret) |
| 151 | return ret; | 151 | return ret; |
| 152 | 152 | ||
| 153 | return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit); | 153 | return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static int tps6586x_regulator_enable(struct regulator_dev *rdev) | 156 | static int tps6586x_regulator_enable(struct regulator_dev *rdev) |
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index e686cdb61b97..9edf8f692341 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c | |||
| @@ -215,8 +215,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, | |||
| 215 | 215 | ||
| 216 | case REGULATOR_MODE_IDLE: | 216 | case REGULATOR_MODE_IDLE: |
| 217 | ret = wm831x_set_bits(wm831x, ctrl_reg, | 217 | ret = wm831x_set_bits(wm831x, ctrl_reg, |
| 218 | WM831X_LDO1_LP_MODE, | 218 | WM831X_LDO1_LP_MODE, 0); |
| 219 | WM831X_LDO1_LP_MODE); | ||
| 220 | if (ret < 0) | 219 | if (ret < 0) |
| 221 | return ret; | 220 | return ret; |
| 222 | 221 | ||
| @@ -225,10 +224,12 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, | |||
| 225 | WM831X_LDO1_ON_MODE); | 224 | WM831X_LDO1_ON_MODE); |
| 226 | if (ret < 0) | 225 | if (ret < 0) |
| 227 | return ret; | 226 | return ret; |
| 227 | break; | ||
| 228 | 228 | ||
| 229 | case REGULATOR_MODE_STANDBY: | 229 | case REGULATOR_MODE_STANDBY: |
| 230 | ret = wm831x_set_bits(wm831x, ctrl_reg, | 230 | ret = wm831x_set_bits(wm831x, ctrl_reg, |
| 231 | WM831X_LDO1_LP_MODE, 0); | 231 | WM831X_LDO1_LP_MODE, |
| 232 | WM831X_LDO1_LP_MODE); | ||
| 232 | if (ret < 0) | 233 | if (ret < 0) |
| 233 | return ret; | 234 | return ret; |
| 234 | 235 | ||
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 0e6ed7db9364..fe4b8a8a9dfd 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c | |||
| @@ -1129,7 +1129,7 @@ static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev) | |||
| 1129 | mode = REGULATOR_MODE_NORMAL; | 1129 | mode = REGULATOR_MODE_NORMAL; |
| 1130 | } else if (!active && !sleep) | 1130 | } else if (!active && !sleep) |
| 1131 | mode = REGULATOR_MODE_IDLE; | 1131 | mode = REGULATOR_MODE_IDLE; |
| 1132 | else if (!sleep) | 1132 | else if (sleep) |
| 1133 | mode = REGULATOR_MODE_STANDBY; | 1133 | mode = REGULATOR_MODE_STANDBY; |
| 1134 | 1134 | ||
| 1135 | return mode; | 1135 | return mode; |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index b7de02525ec9..85cf607fc78f 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c | |||
| @@ -217,8 +217,7 @@ tapeblock_setup_device(struct tape_device * device) | |||
| 217 | if (!blkdat->request_queue) | 217 | if (!blkdat->request_queue) |
| 218 | return -ENOMEM; | 218 | return -ENOMEM; |
| 219 | 219 | ||
| 220 | elevator_exit(blkdat->request_queue->elevator); | 220 | rc = elevator_change(blkdat->request_queue, "noop"); |
| 221 | rc = elevator_init(blkdat->request_queue, "noop"); | ||
| 222 | if (rc) | 221 | if (rc) |
| 223 | goto cleanup_queue; | 222 | goto cleanup_queue; |
| 224 | 223 | ||
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 7d4d2275573c..7f11f3e48e12 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
| @@ -300,8 +300,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
| 300 | enum iscsi_host_param param, char *buf) | 300 | enum iscsi_host_param param, char *buf) |
| 301 | { | 301 | { |
| 302 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | 302 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); |
| 303 | int len = 0; | 303 | int status = 0; |
| 304 | int status; | ||
| 305 | 304 | ||
| 306 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); | 305 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); |
| 307 | switch (param) { | 306 | switch (param) { |
| @@ -315,7 +314,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
| 315 | default: | 314 | default: |
| 316 | return iscsi_host_get_param(shost, param, buf); | 315 | return iscsi_host_get_param(shost, param, buf); |
| 317 | } | 316 | } |
| 318 | return len; | 317 | return status; |
| 319 | } | 318 | } |
| 320 | 319 | ||
| 321 | int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) | 320 | int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 26350e470bcc..877324fc594c 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
| @@ -368,7 +368,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, | |||
| 368 | memset(req, 0, sizeof(*req)); | 368 | memset(req, 0, sizeof(*req)); |
| 369 | wrb->tag0 |= tag; | 369 | wrb->tag0 |= tag; |
| 370 | 370 | ||
| 371 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 1); | 371 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); |
| 372 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 372 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, |
| 373 | OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, | 373 | OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, |
| 374 | sizeof(*req)); | 374 | sizeof(*req)); |
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index cd05e049d5f6..d0c82340f0e2 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c | |||
| @@ -1404,13 +1404,13 @@ void scsi_print_sense(char *name, struct scsi_cmnd *cmd) | |||
| 1404 | { | 1404 | { |
| 1405 | struct scsi_sense_hdr sshdr; | 1405 | struct scsi_sense_hdr sshdr; |
| 1406 | 1406 | ||
| 1407 | scmd_printk(KERN_INFO, cmd, ""); | 1407 | scmd_printk(KERN_INFO, cmd, " "); |
| 1408 | scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, | 1408 | scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, |
| 1409 | &sshdr); | 1409 | &sshdr); |
| 1410 | scsi_show_sense_hdr(&sshdr); | 1410 | scsi_show_sense_hdr(&sshdr); |
| 1411 | scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, | 1411 | scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, |
| 1412 | &sshdr); | 1412 | &sshdr); |
| 1413 | scmd_printk(KERN_INFO, cmd, ""); | 1413 | scmd_printk(KERN_INFO, cmd, " "); |
| 1414 | scsi_show_extd_sense(sshdr.asc, sshdr.ascq); | 1414 | scsi_show_extd_sense(sshdr.asc, sshdr.ascq); |
| 1415 | } | 1415 | } |
| 1416 | EXPORT_SYMBOL(scsi_print_sense); | 1416 | EXPORT_SYMBOL(scsi_print_sense); |
| @@ -1453,7 +1453,7 @@ EXPORT_SYMBOL(scsi_show_result); | |||
| 1453 | 1453 | ||
| 1454 | void scsi_print_result(struct scsi_cmnd *cmd) | 1454 | void scsi_print_result(struct scsi_cmnd *cmd) |
| 1455 | { | 1455 | { |
| 1456 | scmd_printk(KERN_INFO, cmd, ""); | 1456 | scmd_printk(KERN_INFO, cmd, " "); |
| 1457 | scsi_show_result(cmd->result); | 1457 | scsi_show_result(cmd->result); |
| 1458 | } | 1458 | } |
| 1459 | EXPORT_SYMBOL(scsi_print_result); | 1459 | EXPORT_SYMBOL(scsi_print_result); |
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4f5551b5fe53..c5d0606ad097 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
| @@ -3231,6 +3231,12 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) | |||
| 3231 | misc_fw_support = readl(&cfgtable->misc_fw_support); | 3231 | misc_fw_support = readl(&cfgtable->misc_fw_support); |
| 3232 | use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; | 3232 | use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; |
| 3233 | 3233 | ||
| 3234 | /* The doorbell reset seems to cause lockups on some Smart | ||
| 3235 | * Arrays (e.g. P410, P410i, maybe others). Until this is | ||
| 3236 | * fixed or at least isolated, avoid the doorbell reset. | ||
| 3237 | */ | ||
| 3238 | use_doorbell = 0; | ||
| 3239 | |||
| 3234 | rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); | 3240 | rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); |
| 3235 | if (rc) | 3241 | if (rc) |
| 3236 | goto unmap_cfgtable; | 3242 | goto unmap_cfgtable; |
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index fda4de3440c4..e88bbdde49c5 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c | |||
| @@ -865,7 +865,7 @@ void osd_req_read(struct osd_request *or, | |||
| 865 | { | 865 | { |
| 866 | _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len); | 866 | _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len); |
| 867 | WARN_ON(or->in.bio || or->in.total_bytes); | 867 | WARN_ON(or->in.bio || or->in.total_bytes); |
| 868 | WARN_ON(1 == (bio->bi_rw & REQ_WRITE)); | 868 | WARN_ON(bio->bi_rw & REQ_WRITE); |
| 869 | or->in.bio = bio; | 869 | or->in.bio = bio; |
| 870 | or->in.total_bytes = len; | 870 | or->in.total_bytes = len; |
| 871 | } | 871 | } |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 420238cc794e..114bc5a81171 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
| @@ -1838,26 +1838,33 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) | |||
| 1838 | 1838 | ||
| 1839 | qla24xx_disable_vp(vha); | 1839 | qla24xx_disable_vp(vha); |
| 1840 | 1840 | ||
| 1841 | vha->flags.delete_progress = 1; | ||
| 1842 | |||
| 1841 | fc_remove_host(vha->host); | 1843 | fc_remove_host(vha->host); |
| 1842 | 1844 | ||
| 1843 | scsi_remove_host(vha->host); | 1845 | scsi_remove_host(vha->host); |
| 1844 | 1846 | ||
| 1845 | qla2x00_free_fcports(vha); | 1847 | if (vha->timer_active) { |
| 1848 | qla2x00_vp_stop_timer(vha); | ||
| 1849 | DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]" | ||
| 1850 | " = %p has stopped\n", vha->host_no, vha->vp_idx, vha)); | ||
| 1851 | } | ||
| 1846 | 1852 | ||
| 1847 | qla24xx_deallocate_vp_id(vha); | 1853 | qla24xx_deallocate_vp_id(vha); |
| 1848 | 1854 | ||
| 1855 | /* No pending activities shall be there on the vha now */ | ||
| 1856 | DEBUG(msleep(random32()%10)); /* Just to see if something falls on | ||
| 1857 | * the net we have placed below */ | ||
| 1858 | |||
| 1859 | BUG_ON(atomic_read(&vha->vref_count)); | ||
| 1860 | |||
| 1861 | qla2x00_free_fcports(vha); | ||
| 1862 | |||
| 1849 | mutex_lock(&ha->vport_lock); | 1863 | mutex_lock(&ha->vport_lock); |
| 1850 | ha->cur_vport_count--; | 1864 | ha->cur_vport_count--; |
| 1851 | clear_bit(vha->vp_idx, ha->vp_idx_map); | 1865 | clear_bit(vha->vp_idx, ha->vp_idx_map); |
| 1852 | mutex_unlock(&ha->vport_lock); | 1866 | mutex_unlock(&ha->vport_lock); |
| 1853 | 1867 | ||
| 1854 | if (vha->timer_active) { | ||
| 1855 | qla2x00_vp_stop_timer(vha); | ||
| 1856 | DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p " | ||
| 1857 | "has stopped\n", | ||
| 1858 | vha->host_no, vha->vp_idx, vha)); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | if (vha->req->id && !ha->flags.cpu_affinity_enabled) { | 1868 | if (vha->req->id && !ha->flags.cpu_affinity_enabled) { |
| 1862 | if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) | 1869 | if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) |
| 1863 | qla_printk(KERN_WARNING, ha, | 1870 | qla_printk(KERN_WARNING, ha, |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 6cfc28a25eb3..b74e6b5743dc 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
| @@ -29,8 +29,6 @@ | |||
| 29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ | 29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ |
| 30 | /* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */ | 30 | /* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */ |
| 31 | 31 | ||
| 32 | /* #define QL_PRINTK_BUF */ /* Captures printk to buffer */ | ||
| 33 | |||
| 34 | /* | 32 | /* |
| 35 | * Macros use for debugging the driver. | 33 | * Macros use for debugging the driver. |
| 36 | */ | 34 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3a432ea0c7a3..d2a4e1530708 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
| @@ -2641,6 +2641,7 @@ struct qla_hw_data { | |||
| 2641 | #define MBX_UPDATE_FLASH_ACTIVE 3 | 2641 | #define MBX_UPDATE_FLASH_ACTIVE 3 |
| 2642 | 2642 | ||
| 2643 | struct mutex vport_lock; /* Virtual port synchronization */ | 2643 | struct mutex vport_lock; /* Virtual port synchronization */ |
| 2644 | spinlock_t vport_slock; /* order is hardware_lock, then vport_slock */ | ||
| 2644 | struct completion mbx_cmd_comp; /* Serialize mbx access */ | 2645 | struct completion mbx_cmd_comp; /* Serialize mbx access */ |
| 2645 | struct completion mbx_intr_comp; /* Used for completion notification */ | 2646 | struct completion mbx_intr_comp; /* Used for completion notification */ |
| 2646 | struct completion dcbx_comp; /* For set port config notification */ | 2647 | struct completion dcbx_comp; /* For set port config notification */ |
| @@ -2828,6 +2829,7 @@ typedef struct scsi_qla_host { | |||
| 2828 | uint32_t management_server_logged_in :1; | 2829 | uint32_t management_server_logged_in :1; |
| 2829 | uint32_t process_response_queue :1; | 2830 | uint32_t process_response_queue :1; |
| 2830 | uint32_t difdix_supported:1; | 2831 | uint32_t difdix_supported:1; |
| 2832 | uint32_t delete_progress:1; | ||
| 2831 | } flags; | 2833 | } flags; |
| 2832 | 2834 | ||
| 2833 | atomic_t loop_state; | 2835 | atomic_t loop_state; |
| @@ -2922,6 +2924,8 @@ typedef struct scsi_qla_host { | |||
| 2922 | struct req_que *req; | 2924 | struct req_que *req; |
| 2923 | int fw_heartbeat_counter; | 2925 | int fw_heartbeat_counter; |
| 2924 | int seconds_since_last_heartbeat; | 2926 | int seconds_since_last_heartbeat; |
| 2927 | |||
| 2928 | atomic_t vref_count; | ||
| 2925 | } scsi_qla_host_t; | 2929 | } scsi_qla_host_t; |
| 2926 | 2930 | ||
| 2927 | /* | 2931 | /* |
| @@ -2932,6 +2936,22 @@ typedef struct scsi_qla_host { | |||
| 2932 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ | 2936 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ |
| 2933 | atomic_read(&ha->loop_state) == LOOP_DOWN) | 2937 | atomic_read(&ha->loop_state) == LOOP_DOWN) |
| 2934 | 2938 | ||
| 2939 | #define QLA_VHA_MARK_BUSY(__vha, __bail) do { \ | ||
| 2940 | atomic_inc(&__vha->vref_count); \ | ||
| 2941 | mb(); \ | ||
| 2942 | if (__vha->flags.delete_progress) { \ | ||
| 2943 | atomic_dec(&__vha->vref_count); \ | ||
| 2944 | __bail = 1; \ | ||
| 2945 | } else { \ | ||
| 2946 | __bail = 0; \ | ||
| 2947 | } \ | ||
| 2948 | } while (0) | ||
| 2949 | |||
| 2950 | #define QLA_VHA_MARK_NOT_BUSY(__vha) do { \ | ||
| 2951 | atomic_dec(&__vha->vref_count); \ | ||
| 2952 | } while (0) | ||
| 2953 | |||
| 2954 | |||
| 2935 | #define qla_printk(level, ha, format, arg...) \ | 2955 | #define qla_printk(level, ha, format, arg...) \ |
| 2936 | dev_printk(level , &((ha)->pdev->dev) , format , ## arg) | 2956 | dev_printk(level , &((ha)->pdev->dev) , format , ## arg) |
| 2937 | 2957 | ||
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d863ed2619b5..9c383baebe27 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
| @@ -69,21 +69,29 @@ qla2x00_ctx_sp_free(srb_t *sp) | |||
| 69 | { | 69 | { |
| 70 | struct srb_ctx *ctx = sp->ctx; | 70 | struct srb_ctx *ctx = sp->ctx; |
| 71 | struct srb_iocb *iocb = ctx->u.iocb_cmd; | 71 | struct srb_iocb *iocb = ctx->u.iocb_cmd; |
| 72 | struct scsi_qla_host *vha = sp->fcport->vha; | ||
| 72 | 73 | ||
| 73 | del_timer_sync(&iocb->timer); | 74 | del_timer_sync(&iocb->timer); |
| 74 | kfree(iocb); | 75 | kfree(iocb); |
| 75 | kfree(ctx); | 76 | kfree(ctx); |
| 76 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); | 77 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); |
| 78 | |||
| 79 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
| 77 | } | 80 | } |
| 78 | 81 | ||
| 79 | inline srb_t * | 82 | inline srb_t * |
| 80 | qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | 83 | qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, |
| 81 | unsigned long tmo) | 84 | unsigned long tmo) |
| 82 | { | 85 | { |
| 83 | srb_t *sp; | 86 | srb_t *sp = NULL; |
| 84 | struct qla_hw_data *ha = vha->hw; | 87 | struct qla_hw_data *ha = vha->hw; |
| 85 | struct srb_ctx *ctx; | 88 | struct srb_ctx *ctx; |
| 86 | struct srb_iocb *iocb; | 89 | struct srb_iocb *iocb; |
| 90 | uint8_t bail; | ||
| 91 | |||
| 92 | QLA_VHA_MARK_BUSY(vha, bail); | ||
| 93 | if (bail) | ||
| 94 | return NULL; | ||
| 87 | 95 | ||
| 88 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | 96 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); |
| 89 | if (!sp) | 97 | if (!sp) |
| @@ -116,6 +124,8 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | |||
| 116 | iocb->timer.function = qla2x00_ctx_sp_timeout; | 124 | iocb->timer.function = qla2x00_ctx_sp_timeout; |
| 117 | add_timer(&iocb->timer); | 125 | add_timer(&iocb->timer); |
| 118 | done: | 126 | done: |
| 127 | if (!sp) | ||
| 128 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
| 119 | return sp; | 129 | return sp; |
| 120 | } | 130 | } |
| 121 | 131 | ||
| @@ -1777,11 +1787,15 @@ qla2x00_init_rings(scsi_qla_host_t *vha) | |||
| 1777 | qla2x00_init_response_q_entries(rsp); | 1787 | qla2x00_init_response_q_entries(rsp); |
| 1778 | } | 1788 | } |
| 1779 | 1789 | ||
| 1790 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 1780 | /* Clear RSCN queue. */ | 1791 | /* Clear RSCN queue. */ |
| 1781 | list_for_each_entry(vp, &ha->vp_list, list) { | 1792 | list_for_each_entry(vp, &ha->vp_list, list) { |
| 1782 | vp->rscn_in_ptr = 0; | 1793 | vp->rscn_in_ptr = 0; |
| 1783 | vp->rscn_out_ptr = 0; | 1794 | vp->rscn_out_ptr = 0; |
| 1784 | } | 1795 | } |
| 1796 | |||
| 1797 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 1798 | |||
| 1785 | ha->isp_ops->config_rings(vha); | 1799 | ha->isp_ops->config_rings(vha); |
| 1786 | 1800 | ||
| 1787 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1801 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| @@ -3218,12 +3232,17 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
| 3218 | /* Bypass virtual ports of the same host. */ | 3232 | /* Bypass virtual ports of the same host. */ |
| 3219 | found = 0; | 3233 | found = 0; |
| 3220 | if (ha->num_vhosts) { | 3234 | if (ha->num_vhosts) { |
| 3235 | unsigned long flags; | ||
| 3236 | |||
| 3237 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 3221 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 3238 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { |
| 3222 | if (new_fcport->d_id.b24 == vp->d_id.b24) { | 3239 | if (new_fcport->d_id.b24 == vp->d_id.b24) { |
| 3223 | found = 1; | 3240 | found = 1; |
| 3224 | break; | 3241 | break; |
| 3225 | } | 3242 | } |
| 3226 | } | 3243 | } |
| 3244 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 3245 | |||
| 3227 | if (found) | 3246 | if (found) |
| 3228 | continue; | 3247 | continue; |
| 3229 | } | 3248 | } |
| @@ -3343,6 +3362,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) | |||
| 3343 | struct qla_hw_data *ha = vha->hw; | 3362 | struct qla_hw_data *ha = vha->hw; |
| 3344 | struct scsi_qla_host *vp; | 3363 | struct scsi_qla_host *vp; |
| 3345 | struct scsi_qla_host *tvp; | 3364 | struct scsi_qla_host *tvp; |
| 3365 | unsigned long flags = 0; | ||
| 3346 | 3366 | ||
| 3347 | rval = QLA_SUCCESS; | 3367 | rval = QLA_SUCCESS; |
| 3348 | 3368 | ||
| @@ -3367,6 +3387,8 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) | |||
| 3367 | /* Check for loop ID being already in use. */ | 3387 | /* Check for loop ID being already in use. */ |
| 3368 | found = 0; | 3388 | found = 0; |
| 3369 | fcport = NULL; | 3389 | fcport = NULL; |
| 3390 | |||
| 3391 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 3370 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 3392 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { |
| 3371 | list_for_each_entry(fcport, &vp->vp_fcports, list) { | 3393 | list_for_each_entry(fcport, &vp->vp_fcports, list) { |
| 3372 | if (fcport->loop_id == dev->loop_id && | 3394 | if (fcport->loop_id == dev->loop_id && |
| @@ -3379,6 +3401,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) | |||
| 3379 | if (found) | 3401 | if (found) |
| 3380 | break; | 3402 | break; |
| 3381 | } | 3403 | } |
| 3404 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 3382 | 3405 | ||
| 3383 | /* If not in use then it is free to use. */ | 3406 | /* If not in use then it is free to use. */ |
| 3384 | if (!found) { | 3407 | if (!found) { |
| @@ -3791,14 +3814,27 @@ void | |||
| 3791 | qla2x00_update_fcports(scsi_qla_host_t *base_vha) | 3814 | qla2x00_update_fcports(scsi_qla_host_t *base_vha) |
| 3792 | { | 3815 | { |
| 3793 | fc_port_t *fcport; | 3816 | fc_port_t *fcport; |
| 3794 | struct scsi_qla_host *tvp, *vha; | 3817 | struct scsi_qla_host *vha; |
| 3818 | struct qla_hw_data *ha = base_vha->hw; | ||
| 3819 | unsigned long flags; | ||
| 3795 | 3820 | ||
| 3821 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 3796 | /* Go with deferred removal of rport references. */ | 3822 | /* Go with deferred removal of rport references. */ |
| 3797 | list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list) | 3823 | list_for_each_entry(vha, &base_vha->hw->vp_list, list) { |
| 3798 | list_for_each_entry(fcport, &vha->vp_fcports, list) | 3824 | atomic_inc(&vha->vref_count); |
| 3825 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | ||
| 3799 | if (fcport && fcport->drport && | 3826 | if (fcport && fcport->drport && |
| 3800 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) | 3827 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) { |
| 3828 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 3829 | |||
| 3801 | qla2x00_rport_del(fcport); | 3830 | qla2x00_rport_del(fcport); |
| 3831 | |||
| 3832 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 3833 | } | ||
| 3834 | } | ||
| 3835 | atomic_dec(&vha->vref_count); | ||
| 3836 | } | ||
| 3837 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 3802 | } | 3838 | } |
| 3803 | 3839 | ||
| 3804 | void | 3840 | void |
| @@ -3806,7 +3842,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) | |||
| 3806 | { | 3842 | { |
| 3807 | struct qla_hw_data *ha = vha->hw; | 3843 | struct qla_hw_data *ha = vha->hw; |
| 3808 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); | 3844 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); |
| 3809 | struct scsi_qla_host *tvp; | 3845 | unsigned long flags; |
| 3810 | 3846 | ||
| 3811 | vha->flags.online = 0; | 3847 | vha->flags.online = 0; |
| 3812 | ha->flags.chip_reset_done = 0; | 3848 | ha->flags.chip_reset_done = 0; |
| @@ -3824,8 +3860,18 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) | |||
| 3824 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | 3860 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { |
| 3825 | atomic_set(&vha->loop_state, LOOP_DOWN); | 3861 | atomic_set(&vha->loop_state, LOOP_DOWN); |
| 3826 | qla2x00_mark_all_devices_lost(vha, 0); | 3862 | qla2x00_mark_all_devices_lost(vha, 0); |
| 3827 | list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list) | 3863 | |
| 3864 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 3865 | list_for_each_entry(vp, &base_vha->hw->vp_list, list) { | ||
| 3866 | atomic_inc(&vp->vref_count); | ||
| 3867 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 3868 | |||
| 3828 | qla2x00_mark_all_devices_lost(vp, 0); | 3869 | qla2x00_mark_all_devices_lost(vp, 0); |
| 3870 | |||
| 3871 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 3872 | atomic_dec(&vp->vref_count); | ||
| 3873 | } | ||
| 3874 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 3829 | } else { | 3875 | } else { |
| 3830 | if (!atomic_read(&vha->loop_down_timer)) | 3876 | if (!atomic_read(&vha->loop_down_timer)) |
| 3831 | atomic_set(&vha->loop_down_timer, | 3877 | atomic_set(&vha->loop_down_timer, |
| @@ -3862,8 +3908,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
| 3862 | uint8_t status = 0; | 3908 | uint8_t status = 0; |
| 3863 | struct qla_hw_data *ha = vha->hw; | 3909 | struct qla_hw_data *ha = vha->hw; |
| 3864 | struct scsi_qla_host *vp; | 3910 | struct scsi_qla_host *vp; |
| 3865 | struct scsi_qla_host *tvp; | ||
| 3866 | struct req_que *req = ha->req_q_map[0]; | 3911 | struct req_que *req = ha->req_q_map[0]; |
| 3912 | unsigned long flags; | ||
| 3867 | 3913 | ||
| 3868 | if (vha->flags.online) { | 3914 | if (vha->flags.online) { |
| 3869 | qla2x00_abort_isp_cleanup(vha); | 3915 | qla2x00_abort_isp_cleanup(vha); |
| @@ -3970,10 +4016,21 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
| 3970 | DEBUG(printk(KERN_INFO | 4016 | DEBUG(printk(KERN_INFO |
| 3971 | "qla2x00_abort_isp(%ld): succeeded.\n", | 4017 | "qla2x00_abort_isp(%ld): succeeded.\n", |
| 3972 | vha->host_no)); | 4018 | vha->host_no)); |
| 3973 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 4019 | |
| 3974 | if (vp->vp_idx) | 4020 | spin_lock_irqsave(&ha->vport_slock, flags); |
| 4021 | list_for_each_entry(vp, &ha->vp_list, list) { | ||
| 4022 | if (vp->vp_idx) { | ||
| 4023 | atomic_inc(&vp->vref_count); | ||
| 4024 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 4025 | |||
| 3975 | qla2x00_vp_abort_isp(vp); | 4026 | qla2x00_vp_abort_isp(vp); |
| 4027 | |||
| 4028 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 4029 | atomic_dec(&vp->vref_count); | ||
| 4030 | } | ||
| 3976 | } | 4031 | } |
| 4032 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 4033 | |||
| 3977 | } else { | 4034 | } else { |
| 3978 | qla_printk(KERN_INFO, ha, | 4035 | qla_printk(KERN_INFO, ha, |
| 3979 | "qla2x00_abort_isp: **** FAILED ****\n"); | 4036 | "qla2x00_abort_isp: **** FAILED ****\n"); |
| @@ -5185,7 +5242,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) | |||
| 5185 | struct req_que *req = ha->req_q_map[0]; | 5242 | struct req_que *req = ha->req_q_map[0]; |
| 5186 | struct rsp_que *rsp = ha->rsp_q_map[0]; | 5243 | struct rsp_que *rsp = ha->rsp_q_map[0]; |
| 5187 | struct scsi_qla_host *vp; | 5244 | struct scsi_qla_host *vp; |
| 5188 | struct scsi_qla_host *tvp; | 5245 | unsigned long flags; |
| 5189 | 5246 | ||
| 5190 | status = qla2x00_init_rings(vha); | 5247 | status = qla2x00_init_rings(vha); |
| 5191 | if (!status) { | 5248 | if (!status) { |
| @@ -5272,10 +5329,21 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) | |||
| 5272 | DEBUG(printk(KERN_INFO | 5329 | DEBUG(printk(KERN_INFO |
| 5273 | "qla82xx_restart_isp(%ld): succeeded.\n", | 5330 | "qla82xx_restart_isp(%ld): succeeded.\n", |
| 5274 | vha->host_no)); | 5331 | vha->host_no)); |
| 5275 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 5332 | |
| 5276 | if (vp->vp_idx) | 5333 | spin_lock_irqsave(&ha->vport_slock, flags); |
| 5334 | list_for_each_entry(vp, &ha->vp_list, list) { | ||
| 5335 | if (vp->vp_idx) { | ||
| 5336 | atomic_inc(&vp->vref_count); | ||
| 5337 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 5338 | |||
| 5277 | qla2x00_vp_abort_isp(vp); | 5339 | qla2x00_vp_abort_isp(vp); |
| 5340 | |||
| 5341 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 5342 | atomic_dec(&vp->vref_count); | ||
| 5343 | } | ||
| 5278 | } | 5344 | } |
| 5345 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 5346 | |||
| 5279 | } else { | 5347 | } else { |
| 5280 | qla_printk(KERN_INFO, ha, | 5348 | qla_printk(KERN_INFO, ha, |
| 5281 | "qla82xx_restart_isp: **** FAILED ****\n"); | 5349 | "qla82xx_restart_isp: **** FAILED ****\n"); |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6982ba70e12a..28f65be19dad 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
| @@ -1706,19 +1706,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
| 1706 | cp->result = DID_ERROR << 16; | 1706 | cp->result = DID_ERROR << 16; |
| 1707 | break; | 1707 | break; |
| 1708 | } | 1708 | } |
| 1709 | } else if (!lscsi_status) { | 1709 | } else { |
| 1710 | DEBUG2(qla_printk(KERN_INFO, ha, | 1710 | DEBUG2(qla_printk(KERN_INFO, ha, |
| 1711 | "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x " | 1711 | "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x " |
| 1712 | "of 0x%x bytes).\n", vha->host_no, cp->device->id, | 1712 | "of 0x%x bytes).\n", vha->host_no, cp->device->id, |
| 1713 | cp->device->lun, resid, scsi_bufflen(cp))); | 1713 | cp->device->lun, resid, scsi_bufflen(cp))); |
| 1714 | 1714 | ||
| 1715 | cp->result = DID_ERROR << 16; | 1715 | cp->result = DID_ERROR << 16 | lscsi_status; |
| 1716 | break; | 1716 | goto check_scsi_status; |
| 1717 | } | 1717 | } |
| 1718 | 1718 | ||
| 1719 | cp->result = DID_OK << 16 | lscsi_status; | 1719 | cp->result = DID_OK << 16 | lscsi_status; |
| 1720 | logit = 0; | 1720 | logit = 0; |
| 1721 | 1721 | ||
| 1722 | check_scsi_status: | ||
| 1722 | /* | 1723 | /* |
| 1723 | * Check to see if SCSI Status is non zero. If so report SCSI | 1724 | * Check to see if SCSI Status is non zero. If so report SCSI |
| 1724 | * Status. | 1725 | * Status. |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 6009b0c69488..a595ec8264f8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
| @@ -2913,7 +2913,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
| 2913 | uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); | 2913 | uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); |
| 2914 | struct qla_hw_data *ha = vha->hw; | 2914 | struct qla_hw_data *ha = vha->hw; |
| 2915 | scsi_qla_host_t *vp; | 2915 | scsi_qla_host_t *vp; |
| 2916 | scsi_qla_host_t *tvp; | 2916 | unsigned long flags; |
| 2917 | 2917 | ||
| 2918 | if (rptid_entry->entry_status != 0) | 2918 | if (rptid_entry->entry_status != 0) |
| 2919 | return; | 2919 | return; |
| @@ -2945,9 +2945,12 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
| 2945 | return; | 2945 | return; |
| 2946 | } | 2946 | } |
| 2947 | 2947 | ||
| 2948 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) | 2948 | spin_lock_irqsave(&ha->vport_slock, flags); |
| 2949 | list_for_each_entry(vp, &ha->vp_list, list) | ||
| 2949 | if (vp_idx == vp->vp_idx) | 2950 | if (vp_idx == vp->vp_idx) |
| 2950 | break; | 2951 | break; |
| 2952 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 2953 | |||
| 2951 | if (!vp) | 2954 | if (!vp) |
| 2952 | return; | 2955 | return; |
| 2953 | 2956 | ||
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 987c5b0ca78e..2b69392a71a1 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
| @@ -30,6 +30,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) | |||
| 30 | { | 30 | { |
| 31 | uint32_t vp_id; | 31 | uint32_t vp_id; |
| 32 | struct qla_hw_data *ha = vha->hw; | 32 | struct qla_hw_data *ha = vha->hw; |
| 33 | unsigned long flags; | ||
| 33 | 34 | ||
| 34 | /* Find an empty slot and assign an vp_id */ | 35 | /* Find an empty slot and assign an vp_id */ |
| 35 | mutex_lock(&ha->vport_lock); | 36 | mutex_lock(&ha->vport_lock); |
| @@ -44,7 +45,11 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) | |||
| 44 | set_bit(vp_id, ha->vp_idx_map); | 45 | set_bit(vp_id, ha->vp_idx_map); |
| 45 | ha->num_vhosts++; | 46 | ha->num_vhosts++; |
| 46 | vha->vp_idx = vp_id; | 47 | vha->vp_idx = vp_id; |
| 48 | |||
| 49 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 47 | list_add_tail(&vha->list, &ha->vp_list); | 50 | list_add_tail(&vha->list, &ha->vp_list); |
| 51 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 52 | |||
| 48 | mutex_unlock(&ha->vport_lock); | 53 | mutex_unlock(&ha->vport_lock); |
| 49 | return vp_id; | 54 | return vp_id; |
| 50 | } | 55 | } |
| @@ -54,12 +59,31 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) | |||
| 54 | { | 59 | { |
| 55 | uint16_t vp_id; | 60 | uint16_t vp_id; |
| 56 | struct qla_hw_data *ha = vha->hw; | 61 | struct qla_hw_data *ha = vha->hw; |
| 62 | unsigned long flags = 0; | ||
| 57 | 63 | ||
| 58 | mutex_lock(&ha->vport_lock); | 64 | mutex_lock(&ha->vport_lock); |
| 65 | /* | ||
| 66 | * Wait for all pending activities to finish before removing vport from | ||
| 67 | * the list. | ||
| 68 | * Lock needs to be held for safe removal from the list (it | ||
| 69 | * ensures no active vp_list traversal while the vport is removed | ||
| 70 | * from the queue) | ||
| 71 | */ | ||
| 72 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 73 | while (atomic_read(&vha->vref_count)) { | ||
| 74 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 75 | |||
| 76 | msleep(500); | ||
| 77 | |||
| 78 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 79 | } | ||
| 80 | list_del(&vha->list); | ||
| 81 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 82 | |||
| 59 | vp_id = vha->vp_idx; | 83 | vp_id = vha->vp_idx; |
| 60 | ha->num_vhosts--; | 84 | ha->num_vhosts--; |
| 61 | clear_bit(vp_id, ha->vp_idx_map); | 85 | clear_bit(vp_id, ha->vp_idx_map); |
| 62 | list_del(&vha->list); | 86 | |
| 63 | mutex_unlock(&ha->vport_lock); | 87 | mutex_unlock(&ha->vport_lock); |
| 64 | } | 88 | } |
| 65 | 89 | ||
| @@ -68,12 +92,17 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) | |||
| 68 | { | 92 | { |
| 69 | scsi_qla_host_t *vha; | 93 | scsi_qla_host_t *vha; |
| 70 | struct scsi_qla_host *tvha; | 94 | struct scsi_qla_host *tvha; |
| 95 | unsigned long flags; | ||
| 71 | 96 | ||
| 97 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 72 | /* Locate matching device in database. */ | 98 | /* Locate matching device in database. */ |
| 73 | list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { | 99 | list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { |
| 74 | if (!memcmp(port_name, vha->port_name, WWN_SIZE)) | 100 | if (!memcmp(port_name, vha->port_name, WWN_SIZE)) { |
| 101 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 75 | return vha; | 102 | return vha; |
| 103 | } | ||
| 76 | } | 104 | } |
| 105 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 77 | return NULL; | 106 | return NULL; |
| 78 | } | 107 | } |
| 79 | 108 | ||
| @@ -93,6 +122,12 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) | |||
| 93 | static void | 122 | static void |
| 94 | qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) | 123 | qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) |
| 95 | { | 124 | { |
| 125 | /* | ||
| 126 | * !!! NOTE !!! | ||
| 127 | * This function, if called in contexts other than vp create, disable | ||
| 128 | * or delete, please make sure this is synchronized with the | ||
| 129 | * delete thread. | ||
| 130 | */ | ||
| 96 | fc_port_t *fcport; | 131 | fc_port_t *fcport; |
| 97 | 132 | ||
| 98 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 133 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
| @@ -100,7 +135,6 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) | |||
| 100 | "loop_id=0x%04x :%x\n", | 135 | "loop_id=0x%04x :%x\n", |
| 101 | vha->host_no, fcport->loop_id, fcport->vp_idx)); | 136 | vha->host_no, fcport->loop_id, fcport->vp_idx)); |
| 102 | 137 | ||
| 103 | atomic_set(&fcport->state, FCS_DEVICE_DEAD); | ||
| 104 | qla2x00_mark_device_lost(vha, fcport, 0, 0); | 138 | qla2x00_mark_device_lost(vha, fcport, 0, 0); |
| 105 | atomic_set(&fcport->state, FCS_UNCONFIGURED); | 139 | atomic_set(&fcport->state, FCS_UNCONFIGURED); |
| 106 | } | 140 | } |
| @@ -194,12 +228,17 @@ qla24xx_configure_vp(scsi_qla_host_t *vha) | |||
| 194 | void | 228 | void |
| 195 | qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) | 229 | qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) |
| 196 | { | 230 | { |
| 197 | scsi_qla_host_t *vha, *tvha; | 231 | scsi_qla_host_t *vha; |
| 198 | struct qla_hw_data *ha = rsp->hw; | 232 | struct qla_hw_data *ha = rsp->hw; |
| 199 | int i = 0; | 233 | int i = 0; |
| 234 | unsigned long flags; | ||
| 200 | 235 | ||
| 201 | list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { | 236 | spin_lock_irqsave(&ha->vport_slock, flags); |
| 237 | list_for_each_entry(vha, &ha->vp_list, list) { | ||
| 202 | if (vha->vp_idx) { | 238 | if (vha->vp_idx) { |
| 239 | atomic_inc(&vha->vref_count); | ||
| 240 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 241 | |||
| 203 | switch (mb[0]) { | 242 | switch (mb[0]) { |
| 204 | case MBA_LIP_OCCURRED: | 243 | case MBA_LIP_OCCURRED: |
| 205 | case MBA_LOOP_UP: | 244 | case MBA_LOOP_UP: |
| @@ -215,9 +254,13 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) | |||
| 215 | qla2x00_async_event(vha, rsp, mb); | 254 | qla2x00_async_event(vha, rsp, mb); |
| 216 | break; | 255 | break; |
| 217 | } | 256 | } |
| 257 | |||
| 258 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 259 | atomic_dec(&vha->vref_count); | ||
| 218 | } | 260 | } |
| 219 | i++; | 261 | i++; |
| 220 | } | 262 | } |
| 263 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 221 | } | 264 | } |
| 222 | 265 | ||
| 223 | int | 266 | int |
| @@ -297,7 +340,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) | |||
| 297 | int ret; | 340 | int ret; |
| 298 | struct qla_hw_data *ha = vha->hw; | 341 | struct qla_hw_data *ha = vha->hw; |
| 299 | scsi_qla_host_t *vp; | 342 | scsi_qla_host_t *vp; |
| 300 | struct scsi_qla_host *tvp; | 343 | unsigned long flags = 0; |
| 301 | 344 | ||
| 302 | if (vha->vp_idx) | 345 | if (vha->vp_idx) |
| 303 | return; | 346 | return; |
| @@ -309,10 +352,19 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) | |||
| 309 | if (!(ha->current_topology & ISP_CFG_F)) | 352 | if (!(ha->current_topology & ISP_CFG_F)) |
| 310 | return; | 353 | return; |
| 311 | 354 | ||
| 312 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 355 | spin_lock_irqsave(&ha->vport_slock, flags); |
| 313 | if (vp->vp_idx) | 356 | list_for_each_entry(vp, &ha->vp_list, list) { |
| 357 | if (vp->vp_idx) { | ||
| 358 | atomic_inc(&vp->vref_count); | ||
| 359 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 360 | |||
| 314 | ret = qla2x00_do_dpc_vp(vp); | 361 | ret = qla2x00_do_dpc_vp(vp); |
| 362 | |||
| 363 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 364 | atomic_dec(&vp->vref_count); | ||
| 365 | } | ||
| 315 | } | 366 | } |
| 367 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 316 | } | 368 | } |
| 317 | 369 | ||
| 318 | int | 370 | int |
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 915b77a6e193..0a71cc71eab2 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
| @@ -2672,6 +2672,19 @@ qla82xx_start_scsi(srb_t *sp) | |||
| 2672 | sufficient_dsds: | 2672 | sufficient_dsds: |
| 2673 | req_cnt = 1; | 2673 | req_cnt = 1; |
| 2674 | 2674 | ||
| 2675 | if (req->cnt < (req_cnt + 2)) { | ||
| 2676 | cnt = (uint16_t)RD_REG_DWORD_RELAXED( | ||
| 2677 | ®->req_q_out[0]); | ||
| 2678 | if (req->ring_index < cnt) | ||
| 2679 | req->cnt = cnt - req->ring_index; | ||
| 2680 | else | ||
| 2681 | req->cnt = req->length - | ||
| 2682 | (req->ring_index - cnt); | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | if (req->cnt < (req_cnt + 2)) | ||
| 2686 | goto queuing_error; | ||
| 2687 | |||
| 2675 | ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); | 2688 | ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); |
| 2676 | if (!sp->ctx) { | 2689 | if (!sp->ctx) { |
| 2677 | DEBUG(printk(KERN_INFO | 2690 | DEBUG(printk(KERN_INFO |
| @@ -3307,16 +3320,19 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha) | |||
| 3307 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3320 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
| 3308 | } | 3321 | } |
| 3309 | qla2xxx_wake_dpc(vha); | 3322 | qla2xxx_wake_dpc(vha); |
| 3323 | ha->flags.fw_hung = 1; | ||
| 3310 | if (ha->flags.mbox_busy) { | 3324 | if (ha->flags.mbox_busy) { |
| 3311 | ha->flags.fw_hung = 1; | ||
| 3312 | ha->flags.mbox_int = 1; | 3325 | ha->flags.mbox_int = 1; |
| 3313 | DEBUG2(qla_printk(KERN_ERR, ha, | 3326 | DEBUG2(qla_printk(KERN_ERR, ha, |
| 3314 | "Due to fw hung, doing premature " | 3327 | "Due to fw hung, doing premature " |
| 3315 | "completion of mbx command\n")); | 3328 | "completion of mbx command\n")); |
| 3316 | complete(&ha->mbx_intr_comp); | 3329 | if (test_bit(MBX_INTR_WAIT, |
| 3330 | &ha->mbx_cmd_flags)) | ||
| 3331 | complete(&ha->mbx_intr_comp); | ||
| 3317 | } | 3332 | } |
| 3318 | } | 3333 | } |
| 3319 | } | 3334 | } else |
| 3335 | vha->seconds_since_last_heartbeat = 0; | ||
| 3320 | vha->fw_heartbeat_counter = fw_heartbeat_counter; | 3336 | vha->fw_heartbeat_counter = fw_heartbeat_counter; |
| 3321 | } | 3337 | } |
| 3322 | 3338 | ||
| @@ -3418,13 +3434,15 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
| 3418 | "%s(): Adapter reset needed!\n", __func__); | 3434 | "%s(): Adapter reset needed!\n", __func__); |
| 3419 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3435 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
| 3420 | qla2xxx_wake_dpc(vha); | 3436 | qla2xxx_wake_dpc(vha); |
| 3437 | ha->flags.fw_hung = 1; | ||
| 3421 | if (ha->flags.mbox_busy) { | 3438 | if (ha->flags.mbox_busy) { |
| 3422 | ha->flags.fw_hung = 1; | ||
| 3423 | ha->flags.mbox_int = 1; | 3439 | ha->flags.mbox_int = 1; |
| 3424 | DEBUG2(qla_printk(KERN_ERR, ha, | 3440 | DEBUG2(qla_printk(KERN_ERR, ha, |
| 3425 | "Need reset, doing premature " | 3441 | "Need reset, doing premature " |
| 3426 | "completion of mbx command\n")); | 3442 | "completion of mbx command\n")); |
| 3427 | complete(&ha->mbx_intr_comp); | 3443 | if (test_bit(MBX_INTR_WAIT, |
| 3444 | &ha->mbx_cmd_flags)) | ||
| 3445 | complete(&ha->mbx_intr_comp); | ||
| 3428 | } | 3446 | } |
| 3429 | } else { | 3447 | } else { |
| 3430 | qla82xx_check_fw_alive(vha); | 3448 | qla82xx_check_fw_alive(vha); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8c80b49ac1c4..1e4bff695254 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -2341,16 +2341,28 @@ probe_out: | |||
| 2341 | static void | 2341 | static void |
| 2342 | qla2x00_remove_one(struct pci_dev *pdev) | 2342 | qla2x00_remove_one(struct pci_dev *pdev) |
| 2343 | { | 2343 | { |
| 2344 | scsi_qla_host_t *base_vha, *vha, *temp; | 2344 | scsi_qla_host_t *base_vha, *vha; |
| 2345 | struct qla_hw_data *ha; | 2345 | struct qla_hw_data *ha; |
| 2346 | unsigned long flags; | ||
| 2346 | 2347 | ||
| 2347 | base_vha = pci_get_drvdata(pdev); | 2348 | base_vha = pci_get_drvdata(pdev); |
| 2348 | ha = base_vha->hw; | 2349 | ha = base_vha->hw; |
| 2349 | 2350 | ||
| 2350 | list_for_each_entry_safe(vha, temp, &ha->vp_list, list) { | 2351 | spin_lock_irqsave(&ha->vport_slock, flags); |
| 2351 | if (vha && vha->fc_vport) | 2352 | list_for_each_entry(vha, &ha->vp_list, list) { |
| 2353 | atomic_inc(&vha->vref_count); | ||
| 2354 | |||
| 2355 | if (vha && vha->fc_vport) { | ||
| 2356 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 2357 | |||
| 2352 | fc_vport_terminate(vha->fc_vport); | 2358 | fc_vport_terminate(vha->fc_vport); |
| 2359 | |||
| 2360 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
| 2361 | } | ||
| 2362 | |||
| 2363 | atomic_dec(&vha->vref_count); | ||
| 2353 | } | 2364 | } |
| 2365 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
| 2354 | 2366 | ||
| 2355 | set_bit(UNLOADING, &base_vha->dpc_flags); | 2367 | set_bit(UNLOADING, &base_vha->dpc_flags); |
| 2356 | 2368 | ||
| @@ -2975,10 +2987,17 @@ static struct qla_work_evt * | |||
| 2975 | qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) | 2987 | qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) |
| 2976 | { | 2988 | { |
| 2977 | struct qla_work_evt *e; | 2989 | struct qla_work_evt *e; |
| 2990 | uint8_t bail; | ||
| 2991 | |||
| 2992 | QLA_VHA_MARK_BUSY(vha, bail); | ||
| 2993 | if (bail) | ||
| 2994 | return NULL; | ||
| 2978 | 2995 | ||
| 2979 | e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); | 2996 | e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); |
| 2980 | if (!e) | 2997 | if (!e) { |
| 2998 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
| 2981 | return NULL; | 2999 | return NULL; |
| 3000 | } | ||
| 2982 | 3001 | ||
| 2983 | INIT_LIST_HEAD(&e->list); | 3002 | INIT_LIST_HEAD(&e->list); |
| 2984 | e->type = type; | 3003 | e->type = type; |
| @@ -3135,6 +3154,9 @@ qla2x00_do_work(struct scsi_qla_host *vha) | |||
| 3135 | } | 3154 | } |
| 3136 | if (e->flags & QLA_EVT_FLAG_FREE) | 3155 | if (e->flags & QLA_EVT_FLAG_FREE) |
| 3137 | kfree(e); | 3156 | kfree(e); |
| 3157 | |||
| 3158 | /* For each work completed decrement vha ref count */ | ||
| 3159 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
| 3138 | } | 3160 | } |
| 3139 | } | 3161 | } |
| 3140 | 3162 | ||
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index e75ccb91317d..8edbccb3232d 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | /* | 7 | /* |
| 8 | * Driver version | 8 | * Driver version |
| 9 | */ | 9 | */ |
| 10 | #define QLA2XXX_VERSION "8.03.03-k0" | 10 | #define QLA2XXX_VERSION "8.03.04-k0" |
| 11 | 11 | ||
| 12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
| 13 | #define QLA_DRIVER_MINOR_VER 3 | 13 | #define QLA_DRIVER_MINOR_VER 3 |
| 14 | #define QLA_DRIVER_PATCH_VER 3 | 14 | #define QLA_DRIVER_PATCH_VER 4 |
| 15 | #define QLA_DRIVER_BETA_VER 0 | 15 | #define QLA_DRIVER_BETA_VER 0 |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9ade720422c6..ee02d3838a0a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -1011,8 +1011,8 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) | |||
| 1011 | 1011 | ||
| 1012 | err_exit: | 1012 | err_exit: |
| 1013 | scsi_release_buffers(cmd); | 1013 | scsi_release_buffers(cmd); |
| 1014 | scsi_put_command(cmd); | ||
| 1015 | cmd->request->special = NULL; | 1014 | cmd->request->special = NULL; |
| 1015 | scsi_put_command(cmd); | ||
| 1016 | return error; | 1016 | return error; |
| 1017 | } | 1017 | } |
| 1018 | EXPORT_SYMBOL(scsi_init_io); | 1018 | EXPORT_SYMBOL(scsi_init_io); |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2714becc2eaf..ffa0689ee840 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -870,7 +870,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) | |||
| 870 | 870 | ||
| 871 | SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); | 871 | SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); |
| 872 | 872 | ||
| 873 | if (atomic_dec_return(&sdkp->openers) && sdev->removable) { | 873 | if (atomic_dec_return(&sdkp->openers) == 0 && sdev->removable) { |
| 874 | if (scsi_block_when_processing_errors(sdev)) | 874 | if (scsi_block_when_processing_errors(sdev)) |
| 875 | scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); | 875 | scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); |
| 876 | } | 876 | } |
| @@ -2625,15 +2625,15 @@ module_exit(exit_sd); | |||
| 2625 | static void sd_print_sense_hdr(struct scsi_disk *sdkp, | 2625 | static void sd_print_sense_hdr(struct scsi_disk *sdkp, |
| 2626 | struct scsi_sense_hdr *sshdr) | 2626 | struct scsi_sense_hdr *sshdr) |
| 2627 | { | 2627 | { |
| 2628 | sd_printk(KERN_INFO, sdkp, ""); | 2628 | sd_printk(KERN_INFO, sdkp, " "); |
| 2629 | scsi_show_sense_hdr(sshdr); | 2629 | scsi_show_sense_hdr(sshdr); |
| 2630 | sd_printk(KERN_INFO, sdkp, ""); | 2630 | sd_printk(KERN_INFO, sdkp, " "); |
| 2631 | scsi_show_extd_sense(sshdr->asc, sshdr->ascq); | 2631 | scsi_show_extd_sense(sshdr->asc, sshdr->ascq); |
| 2632 | } | 2632 | } |
| 2633 | 2633 | ||
| 2634 | static void sd_print_result(struct scsi_disk *sdkp, int result) | 2634 | static void sd_print_result(struct scsi_disk *sdkp, int result) |
| 2635 | { | 2635 | { |
| 2636 | sd_printk(KERN_INFO, sdkp, ""); | 2636 | sd_printk(KERN_INFO, sdkp, " "); |
| 2637 | scsi_show_result(result); | 2637 | scsi_show_result(result); |
| 2638 | } | 2638 | } |
| 2639 | 2639 | ||
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a7bc8b7b09ac..2c3e89ddf069 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c | |||
| @@ -72,10 +72,7 @@ static void sym_printl_hex(u_char *p, int n) | |||
| 72 | 72 | ||
| 73 | static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg) | 73 | static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg) |
| 74 | { | 74 | { |
| 75 | if (label) | 75 | sym_print_addr(cp->cmd, "%s: ", label); |
| 76 | sym_print_addr(cp->cmd, "%s: ", label); | ||
| 77 | else | ||
| 78 | sym_print_addr(cp->cmd, ""); | ||
| 79 | 76 | ||
| 80 | spi_print_msg(msg); | 77 | spi_print_msg(msg); |
| 81 | printf("\n"); | 78 | printf("\n"); |
| @@ -4558,7 +4555,8 @@ static void sym_int_sir(struct sym_hcb *np) | |||
| 4558 | switch (np->msgin [2]) { | 4555 | switch (np->msgin [2]) { |
| 4559 | case M_X_MODIFY_DP: | 4556 | case M_X_MODIFY_DP: |
| 4560 | if (DEBUG_FLAGS & DEBUG_POINTER) | 4557 | if (DEBUG_FLAGS & DEBUG_POINTER) |
| 4561 | sym_print_msg(cp, NULL, np->msgin); | 4558 | sym_print_msg(cp, "extended msg ", |
| 4559 | np->msgin); | ||
| 4562 | tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) + | 4560 | tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) + |
| 4563 | (np->msgin[5]<<8) + (np->msgin[6]); | 4561 | (np->msgin[5]<<8) + (np->msgin[6]); |
| 4564 | sym_modify_dp(np, tp, cp, tmp); | 4562 | sym_modify_dp(np, tp, cp, tmp); |
| @@ -4585,7 +4583,7 @@ static void sym_int_sir(struct sym_hcb *np) | |||
| 4585 | */ | 4583 | */ |
| 4586 | case M_IGN_RESIDUE: | 4584 | case M_IGN_RESIDUE: |
| 4587 | if (DEBUG_FLAGS & DEBUG_POINTER) | 4585 | if (DEBUG_FLAGS & DEBUG_POINTER) |
| 4588 | sym_print_msg(cp, NULL, np->msgin); | 4586 | sym_print_msg(cp, "1 or 2 byte ", np->msgin); |
| 4589 | if (cp->host_flags & HF_SENSE) | 4587 | if (cp->host_flags & HF_SENSE) |
| 4590 | OUTL_DSP(np, SCRIPTA_BA(np, clrack)); | 4588 | OUTL_DSP(np, SCRIPTA_BA(np, clrack)); |
| 4591 | else | 4589 | else |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 8dedb266f143..c4399e23565a 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
| @@ -500,6 +500,7 @@ static int __init mpc512x_psc_fifoc_init(void) | |||
| 500 | psc_fifoc = of_iomap(np, 0); | 500 | psc_fifoc = of_iomap(np, 0); |
| 501 | if (!psc_fifoc) { | 501 | if (!psc_fifoc) { |
| 502 | pr_err("%s: Can't map FIFOC\n", __func__); | 502 | pr_err("%s: Can't map FIFOC\n", __func__); |
| 503 | of_node_put(np); | ||
| 503 | return -ENODEV; | 504 | return -ENODEV; |
| 504 | } | 505 | } |
| 505 | 506 | ||
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 141c69554bd4..7d475b2a79e8 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
| @@ -335,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link) | |||
| 335 | info->p_dev = link; | 335 | info->p_dev = link; |
| 336 | link->priv = info; | 336 | link->priv = info; |
| 337 | 337 | ||
| 338 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
| 339 | link->resource[0]->end = 8; | ||
| 340 | link->conf.Attributes = CONF_ENABLE_IRQ; | 338 | link->conf.Attributes = CONF_ENABLE_IRQ; |
| 341 | if (do_sound) { | 339 | if (do_sound) { |
| 342 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 340 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
| @@ -411,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
| 411 | 409 | ||
| 412 | /*====================================================================*/ | 410 | /*====================================================================*/ |
| 413 | 411 | ||
| 412 | static int pfc_config(struct pcmcia_device *p_dev) | ||
| 413 | { | ||
| 414 | unsigned int port = 0; | ||
| 415 | struct serial_info *info = p_dev->priv; | ||
| 416 | |||
| 417 | if ((p_dev->resource[1]->end != 0) && | ||
| 418 | (resource_size(p_dev->resource[1]) == 8)) { | ||
| 419 | port = p_dev->resource[1]->start; | ||
| 420 | info->slave = 1; | ||
| 421 | } else if ((info->manfid == MANFID_OSITECH) && | ||
| 422 | (resource_size(p_dev->resource[0]) == 0x40)) { | ||
| 423 | port = p_dev->resource[0]->start + 0x28; | ||
| 424 | info->slave = 1; | ||
| 425 | } | ||
| 426 | if (info->slave) | ||
| 427 | return setup_serial(p_dev, info, port, p_dev->irq); | ||
| 428 | |||
| 429 | dev_warn(&p_dev->dev, "no usable port range found, giving up\n"); | ||
| 430 | return -ENODEV; | ||
| 431 | } | ||
| 432 | |||
| 414 | static int simple_config_check(struct pcmcia_device *p_dev, | 433 | static int simple_config_check(struct pcmcia_device *p_dev, |
| 415 | cistpl_cftable_entry_t *cf, | 434 | cistpl_cftable_entry_t *cf, |
| 416 | cistpl_cftable_entry_t *dflt, | 435 | cistpl_cftable_entry_t *dflt, |
| @@ -461,23 +480,8 @@ static int simple_config(struct pcmcia_device *link) | |||
| 461 | struct serial_info *info = link->priv; | 480 | struct serial_info *info = link->priv; |
| 462 | int i = -ENODEV, try; | 481 | int i = -ENODEV, try; |
| 463 | 482 | ||
| 464 | /* If the card is already configured, look up the port and irq */ | 483 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
| 465 | if (link->function_config) { | 484 | link->resource[0]->end = 8; |
| 466 | unsigned int port = 0; | ||
| 467 | if ((link->resource[1]->end != 0) && | ||
| 468 | (resource_size(link->resource[1]) == 8)) { | ||
| 469 | port = link->resource[1]->end; | ||
| 470 | info->slave = 1; | ||
| 471 | } else if ((info->manfid == MANFID_OSITECH) && | ||
| 472 | (resource_size(link->resource[0]) == 0x40)) { | ||
| 473 | port = link->resource[0]->start + 0x28; | ||
| 474 | info->slave = 1; | ||
| 475 | } | ||
| 476 | if (info->slave) { | ||
| 477 | return setup_serial(link, info, port, | ||
| 478 | link->irq); | ||
| 479 | } | ||
| 480 | } | ||
| 481 | 485 | ||
| 482 | /* First pass: look for a config entry that looks normal. | 486 | /* First pass: look for a config entry that looks normal. |
| 483 | * Two tries: without IO aliases, then with aliases */ | 487 | * Two tries: without IO aliases, then with aliases */ |
| @@ -491,8 +495,7 @@ static int simple_config(struct pcmcia_device *link) | |||
| 491 | if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) | 495 | if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) |
| 492 | goto found_port; | 496 | goto found_port; |
| 493 | 497 | ||
| 494 | printk(KERN_NOTICE | 498 | dev_warn(&link->dev, "no usable port range found, giving up\n"); |
| 495 | "serial_cs: no usable port range found, giving up\n"); | ||
| 496 | return -1; | 499 | return -1; |
| 497 | 500 | ||
| 498 | found_port: | 501 | found_port: |
| @@ -558,6 +561,7 @@ static int multi_config(struct pcmcia_device *link) | |||
| 558 | int i, base2 = 0; | 561 | int i, base2 = 0; |
| 559 | 562 | ||
| 560 | /* First, look for a generic full-sized window */ | 563 | /* First, look for a generic full-sized window */ |
| 564 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | ||
| 561 | link->resource[0]->end = info->multi * 8; | 565 | link->resource[0]->end = info->multi * 8; |
| 562 | if (pcmcia_loop_config(link, multi_config_check, &base2)) { | 566 | if (pcmcia_loop_config(link, multi_config_check, &base2)) { |
| 563 | /* If that didn't work, look for two windows */ | 567 | /* If that didn't work, look for two windows */ |
| @@ -565,15 +569,14 @@ static int multi_config(struct pcmcia_device *link) | |||
| 565 | info->multi = 2; | 569 | info->multi = 2; |
| 566 | if (pcmcia_loop_config(link, multi_config_check_notpicky, | 570 | if (pcmcia_loop_config(link, multi_config_check_notpicky, |
| 567 | &base2)) { | 571 | &base2)) { |
| 568 | printk(KERN_NOTICE "serial_cs: no usable port range" | 572 | dev_warn(&link->dev, "no usable port range " |
| 569 | "found, giving up\n"); | 573 | "found, giving up\n"); |
| 570 | return -ENODEV; | 574 | return -ENODEV; |
| 571 | } | 575 | } |
| 572 | } | 576 | } |
| 573 | 577 | ||
| 574 | if (!link->irq) | 578 | if (!link->irq) |
| 575 | dev_warn(&link->dev, | 579 | dev_warn(&link->dev, "no usable IRQ found, continuing...\n"); |
| 576 | "serial_cs: no usable IRQ found, continuing...\n"); | ||
| 577 | 580 | ||
| 578 | /* | 581 | /* |
| 579 | * Apply any configuration quirks. | 582 | * Apply any configuration quirks. |
| @@ -675,6 +678,7 @@ static int serial_config(struct pcmcia_device * link) | |||
| 675 | multifunction cards that ask for appropriate IO port ranges */ | 678 | multifunction cards that ask for appropriate IO port ranges */ |
| 676 | if ((info->multi == 0) && | 679 | if ((info->multi == 0) && |
| 677 | (link->has_func_id) && | 680 | (link->has_func_id) && |
| 681 | (link->socket->pcmcia_pfc == 0) && | ||
| 678 | ((link->func_id == CISTPL_FUNCID_MULTI) || | 682 | ((link->func_id == CISTPL_FUNCID_MULTI) || |
| 679 | (link->func_id == CISTPL_FUNCID_SERIAL))) | 683 | (link->func_id == CISTPL_FUNCID_SERIAL))) |
| 680 | pcmcia_loop_config(link, serial_check_for_multi, info); | 684 | pcmcia_loop_config(link, serial_check_for_multi, info); |
| @@ -685,7 +689,13 @@ static int serial_config(struct pcmcia_device * link) | |||
| 685 | if (info->quirk && info->quirk->multi != -1) | 689 | if (info->quirk && info->quirk->multi != -1) |
| 686 | info->multi = info->quirk->multi; | 690 | info->multi = info->quirk->multi; |
| 687 | 691 | ||
| 688 | if (info->multi > 1) | 692 | dev_info(&link->dev, |
| 693 | "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n", | ||
| 694 | link->manf_id, link->card_id, | ||
| 695 | link->socket->pcmcia_pfc, info->multi, info->quirk); | ||
| 696 | if (link->socket->pcmcia_pfc) | ||
| 697 | i = pfc_config(link); | ||
| 698 | else if (info->multi > 1) | ||
| 689 | i = multi_config(link); | 699 | i = multi_config(link); |
| 690 | else | 700 | else |
| 691 | i = simple_config(link); | 701 | i = simple_config(link); |
| @@ -704,7 +714,7 @@ static int serial_config(struct pcmcia_device * link) | |||
| 704 | return 0; | 714 | return 0; |
| 705 | 715 | ||
| 706 | failed: | 716 | failed: |
| 707 | dev_warn(&link->dev, "serial_cs: failed to initialize\n"); | 717 | dev_warn(&link->dev, "failed to initialize\n"); |
| 708 | serial_remove(link); | 718 | serial_remove(link); |
| 709 | return -ENODEV; | 719 | return -ENODEV; |
| 710 | } | 720 | } |
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index acd35d1ebd12..4c37c4e28647 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
| @@ -503,8 +503,9 @@ static void giveback(struct pl022 *pl022) | |||
| 503 | msg->state = NULL; | 503 | msg->state = NULL; |
| 504 | if (msg->complete) | 504 | if (msg->complete) |
| 505 | msg->complete(msg->context); | 505 | msg->complete(msg->context); |
| 506 | /* This message is completed, so let's turn off the clock! */ | 506 | /* This message is completed, so let's turn off the clocks! */ |
| 507 | clk_disable(pl022->clk); | 507 | clk_disable(pl022->clk); |
| 508 | amba_pclk_disable(pl022->adev); | ||
| 508 | } | 509 | } |
| 509 | 510 | ||
| 510 | /** | 511 | /** |
| @@ -1139,9 +1140,10 @@ static void pump_messages(struct work_struct *work) | |||
| 1139 | /* Setup the SPI using the per chip configuration */ | 1140 | /* Setup the SPI using the per chip configuration */ |
| 1140 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | 1141 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); |
| 1141 | /* | 1142 | /* |
| 1142 | * We enable the clock here, then the clock will be disabled when | 1143 | * We enable the clocks here, then the clocks will be disabled when |
| 1143 | * giveback() is called in each method (poll/interrupt/DMA) | 1144 | * giveback() is called in each method (poll/interrupt/DMA) |
| 1144 | */ | 1145 | */ |
| 1146 | amba_pclk_enable(pl022->adev); | ||
| 1145 | clk_enable(pl022->clk); | 1147 | clk_enable(pl022->clk); |
| 1146 | restore_state(pl022); | 1148 | restore_state(pl022); |
| 1147 | flush(pl022); | 1149 | flush(pl022); |
| @@ -1786,11 +1788,9 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
| 1786 | } | 1788 | } |
| 1787 | 1789 | ||
| 1788 | /* Disable SSP */ | 1790 | /* Disable SSP */ |
| 1789 | clk_enable(pl022->clk); | ||
| 1790 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), | 1791 | writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), |
| 1791 | SSP_CR1(pl022->virtbase)); | 1792 | SSP_CR1(pl022->virtbase)); |
| 1792 | load_ssp_default_config(pl022); | 1793 | load_ssp_default_config(pl022); |
| 1793 | clk_disable(pl022->clk); | ||
| 1794 | 1794 | ||
| 1795 | status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", | 1795 | status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", |
| 1796 | pl022); | 1796 | pl022); |
| @@ -1818,6 +1818,8 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) | |||
| 1818 | goto err_spi_register; | 1818 | goto err_spi_register; |
| 1819 | } | 1819 | } |
| 1820 | dev_dbg(dev, "probe succeded\n"); | 1820 | dev_dbg(dev, "probe succeded\n"); |
| 1821 | /* Disable the silicon block pclk and clock it when needed */ | ||
| 1822 | amba_pclk_disable(adev); | ||
| 1821 | return 0; | 1823 | return 0; |
| 1822 | 1824 | ||
| 1823 | err_spi_register: | 1825 | err_spi_register: |
| @@ -1879,9 +1881,9 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state) | |||
| 1879 | return status; | 1881 | return status; |
| 1880 | } | 1882 | } |
| 1881 | 1883 | ||
| 1882 | clk_enable(pl022->clk); | 1884 | amba_pclk_enable(adev); |
| 1883 | load_ssp_default_config(pl022); | 1885 | load_ssp_default_config(pl022); |
| 1884 | clk_disable(pl022->clk); | 1886 | amba_pclk_disable(adev); |
| 1885 | dev_dbg(&adev->dev, "suspended\n"); | 1887 | dev_dbg(&adev->dev, "suspended\n"); |
| 1886 | return 0; | 1888 | return 0; |
| 1887 | } | 1889 | } |
| @@ -1981,7 +1983,7 @@ static int __init pl022_init(void) | |||
| 1981 | return amba_driver_register(&pl022_driver); | 1983 | return amba_driver_register(&pl022_driver); |
| 1982 | } | 1984 | } |
| 1983 | 1985 | ||
| 1984 | module_init(pl022_init); | 1986 | subsys_initcall(pl022_init); |
| 1985 | 1987 | ||
| 1986 | static void __exit pl022_exit(void) | 1988 | static void __exit pl022_exit(void) |
| 1987 | { | 1989 | { |
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index d256cb00604c..56247853c298 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c | |||
| @@ -181,10 +181,6 @@ static void flush(struct dw_spi *dws) | |||
| 181 | wait_till_not_busy(dws); | 181 | wait_till_not_busy(dws); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static void null_cs_control(u32 command) | ||
| 185 | { | ||
| 186 | } | ||
| 187 | |||
| 188 | static int null_writer(struct dw_spi *dws) | 184 | static int null_writer(struct dw_spi *dws) |
| 189 | { | 185 | { |
| 190 | u8 n_bytes = dws->n_bytes; | 186 | u8 n_bytes = dws->n_bytes; |
| @@ -322,7 +318,7 @@ static void giveback(struct dw_spi *dws) | |||
| 322 | struct spi_transfer, | 318 | struct spi_transfer, |
| 323 | transfer_list); | 319 | transfer_list); |
| 324 | 320 | ||
| 325 | if (!last_transfer->cs_change) | 321 | if (!last_transfer->cs_change && dws->cs_control) |
| 326 | dws->cs_control(MRST_SPI_DEASSERT); | 322 | dws->cs_control(MRST_SPI_DEASSERT); |
| 327 | 323 | ||
| 328 | msg->state = NULL; | 324 | msg->state = NULL; |
| @@ -396,6 +392,11 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) | |||
| 396 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) | 392 | static irqreturn_t dw_spi_irq(int irq, void *dev_id) |
| 397 | { | 393 | { |
| 398 | struct dw_spi *dws = dev_id; | 394 | struct dw_spi *dws = dev_id; |
| 395 | u16 irq_status, irq_mask = 0x3f; | ||
| 396 | |||
| 397 | irq_status = dw_readw(dws, isr) & irq_mask; | ||
| 398 | if (!irq_status) | ||
| 399 | return IRQ_NONE; | ||
| 399 | 400 | ||
| 400 | if (!dws->cur_msg) { | 401 | if (!dws->cur_msg) { |
| 401 | spi_mask_intr(dws, SPI_INT_TXEI); | 402 | spi_mask_intr(dws, SPI_INT_TXEI); |
| @@ -544,13 +545,13 @@ static void pump_transfers(unsigned long data) | |||
| 544 | */ | 545 | */ |
| 545 | if (dws->cs_control) { | 546 | if (dws->cs_control) { |
| 546 | if (dws->rx && dws->tx) | 547 | if (dws->rx && dws->tx) |
| 547 | chip->tmode = 0x00; | 548 | chip->tmode = SPI_TMOD_TR; |
| 548 | else if (dws->rx) | 549 | else if (dws->rx) |
| 549 | chip->tmode = 0x02; | 550 | chip->tmode = SPI_TMOD_RO; |
| 550 | else | 551 | else |
| 551 | chip->tmode = 0x01; | 552 | chip->tmode = SPI_TMOD_TO; |
| 552 | 553 | ||
| 553 | cr0 &= ~(0x3 << SPI_MODE_OFFSET); | 554 | cr0 &= ~SPI_TMOD_MASK; |
| 554 | cr0 |= (chip->tmode << SPI_TMOD_OFFSET); | 555 | cr0 |= (chip->tmode << SPI_TMOD_OFFSET); |
| 555 | } | 556 | } |
| 556 | 557 | ||
| @@ -699,9 +700,6 @@ static int dw_spi_setup(struct spi_device *spi) | |||
| 699 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); | 700 | chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); |
| 700 | if (!chip) | 701 | if (!chip) |
| 701 | return -ENOMEM; | 702 | return -ENOMEM; |
| 702 | |||
| 703 | chip->cs_control = null_cs_control; | ||
| 704 | chip->enable_dma = 0; | ||
| 705 | } | 703 | } |
| 706 | 704 | ||
| 707 | /* | 705 | /* |
| @@ -883,7 +881,7 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) | |||
| 883 | dws->dma_inited = 0; | 881 | dws->dma_inited = 0; |
| 884 | dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); | 882 | dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); |
| 885 | 883 | ||
| 886 | ret = request_irq(dws->irq, dw_spi_irq, 0, | 884 | ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, |
| 887 | "dw_spi", dws); | 885 | "dw_spi", dws); |
| 888 | if (ret < 0) { | 886 | if (ret < 0) { |
| 889 | dev_err(&master->dev, "can not get IRQ\n"); | 887 | dev_err(&master->dev, "can not get IRQ\n"); |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a9e5c79ae52a..0bcf4c1601a2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -554,11 +554,9 @@ done: | |||
| 554 | EXPORT_SYMBOL_GPL(spi_register_master); | 554 | EXPORT_SYMBOL_GPL(spi_register_master); |
| 555 | 555 | ||
| 556 | 556 | ||
| 557 | static int __unregister(struct device *dev, void *master_dev) | 557 | static int __unregister(struct device *dev, void *null) |
| 558 | { | 558 | { |
| 559 | /* note: before about 2.6.14-rc1 this would corrupt memory: */ | 559 | spi_unregister_device(to_spi_device(dev)); |
| 560 | if (dev != master_dev) | ||
| 561 | spi_unregister_device(to_spi_device(dev)); | ||
| 562 | return 0; | 560 | return 0; |
| 563 | } | 561 | } |
| 564 | 562 | ||
| @@ -576,8 +574,7 @@ void spi_unregister_master(struct spi_master *master) | |||
| 576 | { | 574 | { |
| 577 | int dummy; | 575 | int dummy; |
| 578 | 576 | ||
| 579 | dummy = device_for_each_child(master->dev.parent, &master->dev, | 577 | dummy = device_for_each_child(&master->dev, NULL, __unregister); |
| 580 | __unregister); | ||
| 581 | device_unregister(&master->dev); | 578 | device_unregister(&master->dev); |
| 582 | } | 579 | } |
| 583 | EXPORT_SYMBOL_GPL(spi_unregister_master); | 580 | EXPORT_SYMBOL_GPL(spi_unregister_master); |
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c index 97365815a729..c3038da2648a 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi_s3c64xx.c | |||
| @@ -200,6 +200,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
| 200 | val = readl(regs + S3C64XX_SPI_STATUS); | 200 | val = readl(regs + S3C64XX_SPI_STATUS); |
| 201 | } while (TX_FIFO_LVL(val, sci) && loops--); | 201 | } while (TX_FIFO_LVL(val, sci) && loops--); |
| 202 | 202 | ||
| 203 | if (loops == 0) | ||
| 204 | dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n"); | ||
| 205 | |||
| 203 | /* Flush RxFIFO*/ | 206 | /* Flush RxFIFO*/ |
| 204 | loops = msecs_to_loops(1); | 207 | loops = msecs_to_loops(1); |
| 205 | do { | 208 | do { |
| @@ -210,6 +213,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
| 210 | break; | 213 | break; |
| 211 | } while (loops--); | 214 | } while (loops--); |
| 212 | 215 | ||
| 216 | if (loops == 0) | ||
| 217 | dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n"); | ||
| 218 | |||
| 213 | val = readl(regs + S3C64XX_SPI_CH_CFG); | 219 | val = readl(regs + S3C64XX_SPI_CH_CFG); |
| 214 | val &= ~S3C64XX_SPI_CH_SW_RST; | 220 | val &= ~S3C64XX_SPI_CH_SW_RST; |
| 215 | writel(val, regs + S3C64XX_SPI_CH_CFG); | 221 | writel(val, regs + S3C64XX_SPI_CH_CFG); |
| @@ -320,16 +326,17 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, | |||
| 320 | 326 | ||
| 321 | /* millisecs to xfer 'len' bytes @ 'cur_speed' */ | 327 | /* millisecs to xfer 'len' bytes @ 'cur_speed' */ |
| 322 | ms = xfer->len * 8 * 1000 / sdd->cur_speed; | 328 | ms = xfer->len * 8 * 1000 / sdd->cur_speed; |
| 323 | ms += 5; /* some tolerance */ | 329 | ms += 10; /* some tolerance */ |
| 324 | 330 | ||
| 325 | if (dma_mode) { | 331 | if (dma_mode) { |
| 326 | val = msecs_to_jiffies(ms) + 10; | 332 | val = msecs_to_jiffies(ms) + 10; |
| 327 | val = wait_for_completion_timeout(&sdd->xfer_completion, val); | 333 | val = wait_for_completion_timeout(&sdd->xfer_completion, val); |
| 328 | } else { | 334 | } else { |
| 335 | u32 status; | ||
| 329 | val = msecs_to_loops(ms); | 336 | val = msecs_to_loops(ms); |
| 330 | do { | 337 | do { |
| 331 | val = readl(regs + S3C64XX_SPI_STATUS); | 338 | status = readl(regs + S3C64XX_SPI_STATUS); |
| 332 | } while (RX_FIFO_LVL(val, sci) < xfer->len && --val); | 339 | } while (RX_FIFO_LVL(status, sci) < xfer->len && --val); |
| 333 | } | 340 | } |
| 334 | 341 | ||
| 335 | if (!val) | 342 | if (!val) |
| @@ -447,8 +454,8 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) | |||
| 447 | writel(val, regs + S3C64XX_SPI_CLK_CFG); | 454 | writel(val, regs + S3C64XX_SPI_CLK_CFG); |
| 448 | } | 455 | } |
| 449 | 456 | ||
| 450 | void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, | 457 | static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, |
| 451 | int size, enum s3c2410_dma_buffresult res) | 458 | int size, enum s3c2410_dma_buffresult res) |
| 452 | { | 459 | { |
| 453 | struct s3c64xx_spi_driver_data *sdd = buf_id; | 460 | struct s3c64xx_spi_driver_data *sdd = buf_id; |
| 454 | unsigned long flags; | 461 | unsigned long flags; |
| @@ -467,8 +474,8 @@ void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, | |||
| 467 | spin_unlock_irqrestore(&sdd->lock, flags); | 474 | spin_unlock_irqrestore(&sdd->lock, flags); |
| 468 | } | 475 | } |
| 469 | 476 | ||
| 470 | void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, | 477 | static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, |
| 471 | int size, enum s3c2410_dma_buffresult res) | 478 | int size, enum s3c2410_dma_buffresult res) |
| 472 | { | 479 | { |
| 473 | struct s3c64xx_spi_driver_data *sdd = buf_id; | 480 | struct s3c64xx_spi_driver_data *sdd = buf_id; |
| 474 | unsigned long flags; | 481 | unsigned long flags; |
| @@ -508,8 +515,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, | |||
| 508 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 515 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
| 509 | 516 | ||
| 510 | if (xfer->tx_buf != NULL) { | 517 | if (xfer->tx_buf != NULL) { |
| 511 | xfer->tx_dma = dma_map_single(dev, xfer->tx_buf, | 518 | xfer->tx_dma = dma_map_single(dev, |
| 512 | xfer->len, DMA_TO_DEVICE); | 519 | (void *)xfer->tx_buf, xfer->len, |
| 520 | DMA_TO_DEVICE); | ||
| 513 | if (dma_mapping_error(dev, xfer->tx_dma)) { | 521 | if (dma_mapping_error(dev, xfer->tx_dma)) { |
| 514 | dev_err(dev, "dma_map_single Tx failed\n"); | 522 | dev_err(dev, "dma_map_single Tx failed\n"); |
| 515 | xfer->tx_dma = XFER_DMAADDR_INVALID; | 523 | xfer->tx_dma = XFER_DMAADDR_INVALID; |
| @@ -919,6 +927,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
| 919 | return -ENODEV; | 927 | return -ENODEV; |
| 920 | } | 928 | } |
| 921 | 929 | ||
| 930 | sci = pdev->dev.platform_data; | ||
| 931 | if (!sci->src_clk_name) { | ||
| 932 | dev_err(&pdev->dev, | ||
| 933 | "Board init must call s3c64xx_spi_set_info()\n"); | ||
| 934 | return -EINVAL; | ||
| 935 | } | ||
| 936 | |||
| 922 | /* Check for availability of necessary resource */ | 937 | /* Check for availability of necessary resource */ |
| 923 | 938 | ||
| 924 | dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 939 | dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
| @@ -946,8 +961,6 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
| 946 | return -ENOMEM; | 961 | return -ENOMEM; |
| 947 | } | 962 | } |
| 948 | 963 | ||
| 949 | sci = pdev->dev.platform_data; | ||
| 950 | |||
| 951 | platform_set_drvdata(pdev, master); | 964 | platform_set_drvdata(pdev, master); |
| 952 | 965 | ||
| 953 | sdd = spi_master_get_devdata(master); | 966 | sdd = spi_master_get_devdata(master); |
| @@ -1170,7 +1183,7 @@ static int __init s3c64xx_spi_init(void) | |||
| 1170 | { | 1183 | { |
| 1171 | return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); | 1184 | return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); |
| 1172 | } | 1185 | } |
| 1173 | module_init(s3c64xx_spi_init); | 1186 | subsys_initcall(s3c64xx_spi_init); |
| 1174 | 1187 | ||
| 1175 | static void __exit s3c64xx_spi_exit(void) | 1188 | static void __exit s3c64xx_spi_exit(void) |
| 1176 | { | 1189 | { |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 4b99117f3ecd..c579dcc9200c 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
| @@ -60,22 +60,25 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync, | |||
| 60 | return 0; | 60 | return 0; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn) | ||
| 64 | { | ||
| 65 | INIT_LIST_HEAD(&work->node); | ||
| 66 | work->fn = fn; | ||
| 67 | init_waitqueue_head(&work->done); | ||
| 68 | work->flushing = 0; | ||
| 69 | work->queue_seq = work->done_seq = 0; | ||
| 70 | } | ||
| 71 | |||
| 63 | /* Init poll structure */ | 72 | /* Init poll structure */ |
| 64 | void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, | 73 | void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, |
| 65 | unsigned long mask, struct vhost_dev *dev) | 74 | unsigned long mask, struct vhost_dev *dev) |
| 66 | { | 75 | { |
| 67 | struct vhost_work *work = &poll->work; | ||
| 68 | |||
| 69 | init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); | 76 | init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); |
| 70 | init_poll_funcptr(&poll->table, vhost_poll_func); | 77 | init_poll_funcptr(&poll->table, vhost_poll_func); |
| 71 | poll->mask = mask; | 78 | poll->mask = mask; |
| 72 | poll->dev = dev; | 79 | poll->dev = dev; |
| 73 | 80 | ||
| 74 | INIT_LIST_HEAD(&work->node); | 81 | vhost_work_init(&poll->work, fn); |
| 75 | work->fn = fn; | ||
| 76 | init_waitqueue_head(&work->done); | ||
| 77 | work->flushing = 0; | ||
| 78 | work->queue_seq = work->done_seq = 0; | ||
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | /* Start polling a file. We add ourselves to file's wait queue. The caller must | 84 | /* Start polling a file. We add ourselves to file's wait queue. The caller must |
| @@ -95,35 +98,38 @@ void vhost_poll_stop(struct vhost_poll *poll) | |||
| 95 | remove_wait_queue(poll->wqh, &poll->wait); | 98 | remove_wait_queue(poll->wqh, &poll->wait); |
| 96 | } | 99 | } |
| 97 | 100 | ||
| 98 | /* Flush any work that has been scheduled. When calling this, don't hold any | 101 | static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) |
| 99 | * locks that are also used by the callback. */ | ||
| 100 | void vhost_poll_flush(struct vhost_poll *poll) | ||
| 101 | { | 102 | { |
| 102 | struct vhost_work *work = &poll->work; | ||
| 103 | unsigned seq; | 103 | unsigned seq; |
| 104 | int left; | 104 | int left; |
| 105 | int flushing; | 105 | int flushing; |
| 106 | 106 | ||
| 107 | spin_lock_irq(&poll->dev->work_lock); | 107 | spin_lock_irq(&dev->work_lock); |
| 108 | seq = work->queue_seq; | 108 | seq = work->queue_seq; |
| 109 | work->flushing++; | 109 | work->flushing++; |
| 110 | spin_unlock_irq(&poll->dev->work_lock); | 110 | spin_unlock_irq(&dev->work_lock); |
| 111 | wait_event(work->done, ({ | 111 | wait_event(work->done, ({ |
| 112 | spin_lock_irq(&poll->dev->work_lock); | 112 | spin_lock_irq(&dev->work_lock); |
| 113 | left = seq - work->done_seq <= 0; | 113 | left = seq - work->done_seq <= 0; |
| 114 | spin_unlock_irq(&poll->dev->work_lock); | 114 | spin_unlock_irq(&dev->work_lock); |
| 115 | left; | 115 | left; |
| 116 | })); | 116 | })); |
| 117 | spin_lock_irq(&poll->dev->work_lock); | 117 | spin_lock_irq(&dev->work_lock); |
| 118 | flushing = --work->flushing; | 118 | flushing = --work->flushing; |
| 119 | spin_unlock_irq(&poll->dev->work_lock); | 119 | spin_unlock_irq(&dev->work_lock); |
| 120 | BUG_ON(flushing < 0); | 120 | BUG_ON(flushing < 0); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | void vhost_poll_queue(struct vhost_poll *poll) | 123 | /* Flush any work that has been scheduled. When calling this, don't hold any |
| 124 | * locks that are also used by the callback. */ | ||
| 125 | void vhost_poll_flush(struct vhost_poll *poll) | ||
| 126 | { | ||
| 127 | vhost_work_flush(poll->dev, &poll->work); | ||
| 128 | } | ||
| 129 | |||
| 130 | static inline void vhost_work_queue(struct vhost_dev *dev, | ||
| 131 | struct vhost_work *work) | ||
| 124 | { | 132 | { |
| 125 | struct vhost_dev *dev = poll->dev; | ||
| 126 | struct vhost_work *work = &poll->work; | ||
| 127 | unsigned long flags; | 133 | unsigned long flags; |
| 128 | 134 | ||
| 129 | spin_lock_irqsave(&dev->work_lock, flags); | 135 | spin_lock_irqsave(&dev->work_lock, flags); |
| @@ -135,6 +141,11 @@ void vhost_poll_queue(struct vhost_poll *poll) | |||
| 135 | spin_unlock_irqrestore(&dev->work_lock, flags); | 141 | spin_unlock_irqrestore(&dev->work_lock, flags); |
| 136 | } | 142 | } |
| 137 | 143 | ||
| 144 | void vhost_poll_queue(struct vhost_poll *poll) | ||
| 145 | { | ||
| 146 | vhost_work_queue(poll->dev, &poll->work); | ||
| 147 | } | ||
| 148 | |||
| 138 | static void vhost_vq_reset(struct vhost_dev *dev, | 149 | static void vhost_vq_reset(struct vhost_dev *dev, |
| 139 | struct vhost_virtqueue *vq) | 150 | struct vhost_virtqueue *vq) |
| 140 | { | 151 | { |
| @@ -236,6 +247,29 @@ long vhost_dev_check_owner(struct vhost_dev *dev) | |||
| 236 | return dev->mm == current->mm ? 0 : -EPERM; | 247 | return dev->mm == current->mm ? 0 : -EPERM; |
| 237 | } | 248 | } |
| 238 | 249 | ||
| 250 | struct vhost_attach_cgroups_struct { | ||
| 251 | struct vhost_work work; | ||
| 252 | struct task_struct *owner; | ||
| 253 | int ret; | ||
| 254 | }; | ||
| 255 | |||
| 256 | static void vhost_attach_cgroups_work(struct vhost_work *work) | ||
| 257 | { | ||
| 258 | struct vhost_attach_cgroups_struct *s; | ||
| 259 | s = container_of(work, struct vhost_attach_cgroups_struct, work); | ||
| 260 | s->ret = cgroup_attach_task_all(s->owner, current); | ||
| 261 | } | ||
| 262 | |||
| 263 | static int vhost_attach_cgroups(struct vhost_dev *dev) | ||
| 264 | { | ||
| 265 | struct vhost_attach_cgroups_struct attach; | ||
| 266 | attach.owner = current; | ||
| 267 | vhost_work_init(&attach.work, vhost_attach_cgroups_work); | ||
| 268 | vhost_work_queue(dev, &attach.work); | ||
| 269 | vhost_work_flush(dev, &attach.work); | ||
| 270 | return attach.ret; | ||
| 271 | } | ||
| 272 | |||
| 239 | /* Caller should have device mutex */ | 273 | /* Caller should have device mutex */ |
| 240 | static long vhost_dev_set_owner(struct vhost_dev *dev) | 274 | static long vhost_dev_set_owner(struct vhost_dev *dev) |
| 241 | { | 275 | { |
| @@ -255,14 +289,16 @@ static long vhost_dev_set_owner(struct vhost_dev *dev) | |||
| 255 | } | 289 | } |
| 256 | 290 | ||
| 257 | dev->worker = worker; | 291 | dev->worker = worker; |
| 258 | err = cgroup_attach_task_current_cg(worker); | 292 | wake_up_process(worker); /* avoid contributing to loadavg */ |
| 293 | |||
| 294 | err = vhost_attach_cgroups(dev); | ||
| 259 | if (err) | 295 | if (err) |
| 260 | goto err_cgroup; | 296 | goto err_cgroup; |
| 261 | wake_up_process(worker); /* avoid contributing to loadavg */ | ||
| 262 | 297 | ||
| 263 | return 0; | 298 | return 0; |
| 264 | err_cgroup: | 299 | err_cgroup: |
| 265 | kthread_stop(worker); | 300 | kthread_stop(worker); |
| 301 | dev->worker = NULL; | ||
| 266 | err_worker: | 302 | err_worker: |
| 267 | if (dev->mm) | 303 | if (dev->mm) |
| 268 | mmput(dev->mm); | 304 | mmput(dev->mm); |
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c index da03c074e32a..4d553d0b8d7a 100644 --- a/drivers/video/via/ioctl.c +++ b/drivers/video/via/ioctl.c | |||
| @@ -25,6 +25,8 @@ int viafb_ioctl_get_viafb_info(u_long arg) | |||
| 25 | { | 25 | { |
| 26 | struct viafb_ioctl_info viainfo; | 26 | struct viafb_ioctl_info viainfo; |
| 27 | 27 | ||
| 28 | memset(&viainfo, 0, sizeof(struct viafb_ioctl_info)); | ||
| 29 | |||
| 28 | viainfo.viafb_id = VIAID; | 30 | viainfo.viafb_id = VIAID; |
| 29 | viainfo.vendor_id = PCI_VIA_VENDOR_ID; | 31 | viainfo.vendor_id = PCI_VIA_VENDOR_ID; |
| 30 | 32 | ||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b036677df8c4..24efd8ea41bb 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
| @@ -213,11 +213,11 @@ config OMAP_WATCHDOG | |||
| 213 | here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. | 213 | here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. |
| 214 | 214 | ||
| 215 | config PNX4008_WATCHDOG | 215 | config PNX4008_WATCHDOG |
| 216 | tristate "PNX4008 Watchdog" | 216 | tristate "PNX4008 and LPC32XX Watchdog" |
| 217 | depends on ARCH_PNX4008 | 217 | depends on ARCH_PNX4008 || ARCH_LPC32XX |
| 218 | help | 218 | help |
| 219 | Say Y here if to include support for the watchdog timer | 219 | Say Y here if to include support for the watchdog timer |
| 220 | in the PNX4008 processor. | 220 | in the PNX4008 or LPC32XX processor. |
| 221 | This driver can be built as a module by choosing M. The module | 221 | This driver can be built as a module by choosing M. The module |
| 222 | will be called pnx4008_wdt. | 222 | will be called pnx4008_wdt. |
| 223 | 223 | ||
diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 88c83aa57303..f31493e65b38 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c | |||
| @@ -305,7 +305,7 @@ static int __init sbwdog_init(void) | |||
| 305 | if (ret) { | 305 | if (ret) { |
| 306 | printk(KERN_ERR "%s: failed to request irq 1 - %d\n", | 306 | printk(KERN_ERR "%s: failed to request irq 1 - %d\n", |
| 307 | ident.identity, ret); | 307 | ident.identity, ret); |
| 308 | return ret; | 308 | goto out; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | ret = misc_register(&sbwdog_miscdev); | 311 | ret = misc_register(&sbwdog_miscdev); |
| @@ -313,14 +313,20 @@ static int __init sbwdog_init(void) | |||
| 313 | printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", | 313 | printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", |
| 314 | ident.identity, | 314 | ident.identity, |
| 315 | timeout / 1000000, (timeout / 100000) % 10); | 315 | timeout / 1000000, (timeout / 100000) % 10); |
| 316 | } else | 316 | return 0; |
| 317 | free_irq(1, (void *)user_dog); | 317 | } |
| 318 | free_irq(1, (void *)user_dog); | ||
| 319 | out: | ||
| 320 | unregister_reboot_notifier(&sbwdog_notifier); | ||
| 321 | |||
| 318 | return ret; | 322 | return ret; |
| 319 | } | 323 | } |
| 320 | 324 | ||
| 321 | static void __exit sbwdog_exit(void) | 325 | static void __exit sbwdog_exit(void) |
| 322 | { | 326 | { |
| 323 | misc_deregister(&sbwdog_miscdev); | 327 | misc_deregister(&sbwdog_miscdev); |
| 328 | free_irq(1, (void *)user_dog); | ||
| 329 | unregister_reboot_notifier(&sbwdog_notifier); | ||
| 324 | } | 330 | } |
| 325 | 331 | ||
| 326 | module_init(sbwdog_init); | 332 | module_init(sbwdog_init); |
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 458c499c1223..18cdeb4c4258 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c | |||
| @@ -449,6 +449,9 @@ static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) | |||
| 449 | wdt->pdev = pdev; | 449 | wdt->pdev = pdev; |
| 450 | mutex_init(&wdt->lock); | 450 | mutex_init(&wdt->lock); |
| 451 | 451 | ||
| 452 | /* make sure that the watchdog is disabled */ | ||
| 453 | ts72xx_wdt_stop(wdt); | ||
| 454 | |||
| 452 | error = misc_register(&ts72xx_wdt_miscdev); | 455 | error = misc_register(&ts72xx_wdt_miscdev); |
| 453 | if (error) { | 456 | if (error) { |
| 454 | dev_err(&pdev->dev, "failed to register miscdev\n"); | 457 | dev_err(&pdev->dev, "failed to register miscdev\n"); |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 16c8a2a98c1b..899f168fd19c 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
| @@ -292,9 +292,11 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
| 292 | 292 | ||
| 293 | fid = filp->private_data; | 293 | fid = filp->private_data; |
| 294 | P9_DPRINTK(P9_DEBUG_VFS, | 294 | P9_DPRINTK(P9_DEBUG_VFS, |
| 295 | "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); | 295 | "v9fs_dir_release: inode: %p filp: %p fid: %d\n", |
| 296 | inode, filp, fid ? fid->fid : -1); | ||
| 296 | filemap_write_and_wait(inode->i_mapping); | 297 | filemap_write_and_wait(inode->i_mapping); |
| 297 | p9_client_clunk(fid); | 298 | if (fid) |
| 299 | p9_client_clunk(fid); | ||
| 298 | return 0; | 300 | return 0; |
| 299 | } | 301 | } |
| 300 | 302 | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c7c23eab9440..9e670d527646 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -730,7 +730,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | |||
| 730 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | 730 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); |
| 731 | goto error; | 731 | goto error; |
| 732 | } | 732 | } |
| 733 | dentry->d_op = &v9fs_cached_dentry_operations; | 733 | if (v9ses->cache) |
| 734 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
| 735 | else | ||
| 736 | dentry->d_op = &v9fs_dentry_operations; | ||
| 734 | d_instantiate(dentry, inode); | 737 | d_instantiate(dentry, inode); |
| 735 | err = v9fs_fid_add(dentry, fid); | 738 | err = v9fs_fid_add(dentry, fid); |
| 736 | if (err < 0) | 739 | if (err < 0) |
| @@ -1128,6 +1131,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 1128 | v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); | 1131 | v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); |
| 1129 | generic_fillattr(dentry->d_inode, stat); | 1132 | generic_fillattr(dentry->d_inode, stat); |
| 1130 | 1133 | ||
| 1134 | p9stat_free(st); | ||
| 1131 | kfree(st); | 1135 | kfree(st); |
| 1132 | return 0; | 1136 | return 0; |
| 1133 | } | 1137 | } |
| @@ -1489,6 +1493,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1489 | 1493 | ||
| 1490 | retval = strnlen(buffer, buflen); | 1494 | retval = strnlen(buffer, buflen); |
| 1491 | done: | 1495 | done: |
| 1496 | p9stat_free(st); | ||
| 1492 | kfree(st); | 1497 | kfree(st); |
| 1493 | return retval; | 1498 | return retval; |
| 1494 | } | 1499 | } |
| @@ -1942,7 +1947,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { | |||
| 1942 | .unlink = v9fs_vfs_unlink, | 1947 | .unlink = v9fs_vfs_unlink, |
| 1943 | .mkdir = v9fs_vfs_mkdir, | 1948 | .mkdir = v9fs_vfs_mkdir, |
| 1944 | .rmdir = v9fs_vfs_rmdir, | 1949 | .rmdir = v9fs_vfs_rmdir, |
| 1945 | .mknod = v9fs_vfs_mknod_dotl, | 1950 | .mknod = v9fs_vfs_mknod, |
| 1946 | .rename = v9fs_vfs_rename, | 1951 | .rename = v9fs_vfs_rename, |
| 1947 | .getattr = v9fs_vfs_getattr, | 1952 | .getattr = v9fs_vfs_getattr, |
| 1948 | .setattr = v9fs_vfs_setattr, | 1953 | .setattr = v9fs_vfs_setattr, |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index f9311077de68..1d12ba0ed3db 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
| @@ -122,6 +122,10 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 122 | fid = v9fs_session_init(v9ses, dev_name, data); | 122 | fid = v9fs_session_init(v9ses, dev_name, data); |
| 123 | if (IS_ERR(fid)) { | 123 | if (IS_ERR(fid)) { |
| 124 | retval = PTR_ERR(fid); | 124 | retval = PTR_ERR(fid); |
| 125 | /* | ||
| 126 | * we need to call session_close to tear down some | ||
| 127 | * of the data structure setup by session_init | ||
| 128 | */ | ||
| 125 | goto close_session; | 129 | goto close_session; |
| 126 | } | 130 | } |
| 127 | 131 | ||
| @@ -144,7 +148,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 144 | retval = -ENOMEM; | 148 | retval = -ENOMEM; |
| 145 | goto release_sb; | 149 | goto release_sb; |
| 146 | } | 150 | } |
| 147 | |||
| 148 | sb->s_root = root; | 151 | sb->s_root = root; |
| 149 | 152 | ||
| 150 | if (v9fs_proto_dotl(v9ses)) { | 153 | if (v9fs_proto_dotl(v9ses)) { |
| @@ -152,7 +155,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 152 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | 155 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); |
| 153 | if (IS_ERR(st)) { | 156 | if (IS_ERR(st)) { |
| 154 | retval = PTR_ERR(st); | 157 | retval = PTR_ERR(st); |
| 155 | goto clunk_fid; | 158 | goto release_sb; |
| 156 | } | 159 | } |
| 157 | 160 | ||
| 158 | v9fs_stat2inode_dotl(st, root->d_inode); | 161 | v9fs_stat2inode_dotl(st, root->d_inode); |
| @@ -162,7 +165,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 162 | st = p9_client_stat(fid); | 165 | st = p9_client_stat(fid); |
| 163 | if (IS_ERR(st)) { | 166 | if (IS_ERR(st)) { |
| 164 | retval = PTR_ERR(st); | 167 | retval = PTR_ERR(st); |
| 165 | goto clunk_fid; | 168 | goto release_sb; |
| 166 | } | 169 | } |
| 167 | 170 | ||
| 168 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); | 171 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); |
| @@ -174,19 +177,24 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 174 | 177 | ||
| 175 | v9fs_fid_add(root, fid); | 178 | v9fs_fid_add(root, fid); |
| 176 | 179 | ||
| 177 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); | 180 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); |
| 178 | simple_set_mnt(mnt, sb); | 181 | simple_set_mnt(mnt, sb); |
| 179 | return 0; | 182 | return 0; |
| 180 | 183 | ||
| 181 | clunk_fid: | 184 | clunk_fid: |
| 182 | p9_client_clunk(fid); | 185 | p9_client_clunk(fid); |
| 183 | |||
| 184 | close_session: | 186 | close_session: |
| 185 | v9fs_session_close(v9ses); | 187 | v9fs_session_close(v9ses); |
| 186 | kfree(v9ses); | 188 | kfree(v9ses); |
| 187 | return retval; | 189 | return retval; |
| 188 | |||
| 189 | release_sb: | 190 | release_sb: |
| 191 | /* | ||
| 192 | * we will do the session_close and root dentry release | ||
| 193 | * in the below call. But we need to clunk fid, because we haven't | ||
| 194 | * attached the fid to dentry so it won't get clunked | ||
| 195 | * automatically. | ||
| 196 | */ | ||
| 197 | p9_client_clunk(fid); | ||
| 190 | deactivate_locked_super(sb); | 198 | deactivate_locked_super(sb); |
| 191 | return retval; | 199 | return retval; |
| 192 | } | 200 | } |
| @@ -1659,6 +1659,9 @@ long do_io_submit(aio_context_t ctx_id, long nr, | |||
| 1659 | if (unlikely(nr < 0)) | 1659 | if (unlikely(nr < 0)) |
| 1660 | return -EINVAL; | 1660 | return -EINVAL; |
| 1661 | 1661 | ||
| 1662 | if (unlikely(nr > LONG_MAX/sizeof(*iocbpp))) | ||
| 1663 | nr = LONG_MAX/sizeof(*iocbpp); | ||
| 1664 | |||
| 1662 | if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) | 1665 | if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) |
| 1663 | return -EFAULT; | 1666 | return -EFAULT; |
| 1664 | 1667 | ||
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 612a5c38d3c1..4d0ff5ee27b8 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c | |||
| @@ -413,10 +413,10 @@ int bio_integrity_prep(struct bio *bio) | |||
| 413 | 413 | ||
| 414 | /* Allocate kernel buffer for protection data */ | 414 | /* Allocate kernel buffer for protection data */ |
| 415 | len = sectors * blk_integrity_tuple_size(bi); | 415 | len = sectors * blk_integrity_tuple_size(bi); |
| 416 | buf = kmalloc(len, GFP_NOIO | __GFP_NOFAIL | q->bounce_gfp); | 416 | buf = kmalloc(len, GFP_NOIO | q->bounce_gfp); |
| 417 | if (unlikely(buf == NULL)) { | 417 | if (unlikely(buf == NULL)) { |
| 418 | printk(KERN_ERR "could not allocate integrity buffer\n"); | 418 | printk(KERN_ERR "could not allocate integrity buffer\n"); |
| 419 | return -EIO; | 419 | return -ENOMEM; |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 422 | end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0da1debd499d..917b7d449bb2 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
| @@ -2,8 +2,6 @@ config CIFS | |||
| 2 | tristate "CIFS support (advanced network filesystem, SMBFS successor)" | 2 | tristate "CIFS support (advanced network filesystem, SMBFS successor)" |
| 3 | depends on INET | 3 | depends on INET |
| 4 | select NLS | 4 | select NLS |
| 5 | select CRYPTO_MD5 | ||
| 6 | select CRYPTO_ARC4 | ||
| 7 | help | 5 | help |
| 8 | This is the client VFS module for the Common Internet File System | 6 | This is the client VFS module for the Common Internet File System |
| 9 | (CIFS) protocol which is the successor to the Server Message Block | 7 | (CIFS) protocol which is the successor to the Server Message Block |
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 21f0fbd86989..cfd1ce34e0bc 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c | |||
| @@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 597 | if (compare_oid(oid, oidlen, MSKRB5_OID, | 597 | if (compare_oid(oid, oidlen, MSKRB5_OID, |
| 598 | MSKRB5_OID_LEN)) | 598 | MSKRB5_OID_LEN)) |
| 599 | server->sec_mskerberos = true; | 599 | server->sec_mskerberos = true; |
| 600 | if (compare_oid(oid, oidlen, KRB5U2U_OID, | 600 | else if (compare_oid(oid, oidlen, KRB5U2U_OID, |
| 601 | KRB5U2U_OID_LEN)) | 601 | KRB5U2U_OID_LEN)) |
| 602 | server->sec_kerberosu2u = true; | 602 | server->sec_kerberosu2u = true; |
| 603 | if (compare_oid(oid, oidlen, KRB5_OID, | 603 | else if (compare_oid(oid, oidlen, KRB5_OID, |
| 604 | KRB5_OID_LEN)) | 604 | KRB5_OID_LEN)) |
| 605 | server->sec_kerberos = true; | 605 | server->sec_kerberos = true; |
| 606 | if (compare_oid(oid, oidlen, NTLMSSP_OID, | 606 | else if (compare_oid(oid, oidlen, NTLMSSP_OID, |
| 607 | NTLMSSP_OID_LEN)) | 607 | NTLMSSP_OID_LEN)) |
| 608 | server->sec_ntlmssp = true; | 608 | server->sec_ntlmssp = true; |
| 609 | 609 | ||
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 709f2296bdb4..35042d8f7338 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include "md5.h" | 27 | #include "md5.h" |
| 28 | #include "cifs_unicode.h" | 28 | #include "cifs_unicode.h" |
| 29 | #include "cifsproto.h" | 29 | #include "cifsproto.h" |
| 30 | #include "ntlmssp.h" | ||
| 31 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
| 32 | #include <linux/random.h> | 31 | #include <linux/random.h> |
| 33 | 32 | ||
| @@ -43,43 +42,21 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, | |||
| 43 | unsigned char *p24); | 42 | unsigned char *p24); |
| 44 | 43 | ||
| 45 | static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, | 44 | static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, |
| 46 | struct TCP_Server_Info *server, char *signature) | 45 | const struct mac_key *key, char *signature) |
| 47 | { | 46 | { |
| 48 | int rc; | 47 | struct MD5Context context; |
| 49 | 48 | ||
| 50 | if (cifs_pdu == NULL || server == NULL || signature == NULL) | 49 | if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) |
| 51 | return -EINVAL; | 50 | return -EINVAL; |
| 52 | 51 | ||
| 53 | if (!server->ntlmssp.sdescmd5) { | 52 | cifs_MD5_init(&context); |
| 54 | cERROR(1, | 53 | cifs_MD5_update(&context, (char *)&key->data, key->len); |
| 55 | "cifs_calculate_signature: can't generate signature\n"); | 54 | cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); |
| 56 | return -1; | ||
| 57 | } | ||
| 58 | |||
| 59 | rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); | ||
| 60 | if (rc) { | ||
| 61 | cERROR(1, "cifs_calculate_signature: oould not init md5\n"); | ||
| 62 | return rc; | ||
| 63 | } | ||
| 64 | |||
| 65 | if (server->secType == RawNTLMSSP) | ||
| 66 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 67 | server->session_key.data.ntlmv2.key, | ||
| 68 | CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 69 | else | ||
| 70 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 71 | (char *)&server->session_key.data, | ||
| 72 | server->session_key.len); | ||
| 73 | |||
| 74 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 75 | cifs_pdu->Protocol, cifs_pdu->smb_buf_length); | ||
| 76 | 55 | ||
| 77 | rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); | 56 | cifs_MD5_final(signature, &context); |
| 78 | 57 | return 0; | |
| 79 | return rc; | ||
| 80 | } | 58 | } |
| 81 | 59 | ||
| 82 | |||
| 83 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | 60 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, |
| 84 | __u32 *pexpected_response_sequence_number) | 61 | __u32 *pexpected_response_sequence_number) |
| 85 | { | 62 | { |
| @@ -101,7 +78,8 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | |||
| 101 | server->sequence_number++; | 78 | server->sequence_number++; |
| 102 | spin_unlock(&GlobalMid_Lock); | 79 | spin_unlock(&GlobalMid_Lock); |
| 103 | 80 | ||
| 104 | rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); | 81 | rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, |
| 82 | smb_signature); | ||
| 105 | if (rc) | 83 | if (rc) |
| 106 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); | 84 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); |
| 107 | else | 85 | else |
| @@ -111,39 +89,21 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | |||
| 111 | } | 89 | } |
| 112 | 90 | ||
| 113 | static int cifs_calc_signature2(const struct kvec *iov, int n_vec, | 91 | static int cifs_calc_signature2(const struct kvec *iov, int n_vec, |
| 114 | struct TCP_Server_Info *server, char *signature) | 92 | const struct mac_key *key, char *signature) |
| 115 | { | 93 | { |
| 94 | struct MD5Context context; | ||
| 116 | int i; | 95 | int i; |
| 117 | int rc; | ||
| 118 | 96 | ||
| 119 | if (iov == NULL || server == NULL || signature == NULL) | 97 | if ((iov == NULL) || (signature == NULL) || (key == NULL)) |
| 120 | return -EINVAL; | 98 | return -EINVAL; |
| 121 | 99 | ||
| 122 | if (!server->ntlmssp.sdescmd5) { | 100 | cifs_MD5_init(&context); |
| 123 | cERROR(1, "cifs_calc_signature2: can't generate signature\n"); | 101 | cifs_MD5_update(&context, (char *)&key->data, key->len); |
| 124 | return -1; | ||
| 125 | } | ||
| 126 | |||
| 127 | rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); | ||
| 128 | if (rc) { | ||
| 129 | cERROR(1, "cifs_calc_signature2: oould not init md5\n"); | ||
| 130 | return rc; | ||
| 131 | } | ||
| 132 | |||
| 133 | if (server->secType == RawNTLMSSP) | ||
| 134 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 135 | server->session_key.data.ntlmv2.key, | ||
| 136 | CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 137 | else | ||
| 138 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | ||
| 139 | (char *)&server->session_key.data, | ||
| 140 | server->session_key.len); | ||
| 141 | |||
| 142 | for (i = 0; i < n_vec; i++) { | 102 | for (i = 0; i < n_vec; i++) { |
| 143 | if (iov[i].iov_len == 0) | 103 | if (iov[i].iov_len == 0) |
| 144 | continue; | 104 | continue; |
| 145 | if (iov[i].iov_base == NULL) { | 105 | if (iov[i].iov_base == NULL) { |
| 146 | cERROR(1, "cifs_calc_signature2: null iovec entry"); | 106 | cERROR(1, "null iovec entry"); |
| 147 | return -EIO; | 107 | return -EIO; |
| 148 | } | 108 | } |
| 149 | /* The first entry includes a length field (which does not get | 109 | /* The first entry includes a length field (which does not get |
| @@ -151,18 +111,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, | |||
| 151 | if (i == 0) { | 111 | if (i == 0) { |
| 152 | if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ | 112 | if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ |
| 153 | break; /* nothing to sign or corrupt header */ | 113 | break; /* nothing to sign or corrupt header */ |
| 154 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | 114 | cifs_MD5_update(&context, iov[0].iov_base+4, |
| 155 | iov[i].iov_base + 4, iov[i].iov_len - 4); | 115 | iov[0].iov_len-4); |
| 156 | } else | 116 | } else |
| 157 | crypto_shash_update(&server->ntlmssp.sdescmd5->shash, | 117 | cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); |
| 158 | iov[i].iov_base, iov[i].iov_len); | ||
| 159 | } | 118 | } |
| 160 | 119 | ||
| 161 | rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); | 120 | cifs_MD5_final(signature, &context); |
| 162 | 121 | ||
| 163 | return rc; | 122 | return 0; |
| 164 | } | 123 | } |
| 165 | 124 | ||
| 125 | |||
| 166 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | 126 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, |
| 167 | __u32 *pexpected_response_sequence_number) | 127 | __u32 *pexpected_response_sequence_number) |
| 168 | { | 128 | { |
| @@ -185,7 +145,8 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | |||
| 185 | server->sequence_number++; | 145 | server->sequence_number++; |
| 186 | spin_unlock(&GlobalMid_Lock); | 146 | spin_unlock(&GlobalMid_Lock); |
| 187 | 147 | ||
| 188 | rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); | 148 | rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, |
| 149 | smb_signature); | ||
| 189 | if (rc) | 150 | if (rc) |
| 190 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); | 151 | memset(cifs_pdu->Signature.SecuritySignature, 0, 8); |
| 191 | else | 152 | else |
| @@ -195,14 +156,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | |||
| 195 | } | 156 | } |
| 196 | 157 | ||
| 197 | int cifs_verify_signature(struct smb_hdr *cifs_pdu, | 158 | int cifs_verify_signature(struct smb_hdr *cifs_pdu, |
| 198 | struct TCP_Server_Info *server, | 159 | const struct mac_key *mac_key, |
| 199 | __u32 expected_sequence_number) | 160 | __u32 expected_sequence_number) |
| 200 | { | 161 | { |
| 201 | int rc; | 162 | unsigned int rc; |
| 202 | char server_response_sig[8]; | 163 | char server_response_sig[8]; |
| 203 | char what_we_think_sig_should_be[20]; | 164 | char what_we_think_sig_should_be[20]; |
| 204 | 165 | ||
| 205 | if (cifs_pdu == NULL || server == NULL) | 166 | if ((cifs_pdu == NULL) || (mac_key == NULL)) |
| 206 | return -EINVAL; | 167 | return -EINVAL; |
| 207 | 168 | ||
| 208 | if (cifs_pdu->Command == SMB_COM_NEGOTIATE) | 169 | if (cifs_pdu->Command == SMB_COM_NEGOTIATE) |
| @@ -231,7 +192,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, | |||
| 231 | cpu_to_le32(expected_sequence_number); | 192 | cpu_to_le32(expected_sequence_number); |
| 232 | cifs_pdu->Signature.Sequence.Reserved = 0; | 193 | cifs_pdu->Signature.Sequence.Reserved = 0; |
| 233 | 194 | ||
| 234 | rc = cifs_calculate_signature(cifs_pdu, server, | 195 | rc = cifs_calculate_signature(cifs_pdu, mac_key, |
| 235 | what_we_think_sig_should_be); | 196 | what_we_think_sig_should_be); |
| 236 | 197 | ||
| 237 | if (rc) | 198 | if (rc) |
| @@ -248,7 +209,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, | |||
| 248 | } | 209 | } |
| 249 | 210 | ||
| 250 | /* We fill in key by putting in 40 byte array which was allocated by caller */ | 211 | /* We fill in key by putting in 40 byte array which was allocated by caller */ |
| 251 | int cifs_calculate_session_key(struct session_key *key, const char *rn, | 212 | int cifs_calculate_mac_key(struct mac_key *key, const char *rn, |
| 252 | const char *password) | 213 | const char *password) |
| 253 | { | 214 | { |
| 254 | char temp_key[16]; | 215 | char temp_key[16]; |
| @@ -306,52 +267,38 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | |||
| 306 | { | 267 | { |
| 307 | int rc = 0; | 268 | int rc = 0; |
| 308 | int len; | 269 | int len; |
| 309 | char nt_hash[CIFS_NTHASH_SIZE]; | 270 | char nt_hash[16]; |
| 271 | struct HMACMD5Context *pctxt; | ||
| 310 | wchar_t *user; | 272 | wchar_t *user; |
| 311 | wchar_t *domain; | 273 | wchar_t *domain; |
| 312 | wchar_t *server; | ||
| 313 | 274 | ||
| 314 | if (!ses->server->ntlmssp.sdeschmacmd5) { | 275 | pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); |
| 315 | cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); | 276 | |
| 316 | return -1; | 277 | if (pctxt == NULL) |
| 317 | } | 278 | return -ENOMEM; |
| 318 | 279 | ||
| 319 | /* calculate md4 hash of password */ | 280 | /* calculate md4 hash of password */ |
| 320 | E_md4hash(ses->password, nt_hash); | 281 | E_md4hash(ses->password, nt_hash); |
| 321 | 282 | ||
| 322 | crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash, | 283 | /* convert Domainname to unicode and uppercase */ |
| 323 | CIFS_NTHASH_SIZE); | 284 | hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); |
| 324 | |||
| 325 | rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); | ||
| 326 | if (rc) { | ||
| 327 | cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n"); | ||
| 328 | return rc; | ||
| 329 | } | ||
| 330 | 285 | ||
| 331 | /* convert ses->userName to unicode and uppercase */ | 286 | /* convert ses->userName to unicode and uppercase */ |
| 332 | len = strlen(ses->userName); | 287 | len = strlen(ses->userName); |
| 333 | user = kmalloc(2 + (len * 2), GFP_KERNEL); | 288 | user = kmalloc(2 + (len * 2), GFP_KERNEL); |
| 334 | if (user == NULL) { | 289 | if (user == NULL) |
| 335 | cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); | ||
| 336 | rc = -ENOMEM; | ||
| 337 | goto calc_exit_2; | 290 | goto calc_exit_2; |
| 338 | } | ||
| 339 | len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); | 291 | len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); |
| 340 | UniStrupr(user); | 292 | UniStrupr(user); |
| 341 | 293 | hmac_md5_update((char *)user, 2*len, pctxt); | |
| 342 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 343 | (char *)user, 2 * len); | ||
| 344 | 294 | ||
| 345 | /* convert ses->domainName to unicode and uppercase */ | 295 | /* convert ses->domainName to unicode and uppercase */ |
| 346 | if (ses->domainName) { | 296 | if (ses->domainName) { |
| 347 | len = strlen(ses->domainName); | 297 | len = strlen(ses->domainName); |
| 348 | 298 | ||
| 349 | domain = kmalloc(2 + (len * 2), GFP_KERNEL); | 299 | domain = kmalloc(2 + (len * 2), GFP_KERNEL); |
| 350 | if (domain == NULL) { | 300 | if (domain == NULL) |
| 351 | cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); | ||
| 352 | rc = -ENOMEM; | ||
| 353 | goto calc_exit_1; | 301 | goto calc_exit_1; |
| 354 | } | ||
| 355 | len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, | 302 | len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, |
| 356 | nls_cp); | 303 | nls_cp); |
| 357 | /* the following line was removed since it didn't work well | 304 | /* the following line was removed since it didn't work well |
| @@ -359,292 +306,65 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, | |||
| 359 | Maybe converting the domain name earlier makes sense */ | 306 | Maybe converting the domain name earlier makes sense */ |
| 360 | /* UniStrupr(domain); */ | 307 | /* UniStrupr(domain); */ |
| 361 | 308 | ||
| 362 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | 309 | hmac_md5_update((char *)domain, 2*len, pctxt); |
| 363 | (char *)domain, 2 * len); | ||
| 364 | 310 | ||
| 365 | kfree(domain); | 311 | kfree(domain); |
| 366 | } else if (ses->serverName) { | ||
| 367 | len = strlen(ses->serverName); | ||
| 368 | |||
| 369 | server = kmalloc(2 + (len * 2), GFP_KERNEL); | ||
| 370 | if (server == NULL) { | ||
| 371 | cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); | ||
| 372 | rc = -ENOMEM; | ||
| 373 | goto calc_exit_1; | ||
| 374 | } | ||
| 375 | len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, | ||
| 376 | nls_cp); | ||
| 377 | /* the following line was removed since it didn't work well | ||
| 378 | with lower cased domain name that passed as an option. | ||
| 379 | Maybe converting the domain name earlier makes sense */ | ||
| 380 | /* UniStrupr(domain); */ | ||
| 381 | |||
| 382 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 383 | (char *)server, 2 * len); | ||
| 384 | |||
| 385 | kfree(server); | ||
| 386 | } | 312 | } |
| 387 | |||
| 388 | rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 389 | ses->server->ntlmv2_hash); | ||
| 390 | |||
| 391 | calc_exit_1: | 313 | calc_exit_1: |
| 392 | kfree(user); | 314 | kfree(user); |
| 393 | calc_exit_2: | 315 | calc_exit_2: |
| 394 | /* BB FIXME what about bytes 24 through 40 of the signing key? | 316 | /* BB FIXME what about bytes 24 through 40 of the signing key? |
| 395 | compare with the NTLM example */ | 317 | compare with the NTLM example */ |
| 318 | hmac_md5_final(ses->server->ntlmv2_hash, pctxt); | ||
| 396 | 319 | ||
| 320 | kfree(pctxt); | ||
| 397 | return rc; | 321 | return rc; |
| 398 | } | 322 | } |
| 399 | 323 | ||
| 400 | static int | 324 | void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, |
| 401 | find_domain_name(struct cifsSesInfo *ses) | ||
| 402 | { | ||
| 403 | int rc = 0; | ||
| 404 | unsigned int attrsize; | ||
| 405 | unsigned int type; | ||
| 406 | unsigned char *blobptr; | ||
| 407 | struct ntlmssp2_name *attrptr; | ||
| 408 | |||
| 409 | if (ses->server->tiblob) { | ||
| 410 | blobptr = ses->server->tiblob; | ||
| 411 | attrptr = (struct ntlmssp2_name *) blobptr; | ||
| 412 | |||
| 413 | while ((type = attrptr->type) != 0) { | ||
| 414 | blobptr += 2; /* advance attr type */ | ||
| 415 | attrsize = attrptr->length; | ||
| 416 | blobptr += 2; /* advance attr size */ | ||
| 417 | if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { | ||
| 418 | if (!ses->domainName) { | ||
| 419 | ses->domainName = | ||
| 420 | kmalloc(attrptr->length + 1, | ||
| 421 | GFP_KERNEL); | ||
| 422 | if (!ses->domainName) | ||
| 423 | return -ENOMEM; | ||
| 424 | cifs_from_ucs2(ses->domainName, | ||
| 425 | (__le16 *)blobptr, | ||
| 426 | attrptr->length, | ||
| 427 | attrptr->length, | ||
| 428 | load_nls_default(), false); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | blobptr += attrsize; /* advance attr value */ | ||
| 432 | attrptr = (struct ntlmssp2_name *) blobptr; | ||
| 433 | } | ||
| 434 | } else { | ||
| 435 | ses->server->tilen = 2 * sizeof(struct ntlmssp2_name); | ||
| 436 | ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL); | ||
| 437 | if (!ses->server->tiblob) { | ||
| 438 | ses->server->tilen = 0; | ||
| 439 | cERROR(1, "Challenge target info allocation failure"); | ||
| 440 | return -ENOMEM; | ||
| 441 | } | ||
| 442 | memset(ses->server->tiblob, 0x0, ses->server->tilen); | ||
| 443 | attrptr = (struct ntlmssp2_name *) ses->server->tiblob; | ||
| 444 | attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); | ||
| 445 | } | ||
| 446 | |||
| 447 | return rc; | ||
| 448 | } | ||
| 449 | |||
| 450 | static int | ||
| 451 | CalcNTLMv2_response(const struct TCP_Server_Info *server, | ||
| 452 | char *v2_session_response) | ||
| 453 | { | ||
| 454 | int rc; | ||
| 455 | |||
| 456 | if (!server->ntlmssp.sdeschmacmd5) { | ||
| 457 | cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); | ||
| 458 | return -1; | ||
| 459 | } | ||
| 460 | |||
| 461 | crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash, | ||
| 462 | CIFS_HMAC_MD5_HASH_SIZE); | ||
| 463 | |||
| 464 | rc = crypto_shash_init(&server->ntlmssp.sdeschmacmd5->shash); | ||
| 465 | if (rc) { | ||
| 466 | cERROR(1, "CalcNTLMv2_response: could not init hmacmd5"); | ||
| 467 | return rc; | ||
| 468 | } | ||
| 469 | |||
| 470 | memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, | ||
| 471 | server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE); | ||
| 472 | crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, | ||
| 473 | v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, | ||
| 474 | sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE); | ||
| 475 | |||
| 476 | if (server->tilen) | ||
| 477 | crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, | ||
| 478 | server->tiblob, server->tilen); | ||
| 479 | |||
| 480 | rc = crypto_shash_final(&server->ntlmssp.sdeschmacmd5->shash, | ||
| 481 | v2_session_response); | ||
| 482 | |||
| 483 | return rc; | ||
| 484 | } | ||
| 485 | |||
| 486 | int | ||
| 487 | setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, | ||
| 488 | const struct nls_table *nls_cp) | 325 | const struct nls_table *nls_cp) |
| 489 | { | 326 | { |
| 490 | int rc = 0; | 327 | int rc; |
| 491 | struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; | 328 | struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; |
| 329 | struct HMACMD5Context context; | ||
| 492 | 330 | ||
| 493 | buf->blob_signature = cpu_to_le32(0x00000101); | 331 | buf->blob_signature = cpu_to_le32(0x00000101); |
| 494 | buf->reserved = 0; | 332 | buf->reserved = 0; |
| 495 | buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 333 | buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); |
| 496 | get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); | 334 | get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); |
| 497 | buf->reserved2 = 0; | 335 | buf->reserved2 = 0; |
| 498 | 336 | buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); | |
| 499 | if (!ses->domainName) { | 337 | buf->names[0].length = 0; |
| 500 | rc = find_domain_name(ses); | 338 | buf->names[1].type = 0; |
| 501 | if (rc) { | 339 | buf->names[1].length = 0; |
| 502 | cERROR(1, "could not get domain/server name rc %d", rc); | ||
| 503 | return rc; | ||
| 504 | } | ||
| 505 | } | ||
| 506 | 340 | ||
| 507 | /* calculate buf->ntlmv2_hash */ | 341 | /* calculate buf->ntlmv2_hash */ |
| 508 | rc = calc_ntlmv2_hash(ses, nls_cp); | 342 | rc = calc_ntlmv2_hash(ses, nls_cp); |
| 509 | if (rc) { | 343 | if (rc) |
| 510 | cERROR(1, "could not get v2 hash rc %d", rc); | ||
| 511 | return rc; | ||
| 512 | } | ||
| 513 | rc = CalcNTLMv2_response(ses->server, resp_buf); | ||
| 514 | if (rc) { | ||
| 515 | cERROR(1, "could not get v2 hash rc %d", rc); | 344 | cERROR(1, "could not get v2 hash rc %d", rc); |
| 516 | return rc; | 345 | CalcNTLMv2_response(ses, resp_buf); |
| 517 | } | ||
| 518 | |||
| 519 | if (!ses->server->ntlmssp.sdeschmacmd5) { | ||
| 520 | cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); | ||
| 521 | return -1; | ||
| 522 | } | ||
| 523 | |||
| 524 | crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, | ||
| 525 | ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); | ||
| 526 | 346 | ||
| 527 | rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); | 347 | /* now calculate the MAC key for NTLMv2 */ |
| 528 | if (rc) { | 348 | hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); |
| 529 | cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n"); | 349 | hmac_md5_update(resp_buf, 16, &context); |
| 530 | return rc; | 350 | hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); |
| 531 | } | ||
| 532 | 351 | ||
| 533 | crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, | 352 | memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, |
| 534 | resp_buf, CIFS_HMAC_MD5_HASH_SIZE); | 353 | sizeof(struct ntlmv2_resp)); |
| 535 | 354 | ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); | |
| 536 | rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, | ||
| 537 | ses->server->session_key.data.ntlmv2.key); | ||
| 538 | |||
| 539 | memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf, | ||
| 540 | sizeof(struct ntlmv2_resp)); | ||
| 541 | ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp); | ||
| 542 | |||
| 543 | return rc; | ||
| 544 | } | 355 | } |
| 545 | 356 | ||
| 546 | int | 357 | void CalcNTLMv2_response(const struct cifsSesInfo *ses, |
| 547 | calc_seckey(struct TCP_Server_Info *server) | 358 | char *v2_session_response) |
| 548 | { | ||
| 549 | int rc; | ||
| 550 | unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE]; | ||
| 551 | struct crypto_blkcipher *tfm_arc4; | ||
| 552 | struct scatterlist sgin, sgout; | ||
| 553 | struct blkcipher_desc desc; | ||
| 554 | |||
| 555 | get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 556 | |||
| 557 | tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", | ||
| 558 | 0, CRYPTO_ALG_ASYNC); | ||
| 559 | if (!tfm_arc4 || IS_ERR(tfm_arc4)) { | ||
| 560 | cERROR(1, "could not allocate " "master crypto API arc4\n"); | ||
| 561 | return 1; | ||
| 562 | } | ||
| 563 | |||
| 564 | desc.tfm = tfm_arc4; | ||
| 565 | |||
| 566 | crypto_blkcipher_setkey(tfm_arc4, | ||
| 567 | server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE); | ||
| 568 | sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE); | ||
| 569 | sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); | ||
| 570 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); | ||
| 571 | |||
| 572 | if (!rc) | ||
| 573 | memcpy(server->session_key.data.ntlmv2.key, | ||
| 574 | sec_key, CIFS_NTLMV2_SESSKEY_SIZE); | ||
| 575 | |||
| 576 | crypto_free_blkcipher(tfm_arc4); | ||
| 577 | |||
| 578 | return 0; | ||
| 579 | } | ||
| 580 | |||
| 581 | void | ||
| 582 | cifs_crypto_shash_release(struct TCP_Server_Info *server) | ||
| 583 | { | ||
| 584 | if (server->ntlmssp.md5) | ||
| 585 | crypto_free_shash(server->ntlmssp.md5); | ||
| 586 | |||
| 587 | if (server->ntlmssp.hmacmd5) | ||
| 588 | crypto_free_shash(server->ntlmssp.hmacmd5); | ||
| 589 | |||
| 590 | kfree(server->ntlmssp.sdeschmacmd5); | ||
| 591 | |||
| 592 | kfree(server->ntlmssp.sdescmd5); | ||
| 593 | } | ||
| 594 | |||
| 595 | int | ||
| 596 | cifs_crypto_shash_allocate(struct TCP_Server_Info *server) | ||
| 597 | { | 359 | { |
| 598 | int rc; | 360 | struct HMACMD5Context context; |
| 599 | unsigned int size; | 361 | /* rest of v2 struct already generated */ |
| 600 | 362 | memcpy(v2_session_response + 8, ses->server->cryptKey, 8); | |
| 601 | server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); | 363 | hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); |
| 602 | if (!server->ntlmssp.hmacmd5 || | ||
| 603 | IS_ERR(server->ntlmssp.hmacmd5)) { | ||
| 604 | cERROR(1, "could not allocate crypto hmacmd5\n"); | ||
| 605 | return 1; | ||
| 606 | } | ||
| 607 | |||
| 608 | server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0); | ||
| 609 | if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) { | ||
| 610 | cERROR(1, "could not allocate crypto md5\n"); | ||
| 611 | rc = 1; | ||
| 612 | goto cifs_crypto_shash_allocate_ret1; | ||
| 613 | } | ||
| 614 | |||
| 615 | size = sizeof(struct shash_desc) + | ||
| 616 | crypto_shash_descsize(server->ntlmssp.hmacmd5); | ||
| 617 | server->ntlmssp.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); | ||
| 618 | if (!server->ntlmssp.sdeschmacmd5) { | ||
| 619 | cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n"); | ||
| 620 | rc = -ENOMEM; | ||
| 621 | goto cifs_crypto_shash_allocate_ret2; | ||
| 622 | } | ||
| 623 | server->ntlmssp.sdeschmacmd5->shash.tfm = server->ntlmssp.hmacmd5; | ||
| 624 | server->ntlmssp.sdeschmacmd5->shash.flags = 0x0; | ||
| 625 | 364 | ||
| 365 | hmac_md5_update(v2_session_response+8, | ||
| 366 | sizeof(struct ntlmv2_resp) - 8, &context); | ||
| 626 | 367 | ||
| 627 | size = sizeof(struct shash_desc) + | 368 | hmac_md5_final(v2_session_response, &context); |
| 628 | crypto_shash_descsize(server->ntlmssp.md5); | 369 | /* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ |
| 629 | server->ntlmssp.sdescmd5 = kmalloc(size, GFP_KERNEL); | ||
| 630 | if (!server->ntlmssp.sdescmd5) { | ||
| 631 | cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n"); | ||
| 632 | rc = -ENOMEM; | ||
| 633 | goto cifs_crypto_shash_allocate_ret3; | ||
| 634 | } | ||
| 635 | server->ntlmssp.sdescmd5->shash.tfm = server->ntlmssp.md5; | ||
| 636 | server->ntlmssp.sdescmd5->shash.flags = 0x0; | ||
| 637 | |||
| 638 | return 0; | ||
| 639 | |||
| 640 | cifs_crypto_shash_allocate_ret3: | ||
| 641 | kfree(server->ntlmssp.sdeschmacmd5); | ||
| 642 | |||
| 643 | cifs_crypto_shash_allocate_ret2: | ||
| 644 | crypto_free_shash(server->ntlmssp.md5); | ||
| 645 | |||
| 646 | cifs_crypto_shash_allocate_ret1: | ||
| 647 | crypto_free_shash(server->ntlmssp.hmacmd5); | ||
| 648 | |||
| 649 | return rc; | ||
| 650 | } | 370 | } |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c9d0cfc086eb..0cdfb8c32ac6 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -25,9 +25,6 @@ | |||
| 25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
| 26 | #include "cifs_fs_sb.h" | 26 | #include "cifs_fs_sb.h" |
| 27 | #include "cifsacl.h" | 27 | #include "cifsacl.h" |
| 28 | #include <crypto/internal/hash.h> | ||
| 29 | #include <linux/scatterlist.h> | ||
| 30 | |||
| 31 | /* | 28 | /* |
| 32 | * The sizes of various internal tables and strings | 29 | * The sizes of various internal tables and strings |
| 33 | */ | 30 | */ |
| @@ -100,7 +97,7 @@ enum protocolEnum { | |||
| 100 | /* Netbios frames protocol not supported at this time */ | 97 | /* Netbios frames protocol not supported at this time */ |
| 101 | }; | 98 | }; |
| 102 | 99 | ||
| 103 | struct session_key { | 100 | struct mac_key { |
| 104 | unsigned int len; | 101 | unsigned int len; |
| 105 | union { | 102 | union { |
| 106 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; | 103 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; |
| @@ -123,21 +120,6 @@ struct cifs_cred { | |||
| 123 | struct cifs_ace *aces; | 120 | struct cifs_ace *aces; |
| 124 | }; | 121 | }; |
| 125 | 122 | ||
| 126 | struct sdesc { | ||
| 127 | struct shash_desc shash; | ||
| 128 | char ctx[]; | ||
| 129 | }; | ||
| 130 | |||
| 131 | struct ntlmssp_auth { | ||
| 132 | __u32 client_flags; | ||
| 133 | __u32 server_flags; | ||
| 134 | unsigned char ciphertext[CIFS_CPHTXT_SIZE]; | ||
| 135 | struct crypto_shash *hmacmd5; | ||
| 136 | struct crypto_shash *md5; | ||
| 137 | struct sdesc *sdeschmacmd5; | ||
| 138 | struct sdesc *sdescmd5; | ||
| 139 | }; | ||
| 140 | |||
| 141 | /* | 123 | /* |
| 142 | ***************************************************************** | 124 | ***************************************************************** |
| 143 | * Except the CIFS PDUs themselves all the | 125 | * Except the CIFS PDUs themselves all the |
| @@ -200,14 +182,11 @@ struct TCP_Server_Info { | |||
| 200 | /* 16th byte of RFC1001 workstation name is always null */ | 182 | /* 16th byte of RFC1001 workstation name is always null */ |
| 201 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; | 183 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; |
| 202 | __u32 sequence_number; /* needed for CIFS PDU signature */ | 184 | __u32 sequence_number; /* needed for CIFS PDU signature */ |
| 203 | struct session_key session_key; | 185 | struct mac_key mac_signing_key; |
| 204 | char ntlmv2_hash[16]; | 186 | char ntlmv2_hash[16]; |
| 205 | unsigned long lstrp; /* when we got last response from this server */ | 187 | unsigned long lstrp; /* when we got last response from this server */ |
| 206 | u16 dialect; /* dialect index that server chose */ | 188 | u16 dialect; /* dialect index that server chose */ |
| 207 | /* extended security flavors that server supports */ | 189 | /* extended security flavors that server supports */ |
| 208 | unsigned int tilen; /* length of the target info blob */ | ||
| 209 | unsigned char *tiblob; /* target info blob in challenge response */ | ||
| 210 | struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */ | ||
| 211 | bool sec_kerberos; /* supports plain Kerberos */ | 190 | bool sec_kerberos; /* supports plain Kerberos */ |
| 212 | bool sec_mskerberos; /* supports legacy MS Kerberos */ | 191 | bool sec_mskerberos; /* supports legacy MS Kerberos */ |
| 213 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | 192 | bool sec_kerberosu2u; /* supports U2U Kerberos */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 320e0fd0ba7b..14d036d8db11 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -134,12 +134,6 @@ | |||
| 134 | * Size of the session key (crypto key encrypted with the password | 134 | * Size of the session key (crypto key encrypted with the password |
| 135 | */ | 135 | */ |
| 136 | #define CIFS_SESS_KEY_SIZE (24) | 136 | #define CIFS_SESS_KEY_SIZE (24) |
| 137 | #define CIFS_CLIENT_CHALLENGE_SIZE (8) | ||
| 138 | #define CIFS_SERVER_CHALLENGE_SIZE (8) | ||
| 139 | #define CIFS_HMAC_MD5_HASH_SIZE (16) | ||
| 140 | #define CIFS_CPHTXT_SIZE (16) | ||
| 141 | #define CIFS_NTLMV2_SESSKEY_SIZE (16) | ||
| 142 | #define CIFS_NTHASH_SIZE (16) | ||
| 143 | 137 | ||
| 144 | /* | 138 | /* |
| 145 | * Maximum user name length | 139 | * Maximum user name length |
| @@ -669,6 +663,7 @@ struct ntlmv2_resp { | |||
| 669 | __le64 time; | 663 | __le64 time; |
| 670 | __u64 client_chal; /* random */ | 664 | __u64 client_chal; /* random */ |
| 671 | __u32 reserved2; | 665 | __u32 reserved2; |
| 666 | struct ntlmssp2_name names[2]; | ||
| 672 | /* array of name entries could follow ending in minimum 4 byte struct */ | 667 | /* array of name entries could follow ending in minimum 4 byte struct */ |
| 673 | } __attribute__((packed)); | 668 | } __attribute__((packed)); |
| 674 | 669 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1378d9133844..1d60c655e3e0 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | |||
| 87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
| 88 | struct TCP_Server_Info *server); | 88 | struct TCP_Server_Info *server); |
| 89 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); | 89 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); |
| 90 | extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); | ||
| 90 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 91 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, |
| 91 | unsigned short int port); | 92 | const unsigned short int port); |
| 92 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); | 93 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); |
| 93 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 94 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
| 94 | const struct cifsTconInfo *, int /* length of | 95 | const struct cifsTconInfo *, int /* length of |
| @@ -361,15 +362,13 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); | |||
| 361 | extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, | 362 | extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, |
| 362 | __u32 *); | 363 | __u32 *); |
| 363 | extern int cifs_verify_signature(struct smb_hdr *, | 364 | extern int cifs_verify_signature(struct smb_hdr *, |
| 364 | struct TCP_Server_Info *server, | 365 | const struct mac_key *mac_key, |
| 365 | __u32 expected_sequence_number); | 366 | __u32 expected_sequence_number); |
| 366 | extern int cifs_calculate_session_key(struct session_key *key, const char *rn, | 367 | extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, |
| 367 | const char *pass); | 368 | const char *pass); |
| 368 | extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | 369 | extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); |
| 370 | extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | ||
| 369 | const struct nls_table *); | 371 | const struct nls_table *); |
| 370 | extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); | ||
| 371 | extern void cifs_crypto_shash_release(struct TCP_Server_Info *); | ||
| 372 | extern int calc_seckey(struct TCP_Server_Info *); | ||
| 373 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 372 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
| 374 | extern void calc_lanman_hash(const char *password, const char *cryptkey, | 373 | extern void calc_lanman_hash(const char *password, const char *cryptkey, |
| 375 | bool encrypt, char *lnm_session_key); | 374 | bool encrypt, char *lnm_session_key); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4bda920d1f75..c65c3419dd37 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -604,14 +604,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 604 | else | 604 | else |
| 605 | rc = -EINVAL; | 605 | rc = -EINVAL; |
| 606 | 606 | ||
| 607 | if (server->secType == Kerberos) { | 607 | if (server->sec_kerberos || server->sec_mskerberos) |
| 608 | if (!server->sec_kerberos && | 608 | server->secType = Kerberos; |
| 609 | !server->sec_mskerberos) | 609 | else if (server->sec_ntlmssp) |
| 610 | rc = -EOPNOTSUPP; | 610 | server->secType = RawNTLMSSP; |
| 611 | } else if (server->secType == RawNTLMSSP) { | 611 | else |
| 612 | if (!server->sec_ntlmssp) | ||
| 613 | rc = -EOPNOTSUPP; | ||
| 614 | } else | ||
| 615 | rc = -EOPNOTSUPP; | 612 | rc = -EOPNOTSUPP; |
| 616 | } | 613 | } |
| 617 | } else | 614 | } else |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ec0ea4a43bdb..88c84a38bccb 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -400,7 +400,9 @@ incomplete_rcv: | |||
| 400 | cFYI(1, "call to reconnect done"); | 400 | cFYI(1, "call to reconnect done"); |
| 401 | csocket = server->ssocket; | 401 | csocket = server->ssocket; |
| 402 | continue; | 402 | continue; |
| 403 | } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { | 403 | } else if (length == -ERESTARTSYS || |
| 404 | length == -EAGAIN || | ||
| 405 | length == -EINTR) { | ||
| 404 | msleep(1); /* minimum sleep to prevent looping | 406 | msleep(1); /* minimum sleep to prevent looping |
| 405 | allowing socket to clear and app threads to set | 407 | allowing socket to clear and app threads to set |
| 406 | tcpStatus CifsNeedReconnect if server hung */ | 408 | tcpStatus CifsNeedReconnect if server hung */ |
| @@ -414,18 +416,6 @@ incomplete_rcv: | |||
| 414 | } else | 416 | } else |
| 415 | continue; | 417 | continue; |
| 416 | } else if (length <= 0) { | 418 | } else if (length <= 0) { |
| 417 | if (server->tcpStatus == CifsNew) { | ||
| 418 | cFYI(1, "tcp session abend after SMBnegprot"); | ||
| 419 | /* some servers kill the TCP session rather than | ||
| 420 | returning an SMB negprot error, in which | ||
| 421 | case reconnecting here is not going to help, | ||
| 422 | and so simply return error to mount */ | ||
| 423 | break; | ||
| 424 | } | ||
| 425 | if (!try_to_freeze() && (length == -EINTR)) { | ||
| 426 | cFYI(1, "cifsd thread killed"); | ||
| 427 | break; | ||
| 428 | } | ||
| 429 | cFYI(1, "Reconnect after unexpected peek error %d", | 419 | cFYI(1, "Reconnect after unexpected peek error %d", |
| 430 | length); | 420 | length); |
| 431 | cifs_reconnect(server); | 421 | cifs_reconnect(server); |
| @@ -466,27 +456,19 @@ incomplete_rcv: | |||
| 466 | an error on SMB negprot response */ | 456 | an error on SMB negprot response */ |
| 467 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", | 457 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", |
| 468 | pdu_length); | 458 | pdu_length); |
| 469 | if (server->tcpStatus == CifsNew) { | 459 | /* give server a second to clean up */ |
| 470 | /* if nack on negprot (rather than | 460 | msleep(1000); |
| 471 | ret of smb negprot error) reconnecting | 461 | /* always try 445 first on reconnect since we get NACK |
| 472 | not going to help, ret error to mount */ | 462 | * on some if we ever connected to port 139 (the NACK |
| 473 | break; | 463 | * is since we do not begin with RFC1001 session |
| 474 | } else { | 464 | * initialize frame) |
| 475 | /* give server a second to | 465 | */ |
| 476 | clean up before reconnect attempt */ | 466 | cifs_set_port((struct sockaddr *) |
| 477 | msleep(1000); | 467 | &server->addr.sockAddr, CIFS_PORT); |
| 478 | /* always try 445 first on reconnect | 468 | cifs_reconnect(server); |
| 479 | since we get NACK on some if we ever | 469 | csocket = server->ssocket; |
| 480 | connected to port 139 (the NACK is | 470 | wake_up(&server->response_q); |
| 481 | since we do not begin with RFC1001 | 471 | continue; |
| 482 | session initialize frame) */ | ||
| 483 | server->addr.sockAddr.sin_port = | ||
| 484 | htons(CIFS_PORT); | ||
| 485 | cifs_reconnect(server); | ||
| 486 | csocket = server->ssocket; | ||
| 487 | wake_up(&server->response_q); | ||
| 488 | continue; | ||
| 489 | } | ||
| 490 | } else if (temp != (char) 0) { | 472 | } else if (temp != (char) 0) { |
| 491 | cERROR(1, "Unknown RFC 1002 frame"); | 473 | cERROR(1, "Unknown RFC 1002 frame"); |
| 492 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, | 474 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, |
| @@ -522,8 +504,7 @@ incomplete_rcv: | |||
| 522 | total_read += length) { | 504 | total_read += length) { |
| 523 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, | 505 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, |
| 524 | pdu_length - total_read, 0); | 506 | pdu_length - total_read, 0); |
| 525 | if ((server->tcpStatus == CifsExiting) || | 507 | if (server->tcpStatus == CifsExiting) { |
| 526 | (length == -EINTR)) { | ||
| 527 | /* then will exit */ | 508 | /* then will exit */ |
| 528 | reconnect = 2; | 509 | reconnect = 2; |
| 529 | break; | 510 | break; |
| @@ -534,8 +515,9 @@ incomplete_rcv: | |||
| 534 | /* Now we will reread sock */ | 515 | /* Now we will reread sock */ |
| 535 | reconnect = 1; | 516 | reconnect = 1; |
| 536 | break; | 517 | break; |
| 537 | } else if ((length == -ERESTARTSYS) || | 518 | } else if (length == -ERESTARTSYS || |
| 538 | (length == -EAGAIN)) { | 519 | length == -EAGAIN || |
| 520 | length == -EINTR) { | ||
| 539 | msleep(1); /* minimum sleep to prevent looping, | 521 | msleep(1); /* minimum sleep to prevent looping, |
| 540 | allowing socket to clear and app | 522 | allowing socket to clear and app |
| 541 | threads to set tcpStatus | 523 | threads to set tcpStatus |
| @@ -1708,7 +1690,6 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) | |||
| 1708 | CIFSSMBLogoff(xid, ses); | 1690 | CIFSSMBLogoff(xid, ses); |
| 1709 | _FreeXid(xid); | 1691 | _FreeXid(xid); |
| 1710 | } | 1692 | } |
| 1711 | cifs_crypto_shash_release(server); | ||
| 1712 | sesInfoFree(ses); | 1693 | sesInfoFree(ses); |
| 1713 | cifs_put_tcp_session(server); | 1694 | cifs_put_tcp_session(server); |
| 1714 | } | 1695 | } |
| @@ -1725,9 +1706,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
| 1725 | if (ses) { | 1706 | if (ses) { |
| 1726 | cFYI(1, "Existing smb sess found (status=%d)", ses->status); | 1707 | cFYI(1, "Existing smb sess found (status=%d)", ses->status); |
| 1727 | 1708 | ||
| 1728 | /* existing SMB ses has a server reference already */ | ||
| 1729 | cifs_put_tcp_session(server); | ||
| 1730 | |||
| 1731 | mutex_lock(&ses->session_mutex); | 1709 | mutex_lock(&ses->session_mutex); |
| 1732 | rc = cifs_negotiate_protocol(xid, ses); | 1710 | rc = cifs_negotiate_protocol(xid, ses); |
| 1733 | if (rc) { | 1711 | if (rc) { |
| @@ -1750,6 +1728,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
| 1750 | } | 1728 | } |
| 1751 | } | 1729 | } |
| 1752 | mutex_unlock(&ses->session_mutex); | 1730 | mutex_unlock(&ses->session_mutex); |
| 1731 | |||
| 1732 | /* existing SMB ses has a server reference already */ | ||
| 1733 | cifs_put_tcp_session(server); | ||
| 1753 | FreeXid(xid); | 1734 | FreeXid(xid); |
| 1754 | return ses; | 1735 | return ses; |
| 1755 | } | 1736 | } |
| @@ -1788,23 +1769,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
| 1788 | ses->linux_uid = volume_info->linux_uid; | 1769 | ses->linux_uid = volume_info->linux_uid; |
| 1789 | ses->overrideSecFlg = volume_info->secFlg; | 1770 | ses->overrideSecFlg = volume_info->secFlg; |
| 1790 | 1771 | ||
| 1791 | rc = cifs_crypto_shash_allocate(server); | ||
| 1792 | if (rc) { | ||
| 1793 | cERROR(1, "could not setup hash structures rc %d", rc); | ||
| 1794 | goto get_ses_fail; | ||
| 1795 | } | ||
| 1796 | server->tilen = 0; | ||
| 1797 | server->tiblob = NULL; | ||
| 1798 | |||
| 1799 | mutex_lock(&ses->session_mutex); | 1772 | mutex_lock(&ses->session_mutex); |
| 1800 | rc = cifs_negotiate_protocol(xid, ses); | 1773 | rc = cifs_negotiate_protocol(xid, ses); |
| 1801 | if (!rc) | 1774 | if (!rc) |
| 1802 | rc = cifs_setup_session(xid, ses, volume_info->local_nls); | 1775 | rc = cifs_setup_session(xid, ses, volume_info->local_nls); |
| 1803 | mutex_unlock(&ses->session_mutex); | 1776 | mutex_unlock(&ses->session_mutex); |
| 1804 | if (rc) { | 1777 | if (rc) |
| 1805 | cifs_crypto_shash_release(ses->server); | ||
| 1806 | goto get_ses_fail; | 1778 | goto get_ses_fail; |
| 1807 | } | ||
| 1808 | 1779 | ||
| 1809 | /* success, put it on the list */ | 1780 | /* success, put it on the list */ |
| 1810 | write_lock(&cifs_tcp_ses_lock); | 1781 | write_lock(&cifs_tcp_ses_lock); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 86a164f08a74..93f77d438d3c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -1462,29 +1462,18 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
| 1462 | { | 1462 | { |
| 1463 | char *fromName = NULL; | 1463 | char *fromName = NULL; |
| 1464 | char *toName = NULL; | 1464 | char *toName = NULL; |
| 1465 | struct cifs_sb_info *cifs_sb_source; | 1465 | struct cifs_sb_info *cifs_sb; |
| 1466 | struct cifs_sb_info *cifs_sb_target; | ||
| 1467 | struct cifsTconInfo *tcon; | 1466 | struct cifsTconInfo *tcon; |
| 1468 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | 1467 | FILE_UNIX_BASIC_INFO *info_buf_source = NULL; |
| 1469 | FILE_UNIX_BASIC_INFO *info_buf_target; | 1468 | FILE_UNIX_BASIC_INFO *info_buf_target; |
| 1470 | int xid, rc, tmprc; | 1469 | int xid, rc, tmprc; |
| 1471 | 1470 | ||
| 1472 | cifs_sb_target = CIFS_SB(target_dir->i_sb); | 1471 | cifs_sb = CIFS_SB(source_dir->i_sb); |
| 1473 | cifs_sb_source = CIFS_SB(source_dir->i_sb); | 1472 | tcon = cifs_sb->tcon; |
| 1474 | tcon = cifs_sb_source->tcon; | ||
| 1475 | 1473 | ||
| 1476 | xid = GetXid(); | 1474 | xid = GetXid(); |
| 1477 | 1475 | ||
| 1478 | /* | 1476 | /* |
| 1479 | * BB: this might be allowed if same server, but different share. | ||
| 1480 | * Consider adding support for this | ||
| 1481 | */ | ||
| 1482 | if (tcon != cifs_sb_target->tcon) { | ||
| 1483 | rc = -EXDEV; | ||
| 1484 | goto cifs_rename_exit; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | /* | ||
| 1488 | * we already have the rename sem so we do not need to | 1477 | * we already have the rename sem so we do not need to |
| 1489 | * grab it again here to protect the path integrity | 1478 | * grab it again here to protect the path integrity |
| 1490 | */ | 1479 | */ |
| @@ -1519,17 +1508,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
| 1519 | info_buf_target = info_buf_source + 1; | 1508 | info_buf_target = info_buf_source + 1; |
| 1520 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, | 1509 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, |
| 1521 | info_buf_source, | 1510 | info_buf_source, |
| 1522 | cifs_sb_source->local_nls, | 1511 | cifs_sb->local_nls, |
| 1523 | cifs_sb_source->mnt_cifs_flags & | 1512 | cifs_sb->mnt_cifs_flags & |
| 1524 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1513 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1525 | if (tmprc != 0) | 1514 | if (tmprc != 0) |
| 1526 | goto unlink_target; | 1515 | goto unlink_target; |
| 1527 | 1516 | ||
| 1528 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, | 1517 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, |
| 1529 | toName, info_buf_target, | 1518 | info_buf_target, |
| 1530 | cifs_sb_target->local_nls, | 1519 | cifs_sb->local_nls, |
| 1531 | /* remap based on source sb */ | 1520 | cifs_sb->mnt_cifs_flags & |
| 1532 | cifs_sb_source->mnt_cifs_flags & | ||
| 1533 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1521 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1534 | 1522 | ||
| 1535 | if (tmprc == 0 && (info_buf_source->UniqueId == | 1523 | if (tmprc == 0 && (info_buf_source->UniqueId == |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f97851119e6c..9aad47a2d62f 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -206,26 +206,30 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) | |||
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | int | 208 | int |
| 209 | cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 209 | cifs_set_port(struct sockaddr *addr, const unsigned short int port) |
| 210 | const unsigned short int port) | ||
| 211 | { | 210 | { |
| 212 | if (!cifs_convert_address(dst, src, len)) | 211 | switch (addr->sa_family) { |
| 213 | return 0; | ||
| 214 | |||
| 215 | switch (dst->sa_family) { | ||
| 216 | case AF_INET: | 212 | case AF_INET: |
| 217 | ((struct sockaddr_in *)dst)->sin_port = htons(port); | 213 | ((struct sockaddr_in *)addr)->sin_port = htons(port); |
| 218 | break; | 214 | break; |
| 219 | case AF_INET6: | 215 | case AF_INET6: |
| 220 | ((struct sockaddr_in6 *)dst)->sin6_port = htons(port); | 216 | ((struct sockaddr_in6 *)addr)->sin6_port = htons(port); |
| 221 | break; | 217 | break; |
| 222 | default: | 218 | default: |
| 223 | return 0; | 219 | return 0; |
| 224 | } | 220 | } |
| 225 | |||
| 226 | return 1; | 221 | return 1; |
| 227 | } | 222 | } |
| 228 | 223 | ||
| 224 | int | ||
| 225 | cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | ||
| 226 | const unsigned short int port) | ||
| 227 | { | ||
| 228 | if (!cifs_convert_address(dst, src, len)) | ||
| 229 | return 0; | ||
| 230 | return cifs_set_port(dst, port); | ||
| 231 | } | ||
| 232 | |||
| 229 | /***************************************************************************** | 233 | /***************************************************************************** |
| 230 | convert a NT status code to a dos class/code | 234 | convert a NT status code to a dos class/code |
| 231 | *****************************************************************************/ | 235 | *****************************************************************************/ |
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 1db0f0746a5b..49c9a4e75319 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h | |||
| @@ -61,19 +61,6 @@ | |||
| 61 | #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 | 61 | #define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 |
| 62 | #define NTLMSSP_NEGOTIATE_56 0x80000000 | 62 | #define NTLMSSP_NEGOTIATE_56 0x80000000 |
| 63 | 63 | ||
| 64 | /* Define AV Pair Field IDs */ | ||
| 65 | #define NTLMSSP_AV_EOL 0 | ||
| 66 | #define NTLMSSP_AV_NB_COMPUTER_NAME 1 | ||
| 67 | #define NTLMSSP_AV_NB_DOMAIN_NAME 2 | ||
| 68 | #define NTLMSSP_AV_DNS_COMPUTER_NAME 3 | ||
| 69 | #define NTLMSSP_AV_DNS_DOMAIN_NAME 4 | ||
| 70 | #define NTLMSSP_AV_DNS_TREE_NAME 5 | ||
| 71 | #define NTLMSSP_AV_FLAGS 6 | ||
| 72 | #define NTLMSSP_AV_TIMESTAMP 7 | ||
| 73 | #define NTLMSSP_AV_RESTRICTION 8 | ||
| 74 | #define NTLMSSP_AV_TARGET_NAME 9 | ||
| 75 | #define NTLMSSP_AV_CHANNEL_BINDINGS 10 | ||
| 76 | |||
| 77 | /* Although typedefs are not commonly used for structure definitions */ | 64 | /* Although typedefs are not commonly used for structure definitions */ |
| 78 | /* in the Linux kernel, in this particular case they are useful */ | 65 | /* in the Linux kernel, in this particular case they are useful */ |
| 79 | /* to more closely match the standards document for NTLMSSP from */ | 66 | /* to more closely match the standards document for NTLMSSP from */ |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 795095f4eac6..0a57cb7db5dd 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
| @@ -383,9 +383,6 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, | |||
| 383 | static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | 383 | static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, |
| 384 | struct cifsSesInfo *ses) | 384 | struct cifsSesInfo *ses) |
| 385 | { | 385 | { |
| 386 | unsigned int tioffset; /* challeng message target info area */ | ||
| 387 | unsigned int tilen; /* challeng message target info area length */ | ||
| 388 | |||
| 389 | CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; | 386 | CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; |
| 390 | 387 | ||
| 391 | if (blob_len < sizeof(CHALLENGE_MESSAGE)) { | 388 | if (blob_len < sizeof(CHALLENGE_MESSAGE)) { |
| @@ -408,20 +405,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | |||
| 408 | /* BB spec says that if AvId field of MsvAvTimestamp is populated then | 405 | /* BB spec says that if AvId field of MsvAvTimestamp is populated then |
| 409 | we must set the MIC field of the AUTHENTICATE_MESSAGE */ | 406 | we must set the MIC field of the AUTHENTICATE_MESSAGE */ |
| 410 | 407 | ||
| 411 | ses->server->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags); | ||
| 412 | |||
| 413 | tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset); | ||
| 414 | tilen = cpu_to_le16(pblob->TargetInfoArray.Length); | ||
| 415 | ses->server->tilen = tilen; | ||
| 416 | if (tilen) { | ||
| 417 | ses->server->tiblob = kmalloc(tilen, GFP_KERNEL); | ||
| 418 | if (!ses->server->tiblob) { | ||
| 419 | cERROR(1, "Challenge target info allocation failure"); | ||
| 420 | return -ENOMEM; | ||
| 421 | } | ||
| 422 | memcpy(ses->server->tiblob, bcc_ptr + tioffset, tilen); | ||
| 423 | } | ||
| 424 | |||
| 425 | return 0; | 408 | return 0; |
| 426 | } | 409 | } |
| 427 | 410 | ||
| @@ -442,13 +425,12 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
| 442 | /* BB is NTLMV2 session security format easier to use here? */ | 425 | /* BB is NTLMV2 session security format easier to use here? */ |
| 443 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | | 426 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
| 444 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 427 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
| 445 | NTLMSSP_NEGOTIATE_NTLM; | 428 | NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; |
| 446 | if (ses->server->secMode & | 429 | if (ses->server->secMode & |
| 447 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 430 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
| 448 | flags |= NTLMSSP_NEGOTIATE_SIGN | | 431 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
| 449 | NTLMSSP_NEGOTIATE_KEY_XCH | | 432 | if (ses->server->secMode & SECMODE_SIGN_REQUIRED) |
| 450 | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 433 | flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; |
| 451 | } | ||
| 452 | 434 | ||
| 453 | sec_blob->NegotiateFlags |= cpu_to_le32(flags); | 435 | sec_blob->NegotiateFlags |= cpu_to_le32(flags); |
| 454 | 436 | ||
| @@ -469,12 +451,10 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 469 | struct cifsSesInfo *ses, | 451 | struct cifsSesInfo *ses, |
| 470 | const struct nls_table *nls_cp, bool first) | 452 | const struct nls_table *nls_cp, bool first) |
| 471 | { | 453 | { |
| 472 | int rc; | ||
| 473 | unsigned int size; | ||
| 474 | AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; | 454 | AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; |
| 475 | __u32 flags; | 455 | __u32 flags; |
| 476 | unsigned char *tmp; | 456 | unsigned char *tmp; |
| 477 | struct ntlmv2_resp ntlmv2_response = {}; | 457 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; |
| 478 | 458 | ||
| 479 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); | 459 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); |
| 480 | sec_blob->MessageType = NtLmAuthenticate; | 460 | sec_blob->MessageType = NtLmAuthenticate; |
| @@ -497,25 +477,19 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 497 | sec_blob->LmChallengeResponse.Length = 0; | 477 | sec_blob->LmChallengeResponse.Length = 0; |
| 498 | sec_blob->LmChallengeResponse.MaximumLength = 0; | 478 | sec_blob->LmChallengeResponse.MaximumLength = 0; |
| 499 | 479 | ||
| 500 | sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); | 480 | /* calculate session key, BB what about adding similar ntlmv2 path? */ |
| 501 | rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp); | 481 | SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); |
| 502 | if (rc) { | 482 | if (first) |
| 503 | cERROR(1, "error rc: %d during ntlmssp ntlmv2 setup", rc); | 483 | cifs_calculate_mac_key(&ses->server->mac_signing_key, |
| 504 | goto setup_ntlmv2_ret; | 484 | ntlm_session_key, ses->password); |
| 505 | } | ||
| 506 | size = sizeof(struct ntlmv2_resp); | ||
| 507 | memcpy(tmp, (char *)&ntlmv2_response, size); | ||
| 508 | tmp += size; | ||
| 509 | if (ses->server->tilen > 0) { | ||
| 510 | memcpy(tmp, ses->server->tiblob, ses->server->tilen); | ||
| 511 | tmp += ses->server->tilen; | ||
| 512 | } else | ||
| 513 | ses->server->tilen = 0; | ||
| 514 | 485 | ||
| 515 | sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + | 486 | memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); |
| 516 | ses->server->tilen); | 487 | sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 488 | sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
| 517 | sec_blob->NtChallengeResponse.MaximumLength = | 489 | sec_blob->NtChallengeResponse.MaximumLength = |
| 518 | cpu_to_le16(size + ses->server->tilen); | 490 | cpu_to_le16(CIFS_SESS_KEY_SIZE); |
| 491 | |||
| 492 | tmp += CIFS_SESS_KEY_SIZE; | ||
| 519 | 493 | ||
| 520 | if (ses->domainName == NULL) { | 494 | if (ses->domainName == NULL) { |
| 521 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 495 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| @@ -527,6 +501,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 527 | len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, | 501 | len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, |
| 528 | MAX_USERNAME_SIZE, nls_cp); | 502 | MAX_USERNAME_SIZE, nls_cp); |
| 529 | len *= 2; /* unicode is 2 bytes each */ | 503 | len *= 2; /* unicode is 2 bytes each */ |
| 504 | len += 2; /* trailing null */ | ||
| 530 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 505 | sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 531 | sec_blob->DomainName.Length = cpu_to_le16(len); | 506 | sec_blob->DomainName.Length = cpu_to_le16(len); |
| 532 | sec_blob->DomainName.MaximumLength = cpu_to_le16(len); | 507 | sec_blob->DomainName.MaximumLength = cpu_to_le16(len); |
| @@ -543,6 +518,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 543 | len = cifs_strtoUCS((__le16 *)tmp, ses->userName, | 518 | len = cifs_strtoUCS((__le16 *)tmp, ses->userName, |
| 544 | MAX_USERNAME_SIZE, nls_cp); | 519 | MAX_USERNAME_SIZE, nls_cp); |
| 545 | len *= 2; /* unicode is 2 bytes each */ | 520 | len *= 2; /* unicode is 2 bytes each */ |
| 521 | len += 2; /* trailing null */ | ||
| 546 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); | 522 | sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 547 | sec_blob->UserName.Length = cpu_to_le16(len); | 523 | sec_blob->UserName.Length = cpu_to_le16(len); |
| 548 | sec_blob->UserName.MaximumLength = cpu_to_le16(len); | 524 | sec_blob->UserName.MaximumLength = cpu_to_le16(len); |
| @@ -554,26 +530,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
| 554 | sec_blob->WorkstationName.MaximumLength = 0; | 530 | sec_blob->WorkstationName.MaximumLength = 0; |
| 555 | tmp += 2; | 531 | tmp += 2; |
| 556 | 532 | ||
| 557 | if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && | 533 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); |
| 558 | !calc_seckey(ses->server)) { | 534 | sec_blob->SessionKey.Length = 0; |
| 559 | memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); | 535 | sec_blob->SessionKey.MaximumLength = 0; |
| 560 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | ||
| 561 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); | ||
| 562 | sec_blob->SessionKey.MaximumLength = | ||
| 563 | cpu_to_le16(CIFS_CPHTXT_SIZE); | ||
| 564 | tmp += CIFS_CPHTXT_SIZE; | ||
| 565 | } else { | ||
| 566 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | ||
| 567 | sec_blob->SessionKey.Length = 0; | ||
| 568 | sec_blob->SessionKey.MaximumLength = 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | ses->server->sequence_number = 0; | ||
| 572 | |||
| 573 | setup_ntlmv2_ret: | ||
| 574 | if (ses->server->tilen > 0) | ||
| 575 | kfree(ses->server->tiblob); | ||
| 576 | |||
| 577 | return tmp - pbuffer; | 536 | return tmp - pbuffer; |
| 578 | } | 537 | } |
| 579 | 538 | ||
| @@ -587,14 +546,15 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, | |||
| 587 | return; | 546 | return; |
| 588 | } | 547 | } |
| 589 | 548 | ||
| 590 | static int setup_ntlmssp_auth_req(char *ntlmsspblob, | 549 | static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, |
| 591 | struct cifsSesInfo *ses, | 550 | struct cifsSesInfo *ses, |
| 592 | const struct nls_table *nls, bool first_time) | 551 | const struct nls_table *nls, bool first_time) |
| 593 | { | 552 | { |
| 594 | int bloblen; | 553 | int bloblen; |
| 595 | 554 | ||
| 596 | bloblen = build_ntlmssp_auth_blob(ntlmsspblob, ses, nls, | 555 | bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, |
| 597 | first_time); | 556 | first_time); |
| 557 | pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen); | ||
| 598 | 558 | ||
| 599 | return bloblen; | 559 | return bloblen; |
| 600 | } | 560 | } |
| @@ -730,7 +690,7 @@ ssetup_ntlmssp_authenticate: | |||
| 730 | 690 | ||
| 731 | if (first_time) /* should this be moved into common code | 691 | if (first_time) /* should this be moved into common code |
| 732 | with similar ntlmv2 path? */ | 692 | with similar ntlmv2 path? */ |
| 733 | cifs_calculate_session_key(&ses->server->session_key, | 693 | cifs_calculate_mac_key(&ses->server->mac_signing_key, |
| 734 | ntlm_session_key, ses->password); | 694 | ntlm_session_key, ses->password); |
| 735 | /* copy session key */ | 695 | /* copy session key */ |
| 736 | 696 | ||
| @@ -769,21 +729,12 @@ ssetup_ntlmssp_authenticate: | |||
| 769 | cpu_to_le16(sizeof(struct ntlmv2_resp)); | 729 | cpu_to_le16(sizeof(struct ntlmv2_resp)); |
| 770 | 730 | ||
| 771 | /* calculate session key */ | 731 | /* calculate session key */ |
| 772 | rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); | 732 | setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); |
| 773 | if (rc) { | ||
| 774 | kfree(v2_sess_key); | ||
| 775 | goto ssetup_exit; | ||
| 776 | } | ||
| 777 | /* FIXME: calculate MAC key */ | 733 | /* FIXME: calculate MAC key */ |
| 778 | memcpy(bcc_ptr, (char *)v2_sess_key, | 734 | memcpy(bcc_ptr, (char *)v2_sess_key, |
| 779 | sizeof(struct ntlmv2_resp)); | 735 | sizeof(struct ntlmv2_resp)); |
| 780 | bcc_ptr += sizeof(struct ntlmv2_resp); | 736 | bcc_ptr += sizeof(struct ntlmv2_resp); |
| 781 | kfree(v2_sess_key); | 737 | kfree(v2_sess_key); |
| 782 | if (ses->server->tilen > 0) { | ||
| 783 | memcpy(bcc_ptr, ses->server->tiblob, | ||
| 784 | ses->server->tilen); | ||
| 785 | bcc_ptr += ses->server->tilen; | ||
| 786 | } | ||
| 787 | if (ses->capabilities & CAP_UNICODE) { | 738 | if (ses->capabilities & CAP_UNICODE) { |
| 788 | if (iov[0].iov_len % 2) { | 739 | if (iov[0].iov_len % 2) { |
| 789 | *bcc_ptr = 0; | 740 | *bcc_ptr = 0; |
| @@ -814,15 +765,15 @@ ssetup_ntlmssp_authenticate: | |||
| 814 | } | 765 | } |
| 815 | /* bail out if key is too long */ | 766 | /* bail out if key is too long */ |
| 816 | if (msg->sesskey_len > | 767 | if (msg->sesskey_len > |
| 817 | sizeof(ses->server->session_key.data.krb5)) { | 768 | sizeof(ses->server->mac_signing_key.data.krb5)) { |
| 818 | cERROR(1, "Kerberos signing key too long (%u bytes)", | 769 | cERROR(1, "Kerberos signing key too long (%u bytes)", |
| 819 | msg->sesskey_len); | 770 | msg->sesskey_len); |
| 820 | rc = -EOVERFLOW; | 771 | rc = -EOVERFLOW; |
| 821 | goto ssetup_exit; | 772 | goto ssetup_exit; |
| 822 | } | 773 | } |
| 823 | if (first_time) { | 774 | if (first_time) { |
| 824 | ses->server->session_key.len = msg->sesskey_len; | 775 | ses->server->mac_signing_key.len = msg->sesskey_len; |
| 825 | memcpy(ses->server->session_key.data.krb5, | 776 | memcpy(ses->server->mac_signing_key.data.krb5, |
| 826 | msg->data, msg->sesskey_len); | 777 | msg->data, msg->sesskey_len); |
| 827 | } | 778 | } |
| 828 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 779 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
| @@ -864,28 +815,12 @@ ssetup_ntlmssp_authenticate: | |||
| 864 | if (phase == NtLmNegotiate) { | 815 | if (phase == NtLmNegotiate) { |
| 865 | setup_ntlmssp_neg_req(pSMB, ses); | 816 | setup_ntlmssp_neg_req(pSMB, ses); |
| 866 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); | 817 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); |
| 867 | iov[1].iov_base = &pSMB->req.SecurityBlob[0]; | ||
| 868 | } else if (phase == NtLmAuthenticate) { | 818 | } else if (phase == NtLmAuthenticate) { |
| 869 | int blob_len; | 819 | int blob_len; |
| 870 | char *ntlmsspblob; | 820 | blob_len = setup_ntlmssp_auth_req(pSMB, ses, |
| 871 | 821 | nls_cp, | |
| 872 | ntlmsspblob = kmalloc(5 * | 822 | first_time); |
| 873 | sizeof(struct _AUTHENTICATE_MESSAGE), | ||
| 874 | GFP_KERNEL); | ||
| 875 | if (!ntlmsspblob) { | ||
| 876 | cERROR(1, "Can't allocate NTLMSSP"); | ||
| 877 | rc = -ENOMEM; | ||
| 878 | goto ssetup_exit; | ||
| 879 | } | ||
| 880 | |||
| 881 | blob_len = setup_ntlmssp_auth_req(ntlmsspblob, | ||
| 882 | ses, | ||
| 883 | nls_cp, | ||
| 884 | first_time); | ||
| 885 | iov[1].iov_len = blob_len; | 823 | iov[1].iov_len = blob_len; |
| 886 | iov[1].iov_base = ntlmsspblob; | ||
| 887 | pSMB->req.SecurityBlobLength = | ||
| 888 | cpu_to_le16(blob_len); | ||
| 889 | /* Make sure that we tell the server that we | 824 | /* Make sure that we tell the server that we |
| 890 | are using the uid that it just gave us back | 825 | are using the uid that it just gave us back |
| 891 | on the response (challenge) */ | 826 | on the response (challenge) */ |
| @@ -895,6 +830,7 @@ ssetup_ntlmssp_authenticate: | |||
| 895 | rc = -ENOSYS; | 830 | rc = -ENOSYS; |
| 896 | goto ssetup_exit; | 831 | goto ssetup_exit; |
| 897 | } | 832 | } |
| 833 | iov[1].iov_base = &pSMB->req.SecurityBlob[0]; | ||
| 898 | /* unicode strings must be word aligned */ | 834 | /* unicode strings must be word aligned */ |
| 899 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { | 835 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { |
| 900 | *bcc_ptr = 0; | 836 | *bcc_ptr = 0; |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index e0588cdf4cc5..82f78c4d6978 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -543,7 +543,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 543 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | | 543 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | |
| 544 | SECMODE_SIGN_ENABLED))) { | 544 | SECMODE_SIGN_ENABLED))) { |
| 545 | rc = cifs_verify_signature(midQ->resp_buf, | 545 | rc = cifs_verify_signature(midQ->resp_buf, |
| 546 | ses->server, | 546 | &ses->server->mac_signing_key, |
| 547 | midQ->sequence_number+1); | 547 | midQ->sequence_number+1); |
| 548 | if (rc) { | 548 | if (rc) { |
| 549 | cERROR(1, "Unexpected SMB signature"); | 549 | cERROR(1, "Unexpected SMB signature"); |
| @@ -731,7 +731,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 731 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | | 731 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | |
| 732 | SECMODE_SIGN_ENABLED))) { | 732 | SECMODE_SIGN_ENABLED))) { |
| 733 | rc = cifs_verify_signature(out_buf, | 733 | rc = cifs_verify_signature(out_buf, |
| 734 | ses->server, | 734 | &ses->server->mac_signing_key, |
| 735 | midQ->sequence_number+1); | 735 | midQ->sequence_number+1); |
| 736 | if (rc) { | 736 | if (rc) { |
| 737 | cERROR(1, "Unexpected SMB signature"); | 737 | cERROR(1, "Unexpected SMB signature"); |
| @@ -981,7 +981,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
| 981 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | | 981 | (ses->server->secMode & (SECMODE_SIGN_REQUIRED | |
| 982 | SECMODE_SIGN_ENABLED))) { | 982 | SECMODE_SIGN_ENABLED))) { |
| 983 | rc = cifs_verify_signature(out_buf, | 983 | rc = cifs_verify_signature(out_buf, |
| 984 | ses->server, | 984 | &ses->server->mac_signing_key, |
| 985 | midQ->sequence_number+1); | 985 | midQ->sequence_number+1); |
| 986 | if (rc) { | 986 | if (rc) { |
| 987 | cERROR(1, "Unexpected SMB signature"); | 987 | cERROR(1, "Unexpected SMB signature"); |
| @@ -376,6 +376,9 @@ static int count(const char __user * const __user * argv, int max) | |||
| 376 | argv++; | 376 | argv++; |
| 377 | if (i++ >= max) | 377 | if (i++ >= max) |
| 378 | return -E2BIG; | 378 | return -E2BIG; |
| 379 | |||
| 380 | if (fatal_signal_pending(current)) | ||
| 381 | return -ERESTARTNOHAND; | ||
| 379 | cond_resched(); | 382 | cond_resched(); |
| 380 | } | 383 | } |
| 381 | } | 384 | } |
| @@ -419,6 +422,12 @@ static int copy_strings(int argc, const char __user *const __user *argv, | |||
| 419 | while (len > 0) { | 422 | while (len > 0) { |
| 420 | int offset, bytes_to_copy; | 423 | int offset, bytes_to_copy; |
| 421 | 424 | ||
| 425 | if (fatal_signal_pending(current)) { | ||
| 426 | ret = -ERESTARTNOHAND; | ||
| 427 | goto out; | ||
| 428 | } | ||
| 429 | cond_resched(); | ||
| 430 | |||
| 422 | offset = pos % PAGE_SIZE; | 431 | offset = pos % PAGE_SIZE; |
| 423 | if (offset == 0) | 432 | if (offset == 0) |
| 424 | offset = PAGE_SIZE; | 433 | offset = PAGE_SIZE; |
| @@ -594,6 +603,11 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
| 594 | #else | 603 | #else |
| 595 | stack_top = arch_align_stack(stack_top); | 604 | stack_top = arch_align_stack(stack_top); |
| 596 | stack_top = PAGE_ALIGN(stack_top); | 605 | stack_top = PAGE_ALIGN(stack_top); |
| 606 | |||
| 607 | if (unlikely(stack_top < mmap_min_addr) || | ||
| 608 | unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr)) | ||
| 609 | return -ENOMEM; | ||
| 610 | |||
| 597 | stack_shift = vma->vm_end - stack_top; | 611 | stack_shift = vma->vm_end - stack_top; |
| 598 | 612 | ||
| 599 | bprm->p -= stack_shift; | 613 | bprm->p -= stack_shift; |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 7d9d06ba184b..81e086d8aa57 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -808,7 +808,7 @@ int bdi_writeback_thread(void *data) | |||
| 808 | wb->last_active = jiffies; | 808 | wb->last_active = jiffies; |
| 809 | 809 | ||
| 810 | set_current_state(TASK_INTERRUPTIBLE); | 810 | set_current_state(TASK_INTERRUPTIBLE); |
| 811 | if (!list_empty(&bdi->work_list)) { | 811 | if (!list_empty(&bdi->work_list) || kthread_should_stop()) { |
| 812 | __set_current_state(TASK_RUNNING); | 812 | __set_current_state(TASK_RUNNING); |
| 813 | continue; | 813 | continue; |
| 814 | } | 814 | } |
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 6c2aad49d731..f7e13db613cb 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
| @@ -63,6 +63,7 @@ config NFS_V3_ACL | |||
| 63 | config NFS_V4 | 63 | config NFS_V4 |
| 64 | bool "NFS client support for NFS version 4" | 64 | bool "NFS client support for NFS version 4" |
| 65 | depends on NFS_FS | 65 | depends on NFS_FS |
| 66 | select SUNRPC_GSS | ||
| 66 | help | 67 | help |
| 67 | This option enables support for version 4 of the NFS protocol | 68 | This option enables support for version 4 of the NFS protocol |
| 68 | (RFC 3530) in the kernel's NFS client. | 69 | (RFC 3530) in the kernel's NFS client. |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4e7df2adb212..e7340729af89 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -275,7 +275,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | |||
| 275 | sin1->sin6_scope_id != sin2->sin6_scope_id) | 275 | sin1->sin6_scope_id != sin2->sin6_scope_id) |
| 276 | return 0; | 276 | return 0; |
| 277 | 277 | ||
| 278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); | 278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); |
| 279 | } | 279 | } |
| 280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ | 280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ |
| 281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | 281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index eb51bd6201da..05bf3c0dc751 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -723,10 +723,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
| 723 | default: | 723 | default: |
| 724 | BUG(); | 724 | BUG(); |
| 725 | } | 725 | } |
| 726 | if (res < 0) | ||
| 727 | dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager" | ||
| 728 | " - error %d!\n", | ||
| 729 | __func__, res); | ||
| 730 | return res; | 726 | return res; |
| 731 | } | 727 | } |
| 732 | 728 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ec3966e4706b..f4cbf0c306c6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 431 | goto out_err; | 431 | goto out_err; |
| 432 | 432 | ||
| 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); | 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); |
| 434 | if (unlikely(error == -ESTALE)) { | ||
| 435 | struct dentry *pd_dentry; | ||
| 434 | 436 | ||
| 437 | pd_dentry = dget_parent(dentry); | ||
| 438 | if (pd_dentry != NULL) { | ||
| 439 | nfs_zap_caches(pd_dentry->d_inode); | ||
| 440 | dput(pd_dentry); | ||
| 441 | } | ||
| 442 | } | ||
| 435 | nfs_free_fattr(res.fattr); | 443 | nfs_free_fattr(res.fattr); |
| 436 | if (error < 0) | 444 | if (error < 0) |
| 437 | goto out_err; | 445 | goto out_err; |
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 95932f523aef..4264377552e2 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig | |||
| @@ -69,6 +69,7 @@ config NFSD_V4 | |||
| 69 | depends on NFSD && PROC_FS && EXPERIMENTAL | 69 | depends on NFSD && PROC_FS && EXPERIMENTAL |
| 70 | select NFSD_V3 | 70 | select NFSD_V3 |
| 71 | select FS_POSIX_ACL | 71 | select FS_POSIX_ACL |
| 72 | select SUNRPC_GSS | ||
| 72 | help | 73 | help |
| 73 | This option enables support in your system's NFS server for | 74 | This option enables support in your system's NFS server for |
| 74 | version 4 of the NFS protocol (RFC 3530). | 75 | version 4 of the NFS protocol (RFC 3530). |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index d72cf2bb054a..286e36e21dae 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
| @@ -1932,7 +1932,8 @@ xfs_buf_init(void) | |||
| 1932 | if (!xfs_buf_zone) | 1932 | if (!xfs_buf_zone) |
| 1933 | goto out; | 1933 | goto out; |
| 1934 | 1934 | ||
| 1935 | xfslogd_workqueue = create_workqueue("xfslogd"); | 1935 | xfslogd_workqueue = alloc_workqueue("xfslogd", |
| 1936 | WQ_RESCUER | WQ_HIGHPRI, 1); | ||
| 1936 | if (!xfslogd_workqueue) | 1937 | if (!xfslogd_workqueue) |
| 1937 | goto out_free_buf_zone; | 1938 | goto out_free_buf_zone; |
| 1938 | 1939 | ||
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 4fec427b83ef..3b9e626f7cd1 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
| @@ -785,6 +785,8 @@ xfs_ioc_fsgetxattr( | |||
| 785 | { | 785 | { |
| 786 | struct fsxattr fa; | 786 | struct fsxattr fa; |
| 787 | 787 | ||
| 788 | memset(&fa, 0, sizeof(struct fsxattr)); | ||
| 789 | |||
| 788 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 790 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
| 789 | fa.fsx_xflags = xfs_ip2xflags(ip); | 791 | fa.fsx_xflags = xfs_ip2xflags(ip); |
| 790 | fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; | 792 | fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c9f3cc5949a8..3e5a51af757c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -386,7 +386,15 @@ struct drm_connector_funcs { | |||
| 386 | void (*dpms)(struct drm_connector *connector, int mode); | 386 | void (*dpms)(struct drm_connector *connector, int mode); |
| 387 | void (*save)(struct drm_connector *connector); | 387 | void (*save)(struct drm_connector *connector); |
| 388 | void (*restore)(struct drm_connector *connector); | 388 | void (*restore)(struct drm_connector *connector); |
| 389 | enum drm_connector_status (*detect)(struct drm_connector *connector); | 389 | |
| 390 | /* Check to see if anything is attached to the connector. | ||
| 391 | * @force is set to false whilst polling, true when checking the | ||
| 392 | * connector due to user request. @force can be used by the driver | ||
| 393 | * to avoid expensive, destructive operations during automated | ||
| 394 | * probing. | ||
| 395 | */ | ||
| 396 | enum drm_connector_status (*detect)(struct drm_connector *connector, | ||
| 397 | bool force); | ||
| 390 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); | 398 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); |
| 391 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, | 399 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, |
| 392 | uint64_t val); | 400 | uint64_t val); |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 9ddc8780e8db..5778b559d59c 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
| @@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type, | |||
| 360 | const struct compat_iovec __user *uvector, unsigned long nr_segs, | 360 | const struct compat_iovec __user *uvector, unsigned long nr_segs, |
| 361 | unsigned long fast_segs, struct iovec *fast_pointer, | 361 | unsigned long fast_segs, struct iovec *fast_pointer, |
| 362 | struct iovec **ret_pointer); | 362 | struct iovec **ret_pointer); |
| 363 | |||
| 364 | extern void __user *compat_alloc_user_space(unsigned long len); | ||
| 365 | |||
| 363 | #endif /* CONFIG_COMPAT */ | 366 | #endif /* CONFIG_COMPAT */ |
| 364 | #endif /* _LINUX_COMPAT_H */ | 367 | #endif /* _LINUX_COMPAT_H */ |
diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 2c958f4fce1e..926b50322a46 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h | |||
| @@ -136,6 +136,7 @@ extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t); | |||
| 136 | 136 | ||
| 137 | extern int elevator_init(struct request_queue *, char *); | 137 | extern int elevator_init(struct request_queue *, char *); |
| 138 | extern void elevator_exit(struct elevator_queue *); | 138 | extern void elevator_exit(struct elevator_queue *); |
| 139 | extern int elevator_change(struct request_queue *, const char *); | ||
| 139 | extern int elv_rq_merge_ok(struct request *, struct bio *); | 140 | extern int elv_rq_merge_ok(struct request *, struct bio *); |
| 140 | 141 | ||
| 141 | /* | 142 | /* |
diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 03f616b78cfa..e41f7dd1ae67 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 14 | 14 | ||
| 15 | struct device; | 15 | struct device; |
| 16 | struct gpio_chip; | ||
| 16 | 17 | ||
| 17 | /* | 18 | /* |
| 18 | * Some platforms don't support the GPIO programming interface. | 19 | * Some platforms don't support the GPIO programming interface. |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d50ba858cfe0..d1a9193960f1 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
| @@ -274,8 +274,14 @@ static inline int dquot_alloc_space(struct inode *inode, qsize_t nr) | |||
| 274 | int ret; | 274 | int ret; |
| 275 | 275 | ||
| 276 | ret = dquot_alloc_space_nodirty(inode, nr); | 276 | ret = dquot_alloc_space_nodirty(inode, nr); |
| 277 | if (!ret) | 277 | if (!ret) { |
| 278 | mark_inode_dirty_sync(inode); | 278 | /* |
| 279 | * Mark inode fully dirty. Since we are allocating blocks, inode | ||
| 280 | * would become fully dirty soon anyway and it reportedly | ||
| 281 | * reduces inode_lock contention. | ||
| 282 | */ | ||
| 283 | mark_inode_dirty(inode); | ||
| 284 | } | ||
| 279 | return ret; | 285 | return ret; |
| 280 | } | 286 | } |
| 281 | 287 | ||
diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h index cc813f95a2f2..c91302f3a257 100644 --- a/include/linux/spi/dw_spi.h +++ b/include/linux/spi/dw_spi.h | |||
| @@ -14,7 +14,9 @@ | |||
| 14 | #define SPI_MODE_OFFSET 6 | 14 | #define SPI_MODE_OFFSET 6 |
| 15 | #define SPI_SCPH_OFFSET 6 | 15 | #define SPI_SCPH_OFFSET 6 |
| 16 | #define SPI_SCOL_OFFSET 7 | 16 | #define SPI_SCOL_OFFSET 7 |
| 17 | |||
| 17 | #define SPI_TMOD_OFFSET 8 | 18 | #define SPI_TMOD_OFFSET 8 |
| 19 | #define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET) | ||
| 18 | #define SPI_TMOD_TR 0x0 /* xmit & recv */ | 20 | #define SPI_TMOD_TR 0x0 /* xmit & recv */ |
| 19 | #define SPI_TMOD_TO 0x1 /* xmit only */ | 21 | #define SPI_TMOD_TO 0x1 /* xmit only */ |
| 20 | #define SPI_TMOD_RO 0x2 /* recv only */ | 22 | #define SPI_TMOD_RO 0x2 /* recv only */ |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 569dc722a600..85f38a63f098 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
| @@ -30,7 +30,7 @@ struct rpc_inode; | |||
| 30 | * The high-level client handle | 30 | * The high-level client handle |
| 31 | */ | 31 | */ |
| 32 | struct rpc_clnt { | 32 | struct rpc_clnt { |
| 33 | struct kref cl_kref; /* Number of references */ | 33 | atomic_t cl_count; /* Number of references */ |
| 34 | struct list_head cl_clients; /* Global list of clients */ | 34 | struct list_head cl_clients; /* Global list of clients */ |
| 35 | struct list_head cl_tasks; /* List of tasks */ | 35 | struct list_head cl_tasks; /* List of tasks */ |
| 36 | spinlock_t cl_lock; /* spinlock */ | 36 | spinlock_t cl_lock; /* spinlock */ |
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index f11100f96482..25e02c941bac 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
| @@ -235,6 +235,10 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } | |||
| 235 | #define work_clear_pending(work) \ | 235 | #define work_clear_pending(work) \ |
| 236 | clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)) | 236 | clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)) |
| 237 | 237 | ||
| 238 | /* | ||
| 239 | * Workqueue flags and constants. For details, please refer to | ||
| 240 | * Documentation/workqueue.txt. | ||
| 241 | */ | ||
| 238 | enum { | 242 | enum { |
| 239 | WQ_NON_REENTRANT = 1 << 0, /* guarantee non-reentrance */ | 243 | WQ_NON_REENTRANT = 1 << 0, /* guarantee non-reentrance */ |
| 240 | WQ_UNBOUND = 1 << 1, /* not bound to any cpu */ | 244 | WQ_UNBOUND = 1 << 1, /* not bound to any cpu */ |
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h index 726cc3536409..ef6c24a529e1 100644 --- a/include/net/cls_cgroup.h +++ b/include/net/cls_cgroup.h | |||
| @@ -27,11 +27,17 @@ struct cgroup_cls_state | |||
| 27 | #ifdef CONFIG_NET_CLS_CGROUP | 27 | #ifdef CONFIG_NET_CLS_CGROUP |
| 28 | static inline u32 task_cls_classid(struct task_struct *p) | 28 | static inline u32 task_cls_classid(struct task_struct *p) |
| 29 | { | 29 | { |
| 30 | int classid; | ||
| 31 | |||
| 30 | if (in_interrupt()) | 32 | if (in_interrupt()) |
| 31 | return 0; | 33 | return 0; |
| 32 | 34 | ||
| 33 | return container_of(task_subsys_state(p, net_cls_subsys_id), | 35 | rcu_read_lock(); |
| 34 | struct cgroup_cls_state, css)->classid; | 36 | classid = container_of(task_subsys_state(p, net_cls_subsys_id), |
| 37 | struct cgroup_cls_state, css)->classid; | ||
| 38 | rcu_read_unlock(); | ||
| 39 | |||
| 40 | return classid; | ||
| 35 | } | 41 | } |
| 36 | #else | 42 | #else |
| 37 | extern int net_cls_subsys_id; | 43 | extern int net_cls_subsys_id; |
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index a4747a0f7303..f976885f686f 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
| @@ -955,6 +955,9 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum) | |||
| 955 | return csum_partial(diff, sizeof(diff), oldsum); | 955 | return csum_partial(diff, sizeof(diff), oldsum); |
| 956 | } | 956 | } |
| 957 | 957 | ||
| 958 | extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, | ||
| 959 | int outin); | ||
| 960 | |||
| 958 | #endif /* __KERNEL__ */ | 961 | #endif /* __KERNEL__ */ |
| 959 | 962 | ||
| 960 | #endif /* _NET_IP_VS_H */ | 963 | #endif /* _NET_IP_VS_H */ |
diff --git a/include/net/sock.h b/include/net/sock.h index ac53bfbdfe16..adab9dc58183 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
| @@ -752,6 +752,7 @@ struct proto { | |||
| 752 | /* Keeping track of sk's, looking them up, and port selection methods. */ | 752 | /* Keeping track of sk's, looking them up, and port selection methods. */ |
| 753 | void (*hash)(struct sock *sk); | 753 | void (*hash)(struct sock *sk); |
| 754 | void (*unhash)(struct sock *sk); | 754 | void (*unhash)(struct sock *sk); |
| 755 | void (*rehash)(struct sock *sk); | ||
| 755 | int (*get_port)(struct sock *sk, unsigned short snum); | 756 | int (*get_port)(struct sock *sk, unsigned short snum); |
| 756 | 757 | ||
| 757 | /* Keeping track of sockets in use */ | 758 | /* Keeping track of sockets in use */ |
diff --git a/include/net/udp.h b/include/net/udp.h index 7abdf305da50..a184d3496b13 100644 --- a/include/net/udp.h +++ b/include/net/udp.h | |||
| @@ -151,6 +151,7 @@ static inline void udp_lib_hash(struct sock *sk) | |||
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | extern void udp_lib_unhash(struct sock *sk); | 153 | extern void udp_lib_unhash(struct sock *sk); |
| 154 | extern void udp_lib_rehash(struct sock *sk, u16 new_hash); | ||
| 154 | 155 | ||
| 155 | static inline void udp_lib_close(struct sock *sk, long timeout) | 156 | static inline void udp_lib_close(struct sock *sk, long timeout) |
| 156 | { | 157 | { |
diff --git a/kernel/compat.c b/kernel/compat.c index e167efce8423..c9e2ec0b34a8 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info) | |||
| 1126 | 1126 | ||
| 1127 | return 0; | 1127 | return 0; |
| 1128 | } | 1128 | } |
| 1129 | |||
| 1130 | /* | ||
| 1131 | * Allocate user-space memory for the duration of a single system call, | ||
| 1132 | * in order to marshall parameters inside a compat thunk. | ||
| 1133 | */ | ||
| 1134 | void __user *compat_alloc_user_space(unsigned long len) | ||
| 1135 | { | ||
| 1136 | void __user *ptr; | ||
| 1137 | |||
| 1138 | /* If len would occupy more than half of the entire compat space... */ | ||
| 1139 | if (unlikely(len > (((compat_uptr_t)~0) >> 1))) | ||
| 1140 | return NULL; | ||
| 1141 | |||
| 1142 | ptr = arch_compat_alloc_user_space(len); | ||
| 1143 | |||
| 1144 | if (unlikely(!access_ok(VERIFY_WRITE, ptr, len))) | ||
| 1145 | return NULL; | ||
| 1146 | |||
| 1147 | return ptr; | ||
| 1148 | } | ||
| 1149 | EXPORT_SYMBOL_GPL(compat_alloc_user_space); | ||
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 657555a5f30f..db5b56064687 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -5761,15 +5761,15 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) | |||
| 5761 | { | 5761 | { |
| 5762 | unsigned int cpu = (long)hcpu; | 5762 | unsigned int cpu = (long)hcpu; |
| 5763 | 5763 | ||
| 5764 | switch (action) { | 5764 | switch (action & ~CPU_TASKS_FROZEN) { |
| 5765 | 5765 | ||
| 5766 | case CPU_UP_PREPARE: | 5766 | case CPU_UP_PREPARE: |
| 5767 | case CPU_UP_PREPARE_FROZEN: | 5767 | case CPU_DOWN_FAILED: |
| 5768 | perf_event_init_cpu(cpu); | 5768 | perf_event_init_cpu(cpu); |
| 5769 | break; | 5769 | break; |
| 5770 | 5770 | ||
| 5771 | case CPU_UP_CANCELED: | ||
| 5771 | case CPU_DOWN_PREPARE: | 5772 | case CPU_DOWN_PREPARE: |
| 5772 | case CPU_DOWN_PREPARE_FROZEN: | ||
| 5773 | perf_event_exit_cpu(cpu); | 5773 | perf_event_exit_cpu(cpu); |
| 5774 | break; | 5774 | break; |
| 5775 | 5775 | ||
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c index b7e4c362361b..645e541a45f6 100644 --- a/kernel/pm_qos_params.c +++ b/kernel/pm_qos_params.c | |||
| @@ -389,10 +389,12 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, | |||
| 389 | } else if (count == 11) { /* len('0x12345678/0') */ | 389 | } else if (count == 11) { /* len('0x12345678/0') */ |
| 390 | if (copy_from_user(ascii_value, buf, 11)) | 390 | if (copy_from_user(ascii_value, buf, 11)) |
| 391 | return -EFAULT; | 391 | return -EFAULT; |
| 392 | if (strlen(ascii_value) != 10) | ||
| 393 | return -EINVAL; | ||
| 392 | x = sscanf(ascii_value, "%x", &value); | 394 | x = sscanf(ascii_value, "%x", &value); |
| 393 | if (x != 1) | 395 | if (x != 1) |
| 394 | return -EINVAL; | 396 | return -EINVAL; |
| 395 | pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value); | 397 | pr_debug("%s, %d, 0x%x\n", ascii_value, x, value); |
| 396 | } else | 398 | } else |
| 397 | return -EINVAL; | 399 | return -EINVAL; |
| 398 | 400 | ||
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f6cd6faf84fd..d3f795f01bbc 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
| @@ -1121,9 +1121,19 @@ static unsigned long preallocate_image_pages(unsigned long nr_pages, gfp_t mask) | |||
| 1121 | return nr_alloc; | 1121 | return nr_alloc; |
| 1122 | } | 1122 | } |
| 1123 | 1123 | ||
| 1124 | static unsigned long preallocate_image_memory(unsigned long nr_pages) | 1124 | static unsigned long preallocate_image_memory(unsigned long nr_pages, |
| 1125 | unsigned long avail_normal) | ||
| 1125 | { | 1126 | { |
| 1126 | return preallocate_image_pages(nr_pages, GFP_IMAGE); | 1127 | unsigned long alloc; |
| 1128 | |||
| 1129 | if (avail_normal <= alloc_normal) | ||
| 1130 | return 0; | ||
| 1131 | |||
| 1132 | alloc = avail_normal - alloc_normal; | ||
| 1133 | if (nr_pages < alloc) | ||
| 1134 | alloc = nr_pages; | ||
| 1135 | |||
| 1136 | return preallocate_image_pages(alloc, GFP_IMAGE); | ||
| 1127 | } | 1137 | } |
| 1128 | 1138 | ||
| 1129 | #ifdef CONFIG_HIGHMEM | 1139 | #ifdef CONFIG_HIGHMEM |
| @@ -1169,15 +1179,22 @@ static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages, | |||
| 1169 | */ | 1179 | */ |
| 1170 | static void free_unnecessary_pages(void) | 1180 | static void free_unnecessary_pages(void) |
| 1171 | { | 1181 | { |
| 1172 | unsigned long save_highmem, to_free_normal, to_free_highmem; | 1182 | unsigned long save, to_free_normal, to_free_highmem; |
| 1173 | 1183 | ||
| 1174 | to_free_normal = alloc_normal - count_data_pages(); | 1184 | save = count_data_pages(); |
| 1175 | save_highmem = count_highmem_pages(); | 1185 | if (alloc_normal >= save) { |
| 1176 | if (alloc_highmem > save_highmem) { | 1186 | to_free_normal = alloc_normal - save; |
| 1177 | to_free_highmem = alloc_highmem - save_highmem; | 1187 | save = 0; |
| 1188 | } else { | ||
| 1189 | to_free_normal = 0; | ||
| 1190 | save -= alloc_normal; | ||
| 1191 | } | ||
| 1192 | save += count_highmem_pages(); | ||
| 1193 | if (alloc_highmem >= save) { | ||
| 1194 | to_free_highmem = alloc_highmem - save; | ||
| 1178 | } else { | 1195 | } else { |
| 1179 | to_free_highmem = 0; | 1196 | to_free_highmem = 0; |
| 1180 | to_free_normal -= save_highmem - alloc_highmem; | 1197 | to_free_normal -= save - alloc_highmem; |
| 1181 | } | 1198 | } |
| 1182 | 1199 | ||
| 1183 | memory_bm_position_reset(©_bm); | 1200 | memory_bm_position_reset(©_bm); |
| @@ -1258,7 +1275,7 @@ int hibernate_preallocate_memory(void) | |||
| 1258 | { | 1275 | { |
| 1259 | struct zone *zone; | 1276 | struct zone *zone; |
| 1260 | unsigned long saveable, size, max_size, count, highmem, pages = 0; | 1277 | unsigned long saveable, size, max_size, count, highmem, pages = 0; |
| 1261 | unsigned long alloc, save_highmem, pages_highmem; | 1278 | unsigned long alloc, save_highmem, pages_highmem, avail_normal; |
| 1262 | struct timeval start, stop; | 1279 | struct timeval start, stop; |
| 1263 | int error; | 1280 | int error; |
| 1264 | 1281 | ||
| @@ -1295,6 +1312,7 @@ int hibernate_preallocate_memory(void) | |||
| 1295 | else | 1312 | else |
| 1296 | count += zone_page_state(zone, NR_FREE_PAGES); | 1313 | count += zone_page_state(zone, NR_FREE_PAGES); |
| 1297 | } | 1314 | } |
| 1315 | avail_normal = count; | ||
| 1298 | count += highmem; | 1316 | count += highmem; |
| 1299 | count -= totalreserve_pages; | 1317 | count -= totalreserve_pages; |
| 1300 | 1318 | ||
| @@ -1309,12 +1327,21 @@ int hibernate_preallocate_memory(void) | |||
| 1309 | */ | 1327 | */ |
| 1310 | if (size >= saveable) { | 1328 | if (size >= saveable) { |
| 1311 | pages = preallocate_image_highmem(save_highmem); | 1329 | pages = preallocate_image_highmem(save_highmem); |
| 1312 | pages += preallocate_image_memory(saveable - pages); | 1330 | pages += preallocate_image_memory(saveable - pages, avail_normal); |
| 1313 | goto out; | 1331 | goto out; |
| 1314 | } | 1332 | } |
| 1315 | 1333 | ||
| 1316 | /* Estimate the minimum size of the image. */ | 1334 | /* Estimate the minimum size of the image. */ |
| 1317 | pages = minimum_image_size(saveable); | 1335 | pages = minimum_image_size(saveable); |
| 1336 | /* | ||
| 1337 | * To avoid excessive pressure on the normal zone, leave room in it to | ||
| 1338 | * accommodate an image of the minimum size (unless it's already too | ||
| 1339 | * small, in which case don't preallocate pages from it at all). | ||
| 1340 | */ | ||
| 1341 | if (avail_normal > pages) | ||
| 1342 | avail_normal -= pages; | ||
| 1343 | else | ||
| 1344 | avail_normal = 0; | ||
| 1318 | if (size < pages) | 1345 | if (size < pages) |
| 1319 | size = min_t(unsigned long, pages, max_size); | 1346 | size = min_t(unsigned long, pages, max_size); |
| 1320 | 1347 | ||
| @@ -1335,16 +1362,34 @@ int hibernate_preallocate_memory(void) | |||
| 1335 | */ | 1362 | */ |
| 1336 | pages_highmem = preallocate_image_highmem(highmem / 2); | 1363 | pages_highmem = preallocate_image_highmem(highmem / 2); |
| 1337 | alloc = (count - max_size) - pages_highmem; | 1364 | alloc = (count - max_size) - pages_highmem; |
| 1338 | pages = preallocate_image_memory(alloc); | 1365 | pages = preallocate_image_memory(alloc, avail_normal); |
| 1339 | if (pages < alloc) | 1366 | if (pages < alloc) { |
| 1340 | goto err_out; | 1367 | /* We have exhausted non-highmem pages, try highmem. */ |
| 1341 | size = max_size - size; | 1368 | alloc -= pages; |
| 1342 | alloc = size; | 1369 | pages += pages_highmem; |
| 1343 | size = preallocate_highmem_fraction(size, highmem, count); | 1370 | pages_highmem = preallocate_image_highmem(alloc); |
| 1344 | pages_highmem += size; | 1371 | if (pages_highmem < alloc) |
| 1345 | alloc -= size; | 1372 | goto err_out; |
| 1346 | pages += preallocate_image_memory(alloc); | 1373 | pages += pages_highmem; |
| 1347 | pages += pages_highmem; | 1374 | /* |
| 1375 | * size is the desired number of saveable pages to leave in | ||
| 1376 | * memory, so try to preallocate (all memory - size) pages. | ||
| 1377 | */ | ||
| 1378 | alloc = (count - pages) - size; | ||
| 1379 | pages += preallocate_image_highmem(alloc); | ||
| 1380 | } else { | ||
| 1381 | /* | ||
| 1382 | * There are approximately max_size saveable pages at this point | ||
| 1383 | * and we want to reduce this number down to size. | ||
| 1384 | */ | ||
| 1385 | alloc = max_size - size; | ||
| 1386 | size = preallocate_highmem_fraction(alloc, highmem, count); | ||
| 1387 | pages_highmem += size; | ||
| 1388 | alloc -= size; | ||
| 1389 | size = preallocate_image_memory(alloc, avail_normal); | ||
| 1390 | pages_highmem += preallocate_image_highmem(alloc - size); | ||
| 1391 | pages += pages_highmem + size; | ||
| 1392 | } | ||
| 1348 | 1393 | ||
| 1349 | /* | 1394 | /* |
| 1350 | * We only need as many page frames for the image as there are saveable | 1395 | * We only need as many page frames for the image as there are saveable |
diff --git a/kernel/sched.c b/kernel/sched.c index 09b574e7f4df..ed09d4f2a69c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -1294,6 +1294,10 @@ static void resched_task(struct task_struct *p) | |||
| 1294 | static void sched_rt_avg_update(struct rq *rq, u64 rt_delta) | 1294 | static void sched_rt_avg_update(struct rq *rq, u64 rt_delta) |
| 1295 | { | 1295 | { |
| 1296 | } | 1296 | } |
| 1297 | |||
| 1298 | static void sched_avg_update(struct rq *rq) | ||
| 1299 | { | ||
| 1300 | } | ||
| 1297 | #endif /* CONFIG_SMP */ | 1301 | #endif /* CONFIG_SMP */ |
| 1298 | 1302 | ||
| 1299 | #if BITS_PER_LONG == 32 | 1303 | #if BITS_PER_LONG == 32 |
| @@ -3182,6 +3186,8 @@ static void update_cpu_load(struct rq *this_rq) | |||
| 3182 | 3186 | ||
| 3183 | this_rq->cpu_load[i] = (old_load * (scale - 1) + new_load) >> i; | 3187 | this_rq->cpu_load[i] = (old_load * (scale - 1) + new_load) >> i; |
| 3184 | } | 3188 | } |
| 3189 | |||
| 3190 | sched_avg_update(this_rq); | ||
| 3185 | } | 3191 | } |
| 3186 | 3192 | ||
| 3187 | static void update_cpu_load_active(struct rq *this_rq) | 3193 | static void update_cpu_load_active(struct rq *this_rq) |
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 134f7edb30c6..a171138a9402 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
| @@ -54,13 +54,13 @@ enum sched_tunable_scaling sysctl_sched_tunable_scaling | |||
| 54 | * Minimal preemption granularity for CPU-bound tasks: | 54 | * Minimal preemption granularity for CPU-bound tasks: |
| 55 | * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds) | 55 | * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds) |
| 56 | */ | 56 | */ |
| 57 | unsigned int sysctl_sched_min_granularity = 2000000ULL; | 57 | unsigned int sysctl_sched_min_granularity = 750000ULL; |
| 58 | unsigned int normalized_sysctl_sched_min_granularity = 2000000ULL; | 58 | unsigned int normalized_sysctl_sched_min_granularity = 750000ULL; |
| 59 | 59 | ||
| 60 | /* | 60 | /* |
| 61 | * is kept at sysctl_sched_latency / sysctl_sched_min_granularity | 61 | * is kept at sysctl_sched_latency / sysctl_sched_min_granularity |
| 62 | */ | 62 | */ |
| 63 | static unsigned int sched_nr_latency = 3; | 63 | static unsigned int sched_nr_latency = 8; |
| 64 | 64 | ||
| 65 | /* | 65 | /* |
| 66 | * After fork, child runs first. If set to 0 (default) then | 66 | * After fork, child runs first. If set to 0 (default) then |
| @@ -2267,8 +2267,6 @@ unsigned long scale_rt_power(int cpu) | |||
| 2267 | struct rq *rq = cpu_rq(cpu); | 2267 | struct rq *rq = cpu_rq(cpu); |
| 2268 | u64 total, available; | 2268 | u64 total, available; |
| 2269 | 2269 | ||
| 2270 | sched_avg_update(rq); | ||
| 2271 | |||
| 2272 | total = sched_avg_period() + (rq->clock - rq->age_stamp); | 2270 | total = sched_avg_period() + (rq->clock - rq->age_stamp); |
| 2273 | available = total - rq->rt_avg; | 2271 | available = total - rq->rt_avg; |
| 2274 | 2272 | ||
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 7cb1f45a1de1..fa7ece649fe1 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -1510,6 +1510,8 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
| 1510 | if (*pos > 0) | 1510 | if (*pos > 0) |
| 1511 | return t_hash_start(m, pos); | 1511 | return t_hash_start(m, pos); |
| 1512 | iter->flags |= FTRACE_ITER_PRINTALL; | 1512 | iter->flags |= FTRACE_ITER_PRINTALL; |
| 1513 | /* reset in case of seek/pread */ | ||
| 1514 | iter->flags &= ~FTRACE_ITER_HASH; | ||
| 1513 | return iter; | 1515 | return iter; |
| 1514 | } | 1516 | } |
| 1515 | 1517 | ||
| @@ -2416,7 +2418,7 @@ static const struct file_operations ftrace_filter_fops = { | |||
| 2416 | .open = ftrace_filter_open, | 2418 | .open = ftrace_filter_open, |
| 2417 | .read = seq_read, | 2419 | .read = seq_read, |
| 2418 | .write = ftrace_filter_write, | 2420 | .write = ftrace_filter_write, |
| 2419 | .llseek = ftrace_regex_lseek, | 2421 | .llseek = no_llseek, |
| 2420 | .release = ftrace_filter_release, | 2422 | .release = ftrace_filter_release, |
| 2421 | }; | 2423 | }; |
| 2422 | 2424 | ||
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 000e6e85b445..31cc4cb0dbf2 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c | |||
| @@ -91,6 +91,8 @@ int perf_trace_init(struct perf_event *p_event) | |||
| 91 | tp_event->class && tp_event->class->reg && | 91 | tp_event->class && tp_event->class->reg && |
| 92 | try_module_get(tp_event->mod)) { | 92 | try_module_get(tp_event->mod)) { |
| 93 | ret = perf_trace_event_init(tp_event, p_event); | 93 | ret = perf_trace_event_init(tp_event, p_event); |
| 94 | if (ret) | ||
| 95 | module_put(tp_event->mod); | ||
| 94 | break; | 96 | break; |
| 95 | } | 97 | } |
| 96 | } | 98 | } |
| @@ -146,6 +148,7 @@ void perf_trace_destroy(struct perf_event *p_event) | |||
| 146 | } | 148 | } |
| 147 | } | 149 | } |
| 148 | out: | 150 | out: |
| 151 | module_put(tp_event->mod); | ||
| 149 | mutex_unlock(&event_mutex); | 152 | mutex_unlock(&event_mutex); |
| 150 | } | 153 | } |
| 151 | 154 | ||
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 8b27c9849b42..544301d29dee 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -514,8 +514,8 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); | |||
| 514 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 514 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, |
| 515 | struct pt_regs *regs); | 515 | struct pt_regs *regs); |
| 516 | 516 | ||
| 517 | /* Check the name is good for event/group */ | 517 | /* Check the name is good for event/group/fields */ |
| 518 | static int check_event_name(const char *name) | 518 | static int is_good_name(const char *name) |
| 519 | { | 519 | { |
| 520 | if (!isalpha(*name) && *name != '_') | 520 | if (!isalpha(*name) && *name != '_') |
| 521 | return 0; | 521 | return 0; |
| @@ -557,7 +557,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 557 | else | 557 | else |
| 558 | tp->rp.kp.pre_handler = kprobe_dispatcher; | 558 | tp->rp.kp.pre_handler = kprobe_dispatcher; |
| 559 | 559 | ||
| 560 | if (!event || !check_event_name(event)) { | 560 | if (!event || !is_good_name(event)) { |
| 561 | ret = -EINVAL; | 561 | ret = -EINVAL; |
| 562 | goto error; | 562 | goto error; |
| 563 | } | 563 | } |
| @@ -567,7 +567,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 567 | if (!tp->call.name) | 567 | if (!tp->call.name) |
| 568 | goto error; | 568 | goto error; |
| 569 | 569 | ||
| 570 | if (!group || !check_event_name(group)) { | 570 | if (!group || !is_good_name(group)) { |
| 571 | ret = -EINVAL; | 571 | ret = -EINVAL; |
| 572 | goto error; | 572 | goto error; |
| 573 | } | 573 | } |
| @@ -883,7 +883,7 @@ static int create_trace_probe(int argc, char **argv) | |||
| 883 | int i, ret = 0; | 883 | int i, ret = 0; |
| 884 | int is_return = 0, is_delete = 0; | 884 | int is_return = 0, is_delete = 0; |
| 885 | char *symbol = NULL, *event = NULL, *group = NULL; | 885 | char *symbol = NULL, *event = NULL, *group = NULL; |
| 886 | char *arg, *tmp; | 886 | char *arg; |
| 887 | unsigned long offset = 0; | 887 | unsigned long offset = 0; |
| 888 | void *addr = NULL; | 888 | void *addr = NULL; |
| 889 | char buf[MAX_EVENT_NAME_LEN]; | 889 | char buf[MAX_EVENT_NAME_LEN]; |
| @@ -992,26 +992,36 @@ static int create_trace_probe(int argc, char **argv) | |||
| 992 | /* parse arguments */ | 992 | /* parse arguments */ |
| 993 | ret = 0; | 993 | ret = 0; |
| 994 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { | 994 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { |
| 995 | /* Increment count for freeing args in error case */ | ||
| 996 | tp->nr_args++; | ||
| 997 | |||
| 995 | /* Parse argument name */ | 998 | /* Parse argument name */ |
| 996 | arg = strchr(argv[i], '='); | 999 | arg = strchr(argv[i], '='); |
| 997 | if (arg) | 1000 | if (arg) { |
| 998 | *arg++ = '\0'; | 1001 | *arg++ = '\0'; |
| 999 | else | 1002 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); |
| 1003 | } else { | ||
| 1000 | arg = argv[i]; | 1004 | arg = argv[i]; |
| 1005 | /* If argument name is omitted, set "argN" */ | ||
| 1006 | snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1); | ||
| 1007 | tp->args[i].name = kstrdup(buf, GFP_KERNEL); | ||
| 1008 | } | ||
| 1001 | 1009 | ||
| 1002 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); | ||
| 1003 | if (!tp->args[i].name) { | 1010 | if (!tp->args[i].name) { |
| 1004 | pr_info("Failed to allocate argument%d name '%s'.\n", | 1011 | pr_info("Failed to allocate argument[%d] name.\n", i); |
| 1005 | i, argv[i]); | ||
| 1006 | ret = -ENOMEM; | 1012 | ret = -ENOMEM; |
| 1007 | goto error; | 1013 | goto error; |
| 1008 | } | 1014 | } |
| 1009 | tmp = strchr(tp->args[i].name, ':'); | 1015 | |
| 1010 | if (tmp) | 1016 | if (!is_good_name(tp->args[i].name)) { |
| 1011 | *tmp = '_'; /* convert : to _ */ | 1017 | pr_info("Invalid argument[%d] name: %s\n", |
| 1018 | i, tp->args[i].name); | ||
| 1019 | ret = -EINVAL; | ||
| 1020 | goto error; | ||
| 1021 | } | ||
| 1012 | 1022 | ||
| 1013 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { | 1023 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { |
| 1014 | pr_info("Argument%d name '%s' conflicts with " | 1024 | pr_info("Argument[%d] name '%s' conflicts with " |
| 1015 | "another field.\n", i, argv[i]); | 1025 | "another field.\n", i, argv[i]); |
| 1016 | ret = -EINVAL; | 1026 | ret = -EINVAL; |
| 1017 | goto error; | 1027 | goto error; |
| @@ -1020,12 +1030,9 @@ static int create_trace_probe(int argc, char **argv) | |||
| 1020 | /* Parse fetch argument */ | 1030 | /* Parse fetch argument */ |
| 1021 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); | 1031 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); |
| 1022 | if (ret) { | 1032 | if (ret) { |
| 1023 | pr_info("Parse error at argument%d. (%d)\n", i, ret); | 1033 | pr_info("Parse error at argument[%d]. (%d)\n", i, ret); |
| 1024 | kfree(tp->args[i].name); | ||
| 1025 | goto error; | 1034 | goto error; |
| 1026 | } | 1035 | } |
| 1027 | |||
| 1028 | tp->nr_args++; | ||
| 1029 | } | 1036 | } |
| 1030 | 1037 | ||
| 1031 | ret = register_trace_probe(tp); | 1038 | ret = register_trace_probe(tp); |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 727f24e563ae..f77afd939229 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -1,19 +1,26 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/kernel/workqueue.c | 2 | * kernel/workqueue.c - generic async execution with shared worker pool |
| 3 | * | 3 | * |
| 4 | * Generic mechanism for defining kernel helper threads for running | 4 | * Copyright (C) 2002 Ingo Molnar |
| 5 | * arbitrary tasks in process context. | ||
| 6 | * | 5 | * |
| 7 | * Started by Ingo Molnar, Copyright (C) 2002 | 6 | * Derived from the taskqueue/keventd code by: |
| 7 | * David Woodhouse <dwmw2@infradead.org> | ||
| 8 | * Andrew Morton | ||
| 9 | * Kai Petzke <wpp@marie.physik.tu-berlin.de> | ||
| 10 | * Theodore Ts'o <tytso@mit.edu> | ||
| 8 | * | 11 | * |
| 9 | * Derived from the taskqueue/keventd code by: | 12 | * Made to use alloc_percpu by Christoph Lameter. |
| 10 | * | 13 | * |
| 11 | * David Woodhouse <dwmw2@infradead.org> | 14 | * Copyright (C) 2010 SUSE Linux Products GmbH |
| 12 | * Andrew Morton | 15 | * Copyright (C) 2010 Tejun Heo <tj@kernel.org> |
| 13 | * Kai Petzke <wpp@marie.physik.tu-berlin.de> | ||
| 14 | * Theodore Ts'o <tytso@mit.edu> | ||
| 15 | * | 16 | * |
| 16 | * Made to use alloc_percpu by Christoph Lameter. | 17 | * This is the generic async execution mechanism. Work items as are |
| 18 | * executed in process context. The worker pool is shared and | ||
| 19 | * automatically managed. There is one worker pool for each CPU and | ||
| 20 | * one extra for works which are better served by workers which are | ||
| 21 | * not bound to any specific CPU. | ||
| 22 | * | ||
| 23 | * Please read Documentation/workqueue.txt for details. | ||
| 17 | */ | 24 | */ |
| 18 | 25 | ||
| 19 | #include <linux/module.h> | 26 | #include <linux/module.h> |
diff --git a/lib/scatterlist.c b/lib/scatterlist.c index a5ec42868f99..4ceb05d772ae 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c | |||
| @@ -248,8 +248,18 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, | |||
| 248 | left -= sg_size; | 248 | left -= sg_size; |
| 249 | 249 | ||
| 250 | sg = alloc_fn(alloc_size, gfp_mask); | 250 | sg = alloc_fn(alloc_size, gfp_mask); |
| 251 | if (unlikely(!sg)) | 251 | if (unlikely(!sg)) { |
| 252 | return -ENOMEM; | 252 | /* |
| 253 | * Adjust entry count to reflect that the last | ||
| 254 | * entry of the previous table won't be used for | ||
| 255 | * linkage. Without this, sg_kfree() may get | ||
| 256 | * confused. | ||
| 257 | */ | ||
| 258 | if (prv) | ||
| 259 | table->nents = ++table->orig_nents; | ||
| 260 | |||
| 261 | return -ENOMEM; | ||
| 262 | } | ||
| 253 | 263 | ||
| 254 | sg_init_table(sg, alloc_size); | 264 | sg_init_table(sg, alloc_size); |
| 255 | table->nents = table->orig_nents += sg_size; | 265 | table->nents = table->orig_nents += sg_size; |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index eaa4a5bbe063..c2bf86f470ed 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
| @@ -445,8 +445,8 @@ static int bdi_forker_thread(void *ptr) | |||
| 445 | switch (action) { | 445 | switch (action) { |
| 446 | case FORK_THREAD: | 446 | case FORK_THREAD: |
| 447 | __set_current_state(TASK_RUNNING); | 447 | __set_current_state(TASK_RUNNING); |
| 448 | task = kthread_run(bdi_writeback_thread, &bdi->wb, "flush-%s", | 448 | task = kthread_create(bdi_writeback_thread, &bdi->wb, |
| 449 | dev_name(bdi->dev)); | 449 | "flush-%s", dev_name(bdi->dev)); |
| 450 | if (IS_ERR(task)) { | 450 | if (IS_ERR(task)) { |
| 451 | /* | 451 | /* |
| 452 | * If thread creation fails, force writeout of | 452 | * If thread creation fails, force writeout of |
| @@ -457,10 +457,13 @@ static int bdi_forker_thread(void *ptr) | |||
| 457 | /* | 457 | /* |
| 458 | * The spinlock makes sure we do not lose | 458 | * The spinlock makes sure we do not lose |
| 459 | * wake-ups when racing with 'bdi_queue_work()'. | 459 | * wake-ups when racing with 'bdi_queue_work()'. |
| 460 | * And as soon as the bdi thread is visible, we | ||
| 461 | * can start it. | ||
| 460 | */ | 462 | */ |
| 461 | spin_lock_bh(&bdi->wb_lock); | 463 | spin_lock_bh(&bdi->wb_lock); |
| 462 | bdi->wb.task = task; | 464 | bdi->wb.task = task; |
| 463 | spin_unlock_bh(&bdi->wb_lock); | 465 | spin_unlock_bh(&bdi->wb_lock); |
| 466 | wake_up_process(task); | ||
| 464 | } | 467 | } |
| 465 | break; | 468 | break; |
| 466 | 469 | ||
diff --git a/net/9p/client.c b/net/9p/client.c index dc6f2f26d023..9eb72505308f 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -331,8 +331,10 @@ static void p9_tag_cleanup(struct p9_client *c) | |||
| 331 | } | 331 | } |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | if (c->tagpool) | 334 | if (c->tagpool) { |
| 335 | p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */ | ||
| 335 | p9_idpool_destroy(c->tagpool); | 336 | p9_idpool_destroy(c->tagpool); |
| 337 | } | ||
| 336 | 338 | ||
| 337 | /* free requests associated with tags */ | 339 | /* free requests associated with tags */ |
| 338 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { | 340 | for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { |
| @@ -944,6 +946,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
| 944 | int16_t nwqids, count; | 946 | int16_t nwqids, count; |
| 945 | 947 | ||
| 946 | err = 0; | 948 | err = 0; |
| 949 | wqids = NULL; | ||
| 947 | clnt = oldfid->clnt; | 950 | clnt = oldfid->clnt; |
| 948 | if (clone) { | 951 | if (clone) { |
| 949 | fid = p9_fid_create(clnt); | 952 | fid = p9_fid_create(clnt); |
| @@ -994,9 +997,11 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
| 994 | else | 997 | else |
| 995 | fid->qid = oldfid->qid; | 998 | fid->qid = oldfid->qid; |
| 996 | 999 | ||
| 1000 | kfree(wqids); | ||
| 997 | return fid; | 1001 | return fid; |
| 998 | 1002 | ||
| 999 | clunk_fid: | 1003 | clunk_fid: |
| 1004 | kfree(wqids); | ||
| 1000 | p9_client_clunk(fid); | 1005 | p9_client_clunk(fid); |
| 1001 | fid = NULL; | 1006 | fid = NULL; |
| 1002 | 1007 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index 3721fbb9a83c..b9b22a3c4c8f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2058,16 +2058,16 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, | |||
| 2058 | struct sk_buff *skb) | 2058 | struct sk_buff *skb) |
| 2059 | { | 2059 | { |
| 2060 | int queue_index; | 2060 | int queue_index; |
| 2061 | struct sock *sk = skb->sk; | 2061 | const struct net_device_ops *ops = dev->netdev_ops; |
| 2062 | 2062 | ||
| 2063 | queue_index = sk_tx_queue_get(sk); | 2063 | if (ops->ndo_select_queue) { |
| 2064 | if (queue_index < 0) { | 2064 | queue_index = ops->ndo_select_queue(dev, skb); |
| 2065 | const struct net_device_ops *ops = dev->netdev_ops; | 2065 | queue_index = dev_cap_txqueue(dev, queue_index); |
| 2066 | } else { | ||
| 2067 | struct sock *sk = skb->sk; | ||
| 2068 | queue_index = sk_tx_queue_get(sk); | ||
| 2069 | if (queue_index < 0) { | ||
| 2066 | 2070 | ||
| 2067 | if (ops->ndo_select_queue) { | ||
| 2068 | queue_index = ops->ndo_select_queue(dev, skb); | ||
| 2069 | queue_index = dev_cap_txqueue(dev, queue_index); | ||
| 2070 | } else { | ||
| 2071 | queue_index = 0; | 2071 | queue_index = 0; |
| 2072 | if (dev->real_num_tx_queues > 1) | 2072 | if (dev->real_num_tx_queues > 1) |
| 2073 | queue_index = skb_tx_hash(dev, skb); | 2073 | queue_index = skb_tx_hash(dev, skb); |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 26396ff67cf9..c83b421341c0 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -2706,7 +2706,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
| 2706 | } else if (skb_gro_len(p) != pinfo->gso_size) | 2706 | } else if (skb_gro_len(p) != pinfo->gso_size) |
| 2707 | return -E2BIG; | 2707 | return -E2BIG; |
| 2708 | 2708 | ||
| 2709 | headroom = NET_SKB_PAD + NET_IP_ALIGN; | 2709 | headroom = skb_headroom(p); |
| 2710 | nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC); | 2710 | nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC); |
| 2711 | if (unlikely(!nskb)) | 2711 | if (unlikely(!nskb)) |
| 2712 | return -ENOMEM; | 2712 | return -ENOMEM; |
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index f0550941df7b..721a8a37b45c 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c | |||
| @@ -62,8 +62,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
| 62 | } | 62 | } |
| 63 | if (!inet->inet_saddr) | 63 | if (!inet->inet_saddr) |
| 64 | inet->inet_saddr = rt->rt_src; /* Update source address */ | 64 | inet->inet_saddr = rt->rt_src; /* Update source address */ |
| 65 | if (!inet->inet_rcv_saddr) | 65 | if (!inet->inet_rcv_saddr) { |
| 66 | inet->inet_rcv_saddr = rt->rt_src; | 66 | inet->inet_rcv_saddr = rt->rt_src; |
| 67 | if (sk->sk_prot->rehash) | ||
| 68 | sk->sk_prot->rehash(sk); | ||
| 69 | } | ||
| 67 | inet->inet_daddr = rt->rt_dst; | 70 | inet->inet_daddr = rt->rt_dst; |
| 68 | inet->inet_dport = usin->sin_port; | 71 | inet->inet_dport = usin->sin_port; |
| 69 | sk->sk_state = TCP_ESTABLISHED; | 72 | sk->sk_state = TCP_ESTABLISHED; |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index a43968918350..7d02a9f999fa 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -246,6 +246,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
| 246 | 246 | ||
| 247 | struct fib_result res; | 247 | struct fib_result res; |
| 248 | int no_addr, rpf, accept_local; | 248 | int no_addr, rpf, accept_local; |
| 249 | bool dev_match; | ||
| 249 | int ret; | 250 | int ret; |
| 250 | struct net *net; | 251 | struct net *net; |
| 251 | 252 | ||
| @@ -273,12 +274,22 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
| 273 | } | 274 | } |
| 274 | *spec_dst = FIB_RES_PREFSRC(res); | 275 | *spec_dst = FIB_RES_PREFSRC(res); |
| 275 | fib_combine_itag(itag, &res); | 276 | fib_combine_itag(itag, &res); |
| 277 | dev_match = false; | ||
| 278 | |||
| 276 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 279 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
| 277 | if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1) | 280 | for (ret = 0; ret < res.fi->fib_nhs; ret++) { |
| 281 | struct fib_nh *nh = &res.fi->fib_nh[ret]; | ||
| 282 | |||
| 283 | if (nh->nh_dev == dev) { | ||
| 284 | dev_match = true; | ||
| 285 | break; | ||
| 286 | } | ||
| 287 | } | ||
| 278 | #else | 288 | #else |
| 279 | if (FIB_RES_DEV(res) == dev) | 289 | if (FIB_RES_DEV(res) == dev) |
| 290 | dev_match = true; | ||
| 280 | #endif | 291 | #endif |
| 281 | { | 292 | if (dev_match) { |
| 282 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; | 293 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; |
| 283 | fib_res_put(&res); | 294 | fib_res_put(&res); |
| 284 | return ret; | 295 | return ret; |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 79d057a939ba..4a8e370862bc 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -186,7 +186,9 @@ static inline struct tnode *node_parent_rcu(struct node *node) | |||
| 186 | { | 186 | { |
| 187 | struct tnode *ret = node_parent(node); | 187 | struct tnode *ret = node_parent(node); |
| 188 | 188 | ||
| 189 | return rcu_dereference(ret); | 189 | return rcu_dereference_check(ret, |
| 190 | rcu_read_lock_held() || | ||
| 191 | lockdep_rtnl_is_held()); | ||
| 190 | } | 192 | } |
| 191 | 193 | ||
| 192 | /* Same as rcu_assign_pointer | 194 | /* Same as rcu_assign_pointer |
| @@ -1753,7 +1755,9 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c) | |||
| 1753 | 1755 | ||
| 1754 | static struct leaf *trie_firstleaf(struct trie *t) | 1756 | static struct leaf *trie_firstleaf(struct trie *t) |
| 1755 | { | 1757 | { |
| 1756 | struct tnode *n = (struct tnode *) rcu_dereference(t->trie); | 1758 | struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie, |
| 1759 | rcu_read_lock_held() || | ||
| 1760 | lockdep_rtnl_is_held()); | ||
| 1757 | 1761 | ||
| 1758 | if (!n) | 1762 | if (!n) |
| 1759 | return NULL; | 1763 | return NULL; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3f56b6e6c6aa..6298f75d5e93 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -2738,6 +2738,11 @@ slow_output: | |||
| 2738 | } | 2738 | } |
| 2739 | EXPORT_SYMBOL_GPL(__ip_route_output_key); | 2739 | EXPORT_SYMBOL_GPL(__ip_route_output_key); |
| 2740 | 2740 | ||
| 2741 | static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie) | ||
| 2742 | { | ||
| 2743 | return NULL; | ||
| 2744 | } | ||
| 2745 | |||
| 2741 | static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | 2746 | static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) |
| 2742 | { | 2747 | { |
| 2743 | } | 2748 | } |
| @@ -2746,7 +2751,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { | |||
| 2746 | .family = AF_INET, | 2751 | .family = AF_INET, |
| 2747 | .protocol = cpu_to_be16(ETH_P_IP), | 2752 | .protocol = cpu_to_be16(ETH_P_IP), |
| 2748 | .destroy = ipv4_dst_destroy, | 2753 | .destroy = ipv4_dst_destroy, |
| 2749 | .check = ipv4_dst_check, | 2754 | .check = ipv4_blackhole_dst_check, |
| 2750 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, | 2755 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, |
| 2751 | .entries = ATOMIC_INIT(0), | 2756 | .entries = ATOMIC_INIT(0), |
| 2752 | }; | 2757 | }; |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 32e0bef60d0a..fb23c2e63b52 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk) | |||
| 1260 | } | 1260 | } |
| 1261 | EXPORT_SYMBOL(udp_lib_unhash); | 1261 | EXPORT_SYMBOL(udp_lib_unhash); |
| 1262 | 1262 | ||
| 1263 | /* | ||
| 1264 | * inet_rcv_saddr was changed, we must rehash secondary hash | ||
| 1265 | */ | ||
| 1266 | void udp_lib_rehash(struct sock *sk, u16 newhash) | ||
| 1267 | { | ||
| 1268 | if (sk_hashed(sk)) { | ||
| 1269 | struct udp_table *udptable = sk->sk_prot->h.udp_table; | ||
| 1270 | struct udp_hslot *hslot, *hslot2, *nhslot2; | ||
| 1271 | |||
| 1272 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); | ||
| 1273 | nhslot2 = udp_hashslot2(udptable, newhash); | ||
| 1274 | udp_sk(sk)->udp_portaddr_hash = newhash; | ||
| 1275 | if (hslot2 != nhslot2) { | ||
| 1276 | hslot = udp_hashslot(udptable, sock_net(sk), | ||
| 1277 | udp_sk(sk)->udp_port_hash); | ||
| 1278 | /* we must lock primary chain too */ | ||
| 1279 | spin_lock_bh(&hslot->lock); | ||
| 1280 | |||
| 1281 | spin_lock(&hslot2->lock); | ||
| 1282 | hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); | ||
| 1283 | hslot2->count--; | ||
| 1284 | spin_unlock(&hslot2->lock); | ||
| 1285 | |||
| 1286 | spin_lock(&nhslot2->lock); | ||
| 1287 | hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, | ||
| 1288 | &nhslot2->head); | ||
| 1289 | nhslot2->count++; | ||
| 1290 | spin_unlock(&nhslot2->lock); | ||
| 1291 | |||
| 1292 | spin_unlock_bh(&hslot->lock); | ||
| 1293 | } | ||
| 1294 | } | ||
| 1295 | } | ||
| 1296 | EXPORT_SYMBOL(udp_lib_rehash); | ||
| 1297 | |||
| 1298 | static void udp_v4_rehash(struct sock *sk) | ||
| 1299 | { | ||
| 1300 | u16 new_hash = udp4_portaddr_hash(sock_net(sk), | ||
| 1301 | inet_sk(sk)->inet_rcv_saddr, | ||
| 1302 | inet_sk(sk)->inet_num); | ||
| 1303 | udp_lib_rehash(sk, new_hash); | ||
| 1304 | } | ||
| 1305 | |||
| 1263 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 1306 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 1264 | { | 1307 | { |
| 1265 | int rc; | 1308 | int rc; |
| @@ -1843,6 +1886,7 @@ struct proto udp_prot = { | |||
| 1843 | .backlog_rcv = __udp_queue_rcv_skb, | 1886 | .backlog_rcv = __udp_queue_rcv_skb, |
| 1844 | .hash = udp_lib_hash, | 1887 | .hash = udp_lib_hash, |
| 1845 | .unhash = udp_lib_unhash, | 1888 | .unhash = udp_lib_unhash, |
| 1889 | .rehash = udp_v4_rehash, | ||
| 1846 | .get_port = udp_v4_get_port, | 1890 | .get_port = udp_v4_get_port, |
| 1847 | .memory_allocated = &udp_memory_allocated, | 1891 | .memory_allocated = &udp_memory_allocated, |
| 1848 | .sysctl_mem = sysctl_udp_mem, | 1892 | .sysctl_mem = sysctl_udp_mem, |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 7d929a22cbc2..ef371aa01ac5 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -105,9 +105,12 @@ ipv4_connected: | |||
| 105 | if (ipv6_addr_any(&np->saddr)) | 105 | if (ipv6_addr_any(&np->saddr)) |
| 106 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); | 106 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); |
| 107 | 107 | ||
| 108 | if (ipv6_addr_any(&np->rcv_saddr)) | 108 | if (ipv6_addr_any(&np->rcv_saddr)) { |
| 109 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, | 109 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, |
| 110 | &np->rcv_saddr); | 110 | &np->rcv_saddr); |
| 111 | if (sk->sk_prot->rehash) | ||
| 112 | sk->sk_prot->rehash(sk); | ||
| 113 | } | ||
| 111 | 114 | ||
| 112 | goto out; | 115 | goto out; |
| 113 | } | 116 | } |
| @@ -181,6 +184,8 @@ ipv4_connected: | |||
| 181 | if (ipv6_addr_any(&np->rcv_saddr)) { | 184 | if (ipv6_addr_any(&np->rcv_saddr)) { |
| 182 | ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); | 185 | ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); |
| 183 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 186 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
| 187 | if (sk->sk_prot->rehash) | ||
| 188 | sk->sk_prot->rehash(sk); | ||
| 184 | } | 189 | } |
| 185 | 190 | ||
| 186 | ip6_dst_store(sk, dst, | 191 | ip6_dst_store(sk, dst, |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 13ef5bc05cf5..578f3c1a16db 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -113,14 +113,6 @@ static void nf_skb_free(struct sk_buff *skb) | |||
| 113 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | 113 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | /* Memory Tracking Functions. */ | ||
| 117 | static void frag_kfree_skb(struct sk_buff *skb) | ||
| 118 | { | ||
| 119 | atomic_sub(skb->truesize, &nf_init_frags.mem); | ||
| 120 | nf_skb_free(skb); | ||
| 121 | kfree_skb(skb); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* Destruction primitives. */ | 116 | /* Destruction primitives. */ |
| 125 | 117 | ||
| 126 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) | 118 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) |
| @@ -282,66 +274,22 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 282 | } | 274 | } |
| 283 | 275 | ||
| 284 | found: | 276 | found: |
| 285 | /* We found where to put this one. Check for overlap with | 277 | /* RFC5722, Section 4: |
| 286 | * preceding fragment, and, if needed, align things so that | 278 | * When reassembling an IPv6 datagram, if |
| 287 | * any overlaps are eliminated. | 279 | * one or more its constituent fragments is determined to be an |
| 288 | */ | 280 | * overlapping fragment, the entire datagram (and any constituent |
| 289 | if (prev) { | 281 | * fragments, including those not yet received) MUST be silently |
| 290 | int i = (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset; | 282 | * discarded. |
| 291 | |||
| 292 | if (i > 0) { | ||
| 293 | offset += i; | ||
| 294 | if (end <= offset) { | ||
| 295 | pr_debug("overlap\n"); | ||
| 296 | goto err; | ||
| 297 | } | ||
| 298 | if (!pskb_pull(skb, i)) { | ||
| 299 | pr_debug("Can't pull\n"); | ||
| 300 | goto err; | ||
| 301 | } | ||
| 302 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
| 303 | skb->ip_summed = CHECKSUM_NONE; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /* Look for overlap with succeeding segments. | ||
| 308 | * If we can merge fragments, do it. | ||
| 309 | */ | 283 | */ |
| 310 | while (next && NFCT_FRAG6_CB(next)->offset < end) { | ||
| 311 | /* overlap is 'i' bytes */ | ||
| 312 | int i = end - NFCT_FRAG6_CB(next)->offset; | ||
| 313 | |||
| 314 | if (i < next->len) { | ||
| 315 | /* Eat head of the next overlapped fragment | ||
| 316 | * and leave the loop. The next ones cannot overlap. | ||
| 317 | */ | ||
| 318 | pr_debug("Eat head of the overlapped parts.: %d", i); | ||
| 319 | if (!pskb_pull(next, i)) | ||
| 320 | goto err; | ||
| 321 | 284 | ||
| 322 | /* next fragment */ | 285 | /* Check for overlap with preceding fragment. */ |
| 323 | NFCT_FRAG6_CB(next)->offset += i; | 286 | if (prev && |
| 324 | fq->q.meat -= i; | 287 | (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset > 0) |
| 325 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | 288 | goto discard_fq; |
| 326 | next->ip_summed = CHECKSUM_NONE; | ||
| 327 | break; | ||
| 328 | } else { | ||
| 329 | struct sk_buff *free_it = next; | ||
| 330 | |||
| 331 | /* Old fragmnet is completely overridden with | ||
| 332 | * new one drop it. | ||
| 333 | */ | ||
| 334 | next = next->next; | ||
| 335 | 289 | ||
| 336 | if (prev) | 290 | /* Look for overlap with succeeding segment. */ |
| 337 | prev->next = next; | 291 | if (next && NFCT_FRAG6_CB(next)->offset < end) |
| 338 | else | 292 | goto discard_fq; |
| 339 | fq->q.fragments = next; | ||
| 340 | |||
| 341 | fq->q.meat -= free_it->len; | ||
| 342 | frag_kfree_skb(free_it); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | 293 | ||
| 346 | NFCT_FRAG6_CB(skb)->offset = offset; | 294 | NFCT_FRAG6_CB(skb)->offset = offset; |
| 347 | 295 | ||
| @@ -371,6 +319,8 @@ found: | |||
| 371 | write_unlock(&nf_frags.lock); | 319 | write_unlock(&nf_frags.lock); |
| 372 | return 0; | 320 | return 0; |
| 373 | 321 | ||
| 322 | discard_fq: | ||
| 323 | fq_kill(fq); | ||
| 374 | err: | 324 | err: |
| 375 | return -1; | 325 | return -1; |
| 376 | } | 326 | } |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 545c4141b755..64cfef1b0a4c 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -149,13 +149,6 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a) | |||
| 149 | } | 149 | } |
| 150 | EXPORT_SYMBOL(ip6_frag_match); | 150 | EXPORT_SYMBOL(ip6_frag_match); |
| 151 | 151 | ||
| 152 | /* Memory Tracking Functions. */ | ||
| 153 | static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb) | ||
| 154 | { | ||
| 155 | atomic_sub(skb->truesize, &nf->mem); | ||
| 156 | kfree_skb(skb); | ||
| 157 | } | ||
| 158 | |||
| 159 | void ip6_frag_init(struct inet_frag_queue *q, void *a) | 152 | void ip6_frag_init(struct inet_frag_queue *q, void *a) |
| 160 | { | 153 | { |
| 161 | struct frag_queue *fq = container_of(q, struct frag_queue, q); | 154 | struct frag_queue *fq = container_of(q, struct frag_queue, q); |
| @@ -346,58 +339,22 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 346 | } | 339 | } |
| 347 | 340 | ||
| 348 | found: | 341 | found: |
| 349 | /* We found where to put this one. Check for overlap with | 342 | /* RFC5722, Section 4: |
| 350 | * preceding fragment, and, if needed, align things so that | 343 | * When reassembling an IPv6 datagram, if |
| 351 | * any overlaps are eliminated. | 344 | * one or more its constituent fragments is determined to be an |
| 345 | * overlapping fragment, the entire datagram (and any constituent | ||
| 346 | * fragments, including those not yet received) MUST be silently | ||
| 347 | * discarded. | ||
| 352 | */ | 348 | */ |
| 353 | if (prev) { | ||
| 354 | int i = (FRAG6_CB(prev)->offset + prev->len) - offset; | ||
| 355 | 349 | ||
| 356 | if (i > 0) { | 350 | /* Check for overlap with preceding fragment. */ |
| 357 | offset += i; | 351 | if (prev && |
| 358 | if (end <= offset) | 352 | (FRAG6_CB(prev)->offset + prev->len) - offset > 0) |
| 359 | goto err; | 353 | goto discard_fq; |
| 360 | if (!pskb_pull(skb, i)) | ||
| 361 | goto err; | ||
| 362 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
| 363 | skb->ip_summed = CHECKSUM_NONE; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | 354 | ||
| 367 | /* Look for overlap with succeeding segments. | 355 | /* Look for overlap with succeeding segment. */ |
| 368 | * If we can merge fragments, do it. | 356 | if (next && FRAG6_CB(next)->offset < end) |
| 369 | */ | 357 | goto discard_fq; |
| 370 | while (next && FRAG6_CB(next)->offset < end) { | ||
| 371 | int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */ | ||
| 372 | |||
| 373 | if (i < next->len) { | ||
| 374 | /* Eat head of the next overlapped fragment | ||
| 375 | * and leave the loop. The next ones cannot overlap. | ||
| 376 | */ | ||
| 377 | if (!pskb_pull(next, i)) | ||
| 378 | goto err; | ||
| 379 | FRAG6_CB(next)->offset += i; /* next fragment */ | ||
| 380 | fq->q.meat -= i; | ||
| 381 | if (next->ip_summed != CHECKSUM_UNNECESSARY) | ||
| 382 | next->ip_summed = CHECKSUM_NONE; | ||
| 383 | break; | ||
| 384 | } else { | ||
| 385 | struct sk_buff *free_it = next; | ||
| 386 | |||
| 387 | /* Old fragment is completely overridden with | ||
| 388 | * new one drop it. | ||
| 389 | */ | ||
| 390 | next = next->next; | ||
| 391 | |||
| 392 | if (prev) | ||
| 393 | prev->next = next; | ||
| 394 | else | ||
| 395 | fq->q.fragments = next; | ||
| 396 | |||
| 397 | fq->q.meat -= free_it->len; | ||
| 398 | frag_kfree_skb(fq->q.net, free_it); | ||
| 399 | } | ||
| 400 | } | ||
| 401 | 358 | ||
| 402 | FRAG6_CB(skb)->offset = offset; | 359 | FRAG6_CB(skb)->offset = offset; |
| 403 | 360 | ||
| @@ -436,6 +393,8 @@ found: | |||
| 436 | write_unlock(&ip6_frags.lock); | 393 | write_unlock(&ip6_frags.lock); |
| 437 | return -1; | 394 | return -1; |
| 438 | 395 | ||
| 396 | discard_fq: | ||
| 397 | fq_kill(fq); | ||
| 439 | err: | 398 | err: |
| 440 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 399 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
| 441 | IPSTATS_MIB_REASMFAILS); | 400 | IPSTATS_MIB_REASMFAILS); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1dd1affdead2..5acb3560ff15 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -111,6 +111,15 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
| 111 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); | 111 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static void udp_v6_rehash(struct sock *sk) | ||
| 115 | { | ||
| 116 | u16 new_hash = udp6_portaddr_hash(sock_net(sk), | ||
| 117 | &inet6_sk(sk)->rcv_saddr, | ||
| 118 | inet_sk(sk)->inet_num); | ||
| 119 | |||
| 120 | udp_lib_rehash(sk, new_hash); | ||
| 121 | } | ||
| 122 | |||
| 114 | static inline int compute_score(struct sock *sk, struct net *net, | 123 | static inline int compute_score(struct sock *sk, struct net *net, |
| 115 | unsigned short hnum, | 124 | unsigned short hnum, |
| 116 | struct in6_addr *saddr, __be16 sport, | 125 | struct in6_addr *saddr, __be16 sport, |
| @@ -1447,6 +1456,7 @@ struct proto udpv6_prot = { | |||
| 1447 | .backlog_rcv = udpv6_queue_rcv_skb, | 1456 | .backlog_rcv = udpv6_queue_rcv_skb, |
| 1448 | .hash = udp_lib_hash, | 1457 | .hash = udp_lib_hash, |
| 1449 | .unhash = udp_lib_unhash, | 1458 | .unhash = udp_lib_unhash, |
| 1459 | .rehash = udp_v6_rehash, | ||
| 1450 | .get_port = udp_v6_get_port, | 1460 | .get_port = udp_v6_get_port, |
| 1451 | .memory_allocated = &udp_memory_allocated, | 1461 | .memory_allocated = &udp_memory_allocated, |
| 1452 | .sysctl_mem = sysctl_udp_mem, | 1462 | .sysctl_mem = sysctl_udp_mem, |
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index a788f9e9427d..6130f9d9dbe1 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c | |||
| @@ -1102,7 +1102,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) | |||
| 1102 | memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */ | 1102 | memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */ |
| 1103 | le16_to_cpus(&val_len); n+=2; | 1103 | le16_to_cpus(&val_len); n+=2; |
| 1104 | 1104 | ||
| 1105 | if (val_len > 1016) { | 1105 | if (val_len >= 1016) { |
| 1106 | IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ ); | 1106 | IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ ); |
| 1107 | return -RSP_INVALID_COMMAND_FORMAT; | 1107 | return -RSP_INVALID_COMMAND_FORMAT; |
| 1108 | } | 1108 | } |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 4f8ddba48011..4c2f89df5cce 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -924,6 +924,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
| 924 | 924 | ||
| 925 | ip_vs_out_stats(cp, skb); | 925 | ip_vs_out_stats(cp, skb); |
| 926 | ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp); | 926 | ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp); |
| 927 | ip_vs_update_conntrack(skb, cp, 0); | ||
| 927 | ip_vs_conn_put(cp); | 928 | ip_vs_conn_put(cp); |
| 928 | 929 | ||
| 929 | skb->ipvs_property = 1; | 930 | skb->ipvs_property = 1; |
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index 33b329bfc2d2..7e9af5b76d9e 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c | |||
| @@ -410,7 +410,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 410 | union nf_inet_addr to; | 410 | union nf_inet_addr to; |
| 411 | __be16 port; | 411 | __be16 port; |
| 412 | struct ip_vs_conn *n_cp; | 412 | struct ip_vs_conn *n_cp; |
| 413 | struct nf_conn *ct; | ||
| 414 | 413 | ||
| 415 | #ifdef CONFIG_IP_VS_IPV6 | 414 | #ifdef CONFIG_IP_VS_IPV6 |
| 416 | /* This application helper doesn't work with IPv6 yet, | 415 | /* This application helper doesn't work with IPv6 yet, |
| @@ -497,11 +496,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
| 497 | ip_vs_control_add(n_cp, cp); | 496 | ip_vs_control_add(n_cp, cp); |
| 498 | } | 497 | } |
| 499 | 498 | ||
| 500 | ct = (struct nf_conn *)skb->nfct; | ||
| 501 | if (ct && ct != &nf_conntrack_untracked) | ||
| 502 | ip_vs_expect_related(skb, ct, n_cp, | ||
| 503 | IPPROTO_TCP, &n_cp->dport, 1); | ||
| 504 | |||
| 505 | /* | 499 | /* |
| 506 | * Move tunnel to listen state | 500 | * Move tunnel to listen state |
| 507 | */ | 501 | */ |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 21e1a5e9b9d3..49df6bea6a2d 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
| @@ -349,8 +349,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 349 | } | 349 | } |
| 350 | #endif | 350 | #endif |
| 351 | 351 | ||
| 352 | static void | 352 | void |
| 353 | ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp) | 353 | ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin) |
| 354 | { | 354 | { |
| 355 | struct nf_conn *ct = (struct nf_conn *)skb->nfct; | 355 | struct nf_conn *ct = (struct nf_conn *)skb->nfct; |
| 356 | struct nf_conntrack_tuple new_tuple; | 356 | struct nf_conntrack_tuple new_tuple; |
| @@ -365,11 +365,17 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp) | |||
| 365 | * real-server we will see RIP->DIP. | 365 | * real-server we will see RIP->DIP. |
| 366 | */ | 366 | */ |
| 367 | new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; | 367 | new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; |
| 368 | new_tuple.src.u3 = cp->daddr; | 368 | if (outin) |
| 369 | new_tuple.src.u3 = cp->daddr; | ||
| 370 | else | ||
| 371 | new_tuple.dst.u3 = cp->vaddr; | ||
| 369 | /* | 372 | /* |
| 370 | * This will also take care of UDP and other protocols. | 373 | * This will also take care of UDP and other protocols. |
| 371 | */ | 374 | */ |
| 372 | new_tuple.src.u.tcp.port = cp->dport; | 375 | if (outin) |
| 376 | new_tuple.src.u.tcp.port = cp->dport; | ||
| 377 | else | ||
| 378 | new_tuple.dst.u.tcp.port = cp->vport; | ||
| 373 | nf_conntrack_alter_reply(ct, &new_tuple); | 379 | nf_conntrack_alter_reply(ct, &new_tuple); |
| 374 | } | 380 | } |
| 375 | 381 | ||
| @@ -428,7 +434,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 428 | 434 | ||
| 429 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); | 435 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); |
| 430 | 436 | ||
| 431 | ip_vs_update_conntrack(skb, cp); | 437 | ip_vs_update_conntrack(skb, cp, 1); |
| 432 | 438 | ||
| 433 | /* FIXME: when application helper enlarges the packet and the length | 439 | /* FIXME: when application helper enlarges the packet and the length |
| 434 | is larger than the MTU of outgoing device, there will be still | 440 | is larger than the MTU of outgoing device, there will be still |
| @@ -506,7 +512,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 506 | 512 | ||
| 507 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); | 513 | IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); |
| 508 | 514 | ||
| 509 | ip_vs_update_conntrack(skb, cp); | 515 | ip_vs_update_conntrack(skb, cp, 1); |
| 510 | 516 | ||
| 511 | /* FIXME: when application helper enlarges the packet and the length | 517 | /* FIXME: when application helper enlarges the packet and the length |
| 512 | is larger than the MTU of outgoing device, there will be still | 518 | is larger than the MTU of outgoing device, there will be still |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 24b2cd555637..d344dc481ccc 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -1232,6 +1232,18 @@ out: | |||
| 1232 | return 0; | 1232 | return 0; |
| 1233 | } | 1233 | } |
| 1234 | 1234 | ||
| 1235 | static bool list_has_sctp_addr(const struct list_head *list, | ||
| 1236 | union sctp_addr *ipaddr) | ||
| 1237 | { | ||
| 1238 | struct sctp_transport *addr; | ||
| 1239 | |||
| 1240 | list_for_each_entry(addr, list, transports) { | ||
| 1241 | if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr)) | ||
| 1242 | return true; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | return false; | ||
| 1246 | } | ||
| 1235 | /* A restart is occurring, check to make sure no new addresses | 1247 | /* A restart is occurring, check to make sure no new addresses |
| 1236 | * are being added as we may be under a takeover attack. | 1248 | * are being added as we may be under a takeover attack. |
| 1237 | */ | 1249 | */ |
| @@ -1240,10 +1252,10 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
| 1240 | struct sctp_chunk *init, | 1252 | struct sctp_chunk *init, |
| 1241 | sctp_cmd_seq_t *commands) | 1253 | sctp_cmd_seq_t *commands) |
| 1242 | { | 1254 | { |
| 1243 | struct sctp_transport *new_addr, *addr; | 1255 | struct sctp_transport *new_addr; |
| 1244 | int found; | 1256 | int ret = 1; |
| 1245 | 1257 | ||
| 1246 | /* Implementor's Guide - Sectin 5.2.2 | 1258 | /* Implementor's Guide - Section 5.2.2 |
| 1247 | * ... | 1259 | * ... |
| 1248 | * Before responding the endpoint MUST check to see if the | 1260 | * Before responding the endpoint MUST check to see if the |
| 1249 | * unexpected INIT adds new addresses to the association. If new | 1261 | * unexpected INIT adds new addresses to the association. If new |
| @@ -1254,31 +1266,19 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
| 1254 | /* Search through all current addresses and make sure | 1266 | /* Search through all current addresses and make sure |
| 1255 | * we aren't adding any new ones. | 1267 | * we aren't adding any new ones. |
| 1256 | */ | 1268 | */ |
| 1257 | new_addr = NULL; | ||
| 1258 | found = 0; | ||
| 1259 | |||
| 1260 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, | 1269 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, |
| 1261 | transports) { | 1270 | transports) { |
| 1262 | found = 0; | 1271 | if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, |
| 1263 | list_for_each_entry(addr, &asoc->peer.transport_addr_list, | 1272 | &new_addr->ipaddr)) { |
| 1264 | transports) { | 1273 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, |
| 1265 | if (sctp_cmp_addr_exact(&new_addr->ipaddr, | 1274 | commands); |
| 1266 | &addr->ipaddr)) { | 1275 | ret = 0; |
| 1267 | found = 1; | ||
| 1268 | break; | ||
| 1269 | } | ||
| 1270 | } | ||
| 1271 | if (!found) | ||
| 1272 | break; | 1276 | break; |
| 1273 | } | 1277 | } |
| 1274 | |||
| 1275 | /* If a new address was added, ABORT the sender. */ | ||
| 1276 | if (!found && new_addr) { | ||
| 1277 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands); | ||
| 1278 | } | 1278 | } |
| 1279 | 1279 | ||
| 1280 | /* Return success if all addresses were found. */ | 1280 | /* Return success if all addresses were found. */ |
| 1281 | return found; | 1281 | return ret; |
| 1282 | } | 1282 | } |
| 1283 | 1283 | ||
| 1284 | /* Populate the verification/tie tags based on overlapping INIT | 1284 | /* Populate the verification/tie tags based on overlapping INIT |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 36cb66022a27..e9eaaf7d43c1 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
| @@ -38,7 +38,7 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
| 38 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
| 39 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
| 40 | 40 | ||
| 41 | #define MAX_HASHTABLE_BITS (10) | 41 | #define MAX_HASHTABLE_BITS (14) |
| 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
| 43 | { | 43 | { |
| 44 | unsigned long num; | 44 | unsigned long num; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index dcfc66bab2bb..12c485982814 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
| @@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode) | |||
| 745 | struct rpc_inode *rpci = RPC_I(inode); | 745 | struct rpc_inode *rpci = RPC_I(inode); |
| 746 | struct gss_upcall_msg *gss_msg; | 746 | struct gss_upcall_msg *gss_msg; |
| 747 | 747 | ||
| 748 | restart: | ||
| 748 | spin_lock(&inode->i_lock); | 749 | spin_lock(&inode->i_lock); |
| 749 | while (!list_empty(&rpci->in_downcall)) { | 750 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { |
| 750 | 751 | ||
| 751 | gss_msg = list_entry(rpci->in_downcall.next, | 752 | if (!list_empty(&gss_msg->msg.list)) |
| 752 | struct gss_upcall_msg, list); | 753 | continue; |
| 753 | gss_msg->msg.errno = -EPIPE; | 754 | gss_msg->msg.errno = -EPIPE; |
| 754 | atomic_inc(&gss_msg->count); | 755 | atomic_inc(&gss_msg->count); |
| 755 | __gss_unhash_msg(gss_msg); | 756 | __gss_unhash_msg(gss_msg); |
| 756 | spin_unlock(&inode->i_lock); | 757 | spin_unlock(&inode->i_lock); |
| 757 | gss_release_msg(gss_msg); | 758 | gss_release_msg(gss_msg); |
| 758 | spin_lock(&inode->i_lock); | 759 | goto restart; |
| 759 | } | 760 | } |
| 760 | spin_unlock(&inode->i_lock); | 761 | spin_unlock(&inode->i_lock); |
| 761 | 762 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 032644610524..778e5dfc5144 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
| @@ -237,6 +237,7 @@ get_key(const void *p, const void *end, | |||
| 237 | if (!supported_gss_krb5_enctype(alg)) { | 237 | if (!supported_gss_krb5_enctype(alg)) { |
| 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " | 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " |
| 239 | "encryption key algorithm %d\n", alg); | 239 | "encryption key algorithm %d\n", alg); |
| 240 | p = ERR_PTR(-EINVAL); | ||
| 240 | goto out_err; | 241 | goto out_err; |
| 241 | } | 242 | } |
| 242 | p = simple_get_netobj(p, end, &key); | 243 | p = simple_get_netobj(p, end, &key); |
| @@ -282,15 +283,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
| 282 | ctx->enctype = ENCTYPE_DES_CBC_RAW; | 283 | ctx->enctype = ENCTYPE_DES_CBC_RAW; |
| 283 | 284 | ||
| 284 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); | 285 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); |
| 285 | if (ctx->gk5e == NULL) | 286 | if (ctx->gk5e == NULL) { |
| 287 | p = ERR_PTR(-EINVAL); | ||
| 286 | goto out_err; | 288 | goto out_err; |
| 289 | } | ||
| 287 | 290 | ||
| 288 | /* The downcall format was designed before we completely understood | 291 | /* The downcall format was designed before we completely understood |
| 289 | * the uses of the context fields; so it includes some stuff we | 292 | * the uses of the context fields; so it includes some stuff we |
| 290 | * just give some minimal sanity-checking, and some we ignore | 293 | * just give some minimal sanity-checking, and some we ignore |
| 291 | * completely (like the next twenty bytes): */ | 294 | * completely (like the next twenty bytes): */ |
| 292 | if (unlikely(p + 20 > end || p + 20 < p)) | 295 | if (unlikely(p + 20 > end || p + 20 < p)) { |
| 296 | p = ERR_PTR(-EFAULT); | ||
| 293 | goto out_err; | 297 | goto out_err; |
| 298 | } | ||
| 294 | p += 20; | 299 | p += 20; |
| 295 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); | 300 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); |
| 296 | if (IS_ERR(p)) | 301 | if (IS_ERR(p)) |
| @@ -619,6 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, | |||
| 619 | if (ctx->seq_send64 != ctx->seq_send) { | 624 | if (ctx->seq_send64 != ctx->seq_send) { |
| 620 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, | 625 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, |
| 621 | (long unsigned)ctx->seq_send64, ctx->seq_send); | 626 | (long unsigned)ctx->seq_send64, ctx->seq_send); |
| 627 | p = ERR_PTR(-EINVAL); | ||
| 622 | goto out_err; | 628 | goto out_err; |
| 623 | } | 629 | } |
| 624 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); | 630 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index dc3f1f5ed865..adade3d313f2 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
| @@ -100,6 +100,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 100 | if (version != 1) { | 100 | if (version != 1) { |
| 101 | dprintk("RPC: unknown spkm3 token format: " | 101 | dprintk("RPC: unknown spkm3 token format: " |
| 102 | "obsolete nfs-utils?\n"); | 102 | "obsolete nfs-utils?\n"); |
| 103 | p = ERR_PTR(-EINVAL); | ||
| 103 | goto out_err_free_ctx; | 104 | goto out_err_free_ctx; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| @@ -135,8 +136,10 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 135 | if (IS_ERR(p)) | 136 | if (IS_ERR(p)) |
| 136 | goto out_err_free_intg_alg; | 137 | goto out_err_free_intg_alg; |
| 137 | 138 | ||
| 138 | if (p != end) | 139 | if (p != end) { |
| 140 | p = ERR_PTR(-EFAULT); | ||
| 139 | goto out_err_free_intg_key; | 141 | goto out_err_free_intg_key; |
| 142 | } | ||
| 140 | 143 | ||
| 141 | ctx_id->internal_ctx_id = ctx; | 144 | ctx_id->internal_ctx_id = ctx; |
| 142 | 145 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2388d83b68ff..fa5549079d79 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
| 226 | goto out_no_principal; | 226 | goto out_no_principal; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | kref_init(&clnt->cl_kref); | 229 | atomic_set(&clnt->cl_count, 1); |
| 230 | 230 | ||
| 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
| 232 | if (err < 0) | 232 | if (err < 0) |
| @@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
| 390 | if (new->cl_principal == NULL) | 390 | if (new->cl_principal == NULL) |
| 391 | goto out_no_principal; | 391 | goto out_no_principal; |
| 392 | } | 392 | } |
| 393 | kref_init(&new->cl_kref); | 393 | atomic_set(&new->cl_count, 1); |
| 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
| 395 | if (err != 0) | 395 | if (err != 0) |
| 396 | goto out_no_path; | 396 | goto out_no_path; |
| 397 | if (new->cl_auth) | 397 | if (new->cl_auth) |
| 398 | atomic_inc(&new->cl_auth->au_count); | 398 | atomic_inc(&new->cl_auth->au_count); |
| 399 | xprt_get(clnt->cl_xprt); | 399 | xprt_get(clnt->cl_xprt); |
| 400 | kref_get(&clnt->cl_kref); | 400 | atomic_inc(&clnt->cl_count); |
| 401 | rpc_register_client(new); | 401 | rpc_register_client(new); |
| 402 | rpciod_up(); | 402 | rpciod_up(); |
| 403 | return new; | 403 | return new; |
| @@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
| 465 | * Free an RPC client | 465 | * Free an RPC client |
| 466 | */ | 466 | */ |
| 467 | static void | 467 | static void |
| 468 | rpc_free_client(struct kref *kref) | 468 | rpc_free_client(struct rpc_clnt *clnt) |
| 469 | { | 469 | { |
| 470 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 471 | |||
| 472 | dprintk("RPC: destroying %s client for %s\n", | 470 | dprintk("RPC: destroying %s client for %s\n", |
| 473 | clnt->cl_protname, clnt->cl_server); | 471 | clnt->cl_protname, clnt->cl_server); |
| 474 | if (!IS_ERR(clnt->cl_path.dentry)) { | 472 | if (!IS_ERR(clnt->cl_path.dentry)) { |
| @@ -495,12 +493,10 @@ out_free: | |||
| 495 | * Free an RPC client | 493 | * Free an RPC client |
| 496 | */ | 494 | */ |
| 497 | static void | 495 | static void |
| 498 | rpc_free_auth(struct kref *kref) | 496 | rpc_free_auth(struct rpc_clnt *clnt) |
| 499 | { | 497 | { |
| 500 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 501 | |||
| 502 | if (clnt->cl_auth == NULL) { | 498 | if (clnt->cl_auth == NULL) { |
| 503 | rpc_free_client(kref); | 499 | rpc_free_client(clnt); |
| 504 | return; | 500 | return; |
| 505 | } | 501 | } |
| 506 | 502 | ||
| @@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref) | |||
| 509 | * release remaining GSS contexts. This mechanism ensures | 505 | * release remaining GSS contexts. This mechanism ensures |
| 510 | * that it can do so safely. | 506 | * that it can do so safely. |
| 511 | */ | 507 | */ |
| 512 | kref_init(kref); | 508 | atomic_inc(&clnt->cl_count); |
| 513 | rpcauth_release(clnt->cl_auth); | 509 | rpcauth_release(clnt->cl_auth); |
| 514 | clnt->cl_auth = NULL; | 510 | clnt->cl_auth = NULL; |
| 515 | kref_put(kref, rpc_free_client); | 511 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 512 | rpc_free_client(clnt); | ||
| 516 | } | 513 | } |
| 517 | 514 | ||
| 518 | /* | 515 | /* |
| @@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
| 525 | 522 | ||
| 526 | if (list_empty(&clnt->cl_tasks)) | 523 | if (list_empty(&clnt->cl_tasks)) |
| 527 | wake_up(&destroy_wait); | 524 | wake_up(&destroy_wait); |
| 528 | kref_put(&clnt->cl_kref, rpc_free_auth); | 525 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 526 | rpc_free_auth(clnt); | ||
| 529 | } | 527 | } |
| 530 | 528 | ||
| 531 | /** | 529 | /** |
| @@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | |||
| 588 | if (clnt != NULL) { | 586 | if (clnt != NULL) { |
| 589 | rpc_task_release_client(task); | 587 | rpc_task_release_client(task); |
| 590 | task->tk_client = clnt; | 588 | task->tk_client = clnt; |
| 591 | kref_get(&clnt->cl_kref); | 589 | atomic_inc(&clnt->cl_count); |
| 592 | if (clnt->cl_softrtry) | 590 | if (clnt->cl_softrtry) |
| 593 | task->tk_flags |= RPC_TASK_SOFT; | 591 | task->tk_flags |= RPC_TASK_SOFT; |
| 594 | /* Add to the client's list of all tasks */ | 592 | /* Add to the client's list of all tasks */ |
| @@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task) | |||
| 931 | task->tk_status = 0; | 929 | task->tk_status = 0; |
| 932 | if (status >= 0) { | 930 | if (status >= 0) { |
| 933 | if (task->tk_rqstp) { | 931 | if (task->tk_rqstp) { |
| 934 | task->tk_action = call_allocate; | 932 | task->tk_action = call_refresh; |
| 935 | return; | 933 | return; |
| 936 | } | 934 | } |
| 937 | 935 | ||
| @@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task) | |||
| 966 | } | 964 | } |
| 967 | 965 | ||
| 968 | /* | 966 | /* |
| 969 | * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. | 967 | * 2. Bind and/or refresh the credentials |
| 968 | */ | ||
| 969 | static void | ||
| 970 | call_refresh(struct rpc_task *task) | ||
| 971 | { | ||
| 972 | dprint_status(task); | ||
| 973 | |||
| 974 | task->tk_action = call_refreshresult; | ||
| 975 | task->tk_status = 0; | ||
| 976 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
| 977 | rpcauth_refreshcred(task); | ||
| 978 | } | ||
| 979 | |||
| 980 | /* | ||
| 981 | * 2a. Process the results of a credential refresh | ||
| 982 | */ | ||
| 983 | static void | ||
| 984 | call_refreshresult(struct rpc_task *task) | ||
| 985 | { | ||
| 986 | int status = task->tk_status; | ||
| 987 | |||
| 988 | dprint_status(task); | ||
| 989 | |||
| 990 | task->tk_status = 0; | ||
| 991 | task->tk_action = call_allocate; | ||
| 992 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
| 993 | return; | ||
| 994 | switch (status) { | ||
| 995 | case -EACCES: | ||
| 996 | rpc_exit(task, -EACCES); | ||
| 997 | return; | ||
| 998 | case -ENOMEM: | ||
| 999 | rpc_exit(task, -ENOMEM); | ||
| 1000 | return; | ||
| 1001 | case -ETIMEDOUT: | ||
| 1002 | rpc_delay(task, 3*HZ); | ||
| 1003 | } | ||
| 1004 | task->tk_action = call_refresh; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. | ||
| 970 | * (Note: buffer memory is freed in xprt_release). | 1009 | * (Note: buffer memory is freed in xprt_release). |
| 971 | */ | 1010 | */ |
| 972 | static void | 1011 | static void |
| 973 | call_allocate(struct rpc_task *task) | 1012 | call_allocate(struct rpc_task *task) |
| 974 | { | 1013 | { |
| 975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; | 1014 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; |
| 976 | struct rpc_rqst *req = task->tk_rqstp; | 1015 | struct rpc_rqst *req = task->tk_rqstp; |
| 977 | struct rpc_xprt *xprt = task->tk_xprt; | 1016 | struct rpc_xprt *xprt = task->tk_xprt; |
| 978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 1017 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
| @@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task) | |||
| 980 | dprint_status(task); | 1019 | dprint_status(task); |
| 981 | 1020 | ||
| 982 | task->tk_status = 0; | 1021 | task->tk_status = 0; |
| 983 | task->tk_action = call_refresh; | 1022 | task->tk_action = call_bind; |
| 984 | 1023 | ||
| 985 | if (req->rq_buffer) | 1024 | if (req->rq_buffer) |
| 986 | return; | 1025 | return; |
| @@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task) | |||
| 1017 | rpc_exit(task, -ERESTARTSYS); | 1056 | rpc_exit(task, -ERESTARTSYS); |
| 1018 | } | 1057 | } |
| 1019 | 1058 | ||
| 1020 | /* | ||
| 1021 | * 2a. Bind and/or refresh the credentials | ||
| 1022 | */ | ||
| 1023 | static void | ||
| 1024 | call_refresh(struct rpc_task *task) | ||
| 1025 | { | ||
| 1026 | dprint_status(task); | ||
| 1027 | |||
| 1028 | task->tk_action = call_refreshresult; | ||
| 1029 | task->tk_status = 0; | ||
| 1030 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
| 1031 | rpcauth_refreshcred(task); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | /* | ||
| 1035 | * 2b. Process the results of a credential refresh | ||
| 1036 | */ | ||
| 1037 | static void | ||
| 1038 | call_refreshresult(struct rpc_task *task) | ||
| 1039 | { | ||
| 1040 | int status = task->tk_status; | ||
| 1041 | |||
| 1042 | dprint_status(task); | ||
| 1043 | |||
| 1044 | task->tk_status = 0; | ||
| 1045 | task->tk_action = call_bind; | ||
| 1046 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
| 1047 | return; | ||
| 1048 | switch (status) { | ||
| 1049 | case -EACCES: | ||
| 1050 | rpc_exit(task, -EACCES); | ||
| 1051 | return; | ||
| 1052 | case -ENOMEM: | ||
| 1053 | rpc_exit(task, -ENOMEM); | ||
| 1054 | return; | ||
| 1055 | case -ETIMEDOUT: | ||
| 1056 | rpc_delay(task, 3*HZ); | ||
| 1057 | } | ||
| 1058 | task->tk_action = call_refresh; | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | static inline int | 1059 | static inline int |
| 1062 | rpc_task_need_encode(struct rpc_task *task) | 1060 | rpc_task_need_encode(struct rpc_task *task) |
| 1063 | { | 1061 | { |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 95ccbcf45d3e..8c8eef2b8f26 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -48,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
| 48 | return; | 48 | return; |
| 49 | do { | 49 | do { |
| 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); | 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); |
| 51 | list_del(&msg->list); | 51 | list_del_init(&msg->list); |
| 52 | msg->errno = err; | 52 | msg->errno = err; |
| 53 | destroy_msg(msg); | 53 | destroy_msg(msg); |
| 54 | } while (!list_empty(head)); | 54 | } while (!list_empty(head)); |
| @@ -208,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
| 208 | if (msg != NULL) { | 208 | if (msg != NULL) { |
| 209 | spin_lock(&inode->i_lock); | 209 | spin_lock(&inode->i_lock); |
| 210 | msg->errno = -EAGAIN; | 210 | msg->errno = -EAGAIN; |
| 211 | list_del(&msg->list); | 211 | list_del_init(&msg->list); |
| 212 | spin_unlock(&inode->i_lock); | 212 | spin_unlock(&inode->i_lock); |
| 213 | rpci->ops->destroy_msg(msg); | 213 | rpci->ops->destroy_msg(msg); |
| 214 | } | 214 | } |
| @@ -268,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
| 268 | if (res < 0 || msg->len == msg->copied) { | 268 | if (res < 0 || msg->len == msg->copied) { |
| 269 | filp->private_data = NULL; | 269 | filp->private_data = NULL; |
| 270 | spin_lock(&inode->i_lock); | 270 | spin_lock(&inode->i_lock); |
| 271 | list_del(&msg->list); | 271 | list_del_init(&msg->list); |
| 272 | spin_unlock(&inode->i_lock); | 272 | spin_unlock(&inode->i_lock); |
| 273 | rpci->ops->destroy_msg(msg); | 273 | rpci->ops->destroy_msg(msg); |
| 274 | } | 274 | } |
| @@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) | |||
| 371 | static int | 371 | static int |
| 372 | rpc_info_open(struct inode *inode, struct file *file) | 372 | rpc_info_open(struct inode *inode, struct file *file) |
| 373 | { | 373 | { |
| 374 | struct rpc_clnt *clnt; | 374 | struct rpc_clnt *clnt = NULL; |
| 375 | int ret = single_open(file, rpc_show_info, NULL); | 375 | int ret = single_open(file, rpc_show_info, NULL); |
| 376 | 376 | ||
| 377 | if (!ret) { | 377 | if (!ret) { |
| 378 | struct seq_file *m = file->private_data; | 378 | struct seq_file *m = file->private_data; |
| 379 | mutex_lock(&inode->i_mutex); | 379 | |
| 380 | clnt = RPC_I(inode)->private; | 380 | spin_lock(&file->f_path.dentry->d_lock); |
| 381 | if (clnt) { | 381 | if (!d_unhashed(file->f_path.dentry)) |
| 382 | kref_get(&clnt->cl_kref); | 382 | clnt = RPC_I(inode)->private; |
| 383 | if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { | ||
| 384 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 383 | m->private = clnt; | 385 | m->private = clnt; |
| 384 | } else { | 386 | } else { |
| 387 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 385 | single_release(inode, file); | 388 | single_release(inode, file); |
| 386 | ret = -EINVAL; | 389 | ret = -EINVAL; |
| 387 | } | 390 | } |
| 388 | mutex_unlock(&inode->i_mutex); | ||
| 389 | } | 391 | } |
| 390 | return ret; | 392 | return ret; |
| 391 | } | 393 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 4414a18c63b4..0b39b2451ea5 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -692,6 +692,7 @@ static int unix_autobind(struct socket *sock) | |||
| 692 | static u32 ordernum = 1; | 692 | static u32 ordernum = 1; |
| 693 | struct unix_address *addr; | 693 | struct unix_address *addr; |
| 694 | int err; | 694 | int err; |
| 695 | unsigned int retries = 0; | ||
| 695 | 696 | ||
| 696 | mutex_lock(&u->readlock); | 697 | mutex_lock(&u->readlock); |
| 697 | 698 | ||
| @@ -717,9 +718,17 @@ retry: | |||
| 717 | if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type, | 718 | if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type, |
| 718 | addr->hash)) { | 719 | addr->hash)) { |
| 719 | spin_unlock(&unix_table_lock); | 720 | spin_unlock(&unix_table_lock); |
| 720 | /* Sanity yield. It is unusual case, but yet... */ | 721 | /* |
| 721 | if (!(ordernum&0xFF)) | 722 | * __unix_find_socket_byname() may take long time if many names |
| 722 | yield(); | 723 | * are already in use. |
| 724 | */ | ||
| 725 | cond_resched(); | ||
| 726 | /* Give up if all names seems to be in use. */ | ||
| 727 | if (retries++ == 0xFFFFF) { | ||
| 728 | err = -ENOSPC; | ||
| 729 | kfree(addr); | ||
| 730 | goto out; | ||
| 731 | } | ||
| 723 | goto retry; | 732 | goto retry; |
| 724 | } | 733 | } |
| 725 | addr->hash ^= sk->sk_type; | 734 | addr->hash ^= sk->sk_type; |
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c index 79ab973fb43a..fc3b18d844af 100644 --- a/scripts/basic/docproc.c +++ b/scripts/basic/docproc.c | |||
| @@ -34,12 +34,14 @@ | |||
| 34 | * | 34 | * |
| 35 | */ | 35 | */ |
| 36 | 36 | ||
| 37 | #define _GNU_SOURCE | ||
| 37 | #include <stdio.h> | 38 | #include <stdio.h> |
| 38 | #include <stdlib.h> | 39 | #include <stdlib.h> |
| 39 | #include <string.h> | 40 | #include <string.h> |
| 40 | #include <ctype.h> | 41 | #include <ctype.h> |
| 41 | #include <unistd.h> | 42 | #include <unistd.h> |
| 42 | #include <limits.h> | 43 | #include <limits.h> |
| 44 | #include <errno.h> | ||
| 43 | #include <sys/types.h> | 45 | #include <sys/types.h> |
| 44 | #include <sys/wait.h> | 46 | #include <sys/wait.h> |
| 45 | 47 | ||
| @@ -54,6 +56,7 @@ typedef void FILEONLY(char * file); | |||
| 54 | FILEONLY *internalfunctions; | 56 | FILEONLY *internalfunctions; |
| 55 | FILEONLY *externalfunctions; | 57 | FILEONLY *externalfunctions; |
| 56 | FILEONLY *symbolsonly; | 58 | FILEONLY *symbolsonly; |
| 59 | FILEONLY *findall; | ||
| 57 | 60 | ||
| 58 | typedef void FILELINE(char * file, char * line); | 61 | typedef void FILELINE(char * file, char * line); |
| 59 | FILELINE * singlefunctions; | 62 | FILELINE * singlefunctions; |
| @@ -65,12 +68,30 @@ FILELINE * docsection; | |||
| 65 | #define KERNELDOCPATH "scripts/" | 68 | #define KERNELDOCPATH "scripts/" |
| 66 | #define KERNELDOC "kernel-doc" | 69 | #define KERNELDOC "kernel-doc" |
| 67 | #define DOCBOOK "-docbook" | 70 | #define DOCBOOK "-docbook" |
| 71 | #define LIST "-list" | ||
| 68 | #define FUNCTION "-function" | 72 | #define FUNCTION "-function" |
| 69 | #define NOFUNCTION "-nofunction" | 73 | #define NOFUNCTION "-nofunction" |
| 70 | #define NODOCSECTIONS "-no-doc-sections" | 74 | #define NODOCSECTIONS "-no-doc-sections" |
| 71 | 75 | ||
| 72 | static char *srctree, *kernsrctree; | 76 | static char *srctree, *kernsrctree; |
| 73 | 77 | ||
| 78 | static char **all_list = NULL; | ||
| 79 | static int all_list_len = 0; | ||
| 80 | |||
| 81 | static void consume_symbol(const char *sym) | ||
| 82 | { | ||
| 83 | int i; | ||
| 84 | |||
| 85 | for (i = 0; i < all_list_len; i++) { | ||
| 86 | if (!all_list[i]) | ||
| 87 | continue; | ||
| 88 | if (strcmp(sym, all_list[i])) | ||
| 89 | continue; | ||
| 90 | all_list[i] = NULL; | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 74 | static void usage (void) | 95 | static void usage (void) |
| 75 | { | 96 | { |
| 76 | fprintf(stderr, "Usage: docproc {doc|depend} file\n"); | 97 | fprintf(stderr, "Usage: docproc {doc|depend} file\n"); |
| @@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type) | |||
| 248 | struct symfile * sym = &symfilelist[i]; | 269 | struct symfile * sym = &symfilelist[i]; |
| 249 | for (j=0; j < sym->symbolcnt; j++) { | 270 | for (j=0; j < sym->symbolcnt; j++) { |
| 250 | vec[idx++] = type; | 271 | vec[idx++] = type; |
| 272 | consume_symbol(sym->symbollist[j].name); | ||
| 251 | vec[idx++] = sym->symbollist[j].name; | 273 | vec[idx++] = sym->symbollist[j].name; |
| 252 | } | 274 | } |
| 253 | } | 275 | } |
| @@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line) | |||
| 287 | vec[idx++] = &line[i]; | 309 | vec[idx++] = &line[i]; |
| 288 | } | 310 | } |
| 289 | } | 311 | } |
| 312 | for (i = 0; i < idx; i++) { | ||
| 313 | if (strcmp(vec[i], FUNCTION)) | ||
| 314 | continue; | ||
| 315 | consume_symbol(vec[i + 1]); | ||
| 316 | } | ||
| 290 | vec[idx++] = filename; | 317 | vec[idx++] = filename; |
| 291 | vec[idx] = NULL; | 318 | vec[idx] = NULL; |
| 292 | exec_kernel_doc(vec); | 319 | exec_kernel_doc(vec); |
| @@ -306,6 +333,10 @@ static void docsect(char *filename, char *line) | |||
| 306 | if (*s == '\n') | 333 | if (*s == '\n') |
| 307 | *s = '\0'; | 334 | *s = '\0'; |
| 308 | 335 | ||
| 336 | asprintf(&s, "DOC: %s", line); | ||
| 337 | consume_symbol(s); | ||
| 338 | free(s); | ||
| 339 | |||
| 309 | vec[0] = KERNELDOC; | 340 | vec[0] = KERNELDOC; |
| 310 | vec[1] = DOCBOOK; | 341 | vec[1] = DOCBOOK; |
| 311 | vec[2] = FUNCTION; | 342 | vec[2] = FUNCTION; |
| @@ -315,6 +346,84 @@ static void docsect(char *filename, char *line) | |||
| 315 | exec_kernel_doc(vec); | 346 | exec_kernel_doc(vec); |
| 316 | } | 347 | } |
| 317 | 348 | ||
| 349 | static void find_all_symbols(char *filename) | ||
| 350 | { | ||
| 351 | char *vec[4]; /* kerneldoc -list file NULL */ | ||
| 352 | pid_t pid; | ||
| 353 | int ret, i, count, start; | ||
| 354 | char real_filename[PATH_MAX + 1]; | ||
| 355 | int pipefd[2]; | ||
| 356 | char *data, *str; | ||
| 357 | size_t data_len = 0; | ||
| 358 | |||
| 359 | vec[0] = KERNELDOC; | ||
| 360 | vec[1] = LIST; | ||
| 361 | vec[2] = filename; | ||
| 362 | vec[3] = NULL; | ||
| 363 | |||
| 364 | if (pipe(pipefd)) { | ||
| 365 | perror("pipe"); | ||
| 366 | exit(1); | ||
| 367 | } | ||
| 368 | |||
| 369 | switch (pid=fork()) { | ||
| 370 | case -1: | ||
| 371 | perror("fork"); | ||
| 372 | exit(1); | ||
| 373 | case 0: | ||
| 374 | close(pipefd[0]); | ||
| 375 | dup2(pipefd[1], 1); | ||
| 376 | memset(real_filename, 0, sizeof(real_filename)); | ||
| 377 | strncat(real_filename, kernsrctree, PATH_MAX); | ||
| 378 | strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, | ||
| 379 | PATH_MAX - strlen(real_filename)); | ||
| 380 | execvp(real_filename, vec); | ||
| 381 | fprintf(stderr, "exec "); | ||
| 382 | perror(real_filename); | ||
| 383 | exit(1); | ||
| 384 | default: | ||
| 385 | close(pipefd[1]); | ||
| 386 | data = malloc(4096); | ||
| 387 | do { | ||
| 388 | while ((ret = read(pipefd[0], | ||
| 389 | data + data_len, | ||
| 390 | 4096)) > 0) { | ||
| 391 | data_len += ret; | ||
| 392 | data = realloc(data, data_len + 4096); | ||
| 393 | } | ||
| 394 | } while (ret == -EAGAIN); | ||
| 395 | if (ret != 0) { | ||
| 396 | perror("read"); | ||
| 397 | exit(1); | ||
| 398 | } | ||
| 399 | waitpid(pid, &ret ,0); | ||
| 400 | } | ||
| 401 | if (WIFEXITED(ret)) | ||
| 402 | exitstatus |= WEXITSTATUS(ret); | ||
| 403 | else | ||
| 404 | exitstatus = 0xff; | ||
| 405 | |||
| 406 | count = 0; | ||
| 407 | /* poor man's strtok, but with counting */ | ||
| 408 | for (i = 0; i < data_len; i++) { | ||
| 409 | if (data[i] == '\n') { | ||
| 410 | count++; | ||
| 411 | data[i] = '\0'; | ||
| 412 | } | ||
| 413 | } | ||
| 414 | start = all_list_len; | ||
| 415 | all_list_len += count; | ||
| 416 | all_list = realloc(all_list, sizeof(char *) * all_list_len); | ||
| 417 | str = data; | ||
| 418 | for (i = 0; i < data_len && start != all_list_len; i++) { | ||
| 419 | if (data[i] == '\0') { | ||
| 420 | all_list[start] = str; | ||
| 421 | str = data + i + 1; | ||
| 422 | start++; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 318 | /* | 427 | /* |
| 319 | * Parse file, calling action specific functions for: | 428 | * Parse file, calling action specific functions for: |
| 320 | * 1) Lines containing !E | 429 | * 1) Lines containing !E |
| @@ -322,7 +431,8 @@ static void docsect(char *filename, char *line) | |||
| 322 | * 3) Lines containing !D | 431 | * 3) Lines containing !D |
| 323 | * 4) Lines containing !F | 432 | * 4) Lines containing !F |
| 324 | * 5) Lines containing !P | 433 | * 5) Lines containing !P |
| 325 | * 6) Default lines - lines not matching the above | 434 | * 6) Lines containing !C |
| 435 | * 7) Default lines - lines not matching the above | ||
| 326 | */ | 436 | */ |
| 327 | static void parse_file(FILE *infile) | 437 | static void parse_file(FILE *infile) |
| 328 | { | 438 | { |
| @@ -365,6 +475,12 @@ static void parse_file(FILE *infile) | |||
| 365 | s++; | 475 | s++; |
| 366 | docsection(line + 2, s); | 476 | docsection(line + 2, s); |
| 367 | break; | 477 | break; |
| 478 | case 'C': | ||
| 479 | while (*s && !isspace(*s)) s++; | ||
| 480 | *s = '\0'; | ||
| 481 | if (findall) | ||
| 482 | findall(line+2); | ||
| 483 | break; | ||
| 368 | default: | 484 | default: |
| 369 | defaultline(line); | 485 | defaultline(line); |
| 370 | } | 486 | } |
| @@ -380,6 +496,7 @@ static void parse_file(FILE *infile) | |||
| 380 | int main(int argc, char *argv[]) | 496 | int main(int argc, char *argv[]) |
| 381 | { | 497 | { |
| 382 | FILE * infile; | 498 | FILE * infile; |
| 499 | int i; | ||
| 383 | 500 | ||
| 384 | srctree = getenv("SRCTREE"); | 501 | srctree = getenv("SRCTREE"); |
| 385 | if (!srctree) | 502 | if (!srctree) |
| @@ -415,6 +532,7 @@ int main(int argc, char *argv[]) | |||
| 415 | symbolsonly = find_export_symbols; | 532 | symbolsonly = find_export_symbols; |
| 416 | singlefunctions = noaction2; | 533 | singlefunctions = noaction2; |
| 417 | docsection = noaction2; | 534 | docsection = noaction2; |
| 535 | findall = find_all_symbols; | ||
| 418 | parse_file(infile); | 536 | parse_file(infile); |
| 419 | 537 | ||
| 420 | /* Rewind to start from beginning of file again */ | 538 | /* Rewind to start from beginning of file again */ |
| @@ -425,8 +543,16 @@ int main(int argc, char *argv[]) | |||
| 425 | symbolsonly = printline; | 543 | symbolsonly = printline; |
| 426 | singlefunctions = singfunc; | 544 | singlefunctions = singfunc; |
| 427 | docsection = docsect; | 545 | docsection = docsect; |
| 546 | findall = NULL; | ||
| 428 | 547 | ||
| 429 | parse_file(infile); | 548 | parse_file(infile); |
| 549 | |||
| 550 | for (i = 0; i < all_list_len; i++) { | ||
| 551 | if (!all_list[i]) | ||
| 552 | continue; | ||
| 553 | fprintf(stderr, "Warning: didn't use docs for %s\n", | ||
| 554 | all_list[i]); | ||
| 555 | } | ||
| 430 | } | 556 | } |
| 431 | else if (strcmp("depend", argv[1]) == 0) | 557 | else if (strcmp("depend", argv[1]) == 0) |
| 432 | { | 558 | { |
| @@ -439,6 +565,7 @@ int main(int argc, char *argv[]) | |||
| 439 | symbolsonly = adddep; | 565 | symbolsonly = adddep; |
| 440 | singlefunctions = adddep2; | 566 | singlefunctions = adddep2; |
| 441 | docsection = adddep2; | 567 | docsection = adddep2; |
| 568 | findall = adddep; | ||
| 442 | parse_file(infile); | 569 | parse_file(infile); |
| 443 | printf("\n"); | 570 | printf("\n"); |
| 444 | } | 571 | } |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 102e1235fd5c..cdb6dc1f6458 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
| @@ -44,12 +44,13 @@ use strict; | |||
| 44 | # Note: This only supports 'c'. | 44 | # Note: This only supports 'c'. |
| 45 | 45 | ||
| 46 | # usage: | 46 | # usage: |
| 47 | # kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ] | 47 | # kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ] |
| 48 | # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile | 48 | # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile |
| 49 | # or | 49 | # or |
| 50 | # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile | 50 | # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile |
| 51 | # | 51 | # |
| 52 | # Set output format using one of -docbook -html -text or -man. Default is man. | 52 | # Set output format using one of -docbook -html -text or -man. Default is man. |
| 53 | # The -list format is for internal use by docproc. | ||
| 53 | # | 54 | # |
| 54 | # -no-doc-sections | 55 | # -no-doc-sections |
| 55 | # Do not output DOC: sections | 56 | # Do not output DOC: sections |
| @@ -210,9 +211,16 @@ my %highlights_text = ( $type_constant, "\$1", | |||
| 210 | $type_param, "\$1" ); | 211 | $type_param, "\$1" ); |
| 211 | my $blankline_text = ""; | 212 | my $blankline_text = ""; |
| 212 | 213 | ||
| 214 | # list mode | ||
| 215 | my %highlights_list = ( $type_constant, "\$1", | ||
| 216 | $type_func, "\$1", | ||
| 217 | $type_struct, "\$1", | ||
| 218 | $type_param, "\$1" ); | ||
| 219 | my $blankline_list = ""; | ||
| 213 | 220 | ||
| 214 | sub usage { | 221 | sub usage { |
| 215 | print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n"; | 222 | print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n"; |
| 223 | print " [ -no-doc-sections ]\n"; | ||
| 216 | print " [ -function funcname [ -function funcname ...] ]\n"; | 224 | print " [ -function funcname [ -function funcname ...] ]\n"; |
| 217 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; | 225 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; |
| 218 | print " c source file(s) > outputfile\n"; | 226 | print " c source file(s) > outputfile\n"; |
| @@ -318,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) { | |||
| 318 | $output_mode = "xml"; | 326 | $output_mode = "xml"; |
| 319 | %highlights = %highlights_xml; | 327 | %highlights = %highlights_xml; |
| 320 | $blankline = $blankline_xml; | 328 | $blankline = $blankline_xml; |
| 329 | } elsif ($cmd eq "-list") { | ||
| 330 | $output_mode = "list"; | ||
| 331 | %highlights = %highlights_list; | ||
| 332 | $blankline = $blankline_list; | ||
| 321 | } elsif ($cmd eq "-gnome") { | 333 | } elsif ($cmd eq "-gnome") { |
| 322 | $output_mode = "gnome"; | 334 | $output_mode = "gnome"; |
| 323 | %highlights = %highlights_gnome; | 335 | %highlights = %highlights_gnome; |
| @@ -1361,6 +1373,42 @@ sub output_blockhead_text(%) { | |||
| 1361 | } | 1373 | } |
| 1362 | } | 1374 | } |
| 1363 | 1375 | ||
| 1376 | ## list mode output functions | ||
| 1377 | |||
| 1378 | sub output_function_list(%) { | ||
| 1379 | my %args = %{$_[0]}; | ||
| 1380 | |||
| 1381 | print $args{'function'} . "\n"; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | # output enum in list | ||
| 1385 | sub output_enum_list(%) { | ||
| 1386 | my %args = %{$_[0]}; | ||
| 1387 | print $args{'enum'} . "\n"; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | # output typedef in list | ||
| 1391 | sub output_typedef_list(%) { | ||
| 1392 | my %args = %{$_[0]}; | ||
| 1393 | print $args{'typedef'} . "\n"; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | # output struct as list | ||
| 1397 | sub output_struct_list(%) { | ||
| 1398 | my %args = %{$_[0]}; | ||
| 1399 | |||
| 1400 | print $args{'struct'} . "\n"; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | sub output_blockhead_list(%) { | ||
| 1404 | my %args = %{$_[0]}; | ||
| 1405 | my ($parameter, $section); | ||
| 1406 | |||
| 1407 | foreach $section (@{$args{'sectionlist'}}) { | ||
| 1408 | print "DOC: $section\n"; | ||
| 1409 | } | ||
| 1410 | } | ||
| 1411 | |||
| 1364 | ## | 1412 | ## |
| 1365 | # generic output function for all types (function, struct/union, typedef, enum); | 1413 | # generic output function for all types (function, struct/union, typedef, enum); |
| 1366 | # calls the generated, variable output_ function name based on | 1414 | # calls the generated, variable output_ function name based on |
| @@ -1679,7 +1727,7 @@ sub check_sections($$$$$$) { | |||
| 1679 | foreach $px (0 .. $#prms) { | 1727 | foreach $px (0 .. $#prms) { |
| 1680 | $prm_clean = $prms[$px]; | 1728 | $prm_clean = $prms[$px]; |
| 1681 | $prm_clean =~ s/\[.*\]//; | 1729 | $prm_clean =~ s/\[.*\]//; |
| 1682 | $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//; | 1730 | $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; |
| 1683 | # ignore array size in a parameter string; | 1731 | # ignore array size in a parameter string; |
| 1684 | # however, the original param string may contain | 1732 | # however, the original param string may contain |
| 1685 | # spaces, e.g.: addr[6 + 2] | 1733 | # spaces, e.g.: addr[6 + 2] |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index b2b0998d6abd..60924f6a52db 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
| @@ -1272,6 +1272,7 @@ long keyctl_session_to_parent(void) | |||
| 1272 | keyring_r = NULL; | 1272 | keyring_r = NULL; |
| 1273 | 1273 | ||
| 1274 | me = current; | 1274 | me = current; |
| 1275 | rcu_read_lock(); | ||
| 1275 | write_lock_irq(&tasklist_lock); | 1276 | write_lock_irq(&tasklist_lock); |
| 1276 | 1277 | ||
| 1277 | parent = me->real_parent; | 1278 | parent = me->real_parent; |
| @@ -1304,7 +1305,8 @@ long keyctl_session_to_parent(void) | |||
| 1304 | goto not_permitted; | 1305 | goto not_permitted; |
| 1305 | 1306 | ||
| 1306 | /* the keyrings must have the same UID */ | 1307 | /* the keyrings must have the same UID */ |
| 1307 | if (pcred->tgcred->session_keyring->uid != mycred->euid || | 1308 | if ((pcred->tgcred->session_keyring && |
| 1309 | pcred->tgcred->session_keyring->uid != mycred->euid) || | ||
| 1308 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1310 | mycred->tgcred->session_keyring->uid != mycred->euid) |
| 1309 | goto not_permitted; | 1311 | goto not_permitted; |
| 1310 | 1312 | ||
| @@ -1319,6 +1321,7 @@ long keyctl_session_to_parent(void) | |||
| 1319 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); | 1321 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); |
| 1320 | 1322 | ||
| 1321 | write_unlock_irq(&tasklist_lock); | 1323 | write_unlock_irq(&tasklist_lock); |
| 1324 | rcu_read_unlock(); | ||
| 1322 | if (oldcred) | 1325 | if (oldcred) |
| 1323 | put_cred(oldcred); | 1326 | put_cred(oldcred); |
| 1324 | return 0; | 1327 | return 0; |
| @@ -1327,6 +1330,7 @@ already_same: | |||
| 1327 | ret = 0; | 1330 | ret = 0; |
| 1328 | not_permitted: | 1331 | not_permitted: |
| 1329 | write_unlock_irq(&tasklist_lock); | 1332 | write_unlock_irq(&tasklist_lock); |
| 1333 | rcu_read_unlock(); | ||
| 1330 | put_cred(cred); | 1334 | put_cred(cred); |
| 1331 | return ret; | 1335 | return ret; |
| 1332 | 1336 | ||
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index eb68326c37d4..a7868ad4d530 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
| @@ -829,6 +829,8 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, | |||
| 829 | 829 | ||
| 830 | if (get_user(device, (int __user *)argp)) | 830 | if (get_user(device, (int __user *)argp)) |
| 831 | return -EFAULT; | 831 | return -EFAULT; |
| 832 | if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */ | ||
| 833 | device = SNDRV_RAWMIDI_DEVICES - 1; | ||
| 832 | mutex_lock(®ister_mutex); | 834 | mutex_lock(®ister_mutex); |
| 833 | device = device < 0 ? 0 : device + 1; | 835 | device = device < 0 ? 0 : device + 1; |
| 834 | while (device < SNDRV_RAWMIDI_DEVICES) { | 836 | while (device < SNDRV_RAWMIDI_DEVICES) { |
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index 685712276ac9..69cd7b3c362d 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c | |||
| @@ -281,13 +281,10 @@ snd_seq_oss_open(struct file *file, int level) | |||
| 281 | return 0; | 281 | return 0; |
| 282 | 282 | ||
| 283 | _error: | 283 | _error: |
| 284 | snd_seq_oss_writeq_delete(dp->writeq); | ||
| 285 | snd_seq_oss_readq_delete(dp->readq); | ||
| 286 | snd_seq_oss_synth_cleanup(dp); | 284 | snd_seq_oss_synth_cleanup(dp); |
| 287 | snd_seq_oss_midi_cleanup(dp); | 285 | snd_seq_oss_midi_cleanup(dp); |
| 288 | delete_port(dp); | ||
| 289 | delete_seq_queue(dp->queue); | 286 | delete_seq_queue(dp->queue); |
| 290 | kfree(dp); | 287 | delete_port(dp); |
| 291 | 288 | ||
| 292 | return rc; | 289 | return rc; |
| 293 | } | 290 | } |
| @@ -350,8 +347,10 @@ create_port(struct seq_oss_devinfo *dp) | |||
| 350 | static int | 347 | static int |
| 351 | delete_port(struct seq_oss_devinfo *dp) | 348 | delete_port(struct seq_oss_devinfo *dp) |
| 352 | { | 349 | { |
| 353 | if (dp->port < 0) | 350 | if (dp->port < 0) { |
| 351 | kfree(dp); | ||
| 354 | return 0; | 352 | return 0; |
| 353 | } | ||
| 355 | 354 | ||
| 356 | debug_printk(("delete_port %i\n", dp->port)); | 355 | debug_printk(("delete_port %i\n", dp->port)); |
| 357 | return snd_seq_event_port_detach(dp->cseq, dp->port); | 356 | return snd_seq_event_port_detach(dp->cseq, dp->port); |
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 5f3e68401f90..91d6023a63e5 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c | |||
| @@ -764,9 +764,9 @@ static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | |||
| 764 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; | 764 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; |
| 765 | static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | 765 | static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; |
| 766 | 766 | ||
| 767 | #ifndef MSND_CLASSIC | ||
| 767 | static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | 768 | static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; |
| 768 | 769 | ||
| 769 | #ifndef MSND_CLASSIC | ||
| 770 | /* Extra Peripheral Configuration (Default: Disable) */ | 770 | /* Extra Peripheral Configuration (Default: Disable) */ |
| 771 | static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | 771 | static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; |
| 772 | static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | 772 | static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; |
| @@ -894,7 +894,11 @@ static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx) | |||
| 894 | struct snd_card *card; | 894 | struct snd_card *card; |
| 895 | struct snd_msnd *chip; | 895 | struct snd_msnd *chip; |
| 896 | 896 | ||
| 897 | if (has_isapnp(idx) || cfg[idx] == SNDRV_AUTO_PORT) { | 897 | if (has_isapnp(idx) |
| 898 | #ifndef MSND_CLASSIC | ||
| 899 | || cfg[idx] == SNDRV_AUTO_PORT | ||
| 900 | #endif | ||
| 901 | ) { | ||
| 898 | printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); | 902 | printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); |
| 899 | return -ENODEV; | 903 | return -ENODEV; |
| 900 | } | 904 | } |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 3827092cc1d2..14829210ef0b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
| @@ -4536,7 +4536,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4536 | cfg->hp_outs--; | 4536 | cfg->hp_outs--; |
| 4537 | memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1, | 4537 | memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1, |
| 4538 | sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i)); | 4538 | sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i)); |
| 4539 | memmove(sequences_hp + i - 1, sequences_hp + i, | 4539 | memmove(sequences_hp + i, sequences_hp + i + 1, |
| 4540 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); | 4540 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); |
| 4541 | } | 4541 | } |
| 4542 | } | 4542 | } |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 4ef5efaaaef1..488fd9ade1ba 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
| @@ -972,6 +972,53 @@ static struct hda_verb cs_coef_init_verbs[] = { | |||
| 972 | {} /* terminator */ | 972 | {} /* terminator */ |
| 973 | }; | 973 | }; |
| 974 | 974 | ||
| 975 | /* Errata: CS4207 rev C0/C1/C2 Silicon | ||
| 976 | * | ||
| 977 | * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf | ||
| 978 | * | ||
| 979 | * 6. At high temperature (TA > +85°C), the digital supply current (IVD) | ||
| 980 | * may be excessive (up to an additional 200 μA), which is most easily | ||
| 981 | * observed while the part is being held in reset (RESET# active low). | ||
| 982 | * | ||
| 983 | * Root Cause: At initial powerup of the device, the logic that drives | ||
| 984 | * the clock and write enable to the S/PDIF SRC RAMs is not properly | ||
| 985 | * initialized. | ||
| 986 | * Certain random patterns will cause a steady leakage current in those | ||
| 987 | * RAM cells. The issue will resolve once the SRCs are used (turned on). | ||
| 988 | * | ||
| 989 | * Workaround: The following verb sequence briefly turns on the S/PDIF SRC | ||
| 990 | * blocks, which will alleviate the issue. | ||
| 991 | */ | ||
| 992 | |||
| 993 | static struct hda_verb cs_errata_init_verbs[] = { | ||
| 994 | {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */ | ||
| 995 | {0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ | ||
| 996 | |||
| 997 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, | ||
| 998 | {0x11, AC_VERB_SET_PROC_COEF, 0x9999}, | ||
| 999 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, | ||
| 1000 | {0x11, AC_VERB_SET_PROC_COEF, 0xa412}, | ||
| 1001 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, | ||
| 1002 | {0x11, AC_VERB_SET_PROC_COEF, 0x0009}, | ||
| 1003 | |||
| 1004 | {0x07, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Rx: D0 */ | ||
| 1005 | {0x08, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Tx: D0 */ | ||
| 1006 | |||
| 1007 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, | ||
| 1008 | {0x11, AC_VERB_SET_PROC_COEF, 0x2412}, | ||
| 1009 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, | ||
| 1010 | {0x11, AC_VERB_SET_PROC_COEF, 0x0000}, | ||
| 1011 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, | ||
| 1012 | {0x11, AC_VERB_SET_PROC_COEF, 0x0008}, | ||
| 1013 | {0x11, AC_VERB_SET_PROC_STATE, 0x00}, | ||
| 1014 | |||
| 1015 | {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */ | ||
| 1016 | {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */ | ||
| 1017 | /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */ | ||
| 1018 | |||
| 1019 | {} /* terminator */ | ||
| 1020 | }; | ||
| 1021 | |||
| 975 | /* SPDIF setup */ | 1022 | /* SPDIF setup */ |
| 976 | static void init_digital(struct hda_codec *codec) | 1023 | static void init_digital(struct hda_codec *codec) |
| 977 | { | 1024 | { |
| @@ -991,6 +1038,9 @@ static int cs_init(struct hda_codec *codec) | |||
| 991 | { | 1038 | { |
| 992 | struct cs_spec *spec = codec->spec; | 1039 | struct cs_spec *spec = codec->spec; |
| 993 | 1040 | ||
| 1041 | /* init_verb sequence for C0/C1/C2 errata*/ | ||
| 1042 | snd_hda_sequence_write(codec, cs_errata_init_verbs); | ||
| 1043 | |||
| 994 | snd_hda_sequence_write(codec, cs_coef_init_verbs); | 1044 | snd_hda_sequence_write(codec, cs_coef_init_verbs); |
| 995 | 1045 | ||
| 996 | if (spec->gpio_mask) { | 1046 | if (spec->gpio_mask) { |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5cdb80edbd7f..71f9d6475b09 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
| @@ -116,6 +116,7 @@ struct conexant_spec { | |||
| 116 | unsigned int dell_vostro:1; | 116 | unsigned int dell_vostro:1; |
| 117 | unsigned int ideapad:1; | 117 | unsigned int ideapad:1; |
| 118 | unsigned int thinkpad:1; | 118 | unsigned int thinkpad:1; |
| 119 | unsigned int hp_laptop:1; | ||
| 119 | 120 | ||
| 120 | unsigned int ext_mic_present; | 121 | unsigned int ext_mic_present; |
| 121 | unsigned int recording; | 122 | unsigned int recording; |
| @@ -2299,6 +2300,18 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) | |||
| 2299 | } | 2300 | } |
| 2300 | } | 2301 | } |
| 2301 | 2302 | ||
| 2303 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
| 2304 | static void cxt5066_hp_laptop_automic(struct hda_codec *codec) | ||
| 2305 | { | ||
| 2306 | unsigned int present; | ||
| 2307 | |||
| 2308 | present = snd_hda_jack_detect(codec, 0x1b); | ||
| 2309 | snd_printdd("CXT5066: external microphone present=%d\n", present); | ||
| 2310 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
| 2311 | present ? 1 : 3); | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | |||
| 2302 | /* toggle input of built-in digital mic and mic jack appropriately | 2315 | /* toggle input of built-in digital mic and mic jack appropriately |
| 2303 | order is: external mic -> dock mic -> interal mic */ | 2316 | order is: external mic -> dock mic -> interal mic */ |
| 2304 | static void cxt5066_thinkpad_automic(struct hda_codec *codec) | 2317 | static void cxt5066_thinkpad_automic(struct hda_codec *codec) |
| @@ -2408,6 +2421,20 @@ static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res) | |||
| 2408 | } | 2421 | } |
| 2409 | 2422 | ||
| 2410 | /* unsolicited event for jack sensing */ | 2423 | /* unsolicited event for jack sensing */ |
| 2424 | static void cxt5066_hp_laptop_event(struct hda_codec *codec, unsigned int res) | ||
| 2425 | { | ||
| 2426 | snd_printdd("CXT5066_hp_laptop: unsol event %x (%x)\n", res, res >> 26); | ||
| 2427 | switch (res >> 26) { | ||
| 2428 | case CONEXANT_HP_EVENT: | ||
| 2429 | cxt5066_hp_automute(codec); | ||
| 2430 | break; | ||
| 2431 | case CONEXANT_MIC_EVENT: | ||
| 2432 | cxt5066_hp_laptop_automic(codec); | ||
| 2433 | break; | ||
| 2434 | } | ||
| 2435 | } | ||
| 2436 | |||
| 2437 | /* unsolicited event for jack sensing */ | ||
| 2411 | static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) | 2438 | static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) |
| 2412 | { | 2439 | { |
| 2413 | snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26); | 2440 | snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26); |
| @@ -2989,6 +3016,14 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = { | |||
| 2989 | { } /* end */ | 3016 | { } /* end */ |
| 2990 | }; | 3017 | }; |
| 2991 | 3018 | ||
| 3019 | |||
| 3020 | static struct hda_verb cxt5066_init_verbs_hp_laptop[] = { | ||
| 3021 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
| 3022 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
| 3023 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
| 3024 | { } /* end */ | ||
| 3025 | }; | ||
| 3026 | |||
| 2992 | /* initialize jack-sensing, too */ | 3027 | /* initialize jack-sensing, too */ |
| 2993 | static int cxt5066_init(struct hda_codec *codec) | 3028 | static int cxt5066_init(struct hda_codec *codec) |
| 2994 | { | 3029 | { |
| @@ -3004,6 +3039,8 @@ static int cxt5066_init(struct hda_codec *codec) | |||
| 3004 | cxt5066_ideapad_automic(codec); | 3039 | cxt5066_ideapad_automic(codec); |
| 3005 | else if (spec->thinkpad) | 3040 | else if (spec->thinkpad) |
| 3006 | cxt5066_thinkpad_automic(codec); | 3041 | cxt5066_thinkpad_automic(codec); |
| 3042 | else if (spec->hp_laptop) | ||
| 3043 | cxt5066_hp_laptop_automic(codec); | ||
| 3007 | } | 3044 | } |
| 3008 | cxt5066_set_mic_boost(codec); | 3045 | cxt5066_set_mic_boost(codec); |
| 3009 | return 0; | 3046 | return 0; |
| @@ -3031,6 +3068,7 @@ enum { | |||
| 3031 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ | 3068 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ |
| 3032 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | 3069 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ |
| 3033 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | 3070 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ |
| 3071 | CXT5066_HP_LAPTOP, /* HP Laptop */ | ||
| 3034 | CXT5066_MODELS | 3072 | CXT5066_MODELS |
| 3035 | }; | 3073 | }; |
| 3036 | 3074 | ||
| @@ -3041,6 +3079,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = { | |||
| 3041 | [CXT5066_DELL_VOSTO] = "dell-vostro", | 3079 | [CXT5066_DELL_VOSTO] = "dell-vostro", |
| 3042 | [CXT5066_IDEAPAD] = "ideapad", | 3080 | [CXT5066_IDEAPAD] = "ideapad", |
| 3043 | [CXT5066_THINKPAD] = "thinkpad", | 3081 | [CXT5066_THINKPAD] = "thinkpad", |
| 3082 | [CXT5066_HP_LAPTOP] = "hp-laptop", | ||
| 3044 | }; | 3083 | }; |
| 3045 | 3084 | ||
| 3046 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | 3085 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { |
| @@ -3052,8 +3091,10 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
| 3052 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), | 3091 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), |
| 3053 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), | 3092 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), |
| 3054 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | 3093 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), |
| 3094 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), | ||
| 3055 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), | 3095 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), |
| 3056 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), | 3096 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), |
| 3097 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | ||
| 3057 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), | 3098 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), |
| 3058 | SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), | 3099 | SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), |
| 3059 | SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), | 3100 | SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), |
| @@ -3116,6 +3157,23 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
| 3116 | spec->num_init_verbs++; | 3157 | spec->num_init_verbs++; |
| 3117 | spec->dell_automute = 1; | 3158 | spec->dell_automute = 1; |
| 3118 | break; | 3159 | break; |
| 3160 | case CXT5066_HP_LAPTOP: | ||
| 3161 | codec->patch_ops.init = cxt5066_init; | ||
| 3162 | codec->patch_ops.unsol_event = cxt5066_hp_laptop_event; | ||
| 3163 | spec->init_verbs[spec->num_init_verbs] = | ||
| 3164 | cxt5066_init_verbs_hp_laptop; | ||
| 3165 | spec->num_init_verbs++; | ||
| 3166 | spec->hp_laptop = 1; | ||
| 3167 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
| 3168 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
| 3169 | /* no S/PDIF out */ | ||
| 3170 | spec->multiout.dig_out_nid = 0; | ||
| 3171 | /* input source automatically selected */ | ||
| 3172 | spec->input_mux = NULL; | ||
| 3173 | spec->port_d_mode = 0; | ||
| 3174 | spec->mic_boost = 3; /* default 30dB gain */ | ||
| 3175 | break; | ||
| 3176 | |||
| 3119 | case CXT5066_OLPC_XO_1_5: | 3177 | case CXT5066_OLPC_XO_1_5: |
| 3120 | codec->patch_ops.init = cxt5066_olpc_init; | 3178 | codec->patch_ops.init = cxt5066_olpc_init; |
| 3121 | codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; | 3179 | codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 627bf9963368..bcbf9160ed81 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -5334,6 +5334,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
| 5334 | 5334 | ||
| 5335 | static struct snd_pci_quirk beep_white_list[] = { | 5335 | static struct snd_pci_quirk beep_white_list[] = { |
| 5336 | SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), | 5336 | SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), |
| 5337 | SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), | ||
| 5337 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), | 5338 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), |
| 5338 | {} | 5339 | {} |
| 5339 | }; | 5340 | }; |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index 6147216af744..a3409edcfb50 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
| @@ -155,6 +155,7 @@ void oxygen_pci_remove(struct pci_dev *pci); | |||
| 155 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); | 155 | int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); |
| 156 | int oxygen_pci_resume(struct pci_dev *pci); | 156 | int oxygen_pci_resume(struct pci_dev *pci); |
| 157 | #endif | 157 | #endif |
| 158 | void oxygen_pci_shutdown(struct pci_dev *pci); | ||
| 158 | 159 | ||
| 159 | /* oxygen_mixer.c */ | 160 | /* oxygen_mixer.c */ |
| 160 | 161 | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index fad03d64e3ad..7e93cf884437 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
| @@ -519,16 +519,21 @@ static void oxygen_init(struct oxygen *chip) | |||
| 519 | } | 519 | } |
| 520 | } | 520 | } |
| 521 | 521 | ||
| 522 | static void oxygen_card_free(struct snd_card *card) | 522 | static void oxygen_shutdown(struct oxygen *chip) |
| 523 | { | 523 | { |
| 524 | struct oxygen *chip = card->private_data; | ||
| 525 | |||
| 526 | spin_lock_irq(&chip->reg_lock); | 524 | spin_lock_irq(&chip->reg_lock); |
| 527 | chip->interrupt_mask = 0; | 525 | chip->interrupt_mask = 0; |
| 528 | chip->pcm_running = 0; | 526 | chip->pcm_running = 0; |
| 529 | oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); | 527 | oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); |
| 530 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); | 528 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); |
| 531 | spin_unlock_irq(&chip->reg_lock); | 529 | spin_unlock_irq(&chip->reg_lock); |
| 530 | } | ||
| 531 | |||
| 532 | static void oxygen_card_free(struct snd_card *card) | ||
| 533 | { | ||
| 534 | struct oxygen *chip = card->private_data; | ||
| 535 | |||
| 536 | oxygen_shutdown(chip); | ||
| 532 | if (chip->irq >= 0) | 537 | if (chip->irq >= 0) |
| 533 | free_irq(chip->irq, chip); | 538 | free_irq(chip->irq, chip); |
| 534 | flush_scheduled_work(); | 539 | flush_scheduled_work(); |
| @@ -778,3 +783,13 @@ int oxygen_pci_resume(struct pci_dev *pci) | |||
| 778 | } | 783 | } |
| 779 | EXPORT_SYMBOL(oxygen_pci_resume); | 784 | EXPORT_SYMBOL(oxygen_pci_resume); |
| 780 | #endif /* CONFIG_PM */ | 785 | #endif /* CONFIG_PM */ |
| 786 | |||
| 787 | void oxygen_pci_shutdown(struct pci_dev *pci) | ||
| 788 | { | ||
| 789 | struct snd_card *card = pci_get_drvdata(pci); | ||
| 790 | struct oxygen *chip = card->private_data; | ||
| 791 | |||
| 792 | oxygen_shutdown(chip); | ||
| 793 | chip->model.cleanup(chip); | ||
| 794 | } | ||
| 795 | EXPORT_SYMBOL(oxygen_pci_shutdown); | ||
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index f03a2f2cffee..06c863e86e3d 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
| @@ -95,6 +95,7 @@ static struct pci_driver xonar_driver = { | |||
| 95 | .suspend = oxygen_pci_suspend, | 95 | .suspend = oxygen_pci_suspend, |
| 96 | .resume = oxygen_pci_resume, | 96 | .resume = oxygen_pci_resume, |
| 97 | #endif | 97 | #endif |
| 98 | .shutdown = oxygen_pci_shutdown, | ||
| 98 | }; | 99 | }; |
| 99 | 100 | ||
| 100 | static int __init alsa_card_xonar_init(void) | 101 | static int __init alsa_card_xonar_init(void) |
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index dbc4b89d74e4..b82c1cfa96f5 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
| @@ -53,6 +53,8 @@ struct xonar_wm87x6 { | |||
| 53 | struct xonar_generic generic; | 53 | struct xonar_generic generic; |
| 54 | u16 wm8776_regs[0x17]; | 54 | u16 wm8776_regs[0x17]; |
| 55 | u16 wm8766_regs[0x10]; | 55 | u16 wm8766_regs[0x10]; |
| 56 | struct snd_kcontrol *line_adcmux_control; | ||
| 57 | struct snd_kcontrol *mic_adcmux_control; | ||
| 56 | struct snd_kcontrol *lc_controls[13]; | 58 | struct snd_kcontrol *lc_controls[13]; |
| 57 | }; | 59 | }; |
| 58 | 60 | ||
| @@ -193,6 +195,7 @@ static void xonar_ds_init(struct oxygen *chip) | |||
| 193 | static void xonar_ds_cleanup(struct oxygen *chip) | 195 | static void xonar_ds_cleanup(struct oxygen *chip) |
| 194 | { | 196 | { |
| 195 | xonar_disable_output(chip); | 197 | xonar_disable_output(chip); |
| 198 | wm8776_write(chip, WM8776_RESET, 0); | ||
| 196 | } | 199 | } |
| 197 | 200 | ||
| 198 | static void xonar_ds_suspend(struct oxygen *chip) | 201 | static void xonar_ds_suspend(struct oxygen *chip) |
| @@ -603,6 +606,7 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, | |||
| 603 | { | 606 | { |
| 604 | struct oxygen *chip = ctl->private_data; | 607 | struct oxygen *chip = ctl->private_data; |
| 605 | struct xonar_wm87x6 *data = chip->model_data; | 608 | struct xonar_wm87x6 *data = chip->model_data; |
| 609 | struct snd_kcontrol *other_ctl; | ||
| 606 | unsigned int mux_bit = ctl->private_value; | 610 | unsigned int mux_bit = ctl->private_value; |
| 607 | u16 reg; | 611 | u16 reg; |
| 608 | int changed; | 612 | int changed; |
| @@ -610,8 +614,18 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, | |||
| 610 | mutex_lock(&chip->mutex); | 614 | mutex_lock(&chip->mutex); |
| 611 | reg = data->wm8776_regs[WM8776_ADCMUX]; | 615 | reg = data->wm8776_regs[WM8776_ADCMUX]; |
| 612 | if (value->value.integer.value[0]) { | 616 | if (value->value.integer.value[0]) { |
| 613 | reg &= ~0x003; | ||
| 614 | reg |= mux_bit; | 617 | reg |= mux_bit; |
| 618 | /* line-in and mic-in are exclusive */ | ||
| 619 | mux_bit ^= 3; | ||
| 620 | if (reg & mux_bit) { | ||
| 621 | reg &= ~mux_bit; | ||
| 622 | if (mux_bit == 1) | ||
| 623 | other_ctl = data->line_adcmux_control; | ||
| 624 | else | ||
| 625 | other_ctl = data->mic_adcmux_control; | ||
| 626 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
| 627 | &other_ctl->id); | ||
| 628 | } | ||
| 615 | } else | 629 | } else |
| 616 | reg &= ~mux_bit; | 630 | reg &= ~mux_bit; |
| 617 | changed = reg != data->wm8776_regs[WM8776_ADCMUX]; | 631 | changed = reg != data->wm8776_regs[WM8776_ADCMUX]; |
| @@ -963,7 +977,13 @@ static int xonar_ds_mixer_init(struct oxygen *chip) | |||
| 963 | err = snd_ctl_add(chip->card, ctl); | 977 | err = snd_ctl_add(chip->card, ctl); |
| 964 | if (err < 0) | 978 | if (err < 0) |
| 965 | return err; | 979 | return err; |
| 980 | if (!strcmp(ctl->id.name, "Line Capture Switch")) | ||
| 981 | data->line_adcmux_control = ctl; | ||
| 982 | else if (!strcmp(ctl->id.name, "Mic Capture Switch")) | ||
| 983 | data->mic_adcmux_control = ctl; | ||
| 966 | } | 984 | } |
| 985 | if (!data->line_adcmux_control || !data->mic_adcmux_control) | ||
| 986 | return -ENXIO; | ||
| 967 | BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); | 987 | BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); |
| 968 | for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { | 988 | for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { |
| 969 | ctl = snd_ctl_new1(&lc_controls[i], chip); | 989 | ctl = snd_ctl_new1(&lc_controls[i], chip); |
diff --git a/sound/usb/card.c b/sound/usb/card.c index 9feb00c831a0..4eabafa5b037 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
| @@ -126,7 +126,7 @@ static void snd_usb_stream_disconnect(struct list_head *head) | |||
| 126 | for (idx = 0; idx < 2; idx++) { | 126 | for (idx = 0; idx < 2; idx++) { |
| 127 | subs = &as->substream[idx]; | 127 | subs = &as->substream[idx]; |
| 128 | if (!subs->num_formats) | 128 | if (!subs->num_formats) |
| 129 | return; | 129 | continue; |
| 130 | snd_usb_release_substream_urbs(subs, 1); | 130 | snd_usb_release_substream_urbs(subs, 1); |
| 131 | subs->interface = -1; | 131 | subs->interface = -1; |
| 132 | } | 132 | } |
| @@ -216,6 +216,11 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) | |||
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | switch (protocol) { | 218 | switch (protocol) { |
| 219 | default: | ||
| 220 | snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n", | ||
| 221 | protocol); | ||
| 222 | /* fall through */ | ||
| 223 | |||
| 219 | case UAC_VERSION_1: { | 224 | case UAC_VERSION_1: { |
| 220 | struct uac1_ac_header_descriptor *h1 = control_header; | 225 | struct uac1_ac_header_descriptor *h1 = control_header; |
| 221 | 226 | ||
| @@ -253,10 +258,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) | |||
| 253 | 258 | ||
| 254 | break; | 259 | break; |
| 255 | } | 260 | } |
| 256 | |||
| 257 | default: | ||
| 258 | snd_printk(KERN_ERR "unknown protocol version 0x%02x\n", protocol); | ||
| 259 | return -EINVAL; | ||
| 260 | } | 261 | } |
| 261 | 262 | ||
| 262 | return 0; | 263 | return 0; |
| @@ -465,7 +466,13 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
| 465 | goto __error; | 466 | goto __error; |
| 466 | } | 467 | } |
| 467 | 468 | ||
| 468 | chip->ctrl_intf = alts; | 469 | /* |
| 470 | * For devices with more than one control interface, we assume the | ||
| 471 | * first contains the audio controls. We might need a more specific | ||
| 472 | * check here in the future. | ||
| 473 | */ | ||
| 474 | if (!chip->ctrl_intf) | ||
| 475 | chip->ctrl_intf = alts; | ||
| 469 | 476 | ||
| 470 | if (err > 0) { | 477 | if (err > 0) { |
| 471 | /* create normal USB audio interfaces */ | 478 | /* create normal USB audio interfaces */ |
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index b853f8df794f..7754a1034545 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c | |||
| @@ -295,12 +295,11 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, | |||
| 295 | 295 | ||
| 296 | switch (altsd->bInterfaceProtocol) { | 296 | switch (altsd->bInterfaceProtocol) { |
| 297 | case UAC_VERSION_1: | 297 | case UAC_VERSION_1: |
| 298 | default: | ||
| 298 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); | 299 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); |
| 299 | 300 | ||
| 300 | case UAC_VERSION_2: | 301 | case UAC_VERSION_2: |
| 301 | return set_sample_rate_v2(chip, iface, alts, fmt, rate); | 302 | return set_sample_rate_v2(chip, iface, alts, fmt, rate); |
| 302 | } | 303 | } |
| 303 | |||
| 304 | return -EINVAL; | ||
| 305 | } | 304 | } |
| 306 | 305 | ||
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 1a701f1e8f50..ef0a07e34844 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
| @@ -275,6 +275,12 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
| 275 | 275 | ||
| 276 | /* get audio formats */ | 276 | /* get audio formats */ |
| 277 | switch (protocol) { | 277 | switch (protocol) { |
| 278 | default: | ||
| 279 | snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", | ||
| 280 | dev->devnum, iface_no, altno, protocol); | ||
| 281 | protocol = UAC_VERSION_1; | ||
| 282 | /* fall through */ | ||
| 283 | |||
| 278 | case UAC_VERSION_1: { | 284 | case UAC_VERSION_1: { |
| 279 | struct uac1_as_header_descriptor *as = | 285 | struct uac1_as_header_descriptor *as = |
| 280 | snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); | 286 | snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); |
| @@ -336,11 +342,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
| 336 | dev->devnum, iface_no, altno, as->bTerminalLink); | 342 | dev->devnum, iface_no, altno, as->bTerminalLink); |
| 337 | continue; | 343 | continue; |
| 338 | } | 344 | } |
| 339 | |||
| 340 | default: | ||
| 341 | snd_printk(KERN_ERR "%d:%u:%d : unknown interface protocol %04x\n", | ||
| 342 | dev->devnum, iface_no, altno, protocol); | ||
| 343 | continue; | ||
| 344 | } | 345 | } |
| 345 | 346 | ||
| 346 | /* get format type */ | 347 | /* get format type */ |
diff --git a/sound/usb/format.c b/sound/usb/format.c index 3a1375459c06..69148212aa70 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c | |||
| @@ -49,7 +49,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, | |||
| 49 | u64 pcm_formats; | 49 | u64 pcm_formats; |
| 50 | 50 | ||
| 51 | switch (protocol) { | 51 | switch (protocol) { |
| 52 | case UAC_VERSION_1: { | 52 | case UAC_VERSION_1: |
| 53 | default: { | ||
| 53 | struct uac_format_type_i_discrete_descriptor *fmt = _fmt; | 54 | struct uac_format_type_i_discrete_descriptor *fmt = _fmt; |
| 54 | sample_width = fmt->bBitResolution; | 55 | sample_width = fmt->bBitResolution; |
| 55 | sample_bytes = fmt->bSubframeSize; | 56 | sample_bytes = fmt->bSubframeSize; |
| @@ -64,9 +65,6 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, | |||
| 64 | format <<= 1; | 65 | format <<= 1; |
| 65 | break; | 66 | break; |
| 66 | } | 67 | } |
| 67 | |||
| 68 | default: | ||
| 69 | return -EINVAL; | ||
| 70 | } | 68 | } |
| 71 | 69 | ||
| 72 | pcm_formats = 0; | 70 | pcm_formats = 0; |
| @@ -384,6 +382,10 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
| 384 | * audio class v2 uses class specific EP0 range requests for that. | 382 | * audio class v2 uses class specific EP0 range requests for that. |
| 385 | */ | 383 | */ |
| 386 | switch (protocol) { | 384 | switch (protocol) { |
| 385 | default: | ||
| 386 | snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", | ||
| 387 | chip->dev->devnum, fp->iface, fp->altsetting, protocol); | ||
| 388 | /* fall through */ | ||
| 387 | case UAC_VERSION_1: | 389 | case UAC_VERSION_1: |
| 388 | fp->channels = fmt->bNrChannels; | 390 | fp->channels = fmt->bNrChannels; |
| 389 | ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); | 391 | ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); |
| @@ -392,10 +394,6 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
| 392 | /* fp->channels is already set in this case */ | 394 | /* fp->channels is already set in this case */ |
| 393 | ret = parse_audio_format_rates_v2(chip, fp); | 395 | ret = parse_audio_format_rates_v2(chip, fp); |
| 394 | break; | 396 | break; |
| 395 | default: | ||
| 396 | snd_printk(KERN_ERR "%d:%u:%d : invalid protocol version %d\n", | ||
| 397 | chip->dev->devnum, fp->iface, fp->altsetting, protocol); | ||
| 398 | return -EINVAL; | ||
| 399 | } | 397 | } |
| 400 | 398 | ||
| 401 | if (fp->channels < 1) { | 399 | if (fp->channels < 1) { |
| @@ -438,6 +436,10 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
| 438 | fp->channels = 1; | 436 | fp->channels = 1; |
| 439 | 437 | ||
| 440 | switch (protocol) { | 438 | switch (protocol) { |
| 439 | default: | ||
| 440 | snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", | ||
| 441 | chip->dev->devnum, fp->iface, fp->altsetting, protocol); | ||
| 442 | /* fall through */ | ||
| 441 | case UAC_VERSION_1: { | 443 | case UAC_VERSION_1: { |
| 442 | struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; | 444 | struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; |
| 443 | brate = le16_to_cpu(fmt->wMaxBitRate); | 445 | brate = le16_to_cpu(fmt->wMaxBitRate); |
| @@ -456,10 +458,6 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
| 456 | ret = parse_audio_format_rates_v2(chip, fp); | 458 | ret = parse_audio_format_rates_v2(chip, fp); |
| 457 | break; | 459 | break; |
| 458 | } | 460 | } |
| 459 | default: | ||
| 460 | snd_printk(KERN_ERR "%d:%u:%d : invalid protocol version %d\n", | ||
| 461 | chip->dev->devnum, fp->iface, fp->altsetting, protocol); | ||
| 462 | return -EINVAL; | ||
| 463 | } | 461 | } |
| 464 | 462 | ||
| 465 | return ret; | 463 | return ret; |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c166db0057d3..3ed3901369ce 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
| @@ -2175,7 +2175,15 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
| 2175 | } | 2175 | } |
| 2176 | 2176 | ||
| 2177 | host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; | 2177 | host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; |
| 2178 | mixer->protocol = get_iface_desc(host_iface)->bInterfaceProtocol; | 2178 | switch (get_iface_desc(host_iface)->bInterfaceProtocol) { |
| 2179 | case UAC_VERSION_1: | ||
| 2180 | default: | ||
| 2181 | mixer->protocol = UAC_VERSION_1; | ||
| 2182 | break; | ||
| 2183 | case UAC_VERSION_2: | ||
| 2184 | mixer->protocol = UAC_VERSION_2; | ||
| 2185 | break; | ||
| 2186 | } | ||
| 2179 | 2187 | ||
| 2180 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || | 2188 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || |
| 2181 | (err = snd_usb_mixer_status_create(mixer)) < 0) | 2189 | (err = snd_usb_mixer_status_create(mixer)) < 0) |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 3634cedf9306..3b5135c93062 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
| @@ -173,13 +173,12 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, | |||
| 173 | 173 | ||
| 174 | switch (altsd->bInterfaceProtocol) { | 174 | switch (altsd->bInterfaceProtocol) { |
| 175 | case UAC_VERSION_1: | 175 | case UAC_VERSION_1: |
| 176 | default: | ||
| 176 | return init_pitch_v1(chip, iface, alts, fmt); | 177 | return init_pitch_v1(chip, iface, alts, fmt); |
| 177 | 178 | ||
| 178 | case UAC_VERSION_2: | 179 | case UAC_VERSION_2: |
| 179 | return init_pitch_v2(chip, iface, alts, fmt); | 180 | return init_pitch_v2(chip, iface, alts, fmt); |
| 180 | } | 181 | } |
| 181 | |||
| 182 | return -EINVAL; | ||
| 183 | } | 182 | } |
| 184 | 183 | ||
| 185 | /* | 184 | /* |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index e72f05c3bef0..fcc16e4349df 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -1539,6 +1539,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
| 1539 | goto error; | 1539 | goto error; |
| 1540 | } | 1540 | } |
| 1541 | tev->point.offset = pev->point.offset; | 1541 | tev->point.offset = pev->point.offset; |
| 1542 | tev->point.retprobe = pev->point.retprobe; | ||
| 1542 | tev->nargs = pev->nargs; | 1543 | tev->nargs = pev->nargs; |
| 1543 | if (tev->nargs) { | 1544 | if (tev->nargs) { |
| 1544 | tev->args = zalloc(sizeof(struct probe_trace_arg) | 1545 | tev->args = zalloc(sizeof(struct probe_trace_arg) |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 525136684d4e..32b81f707ff5 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -686,6 +686,25 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) | |||
| 686 | char buf[32], *ptr; | 686 | char buf[32], *ptr; |
| 687 | int ret, nscopes; | 687 | int ret, nscopes; |
| 688 | 688 | ||
| 689 | if (!is_c_varname(pf->pvar->var)) { | ||
| 690 | /* Copy raw parameters */ | ||
| 691 | pf->tvar->value = strdup(pf->pvar->var); | ||
| 692 | if (pf->tvar->value == NULL) | ||
| 693 | return -ENOMEM; | ||
| 694 | if (pf->pvar->type) { | ||
| 695 | pf->tvar->type = strdup(pf->pvar->type); | ||
| 696 | if (pf->tvar->type == NULL) | ||
| 697 | return -ENOMEM; | ||
| 698 | } | ||
| 699 | if (pf->pvar->name) { | ||
| 700 | pf->tvar->name = strdup(pf->pvar->name); | ||
| 701 | if (pf->tvar->name == NULL) | ||
| 702 | return -ENOMEM; | ||
| 703 | } else | ||
| 704 | pf->tvar->name = NULL; | ||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 689 | if (pf->pvar->name) | 708 | if (pf->pvar->name) |
| 690 | pf->tvar->name = strdup(pf->pvar->name); | 709 | pf->tvar->name = strdup(pf->pvar->name); |
| 691 | else { | 710 | else { |
| @@ -700,19 +719,6 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) | |||
| 700 | if (pf->tvar->name == NULL) | 719 | if (pf->tvar->name == NULL) |
| 701 | return -ENOMEM; | 720 | return -ENOMEM; |
| 702 | 721 | ||
| 703 | if (!is_c_varname(pf->pvar->var)) { | ||
| 704 | /* Copy raw parameters */ | ||
| 705 | pf->tvar->value = strdup(pf->pvar->var); | ||
| 706 | if (pf->tvar->value == NULL) | ||
| 707 | return -ENOMEM; | ||
| 708 | if (pf->pvar->type) { | ||
| 709 | pf->tvar->type = strdup(pf->pvar->type); | ||
| 710 | if (pf->tvar->type == NULL) | ||
| 711 | return -ENOMEM; | ||
| 712 | } | ||
| 713 | return 0; | ||
| 714 | } | ||
| 715 | |||
| 716 | pr_debug("Searching '%s' variable in context.\n", | 722 | pr_debug("Searching '%s' variable in context.\n", |
| 717 | pf->pvar->var); | 723 | pf->pvar->var); |
| 718 | /* Search child die for local variables and parameters. */ | 724 | /* Search child die for local variables and parameters. */ |
| @@ -783,6 +789,16 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) | |||
| 783 | /* This function has no name. */ | 789 | /* This function has no name. */ |
| 784 | tev->point.offset = (unsigned long)pf->addr; | 790 | tev->point.offset = (unsigned long)pf->addr; |
| 785 | 791 | ||
| 792 | /* Return probe must be on the head of a subprogram */ | ||
| 793 | if (pf->pev->point.retprobe) { | ||
| 794 | if (tev->point.offset != 0) { | ||
| 795 | pr_warning("Return probe must be on the head of" | ||
| 796 | " a real function\n"); | ||
| 797 | return -EINVAL; | ||
| 798 | } | ||
| 799 | tev->point.retprobe = true; | ||
| 800 | } | ||
| 801 | |||
| 786 | pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, | 802 | pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, |
| 787 | tev->point.offset); | 803 | tev->point.offset); |
| 788 | 804 | ||
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 1a367734e016..b2f5ae97f33d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -2268,6 +2268,9 @@ static int setup_list(struct strlist **list, const char *list_str, | |||
| 2268 | 2268 | ||
| 2269 | int symbol__init(void) | 2269 | int symbol__init(void) |
| 2270 | { | 2270 | { |
| 2271 | if (symbol_conf.initialized) | ||
| 2272 | return 0; | ||
| 2273 | |||
| 2271 | elf_version(EV_CURRENT); | 2274 | elf_version(EV_CURRENT); |
| 2272 | if (symbol_conf.sort_by_name) | 2275 | if (symbol_conf.sort_by_name) |
| 2273 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - | 2276 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - |
| @@ -2293,6 +2296,7 @@ int symbol__init(void) | |||
| 2293 | symbol_conf.sym_list_str, "symbol") < 0) | 2296 | symbol_conf.sym_list_str, "symbol") < 0) |
| 2294 | goto out_free_comm_list; | 2297 | goto out_free_comm_list; |
| 2295 | 2298 | ||
| 2299 | symbol_conf.initialized = true; | ||
| 2296 | return 0; | 2300 | return 0; |
| 2297 | 2301 | ||
| 2298 | out_free_dso_list: | 2302 | out_free_dso_list: |
| @@ -2304,11 +2308,14 @@ out_free_comm_list: | |||
| 2304 | 2308 | ||
| 2305 | void symbol__exit(void) | 2309 | void symbol__exit(void) |
| 2306 | { | 2310 | { |
| 2311 | if (!symbol_conf.initialized) | ||
| 2312 | return; | ||
| 2307 | strlist__delete(symbol_conf.sym_list); | 2313 | strlist__delete(symbol_conf.sym_list); |
| 2308 | strlist__delete(symbol_conf.dso_list); | 2314 | strlist__delete(symbol_conf.dso_list); |
| 2309 | strlist__delete(symbol_conf.comm_list); | 2315 | strlist__delete(symbol_conf.comm_list); |
| 2310 | vmlinux_path__exit(); | 2316 | vmlinux_path__exit(); |
| 2311 | symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; | 2317 | symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; |
| 2318 | symbol_conf.initialized = false; | ||
| 2312 | } | 2319 | } |
| 2313 | 2320 | ||
| 2314 | int machines__create_kernel_maps(struct rb_root *self, pid_t pid) | 2321 | int machines__create_kernel_maps(struct rb_root *self, pid_t pid) |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index b7a8da4af5a0..ea95c2756f05 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -69,7 +69,8 @@ struct symbol_conf { | |||
| 69 | show_nr_samples, | 69 | show_nr_samples, |
| 70 | use_callchain, | 70 | use_callchain, |
| 71 | exclude_other, | 71 | exclude_other, |
| 72 | show_cpu_utilization; | 72 | show_cpu_utilization, |
| 73 | initialized; | ||
| 73 | const char *vmlinux_name, | 74 | const char *vmlinux_name, |
| 74 | *source_prefix, | 75 | *source_prefix, |
| 75 | *field_sep; | 76 | *field_sep; |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index b78b794c1039..d4853a54771a 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -1958,10 +1958,10 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | |||
| 1958 | cpu); | 1958 | cpu); |
| 1959 | hardware_disable(NULL); | 1959 | hardware_disable(NULL); |
| 1960 | break; | 1960 | break; |
| 1961 | case CPU_ONLINE: | 1961 | case CPU_STARTING: |
| 1962 | printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", | 1962 | printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", |
| 1963 | cpu); | 1963 | cpu); |
| 1964 | smp_call_function_single(cpu, hardware_enable, NULL, 1); | 1964 | hardware_enable(NULL); |
| 1965 | break; | 1965 | break; |
| 1966 | } | 1966 | } |
| 1967 | return NOTIFY_OK; | 1967 | return NOTIFY_OK; |
| @@ -2096,7 +2096,6 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, | |||
| 2096 | 2096 | ||
| 2097 | static struct notifier_block kvm_cpu_notifier = { | 2097 | static struct notifier_block kvm_cpu_notifier = { |
| 2098 | .notifier_call = kvm_cpu_hotplug, | 2098 | .notifier_call = kvm_cpu_hotplug, |
| 2099 | .priority = 20, /* must be > scheduler priority */ | ||
| 2100 | }; | 2099 | }; |
| 2101 | 2100 | ||
| 2102 | static int vm_stat_get(void *_offset, u64 *val) | 2101 | static int vm_stat_get(void *_offset, u64 *val) |
