diff options
728 files changed, 27184 insertions, 18584 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 5b5aba404aac..73060819ed99 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -251,8 +251,6 @@ mono.txt - how to execute Mono-based .NET binaries with the help of BINFMT_MISC. moxa-smartio - file with info on installing/using Moxa multiport serial driver. -mtrr.txt - - how to use PPro Memory Type Range Registers to increase performance. mutex-design.txt - info on the generic mutex subsystem. namespaces/ diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index d8b63d164e41..b8e86460046e 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -337,7 +337,7 @@ With scatterlists, you use the resulting mapping like this: int i, count = dma_map_sg(dev, sglist, nents, direction); struct scatterlist *sg; - for (i = 0, sg = sglist; i < count; i++, sg++) { + for_each_sg(sglist, sg, count, i) { hw_address[i] = sg_dma_address(sg); hw_len[i] = sg_dma_len(sg); } diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index b7b1482f6e04..9d0058e788e5 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -283,6 +283,7 @@ X!Earch/x86/kernel/mca_32.c <chapter id="security"> <title>Security Framework</title> !Isecurity/security.c +!Esecurity/inode.c </chapter> <chapter id="audit"> @@ -364,6 +365,10 @@ X!Edrivers/pnp/system.c !Eblock/blk-barrier.c !Eblock/blk-tag.c !Iblock/blk-tag.c +!Eblock/blk-integrity.c +!Iblock/blktrace.c +!Iblock/genhd.c +!Eblock/genhd.c </chapter> <chapter id="chrdev"> diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt index cf5562cbe356..6e253407b3dc 100644 --- a/Documentation/RCU/checklist.txt +++ b/Documentation/RCU/checklist.txt @@ -210,7 +210,7 @@ over a rather long period of time, but improvements are always welcome! number of updates per grace period. 9. All RCU list-traversal primitives, which include - rcu_dereference(), list_for_each_rcu(), list_for_each_entry_rcu(), + rcu_dereference(), list_for_each_entry_rcu(), list_for_each_continue_rcu(), and list_for_each_safe_rcu(), must be either within an RCU read-side critical section or must be protected by appropriate update-side locks. RCU diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt index 451de2ad8329..4202ad093130 100644 --- a/Documentation/RCU/rcuref.txt +++ b/Documentation/RCU/rcuref.txt @@ -29,9 +29,9 @@ release_referenced() delete() } If this list/array is made lock free using RCU as in changing the -write_lock() in add() and delete() to spin_lock and changing read_lock -in search_and_reference to rcu_read_lock(), the atomic_get in -search_and_reference could potentially hold reference to an element which +write_lock() in add() and delete() to spin_lock() and changing read_lock() +in search_and_reference() to rcu_read_lock(), the atomic_inc() in +search_and_reference() could potentially hold reference to an element which has already been deleted from the list/array. Use atomic_inc_not_zero() in this scenario as follows: @@ -40,20 +40,20 @@ add() search_and_reference() { { alloc_object rcu_read_lock(); ... search_for_element - atomic_set(&el->rc, 1); if (atomic_inc_not_zero(&el->rc)) { - write_lock(&list_lock); rcu_read_unlock(); + atomic_set(&el->rc, 1); if (!atomic_inc_not_zero(&el->rc)) { + spin_lock(&list_lock); rcu_read_unlock(); return FAIL; add_element } ... ... - write_unlock(&list_lock); rcu_read_unlock(); + spin_unlock(&list_lock); rcu_read_unlock(); } } 3. 4. release_referenced() delete() { { - ... write_lock(&list_lock); + ... spin_lock(&list_lock); if (atomic_dec_and_test(&el->rc)) ... call_rcu(&el->head, el_free); delete_element - ... write_unlock(&list_lock); + ... spin_unlock(&list_lock); } ... if (atomic_dec_and_test(&el->rc)) call_rcu(&el->head, el_free); diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index e04d643a9f57..96170824a717 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -786,8 +786,6 @@ RCU pointer/list traversal: list_for_each_entry_rcu hlist_for_each_entry_rcu - list_for_each_rcu (to be deprecated in favor of - list_for_each_entry_rcu) list_for_each_continue_rcu (to be deprecated in favor of new list_for_each_entry_continue_rcu) diff --git a/Documentation/SELinux.txt b/Documentation/SELinux.txt new file mode 100644 index 000000000000..07eae00f3314 --- /dev/null +++ b/Documentation/SELinux.txt @@ -0,0 +1,27 @@ +If you want to use SELinux, chances are you will want +to use the distro-provided policies, or install the +latest reference policy release from + http://oss.tresys.com/projects/refpolicy + +However, if you want to install a dummy policy for +testing, you can do using 'mdp' provided under +scripts/selinux. Note that this requires the selinux +userspace to be installed - in particular you will +need checkpolicy to compile a kernel, and setfiles and +fixfiles to label the filesystem. + + 1. Compile the kernel with selinux enabled. + 2. Type 'make' to compile mdp. + 3. Make sure that you are not running with + SELinux enabled and a real policy. If + you are, reboot with selinux disabled + before continuing. + 4. Run install_policy.sh: + cd scripts/selinux + sh install_policy.sh + +Step 4 will create a new dummy policy valid for your +kernel, with a single selinux user, role, and type. +It will compile the policy, will set your SELINUXTYPE to +dummy in /etc/selinux/config, install the compiled policy +as 'dummy', and relabel your filesystem. diff --git a/Documentation/block/deadline-iosched.txt b/Documentation/block/deadline-iosched.txt index c23cab13c3d1..72576769e0f4 100644 --- a/Documentation/block/deadline-iosched.txt +++ b/Documentation/block/deadline-iosched.txt @@ -30,12 +30,18 @@ write_expire (in ms) Similar to read_expire mentioned above, but for writes. -fifo_batch +fifo_batch (number of requests) ---------- -When a read request expires its deadline, we must move some requests from -the sorted io scheduler list to the block device dispatch queue. fifo_batch -controls how many requests we move. +Requests are grouped into ``batches'' of a particular data direction (read or +write) which are serviced in increasing sector order. To limit extra seeking, +deadline expiries are only checked between batches. fifo_batch controls the +maximum number of requests per batch. + +This parameter tunes the balance between per-request latency and aggregate +throughput. When low latency is the primary concern, smaller is better (where +a value of 1 yields first-come first-served behaviour). Increasing fifo_batch +generally improves throughput, at the cost of latency variation. writes_starved (number of dispatches) diff --git a/Documentation/cdrom/ide-cd b/Documentation/cdrom/ide-cd index 91c0dcc6fa5c..2c558cd6c1ef 100644 --- a/Documentation/cdrom/ide-cd +++ b/Documentation/cdrom/ide-cd @@ -145,8 +145,7 @@ useful for reading photocds. To play an audio CD, you should first unmount and remove any data CDROM. Any of the CDROM player programs should then work (workman, -workbone, cdplayer, etc.). Lacking anything else, you could use the -cdtester program in Documentation/cdrom/sbpcd. +workbone, cdplayer, etc.). On a few drives, you can read digital audio directly using a program such as cdda2wav. The only types of drive which I've heard support diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index 0bd32748a467..c6841eee9598 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt @@ -168,10 +168,10 @@ if ($#ARGV < 0) { mkdir $ARGV[0],0777; $state = 0; while (<STDIN>) { - if (/^\.TH \"[^\"]*\" 4 \"([^\"]*)\"/) { + if (/^\.TH \"[^\"]*\" 9 \"([^\"]*)\"/) { if ($state == 1) { close OUT } $state = 1; - $fn = "$ARGV[0]/$1.4"; + $fn = "$ARGV[0]/$1.9"; print STDERR "Creating $fn\n"; open OUT, ">$fn" or die "can't open $fn: $!\n"; print OUT $_; diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1150444a21ab..329dcabe4c5e 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -463,12 +463,6 @@ and is between 256 and 4096 characters. It is defined in the file Range: 0 - 8192 Default: 64 - disable_8254_timer - enable_8254_timer - [IA32/X86_64] Disable/Enable interrupt 0 timer routing - over the 8254 in addition to over the IO-APIC. The - kernel tries to set a sensible default. - hpet= [X86-32,HPET] option to control HPET usage Format: { enable (default) | disable | force } disable: disable HPET and use PIT instead @@ -1882,6 +1876,12 @@ and is between 256 and 4096 characters. It is defined in the file shapers= [NET] Maximal number of shapers. + show_msr= [x86] show boot-time MSR settings + Format: { <integer> } + Show boot-time (BIOS-initialized) MSR settings. + The parameter means the number of CPUs to show, + for example 1 means boot CPU only. + sim710= [SCSI,HW] See header of drivers/scsi/sim710.c. diff --git a/Documentation/scheduler/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt index 88bcb8767335..9d8eb553884c 100644 --- a/Documentation/scheduler/sched-design-CFS.txt +++ b/Documentation/scheduler/sched-design-CFS.txt @@ -1,151 +1,242 @@ + ============= + CFS Scheduler + ============= -This is the CFS scheduler. - -80% of CFS's design can be summed up in a single sentence: CFS basically -models an "ideal, precise multi-tasking CPU" on real hardware. - -"Ideal multi-tasking CPU" is a (non-existent :-)) CPU that has 100% -physical power and which can run each task at precise equal speed, in -parallel, each at 1/nr_running speed. For example: if there are 2 tasks -running then it runs each at 50% physical power - totally in parallel. - -On real hardware, we can run only a single task at once, so while that -one task runs, the other tasks that are waiting for the CPU are at a -disadvantage - the current task gets an unfair amount of CPU time. In -CFS this fairness imbalance is expressed and tracked via the per-task -p->wait_runtime (nanosec-unit) value. "wait_runtime" is the amount of -time the task should now run on the CPU for it to become completely fair -and balanced. - -( small detail: on 'ideal' hardware, the p->wait_runtime value would - always be zero - no task would ever get 'out of balance' from the - 'ideal' share of CPU time. ) - -CFS's task picking logic is based on this p->wait_runtime value and it -is thus very simple: it always tries to run the task with the largest -p->wait_runtime value. In other words, CFS tries to run the task with -the 'gravest need' for more CPU time. So CFS always tries to split up -CPU time between runnable tasks as close to 'ideal multitasking -hardware' as possible. - -Most of the rest of CFS's design just falls out of this really simple -concept, with a few add-on embellishments like nice levels, -multiprocessing and various algorithm variants to recognize sleepers. - -In practice it works like this: the system runs a task a bit, and when -the task schedules (or a scheduler tick happens) the task's CPU usage is -'accounted for': the (small) time it just spent using the physical CPU -is deducted from p->wait_runtime. [minus the 'fair share' it would have -gotten anyway]. Once p->wait_runtime gets low enough so that another -task becomes the 'leftmost task' of the time-ordered rbtree it maintains -(plus a small amount of 'granularity' distance relative to the leftmost -task so that we do not over-schedule tasks and trash the cache) then the -new leftmost task is picked and the current task is preempted. - -The rq->fair_clock value tracks the 'CPU time a runnable task would have -fairly gotten, had it been runnable during that time'. So by using -rq->fair_clock values we can accurately timestamp and measure the -'expected CPU time' a task should have gotten. All runnable tasks are -sorted in the rbtree by the "rq->fair_clock - p->wait_runtime" key, and -CFS picks the 'leftmost' task and sticks to it. As the system progresses -forwards, newly woken tasks are put into the tree more and more to the -right - slowly but surely giving a chance for every task to become the -'leftmost task' and thus get on the CPU within a deterministic amount of -time. - -Some implementation details: - - - the introduction of Scheduling Classes: an extensible hierarchy of - scheduler modules. These modules encapsulate scheduling policy - details and are handled by the scheduler core without the core - code assuming about them too much. - - - sched_fair.c implements the 'CFS desktop scheduler': it is a - replacement for the vanilla scheduler's SCHED_OTHER interactivity - code. - - I'd like to give credit to Con Kolivas for the general approach here: - he has proven via RSDL/SD that 'fair scheduling' is possible and that - it results in better desktop scheduling. Kudos Con! - - The CFS patch uses a completely different approach and implementation - from RSDL/SD. My goal was to make CFS's interactivity quality exceed - that of RSDL/SD, which is a high standard to meet :-) Testing - feedback is welcome to decide this one way or another. [ and, in any - case, all of SD's logic could be added via a kernel/sched_sd.c module - as well, if Con is interested in such an approach. ] - - CFS's design is quite radical: it does not use runqueues, it uses a - time-ordered rbtree to build a 'timeline' of future task execution, - and thus has no 'array switch' artifacts (by which both the vanilla - scheduler and RSDL/SD are affected). - - CFS uses nanosecond granularity accounting and does not rely on any - jiffies or other HZ detail. Thus the CFS scheduler has no notion of - 'timeslices' and has no heuristics whatsoever. There is only one - central tunable (you have to switch on CONFIG_SCHED_DEBUG): - - /proc/sys/kernel/sched_granularity_ns - - which can be used to tune the scheduler from 'desktop' (low - latencies) to 'server' (good batching) workloads. It defaults to a - setting suitable for desktop workloads. SCHED_BATCH is handled by the - CFS scheduler module too. - - Due to its design, the CFS scheduler is not prone to any of the - 'attacks' that exist today against the heuristics of the stock - scheduler: fiftyp.c, thud.c, chew.c, ring-test.c, massive_intr.c all - work fine and do not impact interactivity and produce the expected - behavior. - - the CFS scheduler has a much stronger handling of nice levels and - SCHED_BATCH: both types of workloads should be isolated much more - agressively than under the vanilla scheduler. - - ( another detail: due to nanosec accounting and timeline sorting, - sched_yield() support is very simple under CFS, and in fact under - CFS sched_yield() behaves much better than under any other - scheduler i have tested so far. ) - - - sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler - way than the vanilla scheduler does. It uses 100 runqueues (for all - 100 RT priority levels, instead of 140 in the vanilla scheduler) - and it needs no expired array. - - - reworked/sanitized SMP load-balancing: the runqueue-walking - assumptions are gone from the load-balancing code now, and - iterators of the scheduling modules are used. The balancing code got - quite a bit simpler as a result. - - -Group scheduler extension to CFS -================================ - -Normally the scheduler operates on individual tasks and strives to provide -fair CPU time to each task. Sometimes, it may be desirable to group tasks -and provide fair CPU time to each such task group. For example, it may -be desirable to first provide fair CPU time to each user on the system -and then to each task belonging to a user. - -CONFIG_FAIR_GROUP_SCHED strives to achieve exactly that. It lets -SCHED_NORMAL/BATCH tasks be be grouped and divides CPU time fairly among such -groups. At present, there are two (mutually exclusive) mechanisms to group -tasks for CPU bandwidth control purpose: - - - Based on user id (CONFIG_FAIR_USER_SCHED) - In this option, tasks are grouped according to their user id. - - Based on "cgroup" pseudo filesystem (CONFIG_FAIR_CGROUP_SCHED) - This options lets the administrator create arbitrary groups - of tasks, using the "cgroup" pseudo filesystem. See - Documentation/cgroups.txt for more information about this - filesystem. -Only one of these options to group tasks can be chosen and not both. +1. OVERVIEW + +CFS stands for "Completely Fair Scheduler," and is the new "desktop" process +scheduler implemented by Ingo Molnar and merged in Linux 2.6.23. It is the +replacement for the previous vanilla scheduler's SCHED_OTHER interactivity +code. + +80% of CFS's design can be summed up in a single sentence: CFS basically models +an "ideal, precise multi-tasking CPU" on real hardware. + +"Ideal multi-tasking CPU" is a (non-existent :-)) CPU that has 100% physical +power and which can run each task at precise equal speed, in parallel, each at +1/nr_running speed. For example: if there are 2 tasks running, then it runs +each at 50% physical power --- i.e., actually in parallel. + +On real hardware, we can run only a single task at once, so we have to +introduce the concept of "virtual runtime." The virtual runtime of a task +specifies when its next timeslice would start execution on the ideal +multi-tasking CPU described above. In practice, the virtual runtime of a task +is its actual runtime normalized to the total number of running tasks. + + + +2. FEW IMPLEMENTATION DETAILS + +In CFS the virtual runtime is expressed and tracked via the per-task +p->se.vruntime (nanosec-unit) value. This way, it's possible to accurately +timestamp and measure the "expected CPU time" a task should have gotten. + +[ small detail: on "ideal" hardware, at any time all tasks would have the same + p->se.vruntime value --- i.e., tasks would execute simultaneously and no task + would ever get "out of balance" from the "ideal" share of CPU time. ] + +CFS's task picking logic is based on this p->se.vruntime value and it is thus +very simple: it always tries to run the task with the smallest p->se.vruntime +value (i.e., the task which executed least so far). CFS always tries to split +up CPU time between runnable tasks as close to "ideal multitasking hardware" as +possible. + +Most of the rest of CFS's design just falls out of this really simple concept, +with a few add-on embellishments like nice levels, multiprocessing and various +algorithm variants to recognize sleepers. + + + +3. THE RBTREE + +CFS's design is quite radical: it does not use the old data structures for the +runqueues, but it uses a time-ordered rbtree to build a "timeline" of future +task execution, and thus has no "array switch" artifacts (by which both the +previous vanilla scheduler and RSDL/SD are affected). + +CFS also maintains the rq->cfs.min_vruntime value, which is a monotonic +increasing value tracking the smallest vruntime among all tasks in the +runqueue. The total amount of work done by the system is tracked using +min_vruntime; that value is used to place newly activated entities on the left +side of the tree as much as possible. + +The total number of running tasks in the runqueue is accounted through the +rq->cfs.load value, which is the sum of the weights of the tasks queued on the +runqueue. + +CFS maintains a time-ordered rbtree, where all runnable tasks are sorted by the +p->se.vruntime key (there is a subtraction using rq->cfs.min_vruntime to +account for possible wraparounds). CFS picks the "leftmost" task from this +tree and sticks to it. +As the system progresses forwards, the executed tasks are put into the tree +more and more to the right --- slowly but surely giving a chance for every task +to become the "leftmost task" and thus get on the CPU within a deterministic +amount of time. + +Summing up, CFS works like this: it runs a task a bit, and when the task +schedules (or a scheduler tick happens) the task's CPU usage is "accounted +for": the (small) time it just spent using the physical CPU is added to +p->se.vruntime. Once p->se.vruntime gets high enough so that another task +becomes the "leftmost task" of the time-ordered rbtree it maintains (plus a +small amount of "granularity" distance relative to the leftmost task so that we +do not over-schedule tasks and trash the cache), then the new leftmost task is +picked and the current task is preempted. + + + +4. SOME FEATURES OF CFS + +CFS uses nanosecond granularity accounting and does not rely on any jiffies or +other HZ detail. Thus the CFS scheduler has no notion of "timeslices" in the +way the previous scheduler had, and has no heuristics whatsoever. There is +only one central tunable (you have to switch on CONFIG_SCHED_DEBUG): + + /proc/sys/kernel/sched_granularity_ns + +which can be used to tune the scheduler from "desktop" (i.e., low latencies) to +"server" (i.e., good batching) workloads. It defaults to a setting suitable +for desktop workloads. SCHED_BATCH is handled by the CFS scheduler module too. + +Due to its design, the CFS scheduler is not prone to any of the "attacks" that +exist today against the heuristics of the stock scheduler: fiftyp.c, thud.c, +chew.c, ring-test.c, massive_intr.c all work fine and do not impact +interactivity and produce the expected behavior. + +The CFS scheduler has a much stronger handling of nice levels and SCHED_BATCH +than the previous vanilla scheduler: both types of workloads are isolated much +more aggressively. + +SMP load-balancing has been reworked/sanitized: the runqueue-walking +assumptions are gone from the load-balancing code now, and iterators of the +scheduling modules are used. The balancing code got quite a bit simpler as a +result. + + + +5. Scheduling policies + +CFS implements three scheduling policies: + + - SCHED_NORMAL (traditionally called SCHED_OTHER): The scheduling + policy that is used for regular tasks. + + - SCHED_BATCH: Does not preempt nearly as often as regular tasks + would, thereby allowing tasks to run longer and make better use of + caches but at the cost of interactivity. This is well suited for + batch jobs. + + - SCHED_IDLE: This is even weaker than nice 19, but its not a true + idle timer scheduler in order to avoid to get into priority + inversion problems which would deadlock the machine. + +SCHED_FIFO/_RR are implemented in sched_rt.c and are as specified by +POSIX. + +The command chrt from util-linux-ng 2.13.1.1 can set all of these except +SCHED_IDLE. -Group scheduler tunables: -When CONFIG_FAIR_USER_SCHED is defined, a directory is created in sysfs for -each new user and a "cpu_share" file is added in that directory. + +6. SCHEDULING CLASSES + +The new CFS scheduler has been designed in such a way to introduce "Scheduling +Classes," an extensible hierarchy of scheduler modules. These modules +encapsulate scheduling policy details and are handled by the scheduler core +without the core code assuming too much about them. + +sched_fair.c implements the CFS scheduler described above. + +sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler way than +the previous vanilla scheduler did. It uses 100 runqueues (for all 100 RT +priority levels, instead of 140 in the previous scheduler) and it needs no +expired array. + +Scheduling classes are implemented through the sched_class structure, which +contains hooks to functions that must be called whenever an interesting event +occurs. + +This is the (partial) list of the hooks: + + - enqueue_task(...) + + Called when a task enters a runnable state. + It puts the scheduling entity (task) into the red-black tree and + increments the nr_running variable. + + - dequeue_tree(...) + + When a task is no longer runnable, this function is called to keep the + corresponding scheduling entity out of the red-black tree. It decrements + the nr_running variable. + + - yield_task(...) + + This function is basically just a dequeue followed by an enqueue, unless the + compat_yield sysctl is turned on; in that case, it places the scheduling + entity at the right-most end of the red-black tree. + + - check_preempt_curr(...) + + This function checks if a task that entered the runnable state should + preempt the currently running task. + + - pick_next_task(...) + + This function chooses the most appropriate task eligible to run next. + + - set_curr_task(...) + + This function is called when a task changes its scheduling class or changes + its task group. + + - task_tick(...) + + This function is mostly called from time tick functions; it might lead to + process switch. This drives the running preemption. + + - task_new(...) + + The core scheduler gives the scheduling module an opportunity to manage new + task startup. The CFS scheduling module uses it for group scheduling, while + the scheduling module for a real-time task does not use it. + + + +7. GROUP SCHEDULER EXTENSIONS TO CFS + +Normally, the scheduler operates on individual tasks and strives to provide +fair CPU time to each task. Sometimes, it may be desirable to group tasks and +provide fair CPU time to each such task group. For example, it may be +desirable to first provide fair CPU time to each user on the system and then to +each task belonging to a user. + +CONFIG_GROUP_SCHED strives to achieve exactly that. It lets tasks to be +grouped and divides CPU time fairly among such groups. + +CONFIG_RT_GROUP_SCHED permits to group real-time (i.e., SCHED_FIFO and +SCHED_RR) tasks. + +CONFIG_FAIR_GROUP_SCHED permits to group CFS (i.e., SCHED_NORMAL and +SCHED_BATCH) tasks. + +At present, there are two (mutually exclusive) mechanisms to group tasks for +CPU bandwidth control purposes: + + - Based on user id (CONFIG_USER_SCHED) + + With this option, tasks are grouped according to their user id. + + - Based on "cgroup" pseudo filesystem (CONFIG_CGROUP_SCHED) + + This options needs CONFIG_CGROUPS to be defined, and lets the administrator + create arbitrary groups of tasks, using the "cgroup" pseudo filesystem. See + Documentation/cgroups.txt for more information about this filesystem. + +Only one of these options to group tasks can be chosen and not both. + +When CONFIG_USER_SCHED is defined, a directory is created in sysfs for each new +user and a "cpu_share" file is added in that directory. # cd /sys/kernel/uids # cat 512/cpu_share # Display user 512's CPU share @@ -155,16 +246,14 @@ each new user and a "cpu_share" file is added in that directory. 2048 # -CPU bandwidth between two users are divided in the ratio of their CPU shares. -For ex: if you would like user "root" to get twice the bandwidth of user -"guest", then set the cpu_share for both the users such that "root"'s -cpu_share is twice "guest"'s cpu_share - +CPU bandwidth between two users is divided in the ratio of their CPU shares. +For example: if you would like user "root" to get twice the bandwidth of user +"guest," then set the cpu_share for both the users such that "root"'s cpu_share +is twice "guest"'s cpu_share. -When CONFIG_FAIR_CGROUP_SCHED is defined, a "cpu.shares" file is created -for each group created using the pseudo filesystem. See example steps -below to create task groups and modify their CPU share using the "cgroups" -pseudo filesystem +When CONFIG_CGROUP_SCHED is defined, a "cpu.shares" file is created for each +group created using the pseudo filesystem. See example steps below to create +task groups and modify their CPU share using the "cgroups" pseudo filesystem. # mkdir /dev/cpuctl # mount -t cgroup -ocpu none /dev/cpuctl diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt index 75143f0c23b6..38d324d62b25 100644 --- a/Documentation/scsi/scsi_fc_transport.txt +++ b/Documentation/scsi/scsi_fc_transport.txt @@ -436,6 +436,42 @@ Other: was updated to remove all vports for the fc_host as well. +Transport supplied functions +---------------------------- + +The following functions are supplied by the FC-transport for use by LLDs. + + fc_vport_create - create a vport + fc_vport_terminate - detach and remove a vport + +Details: + +/** + * fc_vport_create - Admin App or LLDD requests creation of a vport + * @shost: scsi host the virtual port is connected to. + * @ids: The world wide names, FC4 port roles, etc for + * the virtual port. + * + * Notes: + * This routine assumes no locks are held on entry. + */ +struct fc_vport * +fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids) + +/** + * fc_vport_terminate - Admin App or LLDD requests termination of a vport + * @vport: fc_vport to be terminated + * + * Calls the LLDD vport_delete() function, then deallocates and removes + * the vport from the shost and object tree. + * + * Notes: + * This routine assumes no locks are held on entry. + */ +int +fc_vport_terminate(struct fc_vport *vport) + + Credits ======= The following people have contributed to this document: diff --git a/Documentation/x86/00-INDEX b/Documentation/x86/00-INDEX new file mode 100644 index 000000000000..dbe3377754af --- /dev/null +++ b/Documentation/x86/00-INDEX @@ -0,0 +1,4 @@ +00-INDEX + - this file +mtrr.txt + - how to use x86 Memory Type Range Registers to increase performance diff --git a/Documentation/x86/i386/boot.txt b/Documentation/x86/boot.txt index 147bfe511cdd..83c0033ee9e0 100644 --- a/Documentation/x86/i386/boot.txt +++ b/Documentation/x86/boot.txt @@ -308,7 +308,7 @@ Protocol: 2.00+ Field name: start_sys Type: read -Offset/size: 0x20c/4 +Offset/size: 0x20c/2 Protocol: 2.00+ The load low segment (0x1000). Obsolete. diff --git a/Documentation/mtrr.txt b/Documentation/x86/mtrr.txt index c39ac395970e..cc071dc333c2 100644 --- a/Documentation/mtrr.txt +++ b/Documentation/x86/mtrr.txt @@ -18,7 +18,7 @@ Richard Gooch The AMD K6-2 (stepping 8 and above) and K6-3 processors have two MTRRs. These are supported. The AMD Athlon family provide 8 Intel style MTRRs. - + The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These are supported. @@ -87,7 +87,7 @@ reg00: base=0x00000000 ( 0MB), size= 64MB: write-back, count=1 reg01: base=0xfb000000 (4016MB), size= 16MB: write-combining, count=1 reg02: base=0xfb000000 (4016MB), size= 4kB: uncachable, count=1 -Some cards (especially Voodoo Graphics boards) need this 4 kB area +Some cards (especially Voodoo Graphics boards) need this 4 kB area excluded from the beginning of the region because it is used for registers. diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt index 17965f927c15..c93ff5f4c0dd 100644 --- a/Documentation/x86/pat.txt +++ b/Documentation/x86/pat.txt @@ -14,6 +14,10 @@ PAT allows for different types of memory attributes. The most commonly used ones that will be supported at this time are Write-back, Uncached, Write-combined and Uncached Minus. + +PAT APIs +-------- + There are many different APIs in the kernel that allows setting of memory attributes at the page level. In order to avoid aliasing, these interfaces should be used thoughtfully. Below is a table of interfaces available, @@ -26,38 +30,38 @@ address range to avoid any aliasing. API | RAM | ACPI,... | Reserved/Holes | -----------------------|----------|------------|------------------| | | | | -ioremap | -- | UC | UC | +ioremap | -- | UC- | UC- | | | | | ioremap_cache | -- | WB | WB | | | | | -ioremap_nocache | -- | UC | UC | +ioremap_nocache | -- | UC- | UC- | | | | | ioremap_wc | -- | -- | WC | | | | | -set_memory_uc | UC | -- | -- | +set_memory_uc | UC- | -- | -- | set_memory_wb | | | | | | | | set_memory_wc | WC | -- | -- | set_memory_wb | | | | | | | | -pci sysfs resource | -- | -- | UC | +pci sysfs resource | -- | -- | UC- | | | | | pci sysfs resource_wc | -- | -- | WC | is IORESOURCE_PREFETCH| | | | | | | | -pci proc | -- | -- | UC | +pci proc | -- | -- | UC- | !PCIIOC_WRITE_COMBINE | | | | | | | | pci proc | -- | -- | WC | PCIIOC_WRITE_COMBINE | | | | | | | | -/dev/mem | -- | UC | UC | +/dev/mem | -- | WB/WC/UC- | WB/WC/UC- | read-write | | | | | | | | -/dev/mem | -- | UC | UC | +/dev/mem | -- | UC- | UC- | mmap SYNC flag | | | | | | | | -/dev/mem | -- | WB/WC/UC | WB/WC/UC | +/dev/mem | -- | WB/WC/UC- | WB/WC/UC- | mmap !SYNC flag | |(from exist-| (from exist- | and | | ing alias)| ing alias) | any alias to this area| | | | @@ -68,7 +72,7 @@ pci proc | -- | -- | WC | and | | | | MTRR says WB | | | | | | | | -/dev/mem | -- | -- | UC_MINUS | +/dev/mem | -- | -- | UC- | mmap !SYNC flag | | | | no alias to this area | | | | and | | | | @@ -98,3 +102,35 @@ types. Drivers should use set_memory_[uc|wc] to set access type for RAM ranges. + +PAT debugging +------------- + +With CONFIG_DEBUG_FS enabled, PAT memtype list can be examined by + +# mount -t debugfs debugfs /sys/kernel/debug +# cat /sys/kernel/debug/x86/pat_memtype_list +PAT memtype list: +uncached-minus @ 0x7fadf000-0x7fae0000 +uncached-minus @ 0x7fb19000-0x7fb1a000 +uncached-minus @ 0x7fb1a000-0x7fb1b000 +uncached-minus @ 0x7fb1b000-0x7fb1c000 +uncached-minus @ 0x7fb1c000-0x7fb1d000 +uncached-minus @ 0x7fb1d000-0x7fb1e000 +uncached-minus @ 0x7fb1e000-0x7fb25000 +uncached-minus @ 0x7fb25000-0x7fb26000 +uncached-minus @ 0x7fb26000-0x7fb27000 +uncached-minus @ 0x7fb27000-0x7fb28000 +uncached-minus @ 0x7fb28000-0x7fb2e000 +uncached-minus @ 0x7fb2e000-0x7fb2f000 +uncached-minus @ 0x7fb2f000-0x7fb30000 +uncached-minus @ 0x7fb31000-0x7fb32000 +uncached-minus @ 0x80000000-0x90000000 + +This list shows physical address ranges and various PAT settings used to +access those physical address ranges. + +Another, more verbose way of getting PAT related debug messages is with +"debugpat" boot parameter. With this parameter, various debug messages are +printed to dmesg log. + diff --git a/Documentation/x86/i386/usb-legacy-support.txt b/Documentation/x86/usb-legacy-support.txt index 1894cdfc69d9..1894cdfc69d9 100644 --- a/Documentation/x86/i386/usb-legacy-support.txt +++ b/Documentation/x86/usb-legacy-support.txt diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt index b0c7b6c4abda..72ffb5373ec7 100644 --- a/Documentation/x86/x86_64/boot-options.txt +++ b/Documentation/x86/x86_64/boot-options.txt @@ -54,10 +54,6 @@ APICs apicmaintimer. Useful when your PIT timer is totally broken. - disable_8254_timer / enable_8254_timer - Enable interrupt 0 timer routing over the 8254 in addition to over - the IO-APIC. The kernel tries to set a sensible default. - Early Console syntax: earlyprintk=vga diff --git a/Documentation/x86/i386/zero-page.txt b/Documentation/x86/zero-page.txt index 169ad423a3d1..169ad423a3d1 100644 --- a/Documentation/x86/i386/zero-page.txt +++ b/Documentation/x86/zero-page.txt diff --git a/MAINTAINERS b/MAINTAINERS index 8dae4555f10e..7a03bd5a91a3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3649,8 +3649,9 @@ M: jmorris@namei.org P: Eric Paris M: eparis@parisplace.org L: linux-kernel@vger.kernel.org (kernel issues) -L: selinux@tycho.nsa.gov (subscribers-only, general discussion) -W: http://www.nsa.gov/selinux +L: selinux@tycho.nsa.gov (subscribers-only, general discussion) +W: http://selinuxproject.org +T: git kernel.org:pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git S: Supported SENSABLE PHANTOM diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 83df541650fc..06b6fdab639f 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -149,6 +149,9 @@ smp_callin(void) atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; + /* inform the notifiers about the new cpu */ + notify_cpu_starting(cpuid); + /* Must have completely accurate bogos. */ local_irq_enable(); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e9842f6767f9..e42a749a56dd 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -277,6 +277,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) /* * Enable local interrupts. */ + notify_cpu_starting(cpu); local_irq_enable(); local_fiq_enable(); diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 952a24b2f5a9..52e16c6436f9 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -178,6 +178,7 @@ void __init smp_callin(void) unmask_irq(IPI_INTR_VECT); unmask_irq(TIMER0_INTR_VECT); preempt_disable(); + notify_cpu_starting(cpu); local_irq_enable(); cpu_set(cpu, cpu_online_map); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index d8f05e504fbf..1dcbb85fc4ee 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -401,6 +401,7 @@ smp_callin (void) spin_lock(&vector_lock); /* Setup the per cpu irq handling data structures */ __setup_vector_irq(cpuid); + notify_cpu_starting(cpuid); cpu_set(cpuid, cpu_online_map); per_cpu(cpu_state, cpuid) = CPU_ONLINE; spin_unlock(&vector_lock); diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index 2c03ac1d005f..fc2994811f15 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -498,6 +498,8 @@ static void __init smp_online(void) { int cpu_id = smp_processor_id(); + notify_cpu_starting(cpu_id); + local_irq_enable(); /* Get our bogomips. */ diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 4410f172b8ab..7b59cfb7e602 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -121,6 +121,8 @@ asmlinkage __cpuinit void start_secondary(void) cpu = smp_processor_id(); cpu_data[cpu].udelay_val = loops_per_jiffy; + notify_cpu_starting(cpu); + mp_ops->smp_finish(); set_cpu_sibling_map(cpu); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 5337ca7bb649..c27b10a1bd79 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -453,6 +453,7 @@ int __devinit start_secondary(void *unused) secondary_cpu_time_init(); ipi_call_lock(); + notify_cpu_starting(cpu); cpu_set(cpu, cpu_online_map); /* Update sibling maps */ base = cpu_first_thread_in_core(cpu); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 00b9b4dec5eb..9e8b1f9b8f4d 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -585,6 +585,8 @@ int __cpuinit start_secondary(void *cpuvoid) /* Enable pfault pseudo page faults on this cpu. */ pfault_init(); + /* call cpu notifiers */ + notify_cpu_starting(smp_processor_id()); /* Mark this cpu as online */ spin_lock(&call_lock); cpu_set(smp_processor_id(), cpu_online_map); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 60c50841143e..001778f9adaf 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -82,6 +82,8 @@ asmlinkage void __cpuinit start_secondary(void) preempt_disable(); + notify_cpu_starting(smp_processor_id()); + local_irq_enable(); calibrate_delay(); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 69596402a500..446767e8f569 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -88,6 +88,7 @@ void __init smp4d_callin(void) local_flush_cache_all(); local_flush_tlb_all(); + notify_cpu_starting(cpuid); /* * Unblock the master CPU _only_ when the scheduler state * of all secondary CPUs will be up-to-date, so after diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index a14a76ac7f36..9964890dc1db 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -71,6 +71,8 @@ void __cpuinit smp4m_callin(void) local_flush_cache_all(); local_flush_tlb_all(); + notify_cpu_starting(cpuid); + /* Get our local ticker going. */ smp_setup_percpu_timer(); diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index be2d50c3aa95..045772142844 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -85,6 +85,7 @@ static int idle_proc(void *cpup) while (!cpu_isset(cpu, smp_commenced_mask)) cpu_relax(); + notify_cpu_starting(cpu); cpu_set(cpu, cpu_online_map); default_idle(); return 0; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ed92864d1325..97f0d2b6dc0c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -29,6 +29,7 @@ config X86 select HAVE_FTRACE select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_ARCH_KGDB if !X86_VOYAGER + select HAVE_ARCH_TRACEHOOK select HAVE_GENERIC_DMA_COHERENT if X86_32 select HAVE_EFFICIENT_UNALIGNED_ACCESS @@ -1020,7 +1021,7 @@ config HAVE_ARCH_ALLOC_REMAP config ARCH_FLATMEM_ENABLE def_bool y - depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC && !NUMA + depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && !NUMA config ARCH_DISCONTIGMEM_ENABLE def_bool y @@ -1036,7 +1037,7 @@ config ARCH_SPARSEMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) + depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC) || X86_GENERICARCH select SPARSEMEM_STATIC if X86_32 select SPARSEMEM_VMEMMAP_ENABLE if X86_64 @@ -1117,10 +1118,10 @@ config MTRR You can safely say Y even if your machine doesn't have MTRRs, you'll just add about 9 KB to your kernel. - See <file:Documentation/mtrr.txt> for more information. + See <file:Documentation/x86/mtrr.txt> for more information. config MTRR_SANITIZER - bool + def_bool y prompt "MTRR cleanup support" depends on MTRR help @@ -1131,7 +1132,7 @@ config MTRR_SANITIZER The largest mtrr entry size for a continous block can be set with mtrr_chunk_size. - If unsure, say N. + If unsure, say Y. config MTRR_SANITIZER_ENABLE_DEFAULT int "MTRR cleanup enable value (0-1)" @@ -1191,7 +1192,6 @@ config IRQBALANCE config SECCOMP def_bool y prompt "Enable seccomp to safely compute untrusted bytecode" - depends on PROC_FS help This kernel feature is useful for number crunching applications that may need to compute untrusted bytecode during their @@ -1199,7 +1199,7 @@ config SECCOMP the process as file descriptors supporting the read/write syscalls, it's possible to isolate those applications in their own address space using seccomp. Once seccomp is - enabled via /proc/<pid>/seccomp, it cannot be disabled + enabled via prctl(PR_SET_SECCOMP), it cannot be disabled and the task is only allowed to execute a few safe syscalls defined by each seccomp mode. @@ -1356,14 +1356,14 @@ config PHYSICAL_ALIGN Don't change this unless you know what you are doing. config HOTPLUG_CPU - bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER + bool "Support for hot-pluggable CPUs" + depends on SMP && HOTPLUG && !X86_VOYAGER ---help--- - Say Y here to experiment with turning CPUs off and on, and to - enable suspend on SMP systems. CPUs can be controlled through - /sys/devices/system/cpu. - Say N if you want to disable CPU hotplug and don't need to - suspend. + Say Y here to allow turning CPUs off and on. CPUs can be + controlled through /sys/devices/system/cpu. + ( Note: power management support will enable this option + automatically on SMP systems. ) + Say N if you want to disable CPU hotplug. config COMPAT_VDSO def_bool y @@ -1378,6 +1378,51 @@ config COMPAT_VDSO If unsure, say Y. +config CMDLINE_BOOL + bool "Built-in kernel command line" + default n + help + Allow for specifying boot arguments to the kernel at + build time. On some systems (e.g. embedded ones), it is + necessary or convenient to provide some or all of the + kernel boot arguments with the kernel itself (that is, + to not rely on the boot loader to provide them.) + + To compile command line arguments into the kernel, + set this option to 'Y', then fill in the + the boot arguments in CONFIG_CMDLINE. + + Systems with fully functional boot loaders (i.e. non-embedded) + should leave this option set to 'N'. + +config CMDLINE + string "Built-in kernel command string" + depends on CMDLINE_BOOL + default "" + help + Enter arguments here that should be compiled into the kernel + image and used at boot time. If the boot loader provides a + command line at boot time, it is appended to this string to + form the full kernel command line, when the system boots. + + However, you can use the CONFIG_CMDLINE_OVERRIDE option to + change this behavior. + + In most cases, the command line (whether built-in or provided + by the boot loader) should specify the device for the root + file system. + +config CMDLINE_OVERRIDE + bool "Built-in command line overrides boot loader arguments" + default n + depends on CMDLINE_BOOL + help + Set this option to 'Y' to have the kernel ignore the boot loader + command line, and use ONLY the built-in command line. + + This is used to work around broken boot loaders. This should + be set to 'N' under normal conditions. + endmenu config ARCH_ENABLE_MEMORY_HOTPLUG @@ -1773,7 +1818,7 @@ config COMPAT_FOR_U64_ALIGNMENT config SYSVIPC_COMPAT def_bool y - depends on X86_64 && COMPAT && SYSVIPC + depends on COMPAT && SYSVIPC endmenu diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index b225219c448c..60a85768cfcb 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -418,3 +418,21 @@ config X86_MINIMUM_CPU_FAMILY config X86_DEBUGCTLMSR def_bool y depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) + +config X86_DS + bool "Debug Store support" + default y + help + Add support for Debug Store. + This allows the kernel to provide a memory buffer to the hardware + to store various profiling and tracing events. + +config X86_PTRACE_BTS + bool "ptrace interface to Branch Trace Store" + default y + depends on (X86_DS && X86_DEBUGCTLMSR) + help + Add a ptrace interface to allow collecting an execution trace + of the traced task. + This collects control flow changes in a (cyclic) buffer and allows + debuggers to fill in the gaps and show an execution trace of the debuggee. diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index ba7736cf2ec7..29c5fbf08392 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -137,14 +137,15 @@ relocated: */ movl output_len(%ebx), %eax pushl %eax + # push arguments for decompress_kernel: pushl %ebp # output address movl input_len(%ebx), %eax pushl %eax # input_len leal input_data(%ebx), %eax pushl %eax # input_data leal boot_heap(%ebx), %eax - pushl %eax # heap area as third argument - pushl %esi # real mode pointer as second arg + pushl %eax # heap area + pushl %esi # real mode pointer call decompress_kernel addl $20, %esp popl %ecx diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 9fea73706479..5780d361105b 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -16,7 +16,7 @@ */ #undef CONFIG_PARAVIRT #ifdef CONFIG_X86_32 -#define _ASM_DESC_H_ 1 +#define ASM_X86__DESC_H 1 #endif #ifdef CONFIG_X86_64 @@ -27,7 +27,7 @@ #include <linux/linkage.h> #include <linux/screen_info.h> #include <linux/elf.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/page.h> #include <asm/boot.h> #include <asm/bootparam.h> @@ -251,7 +251,7 @@ static void __putstr(int error, const char *s) y--; } } else { - vidmem [(x + cols * y) * 2] = c; + vidmem[(x + cols * y) * 2] = c; if (++x >= cols) { x = 0; if (++y >= lines) { @@ -277,7 +277,8 @@ static void *memset(void *s, int c, unsigned n) int i; char *ss = s; - for (i = 0; i < n; i++) ss[i] = c; + for (i = 0; i < n; i++) + ss[i] = c; return s; } @@ -287,7 +288,8 @@ static void *memcpy(void *dest, const void *src, unsigned n) const char *s = src; char *d = dest; - for (i = 0; i < n; i++) d[i] = s[i]; + for (i = 0; i < n; i++) + d[i] = s[i]; return dest; } diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index af86e431acfa..b993062e9a5f 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -30,7 +30,6 @@ SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ /* to be loaded */ ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ -SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ #ifndef SVGA_MODE #define SVGA_MODE ASK_VGA diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 104275e191a8..ef9a52005ec9 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc4 -# Mon Aug 25 15:04:00 2008 +# Linux kernel version: 2.6.27-rc5 +# Wed Sep 3 17:23:09 2008 # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -202,7 +202,7 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # CONFIG_M586 is not set # CONFIG_M586TSC is not set # CONFIG_M586MMX is not set -# CONFIG_M686 is not set +CONFIG_M686=y # CONFIG_MPENTIUMII is not set # CONFIG_MPENTIUMIII is not set # CONFIG_MPENTIUMM is not set @@ -221,13 +221,14 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC7 is not set # CONFIG_MPSC is not set -CONFIG_MCORE2=y +# CONFIG_MCORE2 is not set # CONFIG_GENERIC_CPU is not set CONFIG_X86_GENERIC=y CONFIG_X86_CPU=y CONFIG_X86_CMPXCHG=y CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_XADD=y +# CONFIG_X86_PPRO_FENCE is not set CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_INVLPG=y CONFIG_X86_BSWAP=y @@ -235,14 +236,15 @@ CONFIG_X86_POPAD_OK=y CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_USE_PPRO_CHECKSUM=y CONFIG_X86_TSC=y +CONFIG_X86_CMOV=y CONFIG_X86_MINIMUM_CPU_FAMILY=4 CONFIG_X86_DEBUGCTLMSR=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y CONFIG_DMI=y # CONFIG_IOMMU_HELPER is not set -CONFIG_NR_CPUS=4 -# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=64 +CONFIG_SCHED_SMT=y CONFIG_SCHED_MC=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y @@ -254,7 +256,8 @@ CONFIG_VM86=y # CONFIG_TOSHIBA is not set # CONFIG_I8K is not set CONFIG_X86_REBOOTFIXUPS=y -# CONFIG_MICROCODE is not set +CONFIG_MICROCODE=y +CONFIG_MICROCODE_OLD_INTERFACE=y CONFIG_X86_MSR=y CONFIG_X86_CPUID=y # CONFIG_NOHIGHMEM is not set @@ -2115,7 +2118,7 @@ CONFIG_IO_DELAY_0X80=y CONFIG_DEFAULT_IO_DELAY_TYPE=0 CONFIG_DEBUG_BOOT_PARAMS=y # CONFIG_CPA_DEBUG is not set -# CONFIG_OPTIMIZE_INLINING is not set +CONFIG_OPTIMIZE_INLINING=y # # Security options diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 678c8acefe04..e620ea6e2a7a 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc4 -# Mon Aug 25 14:40:46 2008 +# Linux kernel version: 2.6.27-rc5 +# Wed Sep 3 17:13:39 2008 # CONFIG_64BIT=y # CONFIG_X86_32 is not set @@ -218,17 +218,14 @@ CONFIG_X86_PC=y # CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC7 is not set # CONFIG_MPSC is not set -CONFIG_MCORE2=y -# CONFIG_GENERIC_CPU is not set +# CONFIG_MCORE2 is not set +CONFIG_GENERIC_CPU=y CONFIG_X86_CPU=y -CONFIG_X86_L1_CACHE_BYTES=64 -CONFIG_X86_INTERNODE_CACHE_BYTES=64 +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_INTERNODE_CACHE_BYTES=128 CONFIG_X86_CMPXCHG=y -CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INTEL_USERCOPY=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_P6_NOP=y CONFIG_X86_TSC=y CONFIG_X86_CMPXCHG64=y CONFIG_X86_CMOV=y @@ -243,9 +240,8 @@ CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y CONFIG_AMD_IOMMU=y CONFIG_SWIOTLB=y CONFIG_IOMMU_HELPER=y -# CONFIG_MAXSMP is not set -CONFIG_NR_CPUS=4 -# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=64 +CONFIG_SCHED_SMT=y CONFIG_SCHED_MC=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y @@ -254,7 +250,8 @@ CONFIG_X86_LOCAL_APIC=y CONFIG_X86_IO_APIC=y # CONFIG_X86_MCE is not set # CONFIG_I8K is not set -# CONFIG_MICROCODE is not set +CONFIG_MICROCODE=y +CONFIG_MICROCODE_OLD_INTERFACE=y CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_NUMA=y @@ -290,7 +287,7 @@ CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_MTRR=y # CONFIG_MTRR_SANITIZER is not set -# CONFIG_X86_PAT is not set +CONFIG_X86_PAT=y CONFIG_EFI=y CONFIG_SECCOMP=y # CONFIG_HZ_100 is not set @@ -2089,7 +2086,7 @@ CONFIG_IO_DELAY_0X80=y CONFIG_DEFAULT_IO_DELAY_TYPE=0 CONFIG_DEBUG_BOOT_PARAMS=y # CONFIG_CPA_DEBUG is not set -# CONFIG_OPTIMIZE_INLINING is not set +CONFIG_OPTIMIZE_INLINING=y # # Security options diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 3874c2de5403..903de4aa5094 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -10,6 +10,8 @@ obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o +obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o + aes-i586-y := aes-i586-asm_32.o aes_glue.o twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o diff --git a/arch/x86/crypto/crc32c-intel.c b/arch/x86/crypto/crc32c-intel.c new file mode 100644 index 000000000000..070afc5b6c94 --- /dev/null +++ b/arch/x86/crypto/crc32c-intel.c @@ -0,0 +1,197 @@ +/* + * Using hardware provided CRC32 instruction to accelerate the CRC32 disposal. + * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE) + * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at: + * http://www.intel.com/products/processor/manuals/ + * Intel(R) 64 and IA-32 Architectures Software Developer's Manual + * Volume 2A: Instruction Set Reference, A-M + * + * Copyright (c) 2008 Austin Zhang <austin_zhang@linux.intel.com> + * Copyright (c) 2008 Kent Liu <kent.liu@intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <crypto/internal/hash.h> + +#include <asm/cpufeature.h> + +#define CHKSUM_BLOCK_SIZE 1 +#define CHKSUM_DIGEST_SIZE 4 + +#define SCALE_F sizeof(unsigned long) + +#ifdef CONFIG_X86_64 +#define REX_PRE "0x48, " +#else +#define REX_PRE +#endif + +static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length) +{ + while (length--) { + __asm__ __volatile__( + ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1" + :"=S"(crc) + :"0"(crc), "c"(*data) + ); + data++; + } + + return crc; +} + +static u32 __pure crc32c_intel_le_hw(u32 crc, unsigned char const *p, size_t len) +{ + unsigned int iquotient = len / SCALE_F; + unsigned int iremainder = len % SCALE_F; + unsigned long *ptmp = (unsigned long *)p; + + while (iquotient--) { + __asm__ __volatile__( + ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;" + :"=S"(crc) + :"0"(crc), "c"(*ptmp) + ); + ptmp++; + } + + if (iremainder) + crc = crc32c_intel_le_hw_byte(crc, (unsigned char *)ptmp, + iremainder); + + return crc; +} + +/* + * Setting the seed allows arbitrary accumulators and flexible XOR policy + * If your algorithm starts with ~0, then XOR with ~0 before you set + * the seed. + */ +static int crc32c_intel_setkey(struct crypto_ahash *hash, const u8 *key, + unsigned int keylen) +{ + u32 *mctx = crypto_ahash_ctx(hash); + + if (keylen != sizeof(u32)) { + crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + *mctx = le32_to_cpup((__le32 *)key); + return 0; +} + +static int crc32c_intel_init(struct ahash_request *req) +{ + u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + u32 *crcp = ahash_request_ctx(req); + + *crcp = *mctx; + + return 0; +} + +static int crc32c_intel_update(struct ahash_request *req) +{ + struct crypto_hash_walk walk; + u32 *crcp = ahash_request_ctx(req); + u32 crc = *crcp; + int nbytes; + + for (nbytes = crypto_hash_walk_first(req, &walk); nbytes; + nbytes = crypto_hash_walk_done(&walk, 0)) + crc = crc32c_intel_le_hw(crc, walk.data, nbytes); + + *crcp = crc; + return 0; +} + +static int crc32c_intel_final(struct ahash_request *req) +{ + u32 *crcp = ahash_request_ctx(req); + + *(__le32 *)req->result = ~cpu_to_le32p(crcp); + return 0; +} + +static int crc32c_intel_digest(struct ahash_request *req) +{ + struct crypto_hash_walk walk; + u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); + u32 crc = *mctx; + int nbytes; + + for (nbytes = crypto_hash_walk_first(req, &walk); nbytes; + nbytes = crypto_hash_walk_done(&walk, 0)) + crc = crc32c_intel_le_hw(crc, walk.data, nbytes); + + *(__le32 *)req->result = ~cpu_to_le32(crc); + return 0; +} + +static int crc32c_intel_cra_init(struct crypto_tfm *tfm) +{ + u32 *key = crypto_tfm_ctx(tfm); + + *key = ~0; + + tfm->crt_ahash.reqsize = sizeof(u32); + + return 0; +} + +static struct crypto_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-intel", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_AHASH, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_init = crc32c_intel_cra_init, + .cra_type = &crypto_ahash_type, + .cra_u = { + .ahash = { + .digestsize = CHKSUM_DIGEST_SIZE, + .setkey = crc32c_intel_setkey, + .init = crc32c_intel_init, + .update = crc32c_intel_update, + .final = crc32c_intel_final, + .digest = crc32c_intel_digest, + } + } +}; + + +static int __init crc32c_intel_mod_init(void) +{ + if (cpu_has_xmm4_2) + return crypto_register_alg(&alg); + else + return -ENODEV; +} + +static void __exit crc32c_intel_mod_fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(crc32c_intel_mod_init); +module_exit(crc32c_intel_mod_fini); + +MODULE_AUTHOR("Austin Zhang <austin.zhang@intel.com>, Kent Liu <kent.liu@intel.com>"); +MODULE_DESCRIPTION("CRC32c (Castagnoli) optimization using Intel Hardware."); +MODULE_LICENSE("GPL"); + +MODULE_ALIAS("crc32c"); +MODULE_ALIAS("crc32c-intel"); + diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index a0e1dbe67dc1..127ec3f07214 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -85,8 +85,10 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump) dump->regs.ax = regs->ax; dump->regs.ds = current->thread.ds; dump->regs.es = current->thread.es; - asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs; - asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs; + savesegment(fs, fs); + dump->regs.fs = fs; + savesegment(gs, gs); + dump->regs.gs = gs; dump->regs.orig_ax = regs->orig_ax; dump->regs.ip = regs->ip; dump->regs.cs = regs->cs; @@ -430,8 +432,9 @@ beyond_if: current->mm->start_stack = (unsigned long)create_aout_tables((char __user *)bprm->p, bprm); /* start thread */ - asm volatile("movl %0,%%fs" :: "r" (0)); \ - asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); + loadsegment(fs, 0); + loadsegment(ds, __USER32_DS); + loadsegment(es, __USER32_DS); load_gs_index(0); (regs)->ip = ex.a_entry; (regs)->sp = current->mm->start_stack; diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 20af4c79579a..f1a2ac777faf 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -206,7 +206,7 @@ struct rt_sigframe { unsigned int cur; \ unsigned short pre; \ err |= __get_user(pre, &sc->seg); \ - asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \ + savesegment(seg, cur); \ pre |= mask; \ if (pre != cur) loadsegment(seg, pre); } @@ -235,7 +235,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, */ err |= __get_user(gs, &sc->gs); gs |= 3; - asm("movl %%gs,%0" : "=r" (oldgs)); + savesegment(gs, oldgs); if (gs != oldgs) load_gs_index(gs); @@ -355,14 +355,13 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, { int tmp, err = 0; - tmp = 0; - __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); + savesegment(gs, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->gs); - __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); + savesegment(fs, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->fs); - __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp)); + savesegment(ds, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->ds); - __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp)); + savesegment(es, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->es); err |= __put_user((u32)regs->di, &sc->di); @@ -498,8 +497,8 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, regs->dx = 0; regs->cx = 0; - asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); - asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); + loadsegment(ds, __USER32_DS); + loadsegment(es, __USER32_DS); regs->cs = __USER32_CS; regs->ss = __USER32_DS; @@ -591,8 +590,8 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->dx = (unsigned long) &frame->info; regs->cx = (unsigned long) &frame->uc; - asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); - asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); + loadsegment(ds, __USER32_DS); + loadsegment(es, __USER32_DS); regs->cs = __USER32_CS; regs->ss = __USER32_DS; diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index d3c64088b981..beda4232ce69 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -556,15 +556,6 @@ asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig, return ret; } -/* These are here just in case some old ia32 binary calls it. */ -asmlinkage long sys32_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - - #ifdef CONFIG_SYSCTL_SYSCALL struct sysctl_ia32 { unsigned int name; diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index c102af85df9c..7d40ef7b36e3 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -58,7 +58,6 @@ EXPORT_SYMBOL(acpi_disabled); #ifdef CONFIG_X86_64 #include <asm/proto.h> -#include <asm/genapic.h> #else /* X86 */ @@ -97,8 +96,6 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; #warning ACPI uses CMPXCHG, i486 and later hardware #endif -static int acpi_mcfg_64bit_base_addr __initdata = FALSE; - /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -160,6 +157,8 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size) struct acpi_mcfg_allocation *pci_mmcfg_config; int pci_mmcfg_config_num; +static int acpi_mcfg_64bit_base_addr __initdata = FALSE; + static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg) { if (!strcmp(mcfg->header.oem_id, "SGI")) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 65a0c1b48696..fb04e49776ba 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -231,25 +231,25 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) continue; if (*ptr > text_end) continue; - text_poke(*ptr, ((unsigned char []){0xf0}), 1); /* add lock prefix */ + /* turn DS segment override prefix into lock prefix */ + text_poke(*ptr, ((unsigned char []){0xf0}), 1); }; } static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) { u8 **ptr; - char insn[1]; if (noreplace_smp) return; - add_nops(insn, 1); for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; if (*ptr > text_end) continue; - text_poke(*ptr, insn, 1); + /* turn lock prefix into DS segment override prefix */ + text_poke(*ptr, ((unsigned char []){0x3E}), 1); }; } diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 44e21826db11..9a32b37ee2ee 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -455,11 +455,11 @@ out: force_iommu || valid_agp || fallback_aper_force) { - printk(KERN_ERR + printk(KERN_INFO "Your BIOS doesn't leave a aperture memory hole\n"); - printk(KERN_ERR + printk(KERN_INFO "Please enable the IOMMU option in the BIOS setup\n"); - printk(KERN_ERR + printk(KERN_INFO "This costs you %d MB of RAM\n", 32 << fallback_aper_order); diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 732d1f4e10ee..5145a6e72bbb 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -228,7 +228,6 @@ #include <linux/suspend.h> #include <linux/kthread.h> #include <linux/jiffies.h> -#include <linux/smp_lock.h> #include <asm/system.h> #include <asm/uaccess.h> diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index aa89387006fe..505543a75a56 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -22,7 +22,7 @@ #define __NO_STUBS 1 #undef __SYSCALL -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #define __SYSCALL(nr, sym) [nr] = 1, static char syscalls[] = { #include <asm/unistd.h> diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c index c639bd55391c..fdd585f9c53d 100644 --- a/arch/x86/kernel/bios_uv.c +++ b/arch/x86/kernel/bios_uv.c @@ -25,11 +25,11 @@ x86_bios_strerror(long status) { const char *str; switch (status) { - case 0: str = "Call completed without error"; break; - case -1: str = "Not implemented"; break; - case -2: str = "Invalid argument"; break; - case -3: str = "Call completed with error"; break; - default: str = "Unknown BIOS status code"; break; + case 0: str = "Call completed without error"; break; + case -1: str = "Not implemented"; break; + case -2: str = "Invalid argument"; break; + case -3: str = "Call completed with error"; break; + default: str = "Unknown BIOS status code"; break; } return str; } diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index a11f5d4477cd..305b465889b0 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -430,6 +430,49 @@ static __init int setup_noclflush(char *arg) } __setup("noclflush", setup_noclflush); +struct msr_range { + unsigned min; + unsigned max; +}; + +static struct msr_range msr_range_array[] __cpuinitdata = { + { 0x00000000, 0x00000418}, + { 0xc0000000, 0xc000040b}, + { 0xc0010000, 0xc0010142}, + { 0xc0011000, 0xc001103b}, +}; + +static void __cpuinit print_cpu_msr(void) +{ + unsigned index; + u64 val; + int i; + unsigned index_min, index_max; + + for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) { + index_min = msr_range_array[i].min; + index_max = msr_range_array[i].max; + for (index = index_min; index < index_max; index++) { + if (rdmsrl_amd_safe(index, &val)) + continue; + printk(KERN_INFO " MSR%08x: %016llx\n", index, val); + } + } +} + +static int show_msr __cpuinitdata; +static __init int setup_show_msr(char *arg) +{ + int num; + + get_option(&arg, &num); + + if (num > 0) + show_msr = num; + return 1; +} +__setup("show_msr=", setup_show_msr); + void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) { if (c->x86_model_id[0]) @@ -439,6 +482,14 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) printk(KERN_CONT " stepping %02x\n", c->x86_mask); else printk(KERN_CONT "\n"); + +#ifdef CONFIG_SMP + if (c->cpu_index < show_msr) + print_cpu_msr(); +#else + if (show_msr) + print_cpu_msr(); +#endif } static __init int setup_disablecpuid(char *arg) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index b75f2569b8f8..f113ef4595f6 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -222,10 +222,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_BTS); if (!(l1 & (1<<12))) set_cpu_cap(c, X86_FEATURE_PEBS); + ds_init_intel(c); } if (cpu_has_bts) - ds_init_intel(c); + ptrace_bts_init_intel(c); /* * See if we have a good local APIC by checking for buggy Pentia, diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index cb7d3b6a80eb..4e8d77f01eeb 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -401,12 +401,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, tmp |= ~((1<<(hi - 1)) - 1); if (tmp != mask_lo) { - static int once = 1; - - if (once) { - printk(KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); - once = 0; - } + WARN_ONCE(1, KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); mask_lo = tmp; } } diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index 84c480bb3715..4c4214690dd1 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c @@ -405,9 +405,9 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset) } /* RED-PEN: base can be > 32bit */ len += seq_printf(seq, - "reg%02i: base=0x%05lx000 (%4luMB), size=%4lu%cB: %s, count=%d\n", + "reg%02i: base=0x%06lx000 (%5luMB), size=%5lu%cB, count=%d: %s\n", i, base, base >> (20 - PAGE_SHIFT), size, factor, - mtrr_attrib_to_str(type), mtrr_usage_table[i]); + mtrr_usage_table[i], mtrr_attrib_to_str(type)); } } return 0; diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 885c8265e6b5..c78c04821ea1 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -729,7 +729,7 @@ struct var_mtrr_range_state { mtrr_type type; }; -struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; +static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; static int __initdata debug_print; static int __init @@ -759,7 +759,8 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, /* take out UC ranges */ for (i = 0; i < num_var_ranges; i++) { type = range_state[i].type; - if (type != MTRR_TYPE_UNCACHABLE) + if (type != MTRR_TYPE_UNCACHABLE && + type != MTRR_TYPE_WRPROT) continue; size = range_state[i].size_pfn; if (!size) @@ -836,6 +837,13 @@ static int __init enable_mtrr_cleanup_setup(char *str) } early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup); +static int __init mtrr_cleanup_debug_setup(char *str) +{ + debug_print = 1; + return 0; +} +early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup); + struct var_mtrr_state { unsigned long range_startk; unsigned long range_sizek; @@ -898,6 +906,27 @@ set_var_mtrr_all(unsigned int address_bits) } } +static unsigned long to_size_factor(unsigned long sizek, char *factorp) +{ + char factor; + unsigned long base = sizek; + + if (base & ((1<<10) - 1)) { + /* not MB alignment */ + factor = 'K'; + } else if (base & ((1<<20) - 1)){ + factor = 'M'; + base >>= 10; + } else { + factor = 'G'; + base >>= 20; + } + + *factorp = factor; + + return base; +} + static unsigned int __init range_to_mtrr(unsigned int reg, unsigned long range_startk, unsigned long range_sizek, unsigned char type) @@ -919,13 +948,21 @@ range_to_mtrr(unsigned int reg, unsigned long range_startk, align = max_align; sizek = 1 << align; - if (debug_print) + if (debug_print) { + char start_factor = 'K', size_factor = 'K'; + unsigned long start_base, size_base; + + start_base = to_size_factor(range_startk, &start_factor), + size_base = to_size_factor(sizek, &size_factor), + printk(KERN_DEBUG "Setting variable MTRR %d, " - "base: %ldMB, range: %ldMB, type %s\n", - reg, range_startk >> 10, sizek >> 10, + "base: %ld%cB, range: %ld%cB, type %s\n", + reg, start_base, start_factor, + size_base, size_factor, (type == MTRR_TYPE_UNCACHABLE)?"UC": ((type == MTRR_TYPE_WRBACK)?"WB":"Other") ); + } save_var_mtrr(reg++, range_startk, sizek, type); range_startk += sizek; range_sizek -= sizek; @@ -970,6 +1007,8 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, /* try to append some small hole */ range0_basek = state->range_startk; range0_sizek = ALIGN(state->range_sizek, chunk_sizek); + + /* no increase */ if (range0_sizek == state->range_sizek) { if (debug_print) printk(KERN_DEBUG "rangeX: %016lx - %016lx\n", @@ -980,13 +1019,40 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, return 0; } - range0_sizek -= chunk_sizek; - if (range0_sizek && sizek) { - while (range0_basek + range0_sizek > (basek + sizek)) { - range0_sizek -= chunk_sizek; - if (!range0_sizek) - break; - } + /* only cut back, when it is not the last */ + if (sizek) { + while (range0_basek + range0_sizek > (basek + sizek)) { + if (range0_sizek >= chunk_sizek) + range0_sizek -= chunk_sizek; + else + range0_sizek = 0; + + if (!range0_sizek) + break; + } + } + +second_try: + range_basek = range0_basek + range0_sizek; + + /* one hole in the middle */ + if (range_basek > basek && range_basek <= (basek + sizek)) + second_sizek = range_basek - basek; + + if (range0_sizek > state->range_sizek) { + + /* one hole in middle or at end */ + hole_sizek = range0_sizek - state->range_sizek - second_sizek; + + /* hole size should be less than half of range0 size */ + if (hole_sizek >= (range0_sizek >> 1) && + range0_sizek >= chunk_sizek) { + range0_sizek -= chunk_sizek; + second_sizek = 0; + hole_sizek = 0; + + goto second_try; + } } if (range0_sizek) { @@ -996,50 +1062,28 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, (range0_basek + range0_sizek)<<10); state->reg = range_to_mtrr(state->reg, range0_basek, range0_sizek, MTRR_TYPE_WRBACK); - - } - - range_basek = range0_basek + range0_sizek; - range_sizek = chunk_sizek; - - if (range_basek + range_sizek > basek && - range_basek + range_sizek <= (basek + sizek)) { - /* one hole */ - second_basek = basek; - second_sizek = range_basek + range_sizek - basek; } - /* if last piece, only could one hole near end */ - if ((second_basek || !basek) && - range_sizek - (state->range_sizek - range0_sizek) - second_sizek < - (chunk_sizek >> 1)) { - /* - * one hole in middle (second_sizek is 0) or at end - * (second_sizek is 0 ) - */ - hole_sizek = range_sizek - (state->range_sizek - range0_sizek) - - second_sizek; - hole_basek = range_basek + range_sizek - hole_sizek - - second_sizek; - } else { - /* fallback for big hole, or several holes */ + if (range0_sizek < state->range_sizek) { + /* need to handle left over */ range_sizek = state->range_sizek - range0_sizek; - second_basek = 0; - second_sizek = 0; + + if (debug_print) + printk(KERN_DEBUG "range: %016lx - %016lx\n", + range_basek<<10, + (range_basek + range_sizek)<<10); + state->reg = range_to_mtrr(state->reg, range_basek, + range_sizek, MTRR_TYPE_WRBACK); } - if (debug_print) - printk(KERN_DEBUG "range: %016lx - %016lx\n", range_basek<<10, - (range_basek + range_sizek)<<10); - state->reg = range_to_mtrr(state->reg, range_basek, range_sizek, - MTRR_TYPE_WRBACK); if (hole_sizek) { + hole_basek = range_basek - hole_sizek - second_sizek; if (debug_print) printk(KERN_DEBUG "hole: %016lx - %016lx\n", - hole_basek<<10, (hole_basek + hole_sizek)<<10); - state->reg = range_to_mtrr(state->reg, hole_basek, hole_sizek, - MTRR_TYPE_UNCACHABLE); - + hole_basek<<10, + (hole_basek + hole_sizek)<<10); + state->reg = range_to_mtrr(state->reg, hole_basek, + hole_sizek, MTRR_TYPE_UNCACHABLE); } return second_sizek; @@ -1154,11 +1198,11 @@ struct mtrr_cleanup_result { }; /* - * gran_size: 1M, 2M, ..., 2G - * chunk size: gran_size, ..., 4G - * so we need (2+13)*6 + * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G + * chunk size: gran_size, ..., 2G + * so we need (1+16)*8 */ -#define NUM_RESULT 90 +#define NUM_RESULT 136 #define PSHIFT (PAGE_SHIFT - 10) static struct mtrr_cleanup_result __initdata result[NUM_RESULT]; @@ -1168,13 +1212,14 @@ static unsigned long __initdata min_loss_pfn[RANGE_NUM]; static int __init mtrr_cleanup(unsigned address_bits) { unsigned long extra_remove_base, extra_remove_size; - unsigned long i, base, size, def, dummy; + unsigned long base, size, def, dummy; mtrr_type type; int nr_range, nr_range_new; u64 chunk_size, gran_size; unsigned long range_sums, range_sums_new; int index_good; int num_reg_good; + int i; /* extra one for all 0 */ int num[MTRR_NUM_TYPES + 1]; @@ -1204,6 +1249,8 @@ static int __init mtrr_cleanup(unsigned address_bits) continue; if (!size) type = MTRR_NUM_TYPES; + if (type == MTRR_TYPE_WRPROT) + type = MTRR_TYPE_UNCACHABLE; num[type]++; } @@ -1216,23 +1263,57 @@ static int __init mtrr_cleanup(unsigned address_bits) num_var_ranges - num[MTRR_NUM_TYPES]) return 0; + /* print original var MTRRs at first, for debugging: */ + printk(KERN_DEBUG "original variable MTRRs\n"); + for (i = 0; i < num_var_ranges; i++) { + char start_factor = 'K', size_factor = 'K'; + unsigned long start_base, size_base; + + size_base = range_state[i].size_pfn << (PAGE_SHIFT - 10); + if (!size_base) + continue; + + size_base = to_size_factor(size_base, &size_factor), + start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10); + start_base = to_size_factor(start_base, &start_factor), + type = range_state[i].type; + + printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n", + i, start_base, start_factor, + size_base, size_factor, + (type == MTRR_TYPE_UNCACHABLE) ? "UC" : + ((type == MTRR_TYPE_WRPROT) ? "WP" : + ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other")) + ); + } + memset(range, 0, sizeof(range)); extra_remove_size = 0; - if (mtrr_tom2) { - extra_remove_base = 1 << (32 - PAGE_SHIFT); + extra_remove_base = 1 << (32 - PAGE_SHIFT); + if (mtrr_tom2) extra_remove_size = (mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base; - } nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base, extra_remove_size); + /* + * [0, 1M) should always be coverred by var mtrr with WB + * and fixed mtrrs should take effective before var mtrr for it + */ + nr_range = add_range_with_merge(range, nr_range, 0, + (1ULL<<(20 - PAGE_SHIFT)) - 1); + /* sort the ranges */ + sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); + range_sums = sum_ranges(range, nr_range); printk(KERN_INFO "total RAM coverred: %ldM\n", range_sums >> (20 - PAGE_SHIFT)); if (mtrr_chunk_size && mtrr_gran_size) { int num_reg; + char gran_factor, chunk_factor, lose_factor; + unsigned long gran_base, chunk_base, lose_base; - debug_print = 1; + debug_print++; /* convert ranges to var ranges state */ num_reg = x86_setup_var_mtrrs(range, nr_range, mtrr_chunk_size, mtrr_gran_size); @@ -1256,34 +1337,48 @@ static int __init mtrr_cleanup(unsigned address_bits) result[i].lose_cover_sizek = (range_sums - range_sums_new) << PSHIFT; - printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", - result[i].bad?"*BAD*":" ", result[i].gran_sizek >> 10, - result[i].chunk_sizek >> 10); - printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ldM \n", + gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), + chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), + lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), + printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t", + result[i].bad?"*BAD*":" ", + gran_base, gran_factor, chunk_base, chunk_factor); + printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n", result[i].num_reg, result[i].bad?"-":"", - result[i].lose_cover_sizek >> 10); + lose_base, lose_factor); if (!result[i].bad) { set_var_mtrr_all(address_bits); return 1; } printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, " "will find optimal one\n"); - debug_print = 0; + debug_print--; memset(result, 0, sizeof(result[0])); } i = 0; memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn)); memset(result, 0, sizeof(result)); - for (gran_size = (1ULL<<20); gran_size < (1ULL<<32); gran_size <<= 1) { - for (chunk_size = gran_size; chunk_size < (1ULL<<33); + for (gran_size = (1ULL<<16); gran_size < (1ULL<<32); gran_size <<= 1) { + char gran_factor; + unsigned long gran_base; + + if (debug_print) + gran_base = to_size_factor(gran_size >> 10, &gran_factor); + + for (chunk_size = gran_size; chunk_size < (1ULL<<32); chunk_size <<= 1) { int num_reg; - if (debug_print) - printk(KERN_INFO - "\ngran_size: %lldM chunk_size_size: %lldM\n", - gran_size >> 20, chunk_size >> 20); + if (debug_print) { + char chunk_factor; + unsigned long chunk_base; + + chunk_base = to_size_factor(chunk_size>>10, &chunk_factor), + printk(KERN_INFO "\n"); + printk(KERN_INFO "gran_size: %ld%c chunk_size: %ld%c \n", + gran_base, gran_factor, chunk_base, chunk_factor); + } if (i >= NUM_RESULT) continue; @@ -1326,12 +1421,18 @@ static int __init mtrr_cleanup(unsigned address_bits) /* print out all */ for (i = 0; i < NUM_RESULT; i++) { - printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", - result[i].bad?"*BAD* ":" ", result[i].gran_sizek >> 10, - result[i].chunk_sizek >> 10); - printk(KERN_CONT "num_reg: %d \tlose RAM: %s%ldM\n", - result[i].num_reg, result[i].bad?"-":"", - result[i].lose_cover_sizek >> 10); + char gran_factor, chunk_factor, lose_factor; + unsigned long gran_base, chunk_base, lose_base; + + gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), + chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), + lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), + printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t", + result[i].bad?"*BAD*":" ", + gran_base, gran_factor, chunk_base, chunk_factor); + printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n", + result[i].num_reg, result[i].bad?"-":"", + lose_base, lose_factor); } /* try to find the optimal index */ @@ -1339,10 +1440,8 @@ static int __init mtrr_cleanup(unsigned address_bits) nr_mtrr_spare_reg = num_var_ranges - 1; num_reg_good = -1; for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) { - if (!min_loss_pfn[i]) { + if (!min_loss_pfn[i]) num_reg_good = i; - break; - } } index_good = -1; @@ -1358,21 +1457,26 @@ static int __init mtrr_cleanup(unsigned address_bits) } if (index_good != -1) { + char gran_factor, chunk_factor, lose_factor; + unsigned long gran_base, chunk_base, lose_base; + printk(KERN_INFO "Found optimal setting for mtrr clean up\n"); i = index_good; - printk(KERN_INFO "gran_size: %ldM \tchunk_size: %ldM \t", - result[i].gran_sizek >> 10, - result[i].chunk_sizek >> 10); - printk(KERN_CONT "num_reg: %d \tlose RAM: %ldM\n", - result[i].num_reg, - result[i].lose_cover_sizek >> 10); + gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), + chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), + lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), + printk(KERN_INFO "gran_size: %ld%c \tchunk_size: %ld%c \t", + gran_base, gran_factor, chunk_base, chunk_factor); + printk(KERN_CONT "num_reg: %d \tlose RAM: %ld%c\n", + result[i].num_reg, lose_base, lose_factor); /* convert ranges to var ranges state */ chunk_size = result[i].chunk_sizek; chunk_size <<= 10; gran_size = result[i].gran_sizek; gran_size <<= 10; - debug_print = 1; + debug_print++; x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size); + debug_print--; set_var_mtrr_all(address_bits); return 1; } diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 05cc22dbd4ff..6bff382094f5 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -295,13 +295,19 @@ static int setup_k7_watchdog(unsigned nmi_hz) /* setup the timer */ wrmsr(evntsel_msr, evntsel, 0); write_watchdog_counter(perfctr_msr, "K7_PERFCTR0",nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - evntsel |= K7_EVNTSEL_ENABLE; - wrmsr(evntsel_msr, evntsel, 0); + /* initialize the wd struct before enabling */ wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = 0; /* unused */ + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= K7_EVNTSEL_ENABLE; + wrmsr(evntsel_msr, evntsel, 0); + return 1; } @@ -379,13 +385,19 @@ static int setup_p6_watchdog(unsigned nmi_hz) wrmsr(evntsel_msr, evntsel, 0); nmi_hz = adjust_for_32bit_ctr(nmi_hz); write_watchdog_counter32(perfctr_msr, "P6_PERFCTR0",nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - evntsel |= P6_EVNTSEL0_ENABLE; - wrmsr(evntsel_msr, evntsel, 0); + /* initialize the wd struct before enabling */ wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = 0; /* unused */ + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= P6_EVNTSEL0_ENABLE; + wrmsr(evntsel_msr, evntsel, 0); + return 1; } @@ -432,6 +444,27 @@ static const struct wd_ops p6_wd_ops = { #define P4_CCCR_ENABLE (1 << 12) #define P4_CCCR_OVF (1 << 31) +#define P4_CONTROLS 18 +static unsigned int p4_controls[18] = { + MSR_P4_BPU_CCCR0, + MSR_P4_BPU_CCCR1, + MSR_P4_BPU_CCCR2, + MSR_P4_BPU_CCCR3, + MSR_P4_MS_CCCR0, + MSR_P4_MS_CCCR1, + MSR_P4_MS_CCCR2, + MSR_P4_MS_CCCR3, + MSR_P4_FLAME_CCCR0, + MSR_P4_FLAME_CCCR1, + MSR_P4_FLAME_CCCR2, + MSR_P4_FLAME_CCCR3, + MSR_P4_IQ_CCCR0, + MSR_P4_IQ_CCCR1, + MSR_P4_IQ_CCCR2, + MSR_P4_IQ_CCCR3, + MSR_P4_IQ_CCCR4, + MSR_P4_IQ_CCCR5, +}; /* * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter * CRU_ESCR0 (with any non-null event selector) through a complemented @@ -473,6 +506,26 @@ static int setup_p4_watchdog(unsigned nmi_hz) evntsel_msr = MSR_P4_CRU_ESCR0; cccr_msr = MSR_P4_IQ_CCCR0; cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4); + + /* + * If we're on the kdump kernel or other situation, we may + * still have other performance counter registers set to + * interrupt and they'll keep interrupting forever because + * of the P4_CCCR_OVF quirk. So we need to ACK all the + * pending interrupts and disable all the registers here, + * before reenabling the NMI delivery. Refer to p4_rearm() + * about the P4_CCCR_OVF quirk. + */ + if (reset_devices) { + unsigned int low, high; + int i; + + for (i = 0; i < P4_CONTROLS; i++) { + rdmsr(p4_controls[i], low, high); + low &= ~(P4_CCCR_ENABLE | P4_CCCR_OVF); + wrmsr(p4_controls[i], low, high); + } + } } else { /* logical cpu 1 */ perfctr_msr = MSR_P4_IQ_PERFCTR1; @@ -499,12 +552,17 @@ static int setup_p4_watchdog(unsigned nmi_hz) wrmsr(evntsel_msr, evntsel, 0); wrmsr(cccr_msr, cccr_val, 0); write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0", nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - cccr_val |= P4_CCCR_ENABLE; - wrmsr(cccr_msr, cccr_val, 0); + wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = cccr_msr; + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + cccr_val |= P4_CCCR_ENABLE; + wrmsr(cccr_msr, cccr_val, 0); return 1; } @@ -620,13 +678,17 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz) wrmsr(evntsel_msr, evntsel, 0); nmi_hz = adjust_for_32bit_ctr(nmi_hz); write_watchdog_counter32(perfctr_msr, "INTEL_ARCH_PERFCTR0", nmi_hz); - apic_write(APIC_LVTPC, APIC_DM_NMI); - evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; - wrmsr(evntsel_msr, evntsel, 0); wd->perfctr_msr = perfctr_msr; wd->evntsel_msr = evntsel_msr; wd->cccr_msr = 0; /* unused */ + + /* ok, everything is initialized, announce that we're set */ + cpu_nmi_set_wd_enabled(); + + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; + wrmsr(evntsel_msr, evntsel, 0); intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1); return 1; } diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 8e9cd6a8ec12..6a44d6465991 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -36,7 +36,6 @@ #include <linux/smp_lock.h> #include <linux/major.h> #include <linux/fs.h> -#include <linux/smp_lock.h> #include <linux/device.h> #include <linux/cpu.h> #include <linux/notifier.h> diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index 15e6c6bc4a46..e90a60ef10c2 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -7,9 +7,8 @@ #include <linux/errno.h> #include <linux/crash_dump.h> - -#include <asm/uaccess.h> -#include <asm/io.h> +#include <linux/uaccess.h> +#include <linux/io.h> /** * copy_oldmem_page - copy one page from "oldmem" @@ -25,7 +24,7 @@ * in the current kernel. We stitch up a pte, similar to kmap_atomic. */ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, - size_t csize, unsigned long offset, int userbuf) + size_t csize, unsigned long offset, int userbuf) { void *vaddr; @@ -33,14 +32,16 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, return 0; vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); + if (!vaddr) + return -ENOMEM; if (userbuf) { - if (copy_to_user(buf, (vaddr + offset), csize)) { + if (copy_to_user(buf, vaddr + offset, csize)) { iounmap(vaddr); return -EFAULT; } } else - memcpy(buf, (vaddr + offset), csize); + memcpy(buf, vaddr + offset, csize); iounmap(vaddr); return csize; diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 11c11b8ec48d..2b69994fd3a8 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -2,26 +2,49 @@ * Debug Store support * * This provides a low-level interface to the hardware's Debug Store - * feature that is used for last branch recording (LBR) and + * feature that is used for branch trace store (BTS) and * precise-event based sampling (PEBS). * - * Different architectures use a different DS layout/pointer size. - * The below functions therefore work on a void*. + * It manages: + * - per-thread and per-cpu allocation of BTS and PEBS + * - buffer memory allocation (optional) + * - buffer overflow handling + * - buffer access * + * It assumes: + * - get_task_struct on all parameter tasks + * - current is allowed to trace parameter tasks * - * Since there is no user for PEBS, yet, only LBR (or branch - * trace store, BTS) is supported. * - * - * Copyright (C) 2007 Intel Corporation. - * Markus Metzger <markus.t.metzger@intel.com>, Dec 2007 + * Copyright (C) 2007-2008 Intel Corporation. + * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008 */ + +#ifdef CONFIG_X86_DS + #include <asm/ds.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/slab.h> +#include <linux/sched.h> +#include <linux/mm.h> + + +/* + * The configuration for a particular DS hardware implementation. + */ +struct ds_configuration { + /* the size of the DS structure in bytes */ + unsigned char sizeof_ds; + /* the size of one pointer-typed field in the DS structure in bytes; + this covers the first 8 fields related to buffer management. */ + unsigned char sizeof_field; + /* the size of a BTS/PEBS record in bytes */ + unsigned char sizeof_rec[2]; +}; +static struct ds_configuration ds_cfg; /* @@ -44,378 +67,747 @@ * (interrupt occurs when write pointer passes interrupt pointer) * - value to which counter is reset following counter overflow * - * On later architectures, the last branch recording hardware uses - * 64bit pointers even in 32bit mode. - * - * - * Branch Trace Store (BTS) records store information about control - * flow changes. They at least provide the following information: - * - source linear address - * - destination linear address + * Later architectures use 64bit pointers throughout, whereas earlier + * architectures use 32bit pointers in 32bit mode. * - * Netburst supported a predicated bit that had been dropped in later - * architectures. We do not suppor it. * + * We compute the base address for the first 8 fields based on: + * - the field size stored in the DS configuration + * - the relative field position + * - an offset giving the start of the respective region * - * In order to abstract from the actual DS and BTS layout, we describe - * the access to the relevant fields. - * Thanks to Andi Kleen for proposing this design. + * This offset is further used to index various arrays holding + * information for BTS and PEBS at the respective index. * - * The implementation, however, is not as general as it might seem. In - * order to stay somewhat simple and efficient, we assume an - * underlying unsigned type (mostly a pointer type) and we expect the - * field to be at least as big as that type. + * On later 32bit processors, we only access the lower 32bit of the + * 64bit pointer fields. The upper halves will be zeroed out. */ -/* - * A special from_ip address to indicate that the BTS record is an - * info record that needs to be interpreted or skipped. - */ -#define BTS_ESCAPE_ADDRESS (-1) +enum ds_field { + ds_buffer_base = 0, + ds_index, + ds_absolute_maximum, + ds_interrupt_threshold, +}; -/* - * A field access descriptor - */ -struct access_desc { - unsigned char offset; - unsigned char size; +enum ds_qualifier { + ds_bts = 0, + ds_pebs }; +static inline unsigned long ds_get(const unsigned char *base, + enum ds_qualifier qual, enum ds_field field) +{ + base += (ds_cfg.sizeof_field * (field + (4 * qual))); + return *(unsigned long *)base; +} + +static inline void ds_set(unsigned char *base, enum ds_qualifier qual, + enum ds_field field, unsigned long value) +{ + base += (ds_cfg.sizeof_field * (field + (4 * qual))); + (*(unsigned long *)base) = value; +} + + /* - * The configuration for a particular DS/BTS hardware implementation. + * Locking is done only for allocating BTS or PEBS resources and for + * guarding context and buffer memory allocation. + * + * Most functions require the current task to own the ds context part + * they are going to access. All the locking is done when validating + * access to the context. */ -struct ds_configuration { - /* the DS configuration */ - unsigned char sizeof_ds; - struct access_desc bts_buffer_base; - struct access_desc bts_index; - struct access_desc bts_absolute_maximum; - struct access_desc bts_interrupt_threshold; - /* the BTS configuration */ - unsigned char sizeof_bts; - struct access_desc from_ip; - struct access_desc to_ip; - /* BTS variants used to store additional information like - timestamps */ - struct access_desc info_type; - struct access_desc info_data; - unsigned long debugctl_mask; -}; +static spinlock_t ds_lock = __SPIN_LOCK_UNLOCKED(ds_lock); /* - * The global configuration used by the below accessor functions + * Validate that the current task is allowed to access the BTS/PEBS + * buffer of the parameter task. + * + * Returns 0, if access is granted; -Eerrno, otherwise. */ -static struct ds_configuration ds_cfg; +static inline int ds_validate_access(struct ds_context *context, + enum ds_qualifier qual) +{ + if (!context) + return -EPERM; + + if (context->owner[qual] == current) + return 0; + + return -EPERM; +} + /* - * Accessor functions for some DS and BTS fields using the above - * global ptrace_bts_cfg. + * We either support (system-wide) per-cpu or per-thread allocation. + * We distinguish the two based on the task_struct pointer, where a + * NULL pointer indicates per-cpu allocation for the current cpu. + * + * Allocations are use-counted. As soon as resources are allocated, + * further allocations must be of the same type (per-cpu or + * per-thread). We model this by counting allocations (i.e. the number + * of tracers of a certain type) for one type negatively: + * =0 no tracers + * >0 number of per-thread tracers + * <0 number of per-cpu tracers + * + * The below functions to get and put tracers and to check the + * allocation type require the ds_lock to be held by the caller. + * + * Tracers essentially gives the number of ds contexts for a certain + * type of allocation. */ -static inline unsigned long get_bts_buffer_base(char *base) +static long tracers; + +static inline void get_tracer(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_buffer_base.offset); + tracers += (task ? 1 : -1); } -static inline void set_bts_buffer_base(char *base, unsigned long value) + +static inline void put_tracer(struct task_struct *task) { - (*(unsigned long *)(base + ds_cfg.bts_buffer_base.offset)) = value; + tracers -= (task ? 1 : -1); } -static inline unsigned long get_bts_index(char *base) + +static inline int check_tracer(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_index.offset); + return (task ? (tracers >= 0) : (tracers <= 0)); } -static inline void set_bts_index(char *base, unsigned long value) + + +/* + * The DS context is either attached to a thread or to a cpu: + * - in the former case, the thread_struct contains a pointer to the + * attached context. + * - in the latter case, we use a static array of per-cpu context + * pointers. + * + * Contexts are use-counted. They are allocated on first access and + * deallocated when the last user puts the context. + * + * We distinguish between an allocating and a non-allocating get of a + * context: + * - the allocating get is used for requesting BTS/PEBS resources. It + * requires the caller to hold the global ds_lock. + * - the non-allocating get is used for all other cases. A + * non-existing context indicates an error. It acquires and releases + * the ds_lock itself for obtaining the context. + * + * A context and its DS configuration are allocated and deallocated + * together. A context always has a DS configuration of the + * appropriate size. + */ +static DEFINE_PER_CPU(struct ds_context *, system_context); + +#define this_system_context per_cpu(system_context, smp_processor_id()) + +/* + * Returns the pointer to the parameter task's context or to the + * system-wide context, if task is NULL. + * + * Increases the use count of the returned context, if not NULL. + */ +static inline struct ds_context *ds_get_context(struct task_struct *task) { - (*(unsigned long *)(base + ds_cfg.bts_index.offset)) = value; + struct ds_context *context; + + spin_lock(&ds_lock); + + context = (task ? task->thread.ds_ctx : this_system_context); + if (context) + context->count++; + + spin_unlock(&ds_lock); + + return context; } -static inline unsigned long get_bts_absolute_maximum(char *base) + +/* + * Same as ds_get_context, but allocates the context and it's DS + * structure, if necessary; returns NULL; if out of memory. + * + * pre: requires ds_lock to be held + */ +static inline struct ds_context *ds_alloc_context(struct task_struct *task) { - return *(unsigned long *)(base + ds_cfg.bts_absolute_maximum.offset); + struct ds_context **p_context = + (task ? &task->thread.ds_ctx : &this_system_context); + struct ds_context *context = *p_context; + + if (!context) { + context = kzalloc(sizeof(*context), GFP_KERNEL); + + if (!context) + return NULL; + + context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); + if (!context->ds) { + kfree(context); + return NULL; + } + + *p_context = context; + + context->this = p_context; + context->task = task; + + if (task) + set_tsk_thread_flag(task, TIF_DS_AREA_MSR); + + if (!task || (task == current)) + wrmsr(MSR_IA32_DS_AREA, (unsigned long)context->ds, 0); + + get_tracer(task); + } + + context->count++; + + return context; } -static inline void set_bts_absolute_maximum(char *base, unsigned long value) + +/* + * Decreases the use count of the parameter context, if not NULL. + * Deallocates the context, if the use count reaches zero. + */ +static inline void ds_put_context(struct ds_context *context) { - (*(unsigned long *)(base + ds_cfg.bts_absolute_maximum.offset)) = value; + if (!context) + return; + + spin_lock(&ds_lock); + + if (--context->count) + goto out; + + *(context->this) = NULL; + + if (context->task) + clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR); + + if (!context->task || (context->task == current)) + wrmsrl(MSR_IA32_DS_AREA, 0); + + put_tracer(context->task); + + /* free any leftover buffers from tracers that did not + * deallocate them properly. */ + kfree(context->buffer[ds_bts]); + kfree(context->buffer[ds_pebs]); + kfree(context->ds); + kfree(context); + out: + spin_unlock(&ds_lock); } -static inline unsigned long get_bts_interrupt_threshold(char *base) + + +/* + * Handle a buffer overflow + * + * task: the task whose buffers are overflowing; + * NULL for a buffer overflow on the current cpu + * context: the ds context + * qual: the buffer type + */ +static void ds_overflow(struct task_struct *task, struct ds_context *context, + enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.bts_interrupt_threshold.offset); + if (!context) + return; + + if (context->callback[qual]) + (*context->callback[qual])(task); + + /* todo: do some more overflow handling */ } -static inline void set_bts_interrupt_threshold(char *base, unsigned long value) + + +/* + * Allocate a non-pageable buffer of the parameter size. + * Checks the memory and the locked memory rlimit. + * + * Returns the buffer, if successful; + * NULL, if out of memory or rlimit exceeded. + * + * size: the requested buffer size in bytes + * pages (out): if not NULL, contains the number of pages reserved + */ +static inline void *ds_allocate_buffer(size_t size, unsigned int *pages) { - (*(unsigned long *)(base + ds_cfg.bts_interrupt_threshold.offset)) = value; + unsigned long rlim, vm, pgsz; + void *buffer; + + pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; + + rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; + vm = current->mm->total_vm + pgsz; + if (rlim < vm) + return NULL; + + rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; + vm = current->mm->locked_vm + pgsz; + if (rlim < vm) + return NULL; + + buffer = kzalloc(size, GFP_KERNEL); + if (!buffer) + return NULL; + + current->mm->total_vm += pgsz; + current->mm->locked_vm += pgsz; + + if (pages) + *pages = pgsz; + + return buffer; } -static inline unsigned long get_from_ip(char *base) + +static int ds_request(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl, enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.from_ip.offset); + struct ds_context *context; + unsigned long buffer, adj; + const unsigned long alignment = (1 << 3); + int error = 0; + + if (!ds_cfg.sizeof_ds) + return -EOPNOTSUPP; + + /* we require some space to do alignment adjustments below */ + if (size < (alignment + ds_cfg.sizeof_rec[qual])) + return -EINVAL; + + /* buffer overflow notification is not yet implemented */ + if (ovfl) + return -EOPNOTSUPP; + + + spin_lock(&ds_lock); + + if (!check_tracer(task)) + return -EPERM; + + error = -ENOMEM; + context = ds_alloc_context(task); + if (!context) + goto out_unlock; + + error = -EALREADY; + if (context->owner[qual] == current) + goto out_unlock; + error = -EPERM; + if (context->owner[qual] != NULL) + goto out_unlock; + context->owner[qual] = current; + + spin_unlock(&ds_lock); + + + error = -ENOMEM; + if (!base) { + base = ds_allocate_buffer(size, &context->pages[qual]); + if (!base) + goto out_release; + + context->buffer[qual] = base; + } + error = 0; + + context->callback[qual] = ovfl; + + /* adjust the buffer address and size to meet alignment + * constraints: + * - buffer is double-word aligned + * - size is multiple of record size + * + * We checked the size at the very beginning; we have enough + * space to do the adjustment. + */ + buffer = (unsigned long)base; + + adj = ALIGN(buffer, alignment) - buffer; + buffer += adj; + size -= adj; + + size /= ds_cfg.sizeof_rec[qual]; + size *= ds_cfg.sizeof_rec[qual]; + + ds_set(context->ds, qual, ds_buffer_base, buffer); + ds_set(context->ds, qual, ds_index, buffer); + ds_set(context->ds, qual, ds_absolute_maximum, buffer + size); + + if (ovfl) { + /* todo: select a suitable interrupt threshold */ + } else + ds_set(context->ds, qual, + ds_interrupt_threshold, buffer + size + 1); + + /* we keep the context until ds_release */ + return error; + + out_release: + context->owner[qual] = NULL; + ds_put_context(context); + return error; + + out_unlock: + spin_unlock(&ds_lock); + ds_put_context(context); + return error; } -static inline void set_from_ip(char *base, unsigned long value) + +int ds_request_bts(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl) { - (*(unsigned long *)(base + ds_cfg.from_ip.offset)) = value; + return ds_request(task, base, size, ovfl, ds_bts); } -static inline unsigned long get_to_ip(char *base) + +int ds_request_pebs(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl) { - return *(unsigned long *)(base + ds_cfg.to_ip.offset); + return ds_request(task, base, size, ovfl, ds_pebs); } -static inline void set_to_ip(char *base, unsigned long value) + +static int ds_release(struct task_struct *task, enum ds_qualifier qual) { - (*(unsigned long *)(base + ds_cfg.to_ip.offset)) = value; + struct ds_context *context; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + kfree(context->buffer[qual]); + context->buffer[qual] = NULL; + + current->mm->total_vm -= context->pages[qual]; + current->mm->locked_vm -= context->pages[qual]; + context->pages[qual] = 0; + context->owner[qual] = NULL; + + /* + * we put the context twice: + * once for the ds_get_context + * once for the corresponding ds_request + */ + ds_put_context(context); + out: + ds_put_context(context); + return error; } -static inline unsigned char get_info_type(char *base) + +int ds_release_bts(struct task_struct *task) { - return *(unsigned char *)(base + ds_cfg.info_type.offset); + return ds_release(task, ds_bts); } -static inline void set_info_type(char *base, unsigned char value) + +int ds_release_pebs(struct task_struct *task) { - (*(unsigned char *)(base + ds_cfg.info_type.offset)) = value; + return ds_release(task, ds_pebs); } -static inline unsigned long get_info_data(char *base) + +static int ds_get_index(struct task_struct *task, size_t *pos, + enum ds_qualifier qual) { - return *(unsigned long *)(base + ds_cfg.info_data.offset); + struct ds_context *context; + unsigned long base, index; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + base = ds_get(context->ds, qual, ds_buffer_base); + index = ds_get(context->ds, qual, ds_index); + + error = ((index - base) / ds_cfg.sizeof_rec[qual]); + if (pos) + *pos = error; + out: + ds_put_context(context); + return error; } -static inline void set_info_data(char *base, unsigned long value) + +int ds_get_bts_index(struct task_struct *task, size_t *pos) { - (*(unsigned long *)(base + ds_cfg.info_data.offset)) = value; + return ds_get_index(task, pos, ds_bts); } +int ds_get_pebs_index(struct task_struct *task, size_t *pos) +{ + return ds_get_index(task, pos, ds_pebs); +} -int ds_allocate(void **dsp, size_t bts_size_in_bytes) +static int ds_get_end(struct task_struct *task, size_t *pos, + enum ds_qualifier qual) { - size_t bts_size_in_records; - unsigned long bts; - void *ds; + struct ds_context *context; + unsigned long base, end; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + + base = ds_get(context->ds, qual, ds_buffer_base); + end = ds_get(context->ds, qual, ds_absolute_maximum); + + error = ((end - base) / ds_cfg.sizeof_rec[qual]); + if (pos) + *pos = error; + out: + ds_put_context(context); + return error; +} - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; +int ds_get_bts_end(struct task_struct *task, size_t *pos) +{ + return ds_get_end(task, pos, ds_bts); +} - if (bts_size_in_bytes < 0) - return -EINVAL; +int ds_get_pebs_end(struct task_struct *task, size_t *pos) +{ + return ds_get_end(task, pos, ds_pebs); +} - bts_size_in_records = - bts_size_in_bytes / ds_cfg.sizeof_bts; - bts_size_in_bytes = - bts_size_in_records * ds_cfg.sizeof_bts; +static int ds_access(struct task_struct *task, size_t index, + const void **record, enum ds_qualifier qual) +{ + struct ds_context *context; + unsigned long base, idx; + int error; - if (bts_size_in_bytes <= 0) + if (!record) return -EINVAL; - bts = (unsigned long)kzalloc(bts_size_in_bytes, GFP_KERNEL); - - if (!bts) - return -ENOMEM; + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; - ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); + base = ds_get(context->ds, qual, ds_buffer_base); + idx = base + (index * ds_cfg.sizeof_rec[qual]); - if (!ds) { - kfree((void *)bts); - return -ENOMEM; - } - - set_bts_buffer_base(ds, bts); - set_bts_index(ds, bts); - set_bts_absolute_maximum(ds, bts + bts_size_in_bytes); - set_bts_interrupt_threshold(ds, bts + bts_size_in_bytes + 1); + error = -EINVAL; + if (idx > ds_get(context->ds, qual, ds_absolute_maximum)) + goto out; - *dsp = ds; - return 0; + *record = (const void *)idx; + error = ds_cfg.sizeof_rec[qual]; + out: + ds_put_context(context); + return error; } -int ds_free(void **dsp) +int ds_access_bts(struct task_struct *task, size_t index, const void **record) { - if (*dsp) { - kfree((void *)get_bts_buffer_base(*dsp)); - kfree(*dsp); - *dsp = NULL; - } - return 0; + return ds_access(task, index, record, ds_bts); } -int ds_get_bts_size(void *ds) +int ds_access_pebs(struct task_struct *task, size_t index, const void **record) { - int size_in_bytes; - - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; - - if (!ds) - return 0; - - size_in_bytes = - get_bts_absolute_maximum(ds) - - get_bts_buffer_base(ds); - return size_in_bytes; + return ds_access(task, index, record, ds_pebs); } -int ds_get_bts_end(void *ds) +static int ds_write(struct task_struct *task, const void *record, size_t size, + enum ds_qualifier qual, int force) { - int size_in_bytes = ds_get_bts_size(ds); - - if (size_in_bytes <= 0) - return size_in_bytes; + struct ds_context *context; + int error; - return size_in_bytes / ds_cfg.sizeof_bts; -} + if (!record) + return -EINVAL; -int ds_get_bts_index(void *ds) -{ - int index_offset_in_bytes; + error = -EPERM; + context = ds_get_context(task); + if (!context) + goto out; - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; + if (!force) { + error = ds_validate_access(context, qual); + if (error < 0) + goto out; + } - index_offset_in_bytes = - get_bts_index(ds) - - get_bts_buffer_base(ds); + error = 0; + while (size) { + unsigned long base, index, end, write_end, int_th; + unsigned long write_size, adj_write_size; + + /* + * write as much as possible without producing an + * overflow interrupt. + * + * interrupt_threshold must either be + * - bigger than absolute_maximum or + * - point to a record between buffer_base and absolute_maximum + * + * index points to a valid record. + */ + base = ds_get(context->ds, qual, ds_buffer_base); + index = ds_get(context->ds, qual, ds_index); + end = ds_get(context->ds, qual, ds_absolute_maximum); + int_th = ds_get(context->ds, qual, ds_interrupt_threshold); + + write_end = min(end, int_th); + + /* if we are already beyond the interrupt threshold, + * we fill the entire buffer */ + if (write_end <= index) + write_end = end; + + if (write_end <= index) + goto out; + + write_size = min((unsigned long) size, write_end - index); + memcpy((void *)index, record, write_size); + + record = (const char *)record + write_size; + size -= write_size; + error += write_size; + + adj_write_size = write_size / ds_cfg.sizeof_rec[qual]; + adj_write_size *= ds_cfg.sizeof_rec[qual]; + + /* zero out trailing bytes */ + memset((char *)index + write_size, 0, + adj_write_size - write_size); + index += adj_write_size; + + if (index >= end) + index = base; + ds_set(context->ds, qual, ds_index, index); + + if (index >= int_th) + ds_overflow(task, context, qual); + } - return index_offset_in_bytes / ds_cfg.sizeof_bts; + out: + ds_put_context(context); + return error; } -int ds_set_overflow(void *ds, int method) +int ds_write_bts(struct task_struct *task, const void *record, size_t size) { - switch (method) { - case DS_O_SIGNAL: - return -EOPNOTSUPP; - case DS_O_WRAP: - return 0; - default: - return -EINVAL; - } + return ds_write(task, record, size, ds_bts, /* force = */ 0); } -int ds_get_overflow(void *ds) +int ds_write_pebs(struct task_struct *task, const void *record, size_t size) { - return DS_O_WRAP; + return ds_write(task, record, size, ds_pebs, /* force = */ 0); } -int ds_clear(void *ds) +int ds_unchecked_write_bts(struct task_struct *task, + const void *record, size_t size) { - int bts_size = ds_get_bts_size(ds); - unsigned long bts_base; - - if (bts_size <= 0) - return bts_size; - - bts_base = get_bts_buffer_base(ds); - memset((void *)bts_base, 0, bts_size); - - set_bts_index(ds, bts_base); - return 0; + return ds_write(task, record, size, ds_bts, /* force = */ 1); } -int ds_read_bts(void *ds, int index, struct bts_struct *out) +int ds_unchecked_write_pebs(struct task_struct *task, + const void *record, size_t size) { - void *bts; + return ds_write(task, record, size, ds_pebs, /* force = */ 1); +} - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; +static int ds_reset_or_clear(struct task_struct *task, + enum ds_qualifier qual, int clear) +{ + struct ds_context *context; + unsigned long base, end; + int error; - if (index < 0) - return -EINVAL; + context = ds_get_context(task); + error = ds_validate_access(context, qual); + if (error < 0) + goto out; - if (index >= ds_get_bts_size(ds)) - return -EINVAL; + base = ds_get(context->ds, qual, ds_buffer_base); + end = ds_get(context->ds, qual, ds_absolute_maximum); - bts = (void *)(get_bts_buffer_base(ds) + (index * ds_cfg.sizeof_bts)); + if (clear) + memset((void *)base, 0, end - base); - memset(out, 0, sizeof(*out)); - if (get_from_ip(bts) == BTS_ESCAPE_ADDRESS) { - out->qualifier = get_info_type(bts); - out->variant.jiffies = get_info_data(bts); - } else { - out->qualifier = BTS_BRANCH; - out->variant.lbr.from_ip = get_from_ip(bts); - out->variant.lbr.to_ip = get_to_ip(bts); - } + ds_set(context->ds, qual, ds_index, base); - return sizeof(*out);; + error = 0; + out: + ds_put_context(context); + return error; } -int ds_write_bts(void *ds, const struct bts_struct *in) +int ds_reset_bts(struct task_struct *task) { - unsigned long bts; - - if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts) - return -EOPNOTSUPP; - - if (ds_get_bts_size(ds) <= 0) - return -ENXIO; + return ds_reset_or_clear(task, ds_bts, /* clear = */ 0); +} - bts = get_bts_index(ds); +int ds_reset_pebs(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_pebs, /* clear = */ 0); +} - memset((void *)bts, 0, ds_cfg.sizeof_bts); - switch (in->qualifier) { - case BTS_INVALID: - break; +int ds_clear_bts(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_bts, /* clear = */ 1); +} - case BTS_BRANCH: - set_from_ip((void *)bts, in->variant.lbr.from_ip); - set_to_ip((void *)bts, in->variant.lbr.to_ip); - break; +int ds_clear_pebs(struct task_struct *task) +{ + return ds_reset_or_clear(task, ds_pebs, /* clear = */ 1); +} - case BTS_TASK_ARRIVES: - case BTS_TASK_DEPARTS: - set_from_ip((void *)bts, BTS_ESCAPE_ADDRESS); - set_info_type((void *)bts, in->qualifier); - set_info_data((void *)bts, in->variant.jiffies); - break; +int ds_get_pebs_reset(struct task_struct *task, u64 *value) +{ + struct ds_context *context; + int error; - default: + if (!value) return -EINVAL; - } - bts = bts + ds_cfg.sizeof_bts; - if (bts >= get_bts_absolute_maximum(ds)) - bts = get_bts_buffer_base(ds); - set_bts_index(ds, bts); + context = ds_get_context(task); + error = ds_validate_access(context, ds_pebs); + if (error < 0) + goto out; - return ds_cfg.sizeof_bts; + *value = *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8)); + + error = 0; + out: + ds_put_context(context); + return error; } -unsigned long ds_debugctl_mask(void) +int ds_set_pebs_reset(struct task_struct *task, u64 value) { - return ds_cfg.debugctl_mask; -} + struct ds_context *context; + int error; -#ifdef __i386__ -static const struct ds_configuration ds_cfg_netburst = { - .sizeof_ds = 9 * 4, - .bts_buffer_base = { 0, 4 }, - .bts_index = { 4, 4 }, - .bts_absolute_maximum = { 8, 4 }, - .bts_interrupt_threshold = { 12, 4 }, - .sizeof_bts = 3 * 4, - .from_ip = { 0, 4 }, - .to_ip = { 4, 4 }, - .info_type = { 4, 1 }, - .info_data = { 8, 4 }, - .debugctl_mask = (1<<2)|(1<<3) -}; + context = ds_get_context(task); + error = ds_validate_access(context, ds_pebs); + if (error < 0) + goto out; -static const struct ds_configuration ds_cfg_pentium_m = { - .sizeof_ds = 9 * 4, - .bts_buffer_base = { 0, 4 }, - .bts_index = { 4, 4 }, - .bts_absolute_maximum = { 8, 4 }, - .bts_interrupt_threshold = { 12, 4 }, - .sizeof_bts = 3 * 4, - .from_ip = { 0, 4 }, - .to_ip = { 4, 4 }, - .info_type = { 4, 1 }, - .info_data = { 8, 4 }, - .debugctl_mask = (1<<6)|(1<<7) + *(u64 *)(context->ds + (ds_cfg.sizeof_field * 8)) = value; + + error = 0; + out: + ds_put_context(context); + return error; +} + +static const struct ds_configuration ds_cfg_var = { + .sizeof_ds = sizeof(long) * 12, + .sizeof_field = sizeof(long), + .sizeof_rec[ds_bts] = sizeof(long) * 3, + .sizeof_rec[ds_pebs] = sizeof(long) * 10 }; -#endif /* _i386_ */ - -static const struct ds_configuration ds_cfg_core2 = { - .sizeof_ds = 9 * 8, - .bts_buffer_base = { 0, 8 }, - .bts_index = { 8, 8 }, - .bts_absolute_maximum = { 16, 8 }, - .bts_interrupt_threshold = { 24, 8 }, - .sizeof_bts = 3 * 8, - .from_ip = { 0, 8 }, - .to_ip = { 8, 8 }, - .info_type = { 8, 1 }, - .info_data = { 16, 8 }, - .debugctl_mask = (1<<6)|(1<<7)|(1<<9) +static const struct ds_configuration ds_cfg_64 = { + .sizeof_ds = 8 * 12, + .sizeof_field = 8, + .sizeof_rec[ds_bts] = 8 * 3, + .sizeof_rec[ds_pebs] = 8 * 10 }; static inline void @@ -429,14 +821,13 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) switch (c->x86) { case 0x6: switch (c->x86_model) { -#ifdef __i386__ case 0xD: case 0xE: /* Pentium M */ - ds_configure(&ds_cfg_pentium_m); + ds_configure(&ds_cfg_var); break; -#endif /* _i386_ */ case 0xF: /* Core2 */ - ds_configure(&ds_cfg_core2); + case 0x1C: /* Atom */ + ds_configure(&ds_cfg_64); break; default: /* sorry, don't know about them */ @@ -445,13 +836,11 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) break; case 0xF: switch (c->x86_model) { -#ifdef __i386__ case 0x0: case 0x1: case 0x2: /* Netburst */ - ds_configure(&ds_cfg_netburst); + ds_configure(&ds_cfg_var); break; -#endif /* _i386_ */ default: /* sorry, don't know about them */ break; @@ -462,3 +851,14 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) break; } } + +void ds_free(struct ds_context *context) +{ + /* This is called when the task owning the parameter context + * is dying. There should not be any user of that context left + * to disturb us, anymore. */ + unsigned long leftovers = context->count; + while (leftovers--) + ds_put_context(context); +} +#endif /* CONFIG_X86_DS */ diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 06cc8d4254b1..945a31cdd81f 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -414,9 +414,11 @@ void __init efi_init(void) if (memmap.map == NULL) printk(KERN_ERR "Could not map the EFI memory map!\n"); memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); + if (memmap.desc_size != sizeof(efi_memory_desc_t)) - printk(KERN_WARNING "Kernel-defined memdesc" - "doesn't match the one from EFI!\n"); + printk(KERN_WARNING + "Kernel-defined memdesc doesn't match the one from EFI!\n"); + if (add_efi_memmap) do_add_efi_memmap(); diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 89434d439605..cf3a0b2d0059 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -275,9 +275,9 @@ ENTRY(native_usergs_sysret64) ENTRY(ret_from_fork) CFI_DEFAULT_STACK push kernel_eflags(%rip) - CFI_ADJUST_CFA_OFFSET 4 + CFI_ADJUST_CFA_OFFSET 8 popf # reset kernel eflags - CFI_ADJUST_CFA_OFFSET -4 + CFI_ADJUST_CFA_OFFSET -8 call schedule_tail GET_THREAD_INFO(%rcx) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx) diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 9bfc4d72fb2e..d16084f90649 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -108,12 +108,11 @@ void __init x86_64_start_kernel(char * real_mode_data) } load_idt((const struct desc_ptr *)&idt_descr); - early_printk("Kernel alive\n"); + if (console_loglevel == 10) + early_printk("Kernel alive\n"); x86_64_init_pda(); - early_printk("Kernel really alive\n"); - x86_64_start_reservations(real_mode_data); } diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index 50e5e4a31c85..191914302744 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c @@ -14,6 +14,7 @@ #include <linux/slab.h> #include <linux/thread_info.h> #include <linux/syscalls.h> +#include <asm/syscalls.h> /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ static void set_bitmap(unsigned long *bitmap, unsigned int base, diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c index 3f7537b669d3..f1c688e46f35 100644 --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -20,6 +20,8 @@ #ifdef CONFIG_X86_32 #include <mach_apic.h> +#include <mach_ipi.h> + /* * the following functions deal with sending IPIs between CPUs. * @@ -147,7 +149,6 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector) } /* must come after the send_IPI functions above for inlining */ -#include <mach_ipi.h> static int convert_apicid_to_cpu(int apic_id) { int i; diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 1cf8c1fcc088..b71e02d42f4f 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -325,7 +325,7 @@ skip: for_each_online_cpu(j) seq_printf(p, "%10u ", per_cpu(irq_stat,j).irq_call_count); - seq_printf(p, " function call interrupts\n"); + seq_printf(p, " Function call interrupts\n"); seq_printf(p, "TLB: "); for_each_online_cpu(j) seq_printf(p, "%10u ", diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 1f78b238d8d2..f065fe9071b9 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -129,7 +129,7 @@ skip: seq_printf(p, "CAL: "); for_each_online_cpu(j) seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count); - seq_printf(p, " function call interrupts\n"); + seq_printf(p, " Function call interrupts\n"); seq_printf(p, "TLB: "); for_each_online_cpu(j) seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count); diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 8b7a3cf37d2b..478bca986eca 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -178,7 +178,7 @@ static void kvm_flush_tlb(void) kvm_deferred_mmu_op(&ftlb, sizeof ftlb); } -static void kvm_release_pt(u32 pfn) +static void kvm_release_pt(unsigned long pfn) { struct kvm_mmu_op_release_pt rpt = { .header.op = KVM_MMU_OP_RELEASE_PT, diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index b68e21f06f4f..0ed5f939b905 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -18,6 +18,7 @@ #include <asm/ldt.h> #include <asm/desc.h> #include <asm/mmu_context.h> +#include <asm/syscalls.h> #ifdef CONFIG_SMP static void flush_ldt(void *current_mm) diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index abb78a2cc4ad..2c97f07f1c2c 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -299,6 +299,15 @@ void acpi_nmi_disable(void) on_each_cpu(__acpi_nmi_disable, NULL, 1); } +/* + * This function is called as soon the LAPIC NMI watchdog driver has everything + * in place and it's ready to check if the NMIs belong to the NMI watchdog + */ +void cpu_nmi_set_wd_enabled(void) +{ + __get_cpu_var(wd_enabled) = 1; +} + void setup_apic_nmi_watchdog(void *unused) { if (__get_cpu_var(wd_enabled)) @@ -311,8 +320,6 @@ void setup_apic_nmi_watchdog(void *unused) switch (nmi_watchdog) { case NMI_LOCAL_APIC: - /* enable it before to avoid race with handler */ - __get_cpu_var(wd_enabled) = 1; if (lapic_watchdog_init(nmi_hz) < 0) { __get_cpu_var(wd_enabled) = 0; return; diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c index 3e6672274807..7a13fac63a1f 100644 --- a/arch/x86/kernel/olpc.c +++ b/arch/x86/kernel/olpc.c @@ -190,12 +190,12 @@ EXPORT_SYMBOL_GPL(olpc_ec_cmd); static void __init platform_detect(void) { size_t propsize; - u32 rev; + __be32 rev; if (ofw("getprop", 4, 1, NULL, "board-revision-int", &rev, 4, &propsize) || propsize != 4) { printk(KERN_ERR "ofw: getprop call failed!\n"); - rev = 0; + rev = cpu_to_be32(0); } olpc_platform_info.boardrev = be32_to_cpu(rev); } @@ -203,7 +203,7 @@ static void __init platform_detect(void) static void __init platform_detect(void) { /* stopgap until OFW support is added to the kernel */ - olpc_platform_info.boardrev = be32_to_cpu(0xc2); + olpc_platform_info.boardrev = 0xc2; } #endif diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 300da17e61cb..e2f43768723a 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -330,6 +330,7 @@ struct pv_cpu_ops pv_cpu_ops = { #endif .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, + .read_msr_amd = native_read_msr_amd_safe, .write_msr = native_write_msr_safe, .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, diff --git a/arch/x86/kernel/paravirt_patch_32.c b/arch/x86/kernel/paravirt_patch_32.c index 58262218781b..9fe644f4861d 100644 --- a/arch/x86/kernel/paravirt_patch_32.c +++ b/arch/x86/kernel/paravirt_patch_32.c @@ -23,7 +23,7 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf, start = start_##ops##_##x; \ end = end_##ops##_##x; \ goto patch_site - switch(type) { + switch (type) { PATCH_SITE(pv_irq_ops, irq_disable); PATCH_SITE(pv_irq_ops, irq_enable); PATCH_SITE(pv_irq_ops, restore_fl); diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 87d4d6964ec2..f704cb51ff82 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -82,7 +82,7 @@ void __init dma32_reserve_bootmem(void) * using 512M as goal */ align = 64ULL<<20; - size = round_up(dma32_bootmem_size, align); + size = roundup(dma32_bootmem_size, align); dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align, 512ULL<<20); if (dma32_bootmem_ptr) diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index be33a5442d82..1a895a582534 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -82,7 +82,8 @@ AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ -static unsigned long alloc_iommu(struct device *dev, int size) +static unsigned long alloc_iommu(struct device *dev, int size, + unsigned long align_mask) { unsigned long offset, flags; unsigned long boundary_size; @@ -90,16 +91,17 @@ static unsigned long alloc_iommu(struct device *dev, int size) base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), PAGE_SIZE) >> PAGE_SHIFT; - boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, + boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, PAGE_SIZE) >> PAGE_SHIFT; spin_lock_irqsave(&iommu_bitmap_lock, flags); offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, - size, base_index, boundary_size, 0); + size, base_index, boundary_size, align_mask); if (offset == -1) { need_flush = 1; offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, - size, base_index, boundary_size, 0); + size, base_index, boundary_size, + align_mask); } if (offset != -1) { next_bit = offset+size; @@ -236,10 +238,10 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) * Caller needs to check if the iommu is needed and flush. */ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, - size_t size, int dir) + size_t size, int dir, unsigned long align_mask) { unsigned long npages = iommu_num_pages(phys_mem, size); - unsigned long iommu_page = alloc_iommu(dev, npages); + unsigned long iommu_page = alloc_iommu(dev, npages, align_mask); int i; if (iommu_page == -1) { @@ -262,7 +264,11 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, static dma_addr_t gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir) { - dma_addr_t map = dma_map_area(dev, paddr, size, dir); + dma_addr_t map; + unsigned long align_mask; + + align_mask = (1UL << get_order(size)) - 1; + map = dma_map_area(dev, paddr, size, dir, align_mask); flush_gart(); @@ -281,7 +287,8 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) if (!need_iommu(dev, paddr, size)) return paddr; - bus = gart_map_simple(dev, paddr, size, dir); + bus = dma_map_area(dev, paddr, size, dir, 0); + flush_gart(); return bus; } @@ -340,7 +347,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, unsigned long addr = sg_phys(s); if (nonforced_iommu(dev, addr, s->length)) { - addr = dma_map_area(dev, addr, s->length, dir); + addr = dma_map_area(dev, addr, s->length, dir, 0); if (addr == bad_dma_address) { if (i > 0) gart_unmap_sg(dev, sg, i, dir); @@ -362,7 +369,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, int nelems, struct scatterlist *sout, unsigned long pages) { - unsigned long iommu_start = alloc_iommu(dev, pages); + unsigned long iommu_start = alloc_iommu(dev, pages, 0); unsigned long iommu_page = iommu_start; struct scatterlist *s; int i; diff --git a/arch/x86/kernel/pcspeaker.c b/arch/x86/kernel/pcspeaker.c index bc1f2d3ea277..a311ffcaad16 100644 --- a/arch/x86/kernel/pcspeaker.c +++ b/arch/x86/kernel/pcspeaker.c @@ -1,20 +1,13 @@ #include <linux/platform_device.h> -#include <linux/errno.h> +#include <linux/err.h> #include <linux/init.h> static __init int add_pcspkr(void) { struct platform_device *pd; - int ret; - pd = platform_device_alloc("pcspkr", -1); - if (!pd) - return -ENOMEM; + pd = platform_device_register_simple("pcspkr", -1, NULL, 0); - ret = platform_device_add(pd); - if (ret) - platform_device_put(pd); - - return ret; + return IS_ERR(pd) ? PTR_ERR(pd) : 0; } device_initcall(add_pcspkr); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 876e91890777..ec7a2ba9bce8 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -185,7 +185,8 @@ static void mwait_idle(void) static void poll_idle(void) { local_irq_enable(); - cpu_relax(); + while (!need_resched()) + cpu_relax(); } /* diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 31f40b24bf5d..205188db9626 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -37,6 +37,7 @@ #include <linux/tick.h> #include <linux/percpu.h> #include <linux/prctl.h> +#include <linux/dmi.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -56,6 +57,8 @@ #include <asm/cpu.h> #include <asm/kdebug.h> #include <asm/idle.h> +#include <asm/syscalls.h> +#include <asm/smp.h> asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); @@ -161,6 +164,7 @@ void __show_registers(struct pt_regs *regs, int all) unsigned long d0, d1, d2, d3, d6, d7; unsigned long sp; unsigned short ss, gs; + const char *board; if (user_mode_vm(regs)) { sp = regs->sp; @@ -173,11 +177,15 @@ void __show_registers(struct pt_regs *regs, int all) } printk("\n"); - printk("Pid: %d, comm: %s %s (%s %.*s)\n", + + board = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!board) + board = ""; + printk("Pid: %d, comm: %s %s (%s %.*s) %s\n", task_pid_nr(current), current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); + init_utsname()->version, board); printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", (u16)regs->cs, regs->ip, regs->flags, @@ -277,6 +285,14 @@ void exit_thread(void) tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; put_cpu(); } +#ifdef CONFIG_X86_DS + /* Free any DS contexts that have not been properly released. */ + if (unlikely(current->thread.ds_ctx)) { + /* we clear debugctl to make sure DS is not used. */ + update_debugctlmsr(0); + ds_free(current->thread.ds_ctx); + } +#endif /* CONFIG_X86_DS */ } void flush_thread(void) @@ -438,6 +454,35 @@ int set_tsc_mode(unsigned int val) return 0; } +#ifdef CONFIG_X86_DS +static int update_debugctl(struct thread_struct *prev, + struct thread_struct *next, unsigned long debugctl) +{ + unsigned long ds_prev = 0; + unsigned long ds_next = 0; + + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { + /* we clear debugctl to make sure DS + * is not in use when we change it */ + debugctl = 0; + update_debugctlmsr(0); + wrmsr(MSR_IA32_DS_AREA, ds_next, 0); + } + return debugctl; +} +#else +static int update_debugctl(struct thread_struct *prev, + struct thread_struct *next, unsigned long debugctl) +{ + return debugctl; +} +#endif /* CONFIG_X86_DS */ + static noinline void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, struct tss_struct *tss) @@ -448,14 +493,7 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, prev = &prev_p->thread; next = &next_p->thread; - debugctl = prev->debugctlmsr; - if (next->ds_area_msr != prev->ds_area_msr) { - /* we clear debugctl to make sure DS - * is not in use when we change it */ - debugctl = 0; - update_debugctlmsr(0); - wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0); - } + debugctl = update_debugctl(prev, next, prev->debugctlmsr); if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); @@ -479,13 +517,13 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, hard_enable_TSC(); } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e12e0e4dd256..2a8ccb9238b4 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -37,11 +37,11 @@ #include <linux/kdebug.h> #include <linux/tick.h> #include <linux/prctl.h> +#include <linux/uaccess.h> +#include <linux/io.h> -#include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/system.h> -#include <asm/io.h> #include <asm/processor.h> #include <asm/i387.h> #include <asm/mmu_context.h> @@ -51,6 +51,7 @@ #include <asm/proto.h> #include <asm/ia32.h> #include <asm/idle.h> +#include <asm/syscalls.h> asmlinkage extern void ret_from_fork(void); @@ -88,7 +89,7 @@ void exit_idle(void) #ifdef CONFIG_HOTPLUG_CPU DECLARE_PER_CPU(int, cpu_state); -#include <asm/nmi.h> +#include <linux/nmi.h> /* We halt the CPU with physical CPU hotplug */ static inline void play_dead(void) { @@ -153,7 +154,7 @@ void cpu_idle(void) } /* Prints also some state that isn't saved in the pt_regs */ -void __show_regs(struct pt_regs * regs) +void __show_regs(struct pt_regs *regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; unsigned long d0, d1, d2, d3, d6, d7; @@ -162,59 +163,61 @@ void __show_regs(struct pt_regs * regs) printk("\n"); print_modules(); - printk("Pid: %d, comm: %.20s %s %s %.*s\n", + printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n", current->pid, current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); - printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); + printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); printk_address(regs->ip, 1); - printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->sp, - regs->flags); - printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", + printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, + regs->sp, regs->flags); + printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", regs->ax, regs->bx, regs->cx); - printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", + printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n", regs->dx, regs->si, regs->di); - printk("RBP: %016lx R08: %016lx R09: %016lx\n", + printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n", regs->bp, regs->r8, regs->r9); - printk("R10: %016lx R11: %016lx R12: %016lx\n", - regs->r10, regs->r11, regs->r12); - printk("R13: %016lx R14: %016lx R15: %016lx\n", - regs->r13, regs->r14, regs->r15); - - asm("movl %%ds,%0" : "=r" (ds)); - asm("movl %%cs,%0" : "=r" (cs)); - asm("movl %%es,%0" : "=r" (es)); + printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n", + regs->r10, regs->r11, regs->r12); + printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n", + regs->r13, regs->r14, regs->r15); + + asm("movl %%ds,%0" : "=r" (ds)); + asm("movl %%cs,%0" : "=r" (cs)); + asm("movl %%es,%0" : "=r" (es)); asm("movl %%fs,%0" : "=r" (fsindex)); asm("movl %%gs,%0" : "=r" (gsindex)); rdmsrl(MSR_FS_BASE, fs); - rdmsrl(MSR_GS_BASE, gs); - rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); + rdmsrl(MSR_GS_BASE, gs); + rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); cr4 = read_cr4(); - printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", - fs,fsindex,gs,gsindex,shadowgs); - printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); - printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4); + printk(KERN_INFO "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", + fs, fsindex, gs, gsindex, shadowgs); + printk(KERN_INFO "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, + es, cr0); + printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, + cr4); get_debugreg(d0, 0); get_debugreg(d1, 1); get_debugreg(d2, 2); - printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); + printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); get_debugreg(d3, 3); get_debugreg(d6, 6); get_debugreg(d7, 7); - printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); + printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); } void show_regs(struct pt_regs *regs) { - printk("CPU %d:", smp_processor_id()); + printk(KERN_INFO "CPU %d:", smp_processor_id()); __show_regs(regs); show_trace(NULL, regs, (void *)(regs + 1), regs->bp); } @@ -240,6 +243,14 @@ void exit_thread(void) t->io_bitmap_max = 0; put_cpu(); } +#ifdef CONFIG_X86_DS + /* Free any DS contexts that have not been properly released. */ + if (unlikely(t->ds_ctx)) { + /* we clear debugctl to make sure DS is not used. */ + update_debugctlmsr(0); + ds_free(t->ds_ctx); + } +#endif /* CONFIG_X86_DS */ } void flush_thread(void) @@ -315,10 +326,10 @@ void prepare_to_copy(struct task_struct *tsk) int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long unused, - struct task_struct * p, struct pt_regs * regs) + struct task_struct *p, struct pt_regs *regs) { int err; - struct pt_regs * childregs; + struct pt_regs *childregs; struct task_struct *me = current; childregs = ((struct pt_regs *) @@ -363,10 +374,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, if (test_thread_flag(TIF_IA32)) err = do_set_thread_area(p, -1, (struct user_desc __user *)childregs->si, 0); - else -#endif - err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); - if (err) + else +#endif + err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); + if (err) goto out; } err = 0; @@ -473,13 +484,27 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, next = &next_p->thread; debugctl = prev->debugctlmsr; - if (next->ds_area_msr != prev->ds_area_msr) { - /* we clear debugctl to make sure DS - * is not in use when we change it */ - debugctl = 0; - update_debugctlmsr(0); - wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr); + +#ifdef CONFIG_X86_DS + { + unsigned long ds_prev = 0, ds_next = 0; + + if (prev->ds_ctx) + ds_prev = (unsigned long)prev->ds_ctx->ds; + if (next->ds_ctx) + ds_next = (unsigned long)next->ds_ctx->ds; + + if (ds_next != ds_prev) { + /* + * We clear debugctl to make sure DS + * is not in use when we change it: + */ + debugctl = 0; + update_debugctlmsr(0); + wrmsrl(MSR_IA32_DS_AREA, ds_next); + } } +#endif /* CONFIG_X86_DS */ if (next->debugctlmsr != debugctl) update_debugctlmsr(next->debugctlmsr); @@ -517,13 +542,13 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS); if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS)) ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES); -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ } /* @@ -545,7 +570,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) unsigned fsindex, gsindex; /* we're going to use this soon, after a few expensive things */ - if (next_p->fpu_counter>5) + if (next_p->fpu_counter > 5) prefetch(next->xstate); /* @@ -553,13 +578,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ load_sp0(tss, next); - /* + /* * Switch DS and ES. * This won't pick up thread selector changes, but I guess that is ok. */ savesegment(es, prev->es); if (unlikely(next->es | prev->es)) - loadsegment(es, next->es); + loadsegment(es, next->es); savesegment(ds, prev->ds); if (unlikely(next->ds | prev->ds)) @@ -585,7 +610,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ arch_leave_lazy_cpu_mode(); - /* + /* * Switch FS and GS. * * Segment register != 0 always requires a reload. Also @@ -594,13 +619,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ if (unlikely(fsindex | next->fsindex | prev->fs)) { loadsegment(fs, next->fsindex); - /* + /* * Check if the user used a selector != 0; if yes * clear 64bit base, since overloaded base is always * mapped to the Null selector */ if (fsindex) - prev->fs = 0; + prev->fs = 0; } /* when next process has a 64bit base use it */ if (next->fs) @@ -610,7 +635,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) if (unlikely(gsindex | next->gsindex | prev->gs)) { load_gs_index(next->gsindex); if (gsindex) - prev->gs = 0; + prev->gs = 0; } if (next->gs) wrmsrl(MSR_KERNEL_GS_BASE, next->gs); @@ -619,12 +644,12 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* Must be after DS reload */ unlazy_fpu(prev_p); - /* + /* * Switch the PDA and FPU contexts. */ prev->usersp = read_pda(oldrsp); write_pda(oldrsp, next->usersp); - write_pda(pcurrent, next_p); + write_pda(pcurrent, next_p); write_pda(kernelstack, (unsigned long)task_stack_page(next_p) + @@ -665,7 +690,7 @@ long sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp, struct pt_regs *regs) { long error; - char * filename; + char *filename; filename = getname(name); error = PTR_ERR(filename); @@ -723,55 +748,55 @@ asmlinkage long sys_vfork(struct pt_regs *regs) unsigned long get_wchan(struct task_struct *p) { unsigned long stack; - u64 fp,ip; + u64 fp, ip; int count = 0; - if (!p || p == current || p->state==TASK_RUNNING) - return 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; stack = (unsigned long)task_stack_page(p); if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.sp); - do { + do { if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) - return 0; + return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) return ip; - fp = *(u64 *)fp; - } while (count++ < 16); + fp = *(u64 *)fp; + } while (count++ < 16); return 0; } long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) -{ - int ret = 0; +{ + int ret = 0; int doit = task == current; int cpu; - switch (code) { + switch (code) { case ARCH_SET_GS: if (addr >= TASK_SIZE_OF(task)) - return -EPERM; + return -EPERM; cpu = get_cpu(); - /* handle small bases via the GDT because that's faster to + /* handle small bases via the GDT because that's faster to switch. */ - if (addr <= 0xffffffff) { - set_32bit_tls(task, GS_TLS, addr); - if (doit) { + if (addr <= 0xffffffff) { + set_32bit_tls(task, GS_TLS, addr); + if (doit) { load_TLS(&task->thread, cpu); - load_gs_index(GS_TLS_SEL); + load_gs_index(GS_TLS_SEL); } - task->thread.gsindex = GS_TLS_SEL; + task->thread.gsindex = GS_TLS_SEL; task->thread.gs = 0; - } else { + } else { task->thread.gsindex = 0; task->thread.gs = addr; if (doit) { load_gs_index(0); ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); - } + } } put_cpu(); break; @@ -825,8 +850,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) rdmsrl(MSR_KERNEL_GS_BASE, base); else base = task->thread.gs; - } - else + } else base = task->thread.gs; ret = put_user(base, (unsigned long __user *)addr); break; diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e37dccce85db..e375b658efc3 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -14,6 +14,7 @@ #include <linux/errno.h> #include <linux/ptrace.h> #include <linux/regset.h> +#include <linux/tracehook.h> #include <linux/user.h> #include <linux/elf.h> #include <linux/security.h> @@ -69,7 +70,7 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 -static long *pt_regs_access(struct pt_regs *regs, unsigned long regno) +static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); regno >>= 2; @@ -554,45 +555,115 @@ static int ptrace_set_debugreg(struct task_struct *child, return 0; } -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS +/* + * The configuration for a particular BTS hardware implementation. + */ +struct bts_configuration { + /* the size of a BTS record in bytes; at most BTS_MAX_RECORD_SIZE */ + unsigned char sizeof_bts; + /* the size of a field in the BTS record in bytes */ + unsigned char sizeof_field; + /* a bitmask to enable/disable BTS in DEBUGCTL MSR */ + unsigned long debugctl_mask; +}; +static struct bts_configuration bts_cfg; + +#define BTS_MAX_RECORD_SIZE (8 * 3) + + +/* + * Branch Trace Store (BTS) uses the following format. Different + * architectures vary in the size of those fields. + * - source linear address + * - destination linear address + * - flags + * + * Later architectures use 64bit pointers throughout, whereas earlier + * architectures use 32bit pointers in 32bit mode. + * + * We compute the base address for the first 8 fields based on: + * - the field size stored in the DS configuration + * - the relative field position + * + * In order to store additional information in the BTS buffer, we use + * a special source address to indicate that the record requires + * special interpretation. + * + * Netburst indicated via a bit in the flags field whether the branch + * was predicted; this is ignored. + */ + +enum bts_field { + bts_from = 0, + bts_to, + bts_flags, + + bts_escape = (unsigned long)-1, + bts_qual = bts_to, + bts_jiffies = bts_flags +}; + +static inline unsigned long bts_get(const char *base, enum bts_field field) +{ + base += (bts_cfg.sizeof_field * field); + return *(unsigned long *)base; +} -static int ptrace_bts_get_size(struct task_struct *child) +static inline void bts_set(char *base, enum bts_field field, unsigned long val) { - if (!child->thread.ds_area_msr) - return -ENXIO; + base += (bts_cfg.sizeof_field * field);; + (*(unsigned long *)base) = val; +} - return ds_get_bts_index((void *)child->thread.ds_area_msr); +/* + * Translate a BTS record from the raw format into the bts_struct format + * + * out (out): bts_struct interpretation + * raw: raw BTS record + */ +static void ptrace_bts_translate_record(struct bts_struct *out, const void *raw) +{ + memset(out, 0, sizeof(*out)); + if (bts_get(raw, bts_from) == bts_escape) { + out->qualifier = bts_get(raw, bts_qual); + out->variant.jiffies = bts_get(raw, bts_jiffies); + } else { + out->qualifier = BTS_BRANCH; + out->variant.lbr.from_ip = bts_get(raw, bts_from); + out->variant.lbr.to_ip = bts_get(raw, bts_to); + } } -static int ptrace_bts_read_record(struct task_struct *child, - long index, +static int ptrace_bts_read_record(struct task_struct *child, size_t index, struct bts_struct __user *out) { struct bts_struct ret; - int retval; - int bts_end; - int bts_index; - - if (!child->thread.ds_area_msr) - return -ENXIO; + const void *bts_record; + size_t bts_index, bts_end; + int error; - if (index < 0) - return -EINVAL; + error = ds_get_bts_end(child, &bts_end); + if (error < 0) + return error; - bts_end = ds_get_bts_end((void *)child->thread.ds_area_msr); if (bts_end <= index) return -EINVAL; + error = ds_get_bts_index(child, &bts_index); + if (error < 0) + return error; + /* translate the ptrace bts index into the ds bts index */ - bts_index = ds_get_bts_index((void *)child->thread.ds_area_msr); - bts_index -= (index + 1); - if (bts_index < 0) - bts_index += bts_end; + bts_index += bts_end - (index + 1); + if (bts_end <= bts_index) + bts_index -= bts_end; - retval = ds_read_bts((void *)child->thread.ds_area_msr, - bts_index, &ret); - if (retval < 0) - return retval; + error = ds_access_bts(child, bts_index, &bts_record); + if (error < 0) + return error; + + ptrace_bts_translate_record(&ret, bts_record); if (copy_to_user(out, &ret, sizeof(ret))) return -EFAULT; @@ -600,101 +671,106 @@ static int ptrace_bts_read_record(struct task_struct *child, return sizeof(ret); } -static int ptrace_bts_clear(struct task_struct *child) -{ - if (!child->thread.ds_area_msr) - return -ENXIO; - - return ds_clear((void *)child->thread.ds_area_msr); -} - static int ptrace_bts_drain(struct task_struct *child, long size, struct bts_struct __user *out) { - int end, i; - void *ds = (void *)child->thread.ds_area_msr; - - if (!ds) - return -ENXIO; + struct bts_struct ret; + const unsigned char *raw; + size_t end, i; + int error; - end = ds_get_bts_index(ds); - if (end <= 0) - return end; + error = ds_get_bts_index(child, &end); + if (error < 0) + return error; if (size < (end * sizeof(struct bts_struct))) return -EIO; - for (i = 0; i < end; i++, out++) { - struct bts_struct ret; - int retval; + error = ds_access_bts(child, 0, (const void **)&raw); + if (error < 0) + return error; - retval = ds_read_bts(ds, i, &ret); - if (retval < 0) - return retval; + for (i = 0; i < end; i++, out++, raw += bts_cfg.sizeof_bts) { + ptrace_bts_translate_record(&ret, raw); if (copy_to_user(out, &ret, sizeof(ret))) return -EFAULT; } - ds_clear(ds); + error = ds_clear_bts(child); + if (error < 0) + return error; return end; } +static void ptrace_bts_ovfl(struct task_struct *child) +{ + send_sig(child->thread.bts_ovfl_signal, child, 0); +} + static int ptrace_bts_config(struct task_struct *child, long cfg_size, const struct ptrace_bts_config __user *ucfg) { struct ptrace_bts_config cfg; - int bts_size, ret = 0; - void *ds; + int error = 0; + + error = -EOPNOTSUPP; + if (!bts_cfg.sizeof_bts) + goto errout; + error = -EIO; if (cfg_size < sizeof(cfg)) - return -EIO; + goto errout; + error = -EFAULT; if (copy_from_user(&cfg, ucfg, sizeof(cfg))) - return -EFAULT; + goto errout; - if ((int)cfg.size < 0) - return -EINVAL; + error = -EINVAL; + if ((cfg.flags & PTRACE_BTS_O_SIGNAL) && + !(cfg.flags & PTRACE_BTS_O_ALLOC)) + goto errout; - bts_size = 0; - ds = (void *)child->thread.ds_area_msr; - if (ds) { - bts_size = ds_get_bts_size(ds); - if (bts_size < 0) - return bts_size; - } - cfg.size = PAGE_ALIGN(cfg.size); + if (cfg.flags & PTRACE_BTS_O_ALLOC) { + ds_ovfl_callback_t ovfl = NULL; + unsigned int sig = 0; + + /* we ignore the error in case we were not tracing child */ + (void)ds_release_bts(child); - if (bts_size != cfg.size) { - ret = ptrace_bts_realloc(child, cfg.size, - cfg.flags & PTRACE_BTS_O_CUT_SIZE); - if (ret < 0) + if (cfg.flags & PTRACE_BTS_O_SIGNAL) { + if (!cfg.signal) + goto errout; + + sig = cfg.signal; + ovfl = ptrace_bts_ovfl; + } + + error = ds_request_bts(child, /* base = */ NULL, cfg.size, ovfl); + if (error < 0) goto errout; - ds = (void *)child->thread.ds_area_msr; + child->thread.bts_ovfl_signal = sig; } - if (cfg.flags & PTRACE_BTS_O_SIGNAL) - ret = ds_set_overflow(ds, DS_O_SIGNAL); - else - ret = ds_set_overflow(ds, DS_O_WRAP); - if (ret < 0) + error = -EINVAL; + if (!child->thread.ds_ctx && cfg.flags) goto errout; if (cfg.flags & PTRACE_BTS_O_TRACE) - child->thread.debugctlmsr |= ds_debugctl_mask(); + child->thread.debugctlmsr |= bts_cfg.debugctl_mask; else - child->thread.debugctlmsr &= ~ds_debugctl_mask(); + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; if (cfg.flags & PTRACE_BTS_O_SCHED) set_tsk_thread_flag(child, TIF_BTS_TRACE_TS); else clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); - ret = sizeof(cfg); + error = sizeof(cfg); out: if (child->thread.debugctlmsr) @@ -702,10 +778,10 @@ out: else clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - return ret; + return error; errout: - child->thread.debugctlmsr &= ~ds_debugctl_mask(); + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); goto out; } @@ -714,29 +790,40 @@ static int ptrace_bts_status(struct task_struct *child, long cfg_size, struct ptrace_bts_config __user *ucfg) { - void *ds = (void *)child->thread.ds_area_msr; struct ptrace_bts_config cfg; + size_t end; + const void *base, *max; + int error; if (cfg_size < sizeof(cfg)) return -EIO; - memset(&cfg, 0, sizeof(cfg)); + error = ds_get_bts_end(child, &end); + if (error < 0) + return error; - if (ds) { - cfg.size = ds_get_bts_size(ds); + error = ds_access_bts(child, /* index = */ 0, &base); + if (error < 0) + return error; - if (ds_get_overflow(ds) == DS_O_SIGNAL) - cfg.flags |= PTRACE_BTS_O_SIGNAL; + error = ds_access_bts(child, /* index = */ end, &max); + if (error < 0) + return error; - if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && - child->thread.debugctlmsr & ds_debugctl_mask()) - cfg.flags |= PTRACE_BTS_O_TRACE; + memset(&cfg, 0, sizeof(cfg)); + cfg.size = (max - base); + cfg.signal = child->thread.bts_ovfl_signal; + cfg.bts_size = sizeof(struct bts_struct); - if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) - cfg.flags |= PTRACE_BTS_O_SCHED; - } + if (cfg.signal) + cfg.flags |= PTRACE_BTS_O_SIGNAL; - cfg.bts_size = sizeof(struct bts_struct); + if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && + child->thread.debugctlmsr & bts_cfg.debugctl_mask) + cfg.flags |= PTRACE_BTS_O_TRACE; + + if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) + cfg.flags |= PTRACE_BTS_O_SCHED; if (copy_to_user(ucfg, &cfg, sizeof(cfg))) return -EFAULT; @@ -744,89 +831,38 @@ static int ptrace_bts_status(struct task_struct *child, return sizeof(cfg); } - static int ptrace_bts_write_record(struct task_struct *child, const struct bts_struct *in) { - int retval; + unsigned char bts_record[BTS_MAX_RECORD_SIZE]; - if (!child->thread.ds_area_msr) - return -ENXIO; + BUG_ON(BTS_MAX_RECORD_SIZE < bts_cfg.sizeof_bts); - retval = ds_write_bts((void *)child->thread.ds_area_msr, in); - if (retval) - return retval; + memset(bts_record, 0, bts_cfg.sizeof_bts); + switch (in->qualifier) { + case BTS_INVALID: + break; - return sizeof(*in); -} + case BTS_BRANCH: + bts_set(bts_record, bts_from, in->variant.lbr.from_ip); + bts_set(bts_record, bts_to, in->variant.lbr.to_ip); + break; -static int ptrace_bts_realloc(struct task_struct *child, - int size, int reduce_size) -{ - unsigned long rlim, vm; - int ret, old_size; + case BTS_TASK_ARRIVES: + case BTS_TASK_DEPARTS: + bts_set(bts_record, bts_from, bts_escape); + bts_set(bts_record, bts_qual, in->qualifier); + bts_set(bts_record, bts_jiffies, in->variant.jiffies); + break; - if (size < 0) + default: return -EINVAL; - - old_size = ds_get_bts_size((void *)child->thread.ds_area_msr); - if (old_size < 0) - return old_size; - - ret = ds_free((void **)&child->thread.ds_area_msr); - if (ret < 0) - goto out; - - size >>= PAGE_SHIFT; - old_size >>= PAGE_SHIFT; - - current->mm->total_vm -= old_size; - current->mm->locked_vm -= old_size; - - if (size == 0) - goto out; - - rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; - vm = current->mm->total_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->total_vm; - if (size <= 0) - goto out; - } - - rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; - vm = current->mm->locked_vm + size; - if (rlim < vm) { - ret = -ENOMEM; - - if (!reduce_size) - goto out; - - size = rlim - current->mm->locked_vm; - if (size <= 0) - goto out; } - ret = ds_allocate((void **)&child->thread.ds_area_msr, - size << PAGE_SHIFT); - if (ret < 0) - goto out; - - current->mm->total_vm += size; - current->mm->locked_vm += size; - -out: - if (child->thread.ds_area_msr) - set_tsk_thread_flag(child, TIF_DS_AREA_MSR); - else - clear_tsk_thread_flag(child, TIF_DS_AREA_MSR); - - return ret; + /* The writing task will be the switched-to task on a context + * switch. It needs to write into the switched-from task's BTS + * buffer. */ + return ds_unchecked_write_bts(child, bts_record, bts_cfg.sizeof_bts); } void ptrace_bts_take_timestamp(struct task_struct *tsk, @@ -839,7 +875,66 @@ void ptrace_bts_take_timestamp(struct task_struct *tsk, ptrace_bts_write_record(tsk, &rec); } -#endif /* X86_BTS */ + +static const struct bts_configuration bts_cfg_netburst = { + .sizeof_bts = sizeof(long) * 3, + .sizeof_field = sizeof(long), + .debugctl_mask = (1<<2)|(1<<3)|(1<<5) +}; + +static const struct bts_configuration bts_cfg_pentium_m = { + .sizeof_bts = sizeof(long) * 3, + .sizeof_field = sizeof(long), + .debugctl_mask = (1<<6)|(1<<7) +}; + +static const struct bts_configuration bts_cfg_core2 = { + .sizeof_bts = 8 * 3, + .sizeof_field = 8, + .debugctl_mask = (1<<6)|(1<<7)|(1<<9) +}; + +static inline void bts_configure(const struct bts_configuration *cfg) +{ + bts_cfg = *cfg; +} + +void __cpuinit ptrace_bts_init_intel(struct cpuinfo_x86 *c) +{ + switch (c->x86) { + case 0x6: + switch (c->x86_model) { + case 0xD: + case 0xE: /* Pentium M */ + bts_configure(&bts_cfg_pentium_m); + break; + case 0xF: /* Core2 */ + case 0x1C: /* Atom */ + bts_configure(&bts_cfg_core2); + break; + default: + /* sorry, don't know about them */ + break; + } + break; + case 0xF: + switch (c->x86_model) { + case 0x0: + case 0x1: + case 0x2: /* Netburst */ + bts_configure(&bts_cfg_netburst); + break; + default: + /* sorry, don't know about them */ + break; + } + break; + default: + /* sorry, don't know about them */ + break; + } +} +#endif /* CONFIG_X86_PTRACE_BTS */ /* * Called by kernel/ptrace.c when detaching.. @@ -852,15 +947,15 @@ void ptrace_disable(struct task_struct *child) #ifdef TIF_SYSCALL_EMU clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); #endif - if (child->thread.ds_area_msr) { -#ifdef X86_BTS - ptrace_bts_realloc(child, 0, 0); -#endif - child->thread.debugctlmsr &= ~ds_debugctl_mask(); - if (!child->thread.debugctlmsr) - clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); - } +#ifdef CONFIG_X86_PTRACE_BTS + (void)ds_release_bts(child); + + child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; + if (!child->thread.debugctlmsr) + clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); + + clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); +#endif /* CONFIG_X86_PTRACE_BTS */ } #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION @@ -980,7 +1075,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) /* * These bits need more cooking - not enabled yet: */ -#ifdef X86_BTS +#ifdef CONFIG_X86_PTRACE_BTS case PTRACE_BTS_CONFIG: ret = ptrace_bts_config (child, data, (struct ptrace_bts_config __user *)addr); @@ -992,7 +1087,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_BTS_SIZE: - ret = ptrace_bts_get_size(child); + ret = ds_get_bts_index(child, /* pos = */ NULL); break; case PTRACE_BTS_GET: @@ -1001,14 +1096,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_BTS_CLEAR: - ret = ptrace_bts_clear(child); + ret = ds_clear_bts(child); break; case PTRACE_BTS_DRAIN: ret = ptrace_bts_drain (child, data, (struct bts_struct __user *) addr); break; -#endif +#endif /* CONFIG_X86_PTRACE_BTS */ default: ret = ptrace_request(child, request, addr, data); @@ -1375,30 +1470,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) force_sig_info(SIGTRAP, &info, tsk); } -static void syscall_trace(struct pt_regs *regs) -{ - if (!(current->ptrace & PT_PTRACED)) - return; - -#if 0 - printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n", - current->comm, - regs->ip, regs->sp, regs->ax, regs->orig_ax, __builtin_return_address(0), - current_thread_info()->flags, current->ptrace); -#endif - - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} #ifdef CONFIG_X86_32 # define IS_IA32 1 @@ -1432,8 +1503,9 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs) if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) ret = -1L; - if (ret || test_thread_flag(TIF_SYSCALL_TRACE)) - syscall_trace(regs); + if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) && + tracehook_report_syscall_entry(regs)) + ret = -1L; if (unlikely(current->audit_context)) { if (IS_IA32) @@ -1459,7 +1531,7 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (test_thread_flag(TIF_SYSCALL_TRACE)) - syscall_trace(regs); + tracehook_report_syscall_exit(regs, 0); /* * If TIF_SYSCALL_EMU is set, we only get here because of @@ -1475,6 +1547,6 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) * system call instruction. */ if (test_thread_flag(TIF_SINGLESTEP) && - (current->ptrace & PT_PTRACED)) + tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) send_sigtrap(current, regs, 0); } diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 724adfc63cb9..f4c93f1cfc19 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -29,7 +29,11 @@ EXPORT_SYMBOL(pm_power_off); static const struct desc_ptr no_idt = {}; static int reboot_mode; -enum reboot_type reboot_type = BOOT_KBD; +/* + * Keyboard reset and triple fault may result in INIT, not RESET, which + * doesn't work when we're in vmx root mode. Try ACPI first. + */ +enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9838f2539dfc..141efab52400 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -223,6 +223,9 @@ unsigned long saved_video_mode; #define RAMDISK_LOAD_FLAG 0x4000 static char __initdata command_line[COMMAND_LINE_SIZE]; +#ifdef CONFIG_CMDLINE_BOOL +static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; +#endif #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) struct edd edd; @@ -665,6 +668,19 @@ void __init setup_arch(char **cmdline_p) bss_resource.start = virt_to_phys(&__bss_start); bss_resource.end = virt_to_phys(&__bss_stop)-1; +#ifdef CONFIG_CMDLINE_BOOL +#ifdef CONFIG_CMDLINE_OVERRIDE + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); +#else + if (builtin_cmdline[0]) { + /* append boot loader cmdline to builtin */ + strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); + strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + } +#endif +#endif + strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 76e305e064f9..0e67f72d9316 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -162,9 +162,16 @@ void __init setup_per_cpu_areas(void) printk(KERN_INFO "cpu %d has no node %d or node-local memory\n", cpu, node); + if (ptr) + printk(KERN_DEBUG "per cpu data for cpu%d at %016lx\n", + cpu, __pa(ptr)); } - else + else { ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); + if (ptr) + printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n", + cpu, node, __pa(ptr)); + } #endif per_cpu_offset(cpu) = ptr - __per_cpu_start; memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h index 72bbb519d2dc..8b4956e800ac 100644 --- a/arch/x86/kernel/sigframe.h +++ b/arch/x86/kernel/sigframe.h @@ -24,4 +24,9 @@ struct rt_sigframe { struct ucontext uc; struct siginfo info; }; + +int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs); +int ia32_setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs); #endif diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd8933..2a2435d3037d 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/sched.h> #include <linux/wait.h> +#include <linux/tracehook.h> #include <linux/elf.h> #include <linux/smp.h> #include <linux/mm.h> @@ -26,6 +27,7 @@ #include <asm/uaccess.h> #include <asm/i387.h> #include <asm/vdso.h> +#include <asm/syscalls.h> #include "sigframe.h" @@ -558,8 +560,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * handler too. */ regs->flags &= ~X86_EFLAGS_TF; - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); @@ -568,6 +568,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + return 0; } @@ -661,5 +664,10 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } + clear_thread_flag(TIF_IRET); } diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index ca316b5b742c..694aa888bb19 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -15,17 +15,21 @@ #include <linux/errno.h> #include <linux/wait.h> #include <linux/ptrace.h> +#include <linux/tracehook.h> #include <linux/unistd.h> #include <linux/stddef.h> #include <linux/personality.h> #include <linux/compiler.h> +#include <linux/uaccess.h> + #include <asm/processor.h> #include <asm/ucontext.h> -#include <asm/uaccess.h> #include <asm/i387.h> #include <asm/proto.h> #include <asm/ia32_unistd.h> #include <asm/mce.h> +#include <asm/syscall.h> +#include <asm/syscalls.h> #include "sigframe.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -41,11 +45,6 @@ # define FIX_EFLAGS __FIX_EFLAGS #endif -int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs); -int ia32_setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs * regs); - asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) @@ -128,7 +127,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; -#define COPY(x) err |= __get_user(regs->x, &sc->x) +#define COPY(x) (err |= __get_user(regs->x, &sc->x)) COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(dx); COPY(cx); COPY(ip); @@ -158,7 +157,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, } { - struct _fpstate __user * buf; + struct _fpstate __user *buf; err |= __get_user(buf, &sc->fpstate); if (buf) { @@ -198,7 +197,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) goto badframe; @@ -208,16 +207,17 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) return ax; badframe: - signal_fault(regs,frame,"sigreturn"); + signal_fault(regs, frame, "sigreturn"); return 0; -} +} /* * Set up a signal frame. */ static inline int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, + unsigned long mask, struct task_struct *me) { int err = 0; @@ -273,35 +273,35 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) } static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs) + sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; - struct _fpstate __user *fp = NULL; + struct _fpstate __user *fp = NULL; int err = 0; struct task_struct *me = current; if (used_math()) { - fp = get_stack(ka, regs, sizeof(struct _fpstate)); + fp = get_stack(ka, regs, sizeof(struct _fpstate)); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; - if (save_i387(fp) < 0) - err |= -1; + if (save_i387(fp) < 0) + err |= -1; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - if (ka->sa.sa_flags & SA_SIGINFO) { + if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; } - + /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); @@ -311,9 +311,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); - if (sizeof(*set) == 16) { + if (sizeof(*set) == 16) { __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); - __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); + __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); } else err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -324,7 +324,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { /* could use a vstub here */ - goto give_sigsegv; + goto give_sigsegv; } if (err) @@ -332,7 +332,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->di = sig; - /* In case the signal handler was declared without prototypes */ + /* In case the signal handler was declared without prototypes */ regs->ax = 0; /* This also works for non SA_SIGINFO handlers because they expect the @@ -355,37 +355,8 @@ give_sigsegv: } /* - * Return -1L or the syscall number that @regs is executing. - */ -static long current_syscall(struct pt_regs *regs) -{ - /* - * We always sign-extend a -1 value being set here, - * so this is always either -1L or a syscall number. - */ - return regs->orig_ax; -} - -/* - * Return a value that is -EFOO if the system call in @regs->orig_ax - * returned an error. This only works for @regs from @current. - */ -static long current_syscall_ret(struct pt_regs *regs) -{ -#ifdef CONFIG_IA32_EMULATION - if (test_thread_flag(TIF_IA32)) - /* - * Sign-extend the value so (int)-EFOO becomes (long)-EFOO - * and will match correctly in comparisons. - */ - return (int) regs->ax; -#endif - return regs->ax; -} - -/* * OK, we're invoking a handler - */ + */ static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, @@ -394,9 +365,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, int ret; /* Are we from a system call? */ - if (current_syscall(regs) >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* If so, check system call restarting.. */ - switch (current_syscall_ret(regs)) { + switch (syscall_get_error(current, regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->ax = -EINTR; @@ -429,7 +400,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); else ret = ia32_setup_frame(sig, ka, oldset, regs); - } else + } else #endif ret = setup_rt_frame(sig, ka, info, oldset, regs); @@ -453,15 +424,16 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * handler too. */ regs->flags &= ~X86_EFLAGS_TF; - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); + sigaddset(¤t->blocked, sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); } return ret; @@ -518,9 +490,9 @@ static void do_signal(struct pt_regs *regs) } /* Did we come from a system call? */ - if (current_syscall(regs) >= 0) { + if (syscall_get_nr(current, regs) >= 0) { /* Restart the system call - no handlers present */ - switch (current_syscall_ret(regs)) { + switch (syscall_get_error(current, regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: @@ -558,17 +530,23 @@ void do_notify_resume(struct pt_regs *regs, void *unused, /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); + + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } } void signal_fault(struct pt_regs *regs, void __user *frame, char *where) -{ - struct task_struct *me = current; +{ + struct task_struct *me = current; if (show_unhandled_signals && printk_ratelimit()) { printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", - me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); + me->comm, me->pid, where, frame, regs->ip, + regs->sp, regs->orig_ax); print_vma_addr(" in ", regs->ip); printk("\n"); } - force_sig(SIGSEGV, me); -} + force_sig(SIGSEGV, me); +} diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7985c5b3f916..4e7ccb0e2a9b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -88,7 +88,7 @@ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) #else -struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; +static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; #define get_idle_for_cpu(x) (idle_thread_array[(x)]) #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #endif @@ -129,7 +129,7 @@ static int boot_cpu_logical_apicid; static cpumask_t cpu_sibling_setup_map; /* Set if we find a B stepping CPU */ -int __cpuinitdata smp_b_stepping; +static int __cpuinitdata smp_b_stepping; #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) @@ -257,6 +257,7 @@ static void __cpuinit smp_callin(void) end_local_APIC_setup(); map_cpu_to_logical_apicid(); + notify_cpu_starting(cpuid); /* * Get our bogomips. * @@ -1313,16 +1314,13 @@ __init void prefill_possible_map(void) if (!num_processors) num_processors = 1; -#ifdef CONFIG_HOTPLUG_CPU if (additional_cpus == -1) { if (disabled_cpus > 0) additional_cpus = disabled_cpus; else additional_cpus = 0; } -#else - additional_cpus = 0; -#endif + possible = num_processors + additional_cpus; if (possible > NR_CPUS) possible = NR_CPUS; diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index 7066cb855a60..1884a8d12bfa 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c @@ -22,6 +22,8 @@ #include <linux/uaccess.h> #include <linux/unistd.h> +#include <asm/syscalls.h> + asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 3b360ef33817..6bc211accf08 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -13,15 +13,17 @@ #include <linux/utsname.h> #include <linux/personality.h> #include <linux/random.h> +#include <linux/uaccess.h> -#include <asm/uaccess.h> #include <asm/ia32.h> +#include <asm/syscalls.h> -asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long off) +asmlinkage long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off) { long error; - struct file * file; + struct file *file; error = -EINVAL; if (off & ~PAGE_MASK) @@ -56,9 +58,9 @@ static void find_start_end(unsigned long flags, unsigned long *begin, unmapped base down for this case. This can give conflicts with the heap, but we assume that glibc malloc knows how to fall back to mmap. Give it 1GB - of playground for now. -AK */ - *begin = 0x40000000; - *end = 0x80000000; + of playground for now. -AK */ + *begin = 0x40000000; + *end = 0x80000000; if (current->flags & PF_RANDOMIZE) { new_begin = randomize_range(*begin, *begin + 0x02000000, 0); if (new_begin) @@ -66,9 +68,9 @@ static void find_start_end(unsigned long flags, unsigned long *begin, } } else { *begin = TASK_UNMAPPED_BASE; - *end = TASK_SIZE; + *end = TASK_SIZE; } -} +} unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, @@ -78,11 +80,11 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct vm_area_struct *vma; unsigned long start_addr; unsigned long begin, end; - + if (flags & MAP_FIXED) return addr; - find_start_end(flags, &begin, &end); + find_start_end(flags, &begin, &end); if (len > end) return -ENOMEM; @@ -96,12 +98,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, } if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32)) && len <= mm->cached_hole_size) { - mm->cached_hole_size = 0; + mm->cached_hole_size = 0; mm->free_area_cache = begin; } addr = mm->free_area_cache; - if (addr < begin) - addr = begin; + if (addr < begin) + addr = begin; start_addr = addr; full_search: @@ -127,7 +129,7 @@ full_search: return addr; } if (addr + mm->cached_hole_size < vma->vm_start) - mm->cached_hole_size = vma->vm_start - addr; + mm->cached_hole_size = vma->vm_start - addr; addr = vma->vm_end; } @@ -177,7 +179,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, vma = find_vma(mm, addr-len); if (!vma || addr <= vma->vm_start) /* remember the address as a hint for next time */ - return (mm->free_area_cache = addr-len); + return mm->free_area_cache = addr-len; } if (mm->mmap_base < len) @@ -194,7 +196,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, vma = find_vma(mm, addr); if (!vma || addr+len <= vma->vm_start) /* remember the address as a hint for next time */ - return (mm->free_area_cache = addr); + return mm->free_area_cache = addr; /* remember the largest hole we saw so far */ if (addr + mm->cached_hole_size < vma->vm_start) @@ -224,13 +226,13 @@ bottomup: } -asmlinkage long sys_uname(struct new_utsname __user * name) +asmlinkage long sys_uname(struct new_utsname __user *name) { int err; down_read(&uts_sem); - err = copy_to_user(name, utsname(), sizeof (*name)); + err = copy_to_user(name, utsname(), sizeof(*name)); up_read(&uts_sem); - if (personality(current->personality) == PER_LINUX32) - err |= copy_to_user(&name->machine, "i686", 5); + if (personality(current->personality) == PER_LINUX32) + err |= copy_to_user(&name->machine, "i686", 5); return err ? -EFAULT : 0; } diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c index 170d43c17487..3d1be4f0fac5 100644 --- a/arch/x86/kernel/syscall_64.c +++ b/arch/x86/kernel/syscall_64.c @@ -8,12 +8,12 @@ #define __NO_STUBS #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H #include <asm/unistd_64.h> #undef __SYSCALL #define __SYSCALL(nr, sym) [nr] = sym, -#undef _ASM_X86_64_UNISTD_H_ +#undef ASM_X86__UNISTD_64_H typedef void (*sys_call_ptr_t)(void); diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index ffe3c664afc0..bbecf8b6bf96 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c @@ -36,6 +36,7 @@ #include <asm/arch_hooks.h> #include <asm/hpet.h> #include <asm/time.h> +#include <asm/timer.h> #include "do_timer.h" diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index ab6bf375a307..6bb7b8579e70 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -10,6 +10,7 @@ #include <asm/ldt.h> #include <asm/processor.h> #include <asm/proto.h> +#include <asm/syscalls.h> #include "tls.h" diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 513caaca7115..7a31f104bef9 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -32,6 +32,8 @@ #include <linux/bug.h> #include <linux/nmi.h> #include <linux/mm.h> +#include <linux/smp.h> +#include <linux/io.h> #if defined(CONFIG_EDAC) #include <linux/edac.h> @@ -45,9 +47,6 @@ #include <asm/unwind.h> #include <asm/desc.h> #include <asm/i387.h> -#include <asm/nmi.h> -#include <asm/smp.h> -#include <asm/io.h> #include <asm/pgalloc.h> #include <asm/proto.h> #include <asm/pda.h> @@ -85,7 +84,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) void printk_address(unsigned long address, int reliable) { - printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address); + printk(" [<%016lx>] %s%pS\n", + address, reliable ? "" : "? ", (void *) address); } static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, @@ -98,7 +98,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, [STACKFAULT_STACK - 1] = "#SS", [MCE_STACK - 1] = "#MC", #if DEBUG_STKSZ > EXCEPTION_STKSZ - [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" + [N_EXCEPTION_STACKS ... + N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" #endif }; unsigned k; @@ -163,7 +164,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, } /* - * x86-64 can have up to three kernel stacks: + * x86-64 can have up to three kernel stacks: * process stack * interrupt stack * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack @@ -219,7 +220,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, const struct stacktrace_ops *ops, void *data) { const unsigned cpu = get_cpu(); - unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr; + unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; unsigned used = 0; struct thread_info *tinfo; @@ -237,7 +238,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (!bp) { if (task == current) { /* Grab bp right from our regs */ - asm("movq %%rbp, %0" : "=r" (bp) :); + asm("movq %%rbp, %0" : "=r" (bp) : ); } else { /* bp is the last reg pushed by switch_to */ bp = *(unsigned long *) task->thread.sp; @@ -339,9 +340,8 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, unsigned long bp, char *log_lvl) { - printk("\nCall Trace:\n"); + printk("Call Trace:\n"); dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); - printk("\n"); } void show_trace(struct task_struct *task, struct pt_regs *regs, @@ -357,11 +357,15 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack; int i; const int cpu = smp_processor_id(); - unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr); - unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); + unsigned long *irqstack_end = + (unsigned long *) (cpu_pda(cpu)->irqstackptr); + unsigned long *irqstack = + (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); - // debugging aid: "show_stack(NULL, NULL);" prints the - // back trace for this cpu. + /* + * debugging aid: "show_stack(NULL, NULL);" prints the + * back trace for this cpu. + */ if (sp == NULL) { if (task) @@ -386,6 +390,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, printk(" %016lx", *stack++); touch_nmi_watchdog(); } + printk("\n"); show_trace_log_lvl(task, regs, sp, bp, log_lvl); } @@ -404,7 +409,7 @@ void dump_stack(void) #ifdef CONFIG_FRAME_POINTER if (!bp) - asm("movq %%rbp, %0" : "=r" (bp):); + asm("movq %%rbp, %0" : "=r" (bp) : ); #endif printk("Pid: %d, comm: %.20s %s %s %.*s\n", @@ -414,7 +419,6 @@ void dump_stack(void) init_utsname()->version); show_trace(NULL, NULL, &stack, bp); } - EXPORT_SYMBOL(dump_stack); void show_registers(struct pt_regs *regs) @@ -443,7 +447,6 @@ void show_registers(struct pt_regs *regs) printk("Stack: "); show_stack_log_lvl(NULL, regs, (unsigned long *)sp, regs->bp, ""); - printk("\n"); printk(KERN_EMERG "Code: "); @@ -493,7 +496,7 @@ unsigned __kprobes long oops_begin(void) raw_local_irq_save(flags); cpu = smp_processor_id(); if (!__raw_spin_trylock(&die_lock)) { - if (cpu == die_owner) + if (cpu == die_owner) /* nested oops. should stop eventually */; else __raw_spin_lock(&die_lock); @@ -638,7 +641,7 @@ kernel_trap: } #define DO_ERROR(trapnr, signr, str, name) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ == NOTIFY_STOP) \ @@ -648,7 +651,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ } #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ { \ siginfo_t info; \ info.si_signo = signr; \ @@ -683,7 +686,7 @@ asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code) preempt_conditional_cli(regs); } -asmlinkage void do_double_fault(struct pt_regs * regs, long error_code) +asmlinkage void do_double_fault(struct pt_regs *regs, long error_code) { static const char str[] = "double fault"; struct task_struct *tsk = current; @@ -778,9 +781,10 @@ io_check_error(unsigned char reason, struct pt_regs *regs) } static notrace __kprobes void -unknown_nmi_error(unsigned char reason, struct pt_regs * regs) +unknown_nmi_error(unsigned char reason, struct pt_regs *regs) { - if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) + if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == + NOTIFY_STOP) return; printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n", reason); @@ -882,7 +886,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) else if (user_mode(eregs)) regs = task_pt_regs(current); /* Exception from kernel and interrupts are enabled. Move to - kernel process stack. */ + kernel process stack. */ else if (eregs->flags & X86_EFLAGS_IF) regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs)); if (eregs != regs) @@ -891,7 +895,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) } /* runs on IST stack. */ -asmlinkage void __kprobes do_debug(struct pt_regs * regs, +asmlinkage void __kprobes do_debug(struct pt_regs *regs, unsigned long error_code) { struct task_struct *tsk = current; @@ -1035,7 +1039,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs) asmlinkage void bad_intr(void) { - printk("bad interrupt"); + printk("bad interrupt"); } asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) @@ -1047,7 +1051,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) conditional_sti(regs); if (!user_mode(regs) && - kernel_math_error(regs, "kernel simd math error", 19)) + kernel_math_error(regs, "kernel simd math error", 19)) return; /* @@ -1092,7 +1096,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs) +asmlinkage void do_spurious_interrupt_bug(struct pt_regs *regs) { } @@ -1149,8 +1153,10 @@ void __init trap_init(void) set_intr_gate(0, ÷_error); set_intr_gate_ist(1, &debug, DEBUG_STACK); set_intr_gate_ist(2, &nmi, NMI_STACK); - set_system_gate_ist(3, &int3, DEBUG_STACK); /* int3 can be called from all */ - set_system_gate(4, &overflow); /* int4 can be called from all */ + /* int3 can be called from all */ + set_system_gate_ist(3, &int3, DEBUG_STACK); + /* int4 can be called from all */ + set_system_gate(4, &overflow); set_intr_gate(5, &bounds); set_intr_gate(6, &invalid_op); set_intr_gate(7, &device_not_available); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 8f98e9de1b82..161bb850fc47 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -104,7 +104,7 @@ __setup("notsc", notsc_setup); /* * Read TSC and the reference counters. Take care of SMI disturbance */ -static u64 tsc_read_refs(u64 *pm, u64 *hpet) +static u64 tsc_read_refs(u64 *p, int hpet) { u64 t1, t2; int i; @@ -112,9 +112,9 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet) for (i = 0; i < MAX_RETRIES; i++) { t1 = get_cycles(); if (hpet) - *hpet = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF; + *p = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF; else - *pm = acpi_pm_read_early(); + *p = acpi_pm_read_early(); t2 = get_cycles(); if ((t2 - t1) < SMI_TRESHOLD) return t2; @@ -123,13 +123,59 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet) } /* + * Calculate the TSC frequency from HPET reference + */ +static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2) +{ + u64 tmp; + + if (hpet2 < hpet1) + hpet2 += 0x100000000ULL; + hpet2 -= hpet1; + tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); + do_div(tmp, 1000000); + do_div(deltatsc, tmp); + + return (unsigned long) deltatsc; +} + +/* + * Calculate the TSC frequency from PMTimer reference + */ +static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2) +{ + u64 tmp; + + if (!pm1 && !pm2) + return ULONG_MAX; + + if (pm2 < pm1) + pm2 += (u64)ACPI_PM_OVRRUN; + pm2 -= pm1; + tmp = pm2 * 1000000000LL; + do_div(tmp, PMTMR_TICKS_PER_SEC); + do_div(deltatsc, tmp); + + return (unsigned long) deltatsc; +} + +#define CAL_MS 10 +#define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS)) +#define CAL_PIT_LOOPS 1000 + +#define CAL2_MS 50 +#define CAL2_LATCH (CLOCK_TICK_RATE / (1000 / CAL2_MS)) +#define CAL2_PIT_LOOPS 5000 + + +/* * Try to calibrate the TSC against the Programmable * Interrupt Timer and return the frequency of the TSC * in kHz. * * Return ULONG_MAX on failure to calibrate. */ -static unsigned long pit_calibrate_tsc(void) +static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin) { u64 tsc, t1, t2, delta; unsigned long tscmin, tscmax; @@ -144,8 +190,8 @@ static unsigned long pit_calibrate_tsc(void) * (LSB then MSB) to begin countdown. */ outb(0xb0, 0x43); - outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42); - outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42); + outb(latch & 0xff, 0x42); + outb(latch >> 8, 0x42); tsc = t1 = t2 = get_cycles(); @@ -166,31 +212,154 @@ static unsigned long pit_calibrate_tsc(void) /* * Sanity checks: * - * If we were not able to read the PIT more than 5000 + * If we were not able to read the PIT more than loopmin * times, then we have been hit by a massive SMI * * If the maximum is 10 times larger than the minimum, * then we got hit by an SMI as well. */ - if (pitcnt < 5000 || tscmax > 10 * tscmin) + if (pitcnt < loopmin || tscmax > 10 * tscmin) return ULONG_MAX; /* Calculate the PIT value */ delta = t2 - t1; - do_div(delta, 50); + do_div(delta, ms); return delta; } +/* + * This reads the current MSB of the PIT counter, and + * checks if we are running on sufficiently fast and + * non-virtualized hardware. + * + * Our expectations are: + * + * - the PIT is running at roughly 1.19MHz + * + * - each IO is going to take about 1us on real hardware, + * but we allow it to be much faster (by a factor of 10) or + * _slightly_ slower (ie we allow up to a 2us read+counter + * update - anything else implies a unacceptably slow CPU + * or PIT for the fast calibration to work. + * + * - with 256 PIT ticks to read the value, we have 214us to + * see the same MSB (and overhead like doing a single TSC + * read per MSB value etc). + * + * - We're doing 2 reads per loop (LSB, MSB), and we expect + * them each to take about a microsecond on real hardware. + * So we expect a count value of around 100. But we'll be + * generous, and accept anything over 50. + * + * - if the PIT is stuck, and we see *many* more reads, we + * return early (and the next caller of pit_expect_msb() + * then consider it a failure when they don't see the + * next expected value). + * + * These expectations mean that we know that we have seen the + * transition from one expected value to another with a fairly + * high accuracy, and we didn't miss any events. We can thus + * use the TSC value at the transitions to calculate a pretty + * good value for the TSC frequencty. + */ +static inline int pit_expect_msb(unsigned char val) +{ + int count = 0; + + for (count = 0; count < 50000; count++) { + /* Ignore LSB */ + inb(0x42); + if (inb(0x42) != val) + break; + } + return count > 50; +} + +/* + * How many MSB values do we want to see? We aim for a + * 15ms calibration, which assuming a 2us counter read + * error should give us roughly 150 ppm precision for + * the calibration. + */ +#define QUICK_PIT_MS 15 +#define QUICK_PIT_ITERATIONS (QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256) + +static unsigned long quick_pit_calibrate(void) +{ + /* Set the Gate high, disable speaker */ + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + + /* + * Counter 2, mode 0 (one-shot), binary count + * + * NOTE! Mode 2 decrements by two (and then the + * output is flipped each time, giving the same + * final output frequency as a decrement-by-one), + * so mode 0 is much better when looking at the + * individual counts. + */ + outb(0xb0, 0x43); + + /* Start at 0xffff */ + outb(0xff, 0x42); + outb(0xff, 0x42); + + if (pit_expect_msb(0xff)) { + int i; + u64 t1, t2, delta; + unsigned char expect = 0xfe; + + t1 = get_cycles(); + for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) { + if (!pit_expect_msb(expect)) + goto failed; + } + t2 = get_cycles(); + + /* + * Make sure we can rely on the second TSC timestamp: + */ + if (!pit_expect_msb(expect)) + goto failed; + + /* + * Ok, if we get here, then we've seen the + * MSB of the PIT decrement QUICK_PIT_ITERATIONS + * times, and each MSB had many hits, so we never + * had any sudden jumps. + * + * As a result, we can depend on there not being + * any odd delays anywhere, and the TSC reads are + * reliable. + * + * kHz = ticks / time-in-seconds / 1000; + * kHz = (t2 - t1) / (QPI * 256 / PIT_TICK_RATE) / 1000 + * kHz = ((t2 - t1) * PIT_TICK_RATE) / (QPI * 256 * 1000) + */ + delta = (t2 - t1)*PIT_TICK_RATE; + do_div(delta, QUICK_PIT_ITERATIONS*256*1000); + printk("Fast TSC calibration using PIT\n"); + return delta; + } +failed: + return 0; +} /** * native_calibrate_tsc - calibrate the tsc on boot */ unsigned long native_calibrate_tsc(void) { - u64 tsc1, tsc2, delta, pm1, pm2, hpet1, hpet2; + u64 tsc1, tsc2, delta, ref1, ref2; unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; - unsigned long flags; - int hpet = is_hpet_enabled(), i; + unsigned long flags, latch, ms, fast_calibrate; + int hpet = is_hpet_enabled(), i, loopmin; + + local_irq_save(flags); + fast_calibrate = quick_pit_calibrate(); + local_irq_restore(flags); + if (fast_calibrate) + return fast_calibrate; /* * Run 5 calibration loops to get the lowest frequency value @@ -216,7 +385,13 @@ unsigned long native_calibrate_tsc(void) * calibration delay loop as we have to wait for a certain * amount of time anyway. */ - for (i = 0; i < 5; i++) { + + /* Preset PIT loop values */ + latch = CAL_LATCH; + ms = CAL_MS; + loopmin = CAL_PIT_LOOPS; + + for (i = 0; i < 3; i++) { unsigned long tsc_pit_khz; /* @@ -226,16 +401,16 @@ unsigned long native_calibrate_tsc(void) * read the end value. */ local_irq_save(flags); - tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL); - tsc_pit_khz = pit_calibrate_tsc(); - tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL); + tsc1 = tsc_read_refs(&ref1, hpet); + tsc_pit_khz = pit_calibrate_tsc(latch, ms, loopmin); + tsc2 = tsc_read_refs(&ref2, hpet); local_irq_restore(flags); /* Pick the lowest PIT TSC calibration so far */ tsc_pit_min = min(tsc_pit_min, tsc_pit_khz); /* hpet or pmtimer available ? */ - if (!hpet && !pm1 && !pm2) + if (!hpet && !ref1 && !ref2) continue; /* Check, whether the sampling was disturbed by an SMI */ @@ -243,23 +418,41 @@ unsigned long native_calibrate_tsc(void) continue; tsc2 = (tsc2 - tsc1) * 1000000LL; + if (hpet) + tsc2 = calc_hpet_ref(tsc2, ref1, ref2); + else + tsc2 = calc_pmtimer_ref(tsc2, ref1, ref2); - if (hpet) { - if (hpet2 < hpet1) - hpet2 += 0x100000000ULL; - hpet2 -= hpet1; - tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); - do_div(tsc1, 1000000); - } else { - if (pm2 < pm1) - pm2 += (u64)ACPI_PM_OVRRUN; - pm2 -= pm1; - tsc1 = pm2 * 1000000000LL; - do_div(tsc1, PMTMR_TICKS_PER_SEC); + tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); + + /* Check the reference deviation */ + delta = ((u64) tsc_pit_min) * 100; + do_div(delta, tsc_ref_min); + + /* + * If both calibration results are inside a 10% window + * then we can be sure, that the calibration + * succeeded. We break out of the loop right away. We + * use the reference value, as it is more precise. + */ + if (delta >= 90 && delta <= 110) { + printk(KERN_INFO + "TSC: PIT calibration matches %s. %d loops\n", + hpet ? "HPET" : "PMTIMER", i + 1); + return tsc_ref_min; } - do_div(tsc2, tsc1); - tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); + /* + * Check whether PIT failed more than once. This + * happens in virtualized environments. We need to + * give the virtual PC a slightly longer timeframe for + * the HPET/PMTIMER to make the result precise. + */ + if (i == 1 && tsc_pit_min == ULONG_MAX) { + latch = CAL2_LATCH; + ms = CAL2_MS; + loopmin = CAL2_PIT_LOOPS; + } } /* @@ -270,7 +463,7 @@ unsigned long native_calibrate_tsc(void) printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n"); /* We don't have an alternative source, disable TSC */ - if (!hpet && !pm1 && !pm2) { + if (!hpet && !ref1 && !ref2) { printk("TSC: No reference (HPET/PMTIMER) available\n"); return 0; } @@ -278,7 +471,7 @@ unsigned long native_calibrate_tsc(void) /* The alternative source failed as well, disable TSC */ if (tsc_ref_min == ULONG_MAX) { printk(KERN_WARNING "TSC: HPET/PMTIMER calibration " - "failed due to SMI disturbance.\n"); + "failed.\n"); return 0; } @@ -290,44 +483,25 @@ unsigned long native_calibrate_tsc(void) } /* We don't have an alternative source, use the PIT calibration value */ - if (!hpet && !pm1 && !pm2) { + if (!hpet && !ref1 && !ref2) { printk(KERN_INFO "TSC: Using PIT calibration value\n"); return tsc_pit_min; } /* The alternative source failed, use the PIT calibration value */ if (tsc_ref_min == ULONG_MAX) { - printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed due " - "to SMI disturbance. Using PIT calibration\n"); + printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. " + "Using PIT calibration\n"); return tsc_pit_min; } - /* Check the reference deviation */ - delta = ((u64) tsc_pit_min) * 100; - do_div(delta, tsc_ref_min); - - /* - * If both calibration results are inside a 5% window, the we - * use the lower frequency of those as it is probably the - * closest estimate. - */ - if (delta >= 95 && delta <= 105) { - printk(KERN_INFO "TSC: PIT calibration confirmed by %s.\n", - hpet ? "HPET" : "PMTIMER"); - printk(KERN_INFO "TSC: using %s calibration value\n", - tsc_pit_min <= tsc_ref_min ? "PIT" : - hpet ? "HPET" : "PMTIMER"); - return tsc_pit_min <= tsc_ref_min ? tsc_pit_min : tsc_ref_min; - } - - printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n", - hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min); - /* * The calibration values differ too much. In doubt, we use * the PIT value as we know that there are PMTIMERs around - * running at double speed. + * running at double speed. At least we let the user know: */ + printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n", + hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min); printk(KERN_INFO "TSC: Using PIT calibration value\n"); return tsc_pit_min; } diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 594ef47f0a63..61a97e616f70 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -25,45 +25,31 @@ #include <asm/visws/cobalt.h> #include <asm/visws/piix4.h> #include <asm/arch_hooks.h> +#include <asm/io_apic.h> #include <asm/fixmap.h> #include <asm/reboot.h> #include <asm/setup.h> #include <asm/e820.h> -#include <asm/smp.h> #include <asm/io.h> #include <mach_ipi.h> #include "mach_apic.h" -#include <linux/init.h> -#include <linux/smp.h> - #include <linux/kernel_stat.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <asm/io.h> -#include <asm/apic.h> #include <asm/i8259.h> #include <asm/irq_vectors.h> -#include <asm/visws/cobalt.h> #include <asm/visws/lithium.h> -#include <asm/visws/piix4.h> #include <linux/sched.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/pci.h> #include <linux/pci_ids.h> extern int no_broadcast; -#include <asm/io.h> #include <asm/apic.h> -#include <asm/arch_hooks.h> -#include <asm/visws/cobalt.h> -#include <asm/visws/lithium.h> char visws_board_type = -1; char visws_board_rev = -1; diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 38f566fa27d2..4eeb5cf9720d 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -46,6 +46,7 @@ #include <asm/io.h> #include <asm/tlbflush.h> #include <asm/irq.h> +#include <asm/syscalls.h> /* * Known problems: diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index edfb09f30479..8c9ad02af5a2 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -393,13 +393,13 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type) } #endif -static void vmi_allocate_pte(struct mm_struct *mm, u32 pfn) +static void vmi_allocate_pte(struct mm_struct *mm, unsigned long pfn) { vmi_set_page_type(pfn, VMI_PAGE_L1); vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0); } -static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn) +static void vmi_allocate_pmd(struct mm_struct *mm, unsigned long pfn) { /* * This call comes in very early, before mem_map is setup. @@ -410,20 +410,20 @@ static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn) vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0); } -static void vmi_allocate_pmd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count) +static void vmi_allocate_pmd_clone(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count) { vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE); vmi_check_page_type(clonepfn, VMI_PAGE_L2); vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count); } -static void vmi_release_pte(u32 pfn) +static void vmi_release_pte(unsigned long pfn) { vmi_ops.release_page(pfn, VMI_PAGE_L1); vmi_set_page_type(pfn, VMI_PAGE_NORMAL); } -static void vmi_release_pmd(u32 pfn) +static void vmi_release_pmd(unsigned long pfn) { vmi_ops.release_page(pfn, VMI_PAGE_L2); vmi_set_page_type(pfn, VMI_PAGE_NORMAL); diff --git a/arch/x86/lib/msr-on-cpu.c b/arch/x86/lib/msr-on-cpu.c index 01b868ba82f8..321cf720dbb6 100644 --- a/arch/x86/lib/msr-on-cpu.c +++ b/arch/x86/lib/msr-on-cpu.c @@ -16,37 +16,46 @@ static void __rdmsr_on_cpu(void *info) rdmsr(rv->msr_no, rv->l, rv->h); } -static void __rdmsr_safe_on_cpu(void *info) +static void __wrmsr_on_cpu(void *info) { struct msr_info *rv = info; - rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); + wrmsr(rv->msr_no, rv->l, rv->h); } -static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) { - int err = 0; + int err; struct msr_info rv; rv.msr_no = msr_no; - if (safe) { - err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, - &rv, 1); - err = err ? err : rv.err; - } else { - err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); - } + err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); *l = rv.l; *h = rv.h; return err; } -static void __wrmsr_on_cpu(void *info) +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +{ + int err; + struct msr_info rv; + + rv.msr_no = msr_no; + rv.l = l; + rv.h = h; + err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); + + return err; +} + +/* These "safe" variants are slower and should be used when the target MSR + may not actually exist. */ +static void __rdmsr_safe_on_cpu(void *info) { struct msr_info *rv = info; - wrmsr(rv->msr_no, rv->l, rv->h); + rv->err = rdmsr_safe(rv->msr_no, &rv->l, &rv->h); } static void __wrmsr_safe_on_cpu(void *info) @@ -56,45 +65,30 @@ static void __wrmsr_safe_on_cpu(void *info) rv->err = wrmsr_safe(rv->msr_no, rv->l, rv->h); } -static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) +int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) { - int err = 0; + int err; struct msr_info rv; rv.msr_no = msr_no; - rv.l = l; - rv.h = h; - if (safe) { - err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, - &rv, 1); - err = err ? err : rv.err; - } else { - err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); - } - - return err; -} + err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); + *l = rv.l; + *h = rv.h; -int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) -{ - return _wrmsr_on_cpu(cpu, msr_no, l, h, 0); + return err ? err : rv.err; } -int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - return _rdmsr_on_cpu(cpu, msr_no, l, h, 0); -} - -/* These "safe" variants are slower and should be used when the target MSR - may not actually exist. */ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) { - return _wrmsr_on_cpu(cpu, msr_no, l, h, 1); -} + int err; + struct msr_info rv; -int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) -{ - return _rdmsr_on_cpu(cpu, msr_no, l, h, 1); + rv.msr_no = msr_no; + rv.l = l; + rv.h = h; + err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1); + + return err ? err : rv.err; } EXPORT_SYMBOL(rdmsr_on_cpu); diff --git a/arch/x86/lib/string_32.c b/arch/x86/lib/string_32.c index 94972e7c094d..82004d2bf05e 100644 --- a/arch/x86/lib/string_32.c +++ b/arch/x86/lib/string_32.c @@ -22,7 +22,7 @@ char *strcpy(char *dest, const char *src) "testb %%al,%%al\n\t" "jne 1b" : "=&S" (d0), "=&D" (d1), "=&a" (d2) - :"0" (src), "1" (dest) : "memory"); + : "0" (src), "1" (dest) : "memory"); return dest; } EXPORT_SYMBOL(strcpy); @@ -42,7 +42,7 @@ char *strncpy(char *dest, const char *src, size_t count) "stosb\n" "2:" : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) - :"0" (src), "1" (dest), "2" (count) : "memory"); + : "0" (src), "1" (dest), "2" (count) : "memory"); return dest; } EXPORT_SYMBOL(strncpy); @@ -60,7 +60,7 @@ char *strcat(char *dest, const char *src) "testb %%al,%%al\n\t" "jne 1b" : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) - : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu): "memory"); + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory"); return dest; } EXPORT_SYMBOL(strcat); @@ -105,9 +105,9 @@ int strcmp(const char *cs, const char *ct) "2:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "3:" - :"=a" (res), "=&S" (d0), "=&D" (d1) - :"1" (cs), "2" (ct) - :"memory"); + : "=a" (res), "=&S" (d0), "=&D" (d1) + : "1" (cs), "2" (ct) + : "memory"); return res; } EXPORT_SYMBOL(strcmp); @@ -130,9 +130,9 @@ int strncmp(const char *cs, const char *ct, size_t count) "3:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "4:" - :"=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2) - :"1" (cs), "2" (ct), "3" (count) - :"memory"); + : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + : "1" (cs), "2" (ct), "3" (count) + : "memory"); return res; } EXPORT_SYMBOL(strncmp); @@ -152,9 +152,9 @@ char *strchr(const char *s, int c) "movl $1,%1\n" "2:\tmovl %1,%0\n\t" "decl %0" - :"=a" (res), "=&S" (d0) - :"1" (s), "0" (c) - :"memory"); + : "=a" (res), "=&S" (d0) + : "1" (s), "0" (c) + : "memory"); return res; } EXPORT_SYMBOL(strchr); @@ -169,9 +169,9 @@ size_t strlen(const char *s) "scasb\n\t" "notl %0\n\t" "decl %0" - :"=c" (res), "=&D" (d0) - :"1" (s), "a" (0), "0" (0xffffffffu) - :"memory"); + : "=c" (res), "=&D" (d0) + : "1" (s), "a" (0), "0" (0xffffffffu) + : "memory"); return res; } EXPORT_SYMBOL(strlen); @@ -189,9 +189,9 @@ void *memchr(const void *cs, int c, size_t count) "je 1f\n\t" "movl $1,%0\n" "1:\tdecl %0" - :"=D" (res), "=&c" (d0) - :"a" (c), "0" (cs), "1" (count) - :"memory"); + : "=D" (res), "=&c" (d0) + : "a" (c), "0" (cs), "1" (count) + : "memory"); return res; } EXPORT_SYMBOL(memchr); @@ -228,9 +228,9 @@ size_t strnlen(const char *s, size_t count) "cmpl $-1,%1\n\t" "jne 1b\n" "3:\tsubl %2,%0" - :"=a" (res), "=&d" (d0) - :"c" (s), "1" (count) - :"memory"); + : "=a" (res), "=&d" (d0) + : "c" (s), "1" (count) + : "memory"); return res; } EXPORT_SYMBOL(strnlen); diff --git a/arch/x86/lib/strstr_32.c b/arch/x86/lib/strstr_32.c index 42e8a50303f3..8e2d55f754bf 100644 --- a/arch/x86/lib/strstr_32.c +++ b/arch/x86/lib/strstr_32.c @@ -23,9 +23,9 @@ __asm__ __volatile__( "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "2:" - :"=a" (__res), "=&c" (d0), "=&S" (d1) - :"0" (0), "1" (0xffffffff), "2" (cs), "g" (ct) - :"dx", "di"); + : "=a" (__res), "=&c" (d0), "=&S" (d1) + : "0" (0), "1" (0xffffffff), "2" (cs), "g" (ct) + : "dx", "di"); return __res; } diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c index 3d317836be9e..3f2cf11f201a 100644 --- a/arch/x86/mach-default/setup.c +++ b/arch/x86/mach-default/setup.c @@ -10,13 +10,15 @@ #include <asm/e820.h> #include <asm/setup.h> +#include <mach_ipi.h> + #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) #else #define DEFAULT_SEND_IPI (0) #endif -int no_broadcast=DEFAULT_SEND_IPI; +int no_broadcast = DEFAULT_SEND_IPI; /** * pre_intr_init_hook - initialisation prior to setting up interrupt vectors diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index ee0fba092157..199a5f4a873c 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -448,6 +448,8 @@ static void __init start_secondary(void *unused) VDEBUG(("VOYAGER SMP: CPU%d, stack at about %p\n", cpuid, &cpuid)); + notify_cpu_starting(cpuid); + /* enable interrupts */ local_irq_enable(); diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c index 62fa440678d8..847c164725f4 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/discontig_32.c @@ -328,7 +328,7 @@ void __init initmem_init(unsigned long start_pfn, get_memcfg_numa(); - kva_pages = round_up(calculate_numa_remap_pages(), PTRS_PER_PTE); + kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE); kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE); do { diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index a20d1fa64b4e..e7277cbcfb40 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c @@ -148,8 +148,8 @@ static void note_page(struct seq_file *m, struct pg_state *st, * we have now. "break" is either changing perms, levels or * address space marker. */ - prot = pgprot_val(new_prot) & ~(PTE_PFN_MASK); - cur = pgprot_val(st->current_prot) & ~(PTE_PFN_MASK); + prot = pgprot_val(new_prot) & PTE_FLAGS_MASK; + cur = pgprot_val(st->current_prot) & PTE_FLAGS_MASK; if (!st->level) { /* First entry */ diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 455f3fe67b42..8f92cac4e6db 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -35,6 +35,7 @@ #include <asm/tlbflush.h> #include <asm/proto.h> #include <asm-generic/sections.h> +#include <asm/traps.h> /* * Page fault error code bits @@ -357,8 +358,6 @@ static int is_errata100(struct pt_regs *regs, unsigned long address) return 0; } -void do_invalid_op(struct pt_regs *, unsigned long); - static int is_f00f_bug(struct pt_regs *regs, unsigned long address) { #ifdef CONFIG_X86_F00F_BUG diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 60ec1d08ff24..6b9a9358b330 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -47,6 +47,7 @@ #include <asm/paravirt.h> #include <asm/setup.h> #include <asm/cacheflush.h> +#include <asm/smp.h> unsigned int __VMALLOC_RESERVE = 128 << 20; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index d3746efb060d..770536ebf7e9 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -225,7 +225,7 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size) void __init cleanup_highmap(void) { unsigned long vaddr = __START_KERNEL_map; - unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1; + unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1; pmd_t *pmd = level2_kernel_pgt; pmd_t *last_pmd = pmd + PTRS_PER_PMD; @@ -451,14 +451,14 @@ static void __init find_early_table_space(unsigned long end) unsigned long puds, pmds, ptes, tables, start; puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - tables = round_up(puds * sizeof(pud_t), PAGE_SIZE); + tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); if (direct_gbpages) { unsigned long extra; extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; } else pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE); + tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); if (cpu_has_pse) { unsigned long extra; @@ -466,7 +466,7 @@ static void __init find_early_table_space(unsigned long end) ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; - tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE); + tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); /* * RED-PEN putting page tables only on node 0 could diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index d4b6e6a29ae3..cac6da54203b 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -421,7 +421,7 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr) return; } -int __initdata early_ioremap_debug; +static int __initdata early_ioremap_debug; static int __init early_ioremap_debug_setup(char *str) { @@ -547,7 +547,7 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx) } -int __initdata early_ioremap_nested; +static int __initdata early_ioremap_nested; static int __init check_early_ioremap_leak(void) { diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index a4dd793d6003..cebcbf152d46 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -79,7 +79,7 @@ static int __init allocate_cachealigned_memnodemap(void) return 0; addr = 0x8000; - nodemap_size = round_up(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); + nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES); nodemap_addr = find_e820_area(addr, max_pfn<<PAGE_SHIFT, nodemap_size, L1_CACHE_BYTES); if (nodemap_addr == -1UL) { @@ -176,10 +176,10 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long start_pfn, last_pfn, bootmap_pages, bootmap_size; unsigned long bootmap_start, nodedata_phys; void *bootmap; - const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); + const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE); int nid; - start = round_up(start, ZONE_ALIGN); + start = roundup(start, ZONE_ALIGN); printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid, start, end); @@ -210,9 +210,9 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn); nid = phys_to_nid(nodedata_phys); if (nid == nodeid) - bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); + bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE); else - bootmap_start = round_up(start, PAGE_SIZE); + bootmap_start = roundup(start, PAGE_SIZE); /* * SMP_CACHE_BYTES could be enough, but init_bootmem_node like * to use that to align to PAGE_SIZE diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 43e2f8483e4f..898fad617abe 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -84,7 +84,7 @@ static inline unsigned long highmap_start_pfn(void) static inline unsigned long highmap_end_pfn(void) { - return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; + return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; } #endif @@ -906,11 +906,13 @@ int set_memory_ro(unsigned long addr, int numpages) { return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); } +EXPORT_SYMBOL_GPL(set_memory_ro); int set_memory_rw(unsigned long addr, int numpages) { return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); } +EXPORT_SYMBOL_GPL(set_memory_rw); int set_memory_np(unsigned long addr, int numpages) { diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index d50302774fe2..86f2ffc43c3d 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -63,10 +63,8 @@ static inline void pgd_list_del(pgd_t *pgd) #define UNSHARED_PTRS_PER_PGD \ (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD) -static void pgd_ctor(void *p) +static void pgd_ctor(pgd_t *pgd) { - pgd_t *pgd = p; - /* If the pgd points to a shared pagetable level (either the ptes in non-PAE, or shared PMD in PAE), then just copy the references from swapper_pg_dir. */ @@ -87,7 +85,7 @@ static void pgd_ctor(void *p) pgd_list_add(pgd); } -static void pgd_dtor(void *pgd) +static void pgd_dtor(pgd_t *pgd) { unsigned long flags; /* can be called from interrupt context */ diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index cab0abbd1ebe..0951db9ee519 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c @@ -123,7 +123,8 @@ static int __init parse_vmalloc(char *arg) if (!arg) return -EINVAL; - __VMALLOC_RESERVE = memparse(arg, &arg); + /* Add VMALLOC_OFFSET to the parsed value due to vm area guard hole*/ + __VMALLOC_RESERVE = memparse(arg, &arg) + VMALLOC_OFFSET; return 0; } early_param("vmalloc", parse_vmalloc); diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c index 56b4757a1f47..43ac5af338d8 100644 --- a/arch/x86/oprofile/op_model_p4.c +++ b/arch/x86/oprofile/op_model_p4.c @@ -10,11 +10,12 @@ #include <linux/oprofile.h> #include <linux/smp.h> +#include <linux/ptrace.h> +#include <linux/nmi.h> #include <asm/msr.h> -#include <asm/ptrace.h> #include <asm/fixmap.h> #include <asm/apic.h> -#include <asm/nmi.h> + #include "op_x86_model.h" #include "op_counter.h" @@ -40,7 +41,7 @@ static unsigned int num_controls = NUM_CONTROLS_NON_HT; static inline void setup_num_counters(void) { #ifdef CONFIG_SMP - if (smp_num_siblings == 2){ + if (smp_num_siblings == 2) { num_counters = NUM_COUNTERS_HT2; num_controls = NUM_CONTROLS_HT2; } @@ -86,7 +87,7 @@ struct p4_event_binding { #define CTR_FLAME_2 (1 << 6) #define CTR_IQ_5 (1 << 7) -static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { +static struct p4_counter_binding p4_counters[NUM_COUNTERS_NON_HT] = { { CTR_BPU_0, MSR_P4_BPU_PERFCTR0, MSR_P4_BPU_CCCR0 }, { CTR_MS_0, MSR_P4_MS_PERFCTR0, MSR_P4_MS_CCCR0 }, { CTR_FLAME_0, MSR_P4_FLAME_PERFCTR0, MSR_P4_FLAME_CCCR0 }, @@ -97,32 +98,32 @@ static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { { CTR_IQ_5, MSR_P4_IQ_PERFCTR5, MSR_P4_IQ_CCCR5 } }; -#define NUM_UNUSED_CCCRS NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT +#define NUM_UNUSED_CCCRS (NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT) /* p4 event codes in libop/op_event.h are indices into this table. */ static struct p4_event_binding p4_events[NUM_EVENTS] = { - + { /* BRANCH_RETIRED */ - 0x05, 0x06, + 0x05, 0x06, { {CTR_IQ_4, MSR_P4_CRU_ESCR2}, {CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, - + { /* MISPRED_BRANCH_RETIRED */ - 0x04, 0x03, + 0x04, 0x03, { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, - + { /* TC_DELIVER_MODE */ 0x01, 0x01, - { { CTR_MS_0, MSR_P4_TC_ESCR0}, + { { CTR_MS_0, MSR_P4_TC_ESCR0}, { CTR_MS_2, MSR_P4_TC_ESCR1} } }, - + { /* BPU_FETCH_REQUEST */ - 0x00, 0x03, + 0x00, 0x03, { { CTR_BPU_0, MSR_P4_BPU_ESCR0}, { CTR_BPU_2, MSR_P4_BPU_ESCR1} } }, @@ -146,7 +147,7 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* LOAD_PORT_REPLAY */ - 0x02, 0x04, + 0x02, 0x04, { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } }, @@ -170,43 +171,43 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* BSQ_CACHE_REFERENCE */ - 0x07, 0x0c, + 0x07, 0x0c, { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, { CTR_BPU_2, MSR_P4_BSU_ESCR1} } }, { /* IOQ_ALLOCATION */ - 0x06, 0x03, + 0x06, 0x03, { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { 0, 0 } } }, { /* IOQ_ACTIVE_ENTRIES */ - 0x06, 0x1a, + 0x06, 0x1a, { { CTR_BPU_2, MSR_P4_FSB_ESCR1}, { 0, 0 } } }, { /* FSB_DATA_ACTIVITY */ - 0x06, 0x17, + 0x06, 0x17, { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { CTR_BPU_2, MSR_P4_FSB_ESCR1} } }, { /* BSQ_ALLOCATION */ - 0x07, 0x05, + 0x07, 0x05, { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, { 0, 0 } } }, { /* BSQ_ACTIVE_ENTRIES */ 0x07, 0x06, - { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, + { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, { 0, 0 } } }, { /* X87_ASSIST */ - 0x05, 0x03, + 0x05, 0x03, { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, { CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, @@ -216,21 +217,21 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* PACKED_SP_UOP */ - 0x01, 0x08, + 0x01, 0x08, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* PACKED_DP_UOP */ - 0x01, 0x0c, + 0x01, 0x0c, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, { /* SCALAR_SP_UOP */ - 0x01, 0x0a, + 0x01, 0x0a, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, @@ -242,31 +243,31 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* 64BIT_MMX_UOP */ - 0x01, 0x02, + 0x01, 0x02, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* 128BIT_MMX_UOP */ - 0x01, 0x1a, + 0x01, 0x1a, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, { /* X87_FP_UOP */ - 0x01, 0x04, + 0x01, 0x04, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* X87_SIMD_MOVES_UOP */ - 0x01, 0x2e, + 0x01, 0x2e, { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } }, - + { /* MACHINE_CLEAR */ - 0x05, 0x02, + 0x05, 0x02, { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, { CTR_IQ_5, MSR_P4_CRU_ESCR3} } }, @@ -276,9 +277,9 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, { CTR_BPU_2, MSR_P4_FSB_ESCR1} } }, - + { /* TC_MS_XFER */ - 0x00, 0x05, + 0x00, 0x05, { { CTR_MS_0, MSR_P4_MS_ESCR0}, { CTR_MS_2, MSR_P4_MS_ESCR1} } }, @@ -308,7 +309,7 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { }, { /* INSTR_RETIRED */ - 0x04, 0x02, + 0x04, 0x02, { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, @@ -319,14 +320,14 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { { CTR_IQ_5, MSR_P4_CRU_ESCR1} } }, - { /* UOP_TYPE */ - 0x02, 0x02, + { /* UOP_TYPE */ + 0x02, 0x02, { { CTR_IQ_4, MSR_P4_RAT_ESCR0}, { CTR_IQ_5, MSR_P4_RAT_ESCR1} } }, { /* RETIRED_MISPRED_BRANCH_TYPE */ - 0x02, 0x05, + 0x02, 0x05, { { CTR_MS_0, MSR_P4_TBPU_ESCR0}, { CTR_MS_2, MSR_P4_TBPU_ESCR1} } }, @@ -349,8 +350,8 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1)) #define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3f) << 25)) #define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9)) -#define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) -#define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) +#define ESCR_READ(escr, high, ev, i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high)); } while (0) +#define ESCR_WRITE(escr, high, ev, i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high)); } while (0) #define CCCR_RESERVED_BITS 0x38030FFF #define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS) @@ -360,15 +361,15 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = { #define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1<<27)) #define CCCR_SET_ENABLE(cccr) ((cccr) |= (1<<12)) #define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1<<12)) -#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) -#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) +#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high)); } while (0) +#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high)); } while (0) #define CCCR_OVF_P(cccr) ((cccr) & (1U<<31)) #define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31))) -#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0) -#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0) -#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0) -#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0) +#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0) +#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0) +#define CTR_READ(l, h, i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h)); } while (0) +#define CTR_WRITE(l, i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1); } while (0) #define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000)) @@ -380,7 +381,7 @@ static unsigned int get_stagger(void) #ifdef CONFIG_SMP int cpu = smp_processor_id(); return (cpu != first_cpu(per_cpu(cpu_sibling_map, cpu))); -#endif +#endif return 0; } @@ -395,25 +396,23 @@ static unsigned long reset_value[NUM_COUNTERS_NON_HT]; static void p4_fill_in_addresses(struct op_msrs * const msrs) { - unsigned int i; + unsigned int i; unsigned int addr, cccraddr, stag; setup_num_counters(); stag = get_stagger(); /* initialize some registers */ - for (i = 0; i < num_counters; ++i) { + for (i = 0; i < num_counters; ++i) msrs->counters[i].addr = 0; - } - for (i = 0; i < num_controls; ++i) { + for (i = 0; i < num_controls; ++i) msrs->controls[i].addr = 0; - } - + /* the counter & cccr registers we pay attention to */ for (i = 0; i < num_counters; ++i) { addr = p4_counters[VIRT_CTR(stag, i)].counter_address; cccraddr = p4_counters[VIRT_CTR(stag, i)].cccr_address; - if (reserve_perfctr_nmi(addr)){ + if (reserve_perfctr_nmi(addr)) { msrs->counters[i].addr = addr; msrs->controls[i].addr = cccraddr; } @@ -447,22 +446,22 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs) if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } - + for (addr = MSR_P4_MS_ESCR0 + stag; - addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { + addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } - + for (addr = MSR_P4_IX_ESCR0 + stag; - addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { + addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { if (reserve_evntsel_nmi(addr)) msrs->controls[i].addr = addr; } /* there are 2 remaining non-contiguously located ESCRs */ - if (num_counters == NUM_COUNTERS_NON_HT) { + if (num_counters == NUM_COUNTERS_NON_HT) { /* standard non-HT CPUs handle both remaining ESCRs*/ if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR5)) msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; @@ -498,20 +497,20 @@ static void pmc_setup_one_p4_counter(unsigned int ctr) unsigned int stag; stag = get_stagger(); - + /* convert from counter *number* to counter *bit* */ counter_bit = 1 << VIRT_CTR(stag, ctr); - + /* find our event binding structure. */ if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) { - printk(KERN_ERR - "oprofile: P4 event code 0x%lx out of range\n", + printk(KERN_ERR + "oprofile: P4 event code 0x%lx out of range\n", counter_config[ctr].event); return; } - + ev = &(p4_events[counter_config[ctr].event - 1]); - + for (i = 0; i < maxbind; i++) { if (ev->bindings[i].virt_counter & counter_bit) { @@ -526,25 +525,24 @@ static void pmc_setup_one_p4_counter(unsigned int ctr) ESCR_SET_OS_1(escr, counter_config[ctr].kernel); } ESCR_SET_EVENT_SELECT(escr, ev->event_select); - ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); + ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); ESCR_WRITE(escr, high, ev, i); - + /* modify CCCR */ CCCR_READ(cccr, high, VIRT_CTR(stag, ctr)); CCCR_CLEAR(cccr); CCCR_SET_REQUIRED_BITS(cccr); CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); - if (stag == 0) { + if (stag == 0) CCCR_SET_PMI_OVF_0(cccr); - } else { + else CCCR_SET_PMI_OVF_1(cccr); - } CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr)); return; } } - printk(KERN_ERR + printk(KERN_ERR "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n", counter_config[ctr].event, stag, ctr); } @@ -559,14 +557,14 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) stag = get_stagger(); rdmsr(MSR_IA32_MISC_ENABLE, low, high); - if (! MISC_PMC_ENABLED_P(low)) { + if (!MISC_PMC_ENABLED_P(low)) { printk(KERN_ERR "oprofile: P4 PMC not available\n"); return; } /* clear the cccrs we will use */ for (i = 0 ; i < num_counters ; i++) { - if (unlikely(!CTRL_IS_RESERVED(msrs,i))) + if (unlikely(!CTRL_IS_RESERVED(msrs, i))) continue; rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); CCCR_CLEAR(low); @@ -576,14 +574,14 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) /* clear all escrs (including those outside our concern) */ for (i = num_counters; i < num_controls; i++) { - if (unlikely(!CTRL_IS_RESERVED(msrs,i))) + if (unlikely(!CTRL_IS_RESERVED(msrs, i))) continue; wrmsr(msrs->controls[i].addr, 0, 0); } /* setup all counters */ for (i = 0 ; i < num_counters ; ++i) { - if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs,i))) { + if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs, i))) { reset_value[i] = counter_config[i].count; pmc_setup_one_p4_counter(i); CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i)); @@ -603,11 +601,11 @@ static int p4_check_ctrs(struct pt_regs * const regs, stag = get_stagger(); for (i = 0; i < num_counters; ++i) { - - if (!reset_value[i]) + + if (!reset_value[i]) continue; - /* + /* * there is some eccentricity in the hardware which * requires that we perform 2 extra corrections: * @@ -616,24 +614,24 @@ static int p4_check_ctrs(struct pt_regs * const regs, * * - write the counter back twice to ensure it gets * updated properly. - * + * * the former seems to be related to extra NMIs happening * during the current NMI; the latter is reported as errata * N15 in intel doc 249199-029, pentium 4 specification * update, though their suggested work-around does not * appear to solve the problem. */ - + real = VIRT_CTR(stag, i); CCCR_READ(low, high, real); - CTR_READ(ctr, high, real); + CTR_READ(ctr, high, real); if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) { oprofile_add_sample(regs, i); - CTR_WRITE(reset_value[i], real); + CTR_WRITE(reset_value[i], real); CCCR_CLEAR_OVF(low); CCCR_WRITE(low, high, real); - CTR_WRITE(reset_value[i], real); + CTR_WRITE(reset_value[i], real); } } @@ -683,15 +681,16 @@ static void p4_shutdown(struct op_msrs const * const msrs) int i; for (i = 0 ; i < num_counters ; ++i) { - if (CTR_IS_RESERVED(msrs,i)) + if (CTR_IS_RESERVED(msrs, i)) release_perfctr_nmi(msrs->counters[i].addr); } - /* some of the control registers are specially reserved in + /* + * some of the control registers are specially reserved in * conjunction with the counter registers (hence the starting offset). * This saves a few bits. */ for (i = num_counters ; i < num_controls ; ++i) { - if (CTRL_IS_RESERVED(msrs,i)) + if (CTRL_IS_RESERVED(msrs, i)) release_evntsel_nmi(msrs->controls[i].addr); } } diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 6a0fca78c362..22e057665e55 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -580,7 +580,7 @@ static int __cpuinit amd_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (long)hcpu; - switch(action) { + switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0); diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 8e077185e185..006599db0dc7 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1043,35 +1043,44 @@ static void __init pcibios_fixup_irqs(void) if (io_apic_assign_pci_irqs) { int irq; - if (pin) { - /* - * interrupt pins are numbered starting - * from 1 - */ - pin--; - irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, - PCI_SLOT(dev->devfn), pin); - /* - * Busses behind bridges are typically not listed in the MP-table. - * In this case we have to look up the IRQ based on the parent bus, - * parent slot, and pin number. The SMP code detects such bridged - * busses itself so we should get into this branch reliably. - */ - if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ - struct pci_dev *bridge = dev->bus->self; - - pin = (pin + PCI_SLOT(dev->devfn)) % 4; - irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, - PCI_SLOT(bridge->devfn), pin); - if (irq >= 0) - dev_warn(&dev->dev, "using bridge %s INT %c to get IRQ %d\n", - pci_name(bridge), - 'A' + pin, irq); - } - if (irq >= 0) { - dev_info(&dev->dev, "PCI->APIC IRQ transform: INT %c -> IRQ %d\n", 'A' + pin, irq); - dev->irq = irq; - } + if (!pin) + continue; + + /* + * interrupt pins are numbered starting from 1 + */ + pin--; + irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, + PCI_SLOT(dev->devfn), pin); + /* + * Busses behind bridges are typically not listed in the + * MP-table. In this case we have to look up the IRQ + * based on the parent bus, parent slot, and pin number. + * The SMP code detects such bridged busses itself so we + * should get into this branch reliably. + */ + if (irq < 0 && dev->bus->parent) { + /* go back to the bridge */ + struct pci_dev *bridge = dev->bus->self; + int bus; + + pin = (pin + PCI_SLOT(dev->devfn)) % 4; + bus = bridge->bus->number; + irq = IO_APIC_get_PCI_irq_vector(bus, + PCI_SLOT(bridge->devfn), pin); + if (irq >= 0) + dev_warn(&dev->dev, + "using bridge %s INT %c to " + "get IRQ %d\n", + pci_name(bridge), + 'A' + pin, irq); + } + if (irq >= 0) { + dev_info(&dev->dev, + "PCI->APIC IRQ transform: INT %c " + "-> IRQ %d\n", + 'A' + pin, irq); + dev->irq = irq; } } #endif diff --git a/arch/x86/power/hibernate_asm_32.S b/arch/x86/power/hibernate_asm_32.S index 4fc7e872c85e..d1e9b53f9d33 100644 --- a/arch/x86/power/hibernate_asm_32.S +++ b/arch/x86/power/hibernate_asm_32.S @@ -1,5 +1,3 @@ -.text - /* * This may not use any stack, nor any variable that is not "NoSave": * @@ -12,17 +10,18 @@ #include <asm/segment.h> #include <asm/page.h> #include <asm/asm-offsets.h> +#include <asm/processor-flags.h> - .text +.text ENTRY(swsusp_arch_suspend) - movl %esp, saved_context_esp movl %ebx, saved_context_ebx movl %ebp, saved_context_ebp movl %esi, saved_context_esi movl %edi, saved_context_edi - pushfl ; popl saved_context_eflags + pushfl + popl saved_context_eflags call swsusp_save ret @@ -59,7 +58,7 @@ done: movl mmu_cr4_features, %ecx jecxz 1f # cr4 Pentium and higher, skip if zero movl %ecx, %edx - andl $~(1<<7), %edx; # PGE + andl $~(X86_CR4_PGE), %edx movl %edx, %cr4; # turn off PGE 1: movl %cr3, %eax; # flush TLB @@ -74,7 +73,8 @@ done: movl saved_context_esi, %esi movl saved_context_edi, %edi - pushl saved_context_eflags ; popfl + pushl saved_context_eflags + popfl xorl %eax, %eax diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index a4e201b47f64..7dcd321a0508 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -812,7 +812,7 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) /* Early in boot, while setting up the initial pagetable, assume everything is pinned. */ -static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn) +static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) { #ifdef CONFIG_FLATMEM BUG_ON(mem_map); /* should only be used early */ @@ -822,7 +822,7 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn) /* Early release_pte assumes that all pts are pinned, since there's only init_mm and anything attached to that is pinned. */ -static void xen_release_pte_init(u32 pfn) +static void xen_release_pte_init(unsigned long pfn) { make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } @@ -838,7 +838,7 @@ static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) /* This needs to make sure the new pte page is pinned iff its being attached to a pinned pagetable. */ -static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) +static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level) { struct page *page = pfn_to_page(pfn); @@ -856,12 +856,12 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) } } -static void xen_alloc_pte(struct mm_struct *mm, u32 pfn) +static void xen_alloc_pte(struct mm_struct *mm, unsigned long pfn) { xen_alloc_ptpage(mm, pfn, PT_PTE); } -static void xen_alloc_pmd(struct mm_struct *mm, u32 pfn) +static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn) { xen_alloc_ptpage(mm, pfn, PT_PMD); } @@ -909,7 +909,7 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) } /* This should never happen until we're OK to use struct page */ -static void xen_release_ptpage(u32 pfn, unsigned level) +static void xen_release_ptpage(unsigned long pfn, unsigned level) { struct page *page = pfn_to_page(pfn); @@ -923,23 +923,23 @@ static void xen_release_ptpage(u32 pfn, unsigned level) } } -static void xen_release_pte(u32 pfn) +static void xen_release_pte(unsigned long pfn) { xen_release_ptpage(pfn, PT_PTE); } -static void xen_release_pmd(u32 pfn) +static void xen_release_pmd(unsigned long pfn) { xen_release_ptpage(pfn, PT_PMD); } #if PAGETABLE_LEVELS == 4 -static void xen_alloc_pud(struct mm_struct *mm, u32 pfn) +static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn) { xen_alloc_ptpage(mm, pfn, PT_PUD); } -static void xen_release_pud(u32 pfn) +static void xen_release_pud(unsigned long pfn) { xen_release_ptpage(pfn, PT_PUD); } diff --git a/block/Makefile b/block/Makefile index 208000b0750d..bfe73049f939 100644 --- a/block/Makefile +++ b/block/Makefile @@ -4,8 +4,8 @@ obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \ blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \ - blk-exec.o blk-merge.o ioctl.o genhd.o scsi_ioctl.o \ - cmd-filter.o + blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \ + ioctl.o genhd.o scsi_ioctl.o cmd-filter.o obj-$(CONFIG_BLK_DEV_BSG) += bsg.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o diff --git a/block/as-iosched.c b/block/as-iosched.c index cf4eb0eefbbf..71f0abb219ee 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -462,7 +462,7 @@ static void as_antic_stop(struct as_data *ad) del_timer(&ad->antic_timer); ad->antic_status = ANTIC_FINISHED; /* see as_work_handler */ - kblockd_schedule_work(&ad->antic_work); + kblockd_schedule_work(ad->q, &ad->antic_work); } } @@ -483,7 +483,7 @@ static void as_antic_timeout(unsigned long data) aic = ad->io_context->aic; ad->antic_status = ANTIC_FINISHED; - kblockd_schedule_work(&ad->antic_work); + kblockd_schedule_work(q, &ad->antic_work); if (aic->ttime_samples == 0) { /* process anticipated on has exited or timed out*/ @@ -745,6 +745,14 @@ static int as_can_break_anticipation(struct as_data *ad, struct request *rq) */ static int as_can_anticipate(struct as_data *ad, struct request *rq) { +#if 0 /* disable for now, we need to check tag level as well */ + /* + * SSD device without seek penalty, disable idling + */ + if (blk_queue_nonrot(ad->q)) axman + return 0; +#endif + if (!ad->io_context) /* * Last request submitted was a write @@ -844,7 +852,7 @@ static void as_completed_request(struct request_queue *q, struct request *rq) if (ad->changed_batch && ad->nr_dispatched == 1) { ad->current_batch_expires = jiffies + ad->batch_expire[ad->batch_data_dir]; - kblockd_schedule_work(&ad->antic_work); + kblockd_schedule_work(q, &ad->antic_work); ad->changed_batch = 0; if (ad->batch_data_dir == REQ_SYNC) diff --git a/block/blk-barrier.c b/block/blk-barrier.c index a09ead19f9c5..5c99ff8d2db8 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c @@ -293,7 +293,7 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) bio->bi_end_io = bio_end_empty_barrier; bio->bi_private = &wait; bio->bi_bdev = bdev; - submit_bio(1 << BIO_RW_BARRIER, bio); + submit_bio(WRITE_BARRIER, bio); wait_for_completion(&wait); @@ -315,3 +315,73 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) return ret; } EXPORT_SYMBOL(blkdev_issue_flush); + +static void blkdev_discard_end_io(struct bio *bio, int err) +{ + if (err) { + if (err == -EOPNOTSUPP) + set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); + clear_bit(BIO_UPTODATE, &bio->bi_flags); + } + + bio_put(bio); +} + +/** + * blkdev_issue_discard - queue a discard + * @bdev: blockdev to issue discard for + * @sector: start sector + * @nr_sects: number of sectors to discard + * @gfp_mask: memory allocation flags (for bio_alloc) + * + * Description: + * Issue a discard request for the sectors in question. Does not wait. + */ +int blkdev_issue_discard(struct block_device *bdev, + sector_t sector, sector_t nr_sects, gfp_t gfp_mask) +{ + struct request_queue *q; + struct bio *bio; + int ret = 0; + + if (bdev->bd_disk == NULL) + return -ENXIO; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + + if (!q->prepare_discard_fn) + return -EOPNOTSUPP; + + while (nr_sects && !ret) { + bio = bio_alloc(gfp_mask, 0); + if (!bio) + return -ENOMEM; + + bio->bi_end_io = blkdev_discard_end_io; + bio->bi_bdev = bdev; + + bio->bi_sector = sector; + + if (nr_sects > q->max_hw_sectors) { + bio->bi_size = q->max_hw_sectors << 9; + nr_sects -= q->max_hw_sectors; + sector += q->max_hw_sectors; + } else { + bio->bi_size = nr_sects << 9; + nr_sects = 0; + } + bio_get(bio); + submit_bio(DISCARD_BARRIER, bio); + + /* Check if it failed immediately */ + if (bio_flagged(bio, BIO_EOPNOTSUPP)) + ret = -EOPNOTSUPP; + else if (!bio_flagged(bio, BIO_UPTODATE)) + ret = -EIO; + bio_put(bio); + } + return ret; +} +EXPORT_SYMBOL(blkdev_issue_discard); diff --git a/block/blk-core.c b/block/blk-core.c index 2cba5ef97b2b..2d053b584410 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -26,8 +26,6 @@ #include <linux/swap.h> #include <linux/writeback.h> #include <linux/task_io_accounting_ops.h> -#include <linux/interrupt.h> -#include <linux/cpu.h> #include <linux/blktrace_api.h> #include <linux/fault-inject.h> @@ -50,27 +48,26 @@ struct kmem_cache *blk_requestq_cachep; */ static struct workqueue_struct *kblockd_workqueue; -static DEFINE_PER_CPU(struct list_head, blk_cpu_done); - static void drive_stat_acct(struct request *rq, int new_io) { struct hd_struct *part; int rw = rq_data_dir(rq); + int cpu; if (!blk_fs_request(rq) || !rq->rq_disk) return; - part = get_part(rq->rq_disk, rq->sector); + cpu = part_stat_lock(); + part = disk_map_sector_rcu(rq->rq_disk, rq->sector); + if (!new_io) - __all_stat_inc(rq->rq_disk, part, merges[rw], rq->sector); + part_stat_inc(cpu, part, merges[rw]); else { - disk_round_stats(rq->rq_disk); - rq->rq_disk->in_flight++; - if (part) { - part_round_stats(part); - part->in_flight++; - } + part_round_stats(cpu, part); + part_inc_in_flight(part); } + + part_stat_unlock(); } void blk_queue_congestion_threshold(struct request_queue *q) @@ -113,7 +110,8 @@ void blk_rq_init(struct request_queue *q, struct request *rq) memset(rq, 0, sizeof(*rq)); INIT_LIST_HEAD(&rq->queuelist); - INIT_LIST_HEAD(&rq->donelist); + INIT_LIST_HEAD(&rq->timeout_list); + rq->cpu = -1; rq->q = q; rq->sector = rq->hard_sector = (sector_t) -1; INIT_HLIST_NODE(&rq->hash); @@ -308,7 +306,7 @@ void blk_unplug_timeout(unsigned long data) blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_TIMER, NULL, q->rq.count[READ] + q->rq.count[WRITE]); - kblockd_schedule_work(&q->unplug_work); + kblockd_schedule_work(q, &q->unplug_work); } void blk_unplug(struct request_queue *q) @@ -325,6 +323,21 @@ void blk_unplug(struct request_queue *q) } EXPORT_SYMBOL(blk_unplug); +static void blk_invoke_request_fn(struct request_queue *q) +{ + /* + * one level of recursion is ok and is much faster than kicking + * the unplug handling + */ + if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { + q->request_fn(q); + queue_flag_clear(QUEUE_FLAG_REENTER, q); + } else { + queue_flag_set(QUEUE_FLAG_PLUGGED, q); + kblockd_schedule_work(q, &q->unplug_work); + } +} + /** * blk_start_queue - restart a previously stopped queue * @q: The &struct request_queue in question @@ -339,18 +352,7 @@ void blk_start_queue(struct request_queue *q) WARN_ON(!irqs_disabled()); queue_flag_clear(QUEUE_FLAG_STOPPED, q); - - /* - * one level of recursion is ok and is much faster than kicking - * the unplug handling - */ - if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { - q->request_fn(q); - queue_flag_clear(QUEUE_FLAG_REENTER, q); - } else { - blk_plug_device(q); - kblockd_schedule_work(&q->unplug_work); - } + blk_invoke_request_fn(q); } EXPORT_SYMBOL(blk_start_queue); @@ -408,15 +410,8 @@ void __blk_run_queue(struct request_queue *q) * Only recurse once to avoid overrunning the stack, let the unplug * handling reinvoke the handler shortly if we already got there. */ - if (!elv_queue_empty(q)) { - if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) { - q->request_fn(q); - queue_flag_clear(QUEUE_FLAG_REENTER, q); - } else { - blk_plug_device(q); - kblockd_schedule_work(&q->unplug_work); - } - } + if (!elv_queue_empty(q)) + blk_invoke_request_fn(q); } EXPORT_SYMBOL(__blk_run_queue); @@ -441,6 +436,14 @@ void blk_put_queue(struct request_queue *q) void blk_cleanup_queue(struct request_queue *q) { + /* + * We know we have process context here, so we can be a little + * cautious and ensure that pending block actions on this device + * are done before moving on. Going into this function, we should + * not have processes doing IO to this device. + */ + blk_sync_queue(q); + mutex_lock(&q->sysfs_lock); queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); mutex_unlock(&q->sysfs_lock); @@ -496,6 +499,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) } init_timer(&q->unplug_timer); + setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); + INIT_LIST_HEAD(&q->timeout_list); kobject_init(&q->kobj, &blk_queue_ktype); @@ -531,7 +536,7 @@ EXPORT_SYMBOL(blk_alloc_queue_node); * request queue; this lock will be taken also from interrupt context, so irq * disabling is needed for it. * - * Function returns a pointer to the initialized request queue, or NULL if + * Function returns a pointer to the initialized request queue, or %NULL if * it didn't succeed. * * Note: @@ -569,7 +574,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) q->request_fn = rfn; q->prep_rq_fn = NULL; q->unplug_fn = generic_unplug_device; - q->queue_flags = (1 << QUEUE_FLAG_CLUSTER); + q->queue_flags = (1 << QUEUE_FLAG_CLUSTER | + 1 << QUEUE_FLAG_STACKABLE); q->queue_lock = lock; blk_queue_segment_boundary(q, 0xffffffff); @@ -624,10 +630,6 @@ blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask) blk_rq_init(q, rq); - /* - * first three bits are identical in rq->cmd_flags and bio->bi_rw, - * see bio.h and blkdev.h - */ rq->cmd_flags = rw | REQ_ALLOCED; if (priv) { @@ -888,9 +890,11 @@ EXPORT_SYMBOL(blk_get_request); */ void blk_start_queueing(struct request_queue *q) { - if (!blk_queue_plugged(q)) + if (!blk_queue_plugged(q)) { + if (unlikely(blk_queue_stopped(q))) + return; q->request_fn(q); - else + } else __generic_unplug_device(q); } EXPORT_SYMBOL(blk_start_queueing); @@ -907,6 +911,8 @@ EXPORT_SYMBOL(blk_start_queueing); */ void blk_requeue_request(struct request_queue *q, struct request *rq) { + blk_delete_timer(rq); + blk_clear_rq_complete(rq); blk_add_trace_rq(q, rq, BLK_TA_REQUEUE); if (blk_rq_tagged(rq)) @@ -917,7 +923,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) EXPORT_SYMBOL(blk_requeue_request); /** - * blk_insert_request - insert a special request in to a request queue + * blk_insert_request - insert a special request into a request queue * @q: request queue where request should be inserted * @rq: request to be inserted * @at_head: insert request at head or tail of queue @@ -927,8 +933,8 @@ EXPORT_SYMBOL(blk_requeue_request); * Many block devices need to execute commands asynchronously, so they don't * block the whole kernel from preemption during request execution. This is * accomplished normally by inserting aritficial requests tagged as - * REQ_SPECIAL in to the corresponding request queue, and letting them be - * scheduled for actual execution by the request queue. + * REQ_TYPE_SPECIAL in to the corresponding request queue, and letting them + * be scheduled for actual execution by the request queue. * * We have the option of inserting the head or the tail of the queue. * Typically we use the tail for new ioctls and so forth. We use the head @@ -982,8 +988,22 @@ static inline void add_request(struct request_queue *q, struct request *req) __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); } -/* - * disk_round_stats() - Round off the performance stats on a struct +static void part_round_stats_single(int cpu, struct hd_struct *part, + unsigned long now) +{ + if (now == part->stamp) + return; + + if (part->in_flight) { + __part_stat_add(cpu, part, time_in_queue, + part->in_flight * (now - part->stamp)); + __part_stat_add(cpu, part, io_ticks, (now - part->stamp)); + } + part->stamp = now; +} + +/** + * part_round_stats() - Round off the performance stats on a struct * disk_stats. * * The average IO queue length and utilisation statistics are maintained @@ -997,36 +1017,15 @@ static inline void add_request(struct request_queue *q, struct request *req) * /proc/diskstats. This accounts immediately for all queue usage up to * the current jiffies and restarts the counters again. */ -void disk_round_stats(struct gendisk *disk) +void part_round_stats(int cpu, struct hd_struct *part) { unsigned long now = jiffies; - if (now == disk->stamp) - return; - - if (disk->in_flight) { - __disk_stat_add(disk, time_in_queue, - disk->in_flight * (now - disk->stamp)); - __disk_stat_add(disk, io_ticks, (now - disk->stamp)); - } - disk->stamp = now; -} -EXPORT_SYMBOL_GPL(disk_round_stats); - -void part_round_stats(struct hd_struct *part) -{ - unsigned long now = jiffies; - - if (now == part->stamp) - return; - - if (part->in_flight) { - __part_stat_add(part, time_in_queue, - part->in_flight * (now - part->stamp)); - __part_stat_add(part, io_ticks, (now - part->stamp)); - } - part->stamp = now; + if (part->partno) + part_round_stats_single(cpu, &part_to_disk(part)->part0, now); + part_round_stats_single(cpu, part, now); } +EXPORT_SYMBOL_GPL(part_round_stats); /* * queue lock must be held @@ -1070,6 +1069,7 @@ EXPORT_SYMBOL(blk_put_request); void init_request_from_bio(struct request *req, struct bio *bio) { + req->cpu = bio->bi_comp_cpu; req->cmd_type = REQ_TYPE_FS; /* @@ -1081,7 +1081,12 @@ void init_request_from_bio(struct request *req, struct bio *bio) /* * REQ_BARRIER implies no merging, but lets make it explicit */ - if (unlikely(bio_barrier(bio))) + if (unlikely(bio_discard(bio))) { + req->cmd_flags |= REQ_DISCARD; + if (bio_barrier(bio)) + req->cmd_flags |= REQ_SOFTBARRIER; + req->q->prepare_discard_fn(req->q, req); + } else if (unlikely(bio_barrier(bio))) req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE); if (bio_sync(bio)) @@ -1099,7 +1104,7 @@ void init_request_from_bio(struct request *req, struct bio *bio) static int __make_request(struct request_queue *q, struct bio *bio) { struct request *req; - int el_ret, nr_sectors, barrier, err; + int el_ret, nr_sectors, barrier, discard, err; const unsigned short prio = bio_prio(bio); const int sync = bio_sync(bio); int rw_flags; @@ -1114,7 +1119,14 @@ static int __make_request(struct request_queue *q, struct bio *bio) blk_queue_bounce(q, &bio); barrier = bio_barrier(bio); - if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) { + if (unlikely(barrier) && bio_has_data(bio) && + (q->next_ordered == QUEUE_ORDERED_NONE)) { + err = -EOPNOTSUPP; + goto end_io; + } + + discard = bio_discard(bio); + if (unlikely(discard) && !q->prepare_discard_fn) { err = -EOPNOTSUPP; goto end_io; } @@ -1138,6 +1150,8 @@ static int __make_request(struct request_queue *q, struct bio *bio) req->biotail = bio; req->nr_sectors = req->hard_nr_sectors += nr_sectors; req->ioprio = ioprio_best(req->ioprio, prio); + if (!blk_rq_cpu_valid(req)) + req->cpu = bio->bi_comp_cpu; drive_stat_acct(req, 0); if (!attempt_back_merge(q, req)) elv_merged_request(q, req, el_ret); @@ -1165,6 +1179,8 @@ static int __make_request(struct request_queue *q, struct bio *bio) req->sector = req->hard_sector = bio->bi_sector; req->nr_sectors = req->hard_nr_sectors += nr_sectors; req->ioprio = ioprio_best(req->ioprio, prio); + if (!blk_rq_cpu_valid(req)) + req->cpu = bio->bi_comp_cpu; drive_stat_acct(req, 0); if (!attempt_front_merge(q, req)) elv_merged_request(q, req, el_ret); @@ -1200,13 +1216,15 @@ get_rq: init_request_from_bio(req, bio); spin_lock_irq(q->queue_lock); + if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) || + bio_flagged(bio, BIO_CPU_AFFINE)) + req->cpu = blk_cpu_to_group(smp_processor_id()); if (elv_queue_empty(q)) blk_plug_device(q); add_request(q, req); out: if (sync) __generic_unplug_device(q); - spin_unlock_irq(q->queue_lock); return 0; @@ -1260,8 +1278,9 @@ __setup("fail_make_request=", setup_fail_make_request); static int should_fail_request(struct bio *bio) { - if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) || - (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail)) + struct hd_struct *part = bio->bi_bdev->bd_part; + + if (part_to_disk(part)->part0.make_it_fail || part->make_it_fail) return should_fail(&fail_make_request, bio->bi_size); return 0; @@ -1314,7 +1333,7 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors) } /** - * generic_make_request: hand a buffer to its device driver for I/O + * generic_make_request - hand a buffer to its device driver for I/O * @bio: The bio describing the location in memory and on the device. * * generic_make_request() is used to make I/O requests of block @@ -1409,7 +1428,8 @@ end_io: if (bio_check_eod(bio, nr_sectors)) goto end_io; - if (bio_empty_barrier(bio) && !q->prepare_flush_fn) { + if ((bio_empty_barrier(bio) && !q->prepare_flush_fn) || + (bio_discard(bio) && !q->prepare_discard_fn)) { err = -EOPNOTSUPP; goto end_io; } @@ -1471,13 +1491,13 @@ void generic_make_request(struct bio *bio) EXPORT_SYMBOL(generic_make_request); /** - * submit_bio: submit a bio to the block device layer for I/O + * submit_bio - submit a bio to the block device layer for I/O * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) * @bio: The &struct bio which describes the I/O * * submit_bio() is very similar in purpose to generic_make_request(), and * uses that function to do most of the work. Both are fairly rough - * interfaces, @bio must be presetup and ready for I/O. + * interfaces; @bio must be presetup and ready for I/O. * */ void submit_bio(int rw, struct bio *bio) @@ -1490,11 +1510,7 @@ void submit_bio(int rw, struct bio *bio) * If it's a regular read/write or a barrier with data attached, * go through the normal accounting stuff before submission. */ - if (!bio_empty_barrier(bio)) { - - BIO_BUG_ON(!bio->bi_size); - BIO_BUG_ON(!bio->bi_io_vec); - + if (bio_has_data(bio)) { if (rw & WRITE) { count_vm_events(PGPGOUT, count); } else { @@ -1517,9 +1533,90 @@ void submit_bio(int rw, struct bio *bio) EXPORT_SYMBOL(submit_bio); /** + * blk_rq_check_limits - Helper function to check a request for the queue limit + * @q: the queue + * @rq: the request being checked + * + * Description: + * @rq may have been made based on weaker limitations of upper-level queues + * in request stacking drivers, and it may violate the limitation of @q. + * Since the block layer and the underlying device driver trust @rq + * after it is inserted to @q, it should be checked against @q before + * the insertion using this generic function. + * + * This function should also be useful for request stacking drivers + * in some cases below, so export this fuction. + * Request stacking drivers like request-based dm may change the queue + * limits while requests are in the queue (e.g. dm's table swapping). + * Such request stacking drivers should check those requests agaist + * the new queue limits again when they dispatch those requests, + * although such checkings are also done against the old queue limits + * when submitting requests. + */ +int blk_rq_check_limits(struct request_queue *q, struct request *rq) +{ + if (rq->nr_sectors > q->max_sectors || + rq->data_len > q->max_hw_sectors << 9) { + printk(KERN_ERR "%s: over max size limit.\n", __func__); + return -EIO; + } + + /* + * queue's settings related to segment counting like q->bounce_pfn + * may differ from that of other stacking queues. + * Recalculate it to check the request correctly on this queue's + * limitation. + */ + blk_recalc_rq_segments(rq); + if (rq->nr_phys_segments > q->max_phys_segments || + rq->nr_phys_segments > q->max_hw_segments) { + printk(KERN_ERR "%s: over max segments limit.\n", __func__); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(blk_rq_check_limits); + +/** + * blk_insert_cloned_request - Helper for stacking drivers to submit a request + * @q: the queue to submit the request + * @rq: the request being queued + */ +int blk_insert_cloned_request(struct request_queue *q, struct request *rq) +{ + unsigned long flags; + + if (blk_rq_check_limits(q, rq)) + return -EIO; + +#ifdef CONFIG_FAIL_MAKE_REQUEST + if (rq->rq_disk && rq->rq_disk->part0.make_it_fail && + should_fail(&fail_make_request, blk_rq_bytes(rq))) + return -EIO; +#endif + + spin_lock_irqsave(q->queue_lock, flags); + + /* + * Submitting request must be dequeued before calling this function + * because it will be linked to another request_queue + */ + BUG_ON(blk_queued_rq(rq)); + + drive_stat_acct(rq, 1); + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); + + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(blk_insert_cloned_request); + +/** * __end_that_request_first - end I/O on a request * @req: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * * Description: @@ -1527,8 +1624,8 @@ EXPORT_SYMBOL(submit_bio); * for the next range of segments (if any) in the cluster. * * Return: - * 0 - we are done with this request, call end_that_request_last() - * 1 - still buffers pending for this request + * %0 - we are done with this request, call end_that_request_last() + * %1 - still buffers pending for this request **/ static int __end_that_request_first(struct request *req, int error, int nr_bytes) @@ -1539,7 +1636,7 @@ static int __end_that_request_first(struct request *req, int error, blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE); /* - * for a REQ_BLOCK_PC request, we want to carry any eventual + * for a REQ_TYPE_BLOCK_PC request, we want to carry any eventual * sense key with us all the way through */ if (!blk_pc_request(req)) @@ -1552,11 +1649,14 @@ static int __end_that_request_first(struct request *req, int error, } if (blk_fs_request(req) && req->rq_disk) { - struct hd_struct *part = get_part(req->rq_disk, req->sector); const int rw = rq_data_dir(req); + struct hd_struct *part; + int cpu; - all_stat_add(req->rq_disk, part, sectors[rw], - nr_bytes >> 9, req->sector); + cpu = part_stat_lock(); + part = disk_map_sector_rcu(req->rq_disk, req->sector); + part_stat_add(cpu, part, sectors[rw], nr_bytes >> 9); + part_stat_unlock(); } total_bytes = bio_nbytes = 0; @@ -1641,88 +1741,14 @@ static int __end_that_request_first(struct request *req, int error, } /* - * splice the completion data to a local structure and hand off to - * process_completion_queue() to complete the requests - */ -static void blk_done_softirq(struct softirq_action *h) -{ - struct list_head *cpu_list, local_list; - - local_irq_disable(); - cpu_list = &__get_cpu_var(blk_cpu_done); - list_replace_init(cpu_list, &local_list); - local_irq_enable(); - - while (!list_empty(&local_list)) { - struct request *rq; - - rq = list_entry(local_list.next, struct request, donelist); - list_del_init(&rq->donelist); - rq->q->softirq_done_fn(rq); - } -} - -static int __cpuinit blk_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) -{ - /* - * If a CPU goes away, splice its entries to the current CPU - * and trigger a run of the softirq - */ - if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { - int cpu = (unsigned long) hcpu; - - local_irq_disable(); - list_splice_init(&per_cpu(blk_cpu_done, cpu), - &__get_cpu_var(blk_cpu_done)); - raise_softirq_irqoff(BLOCK_SOFTIRQ); - local_irq_enable(); - } - - return NOTIFY_OK; -} - - -static struct notifier_block blk_cpu_notifier __cpuinitdata = { - .notifier_call = blk_cpu_notify, -}; - -/** - * blk_complete_request - end I/O on a request - * @req: the request being processed - * - * Description: - * Ends all I/O on a request. It does not handle partial completions, - * unless the driver actually implements this in its completion callback - * through requeueing. The actual completion happens out-of-order, - * through a softirq handler. The user must have registered a completion - * callback through blk_queue_softirq_done(). - **/ - -void blk_complete_request(struct request *req) -{ - struct list_head *cpu_list; - unsigned long flags; - - BUG_ON(!req->q->softirq_done_fn); - - local_irq_save(flags); - - cpu_list = &__get_cpu_var(blk_cpu_done); - list_add_tail(&req->donelist, cpu_list); - raise_softirq_irqoff(BLOCK_SOFTIRQ); - - local_irq_restore(flags); -} -EXPORT_SYMBOL(blk_complete_request); - -/* * queue lock must be held */ static void end_that_request_last(struct request *req, int error) { struct gendisk *disk = req->rq_disk; + blk_delete_timer(req); + if (blk_rq_tagged(req)) blk_queue_end_tag(req->q, req); @@ -1740,16 +1766,18 @@ static void end_that_request_last(struct request *req, int error) if (disk && blk_fs_request(req) && req != &req->q->bar_rq) { unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); - struct hd_struct *part = get_part(disk, req->sector); - - __all_stat_inc(disk, part, ios[rw], req->sector); - __all_stat_add(disk, part, ticks[rw], duration, req->sector); - disk_round_stats(disk); - disk->in_flight--; - if (part) { - part_round_stats(part); - part->in_flight--; - } + struct hd_struct *part; + int cpu; + + cpu = part_stat_lock(); + part = disk_map_sector_rcu(disk, req->sector); + + part_stat_inc(cpu, part, ios[rw]); + part_stat_add(cpu, part, ticks[rw], duration); + part_round_stats(cpu, part); + part_dec_in_flight(part); + + part_stat_unlock(); } if (req->end_io) @@ -1762,17 +1790,6 @@ static void end_that_request_last(struct request *req, int error) } } -static inline void __end_request(struct request *rq, int uptodate, - unsigned int nr_bytes) -{ - int error = 0; - - if (uptodate <= 0) - error = uptodate ? uptodate : -EIO; - - __blk_end_request(rq, error, nr_bytes); -} - /** * blk_rq_bytes - Returns bytes left to complete in the entire request * @rq: the request being processed @@ -1803,74 +1820,57 @@ unsigned int blk_rq_cur_bytes(struct request *rq) EXPORT_SYMBOL_GPL(blk_rq_cur_bytes); /** - * end_queued_request - end all I/O on a queued request - * @rq: the request being processed - * @uptodate: error value or 0/1 uptodate flag - * - * Description: - * Ends all I/O on a request, and removes it from the block layer queues. - * Not suitable for normal IO completion, unless the driver still has - * the request attached to the block layer. - * - **/ -void end_queued_request(struct request *rq, int uptodate) -{ - __end_request(rq, uptodate, blk_rq_bytes(rq)); -} -EXPORT_SYMBOL(end_queued_request); - -/** - * end_dequeued_request - end all I/O on a dequeued request - * @rq: the request being processed - * @uptodate: error value or 0/1 uptodate flag - * - * Description: - * Ends all I/O on a request. The request must already have been - * dequeued using blkdev_dequeue_request(), as is normally the case - * for most drivers. - * - **/ -void end_dequeued_request(struct request *rq, int uptodate) -{ - __end_request(rq, uptodate, blk_rq_bytes(rq)); -} -EXPORT_SYMBOL(end_dequeued_request); - - -/** * end_request - end I/O on the current segment of the request * @req: the request being processed - * @uptodate: error value or 0/1 uptodate flag + * @uptodate: error value or %0/%1 uptodate flag * * Description: * Ends I/O on the current segment of a request. If that is the only * remaining segment, the request is also completed and freed. * - * This is a remnant of how older block drivers handled IO completions. - * Modern drivers typically end IO on the full request in one go, unless + * This is a remnant of how older block drivers handled I/O completions. + * Modern drivers typically end I/O on the full request in one go, unless * they have a residual value to account for. For that case this function * isn't really useful, unless the residual just happens to be the * full current segment. In other words, don't use this function in new - * code. Either use end_request_completely(), or the - * end_that_request_chunk() (along with end_that_request_last()) for - * partial completions. - * + * code. Use blk_end_request() or __blk_end_request() to end a request. **/ void end_request(struct request *req, int uptodate) { - __end_request(req, uptodate, req->hard_cur_sectors << 9); + int error = 0; + + if (uptodate <= 0) + error = uptodate ? uptodate : -EIO; + + __blk_end_request(req, error, req->hard_cur_sectors << 9); } EXPORT_SYMBOL(end_request); +static int end_that_request_data(struct request *rq, int error, + unsigned int nr_bytes, unsigned int bidi_bytes) +{ + if (rq->bio) { + if (__end_that_request_first(rq, error, nr_bytes)) + return 1; + + /* Bidi request must be completed as a whole */ + if (blk_bidi_rq(rq) && + __end_that_request_first(rq->next_rq, error, bidi_bytes)) + return 1; + } + + return 0; +} + /** * blk_end_io - Generic end_io function to complete a request. * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete @rq * @bidi_bytes: number of bytes to complete @rq->next_rq * @drv_callback: function called between completion of bios in the request * and completion of the request. - * If the callback returns non 0, this helper returns without + * If the callback returns non %0, this helper returns without * completion of the request. * * Description: @@ -1878,8 +1878,8 @@ EXPORT_SYMBOL(end_request); * If @rq has leftover, sets it up for the next range of segments. * * Return: - * 0 - we are done with this request - * 1 - this request is not freed yet, it still has pending buffers. + * %0 - we are done with this request + * %1 - this request is not freed yet, it still has pending buffers. **/ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, unsigned int bidi_bytes, @@ -1888,15 +1888,8 @@ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, struct request_queue *q = rq->q; unsigned long flags = 0UL; - if (blk_fs_request(rq) || blk_pc_request(rq)) { - if (__end_that_request_first(rq, error, nr_bytes)) - return 1; - - /* Bidi request must be completed as a whole */ - if (blk_bidi_rq(rq) && - __end_that_request_first(rq->next_rq, error, bidi_bytes)) - return 1; - } + if (end_that_request_data(rq, error, nr_bytes, bidi_bytes)) + return 1; /* Special feature for tricky drivers */ if (drv_callback && drv_callback(rq)) @@ -1914,7 +1907,7 @@ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, /** * blk_end_request - Helper function for drivers to complete the request. * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * * Description: @@ -1922,8 +1915,8 @@ static int blk_end_io(struct request *rq, int error, unsigned int nr_bytes, * If @rq has leftover, sets it up for the next range of segments. * * Return: - * 0 - we are done with this request - * 1 - still buffers pending for this request + * %0 - we are done with this request + * %1 - still buffers pending for this request **/ int blk_end_request(struct request *rq, int error, unsigned int nr_bytes) { @@ -1934,22 +1927,20 @@ EXPORT_SYMBOL_GPL(blk_end_request); /** * __blk_end_request - Helper function for drivers to complete the request. * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * * Description: * Must be called with queue lock held unlike blk_end_request(). * * Return: - * 0 - we are done with this request - * 1 - still buffers pending for this request + * %0 - we are done with this request + * %1 - still buffers pending for this request **/ int __blk_end_request(struct request *rq, int error, unsigned int nr_bytes) { - if (blk_fs_request(rq) || blk_pc_request(rq)) { - if (__end_that_request_first(rq, error, nr_bytes)) - return 1; - } + if (rq->bio && __end_that_request_first(rq, error, nr_bytes)) + return 1; add_disk_randomness(rq->rq_disk); @@ -1962,7 +1953,7 @@ EXPORT_SYMBOL_GPL(__blk_end_request); /** * blk_end_bidi_request - Helper function for drivers to complete bidi request. * @rq: the bidi request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete @rq * @bidi_bytes: number of bytes to complete @rq->next_rq * @@ -1970,8 +1961,8 @@ EXPORT_SYMBOL_GPL(__blk_end_request); * Ends I/O on a number of bytes attached to @rq and @rq->next_rq. * * Return: - * 0 - we are done with this request - * 1 - still buffers pending for this request + * %0 - we are done with this request + * %1 - still buffers pending for this request **/ int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes, unsigned int bidi_bytes) @@ -1981,13 +1972,43 @@ int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes, EXPORT_SYMBOL_GPL(blk_end_bidi_request); /** + * blk_update_request - Special helper function for request stacking drivers + * @rq: the request being processed + * @error: %0 for success, < %0 for error + * @nr_bytes: number of bytes to complete @rq + * + * Description: + * Ends I/O on a number of bytes attached to @rq, but doesn't complete + * the request structure even if @rq doesn't have leftover. + * If @rq has leftover, sets it up for the next range of segments. + * + * This special helper function is only for request stacking drivers + * (e.g. request-based dm) so that they can handle partial completion. + * Actual device drivers should use blk_end_request instead. + */ +void blk_update_request(struct request *rq, int error, unsigned int nr_bytes) +{ + if (!end_that_request_data(rq, error, nr_bytes, 0)) { + /* + * These members are not updated in end_that_request_data() + * when all bios are completed. + * Update them so that the request stacking driver can find + * how many bytes remain in the request later. + */ + rq->nr_sectors = rq->hard_nr_sectors = 0; + rq->current_nr_sectors = rq->hard_cur_sectors = 0; + } +} +EXPORT_SYMBOL_GPL(blk_update_request); + +/** * blk_end_request_callback - Special helper function for tricky drivers * @rq: the request being processed - * @error: 0 for success, < 0 for error + * @error: %0 for success, < %0 for error * @nr_bytes: number of bytes to complete * @drv_callback: function called between completion of bios in the request * and completion of the request. - * If the callback returns non 0, this helper returns without + * If the callback returns non %0, this helper returns without * completion of the request. * * Description: @@ -2000,10 +2021,10 @@ EXPORT_SYMBOL_GPL(blk_end_bidi_request); * Don't use this interface in other places anymore. * * Return: - * 0 - we are done with this request - * 1 - this request is not freed yet. - * this request still has pending buffers or - * the driver doesn't want to finish this request yet. + * %0 - we are done with this request + * %1 - this request is not freed yet. + * this request still has pending buffers or + * the driver doesn't want to finish this request yet. **/ int blk_end_request_callback(struct request *rq, int error, unsigned int nr_bytes, @@ -2016,15 +2037,17 @@ EXPORT_SYMBOL_GPL(blk_end_request_callback); void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio) { - /* first two bits are identical in rq->cmd_flags and bio->bi_rw */ + /* Bit 0 (R/W) is identical in rq->cmd_flags and bio->bi_rw, and + we want BIO_RW_AHEAD (bit 1) to imply REQ_FAILFAST (bit 1). */ rq->cmd_flags |= (bio->bi_rw & 3); - rq->nr_phys_segments = bio_phys_segments(q, bio); - rq->nr_hw_segments = bio_hw_segments(q, bio); + if (bio_has_data(bio)) { + rq->nr_phys_segments = bio_phys_segments(q, bio); + rq->buffer = bio_data(bio); + } rq->current_nr_sectors = bio_cur_sectors(bio); rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); - rq->buffer = bio_data(bio); rq->data_len = bio->bi_size; rq->bio = rq->biotail = bio; @@ -2033,7 +2056,35 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, rq->rq_disk = bio->bi_bdev->bd_disk; } -int kblockd_schedule_work(struct work_struct *work) +/** + * blk_lld_busy - Check if underlying low-level drivers of a device are busy + * @q : the queue of the device being checked + * + * Description: + * Check if underlying low-level drivers of a device are busy. + * If the drivers want to export their busy state, they must set own + * exporting function using blk_queue_lld_busy() first. + * + * Basically, this function is used only by request stacking drivers + * to stop dispatching requests to underlying devices when underlying + * devices are busy. This behavior helps more I/O merging on the queue + * of the request stacking driver and prevents I/O throughput regression + * on burst I/O load. + * + * Return: + * 0 - Not busy (The request stacking driver should dispatch request) + * 1 - Busy (The request stacking driver should stop dispatching request) + */ +int blk_lld_busy(struct request_queue *q) +{ + if (q->lld_busy_fn) + return q->lld_busy_fn(q); + + return 0; +} +EXPORT_SYMBOL_GPL(blk_lld_busy); + +int kblockd_schedule_work(struct request_queue *q, struct work_struct *work) { return queue_work(kblockd_workqueue, work); } @@ -2047,8 +2098,6 @@ EXPORT_SYMBOL(kblockd_flush_work); int __init blk_dev_init(void) { - int i; - kblockd_workqueue = create_workqueue("kblockd"); if (!kblockd_workqueue) panic("Failed to create kblockd\n"); @@ -2059,12 +2108,6 @@ int __init blk_dev_init(void) blk_requestq_cachep = kmem_cache_create("blkdev_queue", sizeof(struct request_queue), 0, SLAB_PANIC, NULL); - for_each_possible_cpu(i) - INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); - - open_softirq(BLOCK_SOFTIRQ, blk_done_softirq); - register_hotcpu_notifier(&blk_cpu_notifier); - return 0; } diff --git a/block/blk-exec.c b/block/blk-exec.c index 9bceff7674f2..6af716d1e54e 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -16,7 +16,7 @@ /** * blk_end_sync_rq - executes a completion event on a request * @rq: request to complete - * @error: end io status of the request + * @error: end I/O status of the request */ static void blk_end_sync_rq(struct request *rq, int error) { @@ -41,7 +41,7 @@ static void blk_end_sync_rq(struct request *rq, int error) * @done: I/O completion handler * * Description: - * Insert a fully prepared request at the back of the io scheduler queue + * Insert a fully prepared request at the back of the I/O scheduler queue * for execution. Don't wait for completion. */ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, @@ -72,7 +72,7 @@ EXPORT_SYMBOL_GPL(blk_execute_rq_nowait); * @at_head: insert request at head or tail of queue * * Description: - * Insert a fully prepared request at the back of the io scheduler queue + * Insert a fully prepared request at the back of the I/O scheduler queue * for execution and wait for completion. */ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 3f1a8478cc38..61a8e2f8fdd0 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -108,51 +108,51 @@ new_segment: EXPORT_SYMBOL(blk_rq_map_integrity_sg); /** - * blk_integrity_compare - Compare integrity profile of two block devices - * @b1: Device to compare - * @b2: Device to compare + * blk_integrity_compare - Compare integrity profile of two disks + * @gd1: Disk to compare + * @gd2: Disk to compare * * Description: Meta-devices like DM and MD need to verify that all * sub-devices use the same integrity format before advertising to * upper layers that they can send/receive integrity metadata. This - * function can be used to check whether two block devices have + * function can be used to check whether two gendisk devices have * compatible integrity formats. */ -int blk_integrity_compare(struct block_device *bd1, struct block_device *bd2) +int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) { - struct blk_integrity *b1 = bd1->bd_disk->integrity; - struct blk_integrity *b2 = bd2->bd_disk->integrity; + struct blk_integrity *b1 = gd1->integrity; + struct blk_integrity *b2 = gd2->integrity; - BUG_ON(bd1->bd_disk == NULL); - BUG_ON(bd2->bd_disk == NULL); + if (!b1 && !b2) + return 0; if (!b1 || !b2) - return 0; + return -1; if (b1->sector_size != b2->sector_size) { printk(KERN_ERR "%s: %s/%s sector sz %u != %u\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->sector_size, b2->sector_size); return -1; } if (b1->tuple_size != b2->tuple_size) { printk(KERN_ERR "%s: %s/%s tuple sz %u != %u\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->tuple_size, b2->tuple_size); return -1; } if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { printk(KERN_ERR "%s: %s/%s tag sz %u != %u\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->tag_size, b2->tag_size); return -1; } if (strcmp(b1->name, b2->name)) { printk(KERN_ERR "%s: %s/%s type %s != %s\n", __func__, - bd1->bd_disk->disk_name, bd2->bd_disk->disk_name, + gd1->disk_name, gd2->disk_name, b1->name, b2->name); return -1; } @@ -331,7 +331,8 @@ int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template) return -1; if (kobject_init_and_add(&bi->kobj, &integrity_ktype, - &disk->dev.kobj, "%s", "integrity")) { + &disk_to_dev(disk)->kobj, + "%s", "integrity")) { kmem_cache_free(integrity_cachep, bi); return -1; } @@ -375,7 +376,7 @@ void blk_integrity_unregister(struct gendisk *disk) kobject_uevent(&bi->kobj, KOBJ_REMOVE); kobject_del(&bi->kobj); - kobject_put(&disk->dev.kobj); kmem_cache_free(integrity_cachep, bi); + disk->integrity = NULL; } EXPORT_SYMBOL(blk_integrity_unregister); diff --git a/block/blk-map.c b/block/blk-map.c index af37e4ae62f5..4849fa36161e 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -41,10 +41,10 @@ static int __blk_rq_unmap_user(struct bio *bio) } static int __blk_rq_map_user(struct request_queue *q, struct request *rq, - void __user *ubuf, unsigned int len) + struct rq_map_data *map_data, void __user *ubuf, + unsigned int len, int null_mapped, gfp_t gfp_mask) { unsigned long uaddr; - unsigned int alignment; struct bio *bio, *orig_bio; int reading, ret; @@ -55,15 +55,17 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, * direct dma. else, set up kernel bounce buffers */ uaddr = (unsigned long) ubuf; - alignment = queue_dma_alignment(q) | q->dma_pad_mask; - if (!(uaddr & alignment) && !(len & alignment)) - bio = bio_map_user(q, NULL, uaddr, len, reading); + if (blk_rq_aligned(q, ubuf, len) && !map_data) + bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask); else - bio = bio_copy_user(q, uaddr, len, reading); + bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); + if (null_mapped) + bio->bi_flags |= (1 << BIO_NULL_MAPPED); + orig_bio = bio; blk_queue_bounce(q, &bio); @@ -85,17 +87,19 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, } /** - * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage + * blk_rq_map_user - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request structure to fill + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @ubuf: the user buffer * @len: length of user data + * @gfp_mask: memory allocation flags * * Description: - * Data will be mapped directly for zero copy io, if possible. Otherwise + * Data will be mapped directly for zero copy I/O, if possible. Otherwise * a kernel bounce buffer is used. * - * A matching blk_rq_unmap_user() must be issued at the end of io, while + * A matching blk_rq_unmap_user() must be issued at the end of I/O, while * still in process context. * * Note: The mapped bio may need to be bounced through blk_queue_bounce() @@ -105,16 +109,22 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, * unmapping. */ int blk_rq_map_user(struct request_queue *q, struct request *rq, - void __user *ubuf, unsigned long len) + struct rq_map_data *map_data, void __user *ubuf, + unsigned long len, gfp_t gfp_mask) { unsigned long bytes_read = 0; struct bio *bio = NULL; - int ret; + int ret, null_mapped = 0; if (len > (q->max_hw_sectors << 9)) return -EINVAL; - if (!len || !ubuf) + if (!len) return -EINVAL; + if (!ubuf) { + if (!map_data || rq_data_dir(rq) != READ) + return -EINVAL; + null_mapped = 1; + } while (bytes_read != len) { unsigned long map_len, end, start; @@ -132,7 +142,8 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, if (end - start > BIO_MAX_PAGES) map_len -= PAGE_SIZE; - ret = __blk_rq_map_user(q, rq, ubuf, map_len); + ret = __blk_rq_map_user(q, rq, map_data, ubuf, map_len, + null_mapped, gfp_mask); if (ret < 0) goto unmap_rq; if (!bio) @@ -154,18 +165,20 @@ unmap_rq: EXPORT_SYMBOL(blk_rq_map_user); /** - * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage + * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to map data to + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @iov: pointer to the iovec * @iov_count: number of elements in the iovec * @len: I/O byte count + * @gfp_mask: memory allocation flags * * Description: - * Data will be mapped directly for zero copy io, if possible. Otherwise + * Data will be mapped directly for zero copy I/O, if possible. Otherwise * a kernel bounce buffer is used. * - * A matching blk_rq_unmap_user() must be issued at the end of io, while + * A matching blk_rq_unmap_user() must be issued at the end of I/O, while * still in process context. * * Note: The mapped bio may need to be bounced through blk_queue_bounce() @@ -175,7 +188,8 @@ EXPORT_SYMBOL(blk_rq_map_user); * unmapping. */ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, - struct sg_iovec *iov, int iov_count, unsigned int len) + struct rq_map_data *map_data, struct sg_iovec *iov, + int iov_count, unsigned int len, gfp_t gfp_mask) { struct bio *bio; int i, read = rq_data_dir(rq) == READ; @@ -193,10 +207,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, } } - if (unaligned || (q->dma_pad_mask & len)) - bio = bio_copy_user_iov(q, iov, iov_count, read); + if (unaligned || (q->dma_pad_mask & len) || map_data) + bio = bio_copy_user_iov(q, map_data, iov, iov_count, read, + gfp_mask); else - bio = bio_map_user_iov(q, NULL, iov, iov_count, read); + bio = bio_map_user_iov(q, NULL, iov, iov_count, read, gfp_mask); if (IS_ERR(bio)) return PTR_ERR(bio); @@ -216,6 +231,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, rq->buffer = rq->data = NULL; return 0; } +EXPORT_SYMBOL(blk_rq_map_user_iov); /** * blk_rq_unmap_user - unmap a request with user data @@ -224,7 +240,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, * Description: * Unmap a rq previously mapped by blk_rq_map_user(). The caller must * supply the original rq->bio from the blk_rq_map_user() return, since - * the io completion may have changed rq->bio. + * the I/O completion may have changed rq->bio. */ int blk_rq_unmap_user(struct bio *bio) { @@ -250,7 +266,7 @@ int blk_rq_unmap_user(struct bio *bio) EXPORT_SYMBOL(blk_rq_unmap_user); /** - * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage + * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted * @rq: request to fill * @kbuf: the kernel buffer @@ -264,8 +280,6 @@ EXPORT_SYMBOL(blk_rq_unmap_user); int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, unsigned int len, gfp_t gfp_mask) { - unsigned long kaddr; - unsigned int alignment; int reading = rq_data_dir(rq) == READ; int do_copy = 0; struct bio *bio; @@ -275,11 +289,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, if (!len || !kbuf) return -EINVAL; - kaddr = (unsigned long)kbuf; - alignment = queue_dma_alignment(q) | q->dma_pad_mask; - do_copy = ((kaddr & alignment) || (len & alignment) || - object_is_on_stack(kbuf)); - + do_copy = !blk_rq_aligned(q, kbuf, len) || object_is_on_stack(kbuf); if (do_copy) bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading); else diff --git a/block/blk-merge.c b/block/blk-merge.c index 5efc9e7a68b7..908d3e11ac52 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -11,7 +11,7 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) { - if (blk_fs_request(rq)) { + if (blk_fs_request(rq) || blk_discard_rq(rq)) { rq->hard_sector += nsect; rq->hard_nr_sectors -= nsect; @@ -41,12 +41,9 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) void blk_recalc_rq_segments(struct request *rq) { int nr_phys_segs; - int nr_hw_segs; unsigned int phys_size; - unsigned int hw_size; struct bio_vec *bv, *bvprv = NULL; int seg_size; - int hw_seg_size; int cluster; struct req_iterator iter; int high, highprv = 1; @@ -56,8 +53,8 @@ void blk_recalc_rq_segments(struct request *rq) return; cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); - hw_seg_size = seg_size = 0; - phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; + seg_size = 0; + phys_size = nr_phys_segs = 0; rq_for_each_segment(bv, rq, iter) { /* * the trick here is making sure that a high page is never @@ -66,7 +63,7 @@ void blk_recalc_rq_segments(struct request *rq) */ high = page_to_pfn(bv->bv_page) > q->bounce_pfn; if (high || highprv) - goto new_hw_segment; + goto new_segment; if (cluster) { if (seg_size + bv->bv_len > q->max_segment_size) goto new_segment; @@ -74,40 +71,19 @@ void blk_recalc_rq_segments(struct request *rq) goto new_segment; if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) goto new_segment; - if (BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) - goto new_hw_segment; seg_size += bv->bv_len; - hw_seg_size += bv->bv_len; bvprv = bv; continue; } new_segment: - if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && - !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) - hw_seg_size += bv->bv_len; - else { -new_hw_segment: - if (nr_hw_segs == 1 && - hw_seg_size > rq->bio->bi_hw_front_size) - rq->bio->bi_hw_front_size = hw_seg_size; - hw_seg_size = BIOVEC_VIRT_START_SIZE(bv) + bv->bv_len; - nr_hw_segs++; - } - nr_phys_segs++; bvprv = bv; seg_size = bv->bv_len; highprv = high; } - if (nr_hw_segs == 1 && - hw_seg_size > rq->bio->bi_hw_front_size) - rq->bio->bi_hw_front_size = hw_seg_size; - if (hw_seg_size > rq->biotail->bi_hw_back_size) - rq->biotail->bi_hw_back_size = hw_seg_size; rq->nr_phys_segments = nr_phys_segs; - rq->nr_hw_segments = nr_hw_segs; } void blk_recount_segments(struct request_queue *q, struct bio *bio) @@ -120,7 +96,6 @@ void blk_recount_segments(struct request_queue *q, struct bio *bio) blk_recalc_rq_segments(&rq); bio->bi_next = nxt; bio->bi_phys_segments = rq.nr_phys_segments; - bio->bi_hw_segments = rq.nr_hw_segments; bio->bi_flags |= (1 << BIO_SEG_VALID); } EXPORT_SYMBOL(blk_recount_segments); @@ -131,13 +106,17 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) return 0; - if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt))) - return 0; if (bio->bi_size + nxt->bi_size > q->max_segment_size) return 0; + if (!bio_has_data(bio)) + return 1; + + if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt))) + return 0; + /* - * bio and nxt are contigous in memory, check if the queue allows + * bio and nxt are contiguous in memory; check if the queue allows * these two to be merged into one */ if (BIO_SEG_BOUNDARY(q, bio, nxt)) @@ -146,22 +125,6 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, return 0; } -static int blk_hw_contig_segment(struct request_queue *q, struct bio *bio, - struct bio *nxt) -{ - if (!bio_flagged(bio, BIO_SEG_VALID)) - blk_recount_segments(q, bio); - if (!bio_flagged(nxt, BIO_SEG_VALID)) - blk_recount_segments(q, nxt); - if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) || - BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size)) - return 0; - if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size) - return 0; - - return 1; -} - /* * map a request to scatterlist, return number of sg entries setup. Caller * must make sure sg can hold rq->nr_phys_segments entries @@ -275,10 +238,9 @@ static inline int ll_new_hw_segment(struct request_queue *q, struct request *req, struct bio *bio) { - int nr_hw_segs = bio_hw_segments(q, bio); int nr_phys_segs = bio_phys_segments(q, bio); - if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments + if (req->nr_phys_segments + nr_phys_segs > q->max_hw_segments || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { req->cmd_flags |= REQ_NOMERGE; if (req == q->last_merge) @@ -290,7 +252,6 @@ static inline int ll_new_hw_segment(struct request_queue *q, * This will form the start of a new hw segment. Bump both * counters. */ - req->nr_hw_segments += nr_hw_segs; req->nr_phys_segments += nr_phys_segs; return 1; } @@ -299,7 +260,6 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) { unsigned short max_sectors; - int len; if (unlikely(blk_pc_request(req))) max_sectors = q->max_hw_sectors; @@ -316,19 +276,6 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, blk_recount_segments(q, req->biotail); if (!bio_flagged(bio, BIO_SEG_VALID)) blk_recount_segments(q, bio); - len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size; - if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio)) - && !BIOVEC_VIRT_OVERSIZE(len)) { - int mergeable = ll_new_mergeable(q, req, bio); - - if (mergeable) { - if (req->nr_hw_segments == 1) - req->bio->bi_hw_front_size = len; - if (bio->bi_hw_segments == 1) - bio->bi_hw_back_size = len; - } - return mergeable; - } return ll_new_hw_segment(q, req, bio); } @@ -337,7 +284,6 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) { unsigned short max_sectors; - int len; if (unlikely(blk_pc_request(req))) max_sectors = q->max_hw_sectors; @@ -351,23 +297,10 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req, q->last_merge = NULL; return 0; } - len = bio->bi_hw_back_size + req->bio->bi_hw_front_size; if (!bio_flagged(bio, BIO_SEG_VALID)) blk_recount_segments(q, bio); if (!bio_flagged(req->bio, BIO_SEG_VALID)) blk_recount_segments(q, req->bio); - if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) && - !BIOVEC_VIRT_OVERSIZE(len)) { - int mergeable = ll_new_mergeable(q, req, bio); - - if (mergeable) { - if (bio->bi_hw_segments == 1) - bio->bi_hw_front_size = len; - if (req->nr_hw_segments == 1) - req->biotail->bi_hw_back_size = len; - } - return mergeable; - } return ll_new_hw_segment(q, req, bio); } @@ -376,7 +309,6 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, struct request *next) { int total_phys_segments; - int total_hw_segments; /* * First check if the either of the requests are re-queued @@ -398,26 +330,11 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, if (total_phys_segments > q->max_phys_segments) return 0; - total_hw_segments = req->nr_hw_segments + next->nr_hw_segments; - if (blk_hw_contig_segment(q, req->biotail, next->bio)) { - int len = req->biotail->bi_hw_back_size + - next->bio->bi_hw_front_size; - /* - * propagate the combined length to the end of the requests - */ - if (req->nr_hw_segments == 1) - req->bio->bi_hw_front_size = len; - if (next->nr_hw_segments == 1) - next->biotail->bi_hw_back_size = len; - total_hw_segments--; - } - - if (total_hw_segments > q->max_hw_segments) + if (total_phys_segments > q->max_hw_segments) return 0; /* Merge is OK... */ req->nr_phys_segments = total_phys_segments; - req->nr_hw_segments = total_hw_segments; return 1; } @@ -470,17 +387,21 @@ static int attempt_merge(struct request_queue *q, struct request *req, elv_merge_requests(q, req, next); if (req->rq_disk) { - struct hd_struct *part - = get_part(req->rq_disk, req->sector); - disk_round_stats(req->rq_disk); - req->rq_disk->in_flight--; - if (part) { - part_round_stats(part); - part->in_flight--; - } + struct hd_struct *part; + int cpu; + + cpu = part_stat_lock(); + part = disk_map_sector_rcu(req->rq_disk, req->sector); + + part_round_stats(cpu, part); + part_dec_in_flight(part); + + part_stat_unlock(); } req->ioprio = ioprio_best(req->ioprio, next->ioprio); + if (blk_rq_cpu_valid(next)) + req->cpu = next->cpu; __blk_put_request(q, next); return 1; diff --git a/block/blk-settings.c b/block/blk-settings.c index dfc77012843f..b21dcdb64151 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -33,6 +33,23 @@ void blk_queue_prep_rq(struct request_queue *q, prep_rq_fn *pfn) EXPORT_SYMBOL(blk_queue_prep_rq); /** + * blk_queue_set_discard - set a discard_sectors function for queue + * @q: queue + * @dfn: prepare_discard function + * + * It's possible for a queue to register a discard callback which is used + * to transform a discard request into the appropriate type for the + * hardware. If none is registered, then discard requests are failed + * with %EOPNOTSUPP. + * + */ +void blk_queue_set_discard(struct request_queue *q, prepare_discard_fn *dfn) +{ + q->prepare_discard_fn = dfn; +} +EXPORT_SYMBOL(blk_queue_set_discard); + +/** * blk_queue_merge_bvec - set a merge_bvec function for queue * @q: queue * @mbfn: merge_bvec_fn @@ -60,6 +77,24 @@ void blk_queue_softirq_done(struct request_queue *q, softirq_done_fn *fn) } EXPORT_SYMBOL(blk_queue_softirq_done); +void blk_queue_rq_timeout(struct request_queue *q, unsigned int timeout) +{ + q->rq_timeout = timeout; +} +EXPORT_SYMBOL_GPL(blk_queue_rq_timeout); + +void blk_queue_rq_timed_out(struct request_queue *q, rq_timed_out_fn *fn) +{ + q->rq_timed_out_fn = fn; +} +EXPORT_SYMBOL_GPL(blk_queue_rq_timed_out); + +void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn) +{ + q->lld_busy_fn = fn; +} +EXPORT_SYMBOL_GPL(blk_queue_lld_busy); + /** * blk_queue_make_request - define an alternate make_request function for a device * @q: the request queue for the device to be affected @@ -127,7 +162,7 @@ EXPORT_SYMBOL(blk_queue_make_request); * Different hardware can have different requirements as to what pages * it can do I/O directly to. A low level driver can call * blk_queue_bounce_limit to have lower memory pages allocated as bounce - * buffers for doing I/O to pages residing above @page. + * buffers for doing I/O to pages residing above @dma_addr. **/ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_addr) { @@ -212,7 +247,7 @@ EXPORT_SYMBOL(blk_queue_max_phys_segments); * Description: * Enables a low level driver to set an upper limit on the number of * hw data segments in a request. This would be the largest number of - * address/length pairs the host adapter can actually give as once + * address/length pairs the host adapter can actually give at once * to the device. **/ void blk_queue_max_hw_segments(struct request_queue *q, @@ -393,7 +428,7 @@ EXPORT_SYMBOL(blk_queue_segment_boundary); * @mask: alignment mask * * description: - * set required memory and length aligment for direct dma transactions. + * set required memory and length alignment for direct dma transactions. * this is used when buiding direct io requests for the queue. * **/ @@ -409,7 +444,7 @@ EXPORT_SYMBOL(blk_queue_dma_alignment); * @mask: alignment mask * * description: - * update required memory and length aligment for direct dma transactions. + * update required memory and length alignment for direct dma transactions. * If the requested alignment is larger than the current alignment, then * the current queue alignment is updated to the new value, otherwise it * is left alone. The design of this is to allow multiple objects diff --git a/block/blk-softirq.c b/block/blk-softirq.c new file mode 100644 index 000000000000..e660d26ca656 --- /dev/null +++ b/block/blk-softirq.c @@ -0,0 +1,175 @@ +/* + * Functions related to softirq rq completions + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/bio.h> +#include <linux/blkdev.h> +#include <linux/interrupt.h> +#include <linux/cpu.h> + +#include "blk.h" + +static DEFINE_PER_CPU(struct list_head, blk_cpu_done); + +/* + * Softirq action handler - move entries to local list and loop over them + * while passing them to the queue registered handler. + */ +static void blk_done_softirq(struct softirq_action *h) +{ + struct list_head *cpu_list, local_list; + + local_irq_disable(); + cpu_list = &__get_cpu_var(blk_cpu_done); + list_replace_init(cpu_list, &local_list); + local_irq_enable(); + + while (!list_empty(&local_list)) { + struct request *rq; + + rq = list_entry(local_list.next, struct request, csd.list); + list_del_init(&rq->csd.list); + rq->q->softirq_done_fn(rq); + } +} + +#if defined(CONFIG_SMP) && defined(CONFIG_USE_GENERIC_SMP_HELPERS) +static void trigger_softirq(void *data) +{ + struct request *rq = data; + unsigned long flags; + struct list_head *list; + + local_irq_save(flags); + list = &__get_cpu_var(blk_cpu_done); + list_add_tail(&rq->csd.list, list); + + if (list->next == &rq->csd.list) + raise_softirq_irqoff(BLOCK_SOFTIRQ); + + local_irq_restore(flags); +} + +/* + * Setup and invoke a run of 'trigger_softirq' on the given cpu. + */ +static int raise_blk_irq(int cpu, struct request *rq) +{ + if (cpu_online(cpu)) { + struct call_single_data *data = &rq->csd; + + data->func = trigger_softirq; + data->info = rq; + data->flags = 0; + + __smp_call_function_single(cpu, data); + return 0; + } + + return 1; +} +#else /* CONFIG_SMP && CONFIG_USE_GENERIC_SMP_HELPERS */ +static int raise_blk_irq(int cpu, struct request *rq) +{ + return 1; +} +#endif + +static int __cpuinit blk_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + /* + * If a CPU goes away, splice its entries to the current CPU + * and trigger a run of the softirq + */ + if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { + int cpu = (unsigned long) hcpu; + + local_irq_disable(); + list_splice_init(&per_cpu(blk_cpu_done, cpu), + &__get_cpu_var(blk_cpu_done)); + raise_softirq_irqoff(BLOCK_SOFTIRQ); + local_irq_enable(); + } + + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata blk_cpu_notifier = { + .notifier_call = blk_cpu_notify, +}; + +void __blk_complete_request(struct request *req) +{ + struct request_queue *q = req->q; + unsigned long flags; + int ccpu, cpu, group_cpu; + + BUG_ON(!q->softirq_done_fn); + + local_irq_save(flags); + cpu = smp_processor_id(); + group_cpu = blk_cpu_to_group(cpu); + + /* + * Select completion CPU + */ + if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) && req->cpu != -1) + ccpu = req->cpu; + else + ccpu = cpu; + + if (ccpu == cpu || ccpu == group_cpu) { + struct list_head *list; +do_local: + list = &__get_cpu_var(blk_cpu_done); + list_add_tail(&req->csd.list, list); + + /* + * if the list only contains our just added request, + * signal a raise of the softirq. If there are already + * entries there, someone already raised the irq but it + * hasn't run yet. + */ + if (list->next == &req->csd.list) + raise_softirq_irqoff(BLOCK_SOFTIRQ); + } else if (raise_blk_irq(ccpu, req)) + goto do_local; + + local_irq_restore(flags); +} + +/** + * blk_complete_request - end I/O on a request + * @req: the request being processed + * + * Description: + * Ends all I/O on a request. It does not handle partial completions, + * unless the driver actually implements this in its completion callback + * through requeueing. The actual completion happens out-of-order, + * through a softirq handler. The user must have registered a completion + * callback through blk_queue_softirq_done(). + **/ +void blk_complete_request(struct request *req) +{ + if (unlikely(blk_should_fake_timeout(req->q))) + return; + if (!blk_mark_rq_complete(req)) + __blk_complete_request(req); +} +EXPORT_SYMBOL(blk_complete_request); + +__init int blk_softirq_init(void) +{ + int i; + + for_each_possible_cpu(i) + INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); + + open_softirq(BLOCK_SOFTIRQ, blk_done_softirq); + register_hotcpu_notifier(&blk_cpu_notifier); + return 0; +} +subsys_initcall(blk_softirq_init); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 304ec73ab821..21e275d7eed9 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -156,6 +156,30 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page, return ret; } +static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page) +{ + unsigned int set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags); + + return queue_var_show(set != 0, page); +} + +static ssize_t +queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count) +{ + ssize_t ret = -EINVAL; +#if defined(CONFIG_USE_GENERIC_SMP_HELPERS) + unsigned long val; + + ret = queue_var_store(&val, page, count); + spin_lock_irq(q->queue_lock); + if (val) + queue_flag_set(QUEUE_FLAG_SAME_COMP, q); + else + queue_flag_clear(QUEUE_FLAG_SAME_COMP, q); + spin_unlock_irq(q->queue_lock); +#endif + return ret; +} static struct queue_sysfs_entry queue_requests_entry = { .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, @@ -197,6 +221,12 @@ static struct queue_sysfs_entry queue_nomerges_entry = { .store = queue_nomerges_store, }; +static struct queue_sysfs_entry queue_rq_affinity_entry = { + .attr = {.name = "rq_affinity", .mode = S_IRUGO | S_IWUSR }, + .show = queue_rq_affinity_show, + .store = queue_rq_affinity_store, +}; + static struct attribute *default_attrs[] = { &queue_requests_entry.attr, &queue_ra_entry.attr, @@ -205,6 +235,7 @@ static struct attribute *default_attrs[] = { &queue_iosched_entry.attr, &queue_hw_sector_size_entry.attr, &queue_nomerges_entry.attr, + &queue_rq_affinity_entry.attr, NULL, }; @@ -310,7 +341,7 @@ int blk_register_queue(struct gendisk *disk) if (!q->request_fn) return 0; - ret = kobject_add(&q->kobj, kobject_get(&disk->dev.kobj), + ret = kobject_add(&q->kobj, kobject_get(&disk_to_dev(disk)->kobj), "%s", "queue"); if (ret < 0) return ret; @@ -339,6 +370,6 @@ void blk_unregister_queue(struct gendisk *disk) kobject_uevent(&q->kobj, KOBJ_REMOVE); kobject_del(&q->kobj); - kobject_put(&disk->dev.kobj); + kobject_put(&disk_to_dev(disk)->kobj); } } diff --git a/block/blk-tag.c b/block/blk-tag.c index ed5166fbc599..c0d419e84ce7 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -29,7 +29,7 @@ EXPORT_SYMBOL(blk_queue_find_tag); * __blk_free_tags - release a given set of tag maintenance info * @bqt: the tag map to free * - * Tries to free the specified @bqt@. Returns true if it was + * Tries to free the specified @bqt. Returns true if it was * actually freed and false if there are still references using it */ static int __blk_free_tags(struct blk_queue_tag *bqt) @@ -78,7 +78,7 @@ void __blk_queue_free_tags(struct request_queue *q) * blk_free_tags - release a given set of tag maintenance info * @bqt: the tag map to free * - * For externally managed @bqt@ frees the map. Callers of this + * For externally managed @bqt frees the map. Callers of this * function must guarantee to have released all the queues that * might have been using this tag map. */ @@ -94,7 +94,7 @@ EXPORT_SYMBOL(blk_free_tags); * @q: the request queue for the device * * Notes: - * This is used to disabled tagged queuing to a device, yet leave + * This is used to disable tagged queuing to a device, yet leave * queue in function. **/ void blk_queue_free_tags(struct request_queue *q) @@ -271,7 +271,7 @@ EXPORT_SYMBOL(blk_queue_resize_tags); * @rq: the request that has completed * * Description: - * Typically called when end_that_request_first() returns 0, meaning + * Typically called when end_that_request_first() returns %0, meaning * all transfers have been done for a request. It's important to call * this function before end_that_request_last(), as that will put the * request back on the free list thus corrupting the internal tag list. @@ -337,6 +337,7 @@ EXPORT_SYMBOL(blk_queue_end_tag); int blk_queue_start_tag(struct request_queue *q, struct request *rq) { struct blk_queue_tag *bqt = q->queue_tags; + unsigned max_depth, offset; int tag; if (unlikely((rq->cmd_flags & REQ_QUEUED))) { @@ -350,10 +351,19 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) /* * Protect against shared tag maps, as we may not have exclusive * access to the tag map. + * + * We reserve a few tags just for sync IO, since we don't want + * to starve sync IO on behalf of flooding async IO. */ + max_depth = bqt->max_depth; + if (rq_is_sync(rq)) + offset = 0; + else + offset = max_depth >> 2; + do { - tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); - if (tag >= bqt->max_depth) + tag = find_next_zero_bit(bqt->tag_map, max_depth, offset); + if (tag >= max_depth) return 1; } while (test_and_set_bit_lock(tag, bqt->tag_map)); diff --git a/block/blk-timeout.c b/block/blk-timeout.c new file mode 100644 index 000000000000..972a63f848fb --- /dev/null +++ b/block/blk-timeout.c @@ -0,0 +1,238 @@ +/* + * Functions related to generic timeout handling of requests. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/blkdev.h> +#include <linux/fault-inject.h> + +#include "blk.h" + +#ifdef CONFIG_FAIL_IO_TIMEOUT + +static DECLARE_FAULT_ATTR(fail_io_timeout); + +static int __init setup_fail_io_timeout(char *str) +{ + return setup_fault_attr(&fail_io_timeout, str); +} +__setup("fail_io_timeout=", setup_fail_io_timeout); + +int blk_should_fake_timeout(struct request_queue *q) +{ + if (!test_bit(QUEUE_FLAG_FAIL_IO, &q->queue_flags)) + return 0; + + return should_fail(&fail_io_timeout, 1); +} + +static int __init fail_io_timeout_debugfs(void) +{ + return init_fault_attr_dentries(&fail_io_timeout, "fail_io_timeout"); +} + +late_initcall(fail_io_timeout_debugfs); + +ssize_t part_timeout_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gendisk *disk = dev_to_disk(dev); + int set = test_bit(QUEUE_FLAG_FAIL_IO, &disk->queue->queue_flags); + + return sprintf(buf, "%d\n", set != 0); +} + +ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gendisk *disk = dev_to_disk(dev); + int val; + + if (count) { + struct request_queue *q = disk->queue; + char *p = (char *) buf; + + val = simple_strtoul(p, &p, 10); + spin_lock_irq(q->queue_lock); + if (val) + queue_flag_set(QUEUE_FLAG_FAIL_IO, q); + else + queue_flag_clear(QUEUE_FLAG_FAIL_IO, q); + spin_unlock_irq(q->queue_lock); + } + + return count; +} + +#endif /* CONFIG_FAIL_IO_TIMEOUT */ + +/* + * blk_delete_timer - Delete/cancel timer for a given function. + * @req: request that we are canceling timer for + * + */ +void blk_delete_timer(struct request *req) +{ + struct request_queue *q = req->q; + + /* + * Nothing to detach + */ + if (!q->rq_timed_out_fn || !req->deadline) + return; + + list_del_init(&req->timeout_list); + + if (list_empty(&q->timeout_list)) + del_timer(&q->timeout); +} + +static void blk_rq_timed_out(struct request *req) +{ + struct request_queue *q = req->q; + enum blk_eh_timer_return ret; + + ret = q->rq_timed_out_fn(req); + switch (ret) { + case BLK_EH_HANDLED: + __blk_complete_request(req); + break; + case BLK_EH_RESET_TIMER: + blk_clear_rq_complete(req); + blk_add_timer(req); + break; + case BLK_EH_NOT_HANDLED: + /* + * LLD handles this for now but in the future + * we can send a request msg to abort the command + * and we can move more of the generic scsi eh code to + * the blk layer. + */ + break; + default: + printk(KERN_ERR "block: bad eh return: %d\n", ret); + break; + } +} + +void blk_rq_timed_out_timer(unsigned long data) +{ + struct request_queue *q = (struct request_queue *) data; + unsigned long flags, uninitialized_var(next), next_set = 0; + struct request *rq, *tmp; + + spin_lock_irqsave(q->queue_lock, flags); + + list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) { + if (time_after_eq(jiffies, rq->deadline)) { + list_del_init(&rq->timeout_list); + + /* + * Check if we raced with end io completion + */ + if (blk_mark_rq_complete(rq)) + continue; + blk_rq_timed_out(rq); + } + if (!next_set) { + next = rq->deadline; + next_set = 1; + } else if (time_after(next, rq->deadline)) + next = rq->deadline; + } + + if (next_set && !list_empty(&q->timeout_list)) + mod_timer(&q->timeout, round_jiffies(next)); + + spin_unlock_irqrestore(q->queue_lock, flags); +} + +/** + * blk_abort_request -- Request request recovery for the specified command + * @req: pointer to the request of interest + * + * This function requests that the block layer start recovery for the + * request by deleting the timer and calling the q's timeout function. + * LLDDs who implement their own error recovery MAY ignore the timeout + * event if they generated blk_abort_req. Must hold queue lock. + */ +void blk_abort_request(struct request *req) +{ + if (blk_mark_rq_complete(req)) + return; + blk_delete_timer(req); + blk_rq_timed_out(req); +} +EXPORT_SYMBOL_GPL(blk_abort_request); + +/** + * blk_add_timer - Start timeout timer for a single request + * @req: request that is about to start running. + * + * Notes: + * Each request has its own timer, and as it is added to the queue, we + * set up the timer. When the request completes, we cancel the timer. + */ +void blk_add_timer(struct request *req) +{ + struct request_queue *q = req->q; + unsigned long expiry; + + if (!q->rq_timed_out_fn) + return; + + BUG_ON(!list_empty(&req->timeout_list)); + BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); + + if (req->timeout) + req->deadline = jiffies + req->timeout; + else { + req->deadline = jiffies + q->rq_timeout; + /* + * Some LLDs, like scsi, peek at the timeout to prevent + * a command from being retried forever. + */ + req->timeout = q->rq_timeout; + } + list_add_tail(&req->timeout_list, &q->timeout_list); + + /* + * If the timer isn't already pending or this timeout is earlier + * than an existing one, modify the timer. Round to next nearest + * second. + */ + expiry = round_jiffies(req->deadline); + + /* + * We use ->deadline == 0 to detect whether a timer was added or + * not, so just increase to next jiffy for that specific case + */ + if (unlikely(!req->deadline)) + req->deadline = 1; + + if (!timer_pending(&q->timeout) || + time_before(expiry, q->timeout.expires)) + mod_timer(&q->timeout, expiry); +} + +/** + * blk_abort_queue -- Abort all request on given queue + * @queue: pointer to queue + * + */ +void blk_abort_queue(struct request_queue *q) +{ + unsigned long flags; + struct request *rq, *tmp; + + spin_lock_irqsave(q->queue_lock, flags); + + elv_abort_queue(q); + + list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) + blk_abort_request(rq); + + spin_unlock_irqrestore(q->queue_lock, flags); + +} +EXPORT_SYMBOL_GPL(blk_abort_queue); diff --git a/block/blk.h b/block/blk.h index c79f30e1df52..e5c579769963 100644 --- a/block/blk.h +++ b/block/blk.h @@ -17,6 +17,42 @@ void __blk_queue_free_tags(struct request_queue *q); void blk_unplug_work(struct work_struct *work); void blk_unplug_timeout(unsigned long data); +void blk_rq_timed_out_timer(unsigned long data); +void blk_delete_timer(struct request *); +void blk_add_timer(struct request *); + +/* + * Internal atomic flags for request handling + */ +enum rq_atomic_flags { + REQ_ATOM_COMPLETE = 0, +}; + +/* + * EH timer and IO completion will both attempt to 'grab' the request, make + * sure that only one of them suceeds + */ +static inline int blk_mark_rq_complete(struct request *rq) +{ + return test_and_set_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags); +} + +static inline void blk_clear_rq_complete(struct request *rq) +{ + clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags); +} + +#ifdef CONFIG_FAIL_IO_TIMEOUT +int blk_should_fake_timeout(struct request_queue *); +ssize_t part_timeout_show(struct device *, struct device_attribute *, char *); +ssize_t part_timeout_store(struct device *, struct device_attribute *, + const char *, size_t); +#else +static inline int blk_should_fake_timeout(struct request_queue *q) +{ + return 0; +} +#endif struct io_context *current_io_context(gfp_t gfp_flags, int node); @@ -59,4 +95,16 @@ static inline int queue_congestion_off_threshold(struct request_queue *q) #endif /* BLK_DEV_INTEGRITY */ +static inline int blk_cpu_to_group(int cpu) +{ +#ifdef CONFIG_SCHED_MC + cpumask_t mask = cpu_coregroup_map(cpu); + return first_cpu(mask); +#elif defined(CONFIG_SCHED_SMT) + return first_cpu(per_cpu(cpu_sibling_map, cpu)); +#else + return cpu; +#endif +} + #endif diff --git a/block/blktrace.c b/block/blktrace.c index eb9651ccb241..85049a7e7a17 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -111,23 +111,9 @@ static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, */ static u32 ddir_act[2] __read_mostly = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK_TC_WRITE) }; -/* - * Bio action bits of interest - */ -static u32 bio_act[9] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC), 0, BLK_TC_ACT(BLK_TC_AHEAD), 0, 0, 0, BLK_TC_ACT(BLK_TC_META) }; - -/* - * More could be added as needed, taking care to increment the decrementer - * to get correct indexing - */ -#define trace_barrier_bit(rw) \ - (((rw) & (1 << BIO_RW_BARRIER)) >> (BIO_RW_BARRIER - 0)) -#define trace_sync_bit(rw) \ - (((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1)) -#define trace_ahead_bit(rw) \ - (((rw) & (1 << BIO_RW_AHEAD)) << (2 - BIO_RW_AHEAD)) -#define trace_meta_bit(rw) \ - (((rw) & (1 << BIO_RW_META)) >> (BIO_RW_META - 3)) +/* The ilog2() calls fall out because they're constant */ +#define MASK_TC_BIT(rw, __name) ( (rw & (1 << BIO_RW_ ## __name)) << \ + (ilog2(BLK_TC_ ## __name) + BLK_TC_SHIFT - BIO_RW_ ## __name) ) /* * The worker for the various blk_add_trace*() types. Fills out a @@ -147,10 +133,11 @@ void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, return; what |= ddir_act[rw & WRITE]; - what |= bio_act[trace_barrier_bit(rw)]; - what |= bio_act[trace_sync_bit(rw)]; - what |= bio_act[trace_ahead_bit(rw)]; - what |= bio_act[trace_meta_bit(rw)]; + what |= MASK_TC_BIT(rw, BARRIER); + what |= MASK_TC_BIT(rw, SYNC); + what |= MASK_TC_BIT(rw, AHEAD); + what |= MASK_TC_BIT(rw, META); + what |= MASK_TC_BIT(rw, DISCARD); pid = tsk->pid; if (unlikely(act_log_check(bt, what, sector, pid))) @@ -382,7 +369,8 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, if (!buts->buf_size || !buts->buf_nr) return -EINVAL; - strcpy(buts->name, name); + strncpy(buts->name, name, BLKTRACE_BDEV_SIZE); + buts->name[BLKTRACE_BDEV_SIZE - 1] = '\0'; /* * some device names have larger paths - convert the slashes diff --git a/block/bsg.c b/block/bsg.c index 0aae8d7ba99c..56cb343c76d8 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -283,7 +283,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) next_rq->cmd_type = rq->cmd_type; dxferp = (void*)(unsigned long)hdr->din_xferp; - ret = blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len); + ret = blk_rq_map_user(q, next_rq, NULL, dxferp, + hdr->din_xfer_len, GFP_KERNEL); if (ret) goto out; } @@ -298,7 +299,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) dxfer_len = 0; if (dxfer_len) { - ret = blk_rq_map_user(q, rq, dxferp, dxfer_len); + ret = blk_rq_map_user(q, rq, NULL, dxferp, dxfer_len, + GFP_KERNEL); if (ret) goto out; } diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 1e2aff812ee2..6a062eebbd15 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -39,6 +39,7 @@ static int cfq_slice_idle = HZ / 125; #define CFQ_MIN_TT (2) #define CFQ_SLICE_SCALE (5) +#define CFQ_HW_QUEUE_MIN (5) #define RQ_CIC(rq) \ ((struct cfq_io_context *) (rq)->elevator_private) @@ -86,7 +87,14 @@ struct cfq_data { int rq_in_driver; int sync_flight; + + /* + * queue-depth detection + */ + int rq_queued; int hw_tag; + int hw_tag_samples; + int rq_in_driver_peak; /* * idle window management @@ -244,7 +252,7 @@ static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) { if (cfqd->busy_queues) { cfq_log(cfqd, "schedule dispatch"); - kblockd_schedule_work(&cfqd->unplug_work); + kblockd_schedule_work(cfqd->queue, &cfqd->unplug_work); } } @@ -654,15 +662,6 @@ static void cfq_activate_request(struct request_queue *q, struct request *rq) cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "activate rq, drv=%d", cfqd->rq_in_driver); - /* - * If the depth is larger 1, it really could be queueing. But lets - * make the mark a little higher - idling could still be good for - * low queueing, and a low queueing number could also just indicate - * a SCSI mid layer like behaviour where limit+1 is often seen. - */ - if (!cfqd->hw_tag && cfqd->rq_in_driver > 4) - cfqd->hw_tag = 1; - cfqd->last_position = rq->hard_sector + rq->hard_nr_sectors; } @@ -686,6 +685,7 @@ static void cfq_remove_request(struct request *rq) list_del_init(&rq->queuelist); cfq_del_rq_rb(rq); + cfqq->cfqd->rq_queued--; if (rq_is_meta(rq)) { WARN_ON(!cfqq->meta_pending); cfqq->meta_pending--; @@ -878,6 +878,14 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) struct cfq_io_context *cic; unsigned long sl; + /* + * SSD device without seek penalty, disable idling. But only do so + * for devices that support queuing, otherwise we still have a problem + * with sync vs async workloads. + */ + if (blk_queue_nonrot(cfqd->queue) && cfqd->hw_tag) + return; + WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list)); WARN_ON(cfq_cfqq_slice_new(cfqq)); @@ -1833,6 +1841,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, { struct cfq_io_context *cic = RQ_CIC(rq); + cfqd->rq_queued++; if (rq_is_meta(rq)) cfqq->meta_pending++; @@ -1880,6 +1889,31 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) cfq_rq_enqueued(cfqd, cfqq, rq); } +/* + * Update hw_tag based on peak queue depth over 50 samples under + * sufficient load. + */ +static void cfq_update_hw_tag(struct cfq_data *cfqd) +{ + if (cfqd->rq_in_driver > cfqd->rq_in_driver_peak) + cfqd->rq_in_driver_peak = cfqd->rq_in_driver; + + if (cfqd->rq_queued <= CFQ_HW_QUEUE_MIN && + cfqd->rq_in_driver <= CFQ_HW_QUEUE_MIN) + return; + + if (cfqd->hw_tag_samples++ < 50) + return; + + if (cfqd->rq_in_driver_peak >= CFQ_HW_QUEUE_MIN) + cfqd->hw_tag = 1; + else + cfqd->hw_tag = 0; + + cfqd->hw_tag_samples = 0; + cfqd->rq_in_driver_peak = 0; +} + static void cfq_completed_request(struct request_queue *q, struct request *rq) { struct cfq_queue *cfqq = RQ_CFQQ(rq); @@ -1890,6 +1924,8 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) now = jiffies; cfq_log_cfqq(cfqd, cfqq, "complete"); + cfq_update_hw_tag(cfqd); + WARN_ON(!cfqd->rq_in_driver); WARN_ON(!cfqq->dispatched); cfqd->rq_in_driver--; @@ -2200,6 +2236,7 @@ static void *cfq_init_queue(struct request_queue *q) cfqd->cfq_slice[1] = cfq_slice_sync; cfqd->cfq_slice_async_rq = cfq_slice_async_rq; cfqd->cfq_slice_idle = cfq_slice_idle; + cfqd->hw_tag = 1; return cfqd; } diff --git a/block/cmd-filter.c b/block/cmd-filter.c index 79c14996ac11..e669aed4c6bc 100644 --- a/block/cmd-filter.c +++ b/block/cmd-filter.c @@ -211,14 +211,10 @@ int blk_register_filter(struct gendisk *disk) { int ret; struct blk_cmd_filter *filter = &disk->queue->cmd_filter; - struct kobject *parent = kobject_get(disk->holder_dir->parent); - if (!parent) - return -ENODEV; - - ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, parent, + ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, + &disk_to_dev(disk)->kobj, "%s", "cmd_filter"); - if (ret < 0) return ret; @@ -231,7 +227,6 @@ void blk_unregister_filter(struct gendisk *disk) struct blk_cmd_filter *filter = &disk->queue->cmd_filter; kobject_put(&filter->kobj); - kobject_put(disk->holder_dir->parent); } EXPORT_SYMBOL(blk_unregister_filter); #endif diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index c23177e4623f..1e559fba7bdf 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -788,6 +788,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); case BLKFLSBUF: case BLKROSET: + case BLKDISCARD: /* * the ones below are implemented in blkdev_locked_ioctl, * but we call blkdev_ioctl, which gets the lock for us diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 342448c3d2dd..fd311179f44c 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -33,7 +33,7 @@ struct deadline_data { */ struct rb_root sort_list[2]; struct list_head fifo_list[2]; - + /* * next in sort order. read, write or both are NULL */ @@ -53,7 +53,11 @@ struct deadline_data { static void deadline_move_request(struct deadline_data *, struct request *); -#define RQ_RB_ROOT(dd, rq) (&(dd)->sort_list[rq_data_dir((rq))]) +static inline struct rb_root * +deadline_rb_root(struct deadline_data *dd, struct request *rq) +{ + return &dd->sort_list[rq_data_dir(rq)]; +} /* * get the request after `rq' in sector-sorted order @@ -72,15 +76,11 @@ deadline_latter_request(struct request *rq) static void deadline_add_rq_rb(struct deadline_data *dd, struct request *rq) { - struct rb_root *root = RQ_RB_ROOT(dd, rq); + struct rb_root *root = deadline_rb_root(dd, rq); struct request *__alias; -retry: - __alias = elv_rb_add(root, rq); - if (unlikely(__alias)) { + while (unlikely(__alias = elv_rb_add(root, rq))) deadline_move_request(dd, __alias); - goto retry; - } } static inline void @@ -91,7 +91,7 @@ deadline_del_rq_rb(struct deadline_data *dd, struct request *rq) if (dd->next_rq[data_dir] == rq) dd->next_rq[data_dir] = deadline_latter_request(rq); - elv_rb_del(RQ_RB_ROOT(dd, rq), rq); + elv_rb_del(deadline_rb_root(dd, rq), rq); } /* @@ -106,7 +106,7 @@ deadline_add_request(struct request_queue *q, struct request *rq) deadline_add_rq_rb(dd, rq); /* - * set expire time (only used for reads) and add to fifo list + * set expire time and add to fifo list */ rq_set_fifo_time(rq, jiffies + dd->fifo_expire[data_dir]); list_add_tail(&rq->queuelist, &dd->fifo_list[data_dir]); @@ -162,7 +162,7 @@ static void deadline_merged_request(struct request_queue *q, * if the merge was a front merge, we need to reposition request */ if (type == ELEVATOR_FRONT_MERGE) { - elv_rb_del(RQ_RB_ROOT(dd, req), req); + elv_rb_del(deadline_rb_root(dd, req), req); deadline_add_rq_rb(dd, req); } } @@ -212,7 +212,7 @@ deadline_move_request(struct deadline_data *dd, struct request *rq) dd->next_rq[WRITE] = NULL; dd->next_rq[data_dir] = deadline_latter_request(rq); - dd->last_sector = rq->sector + rq->nr_sectors; + dd->last_sector = rq_end_sector(rq); /* * take it off the sort and fifo list, move @@ -222,7 +222,7 @@ deadline_move_request(struct deadline_data *dd, struct request *rq) } /* - * deadline_check_fifo returns 0 if there are no expired reads on the fifo, + * deadline_check_fifo returns 0 if there are no expired requests on the fifo, * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir]) */ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) @@ -258,17 +258,9 @@ static int deadline_dispatch_requests(struct request_queue *q, int force) else rq = dd->next_rq[READ]; - if (rq) { - /* we have a "next request" */ - - if (dd->last_sector != rq->sector) - /* end the batch on a non sequential request */ - dd->batching += dd->fifo_batch; - - if (dd->batching < dd->fifo_batch) - /* we are still entitled to batch */ - goto dispatch_request; - } + if (rq && dd->batching < dd->fifo_batch) + /* we have a next request are still entitled to batch */ + goto dispatch_request; /* * at this point we are not running a batch. select the appropriate diff --git a/block/elevator.c b/block/elevator.c index ed6f8f32d27e..04518921db31 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -34,8 +34,9 @@ #include <linux/delay.h> #include <linux/blktrace_api.h> #include <linux/hash.h> +#include <linux/uaccess.h> -#include <asm/uaccess.h> +#include "blk.h" static DEFINE_SPINLOCK(elv_list_lock); static LIST_HEAD(elv_list); @@ -75,6 +76,12 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio) return 0; /* + * Don't merge file system requests and discard requests + */ + if (bio_discard(bio) != bio_discard(rq->bio)) + return 0; + + /* * different data direction or already started, don't merge */ if (bio_data_dir(bio) != rq_data_dir(rq)) @@ -438,6 +445,8 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) list_for_each_prev(entry, &q->queue_head) { struct request *pos = list_entry_rq(entry); + if (blk_discard_rq(rq) != blk_discard_rq(pos)) + break; if (rq_data_dir(rq) != rq_data_dir(pos)) break; if (pos->cmd_flags & stop_flags) @@ -607,7 +616,7 @@ void elv_insert(struct request_queue *q, struct request *rq, int where) break; case ELEVATOR_INSERT_SORT: - BUG_ON(!blk_fs_request(rq)); + BUG_ON(!blk_fs_request(rq) && !blk_discard_rq(rq)); rq->cmd_flags |= REQ_SORTED; q->nr_sorted++; if (rq_mergeable(rq)) { @@ -692,7 +701,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where, * this request is scheduling boundary, update * end_sector */ - if (blk_fs_request(rq)) { + if (blk_fs_request(rq) || blk_discard_rq(rq)) { q->end_sector = rq_end_sector(rq); q->boundary_rq = rq; } @@ -745,7 +754,7 @@ struct request *elv_next_request(struct request_queue *q) * not ever see it. */ if (blk_empty_barrier(rq)) { - end_queued_request(rq, 1); + __blk_end_request(rq, 0, blk_rq_bytes(rq)); continue; } if (!(rq->cmd_flags & REQ_STARTED)) { @@ -764,6 +773,12 @@ struct request *elv_next_request(struct request_queue *q) */ rq->cmd_flags |= REQ_STARTED; blk_add_trace_rq(q, rq, BLK_TA_ISSUE); + + /* + * We are now handing the request to the hardware, + * add the timeout handler + */ + blk_add_timer(rq); } if (!q->boundary_rq || q->boundary_rq == rq) { @@ -782,7 +797,6 @@ struct request *elv_next_request(struct request_queue *q) * device can handle */ rq->nr_phys_segments++; - rq->nr_hw_segments++; } if (!q->prep_rq_fn) @@ -805,14 +819,13 @@ struct request *elv_next_request(struct request_queue *q) * so that we don't add it again */ --rq->nr_phys_segments; - --rq->nr_hw_segments; } rq = NULL; break; } else if (ret == BLKPREP_KILL) { rq->cmd_flags |= REQ_QUIET; - end_queued_request(rq, 0); + __blk_end_request(rq, -EIO, blk_rq_bytes(rq)); } else { printk(KERN_ERR "%s: bad return=%d\n", __func__, ret); break; @@ -901,6 +914,19 @@ int elv_may_queue(struct request_queue *q, int rw) return ELV_MQUEUE_MAY; } +void elv_abort_queue(struct request_queue *q) +{ + struct request *rq; + + while (!list_empty(&q->queue_head)) { + rq = list_entry_rq(q->queue_head.next); + rq->cmd_flags |= REQ_QUIET; + blk_add_trace_rq(q, rq, BLK_TA_ABORT); + __blk_end_request(rq, -EIO, blk_rq_bytes(rq)); + } +} +EXPORT_SYMBOL(elv_abort_queue); + void elv_completed_request(struct request_queue *q, struct request *rq) { elevator_t *e = q->elevator; diff --git a/block/genhd.c b/block/genhd.c index e0ce23ac2ece..4cd3433c99ac 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -16,6 +16,7 @@ #include <linux/kobj_map.h> #include <linux/buffer_head.h> #include <linux/mutex.h> +#include <linux/idr.h> #include "blk.h" @@ -24,8 +25,194 @@ static DEFINE_MUTEX(block_class_lock); struct kobject *block_depr; #endif +/* for extended dynamic devt allocation, currently only one major is used */ +#define MAX_EXT_DEVT (1 << MINORBITS) + +/* For extended devt allocation. ext_devt_mutex prevents look up + * results from going away underneath its user. + */ +static DEFINE_MUTEX(ext_devt_mutex); +static DEFINE_IDR(ext_devt_idr); + static struct device_type disk_type; +/** + * disk_get_part - get partition + * @disk: disk to look partition from + * @partno: partition number + * + * Look for partition @partno from @disk. If found, increment + * reference count and return it. + * + * CONTEXT: + * Don't care. + * + * RETURNS: + * Pointer to the found partition on success, NULL if not found. + */ +struct hd_struct *disk_get_part(struct gendisk *disk, int partno) +{ + struct hd_struct *part = NULL; + struct disk_part_tbl *ptbl; + + if (unlikely(partno < 0)) + return NULL; + + rcu_read_lock(); + + ptbl = rcu_dereference(disk->part_tbl); + if (likely(partno < ptbl->len)) { + part = rcu_dereference(ptbl->part[partno]); + if (part) + get_device(part_to_dev(part)); + } + + rcu_read_unlock(); + + return part; +} +EXPORT_SYMBOL_GPL(disk_get_part); + +/** + * disk_part_iter_init - initialize partition iterator + * @piter: iterator to initialize + * @disk: disk to iterate over + * @flags: DISK_PITER_* flags + * + * Initialize @piter so that it iterates over partitions of @disk. + * + * CONTEXT: + * Don't care. + */ +void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk, + unsigned int flags) +{ + struct disk_part_tbl *ptbl; + + rcu_read_lock(); + ptbl = rcu_dereference(disk->part_tbl); + + piter->disk = disk; + piter->part = NULL; + + if (flags & DISK_PITER_REVERSE) + piter->idx = ptbl->len - 1; + else if (flags & DISK_PITER_INCL_PART0) + piter->idx = 0; + else + piter->idx = 1; + + piter->flags = flags; + + rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(disk_part_iter_init); + +/** + * disk_part_iter_next - proceed iterator to the next partition and return it + * @piter: iterator of interest + * + * Proceed @piter to the next partition and return it. + * + * CONTEXT: + * Don't care. + */ +struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) +{ + struct disk_part_tbl *ptbl; + int inc, end; + + /* put the last partition */ + disk_put_part(piter->part); + piter->part = NULL; + + /* get part_tbl */ + rcu_read_lock(); + ptbl = rcu_dereference(piter->disk->part_tbl); + + /* determine iteration parameters */ + if (piter->flags & DISK_PITER_REVERSE) { + inc = -1; + if (piter->flags & DISK_PITER_INCL_PART0) + end = -1; + else + end = 0; + } else { + inc = 1; + end = ptbl->len; + } + + /* iterate to the next partition */ + for (; piter->idx != end; piter->idx += inc) { + struct hd_struct *part; + + part = rcu_dereference(ptbl->part[piter->idx]); + if (!part) + continue; + if (!(piter->flags & DISK_PITER_INCL_EMPTY) && !part->nr_sects) + continue; + + get_device(part_to_dev(part)); + piter->part = part; + piter->idx += inc; + break; + } + + rcu_read_unlock(); + + return piter->part; +} +EXPORT_SYMBOL_GPL(disk_part_iter_next); + +/** + * disk_part_iter_exit - finish up partition iteration + * @piter: iter of interest + * + * Called when iteration is over. Cleans up @piter. + * + * CONTEXT: + * Don't care. + */ +void disk_part_iter_exit(struct disk_part_iter *piter) +{ + disk_put_part(piter->part); + piter->part = NULL; +} +EXPORT_SYMBOL_GPL(disk_part_iter_exit); + +/** + * disk_map_sector_rcu - map sector to partition + * @disk: gendisk of interest + * @sector: sector to map + * + * Find out which partition @sector maps to on @disk. This is + * primarily used for stats accounting. + * + * CONTEXT: + * RCU read locked. The returned partition pointer is valid only + * while preemption is disabled. + * + * RETURNS: + * Found partition on success, part0 is returned if no partition matches + */ +struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) +{ + struct disk_part_tbl *ptbl; + int i; + + ptbl = rcu_dereference(disk->part_tbl); + + for (i = 1; i < ptbl->len; i++) { + struct hd_struct *part = rcu_dereference(ptbl->part[i]); + + if (part && part->start_sect <= sector && + sector < part->start_sect + part->nr_sects) + return part; + } + return &disk->part0; +} +EXPORT_SYMBOL_GPL(disk_map_sector_rcu); + /* * Can be deleted altogether. Later. * @@ -43,14 +230,14 @@ static inline int major_to_index(int major) } #ifdef CONFIG_PROC_FS -void blkdev_show(struct seq_file *f, off_t offset) +void blkdev_show(struct seq_file *seqf, off_t offset) { struct blk_major_name *dp; if (offset < BLKDEV_MAJOR_HASH_SIZE) { mutex_lock(&block_class_lock); for (dp = major_names[offset]; dp; dp = dp->next) - seq_printf(f, "%3d %s\n", dp->major, dp->name); + seq_printf(seqf, "%3d %s\n", dp->major, dp->name); mutex_unlock(&block_class_lock); } } @@ -136,6 +323,118 @@ EXPORT_SYMBOL(unregister_blkdev); static struct kobj_map *bdev_map; +/** + * blk_mangle_minor - scatter minor numbers apart + * @minor: minor number to mangle + * + * Scatter consecutively allocated @minor number apart if MANGLE_DEVT + * is enabled. Mangling twice gives the original value. + * + * RETURNS: + * Mangled value. + * + * CONTEXT: + * Don't care. + */ +static int blk_mangle_minor(int minor) +{ +#ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT + int i; + + for (i = 0; i < MINORBITS / 2; i++) { + int low = minor & (1 << i); + int high = minor & (1 << (MINORBITS - 1 - i)); + int distance = MINORBITS - 1 - 2 * i; + + minor ^= low | high; /* clear both bits */ + low <<= distance; /* swap the positions */ + high >>= distance; + minor |= low | high; /* and set */ + } +#endif + return minor; +} + +/** + * blk_alloc_devt - allocate a dev_t for a partition + * @part: partition to allocate dev_t for + * @gfp_mask: memory allocation flag + * @devt: out parameter for resulting dev_t + * + * Allocate a dev_t for block device. + * + * RETURNS: + * 0 on success, allocated dev_t is returned in *@devt. -errno on + * failure. + * + * CONTEXT: + * Might sleep. + */ +int blk_alloc_devt(struct hd_struct *part, dev_t *devt) +{ + struct gendisk *disk = part_to_disk(part); + int idx, rc; + + /* in consecutive minor range? */ + if (part->partno < disk->minors) { + *devt = MKDEV(disk->major, disk->first_minor + part->partno); + return 0; + } + + /* allocate ext devt */ + do { + if (!idr_pre_get(&ext_devt_idr, GFP_KERNEL)) + return -ENOMEM; + rc = idr_get_new(&ext_devt_idr, part, &idx); + } while (rc == -EAGAIN); + + if (rc) + return rc; + + if (idx > MAX_EXT_DEVT) { + idr_remove(&ext_devt_idr, idx); + return -EBUSY; + } + + *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx)); + return 0; +} + +/** + * blk_free_devt - free a dev_t + * @devt: dev_t to free + * + * Free @devt which was allocated using blk_alloc_devt(). + * + * CONTEXT: + * Might sleep. + */ +void blk_free_devt(dev_t devt) +{ + might_sleep(); + + if (devt == MKDEV(0, 0)) + return; + + if (MAJOR(devt) == BLOCK_EXT_MAJOR) { + mutex_lock(&ext_devt_mutex); + idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); + mutex_unlock(&ext_devt_mutex); + } +} + +static char *bdevt_str(dev_t devt, char *buf) +{ + if (MAJOR(devt) <= 0xff && MINOR(devt) <= 0xff) { + char tbuf[BDEVT_SIZE]; + snprintf(tbuf, BDEVT_SIZE, "%02x%02x", MAJOR(devt), MINOR(devt)); + snprintf(buf, BDEVT_SIZE, "%-9s", tbuf); + } else + snprintf(buf, BDEVT_SIZE, "%03x:%05x", MAJOR(devt), MINOR(devt)); + + return buf; +} + /* * Register device numbers dev..(dev+range-1) * range must be nonzero @@ -157,11 +456,11 @@ void blk_unregister_region(dev_t devt, unsigned long range) EXPORT_SYMBOL(blk_unregister_region); -static struct kobject *exact_match(dev_t devt, int *part, void *data) +static struct kobject *exact_match(dev_t devt, int *partno, void *data) { struct gendisk *p = data; - return &p->dev.kobj; + return &disk_to_dev(p)->kobj; } static int exact_lock(dev_t devt, void *data) @@ -179,21 +478,46 @@ static int exact_lock(dev_t devt, void *data) * * This function registers the partitioning information in @disk * with the kernel. + * + * FIXME: error handling */ void add_disk(struct gendisk *disk) { struct backing_dev_info *bdi; + dev_t devt; int retval; + /* minors == 0 indicates to use ext devt from part0 and should + * be accompanied with EXT_DEVT flag. Make sure all + * parameters make sense. + */ + WARN_ON(disk->minors && !(disk->major || disk->first_minor)); + WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT)); + disk->flags |= GENHD_FL_UP; - blk_register_region(MKDEV(disk->major, disk->first_minor), - disk->minors, NULL, exact_match, exact_lock, disk); + + retval = blk_alloc_devt(&disk->part0, &devt); + if (retval) { + WARN_ON(1); + return; + } + disk_to_dev(disk)->devt = devt; + + /* ->major and ->first_minor aren't supposed to be + * dereferenced from here on, but set them just in case. + */ + disk->major = MAJOR(devt); + disk->first_minor = MINOR(devt); + + blk_register_region(disk_devt(disk), disk->minors, NULL, + exact_match, exact_lock, disk); register_disk(disk); blk_register_queue(disk); bdi = &disk->queue->backing_dev_info; - bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); - retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); + bdi_register_dev(bdi, disk_devt(disk)); + retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj, + "bdi"); WARN_ON(retval); } @@ -202,78 +526,71 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */ void unlink_gendisk(struct gendisk *disk) { - sysfs_remove_link(&disk->dev.kobj, "bdi"); + sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi"); bdi_unregister(&disk->queue->backing_dev_info); blk_unregister_queue(disk); - blk_unregister_region(MKDEV(disk->major, disk->first_minor), - disk->minors); + blk_unregister_region(disk_devt(disk), disk->minors); } /** * get_gendisk - get partitioning information for a given device - * @dev: device to get partitioning information for + * @devt: device to get partitioning information for + * @part: returned partition index * * This function gets the structure containing partitioning - * information for the given device @dev. + * information for the given device @devt. */ -struct gendisk *get_gendisk(dev_t devt, int *part) +struct gendisk *get_gendisk(dev_t devt, int *partno) { - struct kobject *kobj = kobj_lookup(bdev_map, devt, part); - struct device *dev = kobj_to_dev(kobj); + struct gendisk *disk = NULL; + + if (MAJOR(devt) != BLOCK_EXT_MAJOR) { + struct kobject *kobj; + + kobj = kobj_lookup(bdev_map, devt, partno); + if (kobj) + disk = dev_to_disk(kobj_to_dev(kobj)); + } else { + struct hd_struct *part; - return kobj ? dev_to_disk(dev) : NULL; + mutex_lock(&ext_devt_mutex); + part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); + if (part && get_disk(part_to_disk(part))) { + *partno = part->partno; + disk = part_to_disk(part); + } + mutex_unlock(&ext_devt_mutex); + } + + return disk; } -/* - * print a partitions - intended for places where the root filesystem can't be - * mounted and thus to give the victim some idea of what went wrong +/** + * bdget_disk - do bdget() by gendisk and partition number + * @disk: gendisk of interest + * @partno: partition number + * + * Find partition @partno from @disk, do bdget() on it. + * + * CONTEXT: + * Don't care. + * + * RETURNS: + * Resulting block_device on success, NULL on failure. */ -static int printk_partition(struct device *dev, void *data) +struct block_device *bdget_disk(struct gendisk *disk, int partno) { - struct gendisk *sgp; - char buf[BDEVNAME_SIZE]; - int n; - - if (dev->type != &disk_type) - goto exit; + struct hd_struct *part; + struct block_device *bdev = NULL; - sgp = dev_to_disk(dev); - /* - * Don't show empty devices or things that have been surpressed - */ - if (get_capacity(sgp) == 0 || - (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) - goto exit; + part = disk_get_part(disk, partno); + if (part) + bdev = bdget(part_devt(part)); + disk_put_part(part); - /* - * Note, unlike /proc/partitions, I am showing the numbers in - * hex - the same format as the root= option takes. - */ - printk("%02x%02x %10llu %s", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - if (sgp->driverfs_dev != NULL && - sgp->driverfs_dev->driver != NULL) - printk(" driver: %s\n", - sgp->driverfs_dev->driver->name); - else - printk(" (driver?)\n"); - - /* now show the partitions */ - for (n = 0; n < sgp->minors - 1; ++n) { - if (sgp->part[n] == NULL) - goto exit; - if (sgp->part[n]->nr_sects == 0) - goto exit; - printk(" %02x%02x %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1, - disk_name(sgp, n + 1, buf)); - } -exit: - return 0; + return bdev; } +EXPORT_SYMBOL(bdget_disk); /* * print a full list of all partitions - intended for places where the root @@ -282,120 +599,145 @@ exit: */ void __init printk_all_partitions(void) { - mutex_lock(&block_class_lock); - class_for_each_device(&block_class, NULL, NULL, printk_partition); - mutex_unlock(&block_class_lock); + struct class_dev_iter iter; + struct device *dev; + + class_dev_iter_init(&iter, &block_class, NULL, &disk_type); + while ((dev = class_dev_iter_next(&iter))) { + struct gendisk *disk = dev_to_disk(dev); + struct disk_part_iter piter; + struct hd_struct *part; + char name_buf[BDEVNAME_SIZE]; + char devt_buf[BDEVT_SIZE]; + + /* + * Don't show empty devices or things that have been + * surpressed + */ + if (get_capacity(disk) == 0 || + (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) + continue; + + /* + * Note, unlike /proc/partitions, I am showing the + * numbers in hex - the same format as the root= + * option takes. + */ + disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0); + while ((part = disk_part_iter_next(&piter))) { + bool is_part0 = part == &disk->part0; + + printk("%s%s %10llu %s", is_part0 ? "" : " ", + bdevt_str(part_devt(part), devt_buf), + (unsigned long long)part->nr_sects >> 1, + disk_name(disk, part->partno, name_buf)); + if (is_part0) { + if (disk->driverfs_dev != NULL && + disk->driverfs_dev->driver != NULL) + printk(" driver: %s\n", + disk->driverfs_dev->driver->name); + else + printk(" (driver?)\n"); + } else + printk("\n"); + } + disk_part_iter_exit(&piter); + } + class_dev_iter_exit(&iter); } #ifdef CONFIG_PROC_FS /* iterator */ -static int find_start(struct device *dev, void *data) +static void *disk_seqf_start(struct seq_file *seqf, loff_t *pos) { - loff_t *k = data; + loff_t skip = *pos; + struct class_dev_iter *iter; + struct device *dev; - if (dev->type != &disk_type) - return 0; - if (!*k) - return 1; - (*k)--; - return 0; + iter = kmalloc(sizeof(*iter), GFP_KERNEL); + if (!iter) + return ERR_PTR(-ENOMEM); + + seqf->private = iter; + class_dev_iter_init(iter, &block_class, NULL, &disk_type); + do { + dev = class_dev_iter_next(iter); + if (!dev) + return NULL; + } while (skip--); + + return dev_to_disk(dev); } -static void *part_start(struct seq_file *part, loff_t *pos) +static void *disk_seqf_next(struct seq_file *seqf, void *v, loff_t *pos) { struct device *dev; - loff_t k = *pos; - - if (!k) - part->private = (void *)1LU; /* tell show to print header */ - mutex_lock(&block_class_lock); - dev = class_find_device(&block_class, NULL, &k, find_start); - if (dev) { - put_device(dev); + (*pos)++; + dev = class_dev_iter_next(seqf->private); + if (dev) return dev_to_disk(dev); - } + return NULL; } -static int find_next(struct device *dev, void *data) +static void disk_seqf_stop(struct seq_file *seqf, void *v) { - if (dev->type == &disk_type) - return 1; - return 0; -} + struct class_dev_iter *iter = seqf->private; -static void *part_next(struct seq_file *part, void *v, loff_t *pos) -{ - struct gendisk *gp = v; - struct device *dev; - ++*pos; - dev = class_find_device(&block_class, &gp->dev, NULL, find_next); - if (dev) { - put_device(dev); - return dev_to_disk(dev); + /* stop is called even after start failed :-( */ + if (iter) { + class_dev_iter_exit(iter); + kfree(iter); } - return NULL; } -static void part_stop(struct seq_file *part, void *v) +static void *show_partition_start(struct seq_file *seqf, loff_t *pos) { - mutex_unlock(&block_class_lock); + static void *p; + + p = disk_seqf_start(seqf, pos); + if (!IS_ERR(p) && p && !*pos) + seq_puts(seqf, "major minor #blocks name\n\n"); + return p; } -static int show_partition(struct seq_file *part, void *v) +static int show_partition(struct seq_file *seqf, void *v) { struct gendisk *sgp = v; - int n; + struct disk_part_iter piter; + struct hd_struct *part; char buf[BDEVNAME_SIZE]; - /* - * Print header if start told us to do. This is to preserve - * the original behavior of not printing header if no - * partition exists. This hackery will be removed later with - * class iteration clean up. - */ - if (part->private) { - seq_puts(part, "major minor #blocks name\n\n"); - part->private = NULL; - } - /* Don't show non-partitionable removeable devices or empty devices */ - if (!get_capacity(sgp) || - (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) + if (!get_capacity(sgp) || (!disk_partitionable(sgp) && + (sgp->flags & GENHD_FL_REMOVABLE))) return 0; if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) return 0; /* show the full disk and all non-0 size partitions of it */ - seq_printf(part, "%4d %4d %10llu %s\n", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - for (n = 0; n < sgp->minors - 1; n++) { - if (!sgp->part[n]) - continue; - if (sgp->part[n]->nr_sects == 0) - continue; - seq_printf(part, "%4d %4d %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1 , - disk_name(sgp, n + 1, buf)); - } + disk_part_iter_init(&piter, sgp, DISK_PITER_INCL_PART0); + while ((part = disk_part_iter_next(&piter))) + seq_printf(seqf, "%4d %7d %10llu %s\n", + MAJOR(part_devt(part)), MINOR(part_devt(part)), + (unsigned long long)part->nr_sects >> 1, + disk_name(sgp, part->partno, buf)); + disk_part_iter_exit(&piter); return 0; } const struct seq_operations partitions_op = { - .start = part_start, - .next = part_next, - .stop = part_stop, + .start = show_partition_start, + .next = disk_seqf_next, + .stop = disk_seqf_stop, .show = show_partition }; #endif -static struct kobject *base_probe(dev_t devt, int *part, void *data) +static struct kobject *base_probe(dev_t devt, int *partno, void *data) { if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0) /* Make old-style 2.4 aliases work */ @@ -431,29 +773,29 @@ static ssize_t disk_range_show(struct device *dev, return sprintf(buf, "%d\n", disk->minors); } -static ssize_t disk_removable_show(struct device *dev, +static ssize_t disk_ext_range_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gendisk *disk = dev_to_disk(dev); - return sprintf(buf, "%d\n", - (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); + return sprintf(buf, "%d\n", disk_max_parts(disk)); } -static ssize_t disk_ro_show(struct device *dev, +static ssize_t disk_removable_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gendisk *disk = dev_to_disk(dev); - return sprintf(buf, "%d\n", disk->policy ? 1 : 0); + return sprintf(buf, "%d\n", + (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); } -static ssize_t disk_size_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t disk_ro_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct gendisk *disk = dev_to_disk(dev); - return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk)); + return sprintf(buf, "%d\n", get_disk_ro(disk) ? 1 : 0); } static ssize_t disk_capability_show(struct device *dev, @@ -464,73 +806,26 @@ static ssize_t disk_capability_show(struct device *dev, return sprintf(buf, "%x\n", disk->flags); } -static ssize_t disk_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gendisk *disk = dev_to_disk(dev); - - preempt_disable(); - disk_round_stats(disk); - preempt_enable(); - return sprintf(buf, - "%8lu %8lu %8llu %8u " - "%8lu %8lu %8llu %8u " - "%8u %8u %8u" - "\n", - disk_stat_read(disk, ios[READ]), - disk_stat_read(disk, merges[READ]), - (unsigned long long)disk_stat_read(disk, sectors[READ]), - jiffies_to_msecs(disk_stat_read(disk, ticks[READ])), - disk_stat_read(disk, ios[WRITE]), - disk_stat_read(disk, merges[WRITE]), - (unsigned long long)disk_stat_read(disk, sectors[WRITE]), - jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])), - disk->in_flight, - jiffies_to_msecs(disk_stat_read(disk, io_ticks)), - jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); -} - -#ifdef CONFIG_FAIL_MAKE_REQUEST -static ssize_t disk_fail_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gendisk *disk = dev_to_disk(dev); - - return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0); -} - -static ssize_t disk_fail_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gendisk *disk = dev_to_disk(dev); - int i; - - if (count > 0 && sscanf(buf, "%d", &i) > 0) { - if (i == 0) - disk->flags &= ~GENHD_FL_FAIL; - else - disk->flags |= GENHD_FL_FAIL; - } - - return count; -} - -#endif - static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); +static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); -static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); +static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); -static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); +static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); #ifdef CONFIG_FAIL_MAKE_REQUEST static struct device_attribute dev_attr_fail = - __ATTR(make-it-fail, S_IRUGO|S_IWUSR, disk_fail_show, disk_fail_store); + __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store); +#endif +#ifdef CONFIG_FAIL_IO_TIMEOUT +static struct device_attribute dev_attr_fail_timeout = + __ATTR(io-timeout-fail, S_IRUGO|S_IWUSR, part_timeout_show, + part_timeout_store); #endif static struct attribute *disk_attrs[] = { &dev_attr_range.attr, + &dev_attr_ext_range.attr, &dev_attr_removable.attr, &dev_attr_ro.attr, &dev_attr_size.attr, @@ -539,6 +834,9 @@ static struct attribute *disk_attrs[] = { #ifdef CONFIG_FAIL_MAKE_REQUEST &dev_attr_fail.attr, #endif +#ifdef CONFIG_FAIL_IO_TIMEOUT + &dev_attr_fail_timeout.attr, +#endif NULL }; @@ -551,13 +849,87 @@ static struct attribute_group *disk_attr_groups[] = { NULL }; +static void disk_free_ptbl_rcu_cb(struct rcu_head *head) +{ + struct disk_part_tbl *ptbl = + container_of(head, struct disk_part_tbl, rcu_head); + + kfree(ptbl); +} + +/** + * disk_replace_part_tbl - replace disk->part_tbl in RCU-safe way + * @disk: disk to replace part_tbl for + * @new_ptbl: new part_tbl to install + * + * Replace disk->part_tbl with @new_ptbl in RCU-safe way. The + * original ptbl is freed using RCU callback. + * + * LOCKING: + * Matching bd_mutx locked. + */ +static void disk_replace_part_tbl(struct gendisk *disk, + struct disk_part_tbl *new_ptbl) +{ + struct disk_part_tbl *old_ptbl = disk->part_tbl; + + rcu_assign_pointer(disk->part_tbl, new_ptbl); + if (old_ptbl) + call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb); +} + +/** + * disk_expand_part_tbl - expand disk->part_tbl + * @disk: disk to expand part_tbl for + * @partno: expand such that this partno can fit in + * + * Expand disk->part_tbl such that @partno can fit in. disk->part_tbl + * uses RCU to allow unlocked dereferencing for stats and other stuff. + * + * LOCKING: + * Matching bd_mutex locked, might sleep. + * + * RETURNS: + * 0 on success, -errno on failure. + */ +int disk_expand_part_tbl(struct gendisk *disk, int partno) +{ + struct disk_part_tbl *old_ptbl = disk->part_tbl; + struct disk_part_tbl *new_ptbl; + int len = old_ptbl ? old_ptbl->len : 0; + int target = partno + 1; + size_t size; + int i; + + /* disk_max_parts() is zero during initialization, ignore if so */ + if (disk_max_parts(disk) && target > disk_max_parts(disk)) + return -EINVAL; + + if (target <= len) + return 0; + + size = sizeof(*new_ptbl) + target * sizeof(new_ptbl->part[0]); + new_ptbl = kzalloc_node(size, GFP_KERNEL, disk->node_id); + if (!new_ptbl) + return -ENOMEM; + + INIT_RCU_HEAD(&new_ptbl->rcu_head); + new_ptbl->len = target; + + for (i = 0; i < len; i++) + rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]); + + disk_replace_part_tbl(disk, new_ptbl); + return 0; +} + static void disk_release(struct device *dev) { struct gendisk *disk = dev_to_disk(dev); kfree(disk->random); - kfree(disk->part); - free_disk_stats(disk); + disk_replace_part_tbl(disk, NULL); + free_part_stats(&disk->part0); kfree(disk); } struct class block_class = { @@ -578,83 +950,31 @@ static struct device_type disk_type = { * The output looks suspiciously like /proc/partitions with a bunch of * extra fields. */ - -static void *diskstats_start(struct seq_file *part, loff_t *pos) -{ - struct device *dev; - loff_t k = *pos; - - mutex_lock(&block_class_lock); - dev = class_find_device(&block_class, NULL, &k, find_start); - if (dev) { - put_device(dev); - return dev_to_disk(dev); - } - return NULL; -} - -static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) -{ - struct gendisk *gp = v; - struct device *dev; - - ++*pos; - dev = class_find_device(&block_class, &gp->dev, NULL, find_next); - if (dev) { - put_device(dev); - return dev_to_disk(dev); - } - return NULL; -} - -static void diskstats_stop(struct seq_file *part, void *v) -{ - mutex_unlock(&block_class_lock); -} - -static int diskstats_show(struct seq_file *s, void *v) +static int diskstats_show(struct seq_file *seqf, void *v) { struct gendisk *gp = v; + struct disk_part_iter piter; + struct hd_struct *hd; char buf[BDEVNAME_SIZE]; - int n = 0; + int cpu; /* - if (&gp->dev.kobj.entry == block_class.devices.next) - seq_puts(s, "major minor name" + if (&disk_to_dev(gp)->kobj.entry == block_class.devices.next) + seq_puts(seqf, "major minor name" " rio rmerge rsect ruse wio wmerge " "wsect wuse running use aveq" "\n\n"); */ - preempt_disable(); - disk_round_stats(gp); - preempt_enable(); - seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", - gp->major, n + gp->first_minor, disk_name(gp, n, buf), - disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), - (unsigned long long)disk_stat_read(gp, sectors[0]), - jiffies_to_msecs(disk_stat_read(gp, ticks[0])), - disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]), - (unsigned long long)disk_stat_read(gp, sectors[1]), - jiffies_to_msecs(disk_stat_read(gp, ticks[1])), - gp->in_flight, - jiffies_to_msecs(disk_stat_read(gp, io_ticks)), - jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); - - /* now show all non-0 size partitions of it */ - for (n = 0; n < gp->minors - 1; n++) { - struct hd_struct *hd = gp->part[n]; - - if (!hd || !hd->nr_sects) - continue; - - preempt_disable(); - part_round_stats(hd); - preempt_enable(); - seq_printf(s, "%4d %4d %s %lu %lu %llu " + disk_part_iter_init(&piter, gp, DISK_PITER_INCL_PART0); + while ((hd = disk_part_iter_next(&piter))) { + cpu = part_stat_lock(); + part_round_stats(cpu, hd); + part_stat_unlock(); + seq_printf(seqf, "%4d %7d %s %lu %lu %llu " "%u %lu %lu %llu %u %u %u %u\n", - gp->major, n + gp->first_minor + 1, - disk_name(gp, n + 1, buf), + MAJOR(part_devt(hd)), MINOR(part_devt(hd)), + disk_name(gp, hd->partno, buf), part_stat_read(hd, ios[0]), part_stat_read(hd, merges[0]), (unsigned long long)part_stat_read(hd, sectors[0]), @@ -668,14 +988,15 @@ static int diskstats_show(struct seq_file *s, void *v) jiffies_to_msecs(part_stat_read(hd, time_in_queue)) ); } + disk_part_iter_exit(&piter); return 0; } const struct seq_operations diskstats_op = { - .start = diskstats_start, - .next = diskstats_next, - .stop = diskstats_stop, + .start = disk_seqf_start, + .next = disk_seqf_next, + .stop = disk_seqf_stop, .show = diskstats_show }; #endif /* CONFIG_PROC_FS */ @@ -690,7 +1011,7 @@ static void media_change_notify_thread(struct work_struct *work) * set enviroment vars to indicate which event this is for * so that user space will know to go check the media status. */ - kobject_uevent_env(&gd->dev.kobj, KOBJ_CHANGE, envp); + kobject_uevent_env(&disk_to_dev(gd)->kobj, KOBJ_CHANGE, envp); put_device(gd->driverfs_dev); } @@ -703,42 +1024,29 @@ void genhd_media_change_notify(struct gendisk *disk) EXPORT_SYMBOL_GPL(genhd_media_change_notify); #endif /* 0 */ -struct find_block { - const char *name; - int part; -}; - -static int match_id(struct device *dev, void *data) +dev_t blk_lookup_devt(const char *name, int partno) { - struct find_block *find = data; + dev_t devt = MKDEV(0, 0); + struct class_dev_iter iter; + struct device *dev; - if (dev->type != &disk_type) - return 0; - if (strcmp(dev->bus_id, find->name) == 0) { + class_dev_iter_init(&iter, &block_class, NULL, &disk_type); + while ((dev = class_dev_iter_next(&iter))) { struct gendisk *disk = dev_to_disk(dev); - if (find->part < disk->minors) - return 1; - } - return 0; -} + struct hd_struct *part; -dev_t blk_lookup_devt(const char *name, int part) -{ - struct device *dev; - dev_t devt = MKDEV(0, 0); - struct find_block find; + if (strcmp(dev->bus_id, name)) + continue; - mutex_lock(&block_class_lock); - find.name = name; - find.part = part; - dev = class_find_device(&block_class, NULL, &find, match_id); - if (dev) { - put_device(dev); - devt = MKDEV(MAJOR(dev->devt), - MINOR(dev->devt) + part); + part = disk_get_part(disk, partno); + if (part) { + devt = part_devt(part); + disk_put_part(part); + break; + } + disk_put_part(part); } - mutex_unlock(&block_class_lock); - + class_dev_iter_exit(&iter); return devt; } EXPORT_SYMBOL(blk_lookup_devt); @@ -747,6 +1055,7 @@ struct gendisk *alloc_disk(int minors) { return alloc_disk_node(minors, -1); } +EXPORT_SYMBOL(alloc_disk); struct gendisk *alloc_disk_node(int minors, int node_id) { @@ -755,32 +1064,28 @@ struct gendisk *alloc_disk_node(int minors, int node_id) disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL | __GFP_ZERO, node_id); if (disk) { - if (!init_disk_stats(disk)) { + if (!init_part_stats(&disk->part0)) { kfree(disk); return NULL; } - if (minors > 1) { - int size = (minors - 1) * sizeof(struct hd_struct *); - disk->part = kmalloc_node(size, - GFP_KERNEL | __GFP_ZERO, node_id); - if (!disk->part) { - free_disk_stats(disk); - kfree(disk); - return NULL; - } + if (disk_expand_part_tbl(disk, 0)) { + free_part_stats(&disk->part0); + kfree(disk); + return NULL; } + disk->part_tbl->part[0] = &disk->part0; + disk->minors = minors; rand_initialize_disk(disk); - disk->dev.class = &block_class; - disk->dev.type = &disk_type; - device_initialize(&disk->dev); + disk_to_dev(disk)->class = &block_class; + disk_to_dev(disk)->type = &disk_type; + device_initialize(disk_to_dev(disk)); INIT_WORK(&disk->async_notify, media_change_notify_thread); + disk->node_id = node_id; } return disk; } - -EXPORT_SYMBOL(alloc_disk); EXPORT_SYMBOL(alloc_disk_node); struct kobject *get_disk(struct gendisk *disk) @@ -793,7 +1098,7 @@ struct kobject *get_disk(struct gendisk *disk) owner = disk->fops->owner; if (owner && !try_module_get(owner)) return NULL; - kobj = kobject_get(&disk->dev.kobj); + kobj = kobject_get(&disk_to_dev(disk)->kobj); if (kobj == NULL) { module_put(owner); return NULL; @@ -807,27 +1112,28 @@ EXPORT_SYMBOL(get_disk); void put_disk(struct gendisk *disk) { if (disk) - kobject_put(&disk->dev.kobj); + kobject_put(&disk_to_dev(disk)->kobj); } EXPORT_SYMBOL(put_disk); void set_device_ro(struct block_device *bdev, int flag) { - if (bdev->bd_contains != bdev) - bdev->bd_part->policy = flag; - else - bdev->bd_disk->policy = flag; + bdev->bd_part->policy = flag; } EXPORT_SYMBOL(set_device_ro); void set_disk_ro(struct gendisk *disk, int flag) { - int i; - disk->policy = flag; - for (i = 0; i < disk->minors - 1; i++) - if (disk->part[i]) disk->part[i]->policy = flag; + struct disk_part_iter piter; + struct hd_struct *part; + + disk_part_iter_init(&piter, disk, + DISK_PITER_INCL_EMPTY | DISK_PITER_INCL_PART0); + while ((part = disk_part_iter_next(&piter))) + part->policy = flag; + disk_part_iter_exit(&piter); } EXPORT_SYMBOL(set_disk_ro); @@ -836,18 +1142,15 @@ int bdev_read_only(struct block_device *bdev) { if (!bdev) return 0; - else if (bdev->bd_contains != bdev) - return bdev->bd_part->policy; - else - return bdev->bd_disk->policy; + return bdev->bd_part->policy; } EXPORT_SYMBOL(bdev_read_only); -int invalidate_partition(struct gendisk *disk, int index) +int invalidate_partition(struct gendisk *disk, int partno) { int res = 0; - struct block_device *bdev = bdget_disk(disk, index); + struct block_device *bdev = bdget_disk(disk, partno); if (bdev) { fsync_bdev(bdev); res = __invalidate_device(bdev); diff --git a/block/ioctl.c b/block/ioctl.c index 77185e5c026a..38bee321e1fa 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -12,11 +12,12 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user { struct block_device *bdevp; struct gendisk *disk; + struct hd_struct *part; struct blkpg_ioctl_arg a; struct blkpg_partition p; + struct disk_part_iter piter; long long start, length; - int part; - int i; + int partno; int err; if (!capable(CAP_SYS_ADMIN)) @@ -28,8 +29,8 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user disk = bdev->bd_disk; if (bdev != bdev->bd_contains) return -EINVAL; - part = p.pno; - if (part <= 0 || part >= disk->minors) + partno = p.pno; + if (partno <= 0) return -EINVAL; switch (a.op) { case BLKPG_ADD_PARTITION: @@ -43,36 +44,37 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user || pstart < 0 || plength < 0) return -EINVAL; } - /* partition number in use? */ + mutex_lock(&bdev->bd_mutex); - if (disk->part[part - 1]) { - mutex_unlock(&bdev->bd_mutex); - return -EBUSY; - } - /* overlap? */ - for (i = 0; i < disk->minors - 1; i++) { - struct hd_struct *s = disk->part[i]; - if (!s) - continue; - if (!(start+length <= s->start_sect || - start >= s->start_sect + s->nr_sects)) { + /* overlap? */ + disk_part_iter_init(&piter, disk, + DISK_PITER_INCL_EMPTY); + while ((part = disk_part_iter_next(&piter))) { + if (!(start + length <= part->start_sect || + start >= part->start_sect + part->nr_sects)) { + disk_part_iter_exit(&piter); mutex_unlock(&bdev->bd_mutex); return -EBUSY; } } + disk_part_iter_exit(&piter); + /* all seems OK */ - err = add_partition(disk, part, start, length, ADDPART_FLAG_NONE); + err = add_partition(disk, partno, start, length, + ADDPART_FLAG_NONE); mutex_unlock(&bdev->bd_mutex); return err; case BLKPG_DEL_PARTITION: - if (!disk->part[part-1]) - return -ENXIO; - if (disk->part[part - 1]->nr_sects == 0) + part = disk_get_part(disk, partno); + if (!part) return -ENXIO; - bdevp = bdget_disk(disk, part); + + bdevp = bdget(part_devt(part)); + disk_put_part(part); if (!bdevp) return -ENOMEM; + mutex_lock(&bdevp->bd_mutex); if (bdevp->bd_openers) { mutex_unlock(&bdevp->bd_mutex); @@ -84,7 +86,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user invalidate_bdev(bdevp); mutex_lock_nested(&bdev->bd_mutex, 1); - delete_partition(disk, part); + delete_partition(disk, partno); mutex_unlock(&bdev->bd_mutex); mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); @@ -100,7 +102,7 @@ static int blkdev_reread_part(struct block_device *bdev) struct gendisk *disk = bdev->bd_disk; int res; - if (disk->minors == 1 || bdev != bdev->bd_contains) + if (!disk_partitionable(disk) || bdev != bdev->bd_contains) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -111,6 +113,69 @@ static int blkdev_reread_part(struct block_device *bdev) return res; } +static void blk_ioc_discard_endio(struct bio *bio, int err) +{ + if (err) { + if (err == -EOPNOTSUPP) + set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); + clear_bit(BIO_UPTODATE, &bio->bi_flags); + } + complete(bio->bi_private); +} + +static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, + uint64_t len) +{ + struct request_queue *q = bdev_get_queue(bdev); + int ret = 0; + + if (start & 511) + return -EINVAL; + if (len & 511) + return -EINVAL; + start >>= 9; + len >>= 9; + + if (start + len > (bdev->bd_inode->i_size >> 9)) + return -EINVAL; + + if (!q->prepare_discard_fn) + return -EOPNOTSUPP; + + while (len && !ret) { + DECLARE_COMPLETION_ONSTACK(wait); + struct bio *bio; + + bio = bio_alloc(GFP_KERNEL, 0); + if (!bio) + return -ENOMEM; + + bio->bi_end_io = blk_ioc_discard_endio; + bio->bi_bdev = bdev; + bio->bi_private = &wait; + bio->bi_sector = start; + + if (len > q->max_hw_sectors) { + bio->bi_size = q->max_hw_sectors << 9; + len -= q->max_hw_sectors; + start += q->max_hw_sectors; + } else { + bio->bi_size = len << 9; + len = 0; + } + submit_bio(DISCARD_NOBARRIER, bio); + + wait_for_completion(&wait); + + if (bio_flagged(bio, BIO_EOPNOTSUPP)) + ret = -EOPNOTSUPP; + else if (!bio_flagged(bio, BIO_UPTODATE)) + ret = -EIO; + bio_put(bio); + } + return ret; +} + static int put_ushort(unsigned long arg, unsigned short val) { return put_user(val, (unsigned short __user *)arg); @@ -258,6 +323,19 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, set_device_ro(bdev, n); unlock_kernel(); return 0; + + case BLKDISCARD: { + uint64_t range[2]; + + if (!(file->f_mode & FMODE_WRITE)) + return -EBADF; + + if (copy_from_user(range, (void __user *)arg, sizeof(range))) + return -EFAULT; + + return blk_ioctl_discard(bdev, range[0], range[1]); + } + case HDIO_GETGEO: { struct hd_geometry geo; diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index ec4b7f234626..c34272a348fe 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -185,6 +185,7 @@ void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter) __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok); __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok); __set_bit(GPCMD_SET_STREAMING, filter->write_ok); + __set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok); } EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); @@ -313,11 +314,12 @@ static int sg_io(struct file *file, struct request_queue *q, goto out; } - ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, - hdr->dxfer_len); + ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, + hdr->dxfer_len, GFP_KERNEL); kfree(iov); } else if (hdr->dxfer_len) - ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); + ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, + GFP_KERNEL); if (ret) goto out; diff --git a/crypto/Kconfig b/crypto/Kconfig index d83185915eee..39dbd8e4dde1 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -21,6 +21,14 @@ if CRYPTO comment "Crypto core or helper" +config CRYPTO_FIPS + bool "FIPS 200 compliance" + help + This options enables the fips boot option which is + required if you want to system to operate in a FIPS 200 + certification. You should say no unless you know what + this is. + config CRYPTO_ALGAPI tristate help @@ -33,14 +41,21 @@ config CRYPTO_AEAD config CRYPTO_BLKCIPHER tristate select CRYPTO_ALGAPI + select CRYPTO_RNG config CRYPTO_HASH tristate select CRYPTO_ALGAPI +config CRYPTO_RNG + tristate + select CRYPTO_ALGAPI + config CRYPTO_MANAGER tristate "Cryptographic algorithm manager" - select CRYPTO_ALGAPI + select CRYPTO_AEAD + select CRYPTO_HASH + select CRYPTO_BLKCIPHER help Create default cryptographic template instantiations such as cbc(aes). @@ -85,9 +100,7 @@ config CRYPTO_AUTHENC config CRYPTO_TEST tristate "Testing module" depends on m - select CRYPTO_ALGAPI - select CRYPTO_AEAD - select CRYPTO_BLKCIPHER + select CRYPTO_MANAGER help Quick & dirty crypto test module. @@ -113,6 +126,7 @@ config CRYPTO_SEQIV tristate "Sequence Number IV Generator" select CRYPTO_AEAD select CRYPTO_BLKCIPHER + select CRYPTO_RNG help This IV generator generates an IV based on a sequence number by xoring it with a salt. This algorithm is mainly useful for CTR @@ -219,7 +233,19 @@ config CRYPTO_CRC32C Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used by iSCSI for header and data digests and by others. See Castagnoli93. This implementation uses lib/libcrc32c. - Module will be crc32c. + Module will be crc32c. + +config CRYPTO_CRC32C_INTEL + tristate "CRC32c INTEL hardware acceleration" + depends on X86 + select CRYPTO_HASH + help + In Intel processor with SSE4.2 supported, the processor will + support CRC32C implementation using hardware accelerated CRC32 + instruction. This option will create 'crc32c-intel' module, + which will enable any routine to use the CRC32 instruction to + gain performance compared with software implementation. + Module will be crc32c-intel. config CRYPTO_MD4 tristate "MD4 digest algorithm" @@ -243,55 +269,58 @@ config CRYPTO_MICHAEL_MIC of the algorithm. config CRYPTO_RMD128 - tristate "RIPEMD-128 digest algorithm" - select CRYPTO_ALGAPI - help - RIPEMD-128 (ISO/IEC 10118-3:2004). + tristate "RIPEMD-128 digest algorithm" + select CRYPTO_ALGAPI + help + RIPEMD-128 (ISO/IEC 10118-3:2004). - RIPEMD-128 is a 128-bit cryptographic hash function. It should only - to be used as a secure replacement for RIPEMD. For other use cases - RIPEMD-160 should be used. + RIPEMD-128 is a 128-bit cryptographic hash function. It should only + to be used as a secure replacement for RIPEMD. For other use cases + RIPEMD-160 should be used. - Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. - See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> + Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. + See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> config CRYPTO_RMD160 - tristate "RIPEMD-160 digest algorithm" - select CRYPTO_ALGAPI - help - RIPEMD-160 (ISO/IEC 10118-3:2004). + tristate "RIPEMD-160 digest algorithm" + select CRYPTO_ALGAPI + help + RIPEMD-160 (ISO/IEC 10118-3:2004). - RIPEMD-160 is a 160-bit cryptographic hash function. It is intended - to be used as a secure replacement for the 128-bit hash functions - MD4, MD5 and it's predecessor RIPEMD (not to be confused with RIPEMD-128). + RIPEMD-160 is a 160-bit cryptographic hash function. It is intended + to be used as a secure replacement for the 128-bit hash functions + MD4, MD5 and it's predecessor RIPEMD + (not to be confused with RIPEMD-128). - It's speed is comparable to SHA1 and there are no known attacks against - RIPEMD-160. + It's speed is comparable to SHA1 and there are no known attacks + against RIPEMD-160. - Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. - See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> + Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. + See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> config CRYPTO_RMD256 - tristate "RIPEMD-256 digest algorithm" - select CRYPTO_ALGAPI - help - RIPEMD-256 is an optional extension of RIPEMD-128 with a 256 bit hash. - It is intended for applications that require longer hash-results, without - needing a larger security level (than RIPEMD-128). + tristate "RIPEMD-256 digest algorithm" + select CRYPTO_ALGAPI + help + RIPEMD-256 is an optional extension of RIPEMD-128 with a + 256 bit hash. It is intended for applications that require + longer hash-results, without needing a larger security level + (than RIPEMD-128). - Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. - See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> + Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. + See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> config CRYPTO_RMD320 - tristate "RIPEMD-320 digest algorithm" - select CRYPTO_ALGAPI - help - RIPEMD-320 is an optional extension of RIPEMD-160 with a 320 bit hash. - It is intended for applications that require longer hash-results, without - needing a larger security level (than RIPEMD-160). + tristate "RIPEMD-320 digest algorithm" + select CRYPTO_ALGAPI + help + RIPEMD-320 is an optional extension of RIPEMD-160 with a + 320 bit hash. It is intended for applications that require + longer hash-results, without needing a larger security level + (than RIPEMD-160). - Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. - See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> + Developed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. + See <http://home.esat.kuleuven.be/~bosselae/ripemd160.html> config CRYPTO_SHA1 tristate "SHA1 digest algorithm" @@ -308,8 +337,8 @@ config CRYPTO_SHA256 This version of SHA implements a 256 bit hash with 128 bits of security against collision attacks. - This code also includes SHA-224, a 224 bit hash with 112 bits - of security against collision attacks. + This code also includes SHA-224, a 224 bit hash with 112 bits + of security against collision attacks. config CRYPTO_SHA512 tristate "SHA384 and SHA512 digest algorithms" @@ -666,6 +695,18 @@ config CRYPTO_LZO help This is the LZO algorithm. +comment "Random Number Generation" + +config CRYPTO_ANSI_CPRNG + tristate "Pseudo Random Number Generation for Cryptographic modules" + select CRYPTO_AES + select CRYPTO_RNG + select CRYPTO_FIPS + help + This option enables the generic pseudo random number generator + for cryptographic modules. Uses the Algorithm specified in + ANSI X9.31 A.2.4 + source "drivers/crypto/Kconfig" endif # if CRYPTO diff --git a/crypto/Makefile b/crypto/Makefile index d4f3ed857df0..5862b807334e 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -5,6 +5,8 @@ obj-$(CONFIG_CRYPTO) += crypto.o crypto-objs := api.o cipher.o digest.o compress.o +obj-$(CONFIG_CRYPTO_FIPS) += fips.o + crypto_algapi-$(CONFIG_PROC_FS) += proc.o crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y) obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o @@ -13,15 +15,17 @@ obj-$(CONFIG_CRYPTO_AEAD) += aead.o crypto_blkcipher-objs := ablkcipher.o crypto_blkcipher-objs += blkcipher.o -crypto_blkcipher-objs += chainiv.o -crypto_blkcipher-objs += eseqiv.o obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o +obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o +obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o crypto_hash-objs := hash.o crypto_hash-objs += ahash.o obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o +cryptomgr-objs := algboss.o testmgr.o + obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o obj-$(CONFIG_CRYPTO_HMAC) += hmac.o obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o @@ -69,7 +73,9 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o - +obj-$(CONFIG_CRYPTO_RNG) += rng.o +obj-$(CONFIG_CRYPTO_RNG) += krng.o +obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o # diff --git a/crypto/algapi.c b/crypto/algapi.c index e65cb50cf4af..7c41e7405c41 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -21,15 +21,15 @@ #include "internal.h" +static void crypto_remove_final(struct list_head *list); + static LIST_HEAD(crypto_template_list); void crypto_larval_error(const char *name, u32 type, u32 mask) { struct crypto_alg *alg; - down_read(&crypto_alg_sem); - alg = __crypto_alg_lookup(name, type, mask); - up_read(&crypto_alg_sem); + alg = crypto_alg_lookup(name, type, mask); if (alg) { if (crypto_is_larval(alg)) { @@ -128,23 +128,97 @@ static void crypto_remove_spawns(struct list_head *spawns, } } -static int __crypto_register_alg(struct crypto_alg *alg, - struct list_head *list) +static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg) { struct crypto_alg *q; + struct crypto_larval *larval; int ret = -EAGAIN; if (crypto_is_dead(alg)) - goto out; + goto err; INIT_LIST_HEAD(&alg->cra_users); + /* No cheating! */ + alg->cra_flags &= ~CRYPTO_ALG_TESTED; + ret = -EEXIST; atomic_set(&alg->cra_refcnt, 1); list_for_each_entry(q, &crypto_alg_list, cra_list) { if (q == alg) - goto out; + goto err; + + if (crypto_is_larval(q)) { + if (!strcmp(alg->cra_driver_name, q->cra_driver_name)) + goto err; + continue; + } + + if (!strcmp(q->cra_driver_name, alg->cra_name) || + !strcmp(q->cra_name, alg->cra_driver_name)) + goto err; + } + + larval = crypto_larval_alloc(alg->cra_name, + alg->cra_flags | CRYPTO_ALG_TESTED, 0); + if (IS_ERR(larval)) + goto out; + + ret = -ENOENT; + larval->adult = crypto_mod_get(alg); + if (!larval->adult) + goto free_larval; + + atomic_set(&larval->alg.cra_refcnt, 1); + memcpy(larval->alg.cra_driver_name, alg->cra_driver_name, + CRYPTO_MAX_ALG_NAME); + larval->alg.cra_priority = alg->cra_priority; + + list_add(&alg->cra_list, &crypto_alg_list); + list_add(&larval->alg.cra_list, &crypto_alg_list); + +out: + return larval; + +free_larval: + kfree(larval); +err: + larval = ERR_PTR(ret); + goto out; +} + +void crypto_alg_tested(const char *name, int err) +{ + struct crypto_larval *test; + struct crypto_alg *alg; + struct crypto_alg *q; + LIST_HEAD(list); + + down_write(&crypto_alg_sem); + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!crypto_is_larval(q)) + continue; + + test = (struct crypto_larval *)q; + + if (!strcmp(q->cra_driver_name, name)) + goto found; + } + + printk(KERN_ERR "alg: Unexpected test result for %s: %d\n", name, err); + goto unlock; + +found: + alg = test->adult; + if (err || list_empty(&alg->cra_list)) + goto complete; + + alg->cra_flags |= CRYPTO_ALG_TESTED; + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (q == alg) + continue; if (crypto_is_moribund(q)) continue; @@ -180,17 +254,18 @@ static int __crypto_register_alg(struct crypto_alg *alg, q->cra_priority > alg->cra_priority) continue; - crypto_remove_spawns(&q->cra_users, list, alg->cra_flags); + crypto_remove_spawns(&q->cra_users, &list, alg->cra_flags); } - - list_add(&alg->cra_list, &crypto_alg_list); - crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg); - ret = 0; +complete: + complete_all(&test->completion); -out: - return ret; +unlock: + up_write(&crypto_alg_sem); + + crypto_remove_final(&list); } +EXPORT_SYMBOL_GPL(crypto_alg_tested); static void crypto_remove_final(struct list_head *list) { @@ -203,9 +278,27 @@ static void crypto_remove_final(struct list_head *list) } } +static void crypto_wait_for_test(struct crypto_larval *larval) +{ + int err; + + err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult); + if (err != NOTIFY_STOP) { + if (WARN_ON(err != NOTIFY_DONE)) + goto out; + crypto_alg_tested(larval->alg.cra_driver_name, 0); + } + + err = wait_for_completion_interruptible(&larval->completion); + WARN_ON(err); + +out: + crypto_larval_kill(&larval->alg); +} + int crypto_register_alg(struct crypto_alg *alg) { - LIST_HEAD(list); + struct crypto_larval *larval; int err; err = crypto_check_alg(alg); @@ -213,11 +306,14 @@ int crypto_register_alg(struct crypto_alg *alg) return err; down_write(&crypto_alg_sem); - err = __crypto_register_alg(alg, &list); + larval = __crypto_register_alg(alg); up_write(&crypto_alg_sem); - crypto_remove_final(&list); - return err; + if (IS_ERR(larval)) + return PTR_ERR(larval); + + crypto_wait_for_test(larval); + return 0; } EXPORT_SYMBOL_GPL(crypto_register_alg); @@ -335,8 +431,8 @@ EXPORT_SYMBOL_GPL(crypto_lookup_template); int crypto_register_instance(struct crypto_template *tmpl, struct crypto_instance *inst) { - LIST_HEAD(list); - int err = -EINVAL; + struct crypto_larval *larval; + int err; err = crypto_check_alg(&inst->alg); if (err) @@ -346,8 +442,8 @@ int crypto_register_instance(struct crypto_template *tmpl, down_write(&crypto_alg_sem); - err = __crypto_register_alg(&inst->alg, &list); - if (err) + larval = __crypto_register_alg(&inst->alg); + if (IS_ERR(larval)) goto unlock; hlist_add_head(&inst->list, &tmpl->instances); @@ -356,7 +452,12 @@ int crypto_register_instance(struct crypto_template *tmpl, unlock: up_write(&crypto_alg_sem); - crypto_remove_final(&list); + err = PTR_ERR(larval); + if (IS_ERR(larval)) + goto err; + + crypto_wait_for_test(larval); + err = 0; err: return err; diff --git a/crypto/cryptomgr.c b/crypto/algboss.c index e5e3cf848d42..4601e4267c88 100644 --- a/crypto/cryptomgr.c +++ b/crypto/algboss.c @@ -45,6 +45,15 @@ struct cryptomgr_param { char larval[CRYPTO_MAX_ALG_NAME]; char template[CRYPTO_MAX_ALG_NAME]; + + u32 otype; + u32 omask; +}; + +struct crypto_test_param { + char driver[CRYPTO_MAX_ALG_NAME]; + char alg[CRYPTO_MAX_ALG_NAME]; + u32 type; }; static int cryptomgr_probe(void *data) @@ -76,8 +85,7 @@ out: module_put_and_exit(0); err: - crypto_larval_error(param->larval, param->type.data.type, - param->type.data.mask); + crypto_larval_error(param->larval, param->otype, param->omask); goto out; } @@ -169,13 +177,65 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) param->type.attr.rta_len = sizeof(param->type); param->type.attr.rta_type = CRYPTOA_TYPE; - param->type.data.type = larval->alg.cra_flags; - param->type.data.mask = larval->mask; + param->type.data.type = larval->alg.cra_flags & ~CRYPTO_ALG_TESTED; + param->type.data.mask = larval->mask & ~CRYPTO_ALG_TESTED; param->tb[0] = ¶m->type.attr; + param->otype = larval->alg.cra_flags; + param->omask = larval->mask; + memcpy(param->larval, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); - thread = kthread_run(cryptomgr_probe, param, "cryptomgr"); + thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe"); + if (IS_ERR(thread)) + goto err_free_param; + + return NOTIFY_STOP; + +err_free_param: + kfree(param); +err_put_module: + module_put(THIS_MODULE); +err: + return NOTIFY_OK; +} + +static int cryptomgr_test(void *data) +{ + struct crypto_test_param *param = data; + u32 type = param->type; + int err = 0; + + if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & + CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV)) + goto skiptest; + + err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED); + +skiptest: + crypto_alg_tested(param->driver, err); + + kfree(param); + module_put_and_exit(0); +} + +static int cryptomgr_schedule_test(struct crypto_alg *alg) +{ + struct task_struct *thread; + struct crypto_test_param *param; + + if (!try_module_get(THIS_MODULE)) + goto err; + + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) + goto err_put_module; + + memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver)); + memcpy(param->alg, alg->cra_name, sizeof(param->alg)); + param->type = alg->cra_flags; + + thread = kthread_run(cryptomgr_test, param, "cryptomgr_test"); if (IS_ERR(thread)) goto err_free_param; @@ -195,6 +255,8 @@ static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, switch (msg) { case CRYPTO_MSG_ALG_REQUEST: return cryptomgr_schedule_probe(data); + case CRYPTO_MSG_ALG_REGISTER: + return cryptomgr_schedule_test(data); } return NOTIFY_DONE; @@ -206,16 +268,32 @@ static struct notifier_block cryptomgr_notifier = { static int __init cryptomgr_init(void) { - return crypto_register_notifier(&cryptomgr_notifier); + int err; + + err = testmgr_init(); + if (err) + return err; + + err = crypto_register_notifier(&cryptomgr_notifier); + if (err) + goto free_testmgr; + + return 0; + +free_testmgr: + testmgr_exit(); + return err; } static void __exit cryptomgr_exit(void) { int err = crypto_unregister_notifier(&cryptomgr_notifier); BUG_ON(err); + + testmgr_exit(); } -module_init(cryptomgr_init); +subsys_initcall(cryptomgr_init); module_exit(cryptomgr_exit); MODULE_LICENSE("GPL"); diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c new file mode 100644 index 000000000000..72db0fd763cc --- /dev/null +++ b/crypto/ansi_cprng.c @@ -0,0 +1,417 @@ +/* + * PRNG: Pseudo Random Number Generator + * Based on NIST Recommended PRNG From ANSI X9.31 Appendix A.2.4 using + * AES 128 cipher + * + * (C) Neil Horman <nhorman@tuxdriver.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * any later version. + * + * + */ + +#include <crypto/internal/rng.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/string.h> + +#include "internal.h" + +#define DEFAULT_PRNG_KEY "0123456789abcdef" +#define DEFAULT_PRNG_KSZ 16 +#define DEFAULT_BLK_SZ 16 +#define DEFAULT_V_SEED "zaybxcwdveuftgsh" + +/* + * Flags for the prng_context flags field + */ + +#define PRNG_FIXED_SIZE 0x1 +#define PRNG_NEED_RESET 0x2 + +/* + * Note: DT is our counter value + * I is our intermediate value + * V is our seed vector + * See http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf + * for implementation details + */ + + +struct prng_context { + spinlock_t prng_lock; + unsigned char rand_data[DEFAULT_BLK_SZ]; + unsigned char last_rand_data[DEFAULT_BLK_SZ]; + unsigned char DT[DEFAULT_BLK_SZ]; + unsigned char I[DEFAULT_BLK_SZ]; + unsigned char V[DEFAULT_BLK_SZ]; + u32 rand_data_valid; + struct crypto_cipher *tfm; + u32 flags; +}; + +static int dbg; + +static void hexdump(char *note, unsigned char *buf, unsigned int len) +{ + if (dbg) { + printk(KERN_CRIT "%s", note); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, + 16, 1, + buf, len, false); + } +} + +#define dbgprint(format, args...) do {\ +if (dbg)\ + printk(format, ##args);\ +} while (0) + +static void xor_vectors(unsigned char *in1, unsigned char *in2, + unsigned char *out, unsigned int size) +{ + int i; + + for (i = 0; i < size; i++) + out[i] = in1[i] ^ in2[i]; + +} +/* + * Returns DEFAULT_BLK_SZ bytes of random data per call + * returns 0 if generation succeded, <0 if something went wrong + */ +static int _get_more_prng_bytes(struct prng_context *ctx) +{ + int i; + unsigned char tmp[DEFAULT_BLK_SZ]; + unsigned char *output = NULL; + + + dbgprint(KERN_CRIT "Calling _get_more_prng_bytes for context %p\n", + ctx); + + hexdump("Input DT: ", ctx->DT, DEFAULT_BLK_SZ); + hexdump("Input I: ", ctx->I, DEFAULT_BLK_SZ); + hexdump("Input V: ", ctx->V, DEFAULT_BLK_SZ); + + /* + * This algorithm is a 3 stage state machine + */ + for (i = 0; i < 3; i++) { + + switch (i) { + case 0: + /* + * Start by encrypting the counter value + * This gives us an intermediate value I + */ + memcpy(tmp, ctx->DT, DEFAULT_BLK_SZ); + output = ctx->I; + hexdump("tmp stage 0: ", tmp, DEFAULT_BLK_SZ); + break; + case 1: + + /* + * Next xor I with our secret vector V + * encrypt that result to obtain our + * pseudo random data which we output + */ + xor_vectors(ctx->I, ctx->V, tmp, DEFAULT_BLK_SZ); + hexdump("tmp stage 1: ", tmp, DEFAULT_BLK_SZ); + output = ctx->rand_data; + break; + case 2: + /* + * First check that we didn't produce the same + * random data that we did last time around through this + */ + if (!memcmp(ctx->rand_data, ctx->last_rand_data, + DEFAULT_BLK_SZ)) { + printk(KERN_ERR + "ctx %p Failed repetition check!\n", + ctx); + ctx->flags |= PRNG_NEED_RESET; + return -EINVAL; + } + memcpy(ctx->last_rand_data, ctx->rand_data, + DEFAULT_BLK_SZ); + + /* + * Lastly xor the random data with I + * and encrypt that to obtain a new secret vector V + */ + xor_vectors(ctx->rand_data, ctx->I, tmp, + DEFAULT_BLK_SZ); + output = ctx->V; + hexdump("tmp stage 2: ", tmp, DEFAULT_BLK_SZ); + break; + } + + + /* do the encryption */ + crypto_cipher_encrypt_one(ctx->tfm, output, tmp); + + } + + /* + * Now update our DT value + */ + for (i = 0; i < DEFAULT_BLK_SZ; i++) { + ctx->DT[i] += 1; + if (ctx->DT[i] != 0) + break; + } + + dbgprint("Returning new block for context %p\n", ctx); + ctx->rand_data_valid = 0; + + hexdump("Output DT: ", ctx->DT, DEFAULT_BLK_SZ); + hexdump("Output I: ", ctx->I, DEFAULT_BLK_SZ); + hexdump("Output V: ", ctx->V, DEFAULT_BLK_SZ); + hexdump("New Random Data: ", ctx->rand_data, DEFAULT_BLK_SZ); + + return 0; +} + +/* Our exported functions */ +static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx) +{ + unsigned long flags; + unsigned char *ptr = buf; + unsigned int byte_count = (unsigned int)nbytes; + int err; + + + if (nbytes < 0) + return -EINVAL; + + spin_lock_irqsave(&ctx->prng_lock, flags); + + err = -EINVAL; + if (ctx->flags & PRNG_NEED_RESET) + goto done; + + /* + * If the FIXED_SIZE flag is on, only return whole blocks of + * pseudo random data + */ + err = -EINVAL; + if (ctx->flags & PRNG_FIXED_SIZE) { + if (nbytes < DEFAULT_BLK_SZ) + goto done; + byte_count = DEFAULT_BLK_SZ; + } + + err = byte_count; + + dbgprint(KERN_CRIT "getting %d random bytes for context %p\n", + byte_count, ctx); + + +remainder: + if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { + if (_get_more_prng_bytes(ctx) < 0) { + memset(buf, 0, nbytes); + err = -EINVAL; + goto done; + } + } + + /* + * Copy up to the next whole block size + */ + if (byte_count < DEFAULT_BLK_SZ) { + for (; ctx->rand_data_valid < DEFAULT_BLK_SZ; + ctx->rand_data_valid++) { + *ptr = ctx->rand_data[ctx->rand_data_valid]; + ptr++; + byte_count--; + if (byte_count == 0) + goto done; + } + } + + /* + * Now copy whole blocks + */ + for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) { + if (_get_more_prng_bytes(ctx) < 0) { + memset(buf, 0, nbytes); + err = -EINVAL; + goto done; + } + memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ); + ctx->rand_data_valid += DEFAULT_BLK_SZ; + ptr += DEFAULT_BLK_SZ; + } + + /* + * Now copy any extra partial data + */ + if (byte_count) + goto remainder; + +done: + spin_unlock_irqrestore(&ctx->prng_lock, flags); + dbgprint(KERN_CRIT "returning %d from get_prng_bytes in context %p\n", + err, ctx); + return err; +} + +static void free_prng_context(struct prng_context *ctx) +{ + crypto_free_cipher(ctx->tfm); +} + +static int reset_prng_context(struct prng_context *ctx, + unsigned char *key, size_t klen, + unsigned char *V, unsigned char *DT) +{ + int ret; + int rc = -EINVAL; + unsigned char *prng_key; + + spin_lock(&ctx->prng_lock); + ctx->flags |= PRNG_NEED_RESET; + + prng_key = (key != NULL) ? key : (unsigned char *)DEFAULT_PRNG_KEY; + + if (!key) + klen = DEFAULT_PRNG_KSZ; + + if (V) + memcpy(ctx->V, V, DEFAULT_BLK_SZ); + else + memcpy(ctx->V, DEFAULT_V_SEED, DEFAULT_BLK_SZ); + + if (DT) + memcpy(ctx->DT, DT, DEFAULT_BLK_SZ); + else + memset(ctx->DT, 0, DEFAULT_BLK_SZ); + + memset(ctx->rand_data, 0, DEFAULT_BLK_SZ); + memset(ctx->last_rand_data, 0, DEFAULT_BLK_SZ); + + if (ctx->tfm) + crypto_free_cipher(ctx->tfm); + + ctx->tfm = crypto_alloc_cipher("aes", 0, 0); + if (IS_ERR(ctx->tfm)) { + dbgprint(KERN_CRIT "Failed to alloc tfm for context %p\n", + ctx); + ctx->tfm = NULL; + goto out; + } + + ctx->rand_data_valid = DEFAULT_BLK_SZ; + + ret = crypto_cipher_setkey(ctx->tfm, prng_key, klen); + if (ret) { + dbgprint(KERN_CRIT "PRNG: setkey() failed flags=%x\n", + crypto_cipher_get_flags(ctx->tfm)); + crypto_free_cipher(ctx->tfm); + goto out; + } + + rc = 0; + ctx->flags &= ~PRNG_NEED_RESET; +out: + spin_unlock(&ctx->prng_lock); + + return rc; + +} + +static int cprng_init(struct crypto_tfm *tfm) +{ + struct prng_context *ctx = crypto_tfm_ctx(tfm); + + spin_lock_init(&ctx->prng_lock); + + return reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL); +} + +static void cprng_exit(struct crypto_tfm *tfm) +{ + free_prng_context(crypto_tfm_ctx(tfm)); +} + +static int cprng_get_random(struct crypto_rng *tfm, u8 *rdata, + unsigned int dlen) +{ + struct prng_context *prng = crypto_rng_ctx(tfm); + + return get_prng_bytes(rdata, dlen, prng); +} + +static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) +{ + struct prng_context *prng = crypto_rng_ctx(tfm); + u8 *key = seed + DEFAULT_PRNG_KSZ; + + if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ) + return -EINVAL; + + reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, NULL); + + if (prng->flags & PRNG_NEED_RESET) + return -EINVAL; + return 0; +} + +static struct crypto_alg rng_alg = { + .cra_name = "stdrng", + .cra_driver_name = "ansi_cprng", + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_RNG, + .cra_ctxsize = sizeof(struct prng_context), + .cra_type = &crypto_rng_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(rng_alg.cra_list), + .cra_init = cprng_init, + .cra_exit = cprng_exit, + .cra_u = { + .rng = { + .rng_make_random = cprng_get_random, + .rng_reset = cprng_reset, + .seedsize = DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ, + } + } +}; + + +/* Module initalization */ +static int __init prng_mod_init(void) +{ + int ret = 0; + + if (fips_enabled) + rng_alg.cra_priority += 200; + + ret = crypto_register_alg(&rng_alg); + + if (ret) + goto out; +out: + return 0; +} + +static void __exit prng_mod_fini(void) +{ + crypto_unregister_alg(&rng_alg); + return; +} + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Software Pseudo Random Number Generator"); +MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>"); +module_param(dbg, int, 0); +MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)"); +module_init(prng_mod_init); +module_exit(prng_mod_fini); +MODULE_ALIAS("stdrng"); diff --git a/crypto/api.c b/crypto/api.c index d06e33270abe..0444d242e985 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -55,7 +55,13 @@ void crypto_mod_put(struct crypto_alg *alg) } EXPORT_SYMBOL_GPL(crypto_mod_put); -struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) +static inline int crypto_is_test_larval(struct crypto_larval *larval) +{ + return larval->alg.cra_driver_name[0]; +} + +static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, + u32 mask) { struct crypto_alg *q, *alg = NULL; int best = -2; @@ -70,6 +76,7 @@ struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) continue; if (crypto_is_larval(q) && + !crypto_is_test_larval((struct crypto_larval *)q) && ((struct crypto_larval *)q)->mask != mask) continue; @@ -92,7 +99,6 @@ struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) return alg; } -EXPORT_SYMBOL_GPL(__crypto_alg_lookup); static void crypto_larval_destroy(struct crypto_alg *alg) { @@ -104,10 +110,8 @@ static void crypto_larval_destroy(struct crypto_alg *alg) kfree(larval); } -static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, - u32 mask) +struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask) { - struct crypto_alg *alg; struct crypto_larval *larval; larval = kzalloc(sizeof(*larval), GFP_KERNEL); @@ -119,10 +123,25 @@ static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, larval->alg.cra_priority = -1; larval->alg.cra_destroy = crypto_larval_destroy; - atomic_set(&larval->alg.cra_refcnt, 2); strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); init_completion(&larval->completion); + return larval; +} +EXPORT_SYMBOL_GPL(crypto_larval_alloc); + +static struct crypto_alg *crypto_larval_add(const char *name, u32 type, + u32 mask) +{ + struct crypto_alg *alg; + struct crypto_larval *larval; + + larval = crypto_larval_alloc(name, type, mask); + if (IS_ERR(larval)) + return ERR_CAST(larval); + + atomic_set(&larval->alg.cra_refcnt, 2); + down_write(&crypto_alg_sem); alg = __crypto_alg_lookup(name, type, mask); if (!alg) { @@ -152,21 +171,29 @@ EXPORT_SYMBOL_GPL(crypto_larval_kill); static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) { struct crypto_larval *larval = (void *)alg; + long timeout; + + timeout = wait_for_completion_interruptible_timeout( + &larval->completion, 60 * HZ); - wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ); alg = larval->adult; - if (alg) { - if (!crypto_mod_get(alg)) - alg = ERR_PTR(-EAGAIN); - } else + if (timeout < 0) + alg = ERR_PTR(-EINTR); + else if (!timeout) + alg = ERR_PTR(-ETIMEDOUT); + else if (!alg) alg = ERR_PTR(-ENOENT); + else if (crypto_is_test_larval(larval) && + !(alg->cra_flags & CRYPTO_ALG_TESTED)) + alg = ERR_PTR(-EAGAIN); + else if (!crypto_mod_get(alg)) + alg = ERR_PTR(-EAGAIN); crypto_mod_put(&larval->alg); return alg; } -static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, - u32 mask) +struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, u32 mask) { struct crypto_alg *alg; @@ -176,6 +203,7 @@ static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, return alg; } +EXPORT_SYMBOL_GPL(crypto_alg_lookup); struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) { @@ -192,25 +220,40 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) if (alg) return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; - return crypto_larval_alloc(name, type, mask); + return crypto_larval_add(name, type, mask); } EXPORT_SYMBOL_GPL(crypto_larval_lookup); +int crypto_probing_notify(unsigned long val, void *v) +{ + int ok; + + ok = blocking_notifier_call_chain(&crypto_chain, val, v); + if (ok == NOTIFY_DONE) { + request_module("cryptomgr"); + ok = blocking_notifier_call_chain(&crypto_chain, val, v); + } + + return ok; +} +EXPORT_SYMBOL_GPL(crypto_probing_notify); + struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) { struct crypto_alg *alg; struct crypto_alg *larval; int ok; + if (!(mask & CRYPTO_ALG_TESTED)) { + type |= CRYPTO_ALG_TESTED; + mask |= CRYPTO_ALG_TESTED; + } + larval = crypto_larval_lookup(name, type, mask); if (IS_ERR(larval) || !crypto_is_larval(larval)) return larval; - ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); - if (ok == NOTIFY_DONE) { - request_module("cryptomgr"); - ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); - } + ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval); if (ok == NOTIFY_STOP) alg = crypto_larval_wait(larval); diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 185f955fb0d7..4a7e65c4df4d 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -696,34 +696,5 @@ void skcipher_geniv_exit(struct crypto_tfm *tfm) } EXPORT_SYMBOL_GPL(skcipher_geniv_exit); -static int __init blkcipher_module_init(void) -{ - int err; - - err = chainiv_module_init(); - if (err) - goto out; - - err = eseqiv_module_init(); - if (err) - goto eseqiv_err; - -out: - return err; - -eseqiv_err: - chainiv_module_exit(); - goto out; -} - -static void __exit blkcipher_module_exit(void) -{ - eseqiv_module_exit(); - chainiv_module_exit(); -} - -module_init(blkcipher_module_init); -module_exit(blkcipher_module_exit); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic block chaining cipher type"); diff --git a/crypto/chainiv.c b/crypto/chainiv.c index 9affadee3287..7c37a497b860 100644 --- a/crypto/chainiv.c +++ b/crypto/chainiv.c @@ -14,11 +14,11 @@ */ #include <crypto/internal/skcipher.h> +#include <crypto/rng.h> #include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/random.h> #include <linux/spinlock.h> #include <linux/string.h> #include <linux/workqueue.h> @@ -83,6 +83,7 @@ static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) { struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); + int err = 0; spin_lock_bh(&ctx->lock); if (crypto_ablkcipher_crt(geniv)->givencrypt != @@ -90,11 +91,15 @@ static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) goto unlock; crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt; - get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv)); + err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv, + crypto_ablkcipher_ivsize(geniv)); unlock: spin_unlock_bh(&ctx->lock); + if (err) + return err; + return chainiv_givencrypt(req); } @@ -203,6 +208,7 @@ static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) { struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); + int err = 0; if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state)) goto out; @@ -212,11 +218,15 @@ static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) goto unlock; crypto_ablkcipher_crt(geniv)->givencrypt = async_chainiv_givencrypt; - get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv)); + err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv, + crypto_ablkcipher_ivsize(geniv)); unlock: clear_bit(CHAINIV_STATE_INUSE, &ctx->state); + if (err) + return err; + out: return async_chainiv_givencrypt(req); } @@ -284,9 +294,13 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb) if (IS_ERR(algt)) return ERR_PTR(err); + err = crypto_get_default_rng(); + if (err) + return ERR_PTR(err); + inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0, 0); if (IS_ERR(inst)) - goto out; + goto put_rng; inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first; @@ -311,21 +325,37 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb) out: return inst; + +put_rng: + crypto_put_default_rng(); + goto out; +} + +static void chainiv_free(struct crypto_instance *inst) +{ + skcipher_geniv_free(inst); + crypto_put_default_rng(); } static struct crypto_template chainiv_tmpl = { .name = "chainiv", .alloc = chainiv_alloc, - .free = skcipher_geniv_free, + .free = chainiv_free, .module = THIS_MODULE, }; -int __init chainiv_module_init(void) +static int __init chainiv_module_init(void) { return crypto_register_template(&chainiv_tmpl); } -void chainiv_module_exit(void) +static void chainiv_module_exit(void) { crypto_unregister_template(&chainiv_tmpl); } + +module_init(chainiv_module_init); +module_exit(chainiv_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Chain IV Generator"); diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c index 881d30910434..2a342c8e52b3 100644 --- a/crypto/eseqiv.c +++ b/crypto/eseqiv.c @@ -16,13 +16,13 @@ */ #include <crypto/internal/skcipher.h> +#include <crypto/rng.h> #include <crypto/scatterwalk.h> #include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/module.h> -#include <linux/random.h> #include <linux/scatterlist.h> #include <linux/spinlock.h> #include <linux/string.h> @@ -163,17 +163,22 @@ static int eseqiv_givencrypt_first(struct skcipher_givcrypt_request *req) { struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); + int err = 0; spin_lock_bh(&ctx->lock); if (crypto_ablkcipher_crt(geniv)->givencrypt != eseqiv_givencrypt_first) goto unlock; crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt; - get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv)); + err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, + crypto_ablkcipher_ivsize(geniv)); unlock: spin_unlock_bh(&ctx->lock); + if (err) + return err; + return eseqiv_givencrypt(req); } @@ -216,9 +221,13 @@ static struct crypto_instance *eseqiv_alloc(struct rtattr **tb) struct crypto_instance *inst; int err; + err = crypto_get_default_rng(); + if (err) + return ERR_PTR(err); + inst = skcipher_geniv_alloc(&eseqiv_tmpl, tb, 0, 0); if (IS_ERR(inst)) - goto out; + goto put_rng; err = -EINVAL; if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize) @@ -238,22 +247,36 @@ out: free_inst: skcipher_geniv_free(inst); inst = ERR_PTR(err); +put_rng: + crypto_put_default_rng(); goto out; } +static void eseqiv_free(struct crypto_instance *inst) +{ + skcipher_geniv_free(inst); + crypto_put_default_rng(); +} + static struct crypto_template eseqiv_tmpl = { .name = "eseqiv", .alloc = eseqiv_alloc, - .free = skcipher_geniv_free, + .free = eseqiv_free, .module = THIS_MODULE, }; -int __init eseqiv_module_init(void) +static int __init eseqiv_module_init(void) { return crypto_register_template(&eseqiv_tmpl); } -void __exit eseqiv_module_exit(void) +static void __exit eseqiv_module_exit(void) { crypto_unregister_template(&eseqiv_tmpl); } + +module_init(eseqiv_module_init); +module_exit(eseqiv_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator"); diff --git a/crypto/fips.c b/crypto/fips.c new file mode 100644 index 000000000000..553970081c62 --- /dev/null +++ b/crypto/fips.c @@ -0,0 +1,27 @@ +/* + * FIPS 200 support. + * + * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include "internal.h" + +int fips_enabled; +EXPORT_SYMBOL_GPL(fips_enabled); + +/* Process kernel command-line parameter at boot time. fips=0 or fips=1 */ +static int fips_enable(char *str) +{ + fips_enabled = !!simple_strtol(str, NULL, 0); + printk(KERN_INFO "fips mode: %s\n", + fips_enabled ? "enabled" : "disabled"); + return 1; +} + +__setup("fips=", fips_enable); diff --git a/crypto/internal.h b/crypto/internal.h index 683fcb2d91f4..8ef72d76092e 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -26,6 +26,12 @@ #include <linux/rwsem.h> #include <linux/slab.h> +#ifdef CONFIG_CRYPTO_FIPS +extern int fips_enabled; +#else +#define fips_enabled 0 +#endif + /* Crypto notification events. */ enum { CRYPTO_MSG_ALG_REQUEST, @@ -82,7 +88,7 @@ static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg) } struct crypto_alg *crypto_mod_get(struct crypto_alg *alg); -struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask); +struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, u32 mask); struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); int crypto_init_digest_ops(struct crypto_tfm *tfm); @@ -94,9 +100,11 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm); void crypto_exit_cipher_ops(struct crypto_tfm *tfm); void crypto_exit_compress_ops(struct crypto_tfm *tfm); +struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask); void crypto_larval_kill(struct crypto_alg *alg); struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask); void crypto_larval_error(const char *name, u32 type, u32 mask); +void crypto_alg_tested(const char *name, int err); void crypto_shoot_alg(struct crypto_alg *alg); struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, @@ -107,6 +115,10 @@ int crypto_register_instance(struct crypto_template *tmpl, int crypto_register_notifier(struct notifier_block *nb); int crypto_unregister_notifier(struct notifier_block *nb); +int crypto_probing_notify(unsigned long val, void *v); + +int __init testmgr_init(void); +void testmgr_exit(void); static inline void crypto_alg_put(struct crypto_alg *alg) { @@ -139,9 +151,9 @@ static inline int crypto_is_moribund(struct crypto_alg *alg) return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING); } -static inline int crypto_notify(unsigned long val, void *v) +static inline void crypto_notify(unsigned long val, void *v) { - return blocking_notifier_call_chain(&crypto_chain, val, v); + blocking_notifier_call_chain(&crypto_chain, val, v); } #endif /* _CRYPTO_INTERNAL_H */ diff --git a/crypto/krng.c b/crypto/krng.c new file mode 100644 index 000000000000..4328bb3430ed --- /dev/null +++ b/crypto/krng.c @@ -0,0 +1,66 @@ +/* + * RNG implementation using standard kernel RNG. + * + * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * any later version. + * + */ + +#include <crypto/internal/rng.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/random.h> + +static int krng_get_random(struct crypto_rng *tfm, u8 *rdata, unsigned int dlen) +{ + get_random_bytes(rdata, dlen); + return 0; +} + +static int krng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) +{ + return 0; +} + +static struct crypto_alg krng_alg = { + .cra_name = "stdrng", + .cra_driver_name = "krng", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_RNG, + .cra_ctxsize = 0, + .cra_type = &crypto_rng_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(krng_alg.cra_list), + .cra_u = { + .rng = { + .rng_make_random = krng_get_random, + .rng_reset = krng_reset, + .seedsize = 0, + } + } +}; + + +/* Module initalization */ +static int __init krng_mod_init(void) +{ + return crypto_register_alg(&krng_alg); +} + +static void __exit krng_mod_fini(void) +{ + crypto_unregister_alg(&krng_alg); + return; +} + +module_init(krng_mod_init); +module_exit(krng_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Kernel Random Number Generator"); +MODULE_ALIAS("stdrng"); diff --git a/crypto/proc.c b/crypto/proc.c index 02ff5670c158..37a13d05636d 100644 --- a/crypto/proc.c +++ b/crypto/proc.c @@ -19,8 +19,53 @@ #include <linux/rwsem.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/sysctl.h> #include "internal.h" +#ifdef CONFIG_CRYPTO_FIPS +static struct ctl_table crypto_sysctl_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "fips_enabled", + .data = &fips_enabled, + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec + }, + { + .ctl_name = 0, + }, +}; + +static struct ctl_table crypto_dir_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "crypto", + .mode = 0555, + .child = crypto_sysctl_table + }, + { + .ctl_name = 0, + }, +}; + +static struct ctl_table_header *crypto_sysctls; + +static void crypto_proc_fips_init(void) +{ + crypto_sysctls = register_sysctl_table(crypto_dir_table); +} + +static void crypto_proc_fips_exit(void) +{ + if (crypto_sysctls) + unregister_sysctl_table(crypto_sysctls); +} +#else +#define crypto_proc_fips_init() +#define crypto_proc_fips_exit() +#endif + static void *c_start(struct seq_file *m, loff_t *pos) { down_read(&crypto_alg_sem); @@ -46,8 +91,11 @@ static int c_show(struct seq_file *m, void *p) seq_printf(m, "module : %s\n", module_name(alg->cra_module)); seq_printf(m, "priority : %d\n", alg->cra_priority); seq_printf(m, "refcnt : %d\n", atomic_read(&alg->cra_refcnt)); + seq_printf(m, "selftest : %s\n", + (alg->cra_flags & CRYPTO_ALG_TESTED) ? + "passed" : "unknown"); - switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { + switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) { case CRYPTO_ALG_TYPE_CIPHER: seq_printf(m, "type : cipher\n"); seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); @@ -67,7 +115,10 @@ static int c_show(struct seq_file *m, void *p) seq_printf(m, "type : compression\n"); break; default: - if (alg->cra_type && alg->cra_type->show) + if (alg->cra_flags & CRYPTO_ALG_LARVAL) { + seq_printf(m, "type : larval\n"); + seq_printf(m, "flags : 0x%x\n", alg->cra_flags); + } else if (alg->cra_type && alg->cra_type->show) alg->cra_type->show(m, alg); else seq_printf(m, "type : unknown\n"); @@ -100,9 +151,11 @@ static const struct file_operations proc_crypto_ops = { void __init crypto_init_proc(void) { proc_create("crypto", 0, NULL, &proc_crypto_ops); + crypto_proc_fips_init(); } void __exit crypto_exit_proc(void) { + crypto_proc_fips_exit(); remove_proc_entry("crypto", NULL); } diff --git a/crypto/rng.c b/crypto/rng.c new file mode 100644 index 000000000000..6e94bc735578 --- /dev/null +++ b/crypto/rng.c @@ -0,0 +1,126 @@ +/* + * Cryptographic API. + * + * RNG operations. + * + * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <asm/atomic.h> +#include <crypto/internal/rng.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/random.h> +#include <linux/seq_file.h> +#include <linux/string.h> + +static DEFINE_MUTEX(crypto_default_rng_lock); +struct crypto_rng *crypto_default_rng; +EXPORT_SYMBOL_GPL(crypto_default_rng); +static int crypto_default_rng_refcnt; + +static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) +{ + u8 *buf = NULL; + int err; + + if (!seed && slen) { + buf = kmalloc(slen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + get_random_bytes(buf, slen); + seed = buf; + } + + err = crypto_rng_alg(tfm)->rng_reset(tfm, seed, slen); + + kfree(buf); + return err; +} + +static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask) +{ + struct rng_alg *alg = &tfm->__crt_alg->cra_rng; + struct rng_tfm *ops = &tfm->crt_rng; + + ops->rng_gen_random = alg->rng_make_random; + ops->rng_reset = rngapi_reset; + + return 0; +} + +static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); +static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_printf(m, "type : rng\n"); + seq_printf(m, "seedsize : %u\n", alg->cra_rng.seedsize); +} + +static unsigned int crypto_rng_ctxsize(struct crypto_alg *alg, u32 type, + u32 mask) +{ + return alg->cra_ctxsize; +} + +const struct crypto_type crypto_rng_type = { + .ctxsize = crypto_rng_ctxsize, + .init = crypto_init_rng_ops, +#ifdef CONFIG_PROC_FS + .show = crypto_rng_show, +#endif +}; +EXPORT_SYMBOL_GPL(crypto_rng_type); + +int crypto_get_default_rng(void) +{ + struct crypto_rng *rng; + int err; + + mutex_lock(&crypto_default_rng_lock); + if (!crypto_default_rng) { + rng = crypto_alloc_rng("stdrng", 0, 0); + err = PTR_ERR(rng); + if (IS_ERR(rng)) + goto unlock; + + err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng)); + if (err) { + crypto_free_rng(rng); + goto unlock; + } + + crypto_default_rng = rng; + } + + crypto_default_rng_refcnt++; + err = 0; + +unlock: + mutex_unlock(&crypto_default_rng_lock); + + return err; +} +EXPORT_SYMBOL_GPL(crypto_get_default_rng); + +void crypto_put_default_rng(void) +{ + mutex_lock(&crypto_default_rng_lock); + if (!--crypto_default_rng_refcnt) { + crypto_free_rng(crypto_default_rng); + crypto_default_rng = NULL; + } + mutex_unlock(&crypto_default_rng_lock); +} +EXPORT_SYMBOL_GPL(crypto_put_default_rng); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Random Number Genertor"); diff --git a/crypto/seqiv.c b/crypto/seqiv.c index b903aab31577..5a013a8bf87a 100644 --- a/crypto/seqiv.c +++ b/crypto/seqiv.c @@ -15,11 +15,11 @@ #include <crypto/internal/aead.h> #include <crypto/internal/skcipher.h> +#include <crypto/rng.h> #include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/random.h> #include <linux/spinlock.h> #include <linux/string.h> @@ -189,17 +189,22 @@ static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req) { struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); + int err = 0; spin_lock_bh(&ctx->lock); if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first) goto unlock; crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt; - get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv)); + err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, + crypto_ablkcipher_ivsize(geniv)); unlock: spin_unlock_bh(&ctx->lock); + if (err) + return err; + return seqiv_givencrypt(req); } @@ -207,17 +212,22 @@ static int seqiv_aead_givencrypt_first(struct aead_givcrypt_request *req) { struct crypto_aead *geniv = aead_givcrypt_reqtfm(req); struct seqiv_ctx *ctx = crypto_aead_ctx(geniv); + int err = 0; spin_lock_bh(&ctx->lock); if (crypto_aead_crt(geniv)->givencrypt != seqiv_aead_givencrypt_first) goto unlock; crypto_aead_crt(geniv)->givencrypt = seqiv_aead_givencrypt; - get_random_bytes(ctx->salt, crypto_aead_ivsize(geniv)); + err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, + crypto_aead_ivsize(geniv)); unlock: spin_unlock_bh(&ctx->lock); + if (err) + return err; + return seqiv_aead_givencrypt(req); } @@ -298,19 +308,27 @@ static struct crypto_instance *seqiv_alloc(struct rtattr **tb) if (IS_ERR(algt)) return ERR_PTR(err); + err = crypto_get_default_rng(); + if (err) + return ERR_PTR(err); + if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) inst = seqiv_ablkcipher_alloc(tb); else inst = seqiv_aead_alloc(tb); if (IS_ERR(inst)) - goto out; + goto put_rng; inst->alg.cra_alignmask |= __alignof__(u32) - 1; inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx); out: return inst; + +put_rng: + crypto_put_default_rng(); + goto out; } static void seqiv_free(struct crypto_instance *inst) @@ -319,6 +337,7 @@ static void seqiv_free(struct crypto_instance *inst) skcipher_geniv_free(inst); else aead_geniv_free(inst); + crypto_put_default_rng(); } static struct crypto_template seqiv_tmpl = { diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 66368022e0bf..28a45a1e6f42 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -19,11 +19,9 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/mm.h> #include <linux/slab.h> #include <linux/scatterlist.h> #include <linux/string.h> -#include <linux/crypto.h> #include <linux/moduleparam.h> #include <linux/jiffies.h> #include <linux/timex.h> @@ -31,45 +29,23 @@ #include "tcrypt.h" /* - * Need to kmalloc() memory for testing. + * Need slab memory for testing (size in number of pages). */ -#define TVMEMSIZE 16384 -#define XBUFSIZE 32768 +#define TVMEMSIZE 4 /* - * Indexes into the xbuf to simulate cross-page access. - */ -#define IDX1 32 -#define IDX2 32400 -#define IDX3 1 -#define IDX4 8193 -#define IDX5 22222 -#define IDX6 17101 -#define IDX7 27333 -#define IDX8 3000 - -/* -* Used by test_cipher() +* Used by test_cipher_speed() */ #define ENCRYPT 1 #define DECRYPT 0 -struct tcrypt_result { - struct completion completion; - int err; -}; - -static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; - /* * Used by test_cipher_speed() */ static unsigned int sec; static int mode; -static char *xbuf; -static char *axbuf; -static char *tvmem; +static char *tvmem[TVMEMSIZE]; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256", @@ -80,655 +56,13 @@ static char *check[] = { "lzo", "cts", NULL }; -static void hexdump(unsigned char *buf, unsigned int len) -{ - print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, - 16, 1, - buf, len, false); -} - -static void tcrypt_complete(struct crypto_async_request *req, int err) -{ - struct tcrypt_result *res = req->data; - - if (err == -EINPROGRESS) - return; - - res->err = err; - complete(&res->completion); -} - -static void test_hash(char *algo, struct hash_testvec *template, - unsigned int tcount) -{ - unsigned int i, j, k, temp; - struct scatterlist sg[8]; - char result[64]; - struct crypto_ahash *tfm; - struct ahash_request *req; - struct tcrypt_result tresult; - int ret; - void *hash_buff; - - printk("\ntesting %s\n", algo); - - init_completion(&tresult.completion); - - tfm = crypto_alloc_ahash(algo, 0, 0); - if (IS_ERR(tfm)) { - printk("failed to load transform for %s: %ld\n", algo, - PTR_ERR(tfm)); - return; - } - - req = ahash_request_alloc(tfm, GFP_KERNEL); - if (!req) { - printk(KERN_ERR "failed to allocate request for %s\n", algo); - goto out_noreq; - } - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &tresult); - - for (i = 0; i < tcount; i++) { - printk("test %u:\n", i + 1); - memset(result, 0, 64); - - hash_buff = kzalloc(template[i].psize, GFP_KERNEL); - if (!hash_buff) - continue; - - memcpy(hash_buff, template[i].plaintext, template[i].psize); - sg_init_one(&sg[0], hash_buff, template[i].psize); - - if (template[i].ksize) { - crypto_ahash_clear_flags(tfm, ~0); - ret = crypto_ahash_setkey(tfm, template[i].key, - template[i].ksize); - if (ret) { - printk("setkey() failed ret=%d\n", ret); - kfree(hash_buff); - goto out; - } - } - - ahash_request_set_crypt(req, sg, result, template[i].psize); - ret = crypto_ahash_digest(req); - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - ret = wait_for_completion_interruptible( - &tresult.completion); - if (!ret && !(ret = tresult.err)) { - INIT_COMPLETION(tresult.completion); - break; - } - /* fall through */ - default: - printk("digest () failed ret=%d\n", ret); - kfree(hash_buff); - goto out; - } - - hexdump(result, crypto_ahash_digestsize(tfm)); - printk("%s\n", - memcmp(result, template[i].digest, - crypto_ahash_digestsize(tfm)) ? - "fail" : "pass"); - kfree(hash_buff); - } - - printk("testing %s across pages\n", algo); - - /* setup the dummy buffer first */ - memset(xbuf, 0, XBUFSIZE); - - j = 0; - for (i = 0; i < tcount; i++) { - if (template[i].np) { - j++; - printk("test %u:\n", j); - memset(result, 0, 64); - - temp = 0; - sg_init_table(sg, template[i].np); - for (k = 0; k < template[i].np; k++) { - memcpy(&xbuf[IDX[k]], - template[i].plaintext + temp, - template[i].tap[k]); - temp += template[i].tap[k]; - sg_set_buf(&sg[k], &xbuf[IDX[k]], - template[i].tap[k]); - } - - if (template[i].ksize) { - crypto_ahash_clear_flags(tfm, ~0); - ret = crypto_ahash_setkey(tfm, template[i].key, - template[i].ksize); - - if (ret) { - printk("setkey() failed ret=%d\n", ret); - goto out; - } - } - - ahash_request_set_crypt(req, sg, result, - template[i].psize); - ret = crypto_ahash_digest(req); - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - ret = wait_for_completion_interruptible( - &tresult.completion); - if (!ret && !(ret = tresult.err)) { - INIT_COMPLETION(tresult.completion); - break; - } - /* fall through */ - default: - printk("digest () failed ret=%d\n", ret); - goto out; - } - - hexdump(result, crypto_ahash_digestsize(tfm)); - printk("%s\n", - memcmp(result, template[i].digest, - crypto_ahash_digestsize(tfm)) ? - "fail" : "pass"); - } - } - -out: - ahash_request_free(req); -out_noreq: - crypto_free_ahash(tfm); -} - -static void test_aead(char *algo, int enc, struct aead_testvec *template, - unsigned int tcount) -{ - unsigned int ret, i, j, k, n, temp; - char *q; - struct crypto_aead *tfm; - char *key; - struct aead_request *req; - struct scatterlist sg[8]; - struct scatterlist asg[8]; - const char *e; - struct tcrypt_result result; - unsigned int authsize; - void *input; - void *assoc; - char iv[MAX_IVLEN]; - - if (enc == ENCRYPT) - e = "encryption"; - else - e = "decryption"; - - printk(KERN_INFO "\ntesting %s %s\n", algo, e); - - init_completion(&result.completion); - - tfm = crypto_alloc_aead(algo, 0, 0); - - if (IS_ERR(tfm)) { - printk(KERN_INFO "failed to load transform for %s: %ld\n", - algo, PTR_ERR(tfm)); - return; - } - - req = aead_request_alloc(tfm, GFP_KERNEL); - if (!req) { - printk(KERN_INFO "failed to allocate request for %s\n", algo); - goto out; - } - - aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); - - for (i = 0, j = 0; i < tcount; i++) { - if (!template[i].np) { - printk(KERN_INFO "test %u (%d bit key):\n", - ++j, template[i].klen * 8); - - /* some tepmplates have no input data but they will - * touch input - */ - input = kzalloc(template[i].ilen + template[i].rlen, GFP_KERNEL); - if (!input) - continue; - - assoc = kzalloc(template[i].alen, GFP_KERNEL); - if (!assoc) { - kfree(input); - continue; - } - - memcpy(input, template[i].input, template[i].ilen); - memcpy(assoc, template[i].assoc, template[i].alen); - if (template[i].iv) - memcpy(iv, template[i].iv, MAX_IVLEN); - else - memset(iv, 0, MAX_IVLEN); - - crypto_aead_clear_flags(tfm, ~0); - if (template[i].wk) - crypto_aead_set_flags( - tfm, CRYPTO_TFM_REQ_WEAK_KEY); - - if (template[i].key) - key = template[i].key; - else - key = kzalloc(template[i].klen, GFP_KERNEL); - - ret = crypto_aead_setkey(tfm, key, - template[i].klen); - if (ret) { - printk(KERN_INFO "setkey() failed flags=%x\n", - crypto_aead_get_flags(tfm)); - - if (!template[i].fail) - goto next_one; - } - - authsize = abs(template[i].rlen - template[i].ilen); - ret = crypto_aead_setauthsize(tfm, authsize); - if (ret) { - printk(KERN_INFO - "failed to set authsize = %u\n", - authsize); - goto next_one; - } - - sg_init_one(&sg[0], input, - template[i].ilen + (enc ? authsize : 0)); - - sg_init_one(&asg[0], assoc, template[i].alen); - - aead_request_set_crypt(req, sg, sg, - template[i].ilen, iv); - - aead_request_set_assoc(req, asg, template[i].alen); - - ret = enc ? - crypto_aead_encrypt(req) : - crypto_aead_decrypt(req); - - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - ret = wait_for_completion_interruptible( - &result.completion); - if (!ret && !(ret = result.err)) { - INIT_COMPLETION(result.completion); - break; - } - /* fall through */ - default: - printk(KERN_INFO "%s () failed err=%d\n", - e, -ret); - goto next_one; - } - - q = input; - hexdump(q, template[i].rlen); - - printk(KERN_INFO "enc/dec: %s\n", - memcmp(q, template[i].result, - template[i].rlen) ? "fail" : "pass"); -next_one: - if (!template[i].key) - kfree(key); - kfree(assoc); - kfree(input); - } - } - - printk(KERN_INFO "\ntesting %s %s across pages (chunking)\n", algo, e); - memset(axbuf, 0, XBUFSIZE); - - for (i = 0, j = 0; i < tcount; i++) { - if (template[i].np) { - printk(KERN_INFO "test %u (%d bit key):\n", - ++j, template[i].klen * 8); - - if (template[i].iv) - memcpy(iv, template[i].iv, MAX_IVLEN); - else - memset(iv, 0, MAX_IVLEN); - - crypto_aead_clear_flags(tfm, ~0); - if (template[i].wk) - crypto_aead_set_flags( - tfm, CRYPTO_TFM_REQ_WEAK_KEY); - key = template[i].key; - - ret = crypto_aead_setkey(tfm, key, template[i].klen); - if (ret) { - printk(KERN_INFO "setkey() failed flags=%x\n", - crypto_aead_get_flags(tfm)); - - if (!template[i].fail) - goto out; - } - - memset(xbuf, 0, XBUFSIZE); - sg_init_table(sg, template[i].np); - for (k = 0, temp = 0; k < template[i].np; k++) { - memcpy(&xbuf[IDX[k]], - template[i].input + temp, - template[i].tap[k]); - temp += template[i].tap[k]; - sg_set_buf(&sg[k], &xbuf[IDX[k]], - template[i].tap[k]); - } - - authsize = abs(template[i].rlen - template[i].ilen); - ret = crypto_aead_setauthsize(tfm, authsize); - if (ret) { - printk(KERN_INFO - "failed to set authsize = %u\n", - authsize); - goto out; - } - - if (enc) - sg[k - 1].length += authsize; - - sg_init_table(asg, template[i].anp); - for (k = 0, temp = 0; k < template[i].anp; k++) { - memcpy(&axbuf[IDX[k]], - template[i].assoc + temp, - template[i].atap[k]); - temp += template[i].atap[k]; - sg_set_buf(&asg[k], &axbuf[IDX[k]], - template[i].atap[k]); - } - - aead_request_set_crypt(req, sg, sg, - template[i].ilen, - iv); - - aead_request_set_assoc(req, asg, template[i].alen); - - ret = enc ? - crypto_aead_encrypt(req) : - crypto_aead_decrypt(req); - - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - ret = wait_for_completion_interruptible( - &result.completion); - if (!ret && !(ret = result.err)) { - INIT_COMPLETION(result.completion); - break; - } - /* fall through */ - default: - printk(KERN_INFO "%s () failed err=%d\n", - e, -ret); - goto out; - } - - for (k = 0, temp = 0; k < template[i].np; k++) { - printk(KERN_INFO "page %u\n", k); - q = &xbuf[IDX[k]]; - - n = template[i].tap[k]; - if (k == template[i].np - 1) - n += enc ? authsize : -authsize; - hexdump(q, n); - printk(KERN_INFO "%s\n", - memcmp(q, template[i].result + temp, n) ? - "fail" : "pass"); - - q += n; - if (k == template[i].np - 1 && !enc) { - if (memcmp(q, template[i].input + - temp + n, authsize)) - n = authsize; - else - n = 0; - } else { - for (n = 0; q[n]; n++) - ; - } - if (n) { - printk("Result buffer corruption %u " - "bytes:\n", n); - hexdump(q, n); - } - - temp += template[i].tap[k]; - } - } - } - -out: - crypto_free_aead(tfm); - aead_request_free(req); -} - -static void test_cipher(char *algo, int enc, - struct cipher_testvec *template, unsigned int tcount) +static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, + struct scatterlist *sg, int blen, int sec) { - unsigned int ret, i, j, k, n, temp; - char *q; - struct crypto_ablkcipher *tfm; - struct ablkcipher_request *req; - struct scatterlist sg[8]; - const char *e; - struct tcrypt_result result; - void *data; - char iv[MAX_IVLEN]; - - if (enc == ENCRYPT) - e = "encryption"; - else - e = "decryption"; - - printk("\ntesting %s %s\n", algo, e); - - init_completion(&result.completion); - tfm = crypto_alloc_ablkcipher(algo, 0, 0); - - if (IS_ERR(tfm)) { - printk("failed to load transform for %s: %ld\n", algo, - PTR_ERR(tfm)); - return; - } - - req = ablkcipher_request_alloc(tfm, GFP_KERNEL); - if (!req) { - printk("failed to allocate request for %s\n", algo); - goto out; - } - - ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); - - j = 0; - for (i = 0; i < tcount; i++) { - - data = kzalloc(template[i].ilen, GFP_KERNEL); - if (!data) - continue; - - memcpy(data, template[i].input, template[i].ilen); - if (template[i].iv) - memcpy(iv, template[i].iv, MAX_IVLEN); - else - memset(iv, 0, MAX_IVLEN); - - if (!(template[i].np)) { - j++; - printk("test %u (%d bit key):\n", - j, template[i].klen * 8); - - crypto_ablkcipher_clear_flags(tfm, ~0); - if (template[i].wk) - crypto_ablkcipher_set_flags( - tfm, CRYPTO_TFM_REQ_WEAK_KEY); - - ret = crypto_ablkcipher_setkey(tfm, template[i].key, - template[i].klen); - if (ret) { - printk("setkey() failed flags=%x\n", - crypto_ablkcipher_get_flags(tfm)); - - if (!template[i].fail) { - kfree(data); - goto out; - } - } - - sg_init_one(&sg[0], data, template[i].ilen); - - ablkcipher_request_set_crypt(req, sg, sg, - template[i].ilen, iv); - ret = enc ? - crypto_ablkcipher_encrypt(req) : - crypto_ablkcipher_decrypt(req); - - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - ret = wait_for_completion_interruptible( - &result.completion); - if (!ret && !((ret = result.err))) { - INIT_COMPLETION(result.completion); - break; - } - /* fall through */ - default: - printk("%s () failed err=%d\n", e, -ret); - kfree(data); - goto out; - } - - q = data; - hexdump(q, template[i].rlen); - - printk("%s\n", - memcmp(q, template[i].result, - template[i].rlen) ? "fail" : "pass"); - } - kfree(data); - } - - printk("\ntesting %s %s across pages (chunking)\n", algo, e); - - j = 0; - for (i = 0; i < tcount; i++) { - - if (template[i].iv) - memcpy(iv, template[i].iv, MAX_IVLEN); - else - memset(iv, 0, MAX_IVLEN); - - if (template[i].np) { - j++; - printk("test %u (%d bit key):\n", - j, template[i].klen * 8); - - memset(xbuf, 0, XBUFSIZE); - crypto_ablkcipher_clear_flags(tfm, ~0); - if (template[i].wk) - crypto_ablkcipher_set_flags( - tfm, CRYPTO_TFM_REQ_WEAK_KEY); - - ret = crypto_ablkcipher_setkey(tfm, template[i].key, - template[i].klen); - if (ret) { - printk("setkey() failed flags=%x\n", - crypto_ablkcipher_get_flags(tfm)); - - if (!template[i].fail) - goto out; - } - - temp = 0; - sg_init_table(sg, template[i].np); - for (k = 0; k < template[i].np; k++) { - memcpy(&xbuf[IDX[k]], - template[i].input + temp, - template[i].tap[k]); - temp += template[i].tap[k]; - sg_set_buf(&sg[k], &xbuf[IDX[k]], - template[i].tap[k]); - } - - ablkcipher_request_set_crypt(req, sg, sg, - template[i].ilen, iv); - - ret = enc ? - crypto_ablkcipher_encrypt(req) : - crypto_ablkcipher_decrypt(req); - - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - ret = wait_for_completion_interruptible( - &result.completion); - if (!ret && !((ret = result.err))) { - INIT_COMPLETION(result.completion); - break; - } - /* fall through */ - default: - printk("%s () failed err=%d\n", e, -ret); - goto out; - } - - temp = 0; - for (k = 0; k < template[i].np; k++) { - printk("page %u\n", k); - q = &xbuf[IDX[k]]; - hexdump(q, template[i].tap[k]); - printk("%s\n", - memcmp(q, template[i].result + temp, - template[i].tap[k]) ? "fail" : - "pass"); - - for (n = 0; q[template[i].tap[k] + n]; n++) - ; - if (n) { - printk("Result buffer corruption %u " - "bytes:\n", n); - hexdump(&q[template[i].tap[k]], n); - } - temp += template[i].tap[k]; - } - } - } -out: - crypto_free_ablkcipher(tfm); - ablkcipher_request_free(req); -} - -static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p, - int blen, int sec) -{ - struct scatterlist sg[1]; unsigned long start, end; int bcount; int ret; - sg_init_one(sg, p, blen); - for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) @@ -745,16 +79,13 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p, return 0; } -static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p, - int blen) +static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, + struct scatterlist *sg, int blen) { - struct scatterlist sg[1]; unsigned long cycles = 0; int ret = 0; int i; - sg_init_one(sg, p, blen); - local_bh_disable(); local_irq_disable(); @@ -799,12 +130,12 @@ out: static u32 block_sizes[] = { 16, 64, 256, 1024, 8192, 0 }; -static void test_cipher_speed(char *algo, int enc, unsigned int sec, - struct cipher_testvec *template, +static void test_cipher_speed(const char *algo, int enc, unsigned int sec, + struct cipher_speed_template *template, unsigned int tcount, u8 *keysize) { unsigned int ret, i, j, iv_len; - unsigned char *key, *p, iv[128]; + const char *key, iv[128]; struct crypto_blkcipher *tfm; struct blkcipher_desc desc; const char *e; @@ -832,27 +163,28 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec, b_size = block_sizes; do { + struct scatterlist sg[TVMEMSIZE]; - if ((*keysize + *b_size) > TVMEMSIZE) { - printk("template (%u) too big for tvmem (%u)\n", - *keysize + *b_size, TVMEMSIZE); + if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) { + printk("template (%u) too big for " + "tvmem (%lu)\n", *keysize + *b_size, + TVMEMSIZE * PAGE_SIZE); goto out; } printk("test %u (%d bit key, %d byte blocks): ", i, *keysize * 8, *b_size); - memset(tvmem, 0xff, *keysize + *b_size); + memset(tvmem[0], 0xff, PAGE_SIZE); /* set key, plain text and IV */ - key = (unsigned char *)tvmem; + key = tvmem[0]; for (j = 0; j < tcount; j++) { if (template[j].klen == *keysize) { key = template[j].key; break; } } - p = (unsigned char *)tvmem + *keysize; ret = crypto_blkcipher_setkey(tfm, key, *keysize); if (ret) { @@ -861,6 +193,14 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec, goto out; } + sg_init_table(sg, TVMEMSIZE); + sg_set_buf(sg, tvmem[0] + *keysize, + PAGE_SIZE - *keysize); + for (j = 1; j < TVMEMSIZE; j++) { + sg_set_buf(sg + j, tvmem[j], PAGE_SIZE); + memset (tvmem[j], 0xff, PAGE_SIZE); + } + iv_len = crypto_blkcipher_ivsize(tfm); if (iv_len) { memset(&iv, 0xff, iv_len); @@ -868,9 +208,11 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec, } if (sec) - ret = test_cipher_jiffies(&desc, enc, p, *b_size, sec); + ret = test_cipher_jiffies(&desc, enc, sg, + *b_size, sec); else - ret = test_cipher_cycles(&desc, enc, p, *b_size); + ret = test_cipher_cycles(&desc, enc, sg, + *b_size); if (ret) { printk("%s() failed flags=%x\n", e, desc.flags); @@ -886,19 +228,16 @@ out: crypto_free_blkcipher(tfm); } -static int test_hash_jiffies_digest(struct hash_desc *desc, char *p, int blen, +static int test_hash_jiffies_digest(struct hash_desc *desc, + struct scatterlist *sg, int blen, char *out, int sec) { - struct scatterlist sg[1]; unsigned long start, end; int bcount; int ret; - sg_init_table(sg, 1); - for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { - sg_set_buf(sg, p, blen); ret = crypto_hash_digest(desc, sg, blen, out); if (ret) return ret; @@ -910,18 +249,15 @@ static int test_hash_jiffies_digest(struct hash_desc *desc, char *p, int blen, return 0; } -static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen, - int plen, char *out, int sec) +static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg, + int blen, int plen, char *out, int sec) { - struct scatterlist sg[1]; unsigned long start, end; int bcount, pcount; int ret; if (plen == blen) - return test_hash_jiffies_digest(desc, p, blen, out, sec); - - sg_init_table(sg, 1); + return test_hash_jiffies_digest(desc, sg, blen, out, sec); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { @@ -929,7 +265,6 @@ static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen, if (ret) return ret; for (pcount = 0; pcount < blen; pcount += plen) { - sg_set_buf(sg, p + pcount, plen); ret = crypto_hash_update(desc, sg, plen); if (ret) return ret; @@ -946,22 +281,18 @@ static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen, return 0; } -static int test_hash_cycles_digest(struct hash_desc *desc, char *p, int blen, - char *out) +static int test_hash_cycles_digest(struct hash_desc *desc, + struct scatterlist *sg, int blen, char *out) { - struct scatterlist sg[1]; unsigned long cycles = 0; int i; int ret; - sg_init_table(sg, 1); - local_bh_disable(); local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { - sg_set_buf(sg, p, blen); ret = crypto_hash_digest(desc, sg, blen, out); if (ret) goto out; @@ -973,7 +304,6 @@ static int test_hash_cycles_digest(struct hash_desc *desc, char *p, int blen, start = get_cycles(); - sg_set_buf(sg, p, blen); ret = crypto_hash_digest(desc, sg, blen, out); if (ret) goto out; @@ -996,18 +326,15 @@ out: return 0; } -static int test_hash_cycles(struct hash_desc *desc, char *p, int blen, - int plen, char *out) +static int test_hash_cycles(struct hash_desc *desc, struct scatterlist *sg, + int blen, int plen, char *out) { - struct scatterlist sg[1]; unsigned long cycles = 0; int i, pcount; int ret; if (plen == blen) - return test_hash_cycles_digest(desc, p, blen, out); - - sg_init_table(sg, 1); + return test_hash_cycles_digest(desc, sg, blen, out); local_bh_disable(); local_irq_disable(); @@ -1018,7 +345,6 @@ static int test_hash_cycles(struct hash_desc *desc, char *p, int blen, if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { - sg_set_buf(sg, p + pcount, plen); ret = crypto_hash_update(desc, sg, plen); if (ret) goto out; @@ -1038,7 +364,6 @@ static int test_hash_cycles(struct hash_desc *desc, char *p, int blen, if (ret) goto out; for (pcount = 0; pcount < blen; pcount += plen) { - sg_set_buf(sg, p + pcount, plen); ret = crypto_hash_update(desc, sg, plen); if (ret) goto out; @@ -1065,9 +390,10 @@ out: return 0; } -static void test_hash_speed(char *algo, unsigned int sec, - struct hash_speed *speed) +static void test_hash_speed(const char *algo, unsigned int sec, + struct hash_speed *speed) { + struct scatterlist sg[TVMEMSIZE]; struct crypto_hash *tfm; struct hash_desc desc; char output[1024]; @@ -1093,23 +419,27 @@ static void test_hash_speed(char *algo, unsigned int sec, goto out; } + sg_init_table(sg, TVMEMSIZE); + for (i = 0; i < TVMEMSIZE; i++) { + sg_set_buf(sg + i, tvmem[i], PAGE_SIZE); + memset(tvmem[i], 0xff, PAGE_SIZE); + } + for (i = 0; speed[i].blen != 0; i++) { - if (speed[i].blen > TVMEMSIZE) { - printk("template (%u) too big for tvmem (%u)\n", - speed[i].blen, TVMEMSIZE); + if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) { + printk("template (%u) too big for tvmem (%lu)\n", + speed[i].blen, TVMEMSIZE * PAGE_SIZE); goto out; } printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ", i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); - memset(tvmem, 0xff, speed[i].blen); - if (sec) - ret = test_hash_jiffies(&desc, tvmem, speed[i].blen, + ret = test_hash_jiffies(&desc, sg, speed[i].blen, speed[i].plen, output, sec); else - ret = test_hash_cycles(&desc, tvmem, speed[i].blen, + ret = test_hash_cycles(&desc, sg, speed[i].blen, speed[i].plen, output); if (ret) { @@ -1122,73 +452,6 @@ out: crypto_free_hash(tfm); } -static void test_comp(char *algo, struct comp_testvec *ctemplate, - struct comp_testvec *dtemplate, int ctcount, int dtcount) -{ - unsigned int i; - char result[COMP_BUF_SIZE]; - struct crypto_comp *tfm; - unsigned int tsize; - - printk("\ntesting %s compression\n", algo); - - tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { - printk("failed to load transform for %s\n", algo); - return; - } - - for (i = 0; i < ctcount; i++) { - int ilen, ret, dlen = COMP_BUF_SIZE; - - printk("test %u:\n", i + 1); - memset(result, 0, sizeof (result)); - - ilen = ctemplate[i].inlen; - ret = crypto_comp_compress(tfm, ctemplate[i].input, - ilen, result, &dlen); - if (ret) { - printk("fail: ret=%d\n", ret); - continue; - } - hexdump(result, dlen); - printk("%s (ratio %d:%d)\n", - memcmp(result, ctemplate[i].output, dlen) ? "fail" : "pass", - ilen, dlen); - } - - printk("\ntesting %s decompression\n", algo); - - tsize = sizeof(struct comp_testvec); - tsize *= dtcount; - if (tsize > TVMEMSIZE) { - printk("template (%u) too big for tvmem (%u)\n", tsize, - TVMEMSIZE); - goto out; - } - - for (i = 0; i < dtcount; i++) { - int ilen, ret, dlen = COMP_BUF_SIZE; - - printk("test %u:\n", i + 1); - memset(result, 0, sizeof (result)); - - ilen = dtemplate[i].inlen; - ret = crypto_comp_decompress(tfm, dtemplate[i].input, - ilen, result, &dlen); - if (ret) { - printk("fail: ret=%d\n", ret); - continue; - } - hexdump(result, dlen); - printk("%s (ratio %d:%d)\n", - memcmp(result, dtemplate[i].output, dlen) ? "fail" : "pass", - ilen, dlen); - } -out: - crypto_free_comp(tfm); -} - static void test_available(void) { char **name = check; @@ -1201,549 +464,237 @@ static void test_available(void) } } -static void do_test(void) +static inline int tcrypt_test(const char *alg) { - switch (mode) { + return alg_test(alg, alg, 0, 0); +} + +static void do_test(int m) +{ + int i; + switch (m) { case 0: - test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); - - test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); - - //DES - test_cipher("ecb(des)", ENCRYPT, des_enc_tv_template, - DES_ENC_TEST_VECTORS); - test_cipher("ecb(des)", DECRYPT, des_dec_tv_template, - DES_DEC_TEST_VECTORS); - test_cipher("cbc(des)", ENCRYPT, des_cbc_enc_tv_template, - DES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(des)", DECRYPT, des_cbc_dec_tv_template, - DES_CBC_DEC_TEST_VECTORS); - - //DES3_EDE - test_cipher("ecb(des3_ede)", ENCRYPT, des3_ede_enc_tv_template, - DES3_EDE_ENC_TEST_VECTORS); - test_cipher("ecb(des3_ede)", DECRYPT, des3_ede_dec_tv_template, - DES3_EDE_DEC_TEST_VECTORS); - - test_cipher("cbc(des3_ede)", ENCRYPT, - des3_ede_cbc_enc_tv_template, - DES3_EDE_CBC_ENC_TEST_VECTORS); - - test_cipher("cbc(des3_ede)", DECRYPT, - des3_ede_cbc_dec_tv_template, - DES3_EDE_CBC_DEC_TEST_VECTORS); - - test_hash("md4", md4_tv_template, MD4_TEST_VECTORS); - - test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS); - - test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS); - - //BLOWFISH - test_cipher("ecb(blowfish)", ENCRYPT, bf_enc_tv_template, - BF_ENC_TEST_VECTORS); - test_cipher("ecb(blowfish)", DECRYPT, bf_dec_tv_template, - BF_DEC_TEST_VECTORS); - test_cipher("cbc(blowfish)", ENCRYPT, bf_cbc_enc_tv_template, - BF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(blowfish)", DECRYPT, bf_cbc_dec_tv_template, - BF_CBC_DEC_TEST_VECTORS); - - //TWOFISH - test_cipher("ecb(twofish)", ENCRYPT, tf_enc_tv_template, - TF_ENC_TEST_VECTORS); - test_cipher("ecb(twofish)", DECRYPT, tf_dec_tv_template, - TF_DEC_TEST_VECTORS); - test_cipher("cbc(twofish)", ENCRYPT, tf_cbc_enc_tv_template, - TF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(twofish)", DECRYPT, tf_cbc_dec_tv_template, - TF_CBC_DEC_TEST_VECTORS); - - //SERPENT - test_cipher("ecb(serpent)", ENCRYPT, serpent_enc_tv_template, - SERPENT_ENC_TEST_VECTORS); - test_cipher("ecb(serpent)", DECRYPT, serpent_dec_tv_template, - SERPENT_DEC_TEST_VECTORS); - - //TNEPRES - test_cipher("ecb(tnepres)", ENCRYPT, tnepres_enc_tv_template, - TNEPRES_ENC_TEST_VECTORS); - test_cipher("ecb(tnepres)", DECRYPT, tnepres_dec_tv_template, - TNEPRES_DEC_TEST_VECTORS); - - //AES - test_cipher("ecb(aes)", ENCRYPT, aes_enc_tv_template, - AES_ENC_TEST_VECTORS); - test_cipher("ecb(aes)", DECRYPT, aes_dec_tv_template, - AES_DEC_TEST_VECTORS); - test_cipher("cbc(aes)", ENCRYPT, aes_cbc_enc_tv_template, - AES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template, - AES_CBC_DEC_TEST_VECTORS); - test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template, - AES_LRW_ENC_TEST_VECTORS); - test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template, - AES_LRW_DEC_TEST_VECTORS); - test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template, - AES_XTS_ENC_TEST_VECTORS); - test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template, - AES_XTS_DEC_TEST_VECTORS); - test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template, - AES_CTR_ENC_TEST_VECTORS); - test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template, - AES_CTR_DEC_TEST_VECTORS); - test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template, - AES_GCM_ENC_TEST_VECTORS); - test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template, - AES_GCM_DEC_TEST_VECTORS); - test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template, - AES_CCM_ENC_TEST_VECTORS); - test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template, - AES_CCM_DEC_TEST_VECTORS); - - //CAST5 - test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template, - CAST5_ENC_TEST_VECTORS); - test_cipher("ecb(cast5)", DECRYPT, cast5_dec_tv_template, - CAST5_DEC_TEST_VECTORS); - - //CAST6 - test_cipher("ecb(cast6)", ENCRYPT, cast6_enc_tv_template, - CAST6_ENC_TEST_VECTORS); - test_cipher("ecb(cast6)", DECRYPT, cast6_dec_tv_template, - CAST6_DEC_TEST_VECTORS); - - //ARC4 - test_cipher("ecb(arc4)", ENCRYPT, arc4_enc_tv_template, - ARC4_ENC_TEST_VECTORS); - test_cipher("ecb(arc4)", DECRYPT, arc4_dec_tv_template, - ARC4_DEC_TEST_VECTORS); - - //TEA - test_cipher("ecb(tea)", ENCRYPT, tea_enc_tv_template, - TEA_ENC_TEST_VECTORS); - test_cipher("ecb(tea)", DECRYPT, tea_dec_tv_template, - TEA_DEC_TEST_VECTORS); - - - //XTEA - test_cipher("ecb(xtea)", ENCRYPT, xtea_enc_tv_template, - XTEA_ENC_TEST_VECTORS); - test_cipher("ecb(xtea)", DECRYPT, xtea_dec_tv_template, - XTEA_DEC_TEST_VECTORS); - - //KHAZAD - test_cipher("ecb(khazad)", ENCRYPT, khazad_enc_tv_template, - KHAZAD_ENC_TEST_VECTORS); - test_cipher("ecb(khazad)", DECRYPT, khazad_dec_tv_template, - KHAZAD_DEC_TEST_VECTORS); - - //ANUBIS - test_cipher("ecb(anubis)", ENCRYPT, anubis_enc_tv_template, - ANUBIS_ENC_TEST_VECTORS); - test_cipher("ecb(anubis)", DECRYPT, anubis_dec_tv_template, - ANUBIS_DEC_TEST_VECTORS); - test_cipher("cbc(anubis)", ENCRYPT, anubis_cbc_enc_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(anubis)", DECRYPT, anubis_cbc_dec_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); - - //XETA - test_cipher("ecb(xeta)", ENCRYPT, xeta_enc_tv_template, - XETA_ENC_TEST_VECTORS); - test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template, - XETA_DEC_TEST_VECTORS); - - //FCrypt - test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template, - FCRYPT_ENC_TEST_VECTORS); - test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template, - FCRYPT_DEC_TEST_VECTORS); - - //CAMELLIA - test_cipher("ecb(camellia)", ENCRYPT, - camellia_enc_tv_template, - CAMELLIA_ENC_TEST_VECTORS); - test_cipher("ecb(camellia)", DECRYPT, - camellia_dec_tv_template, - CAMELLIA_DEC_TEST_VECTORS); - test_cipher("cbc(camellia)", ENCRYPT, - camellia_cbc_enc_tv_template, - CAMELLIA_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(camellia)", DECRYPT, - camellia_cbc_dec_tv_template, - CAMELLIA_CBC_DEC_TEST_VECTORS); - - //SEED - test_cipher("ecb(seed)", ENCRYPT, seed_enc_tv_template, - SEED_ENC_TEST_VECTORS); - test_cipher("ecb(seed)", DECRYPT, seed_dec_tv_template, - SEED_DEC_TEST_VECTORS); - - //CTS - test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template, - CTS_MODE_ENC_TEST_VECTORS); - test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template, - CTS_MODE_DEC_TEST_VECTORS); - - test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); - test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); - test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS); - test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS); - test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS); - test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS); - test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS); - test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS); - test_comp("deflate", deflate_comp_tv_template, - deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS, - DEFLATE_DECOMP_TEST_VECTORS); - test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template, - LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS); - test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS); - test_hash("hmac(md5)", hmac_md5_tv_template, - HMAC_MD5_TEST_VECTORS); - test_hash("hmac(sha1)", hmac_sha1_tv_template, - HMAC_SHA1_TEST_VECTORS); - test_hash("hmac(sha224)", hmac_sha224_tv_template, - HMAC_SHA224_TEST_VECTORS); - test_hash("hmac(sha256)", hmac_sha256_tv_template, - HMAC_SHA256_TEST_VECTORS); - test_hash("hmac(sha384)", hmac_sha384_tv_template, - HMAC_SHA384_TEST_VECTORS); - test_hash("hmac(sha512)", hmac_sha512_tv_template, - HMAC_SHA512_TEST_VECTORS); - - test_hash("xcbc(aes)", aes_xcbc128_tv_template, - XCBC_AES_TEST_VECTORS); - - test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS); + for (i = 1; i < 200; i++) + do_test(i); break; case 1: - test_hash("md5", md5_tv_template, MD5_TEST_VECTORS); + tcrypt_test("md5"); break; case 2: - test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); + tcrypt_test("sha1"); break; case 3: - test_cipher("ecb(des)", ENCRYPT, des_enc_tv_template, - DES_ENC_TEST_VECTORS); - test_cipher("ecb(des)", DECRYPT, des_dec_tv_template, - DES_DEC_TEST_VECTORS); - test_cipher("cbc(des)", ENCRYPT, des_cbc_enc_tv_template, - DES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(des)", DECRYPT, des_cbc_dec_tv_template, - DES_CBC_DEC_TEST_VECTORS); + tcrypt_test("ecb(des)"); + tcrypt_test("cbc(des)"); break; case 4: - test_cipher("ecb(des3_ede)", ENCRYPT, des3_ede_enc_tv_template, - DES3_EDE_ENC_TEST_VECTORS); - test_cipher("ecb(des3_ede)", DECRYPT, des3_ede_dec_tv_template, - DES3_EDE_DEC_TEST_VECTORS); - - test_cipher("cbc(des3_ede)", ENCRYPT, - des3_ede_cbc_enc_tv_template, - DES3_EDE_CBC_ENC_TEST_VECTORS); - - test_cipher("cbc(des3_ede)", DECRYPT, - des3_ede_cbc_dec_tv_template, - DES3_EDE_CBC_DEC_TEST_VECTORS); + tcrypt_test("ecb(des3_ede)"); + tcrypt_test("cbc(des3_ede)"); break; case 5: - test_hash("md4", md4_tv_template, MD4_TEST_VECTORS); + tcrypt_test("md4"); break; case 6: - test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS); + tcrypt_test("sha256"); break; case 7: - test_cipher("ecb(blowfish)", ENCRYPT, bf_enc_tv_template, - BF_ENC_TEST_VECTORS); - test_cipher("ecb(blowfish)", DECRYPT, bf_dec_tv_template, - BF_DEC_TEST_VECTORS); - test_cipher("cbc(blowfish)", ENCRYPT, bf_cbc_enc_tv_template, - BF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(blowfish)", DECRYPT, bf_cbc_dec_tv_template, - BF_CBC_DEC_TEST_VECTORS); + tcrypt_test("ecb(blowfish)"); + tcrypt_test("cbc(blowfish)"); break; case 8: - test_cipher("ecb(twofish)", ENCRYPT, tf_enc_tv_template, - TF_ENC_TEST_VECTORS); - test_cipher("ecb(twofish)", DECRYPT, tf_dec_tv_template, - TF_DEC_TEST_VECTORS); - test_cipher("cbc(twofish)", ENCRYPT, tf_cbc_enc_tv_template, - TF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(twofish)", DECRYPT, tf_cbc_dec_tv_template, - TF_CBC_DEC_TEST_VECTORS); + tcrypt_test("ecb(twofish)"); + tcrypt_test("cbc(twofish)"); break; case 9: - test_cipher("ecb(serpent)", ENCRYPT, serpent_enc_tv_template, - SERPENT_ENC_TEST_VECTORS); - test_cipher("ecb(serpent)", DECRYPT, serpent_dec_tv_template, - SERPENT_DEC_TEST_VECTORS); + tcrypt_test("ecb(serpent)"); break; case 10: - test_cipher("ecb(aes)", ENCRYPT, aes_enc_tv_template, - AES_ENC_TEST_VECTORS); - test_cipher("ecb(aes)", DECRYPT, aes_dec_tv_template, - AES_DEC_TEST_VECTORS); - test_cipher("cbc(aes)", ENCRYPT, aes_cbc_enc_tv_template, - AES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template, - AES_CBC_DEC_TEST_VECTORS); - test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template, - AES_LRW_ENC_TEST_VECTORS); - test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template, - AES_LRW_DEC_TEST_VECTORS); - test_cipher("xts(aes)", ENCRYPT, aes_xts_enc_tv_template, - AES_XTS_ENC_TEST_VECTORS); - test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template, - AES_XTS_DEC_TEST_VECTORS); - test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template, - AES_CTR_ENC_TEST_VECTORS); - test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template, - AES_CTR_DEC_TEST_VECTORS); + tcrypt_test("ecb(aes)"); + tcrypt_test("cbc(aes)"); + tcrypt_test("lrw(aes)"); + tcrypt_test("xts(aes)"); + tcrypt_test("rfc3686(ctr(aes))"); break; case 11: - test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); + tcrypt_test("sha384"); break; case 12: - test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); + tcrypt_test("sha512"); break; case 13: - test_comp("deflate", deflate_comp_tv_template, - deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS, - DEFLATE_DECOMP_TEST_VECTORS); + tcrypt_test("deflate"); break; case 14: - test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template, - CAST5_ENC_TEST_VECTORS); - test_cipher("ecb(cast5)", DECRYPT, cast5_dec_tv_template, - CAST5_DEC_TEST_VECTORS); + tcrypt_test("ecb(cast5)"); break; case 15: - test_cipher("ecb(cast6)", ENCRYPT, cast6_enc_tv_template, - CAST6_ENC_TEST_VECTORS); - test_cipher("ecb(cast6)", DECRYPT, cast6_dec_tv_template, - CAST6_DEC_TEST_VECTORS); + tcrypt_test("ecb(cast6)"); break; case 16: - test_cipher("ecb(arc4)", ENCRYPT, arc4_enc_tv_template, - ARC4_ENC_TEST_VECTORS); - test_cipher("ecb(arc4)", DECRYPT, arc4_dec_tv_template, - ARC4_DEC_TEST_VECTORS); + tcrypt_test("ecb(arc4)"); break; case 17: - test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS); + tcrypt_test("michael_mic"); break; case 18: - test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS); + tcrypt_test("crc32c"); break; case 19: - test_cipher("ecb(tea)", ENCRYPT, tea_enc_tv_template, - TEA_ENC_TEST_VECTORS); - test_cipher("ecb(tea)", DECRYPT, tea_dec_tv_template, - TEA_DEC_TEST_VECTORS); + tcrypt_test("ecb(tea)"); break; case 20: - test_cipher("ecb(xtea)", ENCRYPT, xtea_enc_tv_template, - XTEA_ENC_TEST_VECTORS); - test_cipher("ecb(xtea)", DECRYPT, xtea_dec_tv_template, - XTEA_DEC_TEST_VECTORS); + tcrypt_test("ecb(xtea)"); break; case 21: - test_cipher("ecb(khazad)", ENCRYPT, khazad_enc_tv_template, - KHAZAD_ENC_TEST_VECTORS); - test_cipher("ecb(khazad)", DECRYPT, khazad_dec_tv_template, - KHAZAD_DEC_TEST_VECTORS); + tcrypt_test("ecb(khazad)"); break; case 22: - test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS); + tcrypt_test("wp512"); break; case 23: - test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS); + tcrypt_test("wp384"); break; case 24: - test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS); + tcrypt_test("wp256"); break; case 25: - test_cipher("ecb(tnepres)", ENCRYPT, tnepres_enc_tv_template, - TNEPRES_ENC_TEST_VECTORS); - test_cipher("ecb(tnepres)", DECRYPT, tnepres_dec_tv_template, - TNEPRES_DEC_TEST_VECTORS); + tcrypt_test("ecb(tnepres)"); break; case 26: - test_cipher("ecb(anubis)", ENCRYPT, anubis_enc_tv_template, - ANUBIS_ENC_TEST_VECTORS); - test_cipher("ecb(anubis)", DECRYPT, anubis_dec_tv_template, - ANUBIS_DEC_TEST_VECTORS); - test_cipher("cbc(anubis)", ENCRYPT, anubis_cbc_enc_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(anubis)", DECRYPT, anubis_cbc_dec_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); + tcrypt_test("ecb(anubis)"); + tcrypt_test("cbc(anubis)"); break; case 27: - test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS); + tcrypt_test("tgr192"); break; case 28: - test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS); + tcrypt_test("tgr160"); break; case 29: - test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS); + tcrypt_test("tgr128"); break; case 30: - test_cipher("ecb(xeta)", ENCRYPT, xeta_enc_tv_template, - XETA_ENC_TEST_VECTORS); - test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template, - XETA_DEC_TEST_VECTORS); + tcrypt_test("ecb(xeta)"); break; case 31: - test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template, - FCRYPT_ENC_TEST_VECTORS); - test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template, - FCRYPT_DEC_TEST_VECTORS); + tcrypt_test("pcbc(fcrypt)"); break; case 32: - test_cipher("ecb(camellia)", ENCRYPT, - camellia_enc_tv_template, - CAMELLIA_ENC_TEST_VECTORS); - test_cipher("ecb(camellia)", DECRYPT, - camellia_dec_tv_template, - CAMELLIA_DEC_TEST_VECTORS); - test_cipher("cbc(camellia)", ENCRYPT, - camellia_cbc_enc_tv_template, - CAMELLIA_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(camellia)", DECRYPT, - camellia_cbc_dec_tv_template, - CAMELLIA_CBC_DEC_TEST_VECTORS); + tcrypt_test("ecb(camellia)"); + tcrypt_test("cbc(camellia)"); break; case 33: - test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS); + tcrypt_test("sha224"); break; case 34: - test_cipher("salsa20", ENCRYPT, - salsa20_stream_enc_tv_template, - SALSA20_STREAM_ENC_TEST_VECTORS); + tcrypt_test("salsa20"); break; case 35: - test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template, - AES_GCM_ENC_TEST_VECTORS); - test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template, - AES_GCM_DEC_TEST_VECTORS); + tcrypt_test("gcm(aes)"); break; case 36: - test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template, - LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS); + tcrypt_test("lzo"); break; case 37: - test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template, - AES_CCM_ENC_TEST_VECTORS); - test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template, - AES_CCM_DEC_TEST_VECTORS); + tcrypt_test("ccm(aes)"); break; case 38: - test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template, - CTS_MODE_ENC_TEST_VECTORS); - test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template, - CTS_MODE_DEC_TEST_VECTORS); + tcrypt_test("cts(cbc(aes))"); break; case 39: - test_hash("rmd128", rmd128_tv_template, RMD128_TEST_VECTORS); + tcrypt_test("rmd128"); break; case 40: - test_hash("rmd160", rmd160_tv_template, RMD160_TEST_VECTORS); + tcrypt_test("rmd160"); break; case 41: - test_hash("rmd256", rmd256_tv_template, RMD256_TEST_VECTORS); + tcrypt_test("rmd256"); break; case 42: - test_hash("rmd320", rmd320_tv_template, RMD320_TEST_VECTORS); + tcrypt_test("rmd320"); + break; + + case 43: + tcrypt_test("ecb(seed)"); break; case 100: - test_hash("hmac(md5)", hmac_md5_tv_template, - HMAC_MD5_TEST_VECTORS); + tcrypt_test("hmac(md5)"); break; case 101: - test_hash("hmac(sha1)", hmac_sha1_tv_template, - HMAC_SHA1_TEST_VECTORS); + tcrypt_test("hmac(sha1)"); break; case 102: - test_hash("hmac(sha256)", hmac_sha256_tv_template, - HMAC_SHA256_TEST_VECTORS); + tcrypt_test("hmac(sha256)"); break; case 103: - test_hash("hmac(sha384)", hmac_sha384_tv_template, - HMAC_SHA384_TEST_VECTORS); + tcrypt_test("hmac(sha384)"); break; case 104: - test_hash("hmac(sha512)", hmac_sha512_tv_template, - HMAC_SHA512_TEST_VECTORS); + tcrypt_test("hmac(sha512)"); break; case 105: - test_hash("hmac(sha224)", hmac_sha224_tv_template, - HMAC_SHA224_TEST_VECTORS); + tcrypt_test("hmac(sha224)"); break; case 106: - test_hash("xcbc(aes)", aes_xcbc128_tv_template, - XCBC_AES_TEST_VECTORS); + tcrypt_test("xcbc(aes)"); break; case 107: - test_hash("hmac(rmd128)", hmac_rmd128_tv_template, - HMAC_RMD128_TEST_VECTORS); + tcrypt_test("hmac(rmd128)"); break; case 108: - test_hash("hmac(rmd160)", hmac_rmd160_tv_template, - HMAC_RMD160_TEST_VECTORS); + tcrypt_test("hmac(rmd160)"); break; case 200: @@ -1767,16 +718,16 @@ static void do_test(void) case 201: test_cipher_speed("ecb(des3_ede)", ENCRYPT, sec, - des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS, + des3_speed_template, DES3_SPEED_VECTORS, speed_template_24); test_cipher_speed("ecb(des3_ede)", DECRYPT, sec, - des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS, + des3_speed_template, DES3_SPEED_VECTORS, speed_template_24); test_cipher_speed("cbc(des3_ede)", ENCRYPT, sec, - des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS, + des3_speed_template, DES3_SPEED_VECTORS, speed_template_24); test_cipher_speed("cbc(des3_ede)", DECRYPT, sec, - des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS, + des3_speed_template, DES3_SPEED_VECTORS, speed_template_24); break; @@ -1906,31 +857,21 @@ static void do_test(void) case 1000: test_available(); break; - - default: - /* useful for debugging */ - printk("not testing anything\n"); - break; } } static int __init tcrypt_mod_init(void) { int err = -ENOMEM; + int i; - tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); - if (tvmem == NULL) - return err; - - xbuf = kmalloc(XBUFSIZE, GFP_KERNEL); - if (xbuf == NULL) - goto err_free_tv; - - axbuf = kmalloc(XBUFSIZE, GFP_KERNEL); - if (axbuf == NULL) - goto err_free_xbuf; + for (i = 0; i < TVMEMSIZE; i++) { + tvmem[i] = (void *)__get_free_page(GFP_KERNEL); + if (!tvmem[i]) + goto err_free_tv; + } - do_test(); + do_test(mode); /* We intentionaly return -EAGAIN to prevent keeping * the module. It does all its work from init() @@ -1940,11 +881,9 @@ static int __init tcrypt_mod_init(void) */ err = -EAGAIN; - kfree(axbuf); - err_free_xbuf: - kfree(xbuf); - err_free_tv: - kfree(tvmem); +err_free_tv: + for (i = 0; i < TVMEMSIZE && tvmem[i]; i++) + free_page((unsigned long)tvmem[i]); return err; } diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index 801e0c288862..966bbfaf95b1 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h @@ -17,53 +17,9 @@ #ifndef _CRYPTO_TCRYPT_H #define _CRYPTO_TCRYPT_H -#define MAX_DIGEST_SIZE 64 -#define MAX_TAP 8 - -#define MAX_KEYLEN 56 -#define MAX_IVLEN 32 - -struct hash_testvec { - /* only used with keyed hash algorithms */ - char *key; - char *plaintext; - char *digest; - unsigned char tap[MAX_TAP]; - unsigned char psize; - unsigned char np; - unsigned char ksize; -}; - -struct cipher_testvec { - char *key; - char *iv; - char *input; - char *result; - unsigned char tap[MAX_TAP]; - int np; - unsigned char fail; - unsigned char wk; /* weak key flag */ - unsigned char klen; - unsigned short ilen; - unsigned short rlen; -}; - -struct aead_testvec { - char *key; - char *iv; - char *input; - char *assoc; - char *result; - unsigned char tap[MAX_TAP]; - unsigned char atap[MAX_TAP]; - int np; - int anp; - unsigned char fail; - unsigned char wk; /* weak key flag */ - unsigned char klen; - unsigned short ilen; - unsigned short alen; - unsigned short rlen; +struct cipher_speed_template { + const char *key; + unsigned int klen; }; struct hash_speed { @@ -71,8673 +27,20 @@ struct hash_speed { unsigned int plen; /* per-update length */ }; -static char zeroed_string[48]; - -/* - * MD4 test vectors from RFC1320 - */ -#define MD4_TEST_VECTORS 7 - -static struct hash_testvec md4_tv_template [] = { - { - .plaintext = "", - .digest = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31" - "\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0", - }, { - .plaintext = "a", - .psize = 1, - .digest = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46" - "\x24\x5e\x05\xfb\xdb\xd6\xfb\x24", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52" - "\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8" - "\x18\x87\x48\x06\xe1\xc7\x01\x4b", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd" - "\xee\xa8\xed\x63\xdf\x41\x2d\xa9", - .np = 2, - .tap = { 13, 13 }, - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\x04\x3f\x85\x82\xf2\x41\xdb\x35" - "\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4", - }, { - .plaintext = "123456789012345678901234567890123456789012345678901234567890123" - "45678901234567890", - .psize = 80, - .digest = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19" - "\x9c\x3e\x7b\x16\x4f\xcc\x05\x36", - }, -}; - -/* - * MD5 test vectors from RFC1321 - */ -#define MD5_TEST_VECTORS 7 - -static struct hash_testvec md5_tv_template[] = { - { - .digest = "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04" - "\xe9\x80\x09\x98\xec\xf8\x42\x7e", - }, { - .plaintext = "a", - .psize = 1, - .digest = "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8" - "\x31\xc3\x99\xe2\x69\x77\x26\x61", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0" - "\xd6\x96\x3f\x7d\x28\xe1\x7f\x72", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d" - "\x52\x5a\x2f\x31\xaa\xf1\x61\xd0", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00" - "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b", - .np = 2, - .tap = {13, 13} - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5" - "\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", - }, { - .plaintext = "12345678901234567890123456789012345678901234567890123456789012" - "345678901234567890", - .psize = 80, - .digest = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55" - "\xac\x49\xda\x2e\x21\x07\xb6\x7a", - } - -}; - -/* - * RIPEMD-128 test vectors from ISO/IEC 10118-3:2004(E) - */ -#define RMD128_TEST_VECTORS 10 - -static struct hash_testvec rmd128_tv_template[] = { - { - .digest = "\xcd\xf2\x62\x13\xa1\x50\xdc\x3e" - "\xcb\x61\x0f\x18\xf6\xb3\x8b\x46", - }, { - .plaintext = "a", - .psize = 1, - .digest = "\x86\xbe\x7a\xfa\x33\x9d\x0f\xc7" - "\xcf\xc7\x85\xe7\x2f\x57\x8d\x33", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\xc1\x4a\x12\x19\x9c\x66\xe4\xba" - "\x84\x63\x6b\x0f\x69\x14\x4c\x77", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\x9e\x32\x7b\x3d\x6e\x52\x30\x62" - "\xaf\xc1\x13\x2d\x7d\xf9\xd1\xb8", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xfd\x2a\xa6\x07\xf7\x1d\xc8\xf5" - "\x10\x71\x49\x22\xb3\x71\x83\x4e", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" - "fghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\xd1\xe9\x59\xeb\x17\x9c\x91\x1f" - "\xae\xa4\x62\x4c\x60\xc5\xc7\x02", - }, { - .plaintext = "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", - .psize = 80, - .digest = "\x3f\x45\xef\x19\x47\x32\xc2\xdb" - "\xb2\xc4\xa2\xc7\x69\x79\x5f\xa3", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighij" - "hijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\xa1\xaa\x06\x89\xd0\xfa\xfa\x2d" - "\xdc\x22\xe8\x8b\x49\x13\x3a\x06", - .np = 2, - .tap = { 28, 28 }, - }, { - .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghi" - "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqr" - "lmnopqrsmnopqrstnopqrstu", - .psize = 112, - .digest = "\xd4\xec\xc9\x13\xe1\xdf\x77\x6b" - "\xf4\x8d\xe9\xd5\x5b\x1f\x25\x46", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijk", - .psize = 32, - .digest = "\x13\xfc\x13\xe8\xef\xff\x34\x7d" - "\xe1\x93\xff\x46\xdb\xac\xcf\xd4", - } -}; - -/* - * RIPEMD-160 test vectors from ISO/IEC 10118-3:2004(E) - */ -#define RMD160_TEST_VECTORS 10 - -static struct hash_testvec rmd160_tv_template[] = { - { - .digest = "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28" - "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31", - }, { - .plaintext = "a", - .psize = 1, - .digest = "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae" - "\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04" - "\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8" - "\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xf7\x1c\x27\x10\x9c\x69\x2c\x1b\x56\xbb" - "\xdc\xeb\x5b\x9d\x28\x65\xb3\x70\x8d\xbc", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" - "fghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\xb0\xe2\x0b\x6e\x31\x16\x64\x02\x86\xed" - "\x3a\x87\xa5\x71\x30\x79\xb2\x1f\x51\x89", - }, { - .plaintext = "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", - .psize = 80, - .digest = "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb" - "\xd3\x32\x3c\xab\x82\xbf\x63\x32\x6b\xfb", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighij" - "hijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05" - "\xa0\x6c\x27\xdc\xf4\x9a\xda\x62\xeb\x2b", - .np = 2, - .tap = { 28, 28 }, - }, { - .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghi" - "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqr" - "lmnopqrsmnopqrstnopqrstu", - .psize = 112, - .digest = "\x6f\x3f\xa3\x9b\x6b\x50\x3c\x38\x4f\x91" - "\x9a\x49\xa7\xaa\x5c\x2c\x08\xbd\xfb\x45", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijk", - .psize = 32, - .digest = "\x94\xc2\x64\x11\x54\x04\xe6\x33\x79\x0d" - "\xfc\xc8\x7b\x58\x7d\x36\x77\x06\x7d\x9f", - } -}; - -/* - * RIPEMD-256 test vectors - */ -#define RMD256_TEST_VECTORS 8 - -static struct hash_testvec rmd256_tv_template[] = { - { - .digest = "\x02\xba\x4c\x4e\x5f\x8e\xcd\x18" - "\x77\xfc\x52\xd6\x4d\x30\xe3\x7a" - "\x2d\x97\x74\xfb\x1e\x5d\x02\x63" - "\x80\xae\x01\x68\xe3\xc5\x52\x2d", - }, { - .plaintext = "a", - .psize = 1, - .digest = "\xf9\x33\x3e\x45\xd8\x57\xf5\xd9" - "\x0a\x91\xba\xb7\x0a\x1e\xba\x0c" - "\xfb\x1b\xe4\xb0\x78\x3c\x9a\xcf" - "\xcd\x88\x3a\x91\x34\x69\x29\x25", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\xaf\xbd\x6e\x22\x8b\x9d\x8c\xbb" - "\xce\xf5\xca\x2d\x03\xe6\xdb\xa1" - "\x0a\xc0\xbc\x7d\xcb\xe4\x68\x0e" - "\x1e\x42\xd2\xe9\x75\x45\x9b\x65", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\x87\xe9\x71\x75\x9a\x1c\xe4\x7a" - "\x51\x4d\x5c\x91\x4c\x39\x2c\x90" - "\x18\xc7\xc4\x6b\xc1\x44\x65\x55" - "\x4a\xfc\xdf\x54\xa5\x07\x0c\x0e", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\x64\x9d\x30\x34\x75\x1e\xa2\x16" - "\x77\x6b\xf9\xa1\x8a\xcc\x81\xbc" - "\x78\x96\x11\x8a\x51\x97\x96\x87" - "\x82\xdd\x1f\xd9\x7d\x8d\x51\x33", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" - "fghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\x57\x40\xa4\x08\xac\x16\xb7\x20" - "\xb8\x44\x24\xae\x93\x1c\xbb\x1f" - "\xe3\x63\xd1\xd0\xbf\x40\x17\xf1" - "\xa8\x9f\x7e\xa6\xde\x77\xa0\xb8", - }, { - .plaintext = "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", - .psize = 80, - .digest = "\x06\xfd\xcc\x7a\x40\x95\x48\xaa" - "\xf9\x13\x68\xc0\x6a\x62\x75\xb5" - "\x53\xe3\xf0\x99\xbf\x0e\xa4\xed" - "\xfd\x67\x78\xdf\x89\xa8\x90\xdd", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighij" - "hijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x38\x43\x04\x55\x83\xaa\xc6\xc8" - "\xc8\xd9\x12\x85\x73\xe7\xa9\x80" - "\x9a\xfb\x2a\x0f\x34\xcc\xc3\x6e" - "\xa9\xe7\x2f\x16\xf6\x36\x8e\x3f", - .np = 2, - .tap = { 28, 28 }, - } -}; - -/* - * RIPEMD-320 test vectors - */ -#define RMD320_TEST_VECTORS 8 - -static struct hash_testvec rmd320_tv_template[] = { - { - .digest = "\x22\xd6\x5d\x56\x61\x53\x6c\xdc\x75\xc1" - "\xfd\xf5\xc6\xde\x7b\x41\xb9\xf2\x73\x25" - "\xeb\xc6\x1e\x85\x57\x17\x7d\x70\x5a\x0e" - "\xc8\x80\x15\x1c\x3a\x32\xa0\x08\x99\xb8", - }, { - .plaintext = "a", - .psize = 1, - .digest = "\xce\x78\x85\x06\x38\xf9\x26\x58\xa5\xa5" - "\x85\x09\x75\x79\x92\x6d\xda\x66\x7a\x57" - "\x16\x56\x2c\xfc\xf6\xfb\xe7\x7f\x63\x54" - "\x2f\x99\xb0\x47\x05\xd6\x97\x0d\xff\x5d", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\xde\x4c\x01\xb3\x05\x4f\x89\x30\xa7\x9d" - "\x09\xae\x73\x8e\x92\x30\x1e\x5a\x17\x08" - "\x5b\xef\xfd\xc1\xb8\xd1\x16\x71\x3e\x74" - "\xf8\x2f\xa9\x42\xd6\x4c\xdb\xc4\x68\x2d", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\x3a\x8e\x28\x50\x2e\xd4\x5d\x42\x2f\x68" - "\x84\x4f\x9d\xd3\x16\xe7\xb9\x85\x33\xfa" - "\x3f\x2a\x91\xd2\x9f\x84\xd4\x25\xc8\x8d" - "\x6b\x4e\xff\x72\x7d\xf6\x6a\x7c\x01\x97", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xca\xbd\xb1\x81\x0b\x92\x47\x0a\x20\x93" - "\xaa\x6b\xce\x05\x95\x2c\x28\x34\x8c\xf4" - "\x3f\xf6\x08\x41\x97\x51\x66\xbb\x40\xed" - "\x23\x40\x04\xb8\x82\x44\x63\xe6\xb0\x09", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" - "fghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\xed\x54\x49\x40\xc8\x6d\x67\xf2\x50\xd2" - "\x32\xc3\x0b\x7b\x3e\x57\x70\xe0\xc6\x0c" - "\x8c\xb9\xa4\xca\xfe\x3b\x11\x38\x8a\xf9" - "\x92\x0e\x1b\x99\x23\x0b\x84\x3c\x86\xa4", - }, { - .plaintext = "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", - .psize = 80, - .digest = "\x55\x78\x88\xaf\x5f\x6d\x8e\xd6\x2a\xb6" - "\x69\x45\xc6\xd2\xa0\xa4\x7e\xcd\x53\x41" - "\xe9\x15\xeb\x8f\xea\x1d\x05\x24\x95\x5f" - "\x82\x5d\xc7\x17\xe4\xa0\x08\xab\x2d\x42", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighij" - "hijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\xd0\x34\xa7\x95\x0c\xf7\x22\x02\x1b\xa4" - "\xb8\x4d\xf7\x69\xa5\xde\x20\x60\xe2\x59" - "\xdf\x4c\x9b\xb4\xa4\x26\x8c\x0e\x93\x5b" - "\xbc\x74\x70\xa9\x69\xc9\xd0\x72\xa1\xac", - .np = 2, - .tap = { 28, 28 }, - } -}; - -/* - * SHA1 test vectors from from FIPS PUB 180-1 - */ -#define SHA1_TEST_VECTORS 2 - -static struct hash_testvec sha1_tv_template[] = { - { - .plaintext = "abc", - .psize = 3, - .digest = "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e" - "\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae" - "\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1", - .np = 2, - .tap = { 28, 28 } - } -}; - - -/* - * SHA224 test vectors from from FIPS PUB 180-2 - */ -#define SHA224_TEST_VECTORS 2 - -static struct hash_testvec sha224_tv_template[] = { - { - .plaintext = "abc", - .psize = 3, - .digest = "\x23\x09\x7D\x22\x34\x05\xD8\x22" - "\x86\x42\xA4\x77\xBD\xA2\x55\xB3" - "\x2A\xAD\xBC\xE4\xBD\xA0\xB3\xF7" - "\xE3\x6C\x9D\xA7", - }, { - .plaintext = - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x75\x38\x8B\x16\x51\x27\x76\xCC" - "\x5D\xBA\x5D\xA1\xFD\x89\x01\x50" - "\xB0\xC6\x45\x5C\xB4\xF5\x8B\x19" - "\x52\x52\x25\x25", - .np = 2, - .tap = { 28, 28 } - } -}; - -/* - * SHA256 test vectors from from NIST - */ -#define SHA256_TEST_VECTORS 2 - -static struct hash_testvec sha256_tv_template[] = { - { - .plaintext = "abc", - .psize = 3, - .digest = "\xba\x78\x16\xbf\x8f\x01\xcf\xea" - "\x41\x41\x40\xde\x5d\xae\x22\x23" - "\xb0\x03\x61\xa3\x96\x17\x7a\x9c" - "\xb4\x10\xff\x61\xf2\x00\x15\xad", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x24\x8d\x6a\x61\xd2\x06\x38\xb8" - "\xe5\xc0\x26\x93\x0c\x3e\x60\x39" - "\xa3\x3c\xe4\x59\x64\xff\x21\x67" - "\xf6\xec\xed\xd4\x19\xdb\x06\xc1", - .np = 2, - .tap = { 28, 28 } - }, -}; - -/* - * SHA384 test vectors from from NIST and kerneli - */ -#define SHA384_TEST_VECTORS 4 - -static struct hash_testvec sha384_tv_template[] = { - { - .plaintext= "abc", - .psize = 3, - .digest = "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b" - "\xb5\xa0\x3d\x69\x9a\xc6\x50\x07" - "\x27\x2c\x32\xab\x0e\xde\xd1\x63" - "\x1a\x8b\x60\x5a\x43\xff\x5b\xed" - "\x80\x86\x07\x2b\xa1\xe7\xcc\x23" - "\x58\xba\xec\xa1\x34\xc8\x25\xa7", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x33\x91\xfd\xdd\xfc\x8d\xc7\x39" - "\x37\x07\xa6\x5b\x1b\x47\x09\x39" - "\x7c\xf8\xb1\xd1\x62\xaf\x05\xab" - "\xfe\x8f\x45\x0d\xe5\xf3\x6b\xc6" - "\xb0\x45\x5a\x85\x20\xbc\x4e\x6f" - "\x5f\xe9\x5b\x1f\xe3\xc8\x45\x2b", - }, { - .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - .psize = 112, - .digest = "\x09\x33\x0c\x33\xf7\x11\x47\xe8" - "\x3d\x19\x2f\xc7\x82\xcd\x1b\x47" - "\x53\x11\x1b\x17\x3b\x3b\x05\xd2" - "\x2f\xa0\x80\x86\xe3\xb0\xf7\x12" - "\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9" - "\x66\xc3\xe9\xfa\x91\x74\x60\x39", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" - "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", - .psize = 104, - .digest = "\x3d\x20\x89\x73\xab\x35\x08\xdb" - "\xbd\x7e\x2c\x28\x62\xba\x29\x0a" - "\xd3\x01\x0e\x49\x78\xc1\x98\xdc" - "\x4d\x8f\xd0\x14\xe5\x82\x82\x3a" - "\x89\xe1\x6f\x9b\x2a\x7b\xbc\x1a" - "\xc9\x38\xe2\xd1\x99\xe8\xbe\xa4", - .np = 4, - .tap = { 26, 26, 26, 26 } - }, -}; - -/* - * SHA512 test vectors from from NIST and kerneli - */ -#define SHA512_TEST_VECTORS 4 - -static struct hash_testvec sha512_tv_template[] = { - { - .plaintext = "abc", - .psize = 3, - .digest = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba" - "\xcc\x41\x73\x49\xae\x20\x41\x31" - "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2" - "\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a" - "\x21\x92\x99\x2a\x27\x4f\xc1\xa8" - "\x36\xba\x3c\x23\xa3\xfe\xeb\xbd" - "\x45\x4d\x44\x23\x64\x3c\xe8\x0e" - "\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a" - "\x0c\xed\x7b\xeb\x8e\x08\xa4\x16" - "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8" - "\x27\x9b\xe3\x31\xa7\x03\xc3\x35" - "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9" - "\xaa\x1d\x3b\xea\x57\x78\x9c\xa0" - "\x31\xad\x85\xc7\xa7\x1d\xd7\x03" - "\x54\xec\x63\x12\x38\xca\x34\x45", - }, { - .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - .psize = 112, - .digest = "\x8e\x95\x9b\x75\xda\xe3\x13\xda" - "\x8c\xf4\xf7\x28\x14\xfc\x14\x3f" - "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1" - "\x72\x99\xae\xad\xb6\x88\x90\x18" - "\x50\x1d\x28\x9e\x49\x00\xf7\xe4" - "\x33\x1b\x99\xde\xc4\xb5\x43\x3a" - "\xc7\xd3\x29\xee\xb6\xdd\x26\x54" - "\x5e\x96\xe5\x5b\x87\x4b\xe9\x09", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" - "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", - .psize = 104, - .digest = "\x93\x0d\x0c\xef\xcb\x30\xff\x11" - "\x33\xb6\x89\x81\x21\xf1\xcf\x3d" - "\x27\x57\x8a\xfc\xaf\xe8\x67\x7c" - "\x52\x57\xcf\x06\x99\x11\xf7\x5d" - "\x8f\x58\x31\xb5\x6e\xbf\xda\x67" - "\xb2\x78\xe6\x6d\xff\x8b\x84\xfe" - "\x2b\x28\x70\xf7\x42\xa5\x80\xd8" - "\xed\xb4\x19\x87\x23\x28\x50\xc9", - .np = 4, - .tap = { 26, 26, 26, 26 } - }, -}; - - -/* - * WHIRLPOOL test vectors from Whirlpool package - * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE - * submission - */ -#define WP512_TEST_VECTORS 8 - -static struct hash_testvec wp512_tv_template[] = { - { - .plaintext = "", - .psize = 0, - .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66" - "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26" - "\xC5\x30\x23\x21\x30\xD4\x07\xF8" - "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7" - "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB" - "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57" - "\xEA\x89\x64\xE5\x9B\x63\xD9\x37" - "\x08\xB1\x38\xCC\x42\xA6\x6E\xB3", - - - }, { - .plaintext = "a", - .psize = 1, - .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F" - "\x11\xA6\x72\x06\x53\x1F\xB7\xD7" - "\xF0\xDF\xF5\x94\x13\x14\x5E\x69" - "\x73\xC4\x50\x01\xD0\x08\x7B\x42" - "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6" - "\x3A\x42\x39\x1A\x39\x14\x5A\x59" - "\x1A\x92\x20\x0D\x56\x01\x95\xE5" - "\x3B\x47\x85\x84\xFD\xAE\x23\x1A", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB" - "\x16\xB6\x56\x2C\x73\xB4\x02\x0B" - "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72" - "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C" - "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27" - "\x7D\x0E\x34\x95\x71\x14\xCB\xD6" - "\xC7\x97\xFC\x9D\x95\xD8\xB5\x82" - "\xD2\x25\x29\x20\x76\xD4\xEE\xF5", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6" - "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC" - "\x83\x8D\x00\x03\x22\x30\xF5\x3C" - "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B" - "\x84\x21\x55\x76\x59\xEF\x55\xC1" - "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6" - "\x92\xED\x92\x00\x52\x83\x8F\x33" - "\x62\xE8\x6D\xBD\x37\xA8\x90\x3E", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9" - "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A" - "\x8D\x38\x63\x1E\xAD\x42\x38\xF5" - "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B" - "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A" - "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6" - "\xF6\x8F\x67\x3E\x72\x07\x86\x5D" - "\x5D\x98\x19\xA3\xDB\xA4\xEB\x3B", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B" - "\xF1\x1F\x00\xED\x9A\xBA\x26\x90" - "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC" - "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E" - "\x08\xEB\xA2\x66\x29\x12\x9D\x8F" - "\xB7\xCB\x57\x21\x1B\x92\x81\xA6" - "\x55\x17\xCC\x87\x9D\x7B\x96\x21" - "\x42\xC6\x5F\x5A\x7A\xF0\x14\x67", - }, { - .plaintext = "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", - .psize = 80, - .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D" - "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0" - "\x87\x84\x37\x2B\xCC\xB2\x04\xD6" - "\x54\x9C\x4A\xFA\xDB\x60\x14\x29" - "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5" - "\x38\xCD\x04\x7B\x26\x81\xA5\x1A" - "\x2C\x60\x48\x1E\x88\xC5\xA2\x0B" - "\x2C\x2A\x80\xCF\x3A\x9A\x08\x3B", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijk", - .psize = 32, - .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61" - "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48" - "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62" - "\x07\xC5\x62\xF9\x88\xE9\x5C\x69" - "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B" - "\x7B\x94\x76\x39\xFE\x05\x0B\x56" - "\x93\x9B\xAA\xA0\xAD\xFF\x9A\xE6" - "\x74\x5B\x7B\x18\x1C\x3B\xE3\xFD", - }, -}; - -#define WP384_TEST_VECTORS 8 - -static struct hash_testvec wp384_tv_template[] = { - { - .plaintext = "", - .psize = 0, - .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66" - "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26" - "\xC5\x30\x23\x21\x30\xD4\x07\xF8" - "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7" - "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB" - "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57", - - - }, { - .plaintext = "a", - .psize = 1, - .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F" - "\x11\xA6\x72\x06\x53\x1F\xB7\xD7" - "\xF0\xDF\xF5\x94\x13\x14\x5E\x69" - "\x73\xC4\x50\x01\xD0\x08\x7B\x42" - "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6" - "\x3A\x42\x39\x1A\x39\x14\x5A\x59", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB" - "\x16\xB6\x56\x2C\x73\xB4\x02\x0B" - "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72" - "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C" - "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27" - "\x7D\x0E\x34\x95\x71\x14\xCB\xD6", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6" - "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC" - "\x83\x8D\x00\x03\x22\x30\xF5\x3C" - "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B" - "\x84\x21\x55\x76\x59\xEF\x55\xC1" - "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9" - "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A" - "\x8D\x38\x63\x1E\xAD\x42\x38\xF5" - "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B" - "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A" - "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B" - "\xF1\x1F\x00\xED\x9A\xBA\x26\x90" - "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC" - "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E" - "\x08\xEB\xA2\x66\x29\x12\x9D\x8F" - "\xB7\xCB\x57\x21\x1B\x92\x81\xA6", - }, { - .plaintext = "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", - .psize = 80, - .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D" - "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0" - "\x87\x84\x37\x2B\xCC\xB2\x04\xD6" - "\x54\x9C\x4A\xFA\xDB\x60\x14\x29" - "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5" - "\x38\xCD\x04\x7B\x26\x81\xA5\x1A", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijk", - .psize = 32, - .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61" - "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48" - "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62" - "\x07\xC5\x62\xF9\x88\xE9\x5C\x69" - "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B" - "\x7B\x94\x76\x39\xFE\x05\x0B\x56", - }, -}; - -#define WP256_TEST_VECTORS 8 - -static struct hash_testvec wp256_tv_template[] = { - { - .plaintext = "", - .psize = 0, - .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66" - "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26" - "\xC5\x30\x23\x21\x30\xD4\x07\xF8" - "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7", - - - }, { - .plaintext = "a", - .psize = 1, - .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F" - "\x11\xA6\x72\x06\x53\x1F\xB7\xD7" - "\xF0\xDF\xF5\x94\x13\x14\x5E\x69" - "\x73\xC4\x50\x01\xD0\x08\x7B\x42", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB" - "\x16\xB6\x56\x2C\x73\xB4\x02\x0B" - "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72" - "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C", - }, { - .plaintext = "message digest", - .psize = 14, - .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6" - "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC" - "\x83\x8D\x00\x03\x22\x30\xF5\x3C" - "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B", - }, { - .plaintext = "abcdefghijklmnopqrstuvwxyz", - .psize = 26, - .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9" - "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A" - "\x8D\x38\x63\x1E\xAD\x42\x38\xF5" - "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789", - .psize = 62, - .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B" - "\xF1\x1F\x00\xED\x9A\xBA\x26\x90" - "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC" - "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E", - }, { - .plaintext = "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", - .psize = 80, - .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D" - "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0" - "\x87\x84\x37\x2B\xCC\xB2\x04\xD6" - "\x54\x9C\x4A\xFA\xDB\x60\x14\x29", - }, { - .plaintext = "abcdbcdecdefdefgefghfghighijhijk", - .psize = 32, - .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61" - "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48" - "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62" - "\x07\xC5\x62\xF9\x88\xE9\x5C\x69", - }, -}; - -/* - * TIGER test vectors from Tiger website - */ -#define TGR192_TEST_VECTORS 6 - -static struct hash_testvec tgr192_tv_template[] = { - { - .plaintext = "", - .psize = 0, - .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32" - "\x16\x16\x6e\x76\xb1\xbb\x92\x5f" - "\xf3\x73\xde\x2d\x49\x58\x4e\x7a", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a" - "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf" - "\x93\x5f\x7b\x95\x1c\x13\x29\x51", - }, { - .plaintext = "Tiger", - .psize = 5, - .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd" - "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec" - "\x37\x79\x0c\x11\x6f\x9d\x2b\xdf", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - .psize = 64, - .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7" - "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e" - "\xb5\x86\x44\x50\x34\xa5\xa3\x86", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", - .psize = 64, - .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48" - "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9" - "\x57\x89\x65\x65\x97\x5f\x91\x97", - }, { - .plaintext = "Tiger - A Fast New Hash Function, " - "by Ross Anderson and Eli Biham, " - "proceedings of Fast Software Encryption 3, " - "Cambridge, 1996.", - .psize = 125, - .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63" - "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24" - "\xdd\x68\x15\x1d\x50\x39\x74\xfc", - }, -}; - -#define TGR160_TEST_VECTORS 6 - -static struct hash_testvec tgr160_tv_template[] = { - { - .plaintext = "", - .psize = 0, - .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32" - "\x16\x16\x6e\x76\xb1\xbb\x92\x5f" - "\xf3\x73\xde\x2d", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a" - "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf" - "\x93\x5f\x7b\x95", - }, { - .plaintext = "Tiger", - .psize = 5, - .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd" - "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec" - "\x37\x79\x0c\x11", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - .psize = 64, - .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7" - "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e" - "\xb5\x86\x44\x50", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", - .psize = 64, - .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48" - "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9" - "\x57\x89\x65\x65", - }, { - .plaintext = "Tiger - A Fast New Hash Function, " - "by Ross Anderson and Eli Biham, " - "proceedings of Fast Software Encryption 3, " - "Cambridge, 1996.", - .psize = 125, - .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63" - "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24" - "\xdd\x68\x15\x1d", - }, -}; - -#define TGR128_TEST_VECTORS 6 - -static struct hash_testvec tgr128_tv_template[] = { - { - .plaintext = "", - .psize = 0, - .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32" - "\x16\x16\x6e\x76\xb1\xbb\x92\x5f", - }, { - .plaintext = "abc", - .psize = 3, - .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a" - "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf", - }, { - .plaintext = "Tiger", - .psize = 5, - .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd" - "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - .psize = 64, - .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7" - "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e", - }, { - .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", - .psize = 64, - .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48" - "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9", - }, { - .plaintext = "Tiger - A Fast New Hash Function, " - "by Ross Anderson and Eli Biham, " - "proceedings of Fast Software Encryption 3, " - "Cambridge, 1996.", - .psize = 125, - .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63" - "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24", - }, -}; - -/* - * HMAC-MD5 test vectors from RFC2202 - * (These need to be fixed to not use strlen). - */ -#define HMAC_MD5_TEST_VECTORS 7 - -static struct hash_testvec hmac_md5_tv_template[] = -{ - { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - .ksize = 16, - .plaintext = "Hi There", - .psize = 8, - .digest = "\x92\x94\x72\x7a\x36\x38\xbb\x1c" - "\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d", - }, { - .key = "Jefe", - .ksize = 4, - .plaintext = "what do ya want for nothing?", - .psize = 28, - .digest = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03" - "\xea\xa8\x6e\x31\x0a\x5d\xb7\x38", - .np = 2, - .tap = {14, 14} - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - .ksize = 16, - .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - .psize = 50, - .digest = "\x56\xbe\x34\x52\x1d\x14\x4c\x88" - "\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6", - }, { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19", - .ksize = 25, - .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - .psize = 50, - .digest = "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea" - "\x3a\x75\x16\x47\x46\xff\xaa\x79", - }, { - .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", - .ksize = 16, - .plaintext = "Test With Truncation", - .psize = 20, - .digest = "\x56\x46\x1e\xf2\x34\x2e\xdc\x00" - "\xf9\xba\xb9\x95\x69\x0e\xfd\x4c", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", - .psize = 54, - .digest = "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f" - "\x0b\x62\xe6\xce\x61\xb9\xd0\xcd", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " - "Block-Size Data", - .psize = 73, - .digest = "\x6f\x63\x0f\xad\x67\xcd\xa0\xee" - "\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", - }, -}; - -/* - * HMAC-RIPEMD128 test vectors from RFC2286 - */ -#define HMAC_RMD128_TEST_VECTORS 7 - -static struct hash_testvec hmac_rmd128_tv_template[] = { - { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - .ksize = 16, - .plaintext = "Hi There", - .psize = 8, - .digest = "\xfb\xf6\x1f\x94\x92\xaa\x4b\xbf" - "\x81\xc1\x72\xe8\x4e\x07\x34\xdb", - }, { - .key = "Jefe", - .ksize = 4, - .plaintext = "what do ya want for nothing?", - .psize = 28, - .digest = "\x87\x5f\x82\x88\x62\xb6\xb3\x34" - "\xb4\x27\xc5\x5f\x9f\x7f\xf0\x9b", - .np = 2, - .tap = { 14, 14 }, - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - .ksize = 16, - .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - .psize = 50, - .digest = "\x09\xf0\xb2\x84\x6d\x2f\x54\x3d" - "\xa3\x63\xcb\xec\x8d\x62\xa3\x8d", - }, { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19", - .ksize = 25, - .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - .psize = 50, - .digest = "\xbd\xbb\xd7\xcf\x03\xe4\x4b\x5a" - "\xa6\x0a\xf8\x15\xbe\x4d\x22\x94", - }, { - .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", - .ksize = 16, - .plaintext = "Test With Truncation", - .psize = 20, - .digest = "\xe7\x98\x08\xf2\x4b\x25\xfd\x03" - "\x1c\x15\x5f\x0d\x55\x1d\x9a\x3a", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", - .psize = 54, - .digest = "\xdc\x73\x29\x28\xde\x98\x10\x4a" - "\x1f\x59\xd3\x73\xc1\x50\xac\xbb", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " - "Block-Size Data", - .psize = 73, - .digest = "\x5c\x6b\xec\x96\x79\x3e\x16\xd4" - "\x06\x90\xc2\x37\x63\x5f\x30\xc5", - }, -}; - -/* - * HMAC-RIPEMD160 test vectors from RFC2286 - */ -#define HMAC_RMD160_TEST_VECTORS 7 - -static struct hash_testvec hmac_rmd160_tv_template[] = { - { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - .ksize = 20, - .plaintext = "Hi There", - .psize = 8, - .digest = "\x24\xcb\x4b\xd6\x7d\x20\xfc\x1a\x5d\x2e" - "\xd7\x73\x2d\xcc\x39\x37\x7f\x0a\x56\x68", - }, { - .key = "Jefe", - .ksize = 4, - .plaintext = "what do ya want for nothing?", - .psize = 28, - .digest = "\xdd\xa6\xc0\x21\x3a\x48\x5a\x9e\x24\xf4" - "\x74\x20\x64\xa7\xf0\x33\xb4\x3c\x40\x69", - .np = 2, - .tap = { 14, 14 }, - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - .ksize = 20, - .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - .psize = 50, - .digest = "\xb0\xb1\x05\x36\x0d\xe7\x59\x96\x0a\xb4" - "\xf3\x52\x98\xe1\x16\xe2\x95\xd8\xe7\xc1", - }, { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19", - .ksize = 25, - .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - .psize = 50, - .digest = "\xd5\xca\x86\x2f\x4d\x21\xd5\xe6\x10\xe1" - "\x8b\x4c\xf1\xbe\xb9\x7a\x43\x65\xec\xf4", - }, { - .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", - .ksize = 20, - .plaintext = "Test With Truncation", - .psize = 20, - .digest = "\x76\x19\x69\x39\x78\xf9\x1d\x90\x53\x9a" - "\xe7\x86\x50\x0f\xf3\xd8\xe0\x51\x8e\x39", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", - .psize = 54, - .digest = "\x64\x66\xca\x07\xac\x5e\xac\x29\xe1\xbd" - "\x52\x3e\x5a\xda\x76\x05\xb7\x91\xfd\x8b", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " - "Block-Size Data", - .psize = 73, - .digest = "\x69\xea\x60\x79\x8d\x71\x61\x6c\xce\x5f" - "\xd0\x87\x1e\x23\x75\x4c\xd7\x5d\x5a\x0a", - }, -}; - -/* - * HMAC-SHA1 test vectors from RFC2202 - */ -#define HMAC_SHA1_TEST_VECTORS 7 - -static struct hash_testvec hmac_sha1_tv_template[] = { - { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - .ksize = 20, - .plaintext = "Hi There", - .psize = 8, - .digest = "\xb6\x17\x31\x86\x55\x05\x72\x64" - "\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1" - "\x46\xbe", - }, { - .key = "Jefe", - .ksize = 4, - .plaintext = "what do ya want for nothing?", - .psize = 28, - .digest = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74" - "\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79", - .np = 2, - .tap = { 14, 14 } - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - .ksize = 20, - .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - .psize = 50, - .digest = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3" - "\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3", - }, { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19", - .ksize = 25, - .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - .psize = 50, - .digest = "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84" - "\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda", - }, { - .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", - .ksize = 20, - .plaintext = "Test With Truncation", - .psize = 20, - .digest = "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2" - "\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", - .psize = 54, - .digest = "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70" - "\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " - "Block-Size Data", - .psize = 73, - .digest = "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b" - "\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91", - }, -}; - - -/* - * SHA224 HMAC test vectors from RFC4231 - */ -#define HMAC_SHA224_TEST_VECTORS 4 - -static struct hash_testvec hmac_sha224_tv_template[] = { - { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b", - .ksize = 20, - /* ("Hi There") */ - .plaintext = "\x48\x69\x20\x54\x68\x65\x72\x65", - .psize = 8, - .digest = "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19" - "\x68\x32\x10\x7c\xd4\x9d\xf3\x3f" - "\x47\xb4\xb1\x16\x99\x12\xba\x4f" - "\x53\x68\x4b\x22", - }, { - .key = "Jefe", - .ksize = 4, - /* ("what do ya want for nothing?") */ - .plaintext = "\x77\x68\x61\x74\x20\x64\x6f\x20" - "\x79\x61\x20\x77\x61\x6e\x74\x20" - "\x66\x6f\x72\x20\x6e\x6f\x74\x68" - "\x69\x6e\x67\x3f", - .psize = 28, - .digest = "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf" - "\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" - "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00" - "\x8f\xd0\x5e\x44", - .np = 4, - .tap = { 7, 7, 7, 7 } - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa", - .ksize = 131, - /* ("Test Using Larger Than Block-Size Key - Hash Key First") */ - .plaintext = "\x54\x65\x73\x74\x20\x55\x73\x69" - "\x6e\x67\x20\x4c\x61\x72\x67\x65" - "\x72\x20\x54\x68\x61\x6e\x20\x42" - "\x6c\x6f\x63\x6b\x2d\x53\x69\x7a" - "\x65\x20\x4b\x65\x79\x20\x2d\x20" - "\x48\x61\x73\x68\x20\x4b\x65\x79" - "\x20\x46\x69\x72\x73\x74", - .psize = 54, - .digest = "\x95\xe9\xa0\xdb\x96\x20\x95\xad" - "\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2" - "\xd4\x99\xf1\x12\xf2\xd2\xb7\x27" - "\x3f\xa6\x87\x0e", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa", - .ksize = 131, - /* ("This is a test using a larger than block-size key and a") - (" larger than block-size data. The key needs to be") - (" hashed before being used by the HMAC algorithm.") */ - .plaintext = "\x54\x68\x69\x73\x20\x69\x73\x20" - "\x61\x20\x74\x65\x73\x74\x20\x75" - "\x73\x69\x6e\x67\x20\x61\x20\x6c" - "\x61\x72\x67\x65\x72\x20\x74\x68" - "\x61\x6e\x20\x62\x6c\x6f\x63\x6b" - "\x2d\x73\x69\x7a\x65\x20\x6b\x65" - "\x79\x20\x61\x6e\x64\x20\x61\x20" - "\x6c\x61\x72\x67\x65\x72\x20\x74" - "\x68\x61\x6e\x20\x62\x6c\x6f\x63" - "\x6b\x2d\x73\x69\x7a\x65\x20\x64" - "\x61\x74\x61\x2e\x20\x54\x68\x65" - "\x20\x6b\x65\x79\x20\x6e\x65\x65" - "\x64\x73\x20\x74\x6f\x20\x62\x65" - "\x20\x68\x61\x73\x68\x65\x64\x20" - "\x62\x65\x66\x6f\x72\x65\x20\x62" - "\x65\x69\x6e\x67\x20\x75\x73\x65" - "\x64\x20\x62\x79\x20\x74\x68\x65" - "\x20\x48\x4d\x41\x43\x20\x61\x6c" - "\x67\x6f\x72\x69\x74\x68\x6d\x2e", - .psize = 152, - .digest = "\x3a\x85\x41\x66\xac\x5d\x9f\x02" - "\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd" - "\x94\x67\x70\xdb\x9c\x2b\x95\xc9" - "\xf6\xf5\x65\xd1", - }, -}; - -/* - * HMAC-SHA256 test vectors from - * draft-ietf-ipsec-ciph-sha-256-01.txt - */ -#define HMAC_SHA256_TEST_VECTORS 10 - -static struct hash_testvec hmac_sha256_tv_template[] = { - { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18" - "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", - .ksize = 32, - .plaintext = "abc", - .psize = 3, - .digest = "\xa2\x1b\x1f\x5d\x4c\xf4\xf7\x3a" - "\x4d\xd9\x39\x75\x0f\x7a\x06\x6a" - "\x7f\x98\xcc\x13\x1c\xb1\x6a\x66" - "\x92\x75\x90\x21\xcf\xab\x81\x81", - }, { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18" - "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", - .ksize = 32, - .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - .psize = 56, - .digest = "\x10\x4f\xdc\x12\x57\x32\x8f\x08" - "\x18\x4b\xa7\x31\x31\xc5\x3c\xae" - "\xe6\x98\xe3\x61\x19\x42\x11\x49" - "\xea\x8c\x71\x24\x56\x69\x7d\x30", - }, { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18" - "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", - .ksize = 32, - .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - .psize = 112, - .digest = "\x47\x03\x05\xfc\x7e\x40\xfe\x34" - "\xd3\xee\xb3\xe7\x73\xd9\x5a\xab" - "\x73\xac\xf0\xfd\x06\x04\x47\xa5" - "\xeb\x45\x95\xbf\x33\xa9\xd1\xa3", - }, { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b", - .ksize = 32, - .plaintext = "Hi There", - .psize = 8, - .digest = "\x19\x8a\x60\x7e\xb4\x4b\xfb\xc6" - "\x99\x03\xa0\xf1\xcf\x2b\xbd\xc5" - "\xba\x0a\xa3\xf3\xd9\xae\x3c\x1c" - "\x7a\x3b\x16\x96\xa0\xb6\x8c\xf7", - }, { - .key = "Jefe", - .ksize = 4, - .plaintext = "what do ya want for nothing?", - .psize = 28, - .digest = "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e" - "\x6a\x04\x24\x26\x08\x95\x75\xc7" - "\x5a\x00\x3f\x08\x9d\x27\x39\x83" - "\x9d\xec\x58\xb9\x64\xec\x38\x43", - .np = 2, - .tap = { 14, 14 } - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - .ksize = 32, - .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - .psize = 50, - .digest = "\xcd\xcb\x12\x20\xd1\xec\xcc\xea" - "\x91\xe5\x3a\xba\x30\x92\xf9\x62" - "\xe5\x49\xfe\x6c\xe9\xed\x7f\xdc" - "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0", - }, { - .key = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18" - "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" - "\x21\x22\x23\x24\x25", - .ksize = 37, - .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - .psize = 50, - .digest = "\xd4\x63\x3c\x17\xf6\xfb\x8d\x74" - "\x4c\x66\xde\xe0\xf8\xf0\x74\x55" - "\x6e\xc4\xaf\x55\xef\x07\x99\x85" - "\x41\x46\x8e\xb4\x9b\xd2\xe9\x17", - }, { - .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" - "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" - "\x0c\x0c\x0c\x0c\x0c\x0c", - .ksize = 32, - .plaintext = "Test With Truncation", - .psize = 20, - .digest = "\x75\x46\xaf\x01\x84\x1f\xc0\x9b" - "\x1a\xb9\xc3\x74\x9a\x5f\x1c\x17" - "\xd4\xf5\x89\x66\x8a\x58\x7b\x27" - "\x00\xa9\xc9\x7c\x11\x93\xcf\x42", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", - .psize = 54, - .digest = "\x69\x53\x02\x5e\xd9\x6f\x0c\x09" - "\xf8\x0a\x96\xf7\x8e\x65\x38\xdb" - "\xe2\xe7\xb8\x20\xe3\xdd\x97\x0e" - "\x7d\xdd\x39\x09\x1b\x32\x35\x2f", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa", - .ksize = 80, - .plaintext = "Test Using Larger Than Block-Size Key and Larger Than " - "One Block-Size Data", - .psize = 73, - .digest = "\x63\x55\xac\x22\xe8\x90\xd0\xa3" - "\xc8\x48\x1a\x5c\xa4\x82\x5b\xc8" - "\x84\xd3\xe7\xa1\xff\x98\xa2\xfc" - "\x2a\xc7\xd8\xe0\x64\xc3\xb2\xe6", - }, -}; - -#define XCBC_AES_TEST_VECTORS 6 - -static struct hash_testvec aes_xcbc128_tv_template[] = { - { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .plaintext = zeroed_string, - .digest = "\x75\xf0\x25\x1d\x52\x8a\xc0\x1c" - "\x45\x73\xdf\xd5\x84\xd7\x9f\x29", - .psize = 0, - .ksize = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .plaintext = "\x00\x01\x02", - .digest = "\x5b\x37\x65\x80\xae\x2f\x19\xaf" - "\xe7\x21\x9c\xee\xf1\x72\x75\x6f", - .psize = 3, - .ksize = 16, - } , { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .digest = "\xd2\xa2\x46\xfa\x34\x9b\x68\xa7" - "\x99\x98\xa4\x39\x4f\xf7\xa2\x63", - .psize = 16, - .ksize = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13", - .digest = "\x47\xf5\x1b\x45\x64\x96\x62\x15" - "\xb8\x98\x5c\x63\x05\x5e\xd3\x08", - .tap = { 10, 10 }, - .psize = 20, - .np = 2, - .ksize = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .digest = "\xf5\x4f\x0e\xc8\xd2\xb9\xf3\xd3" - "\x68\x07\x73\x4b\xd5\x28\x3f\xd4", - .psize = 32, - .ksize = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21", - .digest = "\xbe\xcb\xb3\xbc\xcd\xb5\x18\xa3" - "\x06\x77\xd5\x48\x1f\xb6\xb4\xd8", - .tap = { 17, 17 }, - .psize = 34, - .np = 2, - .ksize = 16, - } -}; - -/* - * SHA384 HMAC test vectors from RFC4231 - */ - -#define HMAC_SHA384_TEST_VECTORS 4 - -static struct hash_testvec hmac_sha384_tv_template[] = { - { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b", - .ksize = 20, - .plaintext = "Hi There", - .psize = 8, - .digest = "\xaf\xd0\x39\x44\xd8\x48\x95\x62" - "\x6b\x08\x25\xf4\xab\x46\x90\x7f" - "\x15\xf9\xda\xdb\xe4\x10\x1e\xc6" - "\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c" - "\xfa\xea\x9e\xa9\x07\x6e\xde\x7f" - "\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6", - }, { - .key = "Jefe", - .ksize = 4, - .plaintext = "what do ya want for nothing?", - .psize = 28, - .digest = "\xaf\x45\xd2\xe3\x76\x48\x40\x31" - "\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" - "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47" - "\xe4\x2e\xc3\x73\x63\x22\x44\x5e" - "\x8e\x22\x40\xca\x5e\x69\xe2\xc7" - "\x8b\x32\x39\xec\xfa\xb2\x16\x49", - .np = 4, - .tap = { 7, 7, 7, 7 } - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa", - .ksize = 131, - .plaintext = "Test Using Larger Than Block-Siz" - "e Key - Hash Key First", - .psize = 54, - .digest = "\x4e\xce\x08\x44\x85\x81\x3e\x90" - "\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4" - "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f" - "\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6" - "\x0c\x2e\xf6\xab\x40\x30\xfe\x82" - "\x96\x24\x8d\xf1\x63\xf4\x49\x52", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa", - .ksize = 131, - .plaintext = "This is a test u" - "sing a larger th" - "an block-size ke" - "y and a larger t" - "han block-size d" - "ata. The key nee" - "ds to be hashed " - "before being use" - "d by the HMAC al" - "gorithm.", - .psize = 152, - .digest = "\x66\x17\x17\x8e\x94\x1f\x02\x0d" - "\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c" - "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a" - "\xdc\xce\xbb\x82\x46\x1e\x99\xc5" - "\xa6\x78\xcc\x31\xe7\x99\x17\x6d" - "\x38\x60\xe6\x11\x0c\x46\x52\x3e", - }, -}; - -/* - * SHA512 HMAC test vectors from RFC4231 - */ - -#define HMAC_SHA512_TEST_VECTORS 4 - -static struct hash_testvec hmac_sha512_tv_template[] = { - { - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b", - .ksize = 20, - .plaintext = "Hi There", - .psize = 8, - .digest = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d" - "\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0" - "\x23\x79\xf4\xe2\xce\x4e\xc2\x78" - "\x7a\xd0\xb3\x05\x45\xe1\x7c\xde" - "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02" - "\x03\x8b\x27\x4e\xae\xa3\xf4\xe4" - "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70" - "\x2e\x69\x6c\x20\x3a\x12\x68\x54", - }, { - .key = "Jefe", - .ksize = 4, - .plaintext = "what do ya want for nothing?", - .psize = 28, - .digest = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2" - "\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" - "\x87\xbd\x64\x22\x2e\x83\x1f\xd6" - "\x10\x27\x0c\xd7\xea\x25\x05\x54" - "\x97\x58\xbf\x75\xc0\x5a\x99\x4a" - "\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" - "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b" - "\x63\x6e\x07\x0a\x38\xbc\xe7\x37", - .np = 4, - .tap = { 7, 7, 7, 7 } - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa", - .ksize = 131, - .plaintext = "Test Using Large" - "r Than Block-Siz" - "e Key - Hash Key" - " First", - .psize = 54, - .digest = "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb" - "\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4" - "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1" - "\x12\x1b\x01\x37\x83\xf8\xf3\x52" - "\x6b\x56\xd0\x37\xe0\x5f\x25\x98" - "\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52" - "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec" - "\x8b\x91\x5a\x98\x5d\x78\x65\x98", - }, { - .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa", - .ksize = 131, - .plaintext = - "This is a test u" - "sing a larger th" - "an block-size ke" - "y and a larger t" - "han block-size d" - "ata. The key nee" - "ds to be hashed " - "before being use" - "d by the HMAC al" - "gorithm.", - .psize = 152, - .digest = "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba" - "\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd" - "\xde\xbd\x71\xf8\x86\x72\x89\x86" - "\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" - "\xb6\x02\x2c\xac\x3c\x49\x82\xb1" - "\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" - "\x13\x46\x76\xfb\x6d\xe0\x44\x60" - "\x65\xc9\x74\x40\xfa\x8c\x6a\x58", - }, -}; - /* * DES test vectors. */ -#define DES_ENC_TEST_VECTORS 10 -#define DES_DEC_TEST_VECTORS 4 -#define DES_CBC_ENC_TEST_VECTORS 5 -#define DES_CBC_DEC_TEST_VECTORS 4 -#define DES3_EDE_ENC_TEST_VECTORS 3 -#define DES3_EDE_DEC_TEST_VECTORS 3 -#define DES3_EDE_CBC_ENC_TEST_VECTORS 1 -#define DES3_EDE_CBC_DEC_TEST_VECTORS 1 - -static struct cipher_testvec des_enc_tv_template[] = { - { /* From Applied Cryptography */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7", - .ilen = 8, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", - .rlen = 8, - }, { /* Same key, different plaintext block */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x22\x33\x44\x55\x66\x77\x88\x99", - .ilen = 8, - .result = "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", - .rlen = 8, - }, { /* Sbox test from NBS */ - .key = "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57", - .klen = 8, - .input = "\x01\xa1\xd6\xd0\x39\x77\x67\x42", - .ilen = 8, - .result = "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", - .rlen = 8, - }, { /* Three blocks */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" - "\x22\x33\x44\x55\x66\x77\x88\x99" - "\xca\xfe\xba\xbe\xfe\xed\xbe\xef", - .ilen = 24, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" - "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b" - "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90", - .rlen = 24, - }, { /* Weak key */ - .fail = 1, - .wk = 1, - .key = "\x01\x01\x01\x01\x01\x01\x01\x01", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7", - .ilen = 8, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", - .rlen = 8, - }, { /* Two blocks -- for testing encryption across pages */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" - "\x22\x33\x44\x55\x66\x77\x88\x99", - .ilen = 16, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" - "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", - .rlen = 16, - .np = 2, - .tap = { 8, 8 } - }, { /* Four blocks -- for testing encryption with chunking */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" - "\x22\x33\x44\x55\x66\x77\x88\x99" - "\xca\xfe\xba\xbe\xfe\xed\xbe\xef" - "\x22\x33\x44\x55\x66\x77\x88\x99", - .ilen = 32, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" - "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b" - "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90" - "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", - .rlen = 32, - .np = 3, - .tap = { 14, 10, 8 } - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" - "\x22\x33\x44\x55\x66\x77\x88\x99" - "\xca\xfe\xba\xbe\xfe\xed\xbe\xef", - .ilen = 24, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" - "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b" - "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90", - .rlen = 24, - .np = 4, - .tap = { 2, 1, 3, 18 } - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" - "\x22\x33\x44\x55\x66\x77\x88\x99", - .ilen = 16, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" - "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", - .rlen = 16, - .np = 5, - .tap = { 2, 2, 2, 2, 8 } - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7", - .ilen = 8, - .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", - .rlen = 8, - .np = 8, - .tap = { 1, 1, 1, 1, 1, 1, 1, 1 } - }, -}; - -static struct cipher_testvec des_dec_tv_template[] = { - { /* From Applied Cryptography */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", - .ilen = 8, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7", - .rlen = 8, - }, { /* Sbox test from NBS */ - .key = "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57", - .klen = 8, - .input = "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", - .ilen = 8, - .result = "\x01\xa1\xd6\xd0\x39\x77\x67\x42", - .rlen = 8, - }, { /* Two blocks, for chunking test */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" - "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", - .ilen = 16, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7" - "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5", - .rlen = 16, - .np = 2, - .tap = { 8, 8 } - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" - "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", - .ilen = 16, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7" - "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5", - .rlen = 16, - .np = 3, - .tap = { 3, 12, 1 } - }, -}; - -static struct cipher_testvec des_cbc_enc_tv_template[] = { - { /* From OpenSSL */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .input = "\x37\x36\x35\x34\x33\x32\x31\x20" - "\x4e\x6f\x77\x20\x69\x73\x20\x74" - "\x68\x65\x20\x74\x69\x6d\x65\x20", - .ilen = 24, - .result = "\xcc\xd1\x73\xff\xab\x20\x39\xf4" - "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb" - "\x46\x8e\x91\x15\x78\x88\xba\x68", - .rlen = 24, - }, { /* FIPS Pub 81 */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\x12\x34\x56\x78\x90\xab\xcd\xef", - .input = "\x4e\x6f\x77\x20\x69\x73\x20\x74", - .ilen = 8, - .result = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", - .input = "\x68\x65\x20\x74\x69\x6d\x65\x20", - .ilen = 8, - .result = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", - .input = "\x66\x6f\x72\x20\x61\x6c\x6c\x20", - .ilen = 8, - .result = "\x68\x37\x88\x49\x9a\x7c\x05\xf6", - .rlen = 8, - }, { /* Copy of openssl vector for chunk testing */ - /* From OpenSSL */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .input = "\x37\x36\x35\x34\x33\x32\x31\x20" - "\x4e\x6f\x77\x20\x69\x73\x20\x74" - "\x68\x65\x20\x74\x69\x6d\x65\x20", - .ilen = 24, - .result = "\xcc\xd1\x73\xff\xab\x20\x39\xf4" - "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb" - "\x46\x8e\x91\x15\x78\x88\xba\x68", - .rlen = 24, - .np = 2, - .tap = { 13, 11 } - }, -}; - -static struct cipher_testvec des_cbc_dec_tv_template[] = { - { /* FIPS Pub 81 */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\x12\x34\x56\x78\x90\xab\xcd\xef", - .input = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", - .ilen = 8, - .result = "\x4e\x6f\x77\x20\x69\x73\x20\x74", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", - .input = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", - .ilen = 8, - .result = "\x68\x65\x20\x74\x69\x6d\x65\x20", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", - .input = "\x68\x37\x88\x49\x9a\x7c\x05\xf6", - .ilen = 8, - .result = "\x66\x6f\x72\x20\x61\x6c\x6c\x20", - .rlen = 8, - }, { /* Copy of above, for chunk testing */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", - .input = "\x68\x37\x88\x49\x9a\x7c\x05\xf6", - .ilen = 8, - .result = "\x66\x6f\x72\x20\x61\x6c\x6c\x20", - .rlen = 8, - .np = 2, - .tap = { 4, 4 } - }, -}; - -static struct cipher_testvec des3_ede_enc_tv_template[] = { - { /* These are from openssl */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\x55\x55\x55\x55\x55\x55\x55\x55" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 24, - .input = "\x73\x6f\x6d\x65\x64\x61\x74\x61", - .ilen = 8, - .result = "\x18\xd7\x48\xe5\x63\x62\x05\x72", - .rlen = 8, - }, { - .key = "\x03\x52\x02\x07\x67\x20\x82\x17" - "\x86\x02\x87\x66\x59\x08\x21\x98" - "\x64\x05\x6a\xbd\xfe\xa9\x34\x57", - .klen = 24, - .input = "\x73\x71\x75\x69\x67\x67\x6c\x65", - .ilen = 8, - .result = "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30", - .rlen = 8, - }, { - .key = "\x10\x46\x10\x34\x89\x98\x80\x20" - "\x91\x07\xd0\x15\x89\x19\x01\x01" - "\x19\x07\x92\x10\x98\x1a\x01\x01", - .klen = 24, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 8, - .result = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b", - .rlen = 8, - }, -}; - -static struct cipher_testvec des3_ede_dec_tv_template[] = { - { /* These are from openssl */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\x55\x55\x55\x55\x55\x55\x55\x55" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 24, - .input = "\x18\xd7\x48\xe5\x63\x62\x05\x72", - .ilen = 8, - .result = "\x73\x6f\x6d\x65\x64\x61\x74\x61", - .rlen = 8, - }, { - .key = "\x03\x52\x02\x07\x67\x20\x82\x17" - "\x86\x02\x87\x66\x59\x08\x21\x98" - "\x64\x05\x6a\xbd\xfe\xa9\x34\x57", - .klen = 24, - .input = "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30", - .ilen = 8, - .result = "\x73\x71\x75\x69\x67\x67\x6c\x65", - .rlen = 8, - }, { - .key = "\x10\x46\x10\x34\x89\x98\x80\x20" - "\x91\x07\xd0\x15\x89\x19\x01\x01" - "\x19\x07\x92\x10\x98\x1a\x01\x01", - .klen = 24, - .input = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b", - .ilen = 8, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00", - .rlen = 8, - }, -}; - -static struct cipher_testvec des3_ede_cbc_enc_tv_template[] = { - { /* Generated from openssl */ - .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" - "\x44\x4D\x99\x5A\x12\xD6\x40\xC0" - "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8", - .klen = 24, - .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", - .input = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" - "\x53\x20\x63\x65\x65\x72\x73\x74" - "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" - "\x20\x79\x65\x53\x72\x63\x74\x65" - "\x20\x73\x6f\x54\x20\x6f\x61\x4d" - "\x79\x6e\x53\x20\x63\x65\x65\x72" - "\x73\x74\x54\x20\x6f\x6f\x4d\x20" - "\x6e\x61\x20\x79\x65\x53\x72\x63" - "\x74\x65\x20\x73\x6f\x54\x20\x6f" - "\x61\x4d\x79\x6e\x53\x20\x63\x65" - "\x65\x72\x73\x74\x54\x20\x6f\x6f" - "\x4d\x20\x6e\x61\x20\x79\x65\x53" - "\x72\x63\x74\x65\x20\x73\x6f\x54" - "\x20\x6f\x61\x4d\x79\x6e\x53\x20" - "\x63\x65\x65\x72\x73\x74\x54\x20" - "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", - .ilen = 128, - .result = "\x0e\x2d\xb6\x97\x3c\x56\x33\xf4" - "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" - "\x74\xb3\x49\x05\xc5\x1c\xd0\xed" - "\x12\x56\x5c\x53\x96\xb6\x00\x7d" - "\x90\x48\xfc\xf5\x8d\x29\x39\xcc" - "\x8a\xd5\x35\x18\x36\x23\x4e\xd7" - "\x76\xd1\xda\x0c\x94\x67\xbb\x04" - "\x8b\xf2\x03\x6c\xa8\xcf\xb6\xea" - "\x22\x64\x47\xaa\x8f\x75\x13\xbf" - "\x9f\xc2\xc3\xf0\xc9\x56\xc5\x7a" - "\x71\x63\x2e\x89\x7b\x1e\x12\xca" - "\xe2\x5f\xaf\xd8\xa4\xf8\xc9\x7a" - "\xd6\xf9\x21\x31\x62\x44\x45\xa6" - "\xd6\xbc\x5a\xd3\x2d\x54\x43\xcc" - "\x9d\xde\xa5\x70\xe9\x42\x45\x8a" - "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", - .rlen = 128, - }, -}; - -static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = { - { /* Generated from openssl */ - .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" - "\x44\x4D\x99\x5A\x12\xD6\x40\xC0" - "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8", - .klen = 24, - .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", - .input = "\x0e\x2d\xb6\x97\x3c\x56\x33\xf4" - "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" - "\x74\xb3\x49\x05\xc5\x1c\xd0\xed" - "\x12\x56\x5c\x53\x96\xb6\x00\x7d" - "\x90\x48\xfc\xf5\x8d\x29\x39\xcc" - "\x8a\xd5\x35\x18\x36\x23\x4e\xd7" - "\x76\xd1\xda\x0c\x94\x67\xbb\x04" - "\x8b\xf2\x03\x6c\xa8\xcf\xb6\xea" - "\x22\x64\x47\xaa\x8f\x75\x13\xbf" - "\x9f\xc2\xc3\xf0\xc9\x56\xc5\x7a" - "\x71\x63\x2e\x89\x7b\x1e\x12\xca" - "\xe2\x5f\xaf\xd8\xa4\xf8\xc9\x7a" - "\xd6\xf9\x21\x31\x62\x44\x45\xa6" - "\xd6\xbc\x5a\xd3\x2d\x54\x43\xcc" - "\x9d\xde\xa5\x70\xe9\x42\x45\x8a" - "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", - .ilen = 128, - .result = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" - "\x53\x20\x63\x65\x65\x72\x73\x74" - "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" - "\x20\x79\x65\x53\x72\x63\x74\x65" - "\x20\x73\x6f\x54\x20\x6f\x61\x4d" - "\x79\x6e\x53\x20\x63\x65\x65\x72" - "\x73\x74\x54\x20\x6f\x6f\x4d\x20" - "\x6e\x61\x20\x79\x65\x53\x72\x63" - "\x74\x65\x20\x73\x6f\x54\x20\x6f" - "\x61\x4d\x79\x6e\x53\x20\x63\x65" - "\x65\x72\x73\x74\x54\x20\x6f\x6f" - "\x4d\x20\x6e\x61\x20\x79\x65\x53" - "\x72\x63\x74\x65\x20\x73\x6f\x54" - "\x20\x6f\x61\x4d\x79\x6e\x53\x20" - "\x63\x65\x65\x72\x73\x74\x54\x20" - "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", - .rlen = 128, - }, -}; - -/* - * Blowfish test vectors. - */ -#define BF_ENC_TEST_VECTORS 6 -#define BF_DEC_TEST_VECTORS 6 -#define BF_CBC_ENC_TEST_VECTORS 1 -#define BF_CBC_DEC_TEST_VECTORS 1 - -static struct cipher_testvec bf_enc_tv_template[] = { - { /* DES test vectors from OpenSSL */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 8, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 8, - .result = "\x4e\xf9\x97\x45\x61\x98\xdd\x78", - .rlen = 8, - }, { - .key = "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .ilen = 8, - .result = "\xa7\x90\x79\x51\x08\xea\x3c\xae", - .rlen = 8, - }, { - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .klen = 8, - .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .ilen = 8, - .result = "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82", - .rlen = 8, - }, { /* Vary the keylength... */ - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" - "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f", - .klen = 16, - .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .ilen = 8, - .result = "\x93\x14\x28\x87\xee\x3b\xe1\x5c", - .rlen = 8, - }, { - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" - "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" - "\x00\x11\x22\x33\x44", - .klen = 21, - .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .ilen = 8, - .result = "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f", - .rlen = 8, - }, { /* Generated with bf488 */ - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" - "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x04\x68\x91\x04\xc2\xfd\x3b\x2f" - "\x58\x40\x23\x64\x1a\xba\x61\x76" - "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e" - "\xff\xff\xff\xff\xff\xff\xff\xff", - .klen = 56, - .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .ilen = 8, - .result = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53", - .rlen = 8, - }, -}; - -static struct cipher_testvec bf_dec_tv_template[] = { - { /* DES test vectors from OpenSSL */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 8, - .input = "\x4e\xf9\x97\x45\x61\x98\xdd\x78", - .ilen = 8, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00", - .rlen = 8, - }, { - .key = "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e", - .klen = 8, - .input = "\xa7\x90\x79\x51\x08\xea\x3c\xae", - .ilen = 8, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .rlen = 8, - }, { - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .klen = 8, - .input = "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82", - .ilen = 8, - .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .rlen = 8, - }, { /* Vary the keylength... */ - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" - "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f", - .klen = 16, - .input = "\x93\x14\x28\x87\xee\x3b\xe1\x5c", - .ilen = 8, - .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .rlen = 8, - }, { - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" - "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" - "\x00\x11\x22\x33\x44", - .klen = 21, - .input = "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f", - .ilen = 8, - .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .rlen = 8, - }, { /* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */ - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" - "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x04\x68\x91\x04\xc2\xfd\x3b\x2f" - "\x58\x40\x23\x64\x1a\xba\x61\x76" - "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e" - "\xff\xff\xff\xff\xff\xff\xff\xff", - .klen = 56, - .input = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53", - .ilen = 8, - .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .rlen = 8, - }, -}; - -static struct cipher_testvec bf_cbc_enc_tv_template[] = { - { /* From OpenSSL */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .klen = 16, - .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .input = "\x37\x36\x35\x34\x33\x32\x31\x20" - "\x4e\x6f\x77\x20\x69\x73\x20\x74" - "\x68\x65\x20\x74\x69\x6d\x65\x20" - "\x66\x6f\x72\x20\x00\x00\x00\x00", - .ilen = 32, - .result = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6" - "\x05\xb1\x56\xe2\x74\x03\x97\x93" - "\x58\xde\xb9\xe7\x15\x46\x16\xd9" - "\x59\xf1\x65\x2b\xd5\xff\x92\xcc", - .rlen = 32, - }, -}; - -static struct cipher_testvec bf_cbc_dec_tv_template[] = { - { /* From OpenSSL */ - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .klen = 16, - .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .input = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6" - "\x05\xb1\x56\xe2\x74\x03\x97\x93" - "\x58\xde\xb9\xe7\x15\x46\x16\xd9" - "\x59\xf1\x65\x2b\xd5\xff\x92\xcc", - .ilen = 32, - .result = "\x37\x36\x35\x34\x33\x32\x31\x20" - "\x4e\x6f\x77\x20\x69\x73\x20\x74" - "\x68\x65\x20\x74\x69\x6d\x65\x20" - "\x66\x6f\x72\x20\x00\x00\x00\x00", - .rlen = 32, - }, -}; - -/* - * Twofish test vectors. - */ -#define TF_ENC_TEST_VECTORS 3 -#define TF_DEC_TEST_VECTORS 3 -#define TF_CBC_ENC_TEST_VECTORS 4 -#define TF_CBC_DEC_TEST_VECTORS 4 - -static struct cipher_testvec tf_enc_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = zeroed_string, - .ilen = 16, - .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", - .rlen = 16, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77", - .klen = 24, - .input = zeroed_string, - .ilen = 16, - .result = "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf" - "\x50\x1f\x13\xb8\x92\xbd\x22\x48", - .rlen = 16, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .klen = 32, - .input = zeroed_string, - .ilen = 16, - .result = "\x37\x52\x7b\xe0\x05\x23\x34\xb8" - "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20", - .rlen = 16, - }, -}; +#define DES3_SPEED_VECTORS 1 -static struct cipher_testvec tf_dec_tv_template[] = { +static struct cipher_speed_template des3_speed_template[] = { { - .key = zeroed_string, - .klen = 16, - .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77", - .klen = 24, - .input = "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf" - "\x50\x1f\x13\xb8\x92\xbd\x22\x48", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .klen = 32, - .input = "\x37\x52\x7b\xe0\x05\x23\x34\xb8" - "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, -}; - -static struct cipher_testvec tf_cbc_enc_tv_template[] = { - { /* Generated with Nettle */ - .key = zeroed_string, - .klen = 16, - .iv = zeroed_string, - .input = zeroed_string, - .ilen = 16, - .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 16, - .iv = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", - .input = zeroed_string, - .ilen = 16, - .result = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" - "\x86\xcb\x08\x6b\x78\x9f\x54\x19", - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 16, - .iv = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" - "\x86\xcb\x08\x6b\x78\x9f\x54\x19", - .input = zeroed_string, - .ilen = 16, - .result = "\x05\xef\x8c\x61\xa8\x11\x58\x26" - "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 16, - .iv = zeroed_string, - .input = zeroed_string, - .ilen = 48, - .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a" - "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" - "\x86\xcb\x08\x6b\x78\x9f\x54\x19" - "\x05\xef\x8c\x61\xa8\x11\x58\x26" - "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", - .rlen = 48, - }, -}; - -static struct cipher_testvec tf_cbc_dec_tv_template[] = { - { /* Reverse of the first four above */ - .key = zeroed_string, - .klen = 16, - .iv = zeroed_string, - .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 16, - .iv = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", - .input = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" - "\x86\xcb\x08\x6b\x78\x9f\x54\x19", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 16, - .iv = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" - "\x86\xcb\x08\x6b\x78\x9f\x54\x19", - .input = "\x05\xef\x8c\x61\xa8\x11\x58\x26" - "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 16, - .iv = zeroed_string, - .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" - "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a" - "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" - "\x86\xcb\x08\x6b\x78\x9f\x54\x19" - "\x05\xef\x8c\x61\xa8\x11\x58\x26" - "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", - .ilen = 48, - .result = zeroed_string, - .rlen = 48, - }, -}; - -/* - * Serpent test vectors. These are backwards because Serpent writes - * octet sequences in right-to-left mode. - */ -#define SERPENT_ENC_TEST_VECTORS 4 -#define SERPENT_DEC_TEST_VECTORS 4 - -#define TNEPRES_ENC_TEST_VECTORS 4 -#define TNEPRES_DEC_TEST_VECTORS 4 - -static struct cipher_testvec serpent_enc_tv_template[] = { - { - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .ilen = 16, - .result = "\x12\x07\xfc\xce\x9b\xd0\xd6\x47" - "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .klen = 16, - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .ilen = 16, - .result = "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c" - "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .klen = 32, - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .ilen = 16, - .result = "\xde\x26\x9f\xf8\x33\xe4\x32\xb8" - "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c", - .rlen = 16, - }, { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", - .klen = 16, - .input = zeroed_string, - .ilen = 16, - .result = "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c" - "\x05\x34\x5a\x9d\xad\xbf\xaf\x49", - .rlen = 16, - }, -}; - -static struct cipher_testvec tnepres_enc_tv_template[] = { - { /* KeySize=128, PT=0, I=1 */ - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .key = "\x80\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .ilen = 16, - .result = "\x49\xaf\xbf\xad\x9d\x5a\x34\x05" - "\x2c\xd8\xff\xa5\x98\x6b\xd2\xdd", - .rlen = 16, - }, { /* KeySize=192, PT=0, I=1 */ - .key = "\x80\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 24, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 16, - .result = "\xe7\x8e\x54\x02\xc7\x19\x55\x68" - "\xac\x36\x78\xf7\xa3\xf6\x0c\x66", - .rlen = 16, - }, { /* KeySize=256, PT=0, I=1 */ - .key = "\x80\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 32, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 16, - .result = "\xab\xed\x96\xe7\x66\xbf\x28\xcb" - "\xc0\xeb\xd2\x1a\x82\xef\x08\x19", - .rlen = 16, - }, { /* KeySize=256, I=257 */ - .key = "\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18" - "\x17\x16\x15\x14\x13\x12\x11\x10" - "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08" - "\x07\x06\x05\x04\x03\x02\x01\x00", - .klen = 32, - .input = "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08" - "\x07\x06\x05\x04\x03\x02\x01\x00", - .ilen = 16, - .result = "\x5c\xe7\x1c\x70\xd2\x88\x2e\x5b" - "\xb8\x32\xe4\x33\xf8\x9f\x26\xde", - .rlen = 16, - }, -}; - - -static struct cipher_testvec serpent_dec_tv_template[] = { - { - .input = "\x12\x07\xfc\xce\x9b\xd0\xd6\x47" - "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2", - .ilen = 16, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .klen = 16, - .input = "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c" - "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d", - .ilen = 16, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .klen = 32, - .input = "\xde\x26\x9f\xf8\x33\xe4\x32\xb8" - "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c", - .ilen = 16, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .rlen = 16, - }, { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", - .klen = 16, - .input = "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c" - "\x05\x34\x5a\x9d\xad\xbf\xaf\x49", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, -}; - -static struct cipher_testvec tnepres_dec_tv_template[] = { - { - .input = "\x41\xcc\x6b\x31\x59\x31\x45\x97" - "\x6d\x6f\xbb\x38\x4b\x37\x21\x28", - .ilen = 16, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .klen = 16, - .input = "\xea\xf4\xd7\xfc\xd8\x01\x34\x47" - "\x81\x45\x0b\xfa\x0c\xd6\xad\x6e", - .ilen = 16, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .klen = 32, - .input = "\x64\xa9\x1a\x37\xed\x9f\xe7\x49" - "\xa8\x4e\x76\xd6\xf5\x0d\x78\xee", - .ilen = 16, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .rlen = 16, - }, { /* KeySize=128, I=121 */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", - .klen = 16, - .input = "\x3d\xda\xbf\xc0\x06\xda\xab\x06" - "\x46\x2a\xf4\xef\x81\x54\x4e\x26", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, -}; - - -/* Cast6 test vectors from RFC 2612 */ -#define CAST6_ENC_TEST_VECTORS 3 -#define CAST6_DEC_TEST_VECTORS 3 - -static struct cipher_testvec cast6_enc_tv_template[] = { - { - .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" - "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d", - .klen = 16, - .input = zeroed_string, - .ilen = 16, - .result = "\xc8\x42\xa0\x89\x72\xb4\x3d\x20" - "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b", - .rlen = 16, - }, { - .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" - "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" - "\xba\xc7\x7a\x77\x17\x94\x28\x63", - .klen = 24, - .input = zeroed_string, - .ilen = 16, - .result = "\x1b\x38\x6c\x02\x10\xdc\xad\xcb" - "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8", - .rlen = 16, - }, { - .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" - "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" - "\x8d\x7c\x47\xce\x26\x49\x08\x46" - "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04", - .klen = 32, - .input = zeroed_string, - .ilen = 16, - .result = "\x4f\x6a\x20\x38\x28\x68\x97\xb9" - "\xc9\x87\x01\x36\x55\x33\x17\xfa", - .rlen = 16, - }, -}; - -static struct cipher_testvec cast6_dec_tv_template[] = { - { - .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" - "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d", - .klen = 16, - .input = "\xc8\x42\xa0\x89\x72\xb4\x3d\x20" - "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { - .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" - "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" - "\xba\xc7\x7a\x77\x17\x94\x28\x63", - .klen = 24, - .input = "\x1b\x38\x6c\x02\x10\xdc\xad\xcb" - "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { - .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" - "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" - "\x8d\x7c\x47\xce\x26\x49\x08\x46" - "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04", - .klen = 32, - .input = "\x4f\x6a\x20\x38\x28\x68\x97\xb9" - "\xc9\x87\x01\x36\x55\x33\x17\xfa", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, -}; - - -/* - * AES test vectors. - */ -#define AES_ENC_TEST_VECTORS 3 -#define AES_DEC_TEST_VECTORS 3 -#define AES_CBC_ENC_TEST_VECTORS 4 -#define AES_CBC_DEC_TEST_VECTORS 4 -#define AES_LRW_ENC_TEST_VECTORS 8 -#define AES_LRW_DEC_TEST_VECTORS 8 -#define AES_XTS_ENC_TEST_VECTORS 4 -#define AES_XTS_DEC_TEST_VECTORS 4 -#define AES_CTR_ENC_TEST_VECTORS 7 -#define AES_CTR_DEC_TEST_VECTORS 6 -#define AES_GCM_ENC_TEST_VECTORS 9 -#define AES_GCM_DEC_TEST_VECTORS 8 -#define AES_CCM_ENC_TEST_VECTORS 7 -#define AES_CCM_DEC_TEST_VECTORS 7 - -static struct cipher_testvec aes_enc_tv_template[] = { - { /* From FIPS-197 */ - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .klen = 16, - .input = "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .ilen = 16, - .result = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" - "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17", - .klen = 24, - .input = "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .ilen = 16, - .result = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" - "\x6e\xaf\x70\xa0\xec\x0d\x71\x91", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .klen = 32, - .input = "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .ilen = 16, - .result = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf" - "\xea\xfc\x49\x90\x4b\x49\x60\x89", - .rlen = 16, - }, -}; - -static struct cipher_testvec aes_dec_tv_template[] = { - { /* From FIPS-197 */ - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .klen = 16, - .input = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" - "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a", - .ilen = 16, - .result = "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17", - .klen = 24, - .input = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" - "\x6e\xaf\x70\xa0\xec\x0d\x71\x91", - .ilen = 16, - .result = "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .klen = 32, - .input = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf" - "\xea\xfc\x49\x90\x4b\x49\x60\x89", - .ilen = 16, - .result = "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .rlen = 16, - }, -}; - -static struct cipher_testvec aes_cbc_enc_tv_template[] = { - { /* From RFC 3602 */ - .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" - "\x51\x2e\x03\xd5\x34\x12\x00\x06", - .klen = 16, - .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" - "\xb4\x22\xda\x80\x2c\x9f\xac\x41", - .input = "Single block msg", - .ilen = 16, - .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" - "\x27\x08\x94\x2d\xbe\x77\x18\x1a", - .rlen = 16, - }, { - .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" - "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", - .klen = 16, - .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" - "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .ilen = 32, - .result = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" - "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" - "\x75\x86\x60\x2d\x25\x3c\xff\xf9" - "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1", - .rlen = 32, - }, { /* From NIST SP800-38A */ - .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" - "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" - "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", - .klen = 24, - .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" - "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" - "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" - "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" - "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" - "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" - "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" - "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", - .ilen = 64, - .result = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" - "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" - "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" - "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" - "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" - "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" - "\x08\xb0\xe2\x79\x88\x59\x88\x81" - "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", - .rlen = 64, - }, { - .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" - "\x2b\x73\xae\xf0\x85\x7d\x77\x81" - "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" - "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", - .klen = 32, - .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" - "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" - "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" - "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" - "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" - "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" - "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" - "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", - .ilen = 64, - .result = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" - "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" - "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" - "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" - "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" - "\xa5\x30\xe2\x63\x04\x23\x14\x61" - "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" - "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", - .rlen = 64, - }, -}; - -static struct cipher_testvec aes_cbc_dec_tv_template[] = { - { /* From RFC 3602 */ - .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" - "\x51\x2e\x03\xd5\x34\x12\x00\x06", - .klen = 16, - .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" - "\xb4\x22\xda\x80\x2c\x9f\xac\x41", - .input = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" - "\x27\x08\x94\x2d\xbe\x77\x18\x1a", - .ilen = 16, - .result = "Single block msg", - .rlen = 16, - }, { - .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" - "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", - .klen = 16, - .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" - "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", - .input = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" - "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" - "\x75\x86\x60\x2d\x25\x3c\xff\xf9" - "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1", - .ilen = 32, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .rlen = 32, - }, { /* From NIST SP800-38A */ - .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" - "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" - "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", - .klen = 24, - .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .input = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" - "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" - "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" - "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" - "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" - "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" - "\x08\xb0\xe2\x79\x88\x59\x88\x81" - "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", - .ilen = 64, - .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" - "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" - "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" - "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" - "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" - "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" - "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" - "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", - .rlen = 64, - }, { - .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" - "\x2b\x73\xae\xf0\x85\x7d\x77\x81" - "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" - "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", - .klen = 32, - .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .input = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" - "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" - "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" - "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" - "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" - "\xa5\x30\xe2\x63\x04\x23\x14\x61" - "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" - "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", - .ilen = 64, - .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" - "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" - "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" - "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" - "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" - "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" - "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" - "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", - .rlen = 64, - }, -}; - -static struct cipher_testvec aes_lrw_enc_tv_template[] = { - /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */ - { /* LRW-32-AES 1 */ - .key = "\x45\x62\xac\x25\xf8\x28\x17\x6d" - "\x4c\x26\x84\x14\xb5\x68\x01\x85" - "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03" - "\xee\x5a\x83\x0c\xcc\x09\x4c\x87", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .ilen = 16, - .result = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f" - "\xe9\x5d\x48\x92\x54\x63\x4e\xb8", - .rlen = 16, - }, { /* LRW-32-AES 2 */ - .key = "\x59\x70\x47\x14\xf5\x57\x47\x8c" - "\xd7\x79\xe8\x0f\x54\x88\x79\x44" - "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea" - "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x02", - .input = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .ilen = 16, - .result = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5" - "\x27\x4f\x07\x69\xb2\x60\xe1\x36", - .rlen = 16, - }, { /* LRW-32-AES 3 */ - .key = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50" - "\x30\xfe\x69\xe2\x37\x7f\x98\x47" - "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6" - "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x02\x00\x00\x00\x00", - .input = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .ilen = 16, - .result = "\x76\x32\x21\x83\xed\x8f\xf1\x82" - "\xf9\x59\x62\x03\x69\x0e\x5e\x01", - .rlen = 16, - }, { /* LRW-32-AES 4 */ - .key = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15" - "\x25\x83\xf7\x3c\x1f\x01\x28\x74" - "\xca\xc6\xbc\x35\x4d\x4a\x65\x54" - "\x90\xae\x61\xcf\x7b\xae\xbd\xcc" - "\xad\xe4\x94\xc5\x4a\x29\xae\x70", - .klen = 40, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .ilen = 16, - .result = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0" - "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41", - .rlen = 16, - }, { /* LRW-32-AES 5 */ - .key = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff" - "\xf8\x86\xce\xac\x93\xc5\xad\xc6" - "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd" - "\x52\x13\xb2\xb7\xf0\xff\x11\xd8" - "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f", - .klen = 40, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x02\x00\x00\x00\x00", - .input = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .ilen = 16, - .result = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65" - "\xc8\x60\x48\x02\x87\xe3\x34\x06", - .rlen = 16, - }, { /* LRW-32-AES 6 */ - .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" - "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" - "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" - "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" - "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" - "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", - .klen = 48, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .ilen = 16, - .result = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e" - "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b", - .rlen = 16, - }, { /* LRW-32-AES 7 */ - .key = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d" - "\xd4\x70\x98\x0b\xc7\x95\x84\xc8" - "\xb2\xfb\x64\xce\x60\x97\x87\x8d" - "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7" - "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4" - "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c", - .klen = 48, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x02\x00\x00\x00\x00", - .input = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .ilen = 16, - .result = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f" - "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5", - .rlen = 16, - }, { -/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */ - .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" - "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" - "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" - "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" - "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" - "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", - .klen = 48, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\x05\x11\xb7\x18\xab\xc6\x2d\xac" - "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c" - "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8" - "\x50\x38\x1f\x71\x49\xb6\x57\xd6" - "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90" - "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6" - "\xad\x1e\x9e\x20\x5f\x38\xbe\x04" - "\xda\x10\x8e\xed\xa2\xa4\x87\xab" - "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c" - "\xc9\xac\x42\x31\x95\x7c\xc9\x04" - "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6" - "\x15\xd7\x3f\x4f\x2f\x66\x69\x03" - "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65" - "\x4c\x96\x12\xed\x7c\x92\x03\x01" - "\x6f\xbc\x35\x93\xac\xf1\x27\xf1" - "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50" - "\x89\xa4\x8e\x66\x44\x85\xcc\xfd" - "\x33\x14\x70\xe3\x96\xb2\xc3\xd3" - "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5" - "\x2d\x64\x75\xdd\xb4\x54\xe6\x74" - "\x8c\xd3\x9d\x9e\x86\xab\x51\x53" - "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40" - "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5" - "\x76\x12\x73\x44\x1a\x56\xd7\x72" - "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda" - "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd" - "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60" - "\x1a\xe2\x70\x85\x58\xc2\x1b\x09" - "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9" - "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8" - "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8" - "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10" - "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1" - "\x90\x3e\x76\x4a\x74\xa4\x21\x2c" - "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e" - "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f" - "\x8d\x23\x31\x74\x84\xeb\x88\x6e" - "\xcc\xb9\xbc\x22\x83\x19\x07\x22" - "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78" - "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5" - "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41" - "\x3c\xce\x8f\x42\x60\x71\xa7\x75" - "\x08\x40\x65\x8a\x82\xbf\xf5\x43" - "\x71\x96\xa9\x4d\x44\x8a\x20\xbe" - "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65" - "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9" - "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4" - "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a" - "\x62\x73\x65\xfd\x46\x63\x25\x3d" - "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf" - "\x24\xf3\xb4\xac\x64\xba\xdf\x4b" - "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7" - "\xc5\x68\x77\x84\x32\x2b\xcc\x85" - "\x74\x96\xf0\x12\x77\x61\xb9\xeb" - "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8" - "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24" - "\xda\x39\x87\x45\xc0\x2b\xbb\x01" - "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce" - "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6" - "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32" - "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45" - "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6" - "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4" - "\x21\xc4\xc2\x75\x67\x89\x37\x0a", - .ilen = 512, - .result = "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b" - "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a" - "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23" - "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e" - "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c" - "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d" - "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3" - "\xe8\x58\x46\x97\x39\x51\x07\xde" - "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3" - "\x0e\x84\x23\x1d\x16\xd4\x1c\x59" - "\x9c\x1a\x02\x55\xab\x3a\x97\x1d" - "\xdf\xdd\xc7\x06\x51\xd7\x70\xae" - "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82" - "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68" - "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce" - "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98" - "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2" - "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f" - "\xea\x20\xe7\xcb\x65\x77\x3a\xdf" - "\xc8\x97\x67\x15\xc2\x2a\x27\xcc" - "\x18\x55\xa1\x24\x0b\x24\x24\xaf" - "\x5b\xec\x68\xb8\xc8\xf5\xba\x63" - "\xff\xed\x89\xce\xd5\x3d\x88\xf3" - "\x25\xef\x05\x7c\x3a\xef\xeb\xd8" - "\x7a\x32\x0d\xd1\x1e\x58\x59\x99" - "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c" - "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50" - "\x41\x30\x58\xc5\x62\x74\x52\x1d" - "\x45\x24\x6a\x42\x64\x4f\x97\x1c" - "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48" - "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1" - "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46" - "\xe4\x81\x84\x95\x36\x59\x7a\x6b" - "\xaa\xb3\x60\xad\xce\x9f\x9f\x28" - "\xe0\x01\x75\x22\xc4\x4e\xa9\x62" - "\x5c\x62\x0d\x00\xcb\x13\xe8\x43" - "\x72\xd4\x2d\x53\x46\xb5\xd1\x16" - "\x22\x18\xdf\x34\x33\xf5\xd6\x1c" - "\xb8\x79\x78\x97\x94\xff\x72\x13" - "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6" - "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4" - "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f" - "\x2d\x14\x8e\x24\x61\x2c\xe1\x17" - "\xcc\xce\x51\x0c\x19\x8a\x82\x30" - "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd" - "\xb7\xeb\xfa\xfd\x27\x51\xde\x85" - "\x1e\x86\x53\x11\x53\x94\x00\xee" - "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11" - "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62" - "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1" - "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a" - "\x9e\xfa\x31\x18\x45\x3c\x21\x33" - "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1" - "\x03\xad\x1b\x48\xd4\x67\x27\xf0" - "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7" - "\xdd\x2b\x01\x39\x04\x5a\x58\x7a" - "\xf7\x11\x90\xec\xbd\x51\x5c\x32" - "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6" - "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d" - "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4" - "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3" - "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29" - "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7" - "\x74\x3f\x7d\x58\x88\x75\xde\x3e", - .rlen = 512, - } -}; - -static struct cipher_testvec aes_lrw_dec_tv_template[] = { - /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */ - /* same as enc vectors with input and result reversed */ - { /* LRW-32-AES 1 */ - .key = "\x45\x62\xac\x25\xf8\x28\x17\x6d" - "\x4c\x26\x84\x14\xb5\x68\x01\x85" - "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03" - "\xee\x5a\x83\x0c\xcc\x09\x4c\x87", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f" - "\xe9\x5d\x48\x92\x54\x63\x4e\xb8", - .ilen = 16, - .result = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .rlen = 16, - }, { /* LRW-32-AES 2 */ - .key = "\x59\x70\x47\x14\xf5\x57\x47\x8c" - "\xd7\x79\xe8\x0f\x54\x88\x79\x44" - "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea" - "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x02", - .input = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5" - "\x27\x4f\x07\x69\xb2\x60\xe1\x36", - .ilen = 16, - .result = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .rlen = 16, - }, { /* LRW-32-AES 3 */ - .key = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50" - "\x30\xfe\x69\xe2\x37\x7f\x98\x47" - "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6" - "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x02\x00\x00\x00\x00", - .input = "\x76\x32\x21\x83\xed\x8f\xf1\x82" - "\xf9\x59\x62\x03\x69\x0e\x5e\x01", - .ilen = 16, - .result = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .rlen = 16, - }, { /* LRW-32-AES 4 */ - .key = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15" - "\x25\x83\xf7\x3c\x1f\x01\x28\x74" - "\xca\xc6\xbc\x35\x4d\x4a\x65\x54" - "\x90\xae\x61\xcf\x7b\xae\xbd\xcc" - "\xad\xe4\x94\xc5\x4a\x29\xae\x70", - .klen = 40, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0" - "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41", - .ilen = 16, - .result = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .rlen = 16, - }, { /* LRW-32-AES 5 */ - .key = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff" - "\xf8\x86\xce\xac\x93\xc5\xad\xc6" - "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd" - "\x52\x13\xb2\xb7\xf0\xff\x11\xd8" - "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f", - .klen = 40, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x02\x00\x00\x00\x00", - .input = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65" - "\xc8\x60\x48\x02\x87\xe3\x34\x06", - .ilen = 16, - .result = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .rlen = 16, - }, { /* LRW-32-AES 6 */ - .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" - "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" - "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" - "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" - "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" - "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", - .klen = 48, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e" - "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b", - .ilen = 16, - .result = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .rlen = 16, - }, { /* LRW-32-AES 7 */ - .key = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d" - "\xd4\x70\x98\x0b\xc7\x95\x84\xc8" - "\xb2\xfb\x64\xce\x60\x97\x87\x8d" - "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7" - "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4" - "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c", - .klen = 48, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x02\x00\x00\x00\x00", - .input = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f" - "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5", - .ilen = 16, - .result = "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x41\x42\x43\x44\x45\x46", - .rlen = 16, - }, { -/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */ - .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" - "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" - "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" - "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" - "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" - "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", - .klen = 48, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x01", - .input = "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b" - "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a" - "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23" - "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e" - "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c" - "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d" - "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3" - "\xe8\x58\x46\x97\x39\x51\x07\xde" - "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3" - "\x0e\x84\x23\x1d\x16\xd4\x1c\x59" - "\x9c\x1a\x02\x55\xab\x3a\x97\x1d" - "\xdf\xdd\xc7\x06\x51\xd7\x70\xae" - "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82" - "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68" - "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce" - "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98" - "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2" - "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f" - "\xea\x20\xe7\xcb\x65\x77\x3a\xdf" - "\xc8\x97\x67\x15\xc2\x2a\x27\xcc" - "\x18\x55\xa1\x24\x0b\x24\x24\xaf" - "\x5b\xec\x68\xb8\xc8\xf5\xba\x63" - "\xff\xed\x89\xce\xd5\x3d\x88\xf3" - "\x25\xef\x05\x7c\x3a\xef\xeb\xd8" - "\x7a\x32\x0d\xd1\x1e\x58\x59\x99" - "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c" - "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50" - "\x41\x30\x58\xc5\x62\x74\x52\x1d" - "\x45\x24\x6a\x42\x64\x4f\x97\x1c" - "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48" - "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1" - "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46" - "\xe4\x81\x84\x95\x36\x59\x7a\x6b" - "\xaa\xb3\x60\xad\xce\x9f\x9f\x28" - "\xe0\x01\x75\x22\xc4\x4e\xa9\x62" - "\x5c\x62\x0d\x00\xcb\x13\xe8\x43" - "\x72\xd4\x2d\x53\x46\xb5\xd1\x16" - "\x22\x18\xdf\x34\x33\xf5\xd6\x1c" - "\xb8\x79\x78\x97\x94\xff\x72\x13" - "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6" - "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4" - "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f" - "\x2d\x14\x8e\x24\x61\x2c\xe1\x17" - "\xcc\xce\x51\x0c\x19\x8a\x82\x30" - "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd" - "\xb7\xeb\xfa\xfd\x27\x51\xde\x85" - "\x1e\x86\x53\x11\x53\x94\x00\xee" - "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11" - "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62" - "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1" - "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a" - "\x9e\xfa\x31\x18\x45\x3c\x21\x33" - "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1" - "\x03\xad\x1b\x48\xd4\x67\x27\xf0" - "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7" - "\xdd\x2b\x01\x39\x04\x5a\x58\x7a" - "\xf7\x11\x90\xec\xbd\x51\x5c\x32" - "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6" - "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d" - "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4" - "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3" - "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29" - "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7" - "\x74\x3f\x7d\x58\x88\x75\xde\x3e", - .ilen = 512, - .result = "\x05\x11\xb7\x18\xab\xc6\x2d\xac" - "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c" - "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8" - "\x50\x38\x1f\x71\x49\xb6\x57\xd6" - "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90" - "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6" - "\xad\x1e\x9e\x20\x5f\x38\xbe\x04" - "\xda\x10\x8e\xed\xa2\xa4\x87\xab" - "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c" - "\xc9\xac\x42\x31\x95\x7c\xc9\x04" - "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6" - "\x15\xd7\x3f\x4f\x2f\x66\x69\x03" - "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65" - "\x4c\x96\x12\xed\x7c\x92\x03\x01" - "\x6f\xbc\x35\x93\xac\xf1\x27\xf1" - "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50" - "\x89\xa4\x8e\x66\x44\x85\xcc\xfd" - "\x33\x14\x70\xe3\x96\xb2\xc3\xd3" - "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5" - "\x2d\x64\x75\xdd\xb4\x54\xe6\x74" - "\x8c\xd3\x9d\x9e\x86\xab\x51\x53" - "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40" - "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5" - "\x76\x12\x73\x44\x1a\x56\xd7\x72" - "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda" - "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd" - "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60" - "\x1a\xe2\x70\x85\x58\xc2\x1b\x09" - "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9" - "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8" - "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8" - "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10" - "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1" - "\x90\x3e\x76\x4a\x74\xa4\x21\x2c" - "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e" - "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f" - "\x8d\x23\x31\x74\x84\xeb\x88\x6e" - "\xcc\xb9\xbc\x22\x83\x19\x07\x22" - "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78" - "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5" - "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41" - "\x3c\xce\x8f\x42\x60\x71\xa7\x75" - "\x08\x40\x65\x8a\x82\xbf\xf5\x43" - "\x71\x96\xa9\x4d\x44\x8a\x20\xbe" - "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65" - "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9" - "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4" - "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a" - "\x62\x73\x65\xfd\x46\x63\x25\x3d" - "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf" - "\x24\xf3\xb4\xac\x64\xba\xdf\x4b" - "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7" - "\xc5\x68\x77\x84\x32\x2b\xcc\x85" - "\x74\x96\xf0\x12\x77\x61\xb9\xeb" - "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8" - "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24" - "\xda\x39\x87\x45\xc0\x2b\xbb\x01" - "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce" - "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6" - "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32" - "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45" - "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6" - "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4" - "\x21\xc4\xc2\x75\x67\x89\x37\x0a", - .rlen = 512, - } -}; - -static struct cipher_testvec aes_xts_enc_tv_template[] = { - /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */ - { /* XTS-AES 1 */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 32, - .result = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec" - "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92" - "\xcd\x43\xd2\xf5\x95\x98\xed\x85" - "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e", - .rlen = 32, - }, { /* XTS-AES 2 */ - .key = "\x11\x11\x11\x11\x11\x11\x11\x11" - "\x11\x11\x11\x11\x11\x11\x11\x11" - "\x22\x22\x22\x22\x22\x22\x22\x22" - "\x22\x22\x22\x22\x22\x22\x22\x22", - .klen = 32, - .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44", - .ilen = 32, - .result = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e" - "\x39\x33\x40\x38\xac\xef\x83\x8b" - "\xfb\x18\x6f\xff\x74\x80\xad\xc4" - "\x28\x93\x82\xec\xd6\xd3\x94\xf0", - .rlen = 32, - }, { /* XTS-AES 3 */ - .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8" - "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0" - "\x22\x22\x22\x22\x22\x22\x22\x22" - "\x22\x22\x22\x22\x22\x22\x22\x22", - .klen = 32, - .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44", - .ilen = 32, - .result = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a" - "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2" - "\x92\xdf\x4c\x04\x7e\x0b\x21\x53" - "\x21\x86\xa5\x97\x1a\x22\x7a\x89", - .rlen = 32, - }, { /* XTS-AES 4 */ - .key = "\x27\x18\x28\x18\x28\x45\x90\x45" - "\x23\x53\x60\x28\x74\x71\x35\x26" - "\x31\x41\x59\x26\x53\x58\x97\x93" - "\x23\x84\x62\x64\x33\x83\x27\x95", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21\x22\x23\x24\x25\x26\x27" - "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" - "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" - "\x40\x41\x42\x43\x44\x45\x46\x47" - "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" - "\x50\x51\x52\x53\x54\x55\x56\x57" - "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" - "\x60\x61\x62\x63\x64\x65\x66\x67" - "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" - "\x70\x71\x72\x73\x74\x75\x76\x77" - "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87" - "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" - "\x90\x91\x92\x93\x94\x95\x96\x97" - "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" - "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" - "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" - "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" - "\xe8\xe9\xea\xeb\xec\xed\xee\xef" - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" - "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" - "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21\x22\x23\x24\x25\x26\x27" - "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" - "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" - "\x40\x41\x42\x43\x44\x45\x46\x47" - "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" - "\x50\x51\x52\x53\x54\x55\x56\x57" - "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" - "\x60\x61\x62\x63\x64\x65\x66\x67" - "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" - "\x70\x71\x72\x73\x74\x75\x76\x77" - "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87" - "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" - "\x90\x91\x92\x93\x94\x95\x96\x97" - "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" - "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" - "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" - "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" - "\xe8\xe9\xea\xeb\xec\xed\xee\xef" - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" - "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", - .ilen = 512, - .result = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76" - "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2" - "\xa9\x6e\x4b\xbe\x32\x08\xff\x25" - "\x28\x7d\xd3\x81\x96\x16\xe8\x9c" - "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f" - "\x83\x33\xd8\xfa\x7f\x56\x00\x00" - "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad" - "\x40\xe7\x36\xdd\xb4\xd3\x54\x12" - "\x32\x80\x63\xfd\x2a\xab\x53\xe5" - "\xea\x1e\x0a\x9f\x33\x25\x00\xa5" - "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc" - "\x51\x2c\x88\x66\xc7\xe8\x60\xce" - "\x93\xfd\xf1\x66\xa2\x49\x12\xb4" - "\x22\x97\x61\x46\xae\x20\xce\x84" - "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a" - "\xae\xf2\x0c\x0d\x61\xad\x02\x65" - "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89" - "\x52\xc6\x51\xd3\x31\x74\xbe\x51" - "\xa1\x0c\x42\x11\x10\xe6\xd8\x15" - "\x88\xed\xe8\x21\x03\xa2\x52\xd8" - "\xa7\x50\xe8\x76\x8d\xef\xff\xed" - "\x91\x22\x81\x0a\xae\xb9\x9f\x91" - "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e" - "\x51\xbc\xb0\x82\x35\xa6\xf4\x34" - "\x13\x32\xe4\xca\x60\x48\x2a\x4b" - "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5" - "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4" - "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c" - "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd" - "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3" - "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f" - "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e" - "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91" - "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19" - "\x7c\x4e\x5b\x03\x39\x36\x97\xe1" - "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc" - "\x1e\x08\x29\x85\x16\xe2\xc9\xed" - "\x03\xff\x3c\x1b\x78\x60\xf6\xde" - "\x76\xd4\xce\xcd\x94\xc8\x11\x98" - "\x55\xef\x52\x97\xca\x67\xe9\xf3" - "\xe7\xff\x72\xb1\xe9\x97\x85\xca" - "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6" - "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc" - "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44" - "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0" - "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95" - "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4" - "\x99\x02\x7a\x78\x57\x2a\xee\xbd" - "\x74\xd2\x0c\xc3\x98\x81\xc2\x13" - "\xee\x77\x0b\x10\x10\xe4\xbe\xa7" - "\x18\x84\x69\x77\xae\x11\x9f\x7a" - "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52" - "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a" - "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38" - "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e" - "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e" - "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad" - "\x15\xb4\xaa\x5b\x65\x50\x16\xa8" - "\x44\x92\x77\xdb\xd4\x77\xef\x2c" - "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d" - "\xeb\x4a\x42\x7d\x19\x23\xce\x3f" - "\xf2\x62\x73\x57\x79\xa4\x18\xf2" - "\x0a\x28\x2d\xf9\x20\x14\x7b\xea" - "\xbe\x42\x1e\xe5\x31\x9d\x05\x68", - .rlen = 512, - } -}; - -static struct cipher_testvec aes_xts_dec_tv_template[] = { - /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */ - { /* XTS-AES 1 */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec" - "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92" - "\xcd\x43\xd2\xf5\x95\x98\xed\x85" - "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e", - .ilen = 32, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .rlen = 32, - }, { /* XTS-AES 2 */ - .key = "\x11\x11\x11\x11\x11\x11\x11\x11" - "\x11\x11\x11\x11\x11\x11\x11\x11" - "\x22\x22\x22\x22\x22\x22\x22\x22" - "\x22\x22\x22\x22\x22\x22\x22\x22", - .klen = 32, - .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e" - "\x39\x33\x40\x38\xac\xef\x83\x8b" - "\xfb\x18\x6f\xff\x74\x80\xad\xc4" - "\x28\x93\x82\xec\xd6\xd3\x94\xf0", - .ilen = 32, - .result = "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44", - .rlen = 32, - }, { /* XTS-AES 3 */ - .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8" - "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0" - "\x22\x22\x22\x22\x22\x22\x22\x22" - "\x22\x22\x22\x22\x22\x22\x22\x22", - .klen = 32, - .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a" - "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2" - "\x92\xdf\x4c\x04\x7e\x0b\x21\x53" - "\x21\x86\xa5\x97\x1a\x22\x7a\x89", - .ilen = 32, - .result = "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44" - "\x44\x44\x44\x44\x44\x44\x44\x44", - .rlen = 32, - }, { /* XTS-AES 4 */ - .key = "\x27\x18\x28\x18\x28\x45\x90\x45" - "\x23\x53\x60\x28\x74\x71\x35\x26" - "\x31\x41\x59\x26\x53\x58\x97\x93" - "\x23\x84\x62\x64\x33\x83\x27\x95", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76" - "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2" - "\xa9\x6e\x4b\xbe\x32\x08\xff\x25" - "\x28\x7d\xd3\x81\x96\x16\xe8\x9c" - "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f" - "\x83\x33\xd8\xfa\x7f\x56\x00\x00" - "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad" - "\x40\xe7\x36\xdd\xb4\xd3\x54\x12" - "\x32\x80\x63\xfd\x2a\xab\x53\xe5" - "\xea\x1e\x0a\x9f\x33\x25\x00\xa5" - "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc" - "\x51\x2c\x88\x66\xc7\xe8\x60\xce" - "\x93\xfd\xf1\x66\xa2\x49\x12\xb4" - "\x22\x97\x61\x46\xae\x20\xce\x84" - "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a" - "\xae\xf2\x0c\x0d\x61\xad\x02\x65" - "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89" - "\x52\xc6\x51\xd3\x31\x74\xbe\x51" - "\xa1\x0c\x42\x11\x10\xe6\xd8\x15" - "\x88\xed\xe8\x21\x03\xa2\x52\xd8" - "\xa7\x50\xe8\x76\x8d\xef\xff\xed" - "\x91\x22\x81\x0a\xae\xb9\x9f\x91" - "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e" - "\x51\xbc\xb0\x82\x35\xa6\xf4\x34" - "\x13\x32\xe4\xca\x60\x48\x2a\x4b" - "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5" - "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4" - "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c" - "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd" - "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3" - "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f" - "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e" - "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91" - "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19" - "\x7c\x4e\x5b\x03\x39\x36\x97\xe1" - "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc" - "\x1e\x08\x29\x85\x16\xe2\xc9\xed" - "\x03\xff\x3c\x1b\x78\x60\xf6\xde" - "\x76\xd4\xce\xcd\x94\xc8\x11\x98" - "\x55\xef\x52\x97\xca\x67\xe9\xf3" - "\xe7\xff\x72\xb1\xe9\x97\x85\xca" - "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6" - "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc" - "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44" - "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0" - "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95" - "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4" - "\x99\x02\x7a\x78\x57\x2a\xee\xbd" - "\x74\xd2\x0c\xc3\x98\x81\xc2\x13" - "\xee\x77\x0b\x10\x10\xe4\xbe\xa7" - "\x18\x84\x69\x77\xae\x11\x9f\x7a" - "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52" - "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a" - "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38" - "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e" - "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e" - "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad" - "\x15\xb4\xaa\x5b\x65\x50\x16\xa8" - "\x44\x92\x77\xdb\xd4\x77\xef\x2c" - "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d" - "\xeb\x4a\x42\x7d\x19\x23\xce\x3f" - "\xf2\x62\x73\x57\x79\xa4\x18\xf2" - "\x0a\x28\x2d\xf9\x20\x14\x7b\xea" - "\xbe\x42\x1e\xe5\x31\x9d\x05\x68", - .ilen = 512, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21\x22\x23\x24\x25\x26\x27" - "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" - "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" - "\x40\x41\x42\x43\x44\x45\x46\x47" - "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" - "\x50\x51\x52\x53\x54\x55\x56\x57" - "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" - "\x60\x61\x62\x63\x64\x65\x66\x67" - "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" - "\x70\x71\x72\x73\x74\x75\x76\x77" - "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87" - "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" - "\x90\x91\x92\x93\x94\x95\x96\x97" - "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" - "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" - "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" - "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" - "\xe8\xe9\xea\xeb\xec\xed\xee\xef" - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" - "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" - "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21\x22\x23\x24\x25\x26\x27" - "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" - "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" - "\x40\x41\x42\x43\x44\x45\x46\x47" - "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" - "\x50\x51\x52\x53\x54\x55\x56\x57" - "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" - "\x60\x61\x62\x63\x64\x65\x66\x67" - "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" - "\x70\x71\x72\x73\x74\x75\x76\x77" - "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87" - "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" - "\x90\x91\x92\x93\x94\x95\x96\x97" - "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" - "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" - "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" - "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" - "\xe8\xe9\xea\xeb\xec\xed\xee\xef" - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" - "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", - .rlen = 512, - } -}; - - -static struct cipher_testvec aes_ctr_enc_tv_template[] = { - { /* From RFC 3686 */ - .key = "\xae\x68\x52\xf8\x12\x10\x67\xcc" - "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e" - "\x00\x00\x00\x30", - .klen = 20, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "Single block msg", - .ilen = 16, - .result = "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79" - "\x2d\x61\x75\xa3\x26\x13\x11\xb8", - .rlen = 16, - }, { - .key = "\x7e\x24\x06\x78\x17\xfa\xe0\xd7" - "\x43\xd6\xce\x1f\x32\x53\x91\x63" - "\x00\x6c\xb6\xdb", - .klen = 20, - .iv = "\xc0\x54\x3b\x59\xda\x48\xd9\x0b", - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .ilen = 32, - .result = "\x51\x04\xa1\x06\x16\x8a\x72\xd9" - "\x79\x0d\x41\xee\x8e\xda\xd3\x88" - "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8" - "\xfc\xe6\x30\xdf\x91\x41\xbe\x28", - .rlen = 32, - }, { - .key = "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79" - "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed" - "\x86\x3d\x06\xcc\xfd\xb7\x85\x15" - "\x00\x00\x00\x48", - .klen = 28, - .iv = "\x36\x73\x3c\x14\x7d\x6d\x93\xcb", - .input = "Single block msg", - .ilen = 16, - .result = "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8" - "\x4e\x79\x35\xa0\x03\xcb\xe9\x28", - .rlen = 16, - }, { - .key = "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c" - "\x19\xe7\x34\x08\x19\xe0\xf6\x9c" - "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a" - "\x00\x96\xb0\x3b", - .klen = 28, - .iv = "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d", - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .ilen = 32, - .result = "\x45\x32\x43\xfc\x60\x9b\x23\x32" - "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f" - "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c" - "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00", - .rlen = 32, - }, { - .key = "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f" - "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c" - "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3" - "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04" - "\x00\x00\x00\x60", - .klen = 36, - .iv = "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2", - .input = "Single block msg", - .ilen = 16, - .result = "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7" - "\x56\x08\x63\xdc\x71\xe3\xe0\xc0", - .rlen = 16, - }, { - .key = "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb" - "\x07\x96\x36\x58\x79\xef\xf8\x86" - "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74" - "\x4b\x50\x59\x0c\x87\xa2\x38\x84" - "\x00\xfa\xac\x24", - .klen = 36, - .iv = "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75", - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .ilen = 32, - .result = "\xf0\x5e\x23\x1b\x38\x94\x61\x2c" - "\x49\xee\x00\x0b\x80\x4e\xb2\xa9" - "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a" - "\x55\x30\x83\x1d\x93\x44\xaf\x1c", - .rlen = 32, - }, { - // generated using Crypto++ - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x00\x00\x00\x00", - .klen = 32 + 4, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = - "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21\x22\x23\x24\x25\x26\x27" - "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" - "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" - "\x40\x41\x42\x43\x44\x45\x46\x47" - "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" - "\x50\x51\x52\x53\x54\x55\x56\x57" - "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" - "\x60\x61\x62\x63\x64\x65\x66\x67" - "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" - "\x70\x71\x72\x73\x74\x75\x76\x77" - "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87" - "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" - "\x90\x91\x92\x93\x94\x95\x96\x97" - "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" - "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" - "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" - "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" - "\xe8\xe9\xea\xeb\xec\xed\xee\xef" - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" - "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" - "\x00\x03\x06\x09\x0c\x0f\x12\x15" - "\x18\x1b\x1e\x21\x24\x27\x2a\x2d" - "\x30\x33\x36\x39\x3c\x3f\x42\x45" - "\x48\x4b\x4e\x51\x54\x57\x5a\x5d" - "\x60\x63\x66\x69\x6c\x6f\x72\x75" - "\x78\x7b\x7e\x81\x84\x87\x8a\x8d" - "\x90\x93\x96\x99\x9c\x9f\xa2\xa5" - "\xa8\xab\xae\xb1\xb4\xb7\xba\xbd" - "\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5" - "\xd8\xdb\xde\xe1\xe4\xe7\xea\xed" - "\xf0\xf3\xf6\xf9\xfc\xff\x02\x05" - "\x08\x0b\x0e\x11\x14\x17\x1a\x1d" - "\x20\x23\x26\x29\x2c\x2f\x32\x35" - "\x38\x3b\x3e\x41\x44\x47\x4a\x4d" - "\x50\x53\x56\x59\x5c\x5f\x62\x65" - "\x68\x6b\x6e\x71\x74\x77\x7a\x7d" - "\x80\x83\x86\x89\x8c\x8f\x92\x95" - "\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad" - "\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5" - "\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd" - "\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5" - "\xf8\xfb\xfe\x01\x04\x07\x0a\x0d" - "\x10\x13\x16\x19\x1c\x1f\x22\x25" - "\x28\x2b\x2e\x31\x34\x37\x3a\x3d" - "\x40\x43\x46\x49\x4c\x4f\x52\x55" - "\x58\x5b\x5e\x61\x64\x67\x6a\x6d" - "\x70\x73\x76\x79\x7c\x7f\x82\x85" - "\x88\x8b\x8e\x91\x94\x97\x9a\x9d" - "\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5" - "\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd" - "\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5" - "\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd" - "\x00\x05\x0a\x0f\x14\x19\x1e\x23" - "\x28\x2d\x32\x37\x3c\x41\x46\x4b" - "\x50\x55\x5a\x5f\x64\x69\x6e\x73" - "\x78\x7d\x82\x87\x8c\x91\x96\x9b" - "\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3" - "\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb" - "\xf0\xf5\xfa\xff\x04\x09\x0e\x13" - "\x18\x1d\x22\x27\x2c\x31\x36\x3b" - "\x40\x45\x4a\x4f\x54\x59\x5e\x63" - "\x68\x6d\x72\x77\x7c\x81\x86\x8b" - "\x90\x95\x9a\x9f\xa4\xa9\xae\xb3" - "\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb" - "\xe0\xe5\xea\xef\xf4\xf9\xfe\x03" - "\x08\x0d\x12\x17\x1c\x21\x26\x2b" - "\x30\x35\x3a\x3f\x44\x49\x4e\x53" - "\x58\x5d\x62\x67\x6c\x71\x76\x7b" - "\x80\x85\x8a\x8f\x94\x99\x9e\xa3" - "\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb" - "\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3" - "\xf8\xfd\x02\x07\x0c\x11\x16\x1b" - "\x20\x25\x2a\x2f\x34\x39\x3e\x43" - "\x48\x4d\x52\x57\x5c\x61\x66\x6b" - "\x70\x75\x7a\x7f\x84\x89\x8e\x93" - "\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb" - "\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3" - "\xe8\xed\xf2\xf7\xfc\x01\x06\x0b" - "\x10\x15\x1a\x1f\x24\x29\x2e\x33" - "\x38\x3d\x42\x47\x4c\x51\x56\x5b" - "\x60\x65\x6a\x6f\x74\x79\x7e\x83" - "\x88\x8d\x92\x97\x9c\xa1\xa6\xab" - "\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3" - "\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb" - "\x00\x07\x0e\x15\x1c\x23\x2a\x31" - "\x38\x3f\x46\x4d\x54\x5b\x62\x69" - "\x70\x77\x7e\x85\x8c\x93\x9a\xa1" - "\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9" - "\xe0\xe7\xee\xf5\xfc\x03\x0a\x11" - "\x18\x1f\x26\x2d\x34\x3b\x42\x49" - "\x50\x57\x5e\x65\x6c\x73\x7a\x81" - "\x88\x8f\x96\x9d\xa4\xab\xb2\xb9" - "\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1" - "\xf8\xff\x06\x0d\x14\x1b\x22\x29" - "\x30\x37\x3e\x45\x4c\x53\x5a\x61" - "\x68\x6f\x76\x7d\x84\x8b\x92\x99" - "\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1" - "\xd8\xdf\xe6\xed\xf4\xfb\x02\x09" - "\x10\x17\x1e\x25\x2c\x33\x3a\x41" - "\x48\x4f\x56\x5d\x64\x6b\x72\x79" - "\x80\x87\x8e\x95\x9c\xa3\xaa\xb1" - "\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9" - "\xf0\xf7\xfe\x05\x0c\x13\x1a\x21" - "\x28\x2f\x36\x3d\x44\x4b\x52\x59" - "\x60\x67\x6e\x75\x7c\x83\x8a\x91" - "\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9" - "\xd0\xd7\xde\xe5\xec\xf3\xfa\x01" - "\x08\x0f\x16\x1d\x24\x2b\x32\x39" - "\x40\x47\x4e\x55\x5c\x63\x6a\x71" - "\x78\x7f\x86\x8d\x94\x9b\xa2\xa9" - "\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1" - "\xe8\xef\xf6\xfd\x04\x0b\x12\x19" - "\x20\x27\x2e\x35\x3c\x43\x4a\x51" - "\x58\x5f\x66\x6d\x74\x7b\x82\x89" - "\x90\x97\x9e\xa5\xac\xb3\xba\xc1" - "\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9" - "\x00\x09\x12\x1b\x24\x2d\x36\x3f" - "\x48\x51\x5a\x63\x6c\x75\x7e\x87" - "\x90\x99\xa2\xab\xb4\xbd\xc6\xcf" - "\xd8\xe1\xea\xf3\xfc\x05\x0e\x17" - "\x20\x29\x32\x3b\x44\x4d\x56\x5f" - "\x68\x71\x7a\x83\x8c\x95\x9e\xa7" - "\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef" - "\xf8\x01\x0a\x13\x1c\x25\x2e\x37" - "\x40\x49\x52\x5b\x64\x6d\x76\x7f" - "\x88\x91\x9a\xa3\xac\xb5\xbe\xc7" - "\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f" - "\x18\x21\x2a\x33\x3c\x45\x4e\x57" - "\x60\x69\x72\x7b\x84\x8d\x96\x9f" - "\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7" - "\xf0\xf9\x02\x0b\x14\x1d\x26\x2f" - "\x38\x41\x4a\x53\x5c\x65\x6e\x77" - "\x80\x89\x92\x9b\xa4\xad\xb6\xbf" - "\xc8\xd1\xda\xe3\xec\xf5\xfe\x07" - "\x10\x19\x22\x2b\x34\x3d\x46\x4f" - "\x58\x61\x6a\x73\x7c\x85\x8e\x97" - "\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf" - "\xe8\xf1\xfa\x03\x0c\x15\x1e\x27" - "\x30\x39\x42\x4b\x54\x5d\x66\x6f" - "\x78\x81\x8a\x93\x9c\xa5\xae\xb7" - "\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff" - "\x08\x11\x1a\x23\x2c\x35\x3e\x47" - "\x50\x59\x62\x6b\x74\x7d\x86\x8f" - "\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7" - "\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f" - "\x28\x31\x3a\x43\x4c\x55\x5e\x67" - "\x70\x79\x82\x8b\x94\x9d\xa6\xaf" - "\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7" - "\x00\x0b\x16\x21\x2c\x37\x42\x4d" - "\x58\x63\x6e\x79\x84\x8f\x9a\xa5" - "\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd" - "\x08\x13\x1e\x29\x34\x3f\x4a\x55" - "\x60\x6b\x76\x81\x8c\x97\xa2\xad" - "\xb8\xc3\xce\xd9\xe4\xef\xfa\x05" - "\x10\x1b\x26\x31\x3c\x47\x52\x5d" - "\x68\x73\x7e\x89\x94\x9f\xaa\xb5" - "\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d" - "\x18\x23\x2e\x39\x44\x4f\x5a\x65" - "\x70\x7b\x86\x91\x9c\xa7\xb2\xbd" - "\xc8\xd3\xde\xe9\xf4\xff\x0a\x15" - "\x20\x2b\x36\x41\x4c\x57\x62\x6d" - "\x78\x83\x8e\x99\xa4\xaf\xba\xc5" - "\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d" - "\x28\x33\x3e\x49\x54\x5f\x6a\x75" - "\x80\x8b\x96\xa1\xac\xb7\xc2\xcd" - "\xd8\xe3\xee\xf9\x04\x0f\x1a\x25" - "\x30\x3b\x46\x51\x5c\x67\x72\x7d" - "\x88\x93\x9e\xa9\xb4\xbf\xca\xd5" - "\xe0\xeb\xf6\x01\x0c\x17\x22\x2d" - "\x38\x43\x4e\x59\x64\x6f\x7a\x85" - "\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd" - "\xe8\xf3\xfe\x09\x14\x1f\x2a\x35" - "\x40\x4b\x56\x61\x6c\x77\x82\x8d" - "\x98\xa3\xae\xb9\xc4\xcf\xda\xe5" - "\xf0\xfb\x06\x11\x1c\x27\x32\x3d" - "\x48\x53\x5e\x69\x74\x7f\x8a\x95" - "\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed" - "\xf8\x03\x0e\x19\x24\x2f\x3a\x45" - "\x50\x5b\x66\x71\x7c\x87\x92\x9d" - "\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5" - "\x00\x0d\x1a\x27\x34\x41\x4e\x5b" - "\x68\x75\x82\x8f\x9c\xa9\xb6\xc3" - "\xd0\xdd\xea\xf7\x04\x11\x1e\x2b" - "\x38\x45\x52\x5f\x6c\x79\x86\x93" - "\xa0\xad\xba\xc7\xd4\xe1\xee\xfb" - "\x08\x15\x22\x2f\x3c\x49\x56\x63" - "\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb" - "\xd8\xe5\xf2\xff\x0c\x19\x26\x33" - "\x40\x4d\x5a\x67\x74\x81\x8e\x9b" - "\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03" - "\x10\x1d\x2a\x37\x44\x51\x5e\x6b" - "\x78\x85\x92\x9f\xac\xb9\xc6\xd3" - "\xe0\xed\xfa\x07\x14\x21\x2e\x3b" - "\x48\x55\x62\x6f\x7c\x89\x96\xa3" - "\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b" - "\x18\x25\x32\x3f\x4c\x59\x66\x73" - "\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb" - "\xe8\xf5\x02\x0f\x1c\x29\x36\x43" - "\x50\x5d\x6a\x77\x84\x91\x9e\xab" - "\xb8\xc5\xd2\xdf\xec\xf9\x06\x13" - "\x20\x2d\x3a\x47\x54\x61\x6e\x7b" - "\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3" - "\xf0\xfd\x0a\x17\x24\x31\x3e\x4b" - "\x58\x65\x72\x7f\x8c\x99\xa6\xb3" - "\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b" - "\x28\x35\x42\x4f\x5c\x69\x76\x83" - "\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb" - "\xf8\x05\x12\x1f\x2c\x39\x46\x53" - "\x60\x6d\x7a\x87\x94\xa1\xae\xbb" - "\xc8\xd5\xe2\xef\xfc\x09\x16\x23" - "\x30\x3d\x4a\x57\x64\x71\x7e\x8b" - "\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3" - "\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69" - "\x78\x87\x96\xa5\xb4\xc3\xd2\xe1" - "\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59" - "\x68\x77\x86\x95\xa4\xb3\xc2\xd1" - "\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49" - "\x58\x67\x76\x85\x94\xa3\xb2\xc1" - "\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39" - "\x48\x57\x66\x75\x84\x93\xa2\xb1" - "\xc0\xcf\xde\xed\xfc\x0b\x1a\x29" - "\x38\x47\x56\x65\x74\x83\x92\xa1" - "\xb0\xbf\xce\xdd\xec\xfb\x0a\x19" - "\x28\x37\x46\x55\x64\x73\x82\x91" - "\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09" - "\x18\x27\x36\x45\x54\x63\x72\x81" - "\x90\x9f\xae\xbd\xcc\xdb\xea\xf9" - "\x08\x17\x26\x35\x44\x53\x62\x71" - "\x80\x8f\x9e\xad\xbc\xcb\xda\xe9" - "\xf8\x07\x16\x25\x34\x43\x52\x61" - "\x70\x7f\x8e\x9d\xac\xbb\xca\xd9" - "\xe8\xf7\x06\x15\x24\x33\x42\x51" - "\x60\x6f\x7e\x8d\x9c\xab\xba\xc9" - "\xd8\xe7\xf6\x05\x14\x23\x32\x41" - "\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9" - "\xc8\xd7\xe6\xf5\x04\x13\x22\x31" - "\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9" - "\xb8\xc7\xd6\xe5\xf4\x03\x12\x21" - "\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99" - "\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11" - "\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89" - "\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01" - "\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79" - "\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff" - "\x10\x21\x32\x43\x54\x65\x76\x87" - "\x98\xa9\xba\xcb\xdc\xed\xfe\x0f" - "\x20\x31\x42\x53\x64\x75\x86\x97" - "\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f" - "\x30\x41\x52\x63\x74\x85\x96\xa7" - "\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f" - "\x40\x51\x62\x73\x84\x95\xa6\xb7" - "\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f" - "\x50\x61\x72\x83\x94\xa5\xb6\xc7" - "\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f" - "\x60\x71\x82\x93\xa4\xb5\xc6\xd7" - "\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f" - "\x70\x81\x92\xa3\xb4\xc5\xd6\xe7" - "\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f" - "\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7" - "\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f" - "\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07" - "\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f" - "\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17" - "\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f" - "\xb0\xc1\xd2\xe3\xf4\x05\x16\x27" - "\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf" - "\xc0\xd1\xe2\xf3\x04\x15\x26\x37" - "\x48\x59\x6a\x7b\x8c\x9d\xae\xbf" - "\xd0\xe1\xf2\x03\x14\x25\x36\x47" - "\x58\x69\x7a\x8b\x9c\xad\xbe\xcf" - "\xe0\xf1\x02\x13\x24\x35\x46\x57" - "\x68\x79\x8a\x9b\xac\xbd\xce\xdf" - "\xf0\x01\x12\x23\x34\x45\x56\x67" - "\x78\x89\x9a\xab\xbc\xcd\xde\xef" - "\x00\x13\x26\x39\x4c\x5f\x72\x85" - "\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d" - "\x30\x43\x56\x69\x7c\x8f\xa2\xb5" - "\xc8\xdb\xee\x01\x14\x27\x3a\x4d" - "\x60\x73\x86\x99\xac\xbf\xd2\xe5" - "\xf8\x0b\x1e\x31\x44\x57\x6a\x7d" - "\x90\xa3\xb6\xc9\xdc\xef\x02\x15" - "\x28\x3b\x4e\x61\x74\x87\x9a\xad" - "\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45" - "\x58\x6b\x7e\x91\xa4\xb7\xca\xdd" - "\xf0\x03\x16\x29\x3c\x4f\x62\x75" - "\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d" - "\x20\x33\x46\x59\x6c\x7f\x92\xa5" - "\xb8\xcb\xde\xf1\x04\x17\x2a\x3d" - "\x50\x63\x76\x89\x9c\xaf\xc2\xd5" - "\xe8\xfb\x0e\x21\x34\x47\x5a\x6d" - "\x80\x93\xa6\xb9\xcc\xdf\xf2\x05" - "\x18\x2b\x3e\x51\x64\x77\x8a\x9d" - "\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35" - "\x48\x5b\x6e\x81\x94\xa7\xba\xcd" - "\xe0\xf3\x06\x19\x2c\x3f\x52\x65" - "\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd" - "\x10\x23\x36\x49\x5c\x6f\x82\x95" - "\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d" - "\x40\x53\x66\x79\x8c\x9f\xb2\xc5" - "\xd8\xeb\xfe\x11\x24\x37\x4a\x5d" - "\x70\x83\x96\xa9\xbc\xcf\xe2\xf5" - "\x08\x1b\x2e\x41\x54\x67\x7a\x8d" - "\xa0\xb3\xc6\xd9\xec\xff\x12\x25" - "\x38\x4b\x5e\x71\x84\x97\xaa\xbd" - "\xd0\xe3\xf6\x09\x1c\x2f\x42\x55" - "\x68\x7b\x8e\xa1\xb4\xc7\xda\xed" - "\x00\x15\x2a\x3f\x54\x69\x7e\x93" - "\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b" - "\x50\x65\x7a\x8f\xa4\xb9\xce\xe3" - "\xf8\x0d\x22\x37\x4c\x61\x76\x8b" - "\xa0\xb5\xca\xdf\xf4\x09\x1e\x33" - "\x48\x5d\x72\x87\x9c\xb1\xc6\xdb" - "\xf0\x05\x1a\x2f\x44\x59\x6e\x83" - "\x98\xad\xc2\xd7\xec\x01\x16\x2b" - "\x40\x55\x6a\x7f\x94\xa9\xbe\xd3" - "\xe8\xfd\x12\x27\x3c\x51\x66\x7b" - "\x90\xa5\xba\xcf\xe4\xf9\x0e\x23" - "\x38\x4d\x62\x77\x8c\xa1\xb6\xcb" - "\xe0\xf5\x0a\x1f\x34\x49\x5e\x73" - "\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b" - "\x30\x45\x5a\x6f\x84\x99\xae\xc3" - "\xd8\xed\x02\x17\x2c\x41\x56\x6b" - "\x80\x95\xaa\xbf\xd4\xe9\xfe\x13" - "\x28\x3d\x52\x67\x7c\x91\xa6\xbb" - "\xd0\xe5\xfa\x0f\x24\x39\x4e\x63" - "\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b" - "\x20\x35\x4a\x5f\x74\x89\x9e\xb3" - "\xc8\xdd\xf2\x07\x1c\x31\x46\x5b" - "\x70\x85\x9a\xaf\xc4\xd9\xee\x03" - "\x18\x2d\x42\x57\x6c\x81\x96\xab" - "\xc0\xd5\xea\xff\x14\x29\x3e\x53" - "\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb" - "\x10\x25\x3a\x4f\x64\x79\x8e\xa3" - "\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b" - "\x60\x75\x8a\x9f\xb4\xc9\xde\xf3" - "\x08\x1d\x32\x47\x5c\x71\x86\x9b" - "\xb0\xc5\xda\xef\x04\x19\x2e\x43" - "\x58\x6d\x82\x97\xac\xc1\xd6\xeb" - "\x00\x17\x2e\x45\x5c\x73\x8a\xa1" - "\xb8\xcf\xe6\xfd\x14\x2b\x42\x59" - "\x70\x87\x9e\xb5\xcc\xe3\xfa\x11" - "\x28\x3f\x56\x6d\x84\x9b\xb2\xc9" - "\xe0\xf7\x0e\x25\x3c\x53\x6a\x81" - "\x98\xaf\xc6\xdd\xf4\x0b\x22\x39" - "\x50\x67\x7e\x95\xac\xc3\xda\xf1" - "\x08\x1f\x36\x4d\x64\x7b\x92\xa9" - "\xc0\xd7\xee\x05\x1c\x33\x4a\x61" - "\x78\x8f\xa6\xbd\xd4\xeb\x02\x19" - "\x30\x47\x5e\x75\x8c\xa3\xba\xd1" - "\xe8\xff\x16\x2d\x44\x5b\x72\x89" - "\xa0\xb7\xce\xe5\xfc\x13\x2a\x41" - "\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9" - "\x10\x27\x3e\x55\x6c\x83\x9a\xb1" - "\xc8\xdf\xf6\x0d\x24\x3b\x52\x69" - "\x80\x97\xae\xc5\xdc\xf3\x0a\x21" - "\x38\x4f\x66\x7d\x94\xab\xc2\xd9" - "\xf0\x07\x1e\x35\x4c\x63\x7a\x91" - "\xa8\xbf\xd6\xed\x04\x1b\x32\x49" - "\x60\x77\x8e\xa5\xbc\xd3\xea\x01" - "\x18\x2f\x46\x5d\x74\x8b\xa2\xb9" - "\xd0\xe7\xfe\x15\x2c\x43\x5a\x71" - "\x88\x9f\xb6\xcd\xe4\xfb\x12\x29" - "\x40\x57\x6e\x85\x9c\xb3\xca\xe1" - "\xf8\x0f\x26\x3d\x54\x6b\x82\x99" - "\xb0\xc7\xde\xf5\x0c\x23\x3a\x51" - "\x68\x7f\x96\xad\xc4\xdb\xf2\x09" - "\x20\x37\x4e\x65\x7c\x93\xaa\xc1" - "\xd8\xef\x06\x1d\x34\x4b\x62\x79" - "\x90\xa7\xbe\xd5\xec\x03\x1a\x31" - "\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9" - "\x00\x19\x32\x4b\x64\x7d\x96\xaf" - "\xc8\xe1\xfa\x13\x2c\x45\x5e\x77" - "\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f" - "\x58\x71\x8a\xa3\xbc\xd5\xee\x07" - "\x20\x39\x52\x6b\x84\x9d\xb6\xcf" - "\xe8\x01\x1a\x33\x4c\x65\x7e\x97" - "\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f" - "\x78\x91\xaa\xc3\xdc\xf5\x0e\x27" - "\x40\x59\x72\x8b\xa4\xbd\xd6\xef" - "\x08\x21\x3a\x53\x6c\x85\x9e\xb7" - "\xd0\xe9\x02\x1b\x34\x4d\x66\x7f" - "\x98\xb1\xca\xe3\xfc\x15\x2e\x47" - "\x60\x79\x92\xab\xc4\xdd\xf6\x0f" - "\x28\x41\x5a\x73\x8c\xa5\xbe\xd7" - "\xf0\x09\x22\x3b\x54\x6d\x86\x9f" - "\xb8\xd1\xea\x03\x1c\x35\x4e\x67" - "\x80\x99\xb2\xcb\xe4\xfd\x16\x2f" - "\x48\x61\x7a\x93\xac\xc5\xde\xf7" - "\x10\x29\x42\x5b\x74\x8d\xa6\xbf" - "\xd8\xf1\x0a\x23\x3c\x55\x6e\x87" - "\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f" - "\x68\x81\x9a\xb3\xcc\xe5\xfe\x17" - "\x30\x49\x62\x7b\x94\xad\xc6\xdf" - "\xf8\x11\x2a\x43\x5c\x75\x8e\xa7" - "\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f" - "\x88\xa1\xba\xd3\xec\x05\x1e\x37" - "\x50\x69\x82\x9b\xb4\xcd\xe6\xff" - "\x18\x31\x4a\x63\x7c\x95\xae\xc7" - "\xe0\xf9\x12\x2b\x44\x5d\x76\x8f" - "\xa8\xc1\xda\xf3\x0c\x25\x3e\x57" - "\x70\x89\xa2\xbb\xd4\xed\x06\x1f" - "\x38\x51\x6a\x83\x9c\xb5\xce\xe7" - "\x00\x1b\x36\x51\x6c\x87\xa2\xbd" - "\xd8\xf3\x0e\x29\x44\x5f\x7a\x95" - "\xb0\xcb\xe6\x01\x1c\x37\x52\x6d" - "\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45" - "\x60\x7b\x96\xb1\xcc\xe7\x02\x1d" - "\x38\x53\x6e\x89\xa4\xbf\xda\xf5" - "\x10\x2b\x46\x61\x7c\x97\xb2\xcd" - "\xe8\x03\x1e\x39\x54\x6f\x8a\xa5" - "\xc0\xdb\xf6\x11\x2c\x47\x62\x7d" - "\x98\xb3\xce\xe9\x04\x1f\x3a\x55" - "\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d" - "\x48\x63\x7e\x99\xb4\xcf\xea\x05" - "\x20\x3b\x56\x71\x8c\xa7\xc2\xdd" - "\xf8\x13\x2e\x49\x64\x7f\x9a\xb5" - "\xd0\xeb\x06\x21\x3c\x57\x72\x8d" - "\xa8\xc3\xde\xf9\x14\x2f\x4a\x65" - "\x80\x9b\xb6\xd1\xec\x07\x22\x3d" - "\x58\x73\x8e\xa9\xc4\xdf\xfa\x15" - "\x30\x4b\x66\x81\x9c\xb7\xd2\xed" - "\x08\x23\x3e\x59\x74\x8f\xaa\xc5" - "\xe0\xfb\x16\x31\x4c\x67\x82\x9d" - "\xb8\xd3\xee\x09\x24\x3f\x5a\x75" - "\x90\xab\xc6\xe1\xfc\x17\x32\x4d" - "\x68\x83\x9e\xb9\xd4\xef\x0a\x25" - "\x40\x5b\x76\x91\xac\xc7\xe2\xfd" - "\x18\x33\x4e\x69\x84\x9f\xba\xd5" - "\xf0\x0b\x26\x41\x5c\x77\x92\xad" - "\xc8\xe3\xfe\x19\x34\x4f\x6a\x85" - "\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d" - "\x78\x93\xae\xc9\xe4\xff\x1a\x35" - "\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d" - "\x28\x43\x5e\x79\x94\xaf\xca\xe5" - "\x00\x1d\x3a\x57\x74\x91\xae\xcb" - "\xe8\x05\x22\x3f\x5c\x79\x96\xb3" - "\xd0\xed\x0a\x27\x44\x61\x7e\x9b" - "\xb8\xd5\xf2\x0f\x2c\x49\x66\x83" - "\xa0\xbd\xda\xf7\x14\x31\x4e\x6b" - "\x88\xa5\xc2\xdf\xfc\x19\x36\x53" - "\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b" - "\x58\x75\x92\xaf\xcc\xe9\x06\x23" - "\x40\x5d\x7a\x97\xb4\xd1\xee\x0b" - "\x28\x45\x62\x7f\x9c\xb9\xd6\xf3" - "\x10\x2d\x4a\x67\x84\xa1\xbe\xdb" - "\xf8\x15\x32\x4f\x6c\x89\xa6\xc3" - "\xe0\xfd\x1a\x37\x54\x71\x8e\xab" - "\xc8\xe5\x02\x1f\x3c\x59\x76\x93" - "\xb0\xcd\xea\x07\x24\x41\x5e\x7b" - "\x98\xb5\xd2\xef\x0c\x29\x46\x63" - "\x80\x9d\xba\xd7\xf4\x11\x2e\x4b" - "\x68\x85\xa2\xbf\xdc\xf9\x16\x33" - "\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b" - "\x38\x55\x72\x8f\xac\xc9\xe6\x03" - "\x20\x3d\x5a\x77\x94\xb1\xce\xeb" - "\x08\x25\x42\x5f\x7c\x99\xb6\xd3" - "\xf0\x0d\x2a\x47\x64\x81\x9e\xbb" - "\xd8\xf5\x12\x2f\x4c\x69\x86\xa3" - "\xc0\xdd\xfa\x17\x34\x51\x6e\x8b" - "\xa8\xc5\xe2\xff\x1c\x39\x56\x73" - "\x90\xad\xca\xe7\x04\x21\x3e\x5b" - "\x78\x95\xb2\xcf\xec\x09\x26\x43" - "\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b" - "\x48\x65\x82\x9f\xbc\xd9\xf6\x13" - "\x30\x4d\x6a\x87\xa4\xc1\xde\xfb" - "\x18\x35\x52\x6f\x8c\xa9\xc6\xe3" - "\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9" - "\xf8\x17\x36\x55\x74\x93\xb2\xd1" - "\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9" - "\xe8\x07\x26\x45\x64\x83\xa2\xc1" - "\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9" - "\xd8\xf7\x16\x35\x54\x73\x92\xb1" - "\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9" - "\xc8\xe7\x06\x25\x44\x63\x82\xa1" - "\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99" - "\xb8\xd7\xf6\x15\x34\x53\x72\x91" - "\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89" - "\xa8\xc7\xe6\x05\x24\x43\x62\x81" - "\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79" - "\x98\xb7\xd6\xf5\x14\x33\x52\x71" - "\x90\xaf\xce\xed\x0c\x2b\x4a\x69" - "\x88\xa7\xc6\xe5\x04\x23\x42\x61" - "\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59" - "\x78\x97\xb6\xd5\xf4\x13\x32\x51" - "\x70\x8f\xae\xcd\xec\x0b\x2a\x49" - "\x68\x87\xa6\xc5\xe4\x03\x22\x41" - "\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39" - "\x58\x77\x96\xb5\xd4\xf3\x12\x31" - "\x50\x6f\x8e\xad\xcc\xeb\x0a\x29" - "\x48\x67\x86\xa5\xc4\xe3\x02\x21" - "\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19" - "\x38\x57\x76\x95\xb4\xd3\xf2\x11" - "\x30\x4f\x6e\x8d\xac\xcb\xea\x09" - "\x28\x47\x66\x85\xa4\xc3\xe2\x01" - "\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9" - "\x18\x37\x56\x75\x94\xb3\xd2\xf1" - "\x10\x2f\x4e\x6d\x8c\xab\xca\xe9" - "\x08\x27\x46\x65\x84\xa3\xc2\xe1" - "\x00\x21\x42\x63", - .ilen = 4100, - .result = - "\xf0\x5c\x74\xad\x4e\xbc\x99\xe2" - "\xae\xff\x91\x3a\x44\xcf\x38\x32" - "\x1e\xad\xa7\xcd\xa1\x39\x95\xaa" - "\x10\xb1\xb3\x2e\x04\x31\x8f\x86" - "\xf2\x62\x74\x70\x0c\xa4\x46\x08" - "\xa8\xb7\x99\xa8\xe9\xd2\x73\x79" - "\x7e\x6e\xd4\x8f\x1e\xc7\x8e\x31" - "\x0b\xfa\x4b\xce\xfd\xf3\x57\x71" - "\xe9\x46\x03\xa5\x3d\x34\x00\xe2" - "\x18\xff\x75\x6d\x06\x2d\x00\xab" - "\xb9\x3e\x6c\x59\xc5\x84\x06\xb5" - "\x8b\xd0\x89\x9c\x4a\x79\x16\xc6" - "\x3d\x74\x54\xfa\x44\xcd\x23\x26" - "\x5c\xcf\x7e\x28\x92\x32\xbf\xdf" - "\xa7\x20\x3c\x74\x58\x2a\x9a\xde" - "\x61\x00\x1c\x4f\xff\x59\xc4\x22" - "\xac\x3c\xd0\xe8\x6c\xf9\x97\x1b" - "\x58\x9b\xad\x71\xe8\xa9\xb5\x0d" - "\xee\x2f\x04\x1f\x7f\xbc\x99\xee" - "\x84\xff\x42\x60\xdc\x3a\x18\xa5" - "\x81\xf9\xef\xdc\x7a\x0f\x65\x41" - "\x2f\xa3\xd3\xf9\xc2\xcb\xc0\x4d" - "\x8f\xd3\x76\x96\xad\x49\x6d\x38" - "\x3d\x39\x0b\x6c\x80\xb7\x54\x69" - "\xf0\x2c\x90\x02\x29\x0d\x1c\x12" - "\xad\x55\xc3\x8b\x68\xd9\xcc\xb3" - "\xb2\x64\x33\x90\x5e\xca\x4b\xe2" - "\xfb\x75\xdc\x63\xf7\x9f\x82\x74" - "\xf0\xc9\xaa\x7f\xe9\x2a\x9b\x33" - "\xbc\x88\x00\x7f\xca\xb2\x1f\x14" - "\xdb\xc5\x8e\x7b\x11\x3c\x3e\x08" - "\xf3\x83\xe8\xe0\x94\x86\x2e\x92" - "\x78\x6b\x01\xc9\xc7\x83\xba\x21" - "\x6a\x25\x15\x33\x4e\x45\x08\xec" - "\x35\xdb\xe0\x6e\x31\x51\x79\xa9" - "\x42\x44\x65\xc1\xa0\xf1\xf9\x2a" - "\x70\xd5\xb6\xc6\xc1\x8c\x39\xfc" - "\x25\xa6\x55\xd9\xdd\x2d\x4c\xec" - "\x49\xc6\xeb\x0e\xa8\x25\x2a\x16" - "\x1b\x66\x84\xda\xe2\x92\xe5\xc0" - "\xc8\x53\x07\xaf\x80\x84\xec\xfd" - "\xcd\xd1\x6e\xcd\x6f\x6a\xf5\x36" - "\xc5\x15\xe5\x25\x7d\x77\xd1\x1a" - "\x93\x36\xa9\xcf\x7c\xa4\x54\x4a" - "\x06\x51\x48\x4e\xf6\x59\x87\xd2" - "\x04\x02\xef\xd3\x44\xde\x76\x31" - "\xb3\x34\x17\x1b\x9d\x66\x11\x9f" - "\x1e\xcc\x17\xe9\xc7\x3c\x1b\xe7" - "\xcb\x50\x08\xfc\xdc\x2b\x24\xdb" - "\x65\x83\xd0\x3b\xe3\x30\xea\x94" - "\x6c\xe7\xe8\x35\x32\xc7\xdb\x64" - "\xb4\x01\xab\x36\x2c\x77\x13\xaf" - "\xf8\x2b\x88\x3f\x54\x39\xc4\x44" - "\xfe\xef\x6f\x68\x34\xbe\x0f\x05" - "\x16\x6d\xf6\x0a\x30\xe7\xe3\xed" - "\xc4\xde\x3c\x1b\x13\xd8\xdb\xfe" - "\x41\x62\xe5\x28\xd4\x8d\xa3\xc7" - "\x93\x97\xc6\x48\x45\x1d\x9f\x83" - "\xdf\x4b\x40\x3e\x42\x25\x87\x80" - "\x4c\x7d\xa8\xd4\x98\x23\x95\x75" - "\x41\x8c\xda\x41\x9b\xd4\xa7\x06" - "\xb5\xf1\x71\x09\x53\xbe\xca\xbf" - "\x32\x03\xed\xf0\x50\x1c\x56\x39" - "\x5b\xa4\x75\x18\xf7\x9b\x58\xef" - "\x53\xfc\x2a\x38\x23\x15\x75\xcd" - "\x45\xe5\x5a\x82\x55\xba\x21\xfa" - "\xd4\xbd\xc6\x94\x7c\xc5\x80\x12" - "\xf7\x4b\x32\xc4\x9a\x82\xd8\x28" - "\x8f\xd9\xc2\x0f\x60\x03\xbe\x5e" - "\x21\xd6\x5f\x58\xbf\x5c\xb1\x32" - "\x82\x8d\xa9\xe5\xf2\x66\x1a\xc0" - "\xa0\xbc\x58\x2f\x71\xf5\x2f\xed" - "\xd1\x26\xb9\xd8\x49\x5a\x07\x19" - "\x01\x7c\x59\xb0\xf8\xa4\xb7\xd3" - "\x7b\x1a\x8c\x38\xf4\x50\xa4\x59" - "\xb0\xcc\x41\x0b\x88\x7f\xe5\x31" - "\xb3\x42\xba\xa2\x7e\xd4\x32\x71" - "\x45\x87\x48\xa9\xc2\xf2\x89\xb3" - "\xe4\xa7\x7e\x52\x15\x61\xfa\xfe" - "\xc9\xdd\x81\xeb\x13\xab\xab\xc3" - "\x98\x59\xd8\x16\x3d\x14\x7a\x1c" - "\x3c\x41\x9a\x16\x16\x9b\xd2\xd2" - "\x69\x3a\x29\x23\xac\x86\x32\xa5" - "\x48\x9c\x9e\xf3\x47\x77\x81\x70" - "\x24\xe8\x85\xd2\xf5\xb5\xfa\xff" - "\x59\x6a\xd3\x50\x59\x43\x59\xde" - "\xd9\xf1\x55\xa5\x0c\xc3\x1a\x1a" - "\x18\x34\x0d\x1a\x63\x33\xed\x10" - "\xe0\x1d\x2a\x18\xd2\xc0\x54\xa8" - "\xca\xb5\x9a\xd3\xdd\xca\x45\x84" - "\x50\xe7\x0f\xfe\xa4\x99\x5a\xbe" - "\x43\x2d\x9a\xcb\x92\x3f\x5a\x1d" - "\x85\xd8\xc9\xdf\x68\xc9\x12\x80" - "\x56\x0c\xdc\x00\xdc\x3a\x7d\x9d" - "\xa3\xa2\xe8\x4d\xbf\xf9\x70\xa0" - "\xa4\x13\x4f\x6b\xaf\x0a\x89\x7f" - "\xda\xf0\xbf\x9b\xc8\x1d\xe5\xf8" - "\x2e\x8b\x07\xb5\x73\x1b\xcc\xa2" - "\xa6\xad\x30\xbc\x78\x3c\x5b\x10" - "\xfa\x5e\x62\x2d\x9e\x64\xb3\x33" - "\xce\xf9\x1f\x86\xe7\x8b\xa2\xb8" - "\xe8\x99\x57\x8c\x11\xed\x66\xd9" - "\x3c\x72\xb9\xc3\xe6\x4e\x17\x3a" - "\x6a\xcb\x42\x24\x06\xed\x3e\x4e" - "\xa3\xe8\x6a\x94\xda\x0d\x4e\xd5" - "\x14\x19\xcf\xb6\x26\xd8\x2e\xcc" - "\x64\x76\x38\x49\x4d\xfe\x30\x6d" - "\xe4\xc8\x8c\x7b\xc4\xe0\x35\xba" - "\x22\x6e\x76\xe1\x1a\xf2\x53\xc3" - "\x28\xa2\x82\x1f\x61\x69\xad\xc1" - "\x7b\x28\x4b\x1e\x6c\x85\x95\x9b" - "\x51\xb5\x17\x7f\x12\x69\x8c\x24" - "\xd5\xc7\x5a\x5a\x11\x54\xff\x5a" - "\xf7\x16\xc3\x91\xa6\xf0\xdc\x0a" - "\xb6\xa7\x4a\x0d\x7a\x58\xfe\xa5" - "\xf5\xcb\x8f\x7b\x0e\xea\x57\xe7" - "\xbd\x79\xd6\x1c\x88\x23\x6c\xf2" - "\x4d\x29\x77\x53\x35\x6a\x00\x8d" - "\xcd\xa3\x58\xbe\x77\x99\x18\xf8" - "\xe6\xe1\x8f\xe9\x37\x8f\xe3\xe2" - "\x5a\x8a\x93\x25\xaf\xf3\x78\x80" - "\xbe\xa6\x1b\xc6\xac\x8b\x1c\x91" - "\x58\xe1\x9f\x89\x35\x9d\x1d\x21" - "\x29\x9f\xf4\x99\x02\x27\x0f\xa8" - "\x4f\x79\x94\x2b\x33\x2c\xda\xa2" - "\x26\x39\x83\x94\xef\x27\xd8\x53" - "\x8f\x66\x0d\xe4\x41\x7d\x34\xcd" - "\x43\x7c\x95\x0a\x53\xef\x66\xda" - "\x7e\x9b\xf3\x93\xaf\xd0\x73\x71" - "\xba\x40\x9b\x74\xf8\xd7\xd7\x41" - "\x6d\xaf\x72\x9c\x8d\x21\x87\x3c" - "\xfd\x0a\x90\xa9\x47\x96\x9e\xd3" - "\x88\xee\x73\xcf\x66\x2f\x52\x56" - "\x6d\xa9\x80\x4c\xe2\x6f\x62\x88" - "\x3f\x0e\x54\x17\x48\x80\x5d\xd3" - "\xc3\xda\x25\x3d\xa1\xc8\xcb\x9f" - "\x9b\x70\xb3\xa1\xeb\x04\x52\xa1" - "\xf2\x22\x0f\xfc\xc8\x18\xfa\xf9" - "\x85\x9c\xf1\xac\xeb\x0c\x02\x46" - "\x75\xd2\xf5\x2c\xe3\xd2\x59\x94" - "\x12\xf3\x3c\xfc\xd7\x92\xfa\x36" - "\xba\x61\x34\x38\x7c\xda\x48\x3e" - "\x08\xc9\x39\x23\x5e\x02\x2c\x1a" - "\x18\x7e\xb4\xd9\xfd\x9e\x40\x02" - "\xb1\x33\x37\x32\xe7\xde\xd6\xd0" - "\x7c\x58\x65\x4b\xf8\x34\x27\x9c" - "\x44\xb4\xbd\xe9\xe9\x4c\x78\x7d" - "\x4b\x9f\xce\xb1\xcd\x47\xa5\x37" - "\xe5\x6d\xbd\xb9\x43\x94\x0a\xd4" - "\xd6\xf9\x04\x5f\xb5\x66\x6c\x1a" - "\x35\x12\xe3\x36\x28\x27\x36\x58" - "\x01\x2b\x79\xe4\xba\x6d\x10\x7d" - "\x65\xdf\x84\x95\xf4\xd5\xb6\x8f" - "\x2b\x9f\x96\x00\x86\x60\xf0\x21" - "\x76\xa8\x6a\x8c\x28\x1c\xb3\x6b" - "\x97\xd7\xb6\x53\x2a\xcc\xab\x40" - "\x9d\x62\x79\x58\x52\xe6\x65\xb7" - "\xab\x55\x67\x9c\x89\x7c\x03\xb0" - "\x73\x59\xc5\x81\xf5\x18\x17\x5c" - "\x89\xf3\x78\x35\x44\x62\x78\x72" - "\xd0\x96\xeb\x31\xe7\x87\x77\x14" - "\x99\x51\xf2\x59\x26\x9e\xb5\xa6" - "\x45\xfe\x6e\xbd\x07\x4c\x94\x5a" - "\xa5\x7d\xfc\xf1\x2b\x77\xe2\xfe" - "\x17\xd4\x84\xa0\xac\xb5\xc7\xda" - "\xa9\x1a\xb6\xf3\x74\x11\xb4\x9d" - "\xfb\x79\x2e\x04\x2d\x50\x28\x83" - "\xbf\xc6\x52\xd3\x34\xd6\xe8\x7a" - "\xb6\xea\xe7\xa8\x6c\x15\x1e\x2c" - "\x57\xbc\x48\x4e\x5f\x5c\xb6\x92" - "\xd2\x49\x77\x81\x6d\x90\x70\xae" - "\x98\xa1\x03\x0d\x6b\xb9\x77\x14" - "\xf1\x4e\x23\xd3\xf8\x68\xbd\xc2" - "\xfe\x04\xb7\x5c\xc5\x17\x60\x8f" - "\x65\x54\xa4\x7a\x42\xdc\x18\x0d" - "\xb5\xcf\x0f\xd3\xc7\x91\x66\x1b" - "\x45\x42\x27\x75\x50\xe5\xee\xb8" - "\x7f\x33\x2c\xba\x4a\x92\x4d\x2c" - "\x3c\xe3\x0d\x80\x01\xba\x0d\x29" - "\xd8\x3c\xe9\x13\x16\x57\xe6\xea" - "\x94\x52\xe7\x00\x4d\x30\xb0\x0f" - "\x35\xb8\xb8\xa7\xb1\xb5\x3b\x44" - "\xe1\x2f\xfd\x88\xed\x43\xe7\x52" - "\x10\x93\xb3\x8a\x30\x6b\x0a\xf7" - "\x23\xc6\x50\x9d\x4a\xb0\xde\xc3" - "\xdc\x9b\x2f\x01\x56\x36\x09\xc5" - "\x2f\x6b\xfe\xf1\xd8\x27\x45\x03" - "\x30\x5e\x5c\x5b\xb4\x62\x0e\x1a" - "\xa9\x21\x2b\x92\x94\x87\x62\x57" - "\x4c\x10\x74\x1a\xf1\x0a\xc5\x84" - "\x3b\x9e\x72\x02\xd7\xcc\x09\x56" - "\xbd\x54\xc1\xf0\xc3\xe3\xb3\xf8" - "\xd2\x0d\x61\xcb\xef\xce\x0d\x05" - "\xb0\x98\xd9\x8e\x4f\xf9\xbc\x93" - "\xa6\xea\xc8\xcf\x10\x53\x4b\xf1" - "\xec\xfc\x89\xf9\x64\xb0\x22\xbf" - "\x9e\x55\x46\x9f\x7c\x50\x8e\x84" - "\x54\x20\x98\xd7\x6c\x40\x1e\xdb" - "\x69\x34\x78\x61\x24\x21\x9c\x8a" - "\xb3\x62\x31\x8b\x6e\xf5\x2a\x35" - "\x86\x13\xb1\x6c\x64\x2e\x41\xa5" - "\x05\xf2\x42\xba\xd2\x3a\x0d\x8e" - "\x8a\x59\x94\x3c\xcf\x36\x27\x82" - "\xc2\x45\xee\x58\xcd\x88\xb4\xec" - "\xde\xb2\x96\x0a\xaf\x38\x6f\x88" - "\xd7\xd8\xe1\xdf\xb9\x96\xa9\x0a" - "\xb1\x95\x28\x86\x20\xe9\x17\x49" - "\xa2\x29\x38\xaa\xa5\xe9\x6e\xf1" - "\x19\x27\xc0\xd5\x2a\x22\xc3\x0b" - "\xdb\x7c\x73\x10\xb9\xba\x89\x76" - "\x54\xae\x7d\x71\xb3\x93\xf6\x32" - "\xe6\x47\x43\x55\xac\xa0\x0d\xc2" - "\x93\x27\x4a\x8e\x0e\x74\x15\xc7" - "\x0b\x85\xd9\x0c\xa9\x30\x7a\x3e" - "\xea\x8f\x85\x6d\x3a\x12\x4f\x72" - "\x69\x58\x7a\x80\xbb\xb5\x97\xf3" - "\xcf\x70\xd2\x5d\xdd\x4d\x21\x79" - "\x54\x4d\xe4\x05\xe8\xbd\xc2\x62" - "\xb1\x3b\x77\x1c\xd6\x5c\xf3\xa0" - "\x79\x00\xa8\x6c\x29\xd9\x18\x24" - "\x36\xa2\x46\xc0\x96\x65\x7f\xbd" - "\x2a\xed\x36\x16\x0c\xaa\x9f\xf4" - "\xc5\xb4\xe2\x12\xed\x69\xed\x4f" - "\x26\x2c\x39\x52\x89\x98\xe7\x2c" - "\x99\xa4\x9e\xa3\x9b\x99\x46\x7a" - "\x3a\xdc\xa8\x59\xa3\xdb\xc3\x3b" - "\x95\x0d\x3b\x09\x6e\xee\x83\x5d" - "\x32\x4d\xed\xab\xfa\x98\x14\x4e" - "\xc3\x15\x45\x53\x61\xc4\x93\xbd" - "\x90\xf4\x99\x95\x4c\xe6\x76\x92" - "\x29\x90\x46\x30\x92\x69\x7d\x13" - "\xf2\xa5\xcd\x69\x49\x44\xb2\x0f" - "\x63\x40\x36\x5f\x09\xe2\x78\xf8" - "\x91\xe3\xe2\xfa\x10\xf7\xc8\x24" - "\xa8\x89\x32\x5c\x37\x25\x1d\xb2" - "\xea\x17\x8a\x0a\xa9\x64\xc3\x7c" - "\x3c\x7c\xbd\xc6\x79\x34\xe7\xe2" - "\x85\x8e\xbf\xf8\xde\x92\xa0\xae" - "\x20\xc4\xf6\xbb\x1f\x38\x19\x0e" - "\xe8\x79\x9c\xa1\x23\xe9\x54\x7e" - "\x37\x2f\xe2\x94\x32\xaf\xa0\x23" - "\x49\xe4\xc0\xb3\xac\x00\x8f\x36" - "\x05\xc4\xa6\x96\xec\x05\x98\x4f" - "\x96\x67\x57\x1f\x20\x86\x1b\x2d" - "\x69\xe4\x29\x93\x66\x5f\xaf\x6b" - "\x88\x26\x2c\x67\x02\x4b\x52\xd0" - "\x83\x7a\x43\x1f\xc0\x71\x15\x25" - "\x77\x65\x08\x60\x11\x76\x4c\x8d" - "\xed\xa9\x27\xc6\xb1\x2a\x2c\x6a" - "\x4a\x97\xf5\xc6\xb7\x70\x42\xd3" - "\x03\xd1\x24\x95\xec\x6d\xab\x38" - "\x72\xce\xe2\x8b\x33\xd7\x51\x09" - "\xdc\x45\xe0\x09\x96\x32\xf3\xc4" - "\x84\xdc\x73\x73\x2d\x1b\x11\x98" - "\xc5\x0e\x69\x28\x94\xc7\xb5\x4d" - "\xc8\x8a\xd0\xaa\x13\x2e\x18\x74" - "\xdd\xd1\x1e\xf3\x90\xe8\xfc\x9a" - "\x72\x4a\x0e\xd1\xe4\xfb\x0d\x96" - "\xd1\x0c\x79\x85\x1b\x1c\xfe\xe1" - "\x62\x8f\x7a\x73\x32\xab\xc8\x18" - "\x69\xe3\x34\x30\xdf\x13\xa6\xe5" - "\xe8\x0e\x67\x7f\x81\x11\xb4\x60" - "\xc7\xbd\x79\x65\x50\xdc\xc4\x5b" - "\xde\x39\xa4\x01\x72\x63\xf3\xd1" - "\x64\x4e\xdf\xfc\x27\x92\x37\x0d" - "\x57\xcd\x11\x4f\x11\x04\x8e\x1d" - "\x16\xf7\xcd\x92\x9a\x99\x30\x14" - "\xf1\x7c\x67\x1b\x1f\x41\x0b\xe8" - "\x32\xe8\xb8\xc1\x4f\x54\x86\x4f" - "\xe5\x79\x81\x73\xcd\x43\x59\x68" - "\x73\x02\x3b\x78\x21\x72\x43\x00" - "\x49\x17\xf7\x00\xaf\x68\x24\x53" - "\x05\x0a\xc3\x33\xe0\x33\x3f\x69" - "\xd2\x84\x2f\x0b\xed\xde\x04\xf4" - "\x11\x94\x13\x69\x51\x09\x28\xde" - "\x57\x5c\xef\xdc\x9a\x49\x1c\x17" - "\x97\xf3\x96\xc1\x7f\x5d\x2e\x7d" - "\x55\xb8\xb3\x02\x09\xb3\x1f\xe7" - "\xc9\x8d\xa3\x36\x34\x8a\x77\x13" - "\x30\x63\x4c\xa5\xcd\xc3\xe0\x7e" - "\x05\xa1\x7b\x0c\xcb\x74\x47\x31" - "\x62\x03\x43\xf1\x87\xb4\xb0\x85" - "\x87\x8e\x4b\x25\xc7\xcf\xae\x4b" - "\x36\x46\x3e\x62\xbc\x6f\xeb\x5f" - "\x73\xac\xe6\x07\xee\xc1\xa1\xd6" - "\xc4\xab\xc9\xd6\x89\x45\xe1\xf1" - "\x04\x4e\x1a\x6f\xbb\x4f\x3a\xa3" - "\xa0\xcb\xa3\x0a\xd8\x71\x35\x55" - "\xe4\xbc\x2e\x04\x06\xe6\xff\x5b" - "\x1c\xc0\x11\x7c\xc5\x17\xf3\x38" - "\xcf\xe9\xba\x0f\x0e\xef\x02\xc2" - "\x8d\xc6\xbc\x4b\x67\x20\x95\xd7" - "\x2c\x45\x5b\x86\x44\x8c\x6f\x2e" - "\x7e\x9f\x1c\x77\xba\x6b\x0e\xa3" - "\x69\xdc\xab\x24\x57\x60\x47\xc1" - "\xd1\xa5\x9d\x23\xe6\xb1\x37\xfe" - "\x93\xd2\x4c\x46\xf9\x0c\xc6\xfb" - "\xd6\x9d\x99\x69\xab\x7a\x07\x0c" - "\x65\xe7\xc4\x08\x96\xe2\xa5\x01" - "\x3f\x46\x07\x05\x7e\xe8\x9a\x90" - "\x50\xdc\xe9\x7a\xea\xa1\x39\x6e" - "\x66\xe4\x6f\xa5\x5f\xb2\xd9\x5b" - "\xf5\xdb\x2a\x32\xf0\x11\x6f\x7c" - "\x26\x10\x8f\x3d\x80\xe9\x58\xf7" - "\xe0\xa8\x57\xf8\xdb\x0e\xce\x99" - "\x63\x19\x3d\xd5\xec\x1b\x77\x69" - "\x98\xf6\xe4\x5f\x67\x17\x4b\x09" - "\x85\x62\x82\x70\x18\xe2\x9a\x78" - "\xe2\x62\xbd\xb4\xf1\x42\xc6\xfb" - "\x08\xd0\xbd\xeb\x4e\x09\xf2\xc8" - "\x1e\xdc\x3d\x32\x21\x56\x9c\x4f" - "\x35\xf3\x61\x06\x72\x84\xc4\x32" - "\xf2\xf1\xfa\x0b\x2f\xc3\xdb\x02" - "\x04\xc2\xde\x57\x64\x60\x8d\xcf" - "\xcb\x86\x5d\x97\x3e\xb1\x9c\x01" - "\xd6\x28\x8f\x99\xbc\x46\xeb\x05" - "\xaf\x7e\xb8\x21\x2a\x56\x85\x1c" - "\xb3\x71\xa0\xde\xca\x96\xf1\x78" - "\x49\xa2\x99\x81\x80\x5c\x01\xf5" - "\xa0\xa2\x56\x63\xe2\x70\x07\xa5" - "\x95\xd6\x85\xeb\x36\x9e\xa9\x51" - "\x66\x56\x5f\x1d\x02\x19\xe2\xf6" - "\x4f\x73\x38\x09\x75\x64\x48\xe0" - "\xf1\x7e\x0e\xe8\x9d\xf9\xed\x94" - "\xfe\x16\x26\x62\x49\x74\xf4\xb0" - "\xd4\xa9\x6c\xb0\xfd\x53\xe9\x81" - "\xe0\x7a\xbf\xcf\xb5\xc4\x01\x81" - "\x79\x99\x77\x01\x3b\xe9\xa2\xb6" - "\xe6\x6a\x8a\x9e\x56\x1c\x8d\x1e" - "\x8f\x06\x55\x2c\x6c\xdc\x92\x87" - "\x64\x3b\x4b\x19\xa1\x13\x64\x1d" - "\x4a\xe9\xc0\x00\xb8\x95\xef\x6b" - "\x1a\x86\x6d\x37\x52\x02\xc2\xe0" - "\xc8\xbb\x42\x0c\x02\x21\x4a\xc9" - "\xef\xa0\x54\xe4\x5e\x16\x53\x81" - "\x70\x62\x10\xaf\xde\xb8\xb5\xd3" - "\xe8\x5e\x6c\xc3\x8a\x3e\x18\x07" - "\xf2\x2f\x7d\xa7\xe1\x3d\x4e\xb4" - "\x26\xa7\xa3\x93\x86\xb2\x04\x1e" - "\x53\x5d\x86\xd6\xde\x65\xca\xe3" - "\x4e\xc1\xcf\xef\xc8\x70\x1b\x83" - "\x13\xdd\x18\x8b\x0d\x76\xd2\xf6" - "\x37\x7a\x93\x7a\x50\x11\x9f\x96" - "\x86\x25\xfd\xac\xdc\xbe\x18\x93" - "\x19\x6b\xec\x58\x4f\xb9\x75\xa7" - "\xdd\x3f\x2f\xec\xc8\x5a\x84\xab" - "\xd5\xe4\x8a\x07\xf6\x4d\x23\xd6" - "\x03\xfb\x03\x6a\xea\x66\xbf\xd4" - "\xb1\x34\xfb\x78\xe9\x55\xdc\x7c" - "\x3d\x9c\xe5\x9a\xac\xc3\x7a\x80" - "\x24\x6d\xa0\xef\x25\x7c\xb7\xea" - "\xce\x4d\x5f\x18\x60\xce\x87\x22" - "\x66\x2f\xd5\xdd\xdd\x02\x21\x75" - "\x82\xa0\x1f\x58\xc6\xd3\x62\xf7" - "\x32\xd8\xaf\x1e\x07\x77\x51\x96" - "\xd5\x6b\x1e\x7e\x80\x02\xe8\x67" - "\xea\x17\x0b\x10\xd2\x3f\x28\x25" - "\x4f\x05\x77\x02\x14\x69\xf0\x2c" - "\xbe\x0c\xf1\x74\x30\xd1\xb9\x9b" - "\xfc\x8c\xbb\x04\x16\xd9\xba\xc3" - "\xbc\x91\x8a\xc4\x30\xa4\xb0\x12" - "\x4c\x21\x87\xcb\xc9\x1d\x16\x96" - "\x07\x6f\x23\x54\xb9\x6f\x79\xe5" - "\x64\xc0\x64\xda\xb1\xae\xdd\x60" - "\x6c\x1a\x9d\xd3\x04\x8e\x45\xb0" - "\x92\x61\xd0\x48\x81\xed\x5e\x1d" - "\xa0\xc9\xa4\x33\xc7\x13\x51\x5d" - "\x7f\x83\x73\xb6\x70\x18\x65\x3e" - "\x2f\x0e\x7a\x12\x39\x98\xab\xd8" - "\x7e\x6f\xa3\xd1\xba\x56\xad\xbd" - "\xf0\x03\x01\x1c\x85\x35\x9f\xeb" - "\x19\x63\xa1\xaf\xfe\x2d\x35\x50" - "\x39\xa0\x65\x7c\x95\x7e\x6b\xfe" - "\xc1\xac\x07\x7c\x98\x4f\xbe\x57" - "\xa7\x22\xec\xe2\x7e\x29\x09\x53" - "\xe8\xbf\xb4\x7e\x3f\x8f\xfc\x14" - "\xce\x54\xf9\x18\x58\xb5\xff\x44" - "\x05\x9d\xce\x1b\xb6\x82\x23\xc8" - "\x2e\xbc\x69\xbb\x4a\x29\x0f\x65" - "\x94\xf0\x63\x06\x0e\xef\x8c\xbd" - "\xff\xfd\xb0\x21\x6e\x57\x05\x75" - "\xda\xd5\xc4\xeb\x8d\x32\xf7\x50" - "\xd3\x6f\x22\xed\x5f\x8e\xa2\x5b" - "\x80\x8c\xc8\x78\x40\x24\x4b\x89" - "\x30\xce\x7a\x97\x0e\xc4\xaf\xef" - "\x9b\xb4\xcd\x66\x74\x14\x04\x2b" - "\xf7\xce\x0b\x1c\x6e\xc2\x78\x8c" - "\xca\xc5\xd0\x1c\x95\x4a\x91\x2d" - "\xa7\x20\xeb\x86\x52\xb7\x67\xd8" - "\x0c\xd6\x04\x14\xde\x51\x74\x75" - "\xe7\x11\xb4\x87\xa3\x3d\x2d\xad" - "\x4f\xef\xa0\x0f\x70\x00\x6d\x13" - "\x19\x1d\x41\x50\xe9\xd8\xf0\x32" - "\x71\xbc\xd3\x11\xf2\xac\xbe\xaf" - "\x75\x46\x65\x4e\x07\x34\x37\xa3" - "\x89\xfe\x75\xd4\x70\x4c\xc6\x3f" - "\x69\x24\x0e\x38\x67\x43\x8c\xde" - "\x06\xb5\xb8\xe7\xc4\xf0\x41\x8f" - "\xf0\xbd\x2f\x0b\xb9\x18\xf8\xde" - "\x64\xb1\xdb\xee\x00\x50\x77\xe1" - "\xc7\xff\xa6\xfa\xdd\x70\xf4\xe3" - "\x93\xe9\x77\x35\x3d\x4b\x2f\x2b" - "\x6d\x55\xf0\xfc\x88\x54\x4e\x89" - "\xc1\x8a\x23\x31\x2d\x14\x2a\xb8" - "\x1b\x15\xdd\x9e\x6e\x7b\xda\x05" - "\x91\x7d\x62\x64\x96\x72\xde\xfc" - "\xc1\xec\xf0\x23\x51\x6f\xdb\x5b" - "\x1d\x08\x57\xce\x09\xb8\xf6\xcd" - "\x8d\x95\xf2\x20\xbf\x0f\x20\x57" - "\x98\x81\x84\x4f\x15\x5c\x76\xe7" - "\x3e\x0a\x3a\x6c\xc4\x8a\xbe\x78" - "\x74\x77\xc3\x09\x4b\x5d\x48\xe4" - "\xc8\xcb\x0b\xea\x17\x28\xcf\xcf" - "\x31\x32\x44\xa4\xe5\x0e\x1a\x98" - "\x94\xc4\xf0\xff\xae\x3e\x44\xe8" - "\xa5\xb3\xb5\x37\x2f\xe8\xaf\x6f" - "\x28\xc1\x37\x5f\x31\xd2\xb9\x33" - "\xb1\xb2\x52\x94\x75\x2c\x29\x59" - "\x06\xc2\x25\xe8\x71\x65\x4e\xed" - "\xc0\x9c\xb1\xbb\x25\xdc\x6c\xe7" - "\x4b\xa5\x7a\x54\x7a\x60\xff\x7a" - "\xe0\x50\x40\x96\x35\x63\xe4\x0b" - "\x76\xbd\xa4\x65\x00\x1b\x57\x88" - "\xae\xed\x39\x88\x42\x11\x3c\xed" - "\x85\x67\x7d\xb9\x68\x82\xe9\x43" - "\x3c\x47\x53\xfa\xe8\xf8\x9f\x1f" - "\x9f\xef\x0f\xf7\x30\xd9\x30\x0e" - "\xb9\x9f\x69\x18\x2f\x7e\xf8\xf8" - "\xf8\x8c\x0f\xd4\x02\x4d\xea\xcd" - "\x0a\x9c\x6f\x71\x6d\x5a\x4c\x60" - "\xce\x20\x56\x32\xc6\xc5\x99\x1f" - "\x09\xe6\x4e\x18\x1a\x15\x13\xa8" - "\x7d\xb1\x6b\xc0\xb2\x6d\xf8\x26" - "\x66\xf8\x3d\x18\x74\x70\x66\x7a" - "\x34\x17\xde\xba\x47\xf1\x06\x18" - "\xcb\xaf\xeb\x4a\x1e\x8f\xa7\x77" - "\xe0\x3b\x78\x62\x66\xc9\x10\xea" - "\x1f\xb7\x29\x0a\x45\xa1\x1d\x1e" - "\x1d\xe2\x65\x61\x50\x9c\xd7\x05" - "\xf2\x0b\x5b\x12\x61\x02\xc8\xe5" - "\x63\x4f\x20\x0c\x07\x17\x33\x5e" - "\x03\x9a\x53\x0f\x2e\x55\xfe\x50" - "\x43\x7d\xd0\xb6\x7e\x5a\xda\xae" - "\x58\xef\x15\xa9\x83\xd9\x46\xb1" - "\x42\xaa\xf5\x02\x6c\xce\x92\x06" - "\x1b\xdb\x66\x45\x91\x79\xc2\x2d" - "\xe6\x53\xd3\x14\xfd\xbb\x44\x63" - "\xc6\xd7\x3d\x7a\x0c\x75\x78\x9d" - "\x5c\xa6\x39\xb3\xe5\x63\xca\x8b" - "\xfe\xd3\xef\x60\x83\xf6\x8e\x70" - "\xb6\x67\xc7\x77\xed\x23\xef\x4c" - "\xf0\xed\x2d\x07\x59\x6f\xc1\x01" - "\x34\x37\x08\xab\xd9\x1f\x09\xb1" - "\xce\x5b\x17\xff\x74\xf8\x9c\xd5" - "\x2c\x56\x39\x79\x0f\x69\x44\x75" - "\x58\x27\x01\xc4\xbf\xa7\xa1\x1d" - "\x90\x17\x77\x86\x5a\x3f\xd9\xd1" - "\x0e\xa0\x10\xf8\xec\x1e\xa5\x7f" - "\x5e\x36\xd1\xe3\x04\x2c\x70\xf7" - "\x8e\xc0\x98\x2f\x6c\x94\x2b\x41" - "\xb7\x60\x00\xb7\x2e\xb8\x02\x8d" - "\xb8\xb0\xd3\x86\xba\x1d\xd7\x90" - "\xd6\xb6\xe1\xfc\xd7\xd8\x28\x06" - "\x63\x9b\xce\x61\x24\x79\xc0\x70" - "\x52\xd0\xb6\xd4\x28\x95\x24\x87" - "\x03\x1f\xb7\x9a\xda\xa3\xfb\x52" - "\x5b\x68\xe7\x4c\x8c\x24\xe1\x42" - "\xf7\xd5\xfd\xad\x06\x32\x9f\xba" - "\xc1\xfc\xdd\xc6\xfc\xfc\xb3\x38" - "\x74\x56\x58\x40\x02\x37\x52\x2c" - "\x55\xcc\xb3\x9e\x7a\xe9\xd4\x38" - "\x41\x5e\x0c\x35\xe2\x11\xd1\x13" - "\xf8\xb7\x8d\x72\x6b\x22\x2a\xb0" - "\xdb\x08\xba\x35\xb9\x3f\xc8\xd3" - "\x24\x90\xec\x58\xd2\x09\xc7\x2d" - "\xed\x38\x80\x36\x72\x43\x27\x49" - "\x4a\x80\x8a\xa2\xe8\xd3\xda\x30" - "\x7d\xb6\x82\x37\x86\x92\x86\x3e" - "\x08\xb2\x28\x5a\x55\x44\x24\x7d" - "\x40\x48\x8a\xb6\x89\x58\x08\xa0" - "\xd6\x6d\x3a\x17\xbf\xf6\x54\xa2" - "\xf5\xd3\x8c\x0f\x78\x12\x57\x8b" - "\xd5\xc2\xfd\x58\x5b\x7f\x38\xe3" - "\xcc\xb7\x7c\x48\xb3\x20\xe8\x81" - "\x14\x32\x45\x05\xe0\xdb\x9f\x75" - "\x85\xb4\x6a\xfc\x95\xe3\x54\x22" - "\x12\xee\x30\xfe\xd8\x30\xef\x34" - "\x50\xab\x46\x30\x98\x2f\xb7\xc0" - "\x15\xa2\x83\xb6\xf2\x06\x21\xa2" - "\xc3\x26\x37\x14\xd1\x4d\xb5\x10" - "\x52\x76\x4d\x6a\xee\xb5\x2b\x15" - "\xb7\xf9\x51\xe8\x2a\xaf\xc7\xfa" - "\x77\xaf\xb0\x05\x4d\xd1\x68\x8e" - "\x74\x05\x9f\x9d\x93\xa5\x3e\x7f" - "\x4e\x5f\x9d\xcb\x09\xc7\x83\xe3" - "\x02\x9d\x27\x1f\xef\x85\x05\x8d" - "\xec\x55\x88\x0f\x0d\x7c\x4c\xe8" - "\xa1\x75\xa0\xd8\x06\x47\x14\xef" - "\xaa\x61\xcf\x26\x15\xad\xd8\xa3" - "\xaa\x75\xf2\x78\x4a\x5a\x61\xdf" - "\x8b\xc7\x04\xbc\xb2\x32\xd2\x7e" - "\x42\xee\xb4\x2f\x51\xff\x7b\x2e" - "\xd3\x02\xe8\xdc\x5d\x0d\x50\xdc" - "\xae\xb7\x46\xf9\xa8\xe6\xd0\x16" - "\xcc\xe6\x2c\x81\xc7\xad\xe9\xf0" - "\x05\x72\x6d\x3d\x0a\x7a\xa9\x02" - "\xac\x82\x93\x6e\xb6\x1c\x28\xfc" - "\x44\x12\xfb\x73\x77\xd4\x13\x39" - "\x29\x88\x8a\xf3\x5c\xa6\x36\xa0" - "\x2a\xed\x7e\xb1\x1d\xd6\x4c\x6b" - "\x41\x01\x18\x5d\x5d\x07\x97\xa6" - "\x4b\xef\x31\x18\xea\xac\xb1\x84" - "\x21\xed\xda\x86", - .rlen = 4100, - }, -}; - -static struct cipher_testvec aes_ctr_dec_tv_template[] = { - { /* From RFC 3686 */ - .key = "\xae\x68\x52\xf8\x12\x10\x67\xcc" - "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e" - "\x00\x00\x00\x30", - .klen = 20, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79" - "\x2d\x61\x75\xa3\x26\x13\x11\xb8", - .ilen = 16, - .result = "Single block msg", - .rlen = 16, - }, { - .key = "\x7e\x24\x06\x78\x17\xfa\xe0\xd7" - "\x43\xd6\xce\x1f\x32\x53\x91\x63" - "\x00\x6c\xb6\xdb", - .klen = 20, - .iv = "\xc0\x54\x3b\x59\xda\x48\xd9\x0b", - .input = "\x51\x04\xa1\x06\x16\x8a\x72\xd9" - "\x79\x0d\x41\xee\x8e\xda\xd3\x88" - "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8" - "\xfc\xe6\x30\xdf\x91\x41\xbe\x28", - .ilen = 32, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .rlen = 32, - }, { - .key = "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79" - "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed" - "\x86\x3d\x06\xcc\xfd\xb7\x85\x15" - "\x00\x00\x00\x48", - .klen = 28, - .iv = "\x36\x73\x3c\x14\x7d\x6d\x93\xcb", - .input = "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8" - "\x4e\x79\x35\xa0\x03\xcb\xe9\x28", - .ilen = 16, - .result = "Single block msg", - .rlen = 16, - }, { - .key = "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c" - "\x19\xe7\x34\x08\x19\xe0\xf6\x9c" - "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a" - "\x00\x96\xb0\x3b", - .klen = 28, - .iv = "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d", - .input = "\x45\x32\x43\xfc\x60\x9b\x23\x32" - "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f" - "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c" - "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00", - .ilen = 32, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .rlen = 32, - }, { - .key = "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f" - "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c" - "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3" - "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04" - "\x00\x00\x00\x60", - .klen = 36, - .iv = "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2", - .input = "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7" - "\x56\x08\x63\xdc\x71\xe3\xe0\xc0", - .ilen = 16, - .result = "Single block msg", - .rlen = 16, - }, { - .key = "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb" - "\x07\x96\x36\x58\x79\xef\xf8\x86" - "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74" - "\x4b\x50\x59\x0c\x87\xa2\x38\x84" - "\x00\xfa\xac\x24", - .klen = 36, - .iv = "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75", - .input = "\xf0\x5e\x23\x1b\x38\x94\x61\x2c" - "\x49\xee\x00\x0b\x80\x4e\xb2\xa9" - "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a" - "\x55\x30\x83\x1d\x93\x44\xaf\x1c", - .ilen = 32, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .rlen = 32, - }, -}; - -static struct aead_testvec aes_gcm_enc_tv_template[] = { - { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */ - .key = zeroed_string, - .klen = 16, - .result = "\x58\xe2\xfc\xce\xfa\x7e\x30\x61" - "\x36\x7f\x1d\x57\xa4\xe7\x45\x5a", - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 16, - .input = zeroed_string, - .ilen = 16, - .result = "\x03\x88\xda\xce\x60\xb6\xa3\x92" - "\xf3\x28\xc2\xb9\x71\xb2\xfe\x78" - "\xab\x6e\x47\xd4\x2c\xec\x13\xbd" - "\xf5\x3a\x67\xb2\x12\x57\xbd\xdf", - .rlen = 32, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08", - .klen = 16, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", - .ilen = 64, - .result = "\x42\x83\x1e\xc2\x21\x77\x74\x24" - "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" - "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" - "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" - "\x21\xd5\x14\xb2\x54\x66\x93\x1c" - "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" - "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" - "\x3d\x58\xe0\x91\x47\x3f\x59\x85" - "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" - "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", - .rlen = 80, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08", - .klen = 16, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39", - .ilen = 60, - .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xab\xad\xda\xd2", - .alen = 20, - .result = "\x42\x83\x1e\xc2\x21\x77\x74\x24" - "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" - "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" - "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" - "\x21\xd5\x14\xb2\x54\x66\x93\x1c" - "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" - "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" - "\x3d\x58\xe0\x91" - "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb" - "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47", - .rlen = 76, - }, { - .key = zeroed_string, - .klen = 24, - .result = "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b" - "\xa0\x0e\xd1\xf3\x12\x57\x24\x35", - .rlen = 16, - }, { - .key = zeroed_string, - .klen = 24, - .input = zeroed_string, - .ilen = 16, - .result = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41" - "\x1c\x26\x7e\x43\x84\xb0\xf6\x00" - "\x2f\xf5\x8d\x80\x03\x39\x27\xab" - "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb", - .rlen = 32, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08" - "\xfe\xff\xe9\x92\x86\x65\x73\x1c", - .klen = 24, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", - .ilen = 64, - .result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" - "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" - "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" - "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" - "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" - "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" - "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" - "\xcc\xda\x27\x10\xac\xad\xe2\x56" - "\x99\x24\xa7\xc8\x58\x73\x36\xbf" - "\xb1\x18\x02\x4d\xb8\x67\x4a\x14", - .rlen = 80, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08" - "\xfe\xff\xe9\x92\x86\x65\x73\x1c", - .klen = 24, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39", - .ilen = 60, - .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xab\xad\xda\xd2", - .alen = 20, - .result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" - "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" - "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" - "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" - "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" - "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" - "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" - "\xcc\xda\x27\x10" - "\x25\x19\x49\x8e\x80\xf1\x47\x8f" - "\x37\xba\x55\xbd\x6d\x27\x61\x8c", - .rlen = 76, - .np = 2, - .tap = { 32, 28 }, - .anp = 2, - .atap = { 8, 12 } - }, { - .key = zeroed_string, - .klen = 32, - .result = "\x53\x0f\x8a\xfb\xc7\x45\x36\xb9" - "\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b", - .rlen = 16, - } -}; - -static struct aead_testvec aes_gcm_dec_tv_template[] = { - { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */ - .key = zeroed_string, - .klen = 32, - .input = "\xce\xa7\x40\x3d\x4d\x60\x6b\x6e" - "\x07\x4e\xc5\xd3\xba\xf3\x9d\x18" - "\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0" - "\x26\x5b\x98\xb5\xd4\x8a\xb9\x19", - .ilen = 32, - .result = zeroed_string, - .rlen = 16, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08" - "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08", - .klen = 32, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" - "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" - "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" - "\x75\x98\xa2\xbd\x25\x55\xd1\xaa" - "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d" - "\xa7\xb0\x8b\x10\x56\x82\x88\x38" - "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a" - "\xbc\xc9\xf6\x62\x89\x80\x15\xad" - "\xb0\x94\xda\xc5\xd9\x34\x71\xbd" - "\xec\x1a\x50\x22\x70\xe3\xcc\x6c", - .ilen = 80, - .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", - .rlen = 64, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08" - "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08", - .klen = 32, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" - "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" - "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" - "\x75\x98\xa2\xbd\x25\x55\xd1\xaa" - "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d" - "\xa7\xb0\x8b\x10\x56\x82\x88\x38" - "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a" - "\xbc\xc9\xf6\x62" - "\x76\xfc\x6e\xce\x0f\x4e\x17\x68" - "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b", - .ilen = 76, - .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xab\xad\xda\xd2", - .alen = 20, - .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39", - .rlen = 60, - .np = 2, - .tap = { 48, 28 }, - .anp = 3, - .atap = { 8, 8, 4 } - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08", - .klen = 16, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\x42\x83\x1e\xc2\x21\x77\x74\x24" - "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" - "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" - "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" - "\x21\xd5\x14\xb2\x54\x66\x93\x1c" - "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" - "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" - "\x3d\x58\xe0\x91\x47\x3f\x59\x85" - "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" - "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", - .ilen = 80, - .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", - .rlen = 64, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08", - .klen = 16, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\x42\x83\x1e\xc2\x21\x77\x74\x24" - "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" - "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" - "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" - "\x21\xd5\x14\xb2\x54\x66\x93\x1c" - "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" - "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" - "\x3d\x58\xe0\x91" - "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb" - "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47", - .ilen = 76, - .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xab\xad\xda\xd2", - .alen = 20, - .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39", - .rlen = 60, - }, { - .key = zeroed_string, - .klen = 24, - .input = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41" - "\x1c\x26\x7e\x43\x84\xb0\xf6\x00" - "\x2f\xf5\x8d\x80\x03\x39\x27\xab" - "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb", - .ilen = 32, - .result = zeroed_string, - .rlen = 16, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08" - "\xfe\xff\xe9\x92\x86\x65\x73\x1c", - .klen = 24, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" - "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" - "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" - "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" - "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" - "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" - "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" - "\xcc\xda\x27\x10\xac\xad\xe2\x56" - "\x99\x24\xa7\xc8\x58\x73\x36\xbf" - "\xb1\x18\x02\x4d\xb8\x67\x4a\x14", - .ilen = 80, - .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", - .rlen = 64, - }, { - .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" - "\x6d\x6a\x8f\x94\x67\x30\x83\x08" - "\xfe\xff\xe9\x92\x86\x65\x73\x1c", - .klen = 24, - .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" - "\xde\xca\xf8\x88", - .input = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" - "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" - "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" - "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" - "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" - "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" - "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" - "\xcc\xda\x27\x10" - "\x25\x19\x49\x8e\x80\xf1\x47\x8f" - "\x37\xba\x55\xbd\x6d\x27\x61\x8c", - .ilen = 76, - .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xfe\xed\xfa\xce\xde\xad\xbe\xef" - "\xab\xad\xda\xd2", - .alen = 20, - .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" - "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" - "\x1c\x3c\x0c\x95\x95\x68\x09\x53" - "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39", - .rlen = 60, - } -}; - -static struct aead_testvec aes_ccm_enc_tv_template[] = { - { /* From RFC 3610 */ - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", - .alen = 8, - .input = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e", - .ilen = 23, - .result = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2" - "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80" - "\x6d\x5f\x6b\x61\xda\xc3\x84\x17" - "\xe8\xd1\x2c\xfd\xf9\x26\xe0", - .rlen = 31, - }, { - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x07\x06\x05\x04" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b", - .alen = 12, - .input = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" - "\x14\x15\x16\x17\x18\x19\x1a\x1b" - "\x1c\x1d\x1e\x1f", - .ilen = 20, - .result = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb" - "\x9d\x4e\x13\x12\x53\x65\x8a\xd8" - "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07" - "\x7d\x9c\x2d\x93", - .rlen = 28, - }, { - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x0b\x0a\x09\x08" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", - .alen = 8, - .input = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20", - .ilen = 25, - .result = "\x82\x53\x1a\x60\xcc\x24\x94\x5a" - "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d" - "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1" - "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1" - "\x7e\x5f\x4e", - .rlen = 35, - }, { - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x0c\x0b\x0a\x09" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b", - .alen = 12, - .input = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" - "\x14\x15\x16\x17\x18\x19\x1a\x1b" - "\x1c\x1d\x1e", - .ilen = 19, - .result = "\x07\x34\x25\x94\x15\x77\x85\x15" - "\x2b\x07\x40\x98\x33\x0a\xbb\x14" - "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b" - "\x4d\x99\x99\x88\xdd", - .rlen = 29, - }, { - .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" - "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", - .klen = 16, - .iv = "\x01\x00\x33\x56\x8e\xf7\xb2\x63" - "\x3c\x96\x96\x76\x6c\xfa\x00\x00", - .assoc = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb", - .alen = 8, - .input = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a" - "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf" - "\xb7\x9c\x70\x28\x94\x9c\xd0\xec", - .ilen = 24, - .result = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa" - "\xa0\x72\x6c\x55\xd3\x78\x06\x12" - "\x98\xc8\x5c\x92\x81\x4a\xbc\x33" - "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a", - .rlen = 32, - }, { - .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" - "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", - .klen = 16, - .iv = "\x01\x00\xd5\x60\x91\x2d\x3f\x70" - "\x3c\x96\x96\x76\x6c\xfa\x00\x00", - .assoc = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81" - "\x20\xea\x60\xc0", - .alen = 12, - .input = "\x64\x35\xac\xba\xfb\x11\xa8\x2e" - "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9" - "\x3a\x80\x3b\xa8\x7f", - .ilen = 21, - .result = "\x00\x97\x69\xec\xab\xdf\x48\x62" - "\x55\x94\xc5\x92\x51\xe6\x03\x57" - "\x22\x67\x5e\x04\xc8\x47\x09\x9e" - "\x5a\xe0\x70\x45\x51", - .rlen = 29, - }, { - .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" - "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", - .klen = 16, - .iv = "\x01\x00\x42\xff\xf8\xf1\x95\x1c" - "\x3c\x96\x96\x76\x6c\xfa\x00\x00", - .assoc = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8", - .alen = 8, - .input = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01" - "\x8e\x5e\x67\x01\xc9\x17\x87\x65" - "\x98\x09\xd6\x7d\xbe\xdd\x18", - .ilen = 23, - .result = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6" - "\xdb\x38\x6a\x99\xac\x1a\xef\x23" - "\xad\xe0\xb5\x29\x39\xcb\x6a\x63" - "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6" - "\xba", - .rlen = 33, - }, -}; - -static struct aead_testvec aes_ccm_dec_tv_template[] = { - { /* From RFC 3610 */ - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", - .alen = 8, - .input = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2" - "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80" - "\x6d\x5f\x6b\x61\xda\xc3\x84\x17" - "\xe8\xd1\x2c\xfd\xf9\x26\xe0", - .ilen = 31, - .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e", - .rlen = 23, - }, { - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x07\x06\x05\x04" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b", - .alen = 12, - .input = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb" - "\x9d\x4e\x13\x12\x53\x65\x8a\xd8" - "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07" - "\x7d\x9c\x2d\x93", - .ilen = 28, - .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" - "\x14\x15\x16\x17\x18\x19\x1a\x1b" - "\x1c\x1d\x1e\x1f", - .rlen = 20, - }, { - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x0b\x0a\x09\x08" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", - .alen = 8, - .input = "\x82\x53\x1a\x60\xcc\x24\x94\x5a" - "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d" - "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1" - "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1" - "\x7e\x5f\x4e", - .ilen = 35, - .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20", - .rlen = 25, - }, { - .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - .klen = 16, - .iv = "\x01\x00\x00\x00\x0c\x0b\x0a\x09" - "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", - .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b", - .alen = 12, - .input = "\x07\x34\x25\x94\x15\x77\x85\x15" - "\x2b\x07\x40\x98\x33\x0a\xbb\x14" - "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b" - "\x4d\x99\x99\x88\xdd", - .ilen = 29, - .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" - "\x14\x15\x16\x17\x18\x19\x1a\x1b" - "\x1c\x1d\x1e", - .rlen = 19, - }, { - .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" - "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", - .klen = 16, - .iv = "\x01\x00\x33\x56\x8e\xf7\xb2\x63" - "\x3c\x96\x96\x76\x6c\xfa\x00\x00", - .assoc = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb", - .alen = 8, - .input = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa" - "\xa0\x72\x6c\x55\xd3\x78\x06\x12" - "\x98\xc8\x5c\x92\x81\x4a\xbc\x33" - "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a", - .ilen = 32, - .result = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a" - "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf" - "\xb7\x9c\x70\x28\x94\x9c\xd0\xec", - .rlen = 24, - }, { - .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" - "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", - .klen = 16, - .iv = "\x01\x00\xd5\x60\x91\x2d\x3f\x70" - "\x3c\x96\x96\x76\x6c\xfa\x00\x00", - .assoc = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81" - "\x20\xea\x60\xc0", - .alen = 12, - .input = "\x00\x97\x69\xec\xab\xdf\x48\x62" - "\x55\x94\xc5\x92\x51\xe6\x03\x57" - "\x22\x67\x5e\x04\xc8\x47\x09\x9e" - "\x5a\xe0\x70\x45\x51", - .ilen = 29, - .result = "\x64\x35\xac\xba\xfb\x11\xa8\x2e" - "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9" - "\x3a\x80\x3b\xa8\x7f", - .rlen = 21, - }, { - .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" - "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", - .klen = 16, - .iv = "\x01\x00\x42\xff\xf8\xf1\x95\x1c" - "\x3c\x96\x96\x76\x6c\xfa\x00\x00", - .assoc = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8", - .alen = 8, - .input = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6" - "\xdb\x38\x6a\x99\xac\x1a\xef\x23" - "\xad\xe0\xb5\x29\x39\xcb\x6a\x63" - "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6" - "\xba", - .ilen = 33, - .result = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01" - "\x8e\x5e\x67\x01\xc9\x17\x87\x65" - "\x98\x09\xd6\x7d\xbe\xdd\x18", - .rlen = 23, - }, -}; - -/* Cast5 test vectors from RFC 2144 */ -#define CAST5_ENC_TEST_VECTORS 3 -#define CAST5_DEC_TEST_VECTORS 3 - -static struct cipher_testvec cast5_enc_tv_template[] = { - { - .key = "\x01\x23\x45\x67\x12\x34\x56\x78" - "\x23\x45\x67\x89\x34\x56\x78\x9a", - .klen = 16, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .ilen = 8, - .result = "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x12\x34\x56\x78" - "\x23\x45", - .klen = 10, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .ilen = 8, - .result = "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x12", - .klen = 5, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .ilen = 8, - .result = "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e", - .rlen = 8, - }, -}; - -static struct cipher_testvec cast5_dec_tv_template[] = { - { - .key = "\x01\x23\x45\x67\x12\x34\x56\x78" - "\x23\x45\x67\x89\x34\x56\x78\x9a", - .klen = 16, - .input = "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2", - .ilen = 8, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x12\x34\x56\x78" - "\x23\x45", - .klen = 10, - .input = "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b", - .ilen = 8, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x12", - .klen = 5, - .input = "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e", - .ilen = 8, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .rlen = 8, - }, -}; - -/* - * ARC4 test vectors from OpenSSL - */ -#define ARC4_ENC_TEST_VECTORS 7 -#define ARC4_DEC_TEST_VECTORS 7 - -static struct cipher_testvec arc4_enc_tv_template[] = { - { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .ilen = 8, - .result = "\x75\xb7\x87\x80\x99\xe0\xc5\x96", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 8, - .result = "\x74\x94\xc2\xe7\x10\x4b\x08\x79", - .rlen = 8, - }, { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 8, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 8, - .result = "\xde\x18\x89\x41\xa3\x37\x5d\x3a", - .rlen = 8, - }, { - .key = "\xef\x01\x23\x45", - .klen = 4, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00", - .ilen = 20, - .result = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" - "\xbd\x61\x5a\x11\x62\xe1\xc7\xba" - "\x36\xb6\x78\x58", - .rlen = 20, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" - "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" - "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" - "\x12\x34\x56\x78", - .ilen = 28, - .result = "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89" - "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c" - "\x89\x2e\xbe\x30\x14\x3c\xe2\x87" - "\x40\x01\x1e\xcf", - .rlen = 28, - }, { - .key = "\xef\x01\x23\x45", - .klen = 4, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00", - .ilen = 10, - .result = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" - "\xbd\x61", - .rlen = 10, - }, { - .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .input = "\x01\x23\x45\x67\x89\xAB\xCD\xEF", - .ilen = 8, - .result = "\x69\x72\x36\x59\x1B\x52\x42\xB1", - .rlen = 8, - }, -}; - -static struct cipher_testvec arc4_dec_tv_template[] = { - { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x75\xb7\x87\x80\x99\xe0\xc5\x96", - .ilen = 8, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .rlen = 8, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x74\x94\xc2\xe7\x10\x4b\x08\x79", - .ilen = 8, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00", - .rlen = 8, - }, { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 8, - .input = "\xde\x18\x89\x41\xa3\x37\x5d\x3a", - .ilen = 8, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00", - .rlen = 8, - }, { - .key = "\xef\x01\x23\x45", - .klen = 4, - .input = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" - "\xbd\x61\x5a\x11\x62\xe1\xc7\xba" - "\x36\xb6\x78\x58", - .ilen = 20, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00", - .rlen = 20, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", - .klen = 8, - .input = "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89" - "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c" - "\x89\x2e\xbe\x30\x14\x3c\xe2\x87" - "\x40\x01\x1e\xcf", - .ilen = 28, - .result = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" - "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" - "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" - "\x12\x34\x56\x78", - .rlen = 28, - }, { - .key = "\xef\x01\x23\x45", - .klen = 4, - .input = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" - "\xbd\x61", - .ilen = 10, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00", - .rlen = 10, - }, { - .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .input = "\x69\x72\x36\x59\x1B\x52\x42\xB1", - .ilen = 8, - .result = "\x01\x23\x45\x67\x89\xAB\xCD\xEF", - .rlen = 8, - }, -}; - -/* - * TEA test vectors - */ -#define TEA_ENC_TEST_VECTORS 4 -#define TEA_DEC_TEST_VECTORS 4 - -static struct cipher_testvec tea_enc_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = zeroed_string, - .ilen = 8, - .result = "\x0a\x3a\xea\x41\x40\xa9\xba\x94", - .rlen = 8, - }, { - .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" - "\x77\x5d\x0e\x26\x6c\x28\x78\x43", - .klen = 16, - .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e", - .ilen = 8, - .result = "\x77\x5d\x2a\x6a\xf6\xce\x92\x09", - .rlen = 8, - }, { - .key = "\x09\x65\x43\x11\x66\x44\x39\x25" - "\x51\x3a\x16\x10\x0a\x08\x12\x6e", - .klen = 16, - .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" - "\x65\x73\x74\x5f\x76\x65\x63\x74", - .ilen = 16, - .result = "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e" - "\xdd\x89\xa1\x25\x04\x21\xdf\x95", - .rlen = 16, - }, { - .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" - "\x5d\x04\x16\x36\x15\x72\x63\x2f", - .klen = 16, - .input = "\x54\x65\x61\x20\x69\x73\x20\x67" - "\x6f\x6f\x64\x20\x66\x6f\x72\x20" - "\x79\x6f\x75\x21\x21\x21\x20\x72" - "\x65\x61\x6c\x6c\x79\x21\x21\x21", - .ilen = 32, - .result = "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47" - "\x94\x18\x95\x91\xa9\xfc\x49\xf8" - "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a" - "\x07\x89\x73\xc2\x45\x92\xc6\x90", - .rlen = 32, - } -}; - -static struct cipher_testvec tea_dec_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = "\x0a\x3a\xea\x41\x40\xa9\xba\x94", - .ilen = 8, - .result = zeroed_string, - .rlen = 8, - }, { - .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" - "\x77\x5d\x0e\x26\x6c\x28\x78\x43", - .klen = 16, - .input = "\x77\x5d\x2a\x6a\xf6\xce\x92\x09", - .ilen = 8, - .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e", - .rlen = 8, - }, { - .key = "\x09\x65\x43\x11\x66\x44\x39\x25" - "\x51\x3a\x16\x10\x0a\x08\x12\x6e", - .klen = 16, - .input = "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e" - "\xdd\x89\xa1\x25\x04\x21\xdf\x95", - .ilen = 16, - .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" - "\x65\x73\x74\x5f\x76\x65\x63\x74", - .rlen = 16, - }, { - .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" - "\x5d\x04\x16\x36\x15\x72\x63\x2f", - .klen = 16, - .input = "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47" - "\x94\x18\x95\x91\xa9\xfc\x49\xf8" - "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a" - "\x07\x89\x73\xc2\x45\x92\xc6\x90", - .ilen = 32, - .result = "\x54\x65\x61\x20\x69\x73\x20\x67" - "\x6f\x6f\x64\x20\x66\x6f\x72\x20" - "\x79\x6f\x75\x21\x21\x21\x20\x72" - "\x65\x61\x6c\x6c\x79\x21\x21\x21", - .rlen = 32, - } -}; - -/* - * XTEA test vectors - */ -#define XTEA_ENC_TEST_VECTORS 4 -#define XTEA_DEC_TEST_VECTORS 4 - -static struct cipher_testvec xtea_enc_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = zeroed_string, - .ilen = 8, - .result = "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7", - .rlen = 8, - }, { - .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" - "\x77\x5d\x0e\x26\x6c\x28\x78\x43", - .klen = 16, - .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e", - .ilen = 8, - .result = "\x94\xeb\xc8\x96\x84\x6a\x49\xa8", - .rlen = 8, - }, { - .key = "\x09\x65\x43\x11\x66\x44\x39\x25" - "\x51\x3a\x16\x10\x0a\x08\x12\x6e", - .klen = 16, - .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" - "\x65\x73\x74\x5f\x76\x65\x63\x74", - .ilen = 16, - .result = "\x3e\xce\xae\x22\x60\x56\xa8\x9d" - "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a", - .rlen = 16, - }, { - .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" - "\x5d\x04\x16\x36\x15\x72\x63\x2f", - .klen = 16, - .input = "\x54\x65\x61\x20\x69\x73\x20\x67" - "\x6f\x6f\x64\x20\x66\x6f\x72\x20" - "\x79\x6f\x75\x21\x21\x21\x20\x72" - "\x65\x61\x6c\x6c\x79\x21\x21\x21", - .ilen = 32, - .result = "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a" - "\x86\xff\x6f\xd0\xe3\x87\x70\x07" - "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4" - "\x73\xa2\xfa\xc9\x16\x59\x5d\x81", - .rlen = 32, - } -}; - -static struct cipher_testvec xtea_dec_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7", - .ilen = 8, - .result = zeroed_string, - .rlen = 8, - }, { - .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" - "\x77\x5d\x0e\x26\x6c\x28\x78\x43", - .klen = 16, - .input = "\x94\xeb\xc8\x96\x84\x6a\x49\xa8", - .ilen = 8, - .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e", - .rlen = 8, - }, { - .key = "\x09\x65\x43\x11\x66\x44\x39\x25" - "\x51\x3a\x16\x10\x0a\x08\x12\x6e", - .klen = 16, - .input = "\x3e\xce\xae\x22\x60\x56\xa8\x9d" - "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a", - .ilen = 16, - .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" - "\x65\x73\x74\x5f\x76\x65\x63\x74", - .rlen = 16, - }, { - .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" - "\x5d\x04\x16\x36\x15\x72\x63\x2f", - .klen = 16, - .input = "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a" - "\x86\xff\x6f\xd0\xe3\x87\x70\x07" - "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4" - "\x73\xa2\xfa\xc9\x16\x59\x5d\x81", - .ilen = 32, - .result = "\x54\x65\x61\x20\x69\x73\x20\x67" - "\x6f\x6f\x64\x20\x66\x6f\x72\x20" - "\x79\x6f\x75\x21\x21\x21\x20\x72" - "\x65\x61\x6c\x6c\x79\x21\x21\x21", - .rlen = 32, - } -}; - -/* - * KHAZAD test vectors. - */ -#define KHAZAD_ENC_TEST_VECTORS 5 -#define KHAZAD_DEC_TEST_VECTORS 5 - -static struct cipher_testvec khazad_enc_tv_template[] = { - { - .key = "\x80\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .input = "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 8, - .result = "\x49\xa4\xce\x32\xac\x19\x0e\x3f", - .rlen = 8, - }, { - .key = "\x38\x38\x38\x38\x38\x38\x38\x38" - "\x38\x38\x38\x38\x38\x38\x38\x38", - .klen = 16, - .input = "\x38\x38\x38\x38\x38\x38\x38\x38", - .ilen = 8, - .result = "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9", - .rlen = 8, - }, { - .key = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2" - "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", - .klen = 16, - .input = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", - .ilen = 8, - .result = "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c", - .rlen = 8, - }, { - .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" - "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .klen = 16, - .input = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .ilen = 8, - .result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8", - .rlen = 8, - }, { - .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" - "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .klen = 16, - .input = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" - "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .ilen = 16, - .result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8" - "\x04\x74\xf5\x70\x50\x16\xd3\xb8", - .rlen = 16, - }, -}; - -static struct cipher_testvec khazad_dec_tv_template[] = { - { - .key = "\x80\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .input = "\x49\xa4\xce\x32\xac\x19\x0e\x3f", - .ilen = 8, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00", - .rlen = 8, - }, { - .key = "\x38\x38\x38\x38\x38\x38\x38\x38" - "\x38\x38\x38\x38\x38\x38\x38\x38", - .klen = 16, - .input = "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9", - .ilen = 8, - .result = "\x38\x38\x38\x38\x38\x38\x38\x38", - .rlen = 8, - }, { - .key = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2" - "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", - .klen = 16, - .input = "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c", - .ilen = 8, - .result = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", - .rlen = 8, - }, { - .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" - "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .klen = 16, - .input = "\x04\x74\xf5\x70\x50\x16\xd3\xb8", - .ilen = 8, - .result = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .rlen = 8, - }, { - .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" - "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .klen = 16, - .input = "\x04\x74\xf5\x70\x50\x16\xd3\xb8" - "\x04\x74\xf5\x70\x50\x16\xd3\xb8", - .ilen = 16, - .result = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" - "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", - .rlen = 16, - }, -}; - -/* - * Anubis test vectors. - */ - -#define ANUBIS_ENC_TEST_VECTORS 5 -#define ANUBIS_DEC_TEST_VECTORS 5 -#define ANUBIS_CBC_ENC_TEST_VECTORS 2 -#define ANUBIS_CBC_DEC_TEST_VECTORS 2 - -static struct cipher_testvec anubis_enc_tv_template[] = { - { - .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .klen = 16, - .input = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .ilen = 16, - .result = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" - "\x08\xb7\x52\x8e\x6e\x6e\x86\x90", - .rlen = 16, - }, { - - .key = "\x03\x03\x03\x03\x03\x03\x03\x03" - "\x03\x03\x03\x03\x03\x03\x03\x03" - "\x03\x03\x03\x03", - .klen = 20, - .input = "\x03\x03\x03\x03\x03\x03\x03\x03" - "\x03\x03\x03\x03\x03\x03\x03\x03", - .ilen = 16, - .result = "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49" - "\x87\x41\x6f\x82\x0a\x98\x64\xae", - .rlen = 16, - }, { - .key = "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24", - .klen = 28, - .input = "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24\x24\x24\x24\x24", - .ilen = 16, - .result = "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d" - "\x06\xd3\x61\x27\xfd\x13\x9e\xde", - .rlen = 16, - }, { - .key = "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25", - .klen = 32, - .input = "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25", - .ilen = 16, - .result = "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4" - "\x17\xd9\xff\x40\x3b\x0e\xe5\xfe", - .rlen = 16, - }, { - .key = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .klen = 40, - .input = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .ilen = 16, - .result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" - "\x9e\xc6\x84\x0f\x17\x21\x07\xee", - .rlen = 16, - }, -}; - -static struct cipher_testvec anubis_dec_tv_template[] = { - { - .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .klen = 16, - .input = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" - "\x08\xb7\x52\x8e\x6e\x6e\x86\x90", - .ilen = 16, - .result = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .rlen = 16, - }, { - - .key = "\x03\x03\x03\x03\x03\x03\x03\x03" - "\x03\x03\x03\x03\x03\x03\x03\x03" - "\x03\x03\x03\x03", - .klen = 20, - .input = "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49" - "\x87\x41\x6f\x82\x0a\x98\x64\xae", - .ilen = 16, - .result = "\x03\x03\x03\x03\x03\x03\x03\x03" - "\x03\x03\x03\x03\x03\x03\x03\x03", - .rlen = 16, - }, { - .key = "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24", - .klen = 28, - .input = "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d" - "\x06\xd3\x61\x27\xfd\x13\x9e\xde", - .ilen = 16, - .result = "\x24\x24\x24\x24\x24\x24\x24\x24" - "\x24\x24\x24\x24\x24\x24\x24\x24", - .rlen = 16, - }, { - .key = "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25", - .klen = 32, - .input = "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4" - "\x17\xd9\xff\x40\x3b\x0e\xe5\xfe", - .ilen = 16, - .result = "\x25\x25\x25\x25\x25\x25\x25\x25" - "\x25\x25\x25\x25\x25\x25\x25\x25", - .rlen = 16, - }, { - .key = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" - "\x9e\xc6\x84\x0f\x17\x21\x07\xee", - .klen = 40, - .ilen = 16, - .result = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .rlen = 16, - }, -}; - -static struct cipher_testvec anubis_cbc_enc_tv_template[] = { - { - .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .klen = 16, - .input = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .ilen = 32, - .result = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" - "\x08\xb7\x52\x8e\x6e\x6e\x86\x90" - "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66" - "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe", - .rlen = 32, - }, { - .key = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .klen = 40, - .input = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .ilen = 32, - .result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" - "\x9e\xc6\x84\x0f\x17\x21\x07\xee" - "\xa2\xbc\x06\x98\xc6\x4b\xda\x75" - "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7", - .rlen = 32, - }, -}; - -static struct cipher_testvec anubis_cbc_dec_tv_template[] = { - { - .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .klen = 16, - .input = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" - "\x08\xb7\x52\x8e\x6e\x6e\x86\x90" - "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66" - "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe", - .ilen = 32, - .result = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" - "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", - .rlen = 32, - }, { - .key = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .klen = 40, - .input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" - "\x9e\xc6\x84\x0f\x17\x21\x07\xee" - "\xa2\xbc\x06\x98\xc6\x4b\xda\x75" - "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7", - .ilen = 32, - .result = "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35" - "\x35\x35\x35\x35\x35\x35\x35\x35", - .rlen = 32, - }, -}; - -/* - * XETA test vectors - */ -#define XETA_ENC_TEST_VECTORS 4 -#define XETA_DEC_TEST_VECTORS 4 - -static struct cipher_testvec xeta_enc_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = zeroed_string, - .ilen = 8, - .result = "\xaa\x22\x96\xe5\x6c\x61\xf3\x45", - .rlen = 8, - }, { - .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" - "\x77\x5d\x0e\x26\x6c\x28\x78\x43", - .klen = 16, - .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e", - .ilen = 8, - .result = "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3", - .rlen = 8, - }, { - .key = "\x09\x65\x43\x11\x66\x44\x39\x25" - "\x51\x3a\x16\x10\x0a\x08\x12\x6e", - .klen = 16, - .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" - "\x65\x73\x74\x5f\x76\x65\x63\x74", - .ilen = 16, - .result = "\xe2\x04\xdb\xf2\x89\x85\x9e\xea" - "\x61\x35\xaa\xed\xb5\xcb\x71\x2c", - .rlen = 16, - }, { - .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" - "\x5d\x04\x16\x36\x15\x72\x63\x2f", - .klen = 16, - .input = "\x54\x65\x61\x20\x69\x73\x20\x67" - "\x6f\x6f\x64\x20\x66\x6f\x72\x20" - "\x79\x6f\x75\x21\x21\x21\x20\x72" - "\x65\x61\x6c\x6c\x79\x21\x21\x21", - .ilen = 32, - .result = "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1" - "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4" - "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f" - "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5", - .rlen = 32, - } -}; - -static struct cipher_testvec xeta_dec_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = "\xaa\x22\x96\xe5\x6c\x61\xf3\x45", - .ilen = 8, - .result = zeroed_string, - .rlen = 8, - }, { - .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" - "\x77\x5d\x0e\x26\x6c\x28\x78\x43", - .klen = 16, - .input = "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3", - .ilen = 8, - .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e", - .rlen = 8, - }, { - .key = "\x09\x65\x43\x11\x66\x44\x39\x25" - "\x51\x3a\x16\x10\x0a\x08\x12\x6e", - .klen = 16, - .input = "\xe2\x04\xdb\xf2\x89\x85\x9e\xea" - "\x61\x35\xaa\xed\xb5\xcb\x71\x2c", - .ilen = 16, - .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" - "\x65\x73\x74\x5f\x76\x65\x63\x74", - .rlen = 16, - }, { - .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" - "\x5d\x04\x16\x36\x15\x72\x63\x2f", - .klen = 16, - .input = "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1" - "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4" - "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f" - "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5", - .ilen = 32, - .result = "\x54\x65\x61\x20\x69\x73\x20\x67" - "\x6f\x6f\x64\x20\x66\x6f\x72\x20" - "\x79\x6f\x75\x21\x21\x21\x20\x72" - "\x65\x61\x6c\x6c\x79\x21\x21\x21", - .rlen = 32, - } -}; - -/* - * FCrypt test vectors - */ -#define FCRYPT_ENC_TEST_VECTORS ARRAY_SIZE(fcrypt_pcbc_enc_tv_template) -#define FCRYPT_DEC_TEST_VECTORS ARRAY_SIZE(fcrypt_pcbc_dec_tv_template) - -static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = { - { /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 8, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 8, - .result = "\x0E\x09\x00\xC7\x3E\xF7\xED\x41", - .rlen = 8, - }, { - .key = "\x11\x44\x77\xAA\xDD\x00\x33\x66", - .klen = 8, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0", - .ilen = 8, - .result = "\xD8\xED\x78\x74\x77\xEC\x06\x80", - .rlen = 8, - }, { /* From Arla */ - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .klen = 8, - .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .input = "The quick brown fox jumps over the lazy dogs.\0\0", - .ilen = 48, - .result = "\x00\xf0\x0e\x11\x75\xe6\x23\x82" - "\xee\xac\x98\x62\x44\x51\xe4\x84" - "\xc3\x59\xd8\xaa\x64\x60\xae\xf7" - "\xd2\xd9\x13\x79\x72\xa3\x45\x03" - "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1" - "\xf8\x91\x3c\xac\x44\x22\x92\xef", - .rlen = 48, - }, { - .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 8, - .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .input = "The quick brown fox jumps over the lazy dogs.\0\0", - .ilen = 48, - .result = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" - "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" - "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" - "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" - "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" - "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", - .rlen = 48, - }, { /* split-page version */ - .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 8, - .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .input = "The quick brown fox jumps over the lazy dogs.\0\0", - .ilen = 48, - .result = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" - "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" - "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" - "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" - "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" - "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", - .rlen = 48, - .np = 2, - .tap = { 20, 28 }, - } -}; - -static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = { - { /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 8, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x0E\x09\x00\xC7\x3E\xF7\xED\x41", - .ilen = 8, - .result = "\x00\x00\x00\x00\x00\x00\x00\x00", - .rlen = 8, - }, { - .key = "\x11\x44\x77\xAA\xDD\x00\x33\x66", - .klen = 8, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\xD8\xED\x78\x74\x77\xEC\x06\x80", - .ilen = 8, - .result = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0", - .rlen = 8, - }, { /* From Arla */ - .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .klen = 8, - .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .input = "\x00\xf0\x0e\x11\x75\xe6\x23\x82" - "\xee\xac\x98\x62\x44\x51\xe4\x84" - "\xc3\x59\xd8\xaa\x64\x60\xae\xf7" - "\xd2\xd9\x13\x79\x72\xa3\x45\x03" - "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1" - "\xf8\x91\x3c\xac\x44\x22\x92\xef", - .ilen = 48, - .result = "The quick brown fox jumps over the lazy dogs.\0\0", - .rlen = 48, - }, { - .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 8, - .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .input = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" - "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" - "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" - "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" - "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" - "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", - .ilen = 48, - .result = "The quick brown fox jumps over the lazy dogs.\0\0", - .rlen = 48, - }, { /* split-page version */ - .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 8, - .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", - .input = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" - "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" - "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" - "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" - "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" - "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", - .ilen = 48, - .result = "The quick brown fox jumps over the lazy dogs.\0\0", - .rlen = 48, - .np = 2, - .tap = { 20, 28 }, - } -}; - -/* - * CAMELLIA test vectors. - */ -#define CAMELLIA_ENC_TEST_VECTORS 3 -#define CAMELLIA_DEC_TEST_VECTORS 3 -#define CAMELLIA_CBC_ENC_TEST_VECTORS 2 -#define CAMELLIA_CBC_DEC_TEST_VECTORS 2 - -static struct cipher_testvec camellia_enc_tv_template[] = { - { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 16, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .ilen = 16, - .result = "\x67\x67\x31\x38\x54\x96\x69\x73" - "\x08\x57\x06\x56\x48\xea\xbe\x43", - .rlen = 16, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77", - .klen = 24, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .ilen = 16, - .result = "\xb4\x99\x34\x01\xb3\xe9\x96\xf8" - "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9", - .rlen = 16, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .klen = 32, - .input = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .ilen = 16, - .result = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c" - "\x20\xef\x7c\x91\x9e\x3a\x75\x09", - .rlen = 16, - }, -}; - -static struct cipher_testvec camellia_dec_tv_template[] = { - { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .klen = 16, - .input = "\x67\x67\x31\x38\x54\x96\x69\x73" - "\x08\x57\x06\x56\x48\xea\xbe\x43", - .ilen = 16, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\x55\x55\x55\x55\x55\x55\x55\x55" "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .rlen = 16, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77", .klen = 24, - .input = "\xb4\x99\x34\x01\xb3\xe9\x96\xf8" - "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9", - .ilen = 16, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .rlen = 16, - }, { - .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", - .klen = 32, - .input = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c" - "\x20\xef\x7c\x91\x9e\x3a\x75\x09", - .ilen = 16, - .result = "\x01\x23\x45\x67\x89\xab\xcd\xef" - "\xfe\xdc\xba\x98\x76\x54\x32\x10", - .rlen = 16, - }, -}; - -static struct cipher_testvec camellia_cbc_enc_tv_template[] = { - { - .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" - "\x51\x2e\x03\xd5\x34\x12\x00\x06", - .klen = 16, - .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" - "\xb4\x22\xda\x80\x2c\x9f\xac\x41", - .input = "Single block msg", - .ilen = 16, - .result = "\xea\x32\x12\x76\x3b\x50\x10\xe7" - "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51", - .rlen = 16, - }, { - .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" - "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", - .klen = 16, - .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" - "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .ilen = 32, - .result = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01" - "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd" - "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0" - "\x15\x78\xe0\x5e\xf2\xcb\x87\x16", - .rlen = 32, - }, -}; - -static struct cipher_testvec camellia_cbc_dec_tv_template[] = { - { - .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" - "\x51\x2e\x03\xd5\x34\x12\x00\x06", - .klen = 16, - .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" - "\xb4\x22\xda\x80\x2c\x9f\xac\x41", - .input = "\xea\x32\x12\x76\x3b\x50\x10\xe7" - "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51", - .ilen = 16, - .result = "Single block msg", - .rlen = 16, - }, { - .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" - "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", - .klen = 16, - .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" - "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", - .input = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01" - "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd" - "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0" - "\x15\x78\xe0\x5e\xf2\xcb\x87\x16", - .ilen = 32, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .rlen = 32, - }, -}; - -/* - * SEED test vectors - */ -#define SEED_ENC_TEST_VECTORS 4 -#define SEED_DEC_TEST_VECTORS 4 - -static struct cipher_testvec seed_enc_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .ilen = 16, - .result = "\x5e\xba\xc6\xe0\x05\x4e\x16\x68" - "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .klen = 16, - .input = zeroed_string, - .ilen = 16, - .result = "\xc1\x1f\x22\xf2\x01\x40\x50\x50" - "\x84\x48\x35\x97\xe4\x37\x0f\x43", - .rlen = 16, - }, { - .key = "\x47\x06\x48\x08\x51\xe6\x1b\xe8" - "\x5d\x74\xbf\xb3\xfd\x95\x61\x85", - .klen = 16, - .input = "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9" - "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d", - .ilen = 16, - .result = "\xee\x54\xd1\x3e\xbc\xae\x70\x6d" - "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a", - .rlen = 16, - }, { - .key = "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d" - "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7", - .klen = 16, - .input = "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14" - "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7", - .ilen = 16, - .result = "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9" - "\x5d\x0b\x36\x18\xf4\x0f\x51\x22", - .rlen = 16, } }; -static struct cipher_testvec seed_dec_tv_template[] = { - { - .key = zeroed_string, - .klen = 16, - .input = "\x5e\xba\xc6\xe0\x05\x4e\x16\x68" - "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb", - .ilen = 16, - .result = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .rlen = 16, - }, { - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - .klen = 16, - .input = "\xc1\x1f\x22\xf2\x01\x40\x50\x50" - "\x84\x48\x35\x97\xe4\x37\x0f\x43", - .ilen = 16, - .result = zeroed_string, - .rlen = 16, - }, { - .key = "\x47\x06\x48\x08\x51\xe6\x1b\xe8" - "\x5d\x74\xbf\xb3\xfd\x95\x61\x85", - .klen = 16, - .input = "\xee\x54\xd1\x3e\xbc\xae\x70\x6d" - "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a", - .ilen = 16, - .result = "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9" - "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d", - .rlen = 16, - }, { - .key = "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d" - "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7", - .klen = 16, - .input = "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9" - "\x5d\x0b\x36\x18\xf4\x0f\x51\x22", - .ilen = 16, - .result = "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14" - "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7", - .rlen = 16, - } -}; - -#define SALSA20_STREAM_ENC_TEST_VECTORS 5 -static struct cipher_testvec salsa20_stream_enc_tv_template[] = { - /* - * Testvectors from verified.test-vectors submitted to ECRYPT. - * They are truncated to size 39, 64, 111, 129 to test a variety - * of input length. - */ - { /* Set 3, vector 0 */ - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", - .klen = 16, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00", - .ilen = 39, - .result = "\x2D\xD5\xC3\xF7\xBA\x2B\x20\xF7" - "\x68\x02\x41\x0C\x68\x86\x88\x89" - "\x5A\xD8\xC1\xBD\x4E\xA6\xC9\xB1" - "\x40\xFB\x9B\x90\xE2\x10\x49\xBF" - "\x58\x3F\x52\x79\x70\xEB\xC1", - .rlen = 39, - }, { /* Set 5, vector 0 */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 16, - .iv = "\x80\x00\x00\x00\x00\x00\x00\x00", - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .ilen = 64, - .result = "\xB6\x6C\x1E\x44\x46\xDD\x95\x57" - "\xE5\x78\xE2\x23\xB0\xB7\x68\x01" - "\x7B\x23\xB2\x67\xBB\x02\x34\xAE" - "\x46\x26\xBF\x44\x3F\x21\x97\x76" - "\x43\x6F\xB1\x9F\xD0\xE8\x86\x6F" - "\xCD\x0D\xE9\xA9\x53\x8F\x4A\x09" - "\xCA\x9A\xC0\x73\x2E\x30\xBC\xF9" - "\x8E\x4F\x13\xE4\xB9\xE2\x01\xD9", - .rlen = 64, - }, { /* Set 3, vector 27 */ - .key = "\x1B\x1C\x1D\x1E\x1F\x20\x21\x22" - "\x23\x24\x25\x26\x27\x28\x29\x2A" - "\x2B\x2C\x2D\x2E\x2F\x30\x31\x32" - "\x33\x34\x35\x36\x37\x38\x39\x3A", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00", - .ilen = 111, - .result = "\xAE\x39\x50\x8E\xAC\x9A\xEC\xE7" - "\xBF\x97\xBB\x20\xB9\xDE\xE4\x1F" - "\x87\xD9\x47\xF8\x28\x91\x35\x98" - "\xDB\x72\xCC\x23\x29\x48\x56\x5E" - "\x83\x7E\x0B\xF3\x7D\x5D\x38\x7B" - "\x2D\x71\x02\xB4\x3B\xB5\xD8\x23" - "\xB0\x4A\xDF\x3C\xEC\xB6\xD9\x3B" - "\x9B\xA7\x52\xBE\xC5\xD4\x50\x59" - "\x15\x14\xB4\x0E\x40\xE6\x53\xD1" - "\x83\x9C\x5B\xA0\x92\x29\x6B\x5E" - "\x96\x5B\x1E\x2F\xD3\xAC\xC1\x92" - "\xB1\x41\x3F\x19\x2F\xC4\x3B\xC6" - "\x95\x46\x45\x54\xE9\x75\x03\x08" - "\x44\xAF\xE5\x8A\x81\x12\x09", - .rlen = 111, - }, { /* Set 5, vector 27 */ - .key = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .klen = 32, - .iv = "\x00\x00\x00\x10\x00\x00\x00\x00", - .input = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00", - .ilen = 129, - .result = "\xD2\xDB\x1A\x5C\xF1\xC1\xAC\xDB" - "\xE8\x1A\x7A\x43\x40\xEF\x53\x43" - "\x5E\x7F\x4B\x1A\x50\x52\x3F\x8D" - "\x28\x3D\xCF\x85\x1D\x69\x6E\x60" - "\xF2\xDE\x74\x56\x18\x1B\x84\x10" - "\xD4\x62\xBA\x60\x50\xF0\x61\xF2" - "\x1C\x78\x7F\xC1\x24\x34\xAF\x58" - "\xBF\x2C\x59\xCA\x90\x77\xF3\xB0" - "\x5B\x4A\xDF\x89\xCE\x2C\x2F\xFC" - "\x67\xF0\xE3\x45\xE8\xB3\xB3\x75" - "\xA0\x95\x71\xA1\x29\x39\x94\xCA" - "\x45\x2F\xBD\xCB\x10\xB6\xBE\x9F" - "\x8E\xF9\xB2\x01\x0A\x5A\x0A\xB7" - "\x6B\x9D\x70\x8E\x4B\xD6\x2F\xCD" - "\x2E\x40\x48\x75\xE9\xE2\x21\x45" - "\x0B\xC9\xB6\xB5\x66\xBC\x9A\x59" - "\x5A", - .rlen = 129, - }, { /* large test vector generated using Crypto++ */ - .key = "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - .klen = 32, - .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00", - .input = - "\x00\x01\x02\x03\x04\x05\x06\x07" - "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" - "\x10\x11\x12\x13\x14\x15\x16\x17" - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" - "\x20\x21\x22\x23\x24\x25\x26\x27" - "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" - "\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" - "\x40\x41\x42\x43\x44\x45\x46\x47" - "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" - "\x50\x51\x52\x53\x54\x55\x56\x57" - "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" - "\x60\x61\x62\x63\x64\x65\x66\x67" - "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" - "\x70\x71\x72\x73\x74\x75\x76\x77" - "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87" - "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" - "\x90\x91\x92\x93\x94\x95\x96\x97" - "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" - "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" - "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" - "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" - "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" - "\xe8\xe9\xea\xeb\xec\xed\xee\xef" - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" - "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" - "\x00\x03\x06\x09\x0c\x0f\x12\x15" - "\x18\x1b\x1e\x21\x24\x27\x2a\x2d" - "\x30\x33\x36\x39\x3c\x3f\x42\x45" - "\x48\x4b\x4e\x51\x54\x57\x5a\x5d" - "\x60\x63\x66\x69\x6c\x6f\x72\x75" - "\x78\x7b\x7e\x81\x84\x87\x8a\x8d" - "\x90\x93\x96\x99\x9c\x9f\xa2\xa5" - "\xa8\xab\xae\xb1\xb4\xb7\xba\xbd" - "\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5" - "\xd8\xdb\xde\xe1\xe4\xe7\xea\xed" - "\xf0\xf3\xf6\xf9\xfc\xff\x02\x05" - "\x08\x0b\x0e\x11\x14\x17\x1a\x1d" - "\x20\x23\x26\x29\x2c\x2f\x32\x35" - "\x38\x3b\x3e\x41\x44\x47\x4a\x4d" - "\x50\x53\x56\x59\x5c\x5f\x62\x65" - "\x68\x6b\x6e\x71\x74\x77\x7a\x7d" - "\x80\x83\x86\x89\x8c\x8f\x92\x95" - "\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad" - "\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5" - "\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd" - "\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5" - "\xf8\xfb\xfe\x01\x04\x07\x0a\x0d" - "\x10\x13\x16\x19\x1c\x1f\x22\x25" - "\x28\x2b\x2e\x31\x34\x37\x3a\x3d" - "\x40\x43\x46\x49\x4c\x4f\x52\x55" - "\x58\x5b\x5e\x61\x64\x67\x6a\x6d" - "\x70\x73\x76\x79\x7c\x7f\x82\x85" - "\x88\x8b\x8e\x91\x94\x97\x9a\x9d" - "\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5" - "\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd" - "\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5" - "\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd" - "\x00\x05\x0a\x0f\x14\x19\x1e\x23" - "\x28\x2d\x32\x37\x3c\x41\x46\x4b" - "\x50\x55\x5a\x5f\x64\x69\x6e\x73" - "\x78\x7d\x82\x87\x8c\x91\x96\x9b" - "\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3" - "\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb" - "\xf0\xf5\xfa\xff\x04\x09\x0e\x13" - "\x18\x1d\x22\x27\x2c\x31\x36\x3b" - "\x40\x45\x4a\x4f\x54\x59\x5e\x63" - "\x68\x6d\x72\x77\x7c\x81\x86\x8b" - "\x90\x95\x9a\x9f\xa4\xa9\xae\xb3" - "\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb" - "\xe0\xe5\xea\xef\xf4\xf9\xfe\x03" - "\x08\x0d\x12\x17\x1c\x21\x26\x2b" - "\x30\x35\x3a\x3f\x44\x49\x4e\x53" - "\x58\x5d\x62\x67\x6c\x71\x76\x7b" - "\x80\x85\x8a\x8f\x94\x99\x9e\xa3" - "\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb" - "\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3" - "\xf8\xfd\x02\x07\x0c\x11\x16\x1b" - "\x20\x25\x2a\x2f\x34\x39\x3e\x43" - "\x48\x4d\x52\x57\x5c\x61\x66\x6b" - "\x70\x75\x7a\x7f\x84\x89\x8e\x93" - "\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb" - "\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3" - "\xe8\xed\xf2\xf7\xfc\x01\x06\x0b" - "\x10\x15\x1a\x1f\x24\x29\x2e\x33" - "\x38\x3d\x42\x47\x4c\x51\x56\x5b" - "\x60\x65\x6a\x6f\x74\x79\x7e\x83" - "\x88\x8d\x92\x97\x9c\xa1\xa6\xab" - "\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3" - "\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb" - "\x00\x07\x0e\x15\x1c\x23\x2a\x31" - "\x38\x3f\x46\x4d\x54\x5b\x62\x69" - "\x70\x77\x7e\x85\x8c\x93\x9a\xa1" - "\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9" - "\xe0\xe7\xee\xf5\xfc\x03\x0a\x11" - "\x18\x1f\x26\x2d\x34\x3b\x42\x49" - "\x50\x57\x5e\x65\x6c\x73\x7a\x81" - "\x88\x8f\x96\x9d\xa4\xab\xb2\xb9" - "\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1" - "\xf8\xff\x06\x0d\x14\x1b\x22\x29" - "\x30\x37\x3e\x45\x4c\x53\x5a\x61" - "\x68\x6f\x76\x7d\x84\x8b\x92\x99" - "\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1" - "\xd8\xdf\xe6\xed\xf4\xfb\x02\x09" - "\x10\x17\x1e\x25\x2c\x33\x3a\x41" - "\x48\x4f\x56\x5d\x64\x6b\x72\x79" - "\x80\x87\x8e\x95\x9c\xa3\xaa\xb1" - "\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9" - "\xf0\xf7\xfe\x05\x0c\x13\x1a\x21" - "\x28\x2f\x36\x3d\x44\x4b\x52\x59" - "\x60\x67\x6e\x75\x7c\x83\x8a\x91" - "\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9" - "\xd0\xd7\xde\xe5\xec\xf3\xfa\x01" - "\x08\x0f\x16\x1d\x24\x2b\x32\x39" - "\x40\x47\x4e\x55\x5c\x63\x6a\x71" - "\x78\x7f\x86\x8d\x94\x9b\xa2\xa9" - "\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1" - "\xe8\xef\xf6\xfd\x04\x0b\x12\x19" - "\x20\x27\x2e\x35\x3c\x43\x4a\x51" - "\x58\x5f\x66\x6d\x74\x7b\x82\x89" - "\x90\x97\x9e\xa5\xac\xb3\xba\xc1" - "\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9" - "\x00\x09\x12\x1b\x24\x2d\x36\x3f" - "\x48\x51\x5a\x63\x6c\x75\x7e\x87" - "\x90\x99\xa2\xab\xb4\xbd\xc6\xcf" - "\xd8\xe1\xea\xf3\xfc\x05\x0e\x17" - "\x20\x29\x32\x3b\x44\x4d\x56\x5f" - "\x68\x71\x7a\x83\x8c\x95\x9e\xa7" - "\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef" - "\xf8\x01\x0a\x13\x1c\x25\x2e\x37" - "\x40\x49\x52\x5b\x64\x6d\x76\x7f" - "\x88\x91\x9a\xa3\xac\xb5\xbe\xc7" - "\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f" - "\x18\x21\x2a\x33\x3c\x45\x4e\x57" - "\x60\x69\x72\x7b\x84\x8d\x96\x9f" - "\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7" - "\xf0\xf9\x02\x0b\x14\x1d\x26\x2f" - "\x38\x41\x4a\x53\x5c\x65\x6e\x77" - "\x80\x89\x92\x9b\xa4\xad\xb6\xbf" - "\xc8\xd1\xda\xe3\xec\xf5\xfe\x07" - "\x10\x19\x22\x2b\x34\x3d\x46\x4f" - "\x58\x61\x6a\x73\x7c\x85\x8e\x97" - "\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf" - "\xe8\xf1\xfa\x03\x0c\x15\x1e\x27" - "\x30\x39\x42\x4b\x54\x5d\x66\x6f" - "\x78\x81\x8a\x93\x9c\xa5\xae\xb7" - "\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff" - "\x08\x11\x1a\x23\x2c\x35\x3e\x47" - "\x50\x59\x62\x6b\x74\x7d\x86\x8f" - "\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7" - "\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f" - "\x28\x31\x3a\x43\x4c\x55\x5e\x67" - "\x70\x79\x82\x8b\x94\x9d\xa6\xaf" - "\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7" - "\x00\x0b\x16\x21\x2c\x37\x42\x4d" - "\x58\x63\x6e\x79\x84\x8f\x9a\xa5" - "\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd" - "\x08\x13\x1e\x29\x34\x3f\x4a\x55" - "\x60\x6b\x76\x81\x8c\x97\xa2\xad" - "\xb8\xc3\xce\xd9\xe4\xef\xfa\x05" - "\x10\x1b\x26\x31\x3c\x47\x52\x5d" - "\x68\x73\x7e\x89\x94\x9f\xaa\xb5" - "\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d" - "\x18\x23\x2e\x39\x44\x4f\x5a\x65" - "\x70\x7b\x86\x91\x9c\xa7\xb2\xbd" - "\xc8\xd3\xde\xe9\xf4\xff\x0a\x15" - "\x20\x2b\x36\x41\x4c\x57\x62\x6d" - "\x78\x83\x8e\x99\xa4\xaf\xba\xc5" - "\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d" - "\x28\x33\x3e\x49\x54\x5f\x6a\x75" - "\x80\x8b\x96\xa1\xac\xb7\xc2\xcd" - "\xd8\xe3\xee\xf9\x04\x0f\x1a\x25" - "\x30\x3b\x46\x51\x5c\x67\x72\x7d" - "\x88\x93\x9e\xa9\xb4\xbf\xca\xd5" - "\xe0\xeb\xf6\x01\x0c\x17\x22\x2d" - "\x38\x43\x4e\x59\x64\x6f\x7a\x85" - "\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd" - "\xe8\xf3\xfe\x09\x14\x1f\x2a\x35" - "\x40\x4b\x56\x61\x6c\x77\x82\x8d" - "\x98\xa3\xae\xb9\xc4\xcf\xda\xe5" - "\xf0\xfb\x06\x11\x1c\x27\x32\x3d" - "\x48\x53\x5e\x69\x74\x7f\x8a\x95" - "\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed" - "\xf8\x03\x0e\x19\x24\x2f\x3a\x45" - "\x50\x5b\x66\x71\x7c\x87\x92\x9d" - "\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5" - "\x00\x0d\x1a\x27\x34\x41\x4e\x5b" - "\x68\x75\x82\x8f\x9c\xa9\xb6\xc3" - "\xd0\xdd\xea\xf7\x04\x11\x1e\x2b" - "\x38\x45\x52\x5f\x6c\x79\x86\x93" - "\xa0\xad\xba\xc7\xd4\xe1\xee\xfb" - "\x08\x15\x22\x2f\x3c\x49\x56\x63" - "\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb" - "\xd8\xe5\xf2\xff\x0c\x19\x26\x33" - "\x40\x4d\x5a\x67\x74\x81\x8e\x9b" - "\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03" - "\x10\x1d\x2a\x37\x44\x51\x5e\x6b" - "\x78\x85\x92\x9f\xac\xb9\xc6\xd3" - "\xe0\xed\xfa\x07\x14\x21\x2e\x3b" - "\x48\x55\x62\x6f\x7c\x89\x96\xa3" - "\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b" - "\x18\x25\x32\x3f\x4c\x59\x66\x73" - "\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb" - "\xe8\xf5\x02\x0f\x1c\x29\x36\x43" - "\x50\x5d\x6a\x77\x84\x91\x9e\xab" - "\xb8\xc5\xd2\xdf\xec\xf9\x06\x13" - "\x20\x2d\x3a\x47\x54\x61\x6e\x7b" - "\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3" - "\xf0\xfd\x0a\x17\x24\x31\x3e\x4b" - "\x58\x65\x72\x7f\x8c\x99\xa6\xb3" - "\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b" - "\x28\x35\x42\x4f\x5c\x69\x76\x83" - "\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb" - "\xf8\x05\x12\x1f\x2c\x39\x46\x53" - "\x60\x6d\x7a\x87\x94\xa1\xae\xbb" - "\xc8\xd5\xe2\xef\xfc\x09\x16\x23" - "\x30\x3d\x4a\x57\x64\x71\x7e\x8b" - "\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3" - "\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69" - "\x78\x87\x96\xa5\xb4\xc3\xd2\xe1" - "\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59" - "\x68\x77\x86\x95\xa4\xb3\xc2\xd1" - "\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49" - "\x58\x67\x76\x85\x94\xa3\xb2\xc1" - "\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39" - "\x48\x57\x66\x75\x84\x93\xa2\xb1" - "\xc0\xcf\xde\xed\xfc\x0b\x1a\x29" - "\x38\x47\x56\x65\x74\x83\x92\xa1" - "\xb0\xbf\xce\xdd\xec\xfb\x0a\x19" - "\x28\x37\x46\x55\x64\x73\x82\x91" - "\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09" - "\x18\x27\x36\x45\x54\x63\x72\x81" - "\x90\x9f\xae\xbd\xcc\xdb\xea\xf9" - "\x08\x17\x26\x35\x44\x53\x62\x71" - "\x80\x8f\x9e\xad\xbc\xcb\xda\xe9" - "\xf8\x07\x16\x25\x34\x43\x52\x61" - "\x70\x7f\x8e\x9d\xac\xbb\xca\xd9" - "\xe8\xf7\x06\x15\x24\x33\x42\x51" - "\x60\x6f\x7e\x8d\x9c\xab\xba\xc9" - "\xd8\xe7\xf6\x05\x14\x23\x32\x41" - "\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9" - "\xc8\xd7\xe6\xf5\x04\x13\x22\x31" - "\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9" - "\xb8\xc7\xd6\xe5\xf4\x03\x12\x21" - "\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99" - "\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11" - "\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89" - "\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01" - "\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79" - "\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1" - "\x00\x11\x22\x33\x44\x55\x66\x77" - "\x88\x99\xaa\xbb\xcc\xdd\xee\xff" - "\x10\x21\x32\x43\x54\x65\x76\x87" - "\x98\xa9\xba\xcb\xdc\xed\xfe\x0f" - "\x20\x31\x42\x53\x64\x75\x86\x97" - "\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f" - "\x30\x41\x52\x63\x74\x85\x96\xa7" - "\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f" - "\x40\x51\x62\x73\x84\x95\xa6\xb7" - "\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f" - "\x50\x61\x72\x83\x94\xa5\xb6\xc7" - "\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f" - "\x60\x71\x82\x93\xa4\xb5\xc6\xd7" - "\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f" - "\x70\x81\x92\xa3\xb4\xc5\xd6\xe7" - "\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f" - "\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7" - "\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f" - "\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07" - "\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f" - "\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17" - "\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f" - "\xb0\xc1\xd2\xe3\xf4\x05\x16\x27" - "\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf" - "\xc0\xd1\xe2\xf3\x04\x15\x26\x37" - "\x48\x59\x6a\x7b\x8c\x9d\xae\xbf" - "\xd0\xe1\xf2\x03\x14\x25\x36\x47" - "\x58\x69\x7a\x8b\x9c\xad\xbe\xcf" - "\xe0\xf1\x02\x13\x24\x35\x46\x57" - "\x68\x79\x8a\x9b\xac\xbd\xce\xdf" - "\xf0\x01\x12\x23\x34\x45\x56\x67" - "\x78\x89\x9a\xab\xbc\xcd\xde\xef" - "\x00\x13\x26\x39\x4c\x5f\x72\x85" - "\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d" - "\x30\x43\x56\x69\x7c\x8f\xa2\xb5" - "\xc8\xdb\xee\x01\x14\x27\x3a\x4d" - "\x60\x73\x86\x99\xac\xbf\xd2\xe5" - "\xf8\x0b\x1e\x31\x44\x57\x6a\x7d" - "\x90\xa3\xb6\xc9\xdc\xef\x02\x15" - "\x28\x3b\x4e\x61\x74\x87\x9a\xad" - "\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45" - "\x58\x6b\x7e\x91\xa4\xb7\xca\xdd" - "\xf0\x03\x16\x29\x3c\x4f\x62\x75" - "\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d" - "\x20\x33\x46\x59\x6c\x7f\x92\xa5" - "\xb8\xcb\xde\xf1\x04\x17\x2a\x3d" - "\x50\x63\x76\x89\x9c\xaf\xc2\xd5" - "\xe8\xfb\x0e\x21\x34\x47\x5a\x6d" - "\x80\x93\xa6\xb9\xcc\xdf\xf2\x05" - "\x18\x2b\x3e\x51\x64\x77\x8a\x9d" - "\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35" - "\x48\x5b\x6e\x81\x94\xa7\xba\xcd" - "\xe0\xf3\x06\x19\x2c\x3f\x52\x65" - "\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd" - "\x10\x23\x36\x49\x5c\x6f\x82\x95" - "\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d" - "\x40\x53\x66\x79\x8c\x9f\xb2\xc5" - "\xd8\xeb\xfe\x11\x24\x37\x4a\x5d" - "\x70\x83\x96\xa9\xbc\xcf\xe2\xf5" - "\x08\x1b\x2e\x41\x54\x67\x7a\x8d" - "\xa0\xb3\xc6\xd9\xec\xff\x12\x25" - "\x38\x4b\x5e\x71\x84\x97\xaa\xbd" - "\xd0\xe3\xf6\x09\x1c\x2f\x42\x55" - "\x68\x7b\x8e\xa1\xb4\xc7\xda\xed" - "\x00\x15\x2a\x3f\x54\x69\x7e\x93" - "\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b" - "\x50\x65\x7a\x8f\xa4\xb9\xce\xe3" - "\xf8\x0d\x22\x37\x4c\x61\x76\x8b" - "\xa0\xb5\xca\xdf\xf4\x09\x1e\x33" - "\x48\x5d\x72\x87\x9c\xb1\xc6\xdb" - "\xf0\x05\x1a\x2f\x44\x59\x6e\x83" - "\x98\xad\xc2\xd7\xec\x01\x16\x2b" - "\x40\x55\x6a\x7f\x94\xa9\xbe\xd3" - "\xe8\xfd\x12\x27\x3c\x51\x66\x7b" - "\x90\xa5\xba\xcf\xe4\xf9\x0e\x23" - "\x38\x4d\x62\x77\x8c\xa1\xb6\xcb" - "\xe0\xf5\x0a\x1f\x34\x49\x5e\x73" - "\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b" - "\x30\x45\x5a\x6f\x84\x99\xae\xc3" - "\xd8\xed\x02\x17\x2c\x41\x56\x6b" - "\x80\x95\xaa\xbf\xd4\xe9\xfe\x13" - "\x28\x3d\x52\x67\x7c\x91\xa6\xbb" - "\xd0\xe5\xfa\x0f\x24\x39\x4e\x63" - "\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b" - "\x20\x35\x4a\x5f\x74\x89\x9e\xb3" - "\xc8\xdd\xf2\x07\x1c\x31\x46\x5b" - "\x70\x85\x9a\xaf\xc4\xd9\xee\x03" - "\x18\x2d\x42\x57\x6c\x81\x96\xab" - "\xc0\xd5\xea\xff\x14\x29\x3e\x53" - "\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb" - "\x10\x25\x3a\x4f\x64\x79\x8e\xa3" - "\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b" - "\x60\x75\x8a\x9f\xb4\xc9\xde\xf3" - "\x08\x1d\x32\x47\x5c\x71\x86\x9b" - "\xb0\xc5\xda\xef\x04\x19\x2e\x43" - "\x58\x6d\x82\x97\xac\xc1\xd6\xeb" - "\x00\x17\x2e\x45\x5c\x73\x8a\xa1" - "\xb8\xcf\xe6\xfd\x14\x2b\x42\x59" - "\x70\x87\x9e\xb5\xcc\xe3\xfa\x11" - "\x28\x3f\x56\x6d\x84\x9b\xb2\xc9" - "\xe0\xf7\x0e\x25\x3c\x53\x6a\x81" - "\x98\xaf\xc6\xdd\xf4\x0b\x22\x39" - "\x50\x67\x7e\x95\xac\xc3\xda\xf1" - "\x08\x1f\x36\x4d\x64\x7b\x92\xa9" - "\xc0\xd7\xee\x05\x1c\x33\x4a\x61" - "\x78\x8f\xa6\xbd\xd4\xeb\x02\x19" - "\x30\x47\x5e\x75\x8c\xa3\xba\xd1" - "\xe8\xff\x16\x2d\x44\x5b\x72\x89" - "\xa0\xb7\xce\xe5\xfc\x13\x2a\x41" - "\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9" - "\x10\x27\x3e\x55\x6c\x83\x9a\xb1" - "\xc8\xdf\xf6\x0d\x24\x3b\x52\x69" - "\x80\x97\xae\xc5\xdc\xf3\x0a\x21" - "\x38\x4f\x66\x7d\x94\xab\xc2\xd9" - "\xf0\x07\x1e\x35\x4c\x63\x7a\x91" - "\xa8\xbf\xd6\xed\x04\x1b\x32\x49" - "\x60\x77\x8e\xa5\xbc\xd3\xea\x01" - "\x18\x2f\x46\x5d\x74\x8b\xa2\xb9" - "\xd0\xe7\xfe\x15\x2c\x43\x5a\x71" - "\x88\x9f\xb6\xcd\xe4\xfb\x12\x29" - "\x40\x57\x6e\x85\x9c\xb3\xca\xe1" - "\xf8\x0f\x26\x3d\x54\x6b\x82\x99" - "\xb0\xc7\xde\xf5\x0c\x23\x3a\x51" - "\x68\x7f\x96\xad\xc4\xdb\xf2\x09" - "\x20\x37\x4e\x65\x7c\x93\xaa\xc1" - "\xd8\xef\x06\x1d\x34\x4b\x62\x79" - "\x90\xa7\xbe\xd5\xec\x03\x1a\x31" - "\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9" - "\x00\x19\x32\x4b\x64\x7d\x96\xaf" - "\xc8\xe1\xfa\x13\x2c\x45\x5e\x77" - "\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f" - "\x58\x71\x8a\xa3\xbc\xd5\xee\x07" - "\x20\x39\x52\x6b\x84\x9d\xb6\xcf" - "\xe8\x01\x1a\x33\x4c\x65\x7e\x97" - "\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f" - "\x78\x91\xaa\xc3\xdc\xf5\x0e\x27" - "\x40\x59\x72\x8b\xa4\xbd\xd6\xef" - "\x08\x21\x3a\x53\x6c\x85\x9e\xb7" - "\xd0\xe9\x02\x1b\x34\x4d\x66\x7f" - "\x98\xb1\xca\xe3\xfc\x15\x2e\x47" - "\x60\x79\x92\xab\xc4\xdd\xf6\x0f" - "\x28\x41\x5a\x73\x8c\xa5\xbe\xd7" - "\xf0\x09\x22\x3b\x54\x6d\x86\x9f" - "\xb8\xd1\xea\x03\x1c\x35\x4e\x67" - "\x80\x99\xb2\xcb\xe4\xfd\x16\x2f" - "\x48\x61\x7a\x93\xac\xc5\xde\xf7" - "\x10\x29\x42\x5b\x74\x8d\xa6\xbf" - "\xd8\xf1\x0a\x23\x3c\x55\x6e\x87" - "\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f" - "\x68\x81\x9a\xb3\xcc\xe5\xfe\x17" - "\x30\x49\x62\x7b\x94\xad\xc6\xdf" - "\xf8\x11\x2a\x43\x5c\x75\x8e\xa7" - "\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f" - "\x88\xa1\xba\xd3\xec\x05\x1e\x37" - "\x50\x69\x82\x9b\xb4\xcd\xe6\xff" - "\x18\x31\x4a\x63\x7c\x95\xae\xc7" - "\xe0\xf9\x12\x2b\x44\x5d\x76\x8f" - "\xa8\xc1\xda\xf3\x0c\x25\x3e\x57" - "\x70\x89\xa2\xbb\xd4\xed\x06\x1f" - "\x38\x51\x6a\x83\x9c\xb5\xce\xe7" - "\x00\x1b\x36\x51\x6c\x87\xa2\xbd" - "\xd8\xf3\x0e\x29\x44\x5f\x7a\x95" - "\xb0\xcb\xe6\x01\x1c\x37\x52\x6d" - "\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45" - "\x60\x7b\x96\xb1\xcc\xe7\x02\x1d" - "\x38\x53\x6e\x89\xa4\xbf\xda\xf5" - "\x10\x2b\x46\x61\x7c\x97\xb2\xcd" - "\xe8\x03\x1e\x39\x54\x6f\x8a\xa5" - "\xc0\xdb\xf6\x11\x2c\x47\x62\x7d" - "\x98\xb3\xce\xe9\x04\x1f\x3a\x55" - "\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d" - "\x48\x63\x7e\x99\xb4\xcf\xea\x05" - "\x20\x3b\x56\x71\x8c\xa7\xc2\xdd" - "\xf8\x13\x2e\x49\x64\x7f\x9a\xb5" - "\xd0\xeb\x06\x21\x3c\x57\x72\x8d" - "\xa8\xc3\xde\xf9\x14\x2f\x4a\x65" - "\x80\x9b\xb6\xd1\xec\x07\x22\x3d" - "\x58\x73\x8e\xa9\xc4\xdf\xfa\x15" - "\x30\x4b\x66\x81\x9c\xb7\xd2\xed" - "\x08\x23\x3e\x59\x74\x8f\xaa\xc5" - "\xe0\xfb\x16\x31\x4c\x67\x82\x9d" - "\xb8\xd3\xee\x09\x24\x3f\x5a\x75" - "\x90\xab\xc6\xe1\xfc\x17\x32\x4d" - "\x68\x83\x9e\xb9\xd4\xef\x0a\x25" - "\x40\x5b\x76\x91\xac\xc7\xe2\xfd" - "\x18\x33\x4e\x69\x84\x9f\xba\xd5" - "\xf0\x0b\x26\x41\x5c\x77\x92\xad" - "\xc8\xe3\xfe\x19\x34\x4f\x6a\x85" - "\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d" - "\x78\x93\xae\xc9\xe4\xff\x1a\x35" - "\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d" - "\x28\x43\x5e\x79\x94\xaf\xca\xe5" - "\x00\x1d\x3a\x57\x74\x91\xae\xcb" - "\xe8\x05\x22\x3f\x5c\x79\x96\xb3" - "\xd0\xed\x0a\x27\x44\x61\x7e\x9b" - "\xb8\xd5\xf2\x0f\x2c\x49\x66\x83" - "\xa0\xbd\xda\xf7\x14\x31\x4e\x6b" - "\x88\xa5\xc2\xdf\xfc\x19\x36\x53" - "\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b" - "\x58\x75\x92\xaf\xcc\xe9\x06\x23" - "\x40\x5d\x7a\x97\xb4\xd1\xee\x0b" - "\x28\x45\x62\x7f\x9c\xb9\xd6\xf3" - "\x10\x2d\x4a\x67\x84\xa1\xbe\xdb" - "\xf8\x15\x32\x4f\x6c\x89\xa6\xc3" - "\xe0\xfd\x1a\x37\x54\x71\x8e\xab" - "\xc8\xe5\x02\x1f\x3c\x59\x76\x93" - "\xb0\xcd\xea\x07\x24\x41\x5e\x7b" - "\x98\xb5\xd2\xef\x0c\x29\x46\x63" - "\x80\x9d\xba\xd7\xf4\x11\x2e\x4b" - "\x68\x85\xa2\xbf\xdc\xf9\x16\x33" - "\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b" - "\x38\x55\x72\x8f\xac\xc9\xe6\x03" - "\x20\x3d\x5a\x77\x94\xb1\xce\xeb" - "\x08\x25\x42\x5f\x7c\x99\xb6\xd3" - "\xf0\x0d\x2a\x47\x64\x81\x9e\xbb" - "\xd8\xf5\x12\x2f\x4c\x69\x86\xa3" - "\xc0\xdd\xfa\x17\x34\x51\x6e\x8b" - "\xa8\xc5\xe2\xff\x1c\x39\x56\x73" - "\x90\xad\xca\xe7\x04\x21\x3e\x5b" - "\x78\x95\xb2\xcf\xec\x09\x26\x43" - "\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b" - "\x48\x65\x82\x9f\xbc\xd9\xf6\x13" - "\x30\x4d\x6a\x87\xa4\xc1\xde\xfb" - "\x18\x35\x52\x6f\x8c\xa9\xc6\xe3" - "\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9" - "\xf8\x17\x36\x55\x74\x93\xb2\xd1" - "\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9" - "\xe8\x07\x26\x45\x64\x83\xa2\xc1" - "\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9" - "\xd8\xf7\x16\x35\x54\x73\x92\xb1" - "\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9" - "\xc8\xe7\x06\x25\x44\x63\x82\xa1" - "\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99" - "\xb8\xd7\xf6\x15\x34\x53\x72\x91" - "\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89" - "\xa8\xc7\xe6\x05\x24\x43\x62\x81" - "\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79" - "\x98\xb7\xd6\xf5\x14\x33\x52\x71" - "\x90\xaf\xce\xed\x0c\x2b\x4a\x69" - "\x88\xa7\xc6\xe5\x04\x23\x42\x61" - "\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59" - "\x78\x97\xb6\xd5\xf4\x13\x32\x51" - "\x70\x8f\xae\xcd\xec\x0b\x2a\x49" - "\x68\x87\xa6\xc5\xe4\x03\x22\x41" - "\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39" - "\x58\x77\x96\xb5\xd4\xf3\x12\x31" - "\x50\x6f\x8e\xad\xcc\xeb\x0a\x29" - "\x48\x67\x86\xa5\xc4\xe3\x02\x21" - "\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19" - "\x38\x57\x76\x95\xb4\xd3\xf2\x11" - "\x30\x4f\x6e\x8d\xac\xcb\xea\x09" - "\x28\x47\x66\x85\xa4\xc3\xe2\x01" - "\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9" - "\x18\x37\x56\x75\x94\xb3\xd2\xf1" - "\x10\x2f\x4e\x6d\x8c\xab\xca\xe9" - "\x08\x27\x46\x65\x84\xa3\xc2\xe1" - "\x00\x21\x42\x63", - .ilen = 4100, - .result = - "\xb5\x81\xf5\x64\x18\x73\xe3\xf0" - "\x4c\x13\xf2\x77\x18\x60\x65\x5e" - "\x29\x01\xce\x98\x55\x53\xf9\x0c" - "\x2a\x08\xd5\x09\xb3\x57\x55\x56" - "\xc5\xe9\x56\x90\xcb\x6a\xa3\xc0" - "\xff\xc4\x79\xb4\xd2\x97\x5d\xc4" - "\x43\xd1\xfe\x94\x7b\x88\x06\x5a" - "\xb2\x9e\x2c\xfc\x44\x03\xb7\x90" - "\xa0\xc1\xba\x6a\x33\xb8\xc7\xb2" - "\x9d\xe1\x12\x4f\xc0\x64\xd4\x01" - "\xfe\x8c\x7a\x66\xf7\xe6\x5a\x91" - "\xbb\xde\x56\x86\xab\x65\x21\x30" - "\x00\x84\x65\x24\xa5\x7d\x85\xb4" - "\xe3\x17\xed\x3a\xb7\x6f\xb4\x0b" - "\x0b\xaf\x15\xae\x5a\x8f\xf2\x0c" - "\x2f\x27\xf4\x09\xd8\xd2\x96\xb7" - "\x71\xf2\xc5\x99\x4d\x7e\x7f\x75" - "\x77\x89\x30\x8b\x59\xdb\xa2\xb2" - "\xa0\xf3\x19\x39\x2b\xc5\x7e\x3f" - "\x4f\xd9\xd3\x56\x28\x97\x44\xdc" - "\xc0\x8b\x77\x24\xd9\x52\xe7\xc5" - "\xaf\xf6\x7d\x59\xb2\x44\x05\x1d" - "\xb1\xb0\x11\xa5\x0f\xec\x33\xe1" - "\x6d\x1b\x4e\x1f\xff\x57\x91\xb4" - "\x5b\x9a\x96\xc5\x53\xbc\xae\x20" - "\x3c\xbb\x14\xe2\xe8\x22\x33\xc1" - "\x5e\x76\x9e\x46\x99\xf6\x2a\x15" - "\xc6\x97\x02\xa0\x66\x43\xd1\xa6" - "\x31\xa6\x9f\xfb\xf4\xd3\x69\xe5" - "\xcd\x76\x95\xb8\x7a\x82\x7f\x21" - "\x45\xff\x3f\xce\x55\xf6\x95\x10" - "\x08\x77\x10\x43\xc6\xf3\x09\xe5" - "\x68\xe7\x3c\xad\x00\x52\x45\x0d" - "\xfe\x2d\xc6\xc2\x94\x8c\x12\x1d" - "\xe6\x25\xae\x98\x12\x8e\x19\x9c" - "\x81\x68\xb1\x11\xf6\x69\xda\xe3" - "\x62\x08\x18\x7a\x25\x49\x28\xac" - "\xba\x71\x12\x0b\xe4\xa2\xe5\xc7" - "\x5d\x8e\xec\x49\x40\x21\xbf\x5a" - "\x98\xf3\x02\x68\x55\x03\x7f\x8a" - "\xe5\x94\x0c\x32\x5c\x07\x82\x63" - "\xaf\x6f\x91\x40\x84\x8e\x52\x25" - "\xd0\xb0\x29\x53\x05\xe2\x50\x7a" - "\x34\xeb\xc9\x46\x20\xa8\x3d\xde" - "\x7f\x16\x5f\x36\xc5\x2e\xdc\xd1" - "\x15\x47\xc7\x50\x40\x6d\x91\xc5" - "\xe7\x93\x95\x1a\xd3\x57\xbc\x52" - "\x33\xee\x14\x19\x22\x52\x89\xa7" - "\x4a\x25\x56\x77\x4b\xca\xcf\x0a" - "\xe1\xf5\x35\x85\x30\x7e\x59\x4a" - "\xbd\x14\x5b\xdf\xe3\x46\xcb\xac" - "\x1f\x6c\x96\x0e\xf4\x81\xd1\x99" - "\xca\x88\x63\x3d\x02\x58\x6b\xa9" - "\xe5\x9f\xb3\x00\xb2\x54\xc6\x74" - "\x1c\xbf\x46\xab\x97\xcc\xf8\x54" - "\x04\x07\x08\x52\xe6\xc0\xda\x93" - "\x74\x7d\x93\x99\x5d\x78\x68\xa6" - "\x2e\x6b\xd3\x6a\x69\xcc\x12\x6b" - "\xd4\xc7\xa5\xc6\xe7\xf6\x03\x04" - "\x5d\xcd\x61\x5e\x17\x40\xdc\xd1" - "\x5c\xf5\x08\xdf\x5c\x90\x85\xa4" - "\xaf\xf6\x78\xbb\x0d\xf1\xf4\xa4" - "\x54\x26\x72\x9e\x61\xfa\x86\xcf" - "\xe8\x9e\xa1\xe0\xc7\x48\x23\xae" - "\x5a\x90\xae\x75\x0a\x74\x18\x89" - "\x05\xb1\x92\xb2\x7f\xd0\x1b\xa6" - "\x62\x07\x25\x01\xc7\xc2\x4f\xf9" - "\xe8\xfe\x63\x95\x80\x07\xb4\x26" - "\xcc\xd1\x26\xb6\xc4\x3f\x9e\xcb" - "\x8e\x3b\x2e\x44\x16\xd3\x10\x9a" - "\x95\x08\xeb\xc8\xcb\xeb\xbf\x6f" - "\x0b\xcd\x1f\xc8\xca\x86\xaa\xec" - "\x33\xe6\x69\xf4\x45\x25\x86\x3a" - "\x22\x94\x4f\x00\x23\x6a\x44\xc2" - "\x49\x97\x33\xab\x36\x14\x0a\x70" - "\x24\xc3\xbe\x04\x3b\x79\xa0\xf9" - "\xb8\xe7\x76\x29\x22\x83\xd7\xf2" - "\x94\xf4\x41\x49\xba\x5f\x7b\x07" - "\xb5\xfb\xdb\x03\x1a\x9f\xb6\x4c" - "\xc2\x2e\x37\x40\x49\xc3\x38\x16" - "\xe2\x4f\x77\x82\xb0\x68\x4c\x71" - "\x1d\x57\x61\x9c\xd9\x4e\x54\x99" - "\x47\x13\x28\x73\x3c\xbb\x00\x90" - "\xf3\x4d\xc9\x0e\xfd\xe7\xb1\x71" - "\xd3\x15\x79\xbf\xcc\x26\x2f\xbd" - "\xad\x6c\x50\x69\x6c\x3e\x6d\x80" - "\x9a\xea\x78\xaf\x19\xb2\x0d\x4d" - "\xad\x04\x07\xae\x22\x90\x4a\x93" - "\x32\x0e\x36\x9b\x1b\x46\xba\x3b" - "\xb4\xac\xc6\xd1\xa2\x31\x53\x3b" - "\x2a\x3d\x45\xfe\x03\x61\x10\x85" - "\x17\x69\xa6\x78\xcc\x6c\x87\x49" - "\x53\xf9\x80\x10\xde\x80\xa2\x41" - "\x6a\xc3\x32\x02\xad\x6d\x3c\x56" - "\x00\x71\x51\x06\xa7\xbd\xfb\xef" - "\x3c\xb5\x9f\xfc\x48\x7d\x53\x7c" - "\x66\xb0\x49\x23\xc4\x47\x10\x0e" - "\xe5\x6c\x74\x13\xe6\xc5\x3f\xaa" - "\xde\xff\x07\x44\xdd\x56\x1b\xad" - "\x09\x77\xfb\x5b\x12\xb8\x0d\x38" - "\x17\x37\x35\x7b\x9b\xbc\xfe\xd4" - "\x7e\x8b\xda\x7e\x5b\x04\xa7\x22" - "\xa7\x31\xa1\x20\x86\xc7\x1b\x99" - "\xdb\xd1\x89\xf4\x94\xa3\x53\x69" - "\x8d\xe7\xe8\x74\x11\x8d\x74\xd6" - "\x07\x37\x91\x9f\xfd\x67\x50\x3a" - "\xc9\xe1\xf4\x36\xd5\xa0\x47\xd1" - "\xf9\xe5\x39\xa3\x31\xac\x07\x36" - "\x23\xf8\x66\x18\x14\x28\x34\x0f" - "\xb8\xd0\xe7\x29\xb3\x04\x4b\x55" - "\x01\x41\xb2\x75\x8d\xcb\x96\x85" - "\x3a\xfb\xab\x2b\x9e\xfa\x58\x20" - "\x44\x1f\xc0\x14\x22\x75\x61\xe8" - "\xaa\x19\xcf\xf1\x82\x56\xf4\xd7" - "\x78\x7b\x3d\x5f\xb3\x9e\x0b\x8a" - "\x57\x50\xdb\x17\x41\x65\x4d\xa3" - "\x02\xc9\x9c\x9c\x53\xfb\x39\x39" - "\x9b\x1d\x72\x24\xda\xb7\x39\xbe" - "\x13\x3b\xfa\x29\xda\x9e\x54\x64" - "\x6e\xba\xd8\xa1\xcb\xb3\x36\xfa" - "\xcb\x47\x85\xe9\x61\x38\xbc\xbe" - "\xc5\x00\x38\x2a\x54\xf7\xc4\xb9" - "\xb3\xd3\x7b\xa0\xa0\xf8\x72\x7f" - "\x8c\x8e\x82\x0e\xc6\x1c\x75\x9d" - "\xca\x8e\x61\x87\xde\xad\x80\xd2" - "\xf5\xf9\x80\xef\x15\x75\xaf\xf5" - "\x80\xfb\xff\x6d\x1e\x25\xb7\x40" - "\x61\x6a\x39\x5a\x6a\xb5\x31\xab" - "\x97\x8a\x19\x89\x44\x40\xc0\xa6" - "\xb4\x4e\x30\x32\x7b\x13\xe7\x67" - "\xa9\x8b\x57\x04\xc2\x01\xa6\xf4" - "\x28\x99\xad\x2c\x76\xa3\x78\xc2" - "\x4a\xe6\xca\x5c\x50\x6a\xc1\xb0" - "\x62\x4b\x10\x8e\x7c\x17\x43\xb3" - "\x17\x66\x1c\x3e\x8d\x69\xf0\x5a" - "\x71\xf5\x97\xdc\xd1\x45\xdd\x28" - "\xf3\x5d\xdf\x53\x7b\x11\xe5\xbc" - "\x4c\xdb\x1b\x51\x6b\xe9\xfb\x3d" - "\xc1\xc3\x2c\xb9\x71\xf5\xb6\xb2" - "\x13\x36\x79\x80\x53\xe8\xd3\xa6" - "\x0a\xaf\xfd\x56\x97\xf7\x40\x8e" - "\x45\xce\xf8\xb0\x9e\x5c\x33\x82" - "\xb0\x44\x56\xfc\x05\x09\xe9\x2a" - "\xac\x26\x80\x14\x1d\xc8\x3a\x35" - "\x4c\x82\x97\xfd\x76\xb7\xa9\x0a" - "\x35\x58\x79\x8e\x0f\x66\xea\xaf" - "\x51\x6c\x09\xa9\x6e\x9b\xcb\x9a" - "\x31\x47\xa0\x2f\x7c\x71\xb4\x4a" - "\x11\xaa\x8c\x66\xc5\x64\xe6\x3a" - "\x54\xda\x24\x6a\xc4\x41\x65\x46" - "\x82\xa0\x0a\x0f\x5f\xfb\x25\xd0" - "\x2c\x91\xa7\xee\xc4\x81\x07\x86" - "\x75\x5e\x33\x69\x97\xe4\x2c\xa8" - "\x9d\x9f\x0b\x6a\xbe\xad\x98\xda" - "\x6d\x94\x41\xda\x2c\x1e\x89\xc4" - "\xc2\xaf\x1e\x00\x05\x0b\x83\x60" - "\xbd\x43\xea\x15\x23\x7f\xb9\xac" - "\xee\x4f\x2c\xaf\x2a\xf3\xdf\xd0" - "\xf3\x19\x31\xbb\x4a\x74\x84\x17" - "\x52\x32\x2c\x7d\x61\xe4\xcb\xeb" - "\x80\x38\x15\x52\xcb\x6f\xea\xe5" - "\x73\x9c\xd9\x24\x69\xc6\x95\x32" - "\x21\xc8\x11\xe4\xdc\x36\xd7\x93" - "\x38\x66\xfb\xb2\x7f\x3a\xb9\xaf" - "\x31\xdd\x93\x75\x78\x8a\x2c\x94" - "\x87\x1a\x58\xec\x9e\x7d\x4d\xba" - "\xe1\xe5\x4d\xfc\xbc\xa4\x2a\x14" - "\xef\xcc\xa7\xec\xab\x43\x09\x18" - "\xd3\xab\x68\xd1\x07\x99\x44\x47" - "\xd6\x83\x85\x3b\x30\xea\xa9\x6b" - "\x63\xea\xc4\x07\xfb\x43\x2f\xa4" - "\xaa\xb0\xab\x03\x89\xce\x3f\x8c" - "\x02\x7c\x86\x54\xbc\x88\xaf\x75" - "\xd2\xdc\x63\x17\xd3\x26\xf6\x96" - "\xa9\x3c\xf1\x61\x8c\x11\x18\xcc" - "\xd6\xea\x5b\xe2\xcd\xf0\xf1\xb2" - "\xe5\x35\x90\x1f\x85\x4c\x76\x5b" - "\x66\xce\x44\xa4\x32\x9f\xe6\x7b" - "\x71\x6e\x9f\x58\x15\x67\x72\x87" - "\x64\x8e\x3a\x44\x45\xd4\x76\xfa" - "\xc2\xf6\xef\x85\x05\x18\x7a\x9b" - "\xba\x41\x54\xac\xf0\xfc\x59\x12" - "\x3f\xdf\xa0\xe5\x8a\x65\xfd\x3a" - "\x62\x8d\x83\x2c\x03\xbe\x05\x76" - "\x2e\x53\x49\x97\x94\x33\xae\x40" - "\x81\x15\xdb\x6e\xad\xaa\xf5\x4b" - "\xe3\x98\x70\xdf\xe0\x7c\xcd\xdb" - "\x02\xd4\x7d\x2f\xc1\xe6\xb4\xf3" - "\xd7\x0d\x7a\xd9\x23\x9e\x87\x2d" - "\xce\x87\xad\xcc\x72\x05\x00\x29" - "\xdc\x73\x7f\x64\xc1\x15\x0e\xc2" - "\xdf\xa7\x5f\xeb\x41\xa1\xcd\xef" - "\x5c\x50\x79\x2a\x56\x56\x71\x8c" - "\xac\xc0\x79\x50\x69\xca\x59\x32" - "\x65\xf2\x54\xe4\x52\x38\x76\xd1" - "\x5e\xde\x26\x9e\xfb\x75\x2e\x11" - "\xb5\x10\xf4\x17\x73\xf5\x89\xc7" - "\x4f\x43\x5c\x8e\x7c\xb9\x05\x52" - "\x24\x40\x99\xfe\x9b\x85\x0b\x6c" - "\x22\x3e\x8b\xae\x86\xa1\xd2\x79" - "\x05\x68\x6b\xab\xe3\x41\x49\xed" - "\x15\xa1\x8d\x40\x2d\x61\xdf\x1a" - "\x59\xc9\x26\x8b\xef\x30\x4c\x88" - "\x4b\x10\xf8\x8d\xa6\x92\x9f\x4b" - "\xf3\xc4\x53\x0b\x89\x5d\x28\x92" - "\xcf\x78\xb2\xc0\x5d\xed\x7e\xfc" - "\xc0\x12\x23\x5f\x5a\x78\x86\x43" - "\x6e\x27\xf7\x5a\xa7\x6a\xed\x19" - "\x04\xf0\xb3\x12\xd1\xbd\x0e\x89" - "\x6e\xbc\x96\xa8\xd8\x49\x39\x9f" - "\x7e\x67\xf0\x2e\x3e\x01\xa9\xba" - "\xec\x8b\x62\x8e\xcb\x4a\x70\x43" - "\xc7\xc2\xc4\xca\x82\x03\x73\xe9" - "\x11\xdf\xcf\x54\xea\xc9\xb0\x95" - "\x51\xc0\x13\x3d\x92\x05\xfa\xf4" - "\xa9\x34\xc8\xce\x6c\x3d\x54\xcc" - "\xc4\xaf\xf1\xdc\x11\x44\x26\xa2" - "\xaf\xf1\x85\x75\x7d\x03\x61\x68" - "\x4e\x78\xc6\x92\x7d\x86\x7d\x77" - "\xdc\x71\x72\xdb\xc6\xae\xa1\xcb" - "\x70\x9a\x0b\x19\xbe\x4a\x6c\x2a" - "\xe2\xba\x6c\x64\x9a\x13\x28\xdf" - "\x85\x75\xe6\x43\xf6\x87\x08\x68" - "\x6e\xba\x6e\x79\x9f\x04\xbc\x23" - "\x50\xf6\x33\x5c\x1f\x24\x25\xbe" - "\x33\x47\x80\x45\x56\xa3\xa7\xd7" - "\x7a\xb1\x34\x0b\x90\x3c\x9c\xad" - "\x44\x5f\x9e\x0e\x9d\xd4\xbd\x93" - "\x5e\xfa\x3c\xe0\xb0\xd9\xed\xf3" - "\xd6\x2e\xff\x24\xd8\x71\x6c\xed" - "\xaf\x55\xeb\x22\xac\x93\x68\x32" - "\x05\x5b\x47\xdd\xc6\x4a\xcb\xc7" - "\x10\xe1\x3c\x92\x1a\xf3\x23\x78" - "\x2b\xa1\xd2\x80\xf4\x12\xb1\x20" - "\x8f\xff\x26\x35\xdd\xfb\xc7\x4e" - "\x78\xf1\x2d\x50\x12\x77\xa8\x60" - "\x7c\x0f\xf5\x16\x2f\x63\x70\x2a" - "\xc0\x96\x80\x4e\x0a\xb4\x93\x35" - "\x5d\x1d\x3f\x56\xf7\x2f\xbb\x90" - "\x11\x16\x8f\xa2\xec\x47\xbe\xac" - "\x56\x01\x26\x56\xb1\x8c\xb2\x10" - "\xf9\x1a\xca\xf5\xd1\xb7\x39\x20" - "\x63\xf1\x69\x20\x4f\x13\x12\x1f" - "\x5b\x65\xfc\x98\xf7\xc4\x7a\xbe" - "\xf7\x26\x4d\x2b\x84\x7b\x42\xad" - "\xd8\x7a\x0a\xb4\xd8\x74\xbf\xc1" - "\xf0\x6e\xb4\x29\xa3\xbb\xca\x46" - "\x67\x70\x6a\x2d\xce\x0e\xa2\x8a" - "\xa9\x87\xbf\x05\xc4\xc1\x04\xa3" - "\xab\xd4\x45\x43\x8c\xb6\x02\xb0" - "\x41\xc8\xfc\x44\x3d\x59\xaa\x2e" - "\x44\x21\x2a\x8d\x88\x9d\x57\xf4" - "\xa0\x02\x77\xb8\xa6\xa0\xe6\x75" - "\x5c\x82\x65\x3e\x03\x5c\x29\x8f" - "\x38\x55\xab\x33\x26\xef\x9f\x43" - "\x52\xfd\x68\xaf\x36\xb4\xbb\x9a" - "\x58\x09\x09\x1b\xc3\x65\x46\x46" - "\x1d\xa7\x94\x18\x23\x50\x2c\xca" - "\x2c\x55\x19\x97\x01\x9d\x93\x3b" - "\x63\x86\xf2\x03\x67\x45\xd2\x72" - "\x28\x52\x6c\xf4\xe3\x1c\xb5\x11" - "\x13\xf1\xeb\x21\xc7\xd9\x56\x82" - "\x2b\x82\x39\xbd\x69\x54\xed\x62" - "\xc3\xe2\xde\x73\xd4\x6a\x12\xae" - "\x13\x21\x7f\x4b\x5b\xfc\xbf\xe8" - "\x2b\xbe\x56\xba\x68\x8b\x9a\xb1" - "\x6e\xfa\xbf\x7e\x5a\x4b\xf1\xac" - "\x98\x65\x85\xd1\x93\x53\xd3\x7b" - "\x09\xdd\x4b\x10\x6d\x84\xb0\x13" - "\x65\xbd\xcf\x52\x09\xc4\x85\xe2" - "\x84\x74\x15\x65\xb7\xf7\x51\xaf" - "\x55\xad\xa4\xd1\x22\x54\x70\x94" - "\xa0\x1c\x90\x41\xfd\x99\xd7\x5a" - "\x31\xef\xaa\x25\xd0\x7f\x4f\xea" - "\x1d\x55\x42\xe5\x49\xb0\xd0\x46" - "\x62\x36\x43\xb2\x82\x15\x75\x50" - "\xa4\x72\xeb\x54\x27\x1f\x8a\xe4" - "\x7d\xe9\x66\xc5\xf1\x53\xa4\xd1" - "\x0c\xeb\xb8\xf8\xbc\xd4\xe2\xe7" - "\xe1\xf8\x4b\xcb\xa9\xa1\xaf\x15" - "\x83\xcb\x72\xd0\x33\x79\x00\x2d" - "\x9f\xd7\xf1\x2e\x1e\x10\xe4\x45" - "\xc0\x75\x3a\x39\xea\x68\xf7\x5d" - "\x1b\x73\x8f\xe9\x8e\x0f\x72\x47" - "\xae\x35\x0a\x31\x7a\x14\x4d\x4a" - "\x6f\x47\xf7\x7e\x91\x6e\x74\x8b" - "\x26\x47\xf9\xc3\xf9\xde\x70\xf5" - "\x61\xab\xa9\x27\x9f\x82\xe4\x9c" - "\x89\x91\x3f\x2e\x6a\xfd\xb5\x49" - "\xe9\xfd\x59\x14\x36\x49\x40\x6d" - "\x32\xd8\x85\x42\xf3\xa5\xdf\x0c" - "\xa8\x27\xd7\x54\xe2\x63\x2f\xf2" - "\x7e\x8b\x8b\xe7\xf1\x9a\x95\x35" - "\x43\xdc\x3a\xe4\xb6\xf4\xd0\xdf" - "\x9c\xcb\x94\xf3\x21\xa0\x77\x50" - "\xe2\xc6\xc4\xc6\x5f\x09\x64\x5b" - "\x92\x90\xd8\xe1\xd1\xed\x4b\x42" - "\xd7\x37\xaf\x65\x3d\x11\x39\xb6" - "\x24\x8a\x60\xae\xd6\x1e\xbf\x0e" - "\x0d\xd7\xdc\x96\x0e\x65\x75\x4e" - "\x29\x06\x9d\xa4\x51\x3a\x10\x63" - "\x8f\x17\x07\xd5\x8e\x3c\xf4\x28" - "\x00\x5a\x5b\x05\x19\xd8\xc0\x6c" - "\xe5\x15\xe4\x9c\x9d\x71\x9d\x5e" - "\x94\x29\x1a\xa7\x80\xfa\x0e\x33" - "\x03\xdd\xb7\x3e\x9a\xa9\x26\x18" - "\x37\xa9\x64\x08\x4d\x94\x5a\x88" - "\xca\x35\xce\x81\x02\xe3\x1f\x1b" - "\x89\x1a\x77\x85\xe3\x41\x6d\x32" - "\x42\x19\x23\x7d\xc8\x73\xee\x25" - "\x85\x0d\xf8\x31\x25\x79\x1b\x6f" - "\x79\x25\xd2\xd8\xd4\x23\xfd\xf7" - "\x82\x36\x6a\x0c\x46\x22\x15\xe9" - "\xff\x72\x41\x91\x91\x7d\x3a\xb7" - "\xdd\x65\x99\x70\xf6\x8d\x84\xf8" - "\x67\x15\x20\x11\xd6\xb2\x55\x7b" - "\xdb\x87\xee\xef\x55\x89\x2a\x59" - "\x2b\x07\x8f\x43\x8a\x59\x3c\x01" - "\x8b\x65\x54\xa1\x66\xd5\x38\xbd" - "\xc6\x30\xa9\xcc\x49\xb6\xa8\x1b" - "\xb8\xc0\x0e\xe3\x45\x28\xe2\xff" - "\x41\x9f\x7e\x7c\xd1\xae\x9e\x25" - "\x3f\x4c\x7c\x7c\xf4\xa8\x26\x4d" - "\x5c\xfd\x4b\x27\x18\xf9\x61\x76" - "\x48\xba\x0c\x6b\xa9\x4d\xfc\xf5" - "\x3b\x35\x7e\x2f\x4a\xa9\xc2\x9a" - "\xae\xab\x86\x09\x89\xc9\xc2\x40" - "\x39\x2c\x81\xb3\xb8\x17\x67\xc2" - "\x0d\x32\x4a\x3a\x67\x81\xd7\x1a" - "\x34\x52\xc5\xdb\x0a\xf5\x63\x39" - "\xea\x1f\xe1\x7c\xa1\x9e\xc1\x35" - "\xe3\xb1\x18\x45\x67\xf9\x22\x38" - "\x95\xd9\x34\x34\x86\xc6\x41\x94" - "\x15\xf9\x5b\x41\xa6\x87\x8b\xf8" - "\xd5\xe1\x1b\xe2\x5b\xf3\x86\x10" - "\xff\xe6\xae\x69\x76\xbc\x0d\xb4" - "\x09\x90\x0c\xa2\x65\x0c\xad\x74" - "\xf5\xd7\xff\xda\xc1\xce\x85\xbe" - "\x00\xa7\xff\x4d\x2f\x65\xd3\x8c" - "\x86\x2d\x05\xe8\xed\x3e\x6b\x8b" - "\x0f\x3d\x83\x8c\xf1\x1d\x5b\x96" - "\x2e\xb1\x9c\xc2\x98\xe1\x70\xb9" - "\xba\x5c\x8a\x43\xd6\x34\xa7\x2d" - "\xc9\x92\xae\xf2\xa5\x7b\x05\x49" - "\xa7\x33\x34\x86\xca\xe4\x96\x23" - "\x76\x5b\xf2\xc6\xf1\x51\x28\x42" - "\x7b\xcc\x76\x8f\xfa\xa2\xad\x31" - "\xd4\xd6\x7a\x6d\x25\x25\x54\xe4" - "\x3f\x50\x59\xe1\x5c\x05\xb7\x27" - "\x48\xbf\x07\xec\x1b\x13\xbe\x2b" - "\xa1\x57\x2b\xd5\xab\xd7\xd0\x4c" - "\x1e\xcb\x71\x9b\xc5\x90\x85\xd3" - "\xde\x59\xec\x71\xeb\x89\xbb\xd0" - "\x09\x50\xe1\x16\x3f\xfd\x1c\x34" - "\xc3\x1c\xa1\x10\x77\x53\x98\xef" - "\xf2\xfd\xa5\x01\x59\xc2\x9b\x26" - "\xc7\x42\xd9\x49\xda\x58\x2b\x6e" - "\x9f\x53\x19\x76\x7e\xd9\xc9\x0e" - "\x68\xc8\x7f\x51\x22\x42\xef\x49" - "\xa4\x55\xb6\x36\xac\x09\xc7\x31" - "\x88\x15\x4b\x2e\x8f\x3a\x08\xf7" - "\xd8\xf7\xa8\xc5\xa9\x33\xa6\x45" - "\xe4\xc4\x94\x76\xf3\x0d\x8f\x7e" - "\xc8\xf6\xbc\x23\x0a\xb6\x4c\xd3" - "\x6a\xcd\x36\xc2\x90\x5c\x5c\x3c" - "\x65\x7b\xc2\xd6\xcc\xe6\x0d\x87" - "\x73\x2e\x71\x79\x16\x06\x63\x28" - "\x09\x15\xd8\x89\x38\x38\x3d\xb5" - "\x42\x1c\x08\x24\xf7\x2a\xd2\x9d" - "\xc8\xca\xef\xf9\x27\xd8\x07\x86" - "\xf7\x43\x0b\x55\x15\x3f\x9f\x83" - "\xef\xdc\x49\x9d\x2a\xc1\x54\x62" - "\xbd\x9b\x66\x55\x9f\xb7\x12\xf3" - "\x1b\x4d\x9d\x2a\x5c\xed\x87\x75" - "\x87\x26\xec\x61\x2c\xb4\x0f\x89" - "\xb0\xfb\x2e\x68\x5d\x15\xc7\x8d" - "\x2e\xc0\xd9\xec\xaf\x4f\xd2\x25" - "\x29\xe8\xd2\x26\x2b\x67\xe9\xfc" - "\x2b\xa8\x67\x96\x12\x1f\x5b\x96" - "\xc6\x14\x53\xaf\x44\xea\xd6\xe2" - "\x94\x98\xe4\x12\x93\x4c\x92\xe0" - "\x18\xa5\x8d\x2d\xe4\x71\x3c\x47" - "\x4c\xf7\xe6\x47\x9e\xc0\x68\xdf" - "\xd4\xf5\x5a\x74\xb1\x2b\x29\x03" - "\x19\x07\xaf\x90\x62\x5c\x68\x98" - "\x48\x16\x11\x02\x9d\xee\xb4\x9b" - "\xe5\x42\x7f\x08\xfd\x16\x32\x0b" - "\xd0\xb3\xfa\x2b\xb7\x99\xf9\x29" - "\xcd\x20\x45\x9f\xb3\x1a\x5d\xa2" - "\xaf\x4d\xe0\xbd\x42\x0d\xbc\x74" - "\x99\x9c\x8e\x53\x1a\xb4\x3e\xbd" - "\xa2\x9a\x2d\xf7\xf8\x39\x0f\x67" - "\x63\xfc\x6b\xc0\xaf\xb3\x4b\x4f" - "\x55\xc4\xcf\xa7\xc8\x04\x11\x3e" - "\x14\x32\xbb\x1b\x38\x77\xd6\x7f" - "\x54\x4c\xdf\x75\xf3\x07\x2d\x33" - "\x9b\xa8\x20\xe1\x7b\x12\xb5\xf3" - "\xef\x2f\xce\x72\xe5\x24\x60\xc1" - "\x30\xe2\xab\xa1\x8e\x11\x09\xa8" - "\x21\x33\x44\xfe\x7f\x35\x32\x93" - "\x39\xa7\xad\x8b\x79\x06\xb2\xcb" - "\x4e\xa9\x5f\xc7\xba\x74\x29\xec" - "\x93\xa0\x4e\x54\x93\xc0\xbc\x55" - "\x64\xf0\x48\xe5\x57\x99\xee\x75" - "\xd6\x79\x0f\x66\xb7\xc6\x57\x76" - "\xf7\xb7\xf3\x9c\xc5\x60\xe8\x7f" - "\x83\x76\xd6\x0e\xaa\xe6\x90\x39" - "\x1d\xa6\x32\x6a\x34\xe3\x55\xf8" - "\x58\xa0\x58\x7d\x33\xe0\x22\x39" - "\x44\x64\x87\x86\x5a\x2f\xa7\x7e" - "\x0f\x38\xea\xb0\x30\xcc\x61\xa5" - "\x6a\x32\xae\x1e\xf7\xe9\xd0\xa9" - "\x0c\x32\x4b\xb5\x49\x28\xab\x85" - "\x2f\x8e\x01\x36\x38\x52\xd0\xba" - "\xd6\x02\x78\xf8\x0e\x3e\x9c\x8b" - "\x6b\x45\x99\x3f\x5c\xfe\x58\xf1" - "\x5c\x94\x04\xe1\xf5\x18\x6d\x51" - "\xb2\x5d\x18\x20\xb6\xc2\x9a\x42" - "\x1d\xb3\xab\x3c\xb6\x3a\x13\x03" - "\xb2\x46\x82\x4f\xfc\x64\xbc\x4f" - "\xca\xfa\x9c\xc0\xd5\xa7\xbd\x11" - "\xb7\xe4\x5a\xf6\x6f\x4d\x4d\x54" - "\xea\xa4\x98\x66\xd4\x22\x3b\xd3" - "\x8f\x34\x47\xd9\x7c\xf4\x72\x3b" - "\x4d\x02\x77\xf6\xd6\xdd\x08\x0a" - "\x81\xe1\x86\x89\x3e\x56\x10\x3c" - "\xba\xd7\x81\x8c\x08\xbc\x8b\xe2" - "\x53\xec\xa7\x89\xee\xc8\x56\xb5" - "\x36\x2c\xb2\x03\xba\x99\xdd\x7c" - "\x48\xa0\xb0\xbc\x91\x33\xe9\xa8" - "\xcb\xcd\xcf\x59\x5f\x1f\x15\xe2" - "\x56\xf5\x4e\x01\x35\x27\x45\x77" - "\x47\xc8\xbc\xcb\x7e\x39\xc1\x97" - "\x28\xd3\x84\xfc\x2c\x3e\xc8\xad" - "\x9c\xf8\x8a\x61\x9c\x28\xaa\xc5" - "\x99\x20\x43\x85\x9d\xa5\xe2\x8b" - "\xb8\xae\xeb\xd0\x32\x0d\x52\x78" - "\x09\x56\x3f\xc7\xd8\x7e\x26\xfc" - "\x37\xfb\x6f\x04\xfc\xfa\x92\x10" - "\xac\xf8\x3e\x21\xdc\x8c\x21\x16" - "\x7d\x67\x6e\xf6\xcd\xda\xb6\x98" - "\x23\xab\x23\x3c\xb2\x10\xa0\x53" - "\x5a\x56\x9f\xc5\xd0\xff\xbb\xe4" - "\x98\x3c\x69\x1e\xdb\x38\x8f\x7e" - "\x0f\xd2\x98\x88\x81\x8b\x45\x67" - "\xea\x33\xf1\xeb\xe9\x97\x55\x2e" - "\xd9\xaa\xeb\x5a\xec\xda\xe1\x68" - "\xa8\x9d\x3c\x84\x7c\x05\x3d\x62" - "\x87\x8f\x03\x21\x28\x95\x0c\x89" - "\x25\x22\x4a\xb0\x93\xa9\x50\xa2" - "\x2f\x57\x6e\x18\x42\x19\x54\x0c" - "\x55\x67\xc6\x11\x49\xf4\x5c\xd2" - "\xe9\x3d\xdd\x8b\x48\x71\x21\x00" - "\xc3\x9a\x6c\x85\x74\x28\x83\x4a" - "\x1b\x31\x05\xe1\x06\x92\xe7\xda" - "\x85\x73\x78\x45\x20\x7f\xae\x13" - "\x7c\x33\x06\x22\xf4\x83\xf9\x35" - "\x3f\x6c\x71\xa8\x4e\x48\xbe\x9b" - "\xce\x8a\xba\xda\xbe\x28\x08\xf7" - "\xe2\x14\x8c\x71\xea\x72\xf9\x33" - "\xf2\x88\x3f\xd7\xbb\x69\x6c\x29" - "\x19\xdc\x84\xce\x1f\x12\x4f\xc8" - "\xaf\xa5\x04\xba\x5a\xab\xb0\xd9" - "\x14\x1f\x6c\x68\x98\x39\x89\x7a" - "\xd9\xd8\x2f\xdf\xa8\x47\x4a\x25" - "\xe2\xfb\x33\xf4\x59\x78\xe1\x68" - "\x85\xcf\xfe\x59\x20\xd4\x05\x1d" - "\x80\x99\xae\xbc\xca\xae\x0f\x2f" - "\x65\x43\x34\x8e\x7e\xac\xd3\x93" - "\x2f\xac\x6d\x14\x3d\x02\x07\x70" - "\x9d\xa4\xf3\x1b\x5c\x36\xfc\x01" - "\x73\x34\x85\x0c\x6c\xd6\xf1\xbd" - "\x3f\xdf\xee\xf5\xd9\xba\x56\xef" - "\xf4\x9b\x6b\xee\x9f\x5a\x78\x6d" - "\x32\x19\xf4\xf7\xf8\x4c\x69\x0b" - "\x4b\xbc\xbb\xb7\xf2\x85\xaf\x70" - "\x75\x24\x6c\x54\xa7\x0e\x4d\x1d" - "\x01\xbf\x08\xac\xcf\x7f\x2c\xe3" - "\x14\x89\x5e\x70\x5a\x99\x92\xcd" - "\x01\x84\xc8\xd2\xab\xe5\x4f\x58" - "\xe7\x0f\x2f\x0e\xff\x68\xea\xfd" - "\x15\xb3\x17\xe6\xb0\xe7\x85\xd8" - "\x23\x2e\x05\xc7\xc9\xc4\x46\x1f" - "\xe1\x9e\x49\x20\x23\x24\x4d\x7e" - "\x29\x65\xff\xf4\xb6\xfd\x1a\x85" - "\xc4\x16\xec\xfc\xea\x7b\xd6\x2c" - "\x43\xf8\xb7\xbf\x79\xc0\x85\xcd" - "\xef\xe1\x98\xd3\xa5\xf7\x90\x8c" - "\xe9\x7f\x80\x6b\xd2\xac\x4c\x30" - "\xa7\xc6\x61\x6c\xd2\xf9\x2c\xff" - "\x30\xbc\x22\x81\x7d\x93\x12\xe4" - "\x0a\xcd\xaf\xdd\xe8\xab\x0a\x1e" - "\x13\xa4\x27\xc3\x5f\xf7\x4b\xbb" - "\x37\x09\x4b\x91\x6f\x92\x4f\xaf" - "\x52\xee\xdf\xef\x09\x6f\xf7\x5c" - "\x6e\x12\x17\x72\x63\x57\xc7\xba" - "\x3b\x6b\x38\x32\x73\x1b\x9c\x80" - "\xc1\x7a\xc6\xcf\xcd\x35\xc0\x6b" - "\x31\x1a\x6b\xe9\xd8\x2c\x29\x3f" - "\x96\xfb\xb6\xcd\x13\x91\x3b\xc2" - "\xd2\xa3\x31\x8d\xa4\xcd\x57\xcd" - "\x13\x3d\x64\xfd\x06\xce\xe6\xdc" - "\x0c\x24\x43\x31\x40\x57\xf1\x72" - "\x17\xe3\x3a\x63\x6d\x35\xcf\x5d" - "\x97\x40\x59\xdd\xf7\x3c\x02\xf7" - "\x1c\x7e\x05\xbb\xa9\x0d\x01\xb1" - "\x8e\xc0\x30\xa9\x53\x24\xc9\x89" - "\x84\x6d\xaa\xd0\xcd\x91\xc2\x4d" - "\x91\xb0\x89\xe2\xbf\x83\x44\xaa" - "\x28\x72\x23\xa0\xc2\xad\xad\x1c" - "\xfc\x3f\x09\x7a\x0b\xdc\xc5\x1b" - "\x87\x13\xc6\x5b\x59\x8d\xf2\xc8" - "\xaf\xdf\x11\x95", - .rlen = 4100, - }, -}; - -/* - * CTS (Cipher Text Stealing) mode tests - */ -#define CTS_MODE_ENC_TEST_VECTORS 6 -#define CTS_MODE_DEC_TEST_VECTORS 6 -static struct cipher_testvec cts_mode_enc_tv_template[] = { - { /* from rfc3962 */ - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .ilen = 17, - .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20", - .rlen = 17, - .result = "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4" - "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f" - "\x97", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .ilen = 31, - .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20", - .rlen = 31, - .result = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1" - "\xd4\x45\xd4\xc8\xef\xf7\xed\x22" - "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .ilen = 32, - .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43", - .rlen = 32, - .result = "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" - "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .ilen = 47, - .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43" - "\x68\x69\x63\x6b\x65\x6e\x2c\x20" - "\x70\x6c\x65\x61\x73\x65\x2c", - .rlen = 47, - .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" - "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c" - "\x1b\x55\x49\xd2\xf8\x38\x02\x9e" - "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .ilen = 48, - .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43" - "\x68\x69\x63\x6b\x65\x6e\x2c\x20" - "\x70\x6c\x65\x61\x73\x65\x2c\x20", - .rlen = 48, - .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" - "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" - "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8" - "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .ilen = 64, - .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43" - "\x68\x69\x63\x6b\x65\x6e\x2c\x20" - "\x70\x6c\x65\x61\x73\x65\x2c\x20" - "\x61\x6e\x64\x20\x77\x6f\x6e\x74" - "\x6f\x6e\x20\x73\x6f\x75\x70\x2e", - .rlen = 64, - .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" - "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" - "\x48\x07\xef\xe8\x36\xee\x89\xa5" - "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40" - "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" - "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8", - } -}; - -static struct cipher_testvec cts_mode_dec_tv_template[] = { - { /* from rfc3962 */ - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .rlen = 17, - .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20", - .ilen = 17, - .input = "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4" - "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f" - "\x97", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .rlen = 31, - .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20", - .ilen = 31, - .input = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1" - "\xd4\x45\xd4\xc8\xef\xf7\xed\x22" - "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .rlen = 32, - .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43", - .ilen = 32, - .input = "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" - "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .rlen = 47, - .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43" - "\x68\x69\x63\x6b\x65\x6e\x2c\x20" - "\x70\x6c\x65\x61\x73\x65\x2c", - .ilen = 47, - .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" - "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c" - "\x1b\x55\x49\xd2\xf8\x38\x02\x9e" - "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .rlen = 48, - .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43" - "\x68\x69\x63\x6b\x65\x6e\x2c\x20" - "\x70\x6c\x65\x61\x73\x65\x2c\x20", - .ilen = 48, - .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" - "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" - "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8" - "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8", - }, { - .klen = 16, - .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" - "\x74\x65\x72\x69\x79\x61\x6b\x69", - .rlen = 64, - .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" - "\x6c\x69\x6b\x65\x20\x74\x68\x65" - "\x20\x47\x65\x6e\x65\x72\x61\x6c" - "\x20\x47\x61\x75\x27\x73\x20\x43" - "\x68\x69\x63\x6b\x65\x6e\x2c\x20" - "\x70\x6c\x65\x61\x73\x65\x2c\x20" - "\x61\x6e\x64\x20\x77\x6f\x6e\x74" - "\x6f\x6e\x20\x73\x6f\x75\x70\x2e", - .ilen = 64, - .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" - "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" - "\x39\x31\x25\x23\xa7\x86\x62\xd5" - "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" - "\x48\x07\xef\xe8\x36\xee\x89\xa5" - "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40" - "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" - "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8", - } -}; - -/* - * Compression stuff. - */ -#define COMP_BUF_SIZE 512 - -struct comp_testvec { - int inlen, outlen; - char input[COMP_BUF_SIZE]; - char output[COMP_BUF_SIZE]; -}; - -/* - * Deflate test vectors (null-terminated strings). - * Params: winbits=11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL. - */ -#define DEFLATE_COMP_TEST_VECTORS 2 -#define DEFLATE_DECOMP_TEST_VECTORS 2 - -static struct comp_testvec deflate_comp_tv_template[] = { - { - .inlen = 70, - .outlen = 38, - .input = "Join us now and share the software " - "Join us now and share the software ", - .output = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" - "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" - "\x28\xce\x48\x2c\x4a\x55\x28\xc9" - "\x48\x55\x28\xce\x4f\x2b\x29\x07" - "\x71\xbc\x08\x2b\x01\x00", - }, { - .inlen = 191, - .outlen = 122, - .input = "This document describes a compression method based on the DEFLATE" - "compression algorithm. This document defines the application of " - "the DEFLATE algorithm to the IP Payload Compression Protocol.", - .output = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" - "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" - "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" - "\x24\xdb\x67\xd9\x47\xc1\xef\x49" - "\x68\x12\x51\xae\x76\x67\xd6\x27" - "\x19\x88\x1a\xde\x85\xab\x21\xf2" - "\x08\x5d\x16\x1e\x20\x04\x2d\xad" - "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" - "\x42\x83\x23\xb6\x6c\x89\x71\x9b" - "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" - "\xed\x62\xa9\x4c\x80\xff\x13\xaf" - "\x52\x37\xed\x0e\x52\x6b\x59\x02" - "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" - "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" - "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" - "\xfa\x02", - }, -}; - -static struct comp_testvec deflate_decomp_tv_template[] = { - { - .inlen = 122, - .outlen = 191, - .input = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" - "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" - "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" - "\x24\xdb\x67\xd9\x47\xc1\xef\x49" - "\x68\x12\x51\xae\x76\x67\xd6\x27" - "\x19\x88\x1a\xde\x85\xab\x21\xf2" - "\x08\x5d\x16\x1e\x20\x04\x2d\xad" - "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" - "\x42\x83\x23\xb6\x6c\x89\x71\x9b" - "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" - "\xed\x62\xa9\x4c\x80\xff\x13\xaf" - "\x52\x37\xed\x0e\x52\x6b\x59\x02" - "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" - "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" - "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" - "\xfa\x02", - .output = "This document describes a compression method based on the DEFLATE" - "compression algorithm. This document defines the application of " - "the DEFLATE algorithm to the IP Payload Compression Protocol.", - }, { - .inlen = 38, - .outlen = 70, - .input = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" - "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" - "\x28\xce\x48\x2c\x4a\x55\x28\xc9" - "\x48\x55\x28\xce\x4f\x2b\x29\x07" - "\x71\xbc\x08\x2b\x01\x00", - .output = "Join us now and share the software " - "Join us now and share the software ", - }, -}; - -/* - * LZO test vectors (null-terminated strings). - */ -#define LZO_COMP_TEST_VECTORS 2 -#define LZO_DECOMP_TEST_VECTORS 2 - -static struct comp_testvec lzo_comp_tv_template[] = { - { - .inlen = 70, - .outlen = 46, - .input = "Join us now and share the software " - "Join us now and share the software ", - .output = "\x00\x0d\x4a\x6f\x69\x6e\x20\x75" - "\x73\x20\x6e\x6f\x77\x20\x61\x6e" - "\x64\x20\x73\x68\x61\x72\x65\x20" - "\x74\x68\x65\x20\x73\x6f\x66\x74" - "\x77\x70\x01\x01\x4a\x6f\x69\x6e" - "\x3d\x88\x00\x11\x00\x00", - }, { - .inlen = 159, - .outlen = 133, - .input = "This document describes a compression method based on the LZO " - "compression algorithm. This document defines the application of " - "the LZO algorithm used in UBIFS.", - .output = "\x00\x2b\x54\x68\x69\x73\x20\x64" - "\x6f\x63\x75\x6d\x65\x6e\x74\x20" - "\x64\x65\x73\x63\x72\x69\x62\x65" - "\x73\x20\x61\x20\x63\x6f\x6d\x70" - "\x72\x65\x73\x73\x69\x6f\x6e\x20" - "\x6d\x65\x74\x68\x6f\x64\x20\x62" - "\x61\x73\x65\x64\x20\x6f\x6e\x20" - "\x74\x68\x65\x20\x4c\x5a\x4f\x2b" - "\x8c\x00\x0d\x61\x6c\x67\x6f\x72" - "\x69\x74\x68\x6d\x2e\x20\x20\x54" - "\x68\x69\x73\x2a\x54\x01\x02\x66" - "\x69\x6e\x65\x73\x94\x06\x05\x61" - "\x70\x70\x6c\x69\x63\x61\x74\x76" - "\x0a\x6f\x66\x88\x02\x60\x09\x27" - "\xf0\x00\x0c\x20\x75\x73\x65\x64" - "\x20\x69\x6e\x20\x55\x42\x49\x46" - "\x53\x2e\x11\x00\x00", - }, -}; - -static struct comp_testvec lzo_decomp_tv_template[] = { - { - .inlen = 133, - .outlen = 159, - .input = "\x00\x2b\x54\x68\x69\x73\x20\x64" - "\x6f\x63\x75\x6d\x65\x6e\x74\x20" - "\x64\x65\x73\x63\x72\x69\x62\x65" - "\x73\x20\x61\x20\x63\x6f\x6d\x70" - "\x72\x65\x73\x73\x69\x6f\x6e\x20" - "\x6d\x65\x74\x68\x6f\x64\x20\x62" - "\x61\x73\x65\x64\x20\x6f\x6e\x20" - "\x74\x68\x65\x20\x4c\x5a\x4f\x2b" - "\x8c\x00\x0d\x61\x6c\x67\x6f\x72" - "\x69\x74\x68\x6d\x2e\x20\x20\x54" - "\x68\x69\x73\x2a\x54\x01\x02\x66" - "\x69\x6e\x65\x73\x94\x06\x05\x61" - "\x70\x70\x6c\x69\x63\x61\x74\x76" - "\x0a\x6f\x66\x88\x02\x60\x09\x27" - "\xf0\x00\x0c\x20\x75\x73\x65\x64" - "\x20\x69\x6e\x20\x55\x42\x49\x46" - "\x53\x2e\x11\x00\x00", - .output = "This document describes a compression method based on the LZO " - "compression algorithm. This document defines the application of " - "the LZO algorithm used in UBIFS.", - }, { - .inlen = 46, - .outlen = 70, - .input = "\x00\x0d\x4a\x6f\x69\x6e\x20\x75" - "\x73\x20\x6e\x6f\x77\x20\x61\x6e" - "\x64\x20\x73\x68\x61\x72\x65\x20" - "\x74\x68\x65\x20\x73\x6f\x66\x74" - "\x77\x70\x01\x01\x4a\x6f\x69\x6e" - "\x3d\x88\x00\x11\x00\x00", - .output = "Join us now and share the software " - "Join us now and share the software ", - }, -}; - -/* - * Michael MIC test vectors from IEEE 802.11i - */ -#define MICHAEL_MIC_TEST_VECTORS 6 - -static struct hash_testvec michael_mic_tv_template[] = { - { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00", - .ksize = 8, - .plaintext = zeroed_string, - .psize = 0, - .digest = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8", - }, - { - .key = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8", - .ksize = 8, - .plaintext = "M", - .psize = 1, - .digest = "\x43\x47\x21\xca\x40\x63\x9b\x3f", - }, - { - .key = "\x43\x47\x21\xca\x40\x63\x9b\x3f", - .ksize = 8, - .plaintext = "Mi", - .psize = 2, - .digest = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29", - }, - { - .key = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29", - .ksize = 8, - .plaintext = "Mic", - .psize = 3, - .digest = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb", - }, - { - .key = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb", - .ksize = 8, - .plaintext = "Mich", - .psize = 4, - .digest = "\xd5\x5e\x10\x05\x10\x12\x89\x86", - }, - { - .key = "\xd5\x5e\x10\x05\x10\x12\x89\x86", - .ksize = 8, - .plaintext = "Michael", - .psize = 7, - .digest = "\x0a\x94\x2b\x12\x4e\xca\xa5\x46", - } -}; - -/* - * CRC32C test vectors - */ -#define CRC32C_TEST_VECTORS 14 - -static struct hash_testvec crc32c_tv_template[] = { - { - .psize = 0, - .digest = "\x00\x00\x00\x00", - }, - { - .key = "\x87\xa9\xcb\xed", - .ksize = 4, - .psize = 0, - .digest = "\x78\x56\x34\x12", - }, - { - .key = "\xff\xff\xff\xff", - .ksize = 4, - .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18" - "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" - "\x21\x22\x23\x24\x25\x26\x27\x28", - .psize = 40, - .digest = "\x7f\x15\x2c\x0e", - }, - { - .key = "\xff\xff\xff\xff", - .ksize = 4, - .plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" - "\x31\x32\x33\x34\x35\x36\x37\x38" - "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" - "\x41\x42\x43\x44\x45\x46\x47\x48" - "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50", - .psize = 40, - .digest = "\xf6\xeb\x80\xe9", - }, - { - .key = "\xff\xff\xff\xff", - .ksize = 4, - .plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58" - "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" - "\x61\x62\x63\x64\x65\x66\x67\x68" - "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" - "\x71\x72\x73\x74\x75\x76\x77\x78", - .psize = 40, - .digest = "\xed\xbd\x74\xde", - }, - { - .key = "\xff\xff\xff\xff", - .ksize = 4, - .plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" - "\x81\x82\x83\x84\x85\x86\x87\x88" - "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" - "\x91\x92\x93\x94\x95\x96\x97\x98" - "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0", - .psize = 40, - .digest = "\x62\xc8\x79\xd5", - }, - { - .key = "\xff\xff\xff\xff", - .ksize = 4, - .plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" - "\xa9\xaa\xab\xac\xad\xae\xaf\xb0" - "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" - "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" - "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8", - .psize = 40, - .digest = "\xd0\x9a\x97\xba", - }, - { - .key = "\xff\xff\xff\xff", - .ksize = 4, - .plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" - "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" - "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" - "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8" - "\xe9\xea\xeb\xec\xed\xee\xef\xf0", - .psize = 40, - .digest = "\x13\xd9\x29\x2b", - }, - { - .key = "\x80\xea\xd3\xf1", - .ksize = 4, - .plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" - "\x31\x32\x33\x34\x35\x36\x37\x38" - "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" - "\x41\x42\x43\x44\x45\x46\x47\x48" - "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50", - .psize = 40, - .digest = "\x0c\xb5\xe2\xa2", - }, - { - .key = "\xf3\x4a\x1d\x5d", - .ksize = 4, - .plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58" - "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" - "\x61\x62\x63\x64\x65\x66\x67\x68" - "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" - "\x71\x72\x73\x74\x75\x76\x77\x78", - .psize = 40, - .digest = "\xd1\x7f\xfb\xa6", - }, - { - .key = "\x2e\x80\x04\x59", - .ksize = 4, - .plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" - "\x81\x82\x83\x84\x85\x86\x87\x88" - "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" - "\x91\x92\x93\x94\x95\x96\x97\x98" - "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0", - .psize = 40, - .digest = "\x59\x33\xe6\x7a", - }, - { - .key = "\xa6\xcc\x19\x85", - .ksize = 4, - .plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" - "\xa9\xaa\xab\xac\xad\xae\xaf\xb0" - "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" - "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" - "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8", - .psize = 40, - .digest = "\xbe\x03\x01\xd2", - }, - { - .key = "\x41\xfc\xfe\x2d", - .ksize = 4, - .plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" - "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" - "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" - "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8" - "\xe9\xea\xeb\xec\xed\xee\xef\xf0", - .psize = 40, - .digest = "\x75\xd3\xc5\x24", - }, - { - .key = "\xff\xff\xff\xff", - .ksize = 4, - .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18" - "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" - "\x21\x22\x23\x24\x25\x26\x27\x28" - "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" - "\x31\x32\x33\x34\x35\x36\x37\x38" - "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" - "\x41\x42\x43\x44\x45\x46\x47\x48" - "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" - "\x51\x52\x53\x54\x55\x56\x57\x58" - "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" - "\x61\x62\x63\x64\x65\x66\x67\x68" - "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" - "\x71\x72\x73\x74\x75\x76\x77\x78" - "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" - "\x81\x82\x83\x84\x85\x86\x87\x88" - "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" - "\x91\x92\x93\x94\x95\x96\x97\x98" - "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" - "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" - "\xa9\xaa\xab\xac\xad\xae\xaf\xb0" - "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" - "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" - "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8" - "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" - "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" - "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" - "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8" - "\xe9\xea\xeb\xec\xed\xee\xef\xf0", - .psize = 240, - .digest = "\x75\xd3\xc5\x24", - .np = 2, - .tap = { 31, 209 } - }, -}; - /* * Cipher speed tests */ diff --git a/crypto/testmgr.c b/crypto/testmgr.c new file mode 100644 index 000000000000..b828c6cf1b1d --- /dev/null +++ b/crypto/testmgr.c @@ -0,0 +1,1868 @@ +/* + * Algorithm testing framework and tests. + * + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org> + * Copyright (c) 2007 Nokia Siemens Networks + * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <crypto/hash.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include "internal.h" +#include "testmgr.h" + +/* + * Need slab memory for testing (size in number of pages). + */ +#define XBUFSIZE 8 + +/* + * Indexes into the xbuf to simulate cross-page access. + */ +#define IDX1 32 +#define IDX2 32400 +#define IDX3 1 +#define IDX4 8193 +#define IDX5 22222 +#define IDX6 17101 +#define IDX7 27333 +#define IDX8 3000 + +/* +* Used by test_cipher() +*/ +#define ENCRYPT 1 +#define DECRYPT 0 + +struct tcrypt_result { + struct completion completion; + int err; +}; + +struct aead_test_suite { + struct { + struct aead_testvec *vecs; + unsigned int count; + } enc, dec; +}; + +struct cipher_test_suite { + struct { + struct cipher_testvec *vecs; + unsigned int count; + } enc, dec; +}; + +struct comp_test_suite { + struct { + struct comp_testvec *vecs; + unsigned int count; + } comp, decomp; +}; + +struct hash_test_suite { + struct hash_testvec *vecs; + unsigned int count; +}; + +struct alg_test_desc { + const char *alg; + int (*test)(const struct alg_test_desc *desc, const char *driver, + u32 type, u32 mask); + + union { + struct aead_test_suite aead; + struct cipher_test_suite cipher; + struct comp_test_suite comp; + struct hash_test_suite hash; + } suite; +}; + +static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; + +static char *xbuf[XBUFSIZE]; +static char *axbuf[XBUFSIZE]; + +static void hexdump(unsigned char *buf, unsigned int len) +{ + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, + 16, 1, + buf, len, false); +} + +static void tcrypt_complete(struct crypto_async_request *req, int err) +{ + struct tcrypt_result *res = req->data; + + if (err == -EINPROGRESS) + return; + + res->err = err; + complete(&res->completion); +} + +static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, + unsigned int tcount) +{ + const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm)); + unsigned int i, j, k, temp; + struct scatterlist sg[8]; + char result[64]; + struct ahash_request *req; + struct tcrypt_result tresult; + int ret; + void *hash_buff; + + init_completion(&tresult.completion); + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + printk(KERN_ERR "alg: hash: Failed to allocate request for " + "%s\n", algo); + ret = -ENOMEM; + goto out_noreq; + } + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, &tresult); + + for (i = 0; i < tcount; i++) { + memset(result, 0, 64); + + hash_buff = xbuf[0]; + + memcpy(hash_buff, template[i].plaintext, template[i].psize); + sg_init_one(&sg[0], hash_buff, template[i].psize); + + if (template[i].ksize) { + crypto_ahash_clear_flags(tfm, ~0); + ret = crypto_ahash_setkey(tfm, template[i].key, + template[i].ksize); + if (ret) { + printk(KERN_ERR "alg: hash: setkey failed on " + "test %d for %s: ret=%d\n", i + 1, algo, + -ret); + goto out; + } + } + + ahash_request_set_crypt(req, sg, result, template[i].psize); + ret = crypto_ahash_digest(req); + switch (ret) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible( + &tresult.completion); + if (!ret && !(ret = tresult.err)) { + INIT_COMPLETION(tresult.completion); + break; + } + /* fall through */ + default: + printk(KERN_ERR "alg: hash: digest failed on test %d " + "for %s: ret=%d\n", i + 1, algo, -ret); + goto out; + } + + if (memcmp(result, template[i].digest, + crypto_ahash_digestsize(tfm))) { + printk(KERN_ERR "alg: hash: Test %d failed for %s\n", + i + 1, algo); + hexdump(result, crypto_ahash_digestsize(tfm)); + ret = -EINVAL; + goto out; + } + } + + j = 0; + for (i = 0; i < tcount; i++) { + if (template[i].np) { + j++; + memset(result, 0, 64); + + temp = 0; + sg_init_table(sg, template[i].np); + for (k = 0; k < template[i].np; k++) { + sg_set_buf(&sg[k], + memcpy(xbuf[IDX[k] >> PAGE_SHIFT] + + offset_in_page(IDX[k]), + template[i].plaintext + temp, + template[i].tap[k]), + template[i].tap[k]); + temp += template[i].tap[k]; + } + + if (template[i].ksize) { + crypto_ahash_clear_flags(tfm, ~0); + ret = crypto_ahash_setkey(tfm, template[i].key, + template[i].ksize); + + if (ret) { + printk(KERN_ERR "alg: hash: setkey " + "failed on chunking test %d " + "for %s: ret=%d\n", j, algo, + -ret); + goto out; + } + } + + ahash_request_set_crypt(req, sg, result, + template[i].psize); + ret = crypto_ahash_digest(req); + switch (ret) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible( + &tresult.completion); + if (!ret && !(ret = tresult.err)) { + INIT_COMPLETION(tresult.completion); + break; + } + /* fall through */ + default: + printk(KERN_ERR "alg: hash: digest failed " + "on chunking test %d for %s: " + "ret=%d\n", j, algo, -ret); + goto out; + } + + if (memcmp(result, template[i].digest, + crypto_ahash_digestsize(tfm))) { + printk(KERN_ERR "alg: hash: Chunking test %d " + "failed for %s\n", j, algo); + hexdump(result, crypto_ahash_digestsize(tfm)); + ret = -EINVAL; + goto out; + } + } + } + + ret = 0; + +out: + ahash_request_free(req); +out_noreq: + return ret; +} + +static int test_aead(struct crypto_aead *tfm, int enc, + struct aead_testvec *template, unsigned int tcount) +{ + const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)); + unsigned int i, j, k, n, temp; + int ret = 0; + char *q; + char *key; + struct aead_request *req; + struct scatterlist sg[8]; + struct scatterlist asg[8]; + const char *e; + struct tcrypt_result result; + unsigned int authsize; + void *input; + void *assoc; + char iv[MAX_IVLEN]; + + if (enc == ENCRYPT) + e = "encryption"; + else + e = "decryption"; + + init_completion(&result.completion); + + req = aead_request_alloc(tfm, GFP_KERNEL); + if (!req) { + printk(KERN_ERR "alg: aead: Failed to allocate request for " + "%s\n", algo); + ret = -ENOMEM; + goto out; + } + + aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, &result); + + for (i = 0, j = 0; i < tcount; i++) { + if (!template[i].np) { + j++; + + /* some tepmplates have no input data but they will + * touch input + */ + input = xbuf[0]; + assoc = axbuf[0]; + + memcpy(input, template[i].input, template[i].ilen); + memcpy(assoc, template[i].assoc, template[i].alen); + if (template[i].iv) + memcpy(iv, template[i].iv, MAX_IVLEN); + else + memset(iv, 0, MAX_IVLEN); + + crypto_aead_clear_flags(tfm, ~0); + if (template[i].wk) + crypto_aead_set_flags( + tfm, CRYPTO_TFM_REQ_WEAK_KEY); + + key = template[i].key; + + ret = crypto_aead_setkey(tfm, key, + template[i].klen); + if (!ret == template[i].fail) { + printk(KERN_ERR "alg: aead: setkey failed on " + "test %d for %s: flags=%x\n", j, algo, + crypto_aead_get_flags(tfm)); + goto out; + } else if (ret) + continue; + + authsize = abs(template[i].rlen - template[i].ilen); + ret = crypto_aead_setauthsize(tfm, authsize); + if (ret) { + printk(KERN_ERR "alg: aead: Failed to set " + "authsize to %u on test %d for %s\n", + authsize, j, algo); + goto out; + } + + sg_init_one(&sg[0], input, + template[i].ilen + (enc ? authsize : 0)); + + sg_init_one(&asg[0], assoc, template[i].alen); + + aead_request_set_crypt(req, sg, sg, + template[i].ilen, iv); + + aead_request_set_assoc(req, asg, template[i].alen); + + ret = enc ? + crypto_aead_encrypt(req) : + crypto_aead_decrypt(req); + + switch (ret) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible( + &result.completion); + if (!ret && !(ret = result.err)) { + INIT_COMPLETION(result.completion); + break; + } + /* fall through */ + default: + printk(KERN_ERR "alg: aead: %s failed on test " + "%d for %s: ret=%d\n", e, j, algo, -ret); + goto out; + } + + q = input; + if (memcmp(q, template[i].result, template[i].rlen)) { + printk(KERN_ERR "alg: aead: Test %d failed on " + "%s for %s\n", j, e, algo); + hexdump(q, template[i].rlen); + ret = -EINVAL; + goto out; + } + } + } + + for (i = 0, j = 0; i < tcount; i++) { + if (template[i].np) { + j++; + + if (template[i].iv) + memcpy(iv, template[i].iv, MAX_IVLEN); + else + memset(iv, 0, MAX_IVLEN); + + crypto_aead_clear_flags(tfm, ~0); + if (template[i].wk) + crypto_aead_set_flags( + tfm, CRYPTO_TFM_REQ_WEAK_KEY); + key = template[i].key; + + ret = crypto_aead_setkey(tfm, key, template[i].klen); + if (!ret == template[i].fail) { + printk(KERN_ERR "alg: aead: setkey failed on " + "chunk test %d for %s: flags=%x\n", j, + algo, crypto_aead_get_flags(tfm)); + goto out; + } else if (ret) + continue; + + authsize = abs(template[i].rlen - template[i].ilen); + + ret = -EINVAL; + sg_init_table(sg, template[i].np); + for (k = 0, temp = 0; k < template[i].np; k++) { + if (WARN_ON(offset_in_page(IDX[k]) + + template[i].tap[k] > PAGE_SIZE)) + goto out; + + q = xbuf[IDX[k] >> PAGE_SHIFT] + + offset_in_page(IDX[k]); + + memcpy(q, template[i].input + temp, + template[i].tap[k]); + + n = template[i].tap[k]; + if (k == template[i].np - 1 && enc) + n += authsize; + if (offset_in_page(q) + n < PAGE_SIZE) + q[n] = 0; + + sg_set_buf(&sg[k], q, template[i].tap[k]); + temp += template[i].tap[k]; + } + + ret = crypto_aead_setauthsize(tfm, authsize); + if (ret) { + printk(KERN_ERR "alg: aead: Failed to set " + "authsize to %u on chunk test %d for " + "%s\n", authsize, j, algo); + goto out; + } + + if (enc) { + if (WARN_ON(sg[k - 1].offset + + sg[k - 1].length + authsize > + PAGE_SIZE)) { + ret = -EINVAL; + goto out; + } + + sg[k - 1].length += authsize; + } + + sg_init_table(asg, template[i].anp); + for (k = 0, temp = 0; k < template[i].anp; k++) { + sg_set_buf(&asg[k], + memcpy(axbuf[IDX[k] >> PAGE_SHIFT] + + offset_in_page(IDX[k]), + template[i].assoc + temp, + template[i].atap[k]), + template[i].atap[k]); + temp += template[i].atap[k]; + } + + aead_request_set_crypt(req, sg, sg, + template[i].ilen, + iv); + + aead_request_set_assoc(req, asg, template[i].alen); + + ret = enc ? + crypto_aead_encrypt(req) : + crypto_aead_decrypt(req); + + switch (ret) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible( + &result.completion); + if (!ret && !(ret = result.err)) { + INIT_COMPLETION(result.completion); + break; + } + /* fall through */ + default: + printk(KERN_ERR "alg: aead: %s failed on " + "chunk test %d for %s: ret=%d\n", e, j, + algo, -ret); + goto out; + } + + ret = -EINVAL; + for (k = 0, temp = 0; k < template[i].np; k++) { + q = xbuf[IDX[k] >> PAGE_SHIFT] + + offset_in_page(IDX[k]); + + n = template[i].tap[k]; + if (k == template[i].np - 1) + n += enc ? authsize : -authsize; + + if (memcmp(q, template[i].result + temp, n)) { + printk(KERN_ERR "alg: aead: Chunk " + "test %d failed on %s at page " + "%u for %s\n", j, e, k, algo); + hexdump(q, n); + goto out; + } + + q += n; + if (k == template[i].np - 1 && !enc) { + if (memcmp(q, template[i].input + + temp + n, authsize)) + n = authsize; + else + n = 0; + } else { + for (n = 0; offset_in_page(q + n) && + q[n]; n++) + ; + } + if (n) { + printk(KERN_ERR "alg: aead: Result " + "buffer corruption in chunk " + "test %d on %s at page %u for " + "%s: %u bytes:\n", j, e, k, + algo, n); + hexdump(q, n); + goto out; + } + + temp += template[i].tap[k]; + } + } + } + + ret = 0; + +out: + aead_request_free(req); + return ret; +} + +static int test_cipher(struct crypto_cipher *tfm, int enc, + struct cipher_testvec *template, unsigned int tcount) +{ + const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm)); + unsigned int i, j, k; + int ret; + char *q; + const char *e; + void *data; + + if (enc == ENCRYPT) + e = "encryption"; + else + e = "decryption"; + + j = 0; + for (i = 0; i < tcount; i++) { + if (template[i].np) + continue; + + j++; + + data = xbuf[0]; + memcpy(data, template[i].input, template[i].ilen); + + crypto_cipher_clear_flags(tfm, ~0); + if (template[i].wk) + crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); + + ret = crypto_cipher_setkey(tfm, template[i].key, + template[i].klen); + if (!ret == template[i].fail) { + printk(KERN_ERR "alg: cipher: setkey failed " + "on test %d for %s: flags=%x\n", j, + algo, crypto_cipher_get_flags(tfm)); + goto out; + } else if (ret) + continue; + + for (k = 0; k < template[i].ilen; + k += crypto_cipher_blocksize(tfm)) { + if (enc) + crypto_cipher_encrypt_one(tfm, data + k, + data + k); + else + crypto_cipher_decrypt_one(tfm, data + k, + data + k); + } + + q = data; + if (memcmp(q, template[i].result, template[i].rlen)) { + printk(KERN_ERR "alg: cipher: Test %d failed " + "on %s for %s\n", j, e, algo); + hexdump(q, template[i].rlen); + ret = -EINVAL; + goto out; + } + } + + ret = 0; + +out: + return ret; +} + +static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, + struct cipher_testvec *template, unsigned int tcount) +{ + const char *algo = + crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm)); + unsigned int i, j, k, n, temp; + int ret; + char *q; + struct ablkcipher_request *req; + struct scatterlist sg[8]; + const char *e; + struct tcrypt_result result; + void *data; + char iv[MAX_IVLEN]; + + if (enc == ENCRYPT) + e = "encryption"; + else + e = "decryption"; + + init_completion(&result.completion); + + req = ablkcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + printk(KERN_ERR "alg: skcipher: Failed to allocate request " + "for %s\n", algo); + ret = -ENOMEM; + goto out; + } + + ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, &result); + + j = 0; + for (i = 0; i < tcount; i++) { + if (template[i].iv) + memcpy(iv, template[i].iv, MAX_IVLEN); + else + memset(iv, 0, MAX_IVLEN); + + if (!(template[i].np)) { + j++; + + data = xbuf[0]; + memcpy(data, template[i].input, template[i].ilen); + + crypto_ablkcipher_clear_flags(tfm, ~0); + if (template[i].wk) + crypto_ablkcipher_set_flags( + tfm, CRYPTO_TFM_REQ_WEAK_KEY); + + ret = crypto_ablkcipher_setkey(tfm, template[i].key, + template[i].klen); + if (!ret == template[i].fail) { + printk(KERN_ERR "alg: skcipher: setkey failed " + "on test %d for %s: flags=%x\n", j, + algo, crypto_ablkcipher_get_flags(tfm)); + goto out; + } else if (ret) + continue; + + sg_init_one(&sg[0], data, template[i].ilen); + + ablkcipher_request_set_crypt(req, sg, sg, + template[i].ilen, iv); + ret = enc ? + crypto_ablkcipher_encrypt(req) : + crypto_ablkcipher_decrypt(req); + + switch (ret) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible( + &result.completion); + if (!ret && !((ret = result.err))) { + INIT_COMPLETION(result.completion); + break; + } + /* fall through */ + default: + printk(KERN_ERR "alg: skcipher: %s failed on " + "test %d for %s: ret=%d\n", e, j, algo, + -ret); + goto out; + } + + q = data; + if (memcmp(q, template[i].result, template[i].rlen)) { + printk(KERN_ERR "alg: skcipher: Test %d " + "failed on %s for %s\n", j, e, algo); + hexdump(q, template[i].rlen); + ret = -EINVAL; + goto out; + } + } + } + + j = 0; + for (i = 0; i < tcount; i++) { + + if (template[i].iv) + memcpy(iv, template[i].iv, MAX_IVLEN); + else + memset(iv, 0, MAX_IVLEN); + + if (template[i].np) { + j++; + + crypto_ablkcipher_clear_flags(tfm, ~0); + if (template[i].wk) + crypto_ablkcipher_set_flags( + tfm, CRYPTO_TFM_REQ_WEAK_KEY); + + ret = crypto_ablkcipher_setkey(tfm, template[i].key, + template[i].klen); + if (!ret == template[i].fail) { + printk(KERN_ERR "alg: skcipher: setkey failed " + "on chunk test %d for %s: flags=%x\n", + j, algo, + crypto_ablkcipher_get_flags(tfm)); + goto out; + } else if (ret) + continue; + + temp = 0; + ret = -EINVAL; + sg_init_table(sg, template[i].np); + for (k = 0; k < template[i].np; k++) { + if (WARN_ON(offset_in_page(IDX[k]) + + template[i].tap[k] > PAGE_SIZE)) + goto out; + + q = xbuf[IDX[k] >> PAGE_SHIFT] + + offset_in_page(IDX[k]); + + memcpy(q, template[i].input + temp, + template[i].tap[k]); + + if (offset_in_page(q) + template[i].tap[k] < + PAGE_SIZE) + q[template[i].tap[k]] = 0; + + sg_set_buf(&sg[k], q, template[i].tap[k]); + + temp += template[i].tap[k]; + } + + ablkcipher_request_set_crypt(req, sg, sg, + template[i].ilen, iv); + + ret = enc ? + crypto_ablkcipher_encrypt(req) : + crypto_ablkcipher_decrypt(req); + + switch (ret) { + case 0: + break; + case -EINPROGRESS: + case -EBUSY: + ret = wait_for_completion_interruptible( + &result.completion); + if (!ret && !((ret = result.err))) { + INIT_COMPLETION(result.completion); + break; + } + /* fall through */ + default: + printk(KERN_ERR "alg: skcipher: %s failed on " + "chunk test %d for %s: ret=%d\n", e, j, + algo, -ret); + goto out; + } + + temp = 0; + ret = -EINVAL; + for (k = 0; k < template[i].np; k++) { + q = xbuf[IDX[k] >> PAGE_SHIFT] + + offset_in_page(IDX[k]); + + if (memcmp(q, template[i].result + temp, + template[i].tap[k])) { + printk(KERN_ERR "alg: skcipher: Chunk " + "test %d failed on %s at page " + "%u for %s\n", j, e, k, algo); + hexdump(q, template[i].tap[k]); + goto out; + } + + q += template[i].tap[k]; + for (n = 0; offset_in_page(q + n) && q[n]; n++) + ; + if (n) { + printk(KERN_ERR "alg: skcipher: " + "Result buffer corruption in " + "chunk test %d on %s at page " + "%u for %s: %u bytes:\n", j, e, + k, algo, n); + hexdump(q, n); + goto out; + } + temp += template[i].tap[k]; + } + } + } + + ret = 0; + +out: + ablkcipher_request_free(req); + return ret; +} + +static int test_comp(struct crypto_comp *tfm, struct comp_testvec *ctemplate, + struct comp_testvec *dtemplate, int ctcount, int dtcount) +{ + const char *algo = crypto_tfm_alg_driver_name(crypto_comp_tfm(tfm)); + unsigned int i; + char result[COMP_BUF_SIZE]; + int ret; + + for (i = 0; i < ctcount; i++) { + int ilen, dlen = COMP_BUF_SIZE; + + memset(result, 0, sizeof (result)); + + ilen = ctemplate[i].inlen; + ret = crypto_comp_compress(tfm, ctemplate[i].input, + ilen, result, &dlen); + if (ret) { + printk(KERN_ERR "alg: comp: compression failed " + "on test %d for %s: ret=%d\n", i + 1, algo, + -ret); + goto out; + } + + if (memcmp(result, ctemplate[i].output, dlen)) { + printk(KERN_ERR "alg: comp: Compression test %d " + "failed for %s\n", i + 1, algo); + hexdump(result, dlen); + ret = -EINVAL; + goto out; + } + } + + for (i = 0; i < dtcount; i++) { + int ilen, ret, dlen = COMP_BUF_SIZE; + + memset(result, 0, sizeof (result)); + + ilen = dtemplate[i].inlen; + ret = crypto_comp_decompress(tfm, dtemplate[i].input, + ilen, result, &dlen); + if (ret) { + printk(KERN_ERR "alg: comp: decompression failed " + "on test %d for %s: ret=%d\n", i + 1, algo, + -ret); + goto out; + } + + if (memcmp(result, dtemplate[i].output, dlen)) { + printk(KERN_ERR "alg: comp: Decompression test %d " + "failed for %s\n", i + 1, algo); + hexdump(result, dlen); + ret = -EINVAL; + goto out; + } + } + + ret = 0; + +out: + return ret; +} + +static int alg_test_aead(const struct alg_test_desc *desc, const char *driver, + u32 type, u32 mask) +{ + struct crypto_aead *tfm; + int err = 0; + + tfm = crypto_alloc_aead(driver, type, mask); + if (IS_ERR(tfm)) { + printk(KERN_ERR "alg: aead: Failed to load transform for %s: " + "%ld\n", driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + if (desc->suite.aead.enc.vecs) { + err = test_aead(tfm, ENCRYPT, desc->suite.aead.enc.vecs, + desc->suite.aead.enc.count); + if (err) + goto out; + } + + if (!err && desc->suite.aead.dec.vecs) + err = test_aead(tfm, DECRYPT, desc->suite.aead.dec.vecs, + desc->suite.aead.dec.count); + +out: + crypto_free_aead(tfm); + return err; +} + +static int alg_test_cipher(const struct alg_test_desc *desc, + const char *driver, u32 type, u32 mask) +{ + struct crypto_cipher *tfm; + int err = 0; + + tfm = crypto_alloc_cipher(driver, type, mask); + if (IS_ERR(tfm)) { + printk(KERN_ERR "alg: cipher: Failed to load transform for " + "%s: %ld\n", driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + if (desc->suite.cipher.enc.vecs) { + err = test_cipher(tfm, ENCRYPT, desc->suite.cipher.enc.vecs, + desc->suite.cipher.enc.count); + if (err) + goto out; + } + + if (desc->suite.cipher.dec.vecs) + err = test_cipher(tfm, DECRYPT, desc->suite.cipher.dec.vecs, + desc->suite.cipher.dec.count); + +out: + crypto_free_cipher(tfm); + return err; +} + +static int alg_test_skcipher(const struct alg_test_desc *desc, + const char *driver, u32 type, u32 mask) +{ + struct crypto_ablkcipher *tfm; + int err = 0; + + tfm = crypto_alloc_ablkcipher(driver, type, mask); + if (IS_ERR(tfm)) { + printk(KERN_ERR "alg: skcipher: Failed to load transform for " + "%s: %ld\n", driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + if (desc->suite.cipher.enc.vecs) { + err = test_skcipher(tfm, ENCRYPT, desc->suite.cipher.enc.vecs, + desc->suite.cipher.enc.count); + if (err) + goto out; + } + + if (desc->suite.cipher.dec.vecs) + err = test_skcipher(tfm, DECRYPT, desc->suite.cipher.dec.vecs, + desc->suite.cipher.dec.count); + +out: + crypto_free_ablkcipher(tfm); + return err; +} + +static int alg_test_comp(const struct alg_test_desc *desc, const char *driver, + u32 type, u32 mask) +{ + struct crypto_comp *tfm; + int err; + + tfm = crypto_alloc_comp(driver, type, mask); + if (IS_ERR(tfm)) { + printk(KERN_ERR "alg: comp: Failed to load transform for %s: " + "%ld\n", driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + err = test_comp(tfm, desc->suite.comp.comp.vecs, + desc->suite.comp.decomp.vecs, + desc->suite.comp.comp.count, + desc->suite.comp.decomp.count); + + crypto_free_comp(tfm); + return err; +} + +static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, + u32 type, u32 mask) +{ + struct crypto_ahash *tfm; + int err; + + tfm = crypto_alloc_ahash(driver, type, mask); + if (IS_ERR(tfm)) { + printk(KERN_ERR "alg: hash: Failed to load transform for %s: " + "%ld\n", driver, PTR_ERR(tfm)); + return PTR_ERR(tfm); + } + + err = test_hash(tfm, desc->suite.hash.vecs, desc->suite.hash.count); + + crypto_free_ahash(tfm); + return err; +} + +/* Please keep this list sorted by algorithm name. */ +static const struct alg_test_desc alg_test_descs[] = { + { + .alg = "cbc(aes)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = aes_cbc_enc_tv_template, + .count = AES_CBC_ENC_TEST_VECTORS + }, + .dec = { + .vecs = aes_cbc_dec_tv_template, + .count = AES_CBC_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "cbc(anubis)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = anubis_cbc_enc_tv_template, + .count = ANUBIS_CBC_ENC_TEST_VECTORS + }, + .dec = { + .vecs = anubis_cbc_dec_tv_template, + .count = ANUBIS_CBC_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "cbc(blowfish)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = bf_cbc_enc_tv_template, + .count = BF_CBC_ENC_TEST_VECTORS + }, + .dec = { + .vecs = bf_cbc_dec_tv_template, + .count = BF_CBC_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "cbc(camellia)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = camellia_cbc_enc_tv_template, + .count = CAMELLIA_CBC_ENC_TEST_VECTORS + }, + .dec = { + .vecs = camellia_cbc_dec_tv_template, + .count = CAMELLIA_CBC_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "cbc(des)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = des_cbc_enc_tv_template, + .count = DES_CBC_ENC_TEST_VECTORS + }, + .dec = { + .vecs = des_cbc_dec_tv_template, + .count = DES_CBC_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "cbc(des3_ede)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = des3_ede_cbc_enc_tv_template, + .count = DES3_EDE_CBC_ENC_TEST_VECTORS + }, + .dec = { + .vecs = des3_ede_cbc_dec_tv_template, + .count = DES3_EDE_CBC_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "cbc(twofish)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = tf_cbc_enc_tv_template, + .count = TF_CBC_ENC_TEST_VECTORS + }, + .dec = { + .vecs = tf_cbc_dec_tv_template, + .count = TF_CBC_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ccm(aes)", + .test = alg_test_aead, + .suite = { + .aead = { + .enc = { + .vecs = aes_ccm_enc_tv_template, + .count = AES_CCM_ENC_TEST_VECTORS + }, + .dec = { + .vecs = aes_ccm_dec_tv_template, + .count = AES_CCM_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "crc32c", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = crc32c_tv_template, + .count = CRC32C_TEST_VECTORS + } + } + }, { + .alg = "cts(cbc(aes))", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = cts_mode_enc_tv_template, + .count = CTS_MODE_ENC_TEST_VECTORS + }, + .dec = { + .vecs = cts_mode_dec_tv_template, + .count = CTS_MODE_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "deflate", + .test = alg_test_comp, + .suite = { + .comp = { + .comp = { + .vecs = deflate_comp_tv_template, + .count = DEFLATE_COMP_TEST_VECTORS + }, + .decomp = { + .vecs = deflate_decomp_tv_template, + .count = DEFLATE_DECOMP_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(aes)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = aes_enc_tv_template, + .count = AES_ENC_TEST_VECTORS + }, + .dec = { + .vecs = aes_dec_tv_template, + .count = AES_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(anubis)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = anubis_enc_tv_template, + .count = ANUBIS_ENC_TEST_VECTORS + }, + .dec = { + .vecs = anubis_dec_tv_template, + .count = ANUBIS_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(arc4)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = arc4_enc_tv_template, + .count = ARC4_ENC_TEST_VECTORS + }, + .dec = { + .vecs = arc4_dec_tv_template, + .count = ARC4_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(blowfish)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = bf_enc_tv_template, + .count = BF_ENC_TEST_VECTORS + }, + .dec = { + .vecs = bf_dec_tv_template, + .count = BF_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(camellia)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = camellia_enc_tv_template, + .count = CAMELLIA_ENC_TEST_VECTORS + }, + .dec = { + .vecs = camellia_dec_tv_template, + .count = CAMELLIA_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(cast5)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = cast5_enc_tv_template, + .count = CAST5_ENC_TEST_VECTORS + }, + .dec = { + .vecs = cast5_dec_tv_template, + .count = CAST5_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(cast6)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = cast6_enc_tv_template, + .count = CAST6_ENC_TEST_VECTORS + }, + .dec = { + .vecs = cast6_dec_tv_template, + .count = CAST6_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(des)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = des_enc_tv_template, + .count = DES_ENC_TEST_VECTORS + }, + .dec = { + .vecs = des_dec_tv_template, + .count = DES_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(des3_ede)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = des3_ede_enc_tv_template, + .count = DES3_EDE_ENC_TEST_VECTORS + }, + .dec = { + .vecs = des3_ede_dec_tv_template, + .count = DES3_EDE_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(khazad)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = khazad_enc_tv_template, + .count = KHAZAD_ENC_TEST_VECTORS + }, + .dec = { + .vecs = khazad_dec_tv_template, + .count = KHAZAD_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(seed)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = seed_enc_tv_template, + .count = SEED_ENC_TEST_VECTORS + }, + .dec = { + .vecs = seed_dec_tv_template, + .count = SEED_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(serpent)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = serpent_enc_tv_template, + .count = SERPENT_ENC_TEST_VECTORS + }, + .dec = { + .vecs = serpent_dec_tv_template, + .count = SERPENT_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(tea)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = tea_enc_tv_template, + .count = TEA_ENC_TEST_VECTORS + }, + .dec = { + .vecs = tea_dec_tv_template, + .count = TEA_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(tnepres)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = tnepres_enc_tv_template, + .count = TNEPRES_ENC_TEST_VECTORS + }, + .dec = { + .vecs = tnepres_dec_tv_template, + .count = TNEPRES_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(twofish)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = tf_enc_tv_template, + .count = TF_ENC_TEST_VECTORS + }, + .dec = { + .vecs = tf_dec_tv_template, + .count = TF_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(xeta)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = xeta_enc_tv_template, + .count = XETA_ENC_TEST_VECTORS + }, + .dec = { + .vecs = xeta_dec_tv_template, + .count = XETA_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "ecb(xtea)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = xtea_enc_tv_template, + .count = XTEA_ENC_TEST_VECTORS + }, + .dec = { + .vecs = xtea_dec_tv_template, + .count = XTEA_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "gcm(aes)", + .test = alg_test_aead, + .suite = { + .aead = { + .enc = { + .vecs = aes_gcm_enc_tv_template, + .count = AES_GCM_ENC_TEST_VECTORS + }, + .dec = { + .vecs = aes_gcm_dec_tv_template, + .count = AES_GCM_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "hmac(md5)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_md5_tv_template, + .count = HMAC_MD5_TEST_VECTORS + } + } + }, { + .alg = "hmac(rmd128)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_rmd128_tv_template, + .count = HMAC_RMD128_TEST_VECTORS + } + } + }, { + .alg = "hmac(rmd160)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_rmd160_tv_template, + .count = HMAC_RMD160_TEST_VECTORS + } + } + }, { + .alg = "hmac(sha1)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_sha1_tv_template, + .count = HMAC_SHA1_TEST_VECTORS + } + } + }, { + .alg = "hmac(sha224)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_sha224_tv_template, + .count = HMAC_SHA224_TEST_VECTORS + } + } + }, { + .alg = "hmac(sha256)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_sha256_tv_template, + .count = HMAC_SHA256_TEST_VECTORS + } + } + }, { + .alg = "hmac(sha384)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_sha384_tv_template, + .count = HMAC_SHA384_TEST_VECTORS + } + } + }, { + .alg = "hmac(sha512)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = hmac_sha512_tv_template, + .count = HMAC_SHA512_TEST_VECTORS + } + } + }, { + .alg = "lrw(aes)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = aes_lrw_enc_tv_template, + .count = AES_LRW_ENC_TEST_VECTORS + }, + .dec = { + .vecs = aes_lrw_dec_tv_template, + .count = AES_LRW_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "lzo", + .test = alg_test_comp, + .suite = { + .comp = { + .comp = { + .vecs = lzo_comp_tv_template, + .count = LZO_COMP_TEST_VECTORS + }, + .decomp = { + .vecs = lzo_decomp_tv_template, + .count = LZO_DECOMP_TEST_VECTORS + } + } + } + }, { + .alg = "md4", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = md4_tv_template, + .count = MD4_TEST_VECTORS + } + } + }, { + .alg = "md5", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = md5_tv_template, + .count = MD5_TEST_VECTORS + } + } + }, { + .alg = "michael_mic", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = michael_mic_tv_template, + .count = MICHAEL_MIC_TEST_VECTORS + } + } + }, { + .alg = "pcbc(fcrypt)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = fcrypt_pcbc_enc_tv_template, + .count = FCRYPT_ENC_TEST_VECTORS + }, + .dec = { + .vecs = fcrypt_pcbc_dec_tv_template, + .count = FCRYPT_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "rfc3686(ctr(aes))", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = aes_ctr_enc_tv_template, + .count = AES_CTR_ENC_TEST_VECTORS + }, + .dec = { + .vecs = aes_ctr_dec_tv_template, + .count = AES_CTR_DEC_TEST_VECTORS + } + } + } + }, { + .alg = "rmd128", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = rmd128_tv_template, + .count = RMD128_TEST_VECTORS + } + } + }, { + .alg = "rmd160", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = rmd160_tv_template, + .count = RMD160_TEST_VECTORS + } + } + }, { + .alg = "rmd256", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = rmd256_tv_template, + .count = RMD256_TEST_VECTORS + } + } + }, { + .alg = "rmd320", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = rmd320_tv_template, + .count = RMD320_TEST_VECTORS + } + } + }, { + .alg = "salsa20", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = salsa20_stream_enc_tv_template, + .count = SALSA20_STREAM_ENC_TEST_VECTORS + } + } + } + }, { + .alg = "sha1", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = sha1_tv_template, + .count = SHA1_TEST_VECTORS + } + } + }, { + .alg = "sha224", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = sha224_tv_template, + .count = SHA224_TEST_VECTORS + } + } + }, { + .alg = "sha256", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = sha256_tv_template, + .count = SHA256_TEST_VECTORS + } + } + }, { + .alg = "sha384", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = sha384_tv_template, + .count = SHA384_TEST_VECTORS + } + } + }, { + .alg = "sha512", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = sha512_tv_template, + .count = SHA512_TEST_VECTORS + } + } + }, { + .alg = "tgr128", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = tgr128_tv_template, + .count = TGR128_TEST_VECTORS + } + } + }, { + .alg = "tgr160", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = tgr160_tv_template, + .count = TGR160_TEST_VECTORS + } + } + }, { + .alg = "tgr192", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = tgr192_tv_template, + .count = TGR192_TEST_VECTORS + } + } + }, { + .alg = "wp256", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = wp256_tv_template, + .count = WP256_TEST_VECTORS + } + } + }, { + .alg = "wp384", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = wp384_tv_template, + .count = WP384_TEST_VECTORS + } + } + }, { + .alg = "wp512", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = wp512_tv_template, + .count = WP512_TEST_VECTORS + } + } + }, { + .alg = "xcbc(aes)", + .test = alg_test_hash, + .suite = { + .hash = { + .vecs = aes_xcbc128_tv_template, + .count = XCBC_AES_TEST_VECTORS + } + } + }, { + .alg = "xts(aes)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = aes_xts_enc_tv_template, + .count = AES_XTS_ENC_TEST_VECTORS + }, + .dec = { + .vecs = aes_xts_dec_tv_template, + .count = AES_XTS_DEC_TEST_VECTORS + } + } + } + } +}; + +static int alg_find_test(const char *alg) +{ + int start = 0; + int end = ARRAY_SIZE(alg_test_descs); + + while (start < end) { + int i = (start + end) / 2; + int diff = strcmp(alg_test_descs[i].alg, alg); + + if (diff > 0) { + end = i; + continue; + } + + if (diff < 0) { + start = i + 1; + continue; + } + + return i; + } + + return -1; +} + +int alg_test(const char *driver, const char *alg, u32 type, u32 mask) +{ + int i; + + if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) { + char nalg[CRYPTO_MAX_ALG_NAME]; + + if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >= + sizeof(nalg)) + return -ENAMETOOLONG; + + i = alg_find_test(nalg); + if (i < 0) + goto notest; + + return alg_test_cipher(alg_test_descs + i, driver, type, mask); + } + + i = alg_find_test(alg); + if (i < 0) + goto notest; + + return alg_test_descs[i].test(alg_test_descs + i, driver, + type, mask); + +notest: + printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver); + return 0; +} +EXPORT_SYMBOL_GPL(alg_test); + +int __init testmgr_init(void) +{ + int i; + + for (i = 0; i < XBUFSIZE; i++) { + xbuf[i] = (void *)__get_free_page(GFP_KERNEL); + if (!xbuf[i]) + goto err_free_xbuf; + } + + for (i = 0; i < XBUFSIZE; i++) { + axbuf[i] = (void *)__get_free_page(GFP_KERNEL); + if (!axbuf[i]) + goto err_free_axbuf; + } + + return 0; + +err_free_axbuf: + for (i = 0; i < XBUFSIZE && axbuf[i]; i++) + free_page((unsigned long)axbuf[i]); +err_free_xbuf: + for (i = 0; i < XBUFSIZE && xbuf[i]; i++) + free_page((unsigned long)xbuf[i]); + + return -ENOMEM; +} + +void testmgr_exit(void) +{ + int i; + + for (i = 0; i < XBUFSIZE; i++) + free_page((unsigned long)axbuf[i]); + for (i = 0; i < XBUFSIZE; i++) + free_page((unsigned long)xbuf[i]); +} diff --git a/crypto/testmgr.h b/crypto/testmgr.h new file mode 100644 index 000000000000..dee94d9ecfba --- /dev/null +++ b/crypto/testmgr.h @@ -0,0 +1,8738 @@ +/* + * Algorithm testing framework and tests. + * + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org> + * Copyright (c) 2007 Nokia Siemens Networks + * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_TESTMGR_H +#define _CRYPTO_TESTMGR_H + +#define MAX_DIGEST_SIZE 64 +#define MAX_TAP 8 + +#define MAX_KEYLEN 56 +#define MAX_IVLEN 32 + +struct hash_testvec { + /* only used with keyed hash algorithms */ + char *key; + char *plaintext; + char *digest; + unsigned char tap[MAX_TAP]; + unsigned char psize; + unsigned char np; + unsigned char ksize; +}; + +struct cipher_testvec { + char *key; + char *iv; + char *input; + char *result; + unsigned short tap[MAX_TAP]; + int np; + unsigned char fail; + unsigned char wk; /* weak key flag */ + unsigned char klen; + unsigned short ilen; + unsigned short rlen; +}; + +struct aead_testvec { + char *key; + char *iv; + char *input; + char *assoc; + char *result; + unsigned char tap[MAX_TAP]; + unsigned char atap[MAX_TAP]; + int np; + int anp; + unsigned char fail; + unsigned char wk; /* weak key flag */ + unsigned char klen; + unsigned short ilen; + unsigned short alen; + unsigned short rlen; +}; + +static char zeroed_string[48]; + +/* + * MD4 test vectors from RFC1320 + */ +#define MD4_TEST_VECTORS 7 + +static struct hash_testvec md4_tv_template [] = { + { + .plaintext = "", + .digest = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31" + "\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0", + }, { + .plaintext = "a", + .psize = 1, + .digest = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46" + "\x24\x5e\x05\xfb\xdb\xd6\xfb\x24", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52" + "\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8" + "\x18\x87\x48\x06\xe1\xc7\x01\x4b", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd" + "\xee\xa8\xed\x63\xdf\x41\x2d\xa9", + .np = 2, + .tap = { 13, 13 }, + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\x04\x3f\x85\x82\xf2\x41\xdb\x35" + "\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4", + }, { + .plaintext = "123456789012345678901234567890123456789012345678901234567890123" + "45678901234567890", + .psize = 80, + .digest = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19" + "\x9c\x3e\x7b\x16\x4f\xcc\x05\x36", + }, +}; + +/* + * MD5 test vectors from RFC1321 + */ +#define MD5_TEST_VECTORS 7 + +static struct hash_testvec md5_tv_template[] = { + { + .digest = "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04" + "\xe9\x80\x09\x98\xec\xf8\x42\x7e", + }, { + .plaintext = "a", + .psize = 1, + .digest = "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8" + "\x31\xc3\x99\xe2\x69\x77\x26\x61", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0" + "\xd6\x96\x3f\x7d\x28\xe1\x7f\x72", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d" + "\x52\x5a\x2f\x31\xaa\xf1\x61\xd0", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00" + "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b", + .np = 2, + .tap = {13, 13} + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5" + "\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", + }, { + .plaintext = "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890", + .psize = 80, + .digest = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55" + "\xac\x49\xda\x2e\x21\x07\xb6\x7a", + } + +}; + +/* + * RIPEMD-128 test vectors from ISO/IEC 10118-3:2004(E) + */ +#define RMD128_TEST_VECTORS 10 + +static struct hash_testvec rmd128_tv_template[] = { + { + .digest = "\xcd\xf2\x62\x13\xa1\x50\xdc\x3e" + "\xcb\x61\x0f\x18\xf6\xb3\x8b\x46", + }, { + .plaintext = "a", + .psize = 1, + .digest = "\x86\xbe\x7a\xfa\x33\x9d\x0f\xc7" + "\xcf\xc7\x85\xe7\x2f\x57\x8d\x33", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\xc1\x4a\x12\x19\x9c\x66\xe4\xba" + "\x84\x63\x6b\x0f\x69\x14\x4c\x77", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\x9e\x32\x7b\x3d\x6e\x52\x30\x62" + "\xaf\xc1\x13\x2d\x7d\xf9\xd1\xb8", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xfd\x2a\xa6\x07\xf7\x1d\xc8\xf5" + "\x10\x71\x49\x22\xb3\x71\x83\x4e", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" + "fghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\xd1\xe9\x59\xeb\x17\x9c\x91\x1f" + "\xae\xa4\x62\x4c\x60\xc5\xc7\x02", + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = "\x3f\x45\xef\x19\x47\x32\xc2\xdb" + "\xb2\xc4\xa2\xc7\x69\x79\x5f\xa3", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xa1\xaa\x06\x89\xd0\xfa\xfa\x2d" + "\xdc\x22\xe8\x8b\x49\x13\x3a\x06", + .np = 2, + .tap = { 28, 28 }, + }, { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghi" + "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqr" + "lmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = "\xd4\xec\xc9\x13\xe1\xdf\x77\x6b" + "\xf4\x8d\xe9\xd5\x5b\x1f\x25\x46", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = "\x13\xfc\x13\xe8\xef\xff\x34\x7d" + "\xe1\x93\xff\x46\xdb\xac\xcf\xd4", + } +}; + +/* + * RIPEMD-160 test vectors from ISO/IEC 10118-3:2004(E) + */ +#define RMD160_TEST_VECTORS 10 + +static struct hash_testvec rmd160_tv_template[] = { + { + .digest = "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28" + "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31", + }, { + .plaintext = "a", + .psize = 1, + .digest = "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae" + "\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04" + "\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8" + "\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xf7\x1c\x27\x10\x9c\x69\x2c\x1b\x56\xbb" + "\xdc\xeb\x5b\x9d\x28\x65\xb3\x70\x8d\xbc", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" + "fghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\xb0\xe2\x0b\x6e\x31\x16\x64\x02\x86\xed" + "\x3a\x87\xa5\x71\x30\x79\xb2\x1f\x51\x89", + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb" + "\xd3\x32\x3c\xab\x82\xbf\x63\x32\x6b\xfb", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05" + "\xa0\x6c\x27\xdc\xf4\x9a\xda\x62\xeb\x2b", + .np = 2, + .tap = { 28, 28 }, + }, { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghi" + "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqr" + "lmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = "\x6f\x3f\xa3\x9b\x6b\x50\x3c\x38\x4f\x91" + "\x9a\x49\xa7\xaa\x5c\x2c\x08\xbd\xfb\x45", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = "\x94\xc2\x64\x11\x54\x04\xe6\x33\x79\x0d" + "\xfc\xc8\x7b\x58\x7d\x36\x77\x06\x7d\x9f", + } +}; + +/* + * RIPEMD-256 test vectors + */ +#define RMD256_TEST_VECTORS 8 + +static struct hash_testvec rmd256_tv_template[] = { + { + .digest = "\x02\xba\x4c\x4e\x5f\x8e\xcd\x18" + "\x77\xfc\x52\xd6\x4d\x30\xe3\x7a" + "\x2d\x97\x74\xfb\x1e\x5d\x02\x63" + "\x80\xae\x01\x68\xe3\xc5\x52\x2d", + }, { + .plaintext = "a", + .psize = 1, + .digest = "\xf9\x33\x3e\x45\xd8\x57\xf5\xd9" + "\x0a\x91\xba\xb7\x0a\x1e\xba\x0c" + "\xfb\x1b\xe4\xb0\x78\x3c\x9a\xcf" + "\xcd\x88\x3a\x91\x34\x69\x29\x25", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\xaf\xbd\x6e\x22\x8b\x9d\x8c\xbb" + "\xce\xf5\xca\x2d\x03\xe6\xdb\xa1" + "\x0a\xc0\xbc\x7d\xcb\xe4\x68\x0e" + "\x1e\x42\xd2\xe9\x75\x45\x9b\x65", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\x87\xe9\x71\x75\x9a\x1c\xe4\x7a" + "\x51\x4d\x5c\x91\x4c\x39\x2c\x90" + "\x18\xc7\xc4\x6b\xc1\x44\x65\x55" + "\x4a\xfc\xdf\x54\xa5\x07\x0c\x0e", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\x64\x9d\x30\x34\x75\x1e\xa2\x16" + "\x77\x6b\xf9\xa1\x8a\xcc\x81\xbc" + "\x78\x96\x11\x8a\x51\x97\x96\x87" + "\x82\xdd\x1f\xd9\x7d\x8d\x51\x33", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" + "fghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\x57\x40\xa4\x08\xac\x16\xb7\x20" + "\xb8\x44\x24\xae\x93\x1c\xbb\x1f" + "\xe3\x63\xd1\xd0\xbf\x40\x17\xf1" + "\xa8\x9f\x7e\xa6\xde\x77\xa0\xb8", + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = "\x06\xfd\xcc\x7a\x40\x95\x48\xaa" + "\xf9\x13\x68\xc0\x6a\x62\x75\xb5" + "\x53\xe3\xf0\x99\xbf\x0e\xa4\xed" + "\xfd\x67\x78\xdf\x89\xa8\x90\xdd", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x38\x43\x04\x55\x83\xaa\xc6\xc8" + "\xc8\xd9\x12\x85\x73\xe7\xa9\x80" + "\x9a\xfb\x2a\x0f\x34\xcc\xc3\x6e" + "\xa9\xe7\x2f\x16\xf6\x36\x8e\x3f", + .np = 2, + .tap = { 28, 28 }, + } +}; + +/* + * RIPEMD-320 test vectors + */ +#define RMD320_TEST_VECTORS 8 + +static struct hash_testvec rmd320_tv_template[] = { + { + .digest = "\x22\xd6\x5d\x56\x61\x53\x6c\xdc\x75\xc1" + "\xfd\xf5\xc6\xde\x7b\x41\xb9\xf2\x73\x25" + "\xeb\xc6\x1e\x85\x57\x17\x7d\x70\x5a\x0e" + "\xc8\x80\x15\x1c\x3a\x32\xa0\x08\x99\xb8", + }, { + .plaintext = "a", + .psize = 1, + .digest = "\xce\x78\x85\x06\x38\xf9\x26\x58\xa5\xa5" + "\x85\x09\x75\x79\x92\x6d\xda\x66\x7a\x57" + "\x16\x56\x2c\xfc\xf6\xfb\xe7\x7f\x63\x54" + "\x2f\x99\xb0\x47\x05\xd6\x97\x0d\xff\x5d", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\xde\x4c\x01\xb3\x05\x4f\x89\x30\xa7\x9d" + "\x09\xae\x73\x8e\x92\x30\x1e\x5a\x17\x08" + "\x5b\xef\xfd\xc1\xb8\xd1\x16\x71\x3e\x74" + "\xf8\x2f\xa9\x42\xd6\x4c\xdb\xc4\x68\x2d", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\x3a\x8e\x28\x50\x2e\xd4\x5d\x42\x2f\x68" + "\x84\x4f\x9d\xd3\x16\xe7\xb9\x85\x33\xfa" + "\x3f\x2a\x91\xd2\x9f\x84\xd4\x25\xc8\x8d" + "\x6b\x4e\xff\x72\x7d\xf6\x6a\x7c\x01\x97", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xca\xbd\xb1\x81\x0b\x92\x47\x0a\x20\x93" + "\xaa\x6b\xce\x05\x95\x2c\x28\x34\x8c\xf4" + "\x3f\xf6\x08\x41\x97\x51\x66\xbb\x40\xed" + "\x23\x40\x04\xb8\x82\x44\x63\xe6\xb0\x09", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" + "fghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\xed\x54\x49\x40\xc8\x6d\x67\xf2\x50\xd2" + "\x32\xc3\x0b\x7b\x3e\x57\x70\xe0\xc6\x0c" + "\x8c\xb9\xa4\xca\xfe\x3b\x11\x38\x8a\xf9" + "\x92\x0e\x1b\x99\x23\x0b\x84\x3c\x86\xa4", + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = "\x55\x78\x88\xaf\x5f\x6d\x8e\xd6\x2a\xb6" + "\x69\x45\xc6\xd2\xa0\xa4\x7e\xcd\x53\x41" + "\xe9\x15\xeb\x8f\xea\x1d\x05\x24\x95\x5f" + "\x82\x5d\xc7\x17\xe4\xa0\x08\xab\x2d\x42", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighij" + "hijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\xd0\x34\xa7\x95\x0c\xf7\x22\x02\x1b\xa4" + "\xb8\x4d\xf7\x69\xa5\xde\x20\x60\xe2\x59" + "\xdf\x4c\x9b\xb4\xa4\x26\x8c\x0e\x93\x5b" + "\xbc\x74\x70\xa9\x69\xc9\xd0\x72\xa1\xac", + .np = 2, + .tap = { 28, 28 }, + } +}; + +/* + * SHA1 test vectors from from FIPS PUB 180-1 + */ +#define SHA1_TEST_VECTORS 2 + +static struct hash_testvec sha1_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e" + "\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae" + "\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1", + .np = 2, + .tap = { 28, 28 } + } +}; + + +/* + * SHA224 test vectors from from FIPS PUB 180-2 + */ +#define SHA224_TEST_VECTORS 2 + +static struct hash_testvec sha224_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = "\x23\x09\x7D\x22\x34\x05\xD8\x22" + "\x86\x42\xA4\x77\xBD\xA2\x55\xB3" + "\x2A\xAD\xBC\xE4\xBD\xA0\xB3\xF7" + "\xE3\x6C\x9D\xA7", + }, { + .plaintext = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x75\x38\x8B\x16\x51\x27\x76\xCC" + "\x5D\xBA\x5D\xA1\xFD\x89\x01\x50" + "\xB0\xC6\x45\x5C\xB4\xF5\x8B\x19" + "\x52\x52\x25\x25", + .np = 2, + .tap = { 28, 28 } + } +}; + +/* + * SHA256 test vectors from from NIST + */ +#define SHA256_TEST_VECTORS 2 + +static struct hash_testvec sha256_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = "\xba\x78\x16\xbf\x8f\x01\xcf\xea" + "\x41\x41\x40\xde\x5d\xae\x22\x23" + "\xb0\x03\x61\xa3\x96\x17\x7a\x9c" + "\xb4\x10\xff\x61\xf2\x00\x15\xad", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x24\x8d\x6a\x61\xd2\x06\x38\xb8" + "\xe5\xc0\x26\x93\x0c\x3e\x60\x39" + "\xa3\x3c\xe4\x59\x64\xff\x21\x67" + "\xf6\xec\xed\xd4\x19\xdb\x06\xc1", + .np = 2, + .tap = { 28, 28 } + }, +}; + +/* + * SHA384 test vectors from from NIST and kerneli + */ +#define SHA384_TEST_VECTORS 4 + +static struct hash_testvec sha384_tv_template[] = { + { + .plaintext= "abc", + .psize = 3, + .digest = "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b" + "\xb5\xa0\x3d\x69\x9a\xc6\x50\x07" + "\x27\x2c\x32\xab\x0e\xde\xd1\x63" + "\x1a\x8b\x60\x5a\x43\xff\x5b\xed" + "\x80\x86\x07\x2b\xa1\xe7\xcc\x23" + "\x58\xba\xec\xa1\x34\xc8\x25\xa7", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x33\x91\xfd\xdd\xfc\x8d\xc7\x39" + "\x37\x07\xa6\x5b\x1b\x47\x09\x39" + "\x7c\xf8\xb1\xd1\x62\xaf\x05\xab" + "\xfe\x8f\x45\x0d\xe5\xf3\x6b\xc6" + "\xb0\x45\x5a\x85\x20\xbc\x4e\x6f" + "\x5f\xe9\x5b\x1f\xe3\xc8\x45\x2b", + }, { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = "\x09\x33\x0c\x33\xf7\x11\x47\xe8" + "\x3d\x19\x2f\xc7\x82\xcd\x1b\x47" + "\x53\x11\x1b\x17\x3b\x3b\x05\xd2" + "\x2f\xa0\x80\x86\xe3\xb0\xf7\x12" + "\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9" + "\x66\xc3\xe9\xfa\x91\x74\x60\x39", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + .psize = 104, + .digest = "\x3d\x20\x89\x73\xab\x35\x08\xdb" + "\xbd\x7e\x2c\x28\x62\xba\x29\x0a" + "\xd3\x01\x0e\x49\x78\xc1\x98\xdc" + "\x4d\x8f\xd0\x14\xe5\x82\x82\x3a" + "\x89\xe1\x6f\x9b\x2a\x7b\xbc\x1a" + "\xc9\x38\xe2\xd1\x99\xe8\xbe\xa4", + .np = 4, + .tap = { 26, 26, 26, 26 } + }, +}; + +/* + * SHA512 test vectors from from NIST and kerneli + */ +#define SHA512_TEST_VECTORS 4 + +static struct hash_testvec sha512_tv_template[] = { + { + .plaintext = "abc", + .psize = 3, + .digest = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba" + "\xcc\x41\x73\x49\xae\x20\x41\x31" + "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2" + "\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a" + "\x21\x92\x99\x2a\x27\x4f\xc1\xa8" + "\x36\xba\x3c\x23\xa3\xfe\xeb\xbd" + "\x45\x4d\x44\x23\x64\x3c\xe8\x0e" + "\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a" + "\x0c\xed\x7b\xeb\x8e\x08\xa4\x16" + "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8" + "\x27\x9b\xe3\x31\xa7\x03\xc3\x35" + "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9" + "\xaa\x1d\x3b\xea\x57\x78\x9c\xa0" + "\x31\xad\x85\xc7\xa7\x1d\xd7\x03" + "\x54\xec\x63\x12\x38\xca\x34\x45", + }, { + .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + .psize = 112, + .digest = "\x8e\x95\x9b\x75\xda\xe3\x13\xda" + "\x8c\xf4\xf7\x28\x14\xfc\x14\x3f" + "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1" + "\x72\x99\xae\xad\xb6\x88\x90\x18" + "\x50\x1d\x28\x9e\x49\x00\xf7\xe4" + "\x33\x1b\x99\xde\xc4\xb5\x43\x3a" + "\xc7\xd3\x29\xee\xb6\xdd\x26\x54" + "\x5e\x96\xe5\x5b\x87\x4b\xe9\x09", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + .psize = 104, + .digest = "\x93\x0d\x0c\xef\xcb\x30\xff\x11" + "\x33\xb6\x89\x81\x21\xf1\xcf\x3d" + "\x27\x57\x8a\xfc\xaf\xe8\x67\x7c" + "\x52\x57\xcf\x06\x99\x11\xf7\x5d" + "\x8f\x58\x31\xb5\x6e\xbf\xda\x67" + "\xb2\x78\xe6\x6d\xff\x8b\x84\xfe" + "\x2b\x28\x70\xf7\x42\xa5\x80\xd8" + "\xed\xb4\x19\x87\x23\x28\x50\xc9", + .np = 4, + .tap = { 26, 26, 26, 26 } + }, +}; + + +/* + * WHIRLPOOL test vectors from Whirlpool package + * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE + * submission + */ +#define WP512_TEST_VECTORS 8 + +static struct hash_testvec wp512_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66" + "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26" + "\xC5\x30\x23\x21\x30\xD4\x07\xF8" + "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7" + "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB" + "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57" + "\xEA\x89\x64\xE5\x9B\x63\xD9\x37" + "\x08\xB1\x38\xCC\x42\xA6\x6E\xB3", + + + }, { + .plaintext = "a", + .psize = 1, + .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F" + "\x11\xA6\x72\x06\x53\x1F\xB7\xD7" + "\xF0\xDF\xF5\x94\x13\x14\x5E\x69" + "\x73\xC4\x50\x01\xD0\x08\x7B\x42" + "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6" + "\x3A\x42\x39\x1A\x39\x14\x5A\x59" + "\x1A\x92\x20\x0D\x56\x01\x95\xE5" + "\x3B\x47\x85\x84\xFD\xAE\x23\x1A", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB" + "\x16\xB6\x56\x2C\x73\xB4\x02\x0B" + "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72" + "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C" + "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27" + "\x7D\x0E\x34\x95\x71\x14\xCB\xD6" + "\xC7\x97\xFC\x9D\x95\xD8\xB5\x82" + "\xD2\x25\x29\x20\x76\xD4\xEE\xF5", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6" + "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC" + "\x83\x8D\x00\x03\x22\x30\xF5\x3C" + "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B" + "\x84\x21\x55\x76\x59\xEF\x55\xC1" + "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6" + "\x92\xED\x92\x00\x52\x83\x8F\x33" + "\x62\xE8\x6D\xBD\x37\xA8\x90\x3E", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9" + "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A" + "\x8D\x38\x63\x1E\xAD\x42\x38\xF5" + "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B" + "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A" + "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6" + "\xF6\x8F\x67\x3E\x72\x07\x86\x5D" + "\x5D\x98\x19\xA3\xDB\xA4\xEB\x3B", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B" + "\xF1\x1F\x00\xED\x9A\xBA\x26\x90" + "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC" + "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E" + "\x08\xEB\xA2\x66\x29\x12\x9D\x8F" + "\xB7\xCB\x57\x21\x1B\x92\x81\xA6" + "\x55\x17\xCC\x87\x9D\x7B\x96\x21" + "\x42\xC6\x5F\x5A\x7A\xF0\x14\x67", + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D" + "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0" + "\x87\x84\x37\x2B\xCC\xB2\x04\xD6" + "\x54\x9C\x4A\xFA\xDB\x60\x14\x29" + "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5" + "\x38\xCD\x04\x7B\x26\x81\xA5\x1A" + "\x2C\x60\x48\x1E\x88\xC5\xA2\x0B" + "\x2C\x2A\x80\xCF\x3A\x9A\x08\x3B", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61" + "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48" + "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62" + "\x07\xC5\x62\xF9\x88\xE9\x5C\x69" + "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B" + "\x7B\x94\x76\x39\xFE\x05\x0B\x56" + "\x93\x9B\xAA\xA0\xAD\xFF\x9A\xE6" + "\x74\x5B\x7B\x18\x1C\x3B\xE3\xFD", + }, +}; + +#define WP384_TEST_VECTORS 8 + +static struct hash_testvec wp384_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66" + "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26" + "\xC5\x30\x23\x21\x30\xD4\x07\xF8" + "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7" + "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB" + "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57", + + + }, { + .plaintext = "a", + .psize = 1, + .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F" + "\x11\xA6\x72\x06\x53\x1F\xB7\xD7" + "\xF0\xDF\xF5\x94\x13\x14\x5E\x69" + "\x73\xC4\x50\x01\xD0\x08\x7B\x42" + "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6" + "\x3A\x42\x39\x1A\x39\x14\x5A\x59", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB" + "\x16\xB6\x56\x2C\x73\xB4\x02\x0B" + "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72" + "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C" + "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27" + "\x7D\x0E\x34\x95\x71\x14\xCB\xD6", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6" + "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC" + "\x83\x8D\x00\x03\x22\x30\xF5\x3C" + "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B" + "\x84\x21\x55\x76\x59\xEF\x55\xC1" + "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9" + "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A" + "\x8D\x38\x63\x1E\xAD\x42\x38\xF5" + "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B" + "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A" + "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B" + "\xF1\x1F\x00\xED\x9A\xBA\x26\x90" + "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC" + "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E" + "\x08\xEB\xA2\x66\x29\x12\x9D\x8F" + "\xB7\xCB\x57\x21\x1B\x92\x81\xA6", + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D" + "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0" + "\x87\x84\x37\x2B\xCC\xB2\x04\xD6" + "\x54\x9C\x4A\xFA\xDB\x60\x14\x29" + "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5" + "\x38\xCD\x04\x7B\x26\x81\xA5\x1A", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61" + "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48" + "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62" + "\x07\xC5\x62\xF9\x88\xE9\x5C\x69" + "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B" + "\x7B\x94\x76\x39\xFE\x05\x0B\x56", + }, +}; + +#define WP256_TEST_VECTORS 8 + +static struct hash_testvec wp256_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66" + "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26" + "\xC5\x30\x23\x21\x30\xD4\x07\xF8" + "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7", + + + }, { + .plaintext = "a", + .psize = 1, + .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F" + "\x11\xA6\x72\x06\x53\x1F\xB7\xD7" + "\xF0\xDF\xF5\x94\x13\x14\x5E\x69" + "\x73\xC4\x50\x01\xD0\x08\x7B\x42", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB" + "\x16\xB6\x56\x2C\x73\xB4\x02\x0B" + "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72" + "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C", + }, { + .plaintext = "message digest", + .psize = 14, + .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6" + "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC" + "\x83\x8D\x00\x03\x22\x30\xF5\x3C" + "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B", + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9" + "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A" + "\x8D\x38\x63\x1E\xAD\x42\x38\xF5" + "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B" + "\xF1\x1F\x00\xED\x9A\xBA\x26\x90" + "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC" + "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E", + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D" + "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0" + "\x87\x84\x37\x2B\xCC\xB2\x04\xD6" + "\x54\x9C\x4A\xFA\xDB\x60\x14\x29", + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61" + "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48" + "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62" + "\x07\xC5\x62\xF9\x88\xE9\x5C\x69", + }, +}; + +/* + * TIGER test vectors from Tiger website + */ +#define TGR192_TEST_VECTORS 6 + +static struct hash_testvec tgr192_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32" + "\x16\x16\x6e\x76\xb1\xbb\x92\x5f" + "\xf3\x73\xde\x2d\x49\x58\x4e\x7a", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a" + "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf" + "\x93\x5f\x7b\x95\x1c\x13\x29\x51", + }, { + .plaintext = "Tiger", + .psize = 5, + .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd" + "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec" + "\x37\x79\x0c\x11\x6f\x9d\x2b\xdf", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7" + "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e" + "\xb5\x86\x44\x50\x34\xa5\xa3\x86", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", + .psize = 64, + .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48" + "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9" + "\x57\x89\x65\x65\x97\x5f\x91\x97", + }, { + .plaintext = "Tiger - A Fast New Hash Function, " + "by Ross Anderson and Eli Biham, " + "proceedings of Fast Software Encryption 3, " + "Cambridge, 1996.", + .psize = 125, + .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63" + "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24" + "\xdd\x68\x15\x1d\x50\x39\x74\xfc", + }, +}; + +#define TGR160_TEST_VECTORS 6 + +static struct hash_testvec tgr160_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32" + "\x16\x16\x6e\x76\xb1\xbb\x92\x5f" + "\xf3\x73\xde\x2d", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a" + "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf" + "\x93\x5f\x7b\x95", + }, { + .plaintext = "Tiger", + .psize = 5, + .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd" + "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec" + "\x37\x79\x0c\x11", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7" + "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e" + "\xb5\x86\x44\x50", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", + .psize = 64, + .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48" + "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9" + "\x57\x89\x65\x65", + }, { + .plaintext = "Tiger - A Fast New Hash Function, " + "by Ross Anderson and Eli Biham, " + "proceedings of Fast Software Encryption 3, " + "Cambridge, 1996.", + .psize = 125, + .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63" + "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24" + "\xdd\x68\x15\x1d", + }, +}; + +#define TGR128_TEST_VECTORS 6 + +static struct hash_testvec tgr128_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32" + "\x16\x16\x6e\x76\xb1\xbb\x92\x5f", + }, { + .plaintext = "abc", + .psize = 3, + .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a" + "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf", + }, { + .plaintext = "Tiger", + .psize = 5, + .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd" + "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + .psize = 64, + .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7" + "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e", + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", + .psize = 64, + .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48" + "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9", + }, { + .plaintext = "Tiger - A Fast New Hash Function, " + "by Ross Anderson and Eli Biham, " + "proceedings of Fast Software Encryption 3, " + "Cambridge, 1996.", + .psize = 125, + .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63" + "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24", + }, +}; + +/* + * HMAC-MD5 test vectors from RFC2202 + * (These need to be fixed to not use strlen). + */ +#define HMAC_MD5_TEST_VECTORS 7 + +static struct hash_testvec hmac_md5_tv_template[] = +{ + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 16, + .plaintext = "Hi There", + .psize = 8, + .digest = "\x92\x94\x72\x7a\x36\x38\xbb\x1c" + "\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d", + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03" + "\xea\xa8\x6e\x31\x0a\x5d\xb7\x38", + .np = 2, + .tap = {14, 14} + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 16, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\x56\xbe\x34\x52\x1d\x14\x4c\x88" + "\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6", + }, { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + .ksize = 25, + .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + .psize = 50, + .digest = "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea" + "\x3a\x75\x16\x47\x46\xff\xaa\x79", + }, { + .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + .ksize = 16, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = "\x56\x46\x1e\xf2\x34\x2e\xdc\x00" + "\xf9\xba\xb9\x95\x69\x0e\xfd\x4c", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f" + "\x0b\x62\xe6\xce\x61\xb9\xd0\xcd", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + .psize = 73, + .digest = "\x6f\x63\x0f\xad\x67\xcd\xa0\xee" + "\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", + }, +}; + +/* + * HMAC-RIPEMD128 test vectors from RFC2286 + */ +#define HMAC_RMD128_TEST_VECTORS 7 + +static struct hash_testvec hmac_rmd128_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 16, + .plaintext = "Hi There", + .psize = 8, + .digest = "\xfb\xf6\x1f\x94\x92\xaa\x4b\xbf" + "\x81\xc1\x72\xe8\x4e\x07\x34\xdb", + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x87\x5f\x82\x88\x62\xb6\xb3\x34" + "\xb4\x27\xc5\x5f\x9f\x7f\xf0\x9b", + .np = 2, + .tap = { 14, 14 }, + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 16, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\x09\xf0\xb2\x84\x6d\x2f\x54\x3d" + "\xa3\x63\xcb\xec\x8d\x62\xa3\x8d", + }, { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + .ksize = 25, + .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + .psize = 50, + .digest = "\xbd\xbb\xd7\xcf\x03\xe4\x4b\x5a" + "\xa6\x0a\xf8\x15\xbe\x4d\x22\x94", + }, { + .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + .ksize = 16, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = "\xe7\x98\x08\xf2\x4b\x25\xfd\x03" + "\x1c\x15\x5f\x0d\x55\x1d\x9a\x3a", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = "\xdc\x73\x29\x28\xde\x98\x10\x4a" + "\x1f\x59\xd3\x73\xc1\x50\xac\xbb", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + .psize = 73, + .digest = "\x5c\x6b\xec\x96\x79\x3e\x16\xd4" + "\x06\x90\xc2\x37\x63\x5f\x30\xc5", + }, +}; + +/* + * HMAC-RIPEMD160 test vectors from RFC2286 + */ +#define HMAC_RMD160_TEST_VECTORS 7 + +static struct hash_testvec hmac_rmd160_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = "\x24\xcb\x4b\xd6\x7d\x20\xfc\x1a\x5d\x2e" + "\xd7\x73\x2d\xcc\x39\x37\x7f\x0a\x56\x68", + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\xdd\xa6\xc0\x21\x3a\x48\x5a\x9e\x24\xf4" + "\x74\x20\x64\xa7\xf0\x33\xb4\x3c\x40\x69", + .np = 2, + .tap = { 14, 14 }, + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 20, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\xb0\xb1\x05\x36\x0d\xe7\x59\x96\x0a\xb4" + "\xf3\x52\x98\xe1\x16\xe2\x95\xd8\xe7\xc1", + }, { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + .ksize = 25, + .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + .psize = 50, + .digest = "\xd5\xca\x86\x2f\x4d\x21\xd5\xe6\x10\xe1" + "\x8b\x4c\xf1\xbe\xb9\x7a\x43\x65\xec\xf4", + }, { + .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + .ksize = 20, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = "\x76\x19\x69\x39\x78\xf9\x1d\x90\x53\x9a" + "\xe7\x86\x50\x0f\xf3\xd8\xe0\x51\x8e\x39", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = "\x64\x66\xca\x07\xac\x5e\xac\x29\xe1\xbd" + "\x52\x3e\x5a\xda\x76\x05\xb7\x91\xfd\x8b", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + .psize = 73, + .digest = "\x69\xea\x60\x79\x8d\x71\x61\x6c\xce\x5f" + "\xd0\x87\x1e\x23\x75\x4c\xd7\x5d\x5a\x0a", + }, +}; + +/* + * HMAC-SHA1 test vectors from RFC2202 + */ +#define HMAC_SHA1_TEST_VECTORS 7 + +static struct hash_testvec hmac_sha1_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = "\xb6\x17\x31\x86\x55\x05\x72\x64" + "\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1" + "\x46\xbe", + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74" + "\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79", + .np = 2, + .tap = { 14, 14 } + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 20, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3" + "\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3", + }, { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + .ksize = 25, + .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + .psize = 50, + .digest = "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84" + "\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda", + }, { + .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + .ksize = 20, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2" + "\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70" + "\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + .psize = 73, + .digest = "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b" + "\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91", + }, +}; + + +/* + * SHA224 HMAC test vectors from RFC4231 + */ +#define HMAC_SHA224_TEST_VECTORS 4 + +static struct hash_testvec hmac_sha224_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + .ksize = 20, + /* ("Hi There") */ + .plaintext = "\x48\x69\x20\x54\x68\x65\x72\x65", + .psize = 8, + .digest = "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19" + "\x68\x32\x10\x7c\xd4\x9d\xf3\x3f" + "\x47\xb4\xb1\x16\x99\x12\xba\x4f" + "\x53\x68\x4b\x22", + }, { + .key = "Jefe", + .ksize = 4, + /* ("what do ya want for nothing?") */ + .plaintext = "\x77\x68\x61\x74\x20\x64\x6f\x20" + "\x79\x61\x20\x77\x61\x6e\x74\x20" + "\x66\x6f\x72\x20\x6e\x6f\x74\x68" + "\x69\x6e\x67\x3f", + .psize = 28, + .digest = "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf" + "\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" + "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00" + "\x8f\xd0\x5e\x44", + .np = 4, + .tap = { 7, 7, 7, 7 } + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 131, + /* ("Test Using Larger Than Block-Size Key - Hash Key First") */ + .plaintext = "\x54\x65\x73\x74\x20\x55\x73\x69" + "\x6e\x67\x20\x4c\x61\x72\x67\x65" + "\x72\x20\x54\x68\x61\x6e\x20\x42" + "\x6c\x6f\x63\x6b\x2d\x53\x69\x7a" + "\x65\x20\x4b\x65\x79\x20\x2d\x20" + "\x48\x61\x73\x68\x20\x4b\x65\x79" + "\x20\x46\x69\x72\x73\x74", + .psize = 54, + .digest = "\x95\xe9\xa0\xdb\x96\x20\x95\xad" + "\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2" + "\xd4\x99\xf1\x12\xf2\xd2\xb7\x27" + "\x3f\xa6\x87\x0e", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 131, + /* ("This is a test using a larger than block-size key and a") + (" larger than block-size data. The key needs to be") + (" hashed before being used by the HMAC algorithm.") */ + .plaintext = "\x54\x68\x69\x73\x20\x69\x73\x20" + "\x61\x20\x74\x65\x73\x74\x20\x75" + "\x73\x69\x6e\x67\x20\x61\x20\x6c" + "\x61\x72\x67\x65\x72\x20\x74\x68" + "\x61\x6e\x20\x62\x6c\x6f\x63\x6b" + "\x2d\x73\x69\x7a\x65\x20\x6b\x65" + "\x79\x20\x61\x6e\x64\x20\x61\x20" + "\x6c\x61\x72\x67\x65\x72\x20\x74" + "\x68\x61\x6e\x20\x62\x6c\x6f\x63" + "\x6b\x2d\x73\x69\x7a\x65\x20\x64" + "\x61\x74\x61\x2e\x20\x54\x68\x65" + "\x20\x6b\x65\x79\x20\x6e\x65\x65" + "\x64\x73\x20\x74\x6f\x20\x62\x65" + "\x20\x68\x61\x73\x68\x65\x64\x20" + "\x62\x65\x66\x6f\x72\x65\x20\x62" + "\x65\x69\x6e\x67\x20\x75\x73\x65" + "\x64\x20\x62\x79\x20\x74\x68\x65" + "\x20\x48\x4d\x41\x43\x20\x61\x6c" + "\x67\x6f\x72\x69\x74\x68\x6d\x2e", + .psize = 152, + .digest = "\x3a\x85\x41\x66\xac\x5d\x9f\x02" + "\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd" + "\x94\x67\x70\xdb\x9c\x2b\x95\xc9" + "\xf6\xf5\x65\xd1", + }, +}; + +/* + * HMAC-SHA256 test vectors from + * draft-ietf-ipsec-ciph-sha-256-01.txt + */ +#define HMAC_SHA256_TEST_VECTORS 10 + +static struct hash_testvec hmac_sha256_tv_template[] = { + { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", + .ksize = 32, + .plaintext = "abc", + .psize = 3, + .digest = "\xa2\x1b\x1f\x5d\x4c\xf4\xf7\x3a" + "\x4d\xd9\x39\x75\x0f\x7a\x06\x6a" + "\x7f\x98\xcc\x13\x1c\xb1\x6a\x66" + "\x92\x75\x90\x21\xcf\xab\x81\x81", + }, { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", + .ksize = 32, + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 56, + .digest = "\x10\x4f\xdc\x12\x57\x32\x8f\x08" + "\x18\x4b\xa7\x31\x31\xc5\x3c\xae" + "\xe6\x98\xe3\x61\x19\x42\x11\x49" + "\xea\x8c\x71\x24\x56\x69\x7d\x30", + }, { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20", + .ksize = 32, + .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .psize = 112, + .digest = "\x47\x03\x05\xfc\x7e\x40\xfe\x34" + "\xd3\xee\xb3\xe7\x73\xd9\x5a\xab" + "\x73\xac\xf0\xfd\x06\x04\x47\xa5" + "\xeb\x45\x95\xbf\x33\xa9\xd1\xa3", + }, { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b", + .ksize = 32, + .plaintext = "Hi There", + .psize = 8, + .digest = "\x19\x8a\x60\x7e\xb4\x4b\xfb\xc6" + "\x99\x03\xa0\xf1\xcf\x2b\xbd\xc5" + "\xba\x0a\xa3\xf3\xd9\xae\x3c\x1c" + "\x7a\x3b\x16\x96\xa0\xb6\x8c\xf7", + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e" + "\x6a\x04\x24\x26\x08\x95\x75\xc7" + "\x5a\x00\x3f\x08\x9d\x27\x39\x83" + "\x9d\xec\x58\xb9\x64\xec\x38\x43", + .np = 2, + .tap = { 14, 14 } + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + .ksize = 32, + .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + .psize = 50, + .digest = "\xcd\xcb\x12\x20\xd1\xec\xcc\xea" + "\x91\xe5\x3a\xba\x30\x92\xf9\x62" + "\xe5\x49\xfe\x6c\xe9\xed\x7f\xdc" + "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0", + }, { + .key = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25", + .ksize = 37, + .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + .psize = 50, + .digest = "\xd4\x63\x3c\x17\xf6\xfb\x8d\x74" + "\x4c\x66\xde\xe0\xf8\xf0\x74\x55" + "\x6e\xc4\xaf\x55\xef\x07\x99\x85" + "\x41\x46\x8e\xb4\x9b\xd2\xe9\x17", + }, { + .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c", + .ksize = 32, + .plaintext = "Test With Truncation", + .psize = 20, + .digest = "\x75\x46\xaf\x01\x84\x1f\xc0\x9b" + "\x1a\xb9\xc3\x74\x9a\x5f\x1c\x17" + "\xd4\xf5\x89\x66\x8a\x58\x7b\x27" + "\x00\xa9\xc9\x7c\x11\x93\xcf\x42", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First", + .psize = 54, + .digest = "\x69\x53\x02\x5e\xd9\x6f\x0c\x09" + "\xf8\x0a\x96\xf7\x8e\x65\x38\xdb" + "\xe2\xe7\xb8\x20\xe3\xdd\x97\x0e" + "\x7d\xdd\x39\x09\x1b\x32\x35\x2f", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa", + .ksize = 80, + .plaintext = "Test Using Larger Than Block-Size Key and Larger Than " + "One Block-Size Data", + .psize = 73, + .digest = "\x63\x55\xac\x22\xe8\x90\xd0\xa3" + "\xc8\x48\x1a\x5c\xa4\x82\x5b\xc8" + "\x84\xd3\xe7\xa1\xff\x98\xa2\xfc" + "\x2a\xc7\xd8\xe0\x64\xc3\xb2\xe6", + }, +}; + +#define XCBC_AES_TEST_VECTORS 6 + +static struct hash_testvec aes_xcbc128_tv_template[] = { + { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .plaintext = zeroed_string, + .digest = "\x75\xf0\x25\x1d\x52\x8a\xc0\x1c" + "\x45\x73\xdf\xd5\x84\xd7\x9f\x29", + .psize = 0, + .ksize = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .plaintext = "\x00\x01\x02", + .digest = "\x5b\x37\x65\x80\xae\x2f\x19\xaf" + "\xe7\x21\x9c\xee\xf1\x72\x75\x6f", + .psize = 3, + .ksize = 16, + } , { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .digest = "\xd2\xa2\x46\xfa\x34\x9b\x68\xa7" + "\x99\x98\xa4\x39\x4f\xf7\xa2\x63", + .psize = 16, + .ksize = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13", + .digest = "\x47\xf5\x1b\x45\x64\x96\x62\x15" + "\xb8\x98\x5c\x63\x05\x5e\xd3\x08", + .tap = { 10, 10 }, + .psize = 20, + .np = 2, + .ksize = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .digest = "\xf5\x4f\x0e\xc8\xd2\xb9\xf3\xd3" + "\x68\x07\x73\x4b\xd5\x28\x3f\xd4", + .psize = 32, + .ksize = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21", + .digest = "\xbe\xcb\xb3\xbc\xcd\xb5\x18\xa3" + "\x06\x77\xd5\x48\x1f\xb6\xb4\xd8", + .tap = { 17, 17 }, + .psize = 34, + .np = 2, + .ksize = 16, + } +}; + +/* + * SHA384 HMAC test vectors from RFC4231 + */ + +#define HMAC_SHA384_TEST_VECTORS 4 + +static struct hash_testvec hmac_sha384_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = "\xaf\xd0\x39\x44\xd8\x48\x95\x62" + "\x6b\x08\x25\xf4\xab\x46\x90\x7f" + "\x15\xf9\xda\xdb\xe4\x10\x1e\xc6" + "\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c" + "\xfa\xea\x9e\xa9\x07\x6e\xde\x7f" + "\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6", + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\xaf\x45\xd2\xe3\x76\x48\x40\x31" + "\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" + "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47" + "\xe4\x2e\xc3\x73\x63\x22\x44\x5e" + "\x8e\x22\x40\xca\x5e\x69\xe2\xc7" + "\x8b\x32\x39\xec\xfa\xb2\x16\x49", + .np = 4, + .tap = { 7, 7, 7, 7 } + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 131, + .plaintext = "Test Using Larger Than Block-Siz" + "e Key - Hash Key First", + .psize = 54, + .digest = "\x4e\xce\x08\x44\x85\x81\x3e\x90" + "\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4" + "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f" + "\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6" + "\x0c\x2e\xf6\xab\x40\x30\xfe\x82" + "\x96\x24\x8d\xf1\x63\xf4\x49\x52", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 131, + .plaintext = "This is a test u" + "sing a larger th" + "an block-size ke" + "y and a larger t" + "han block-size d" + "ata. The key nee" + "ds to be hashed " + "before being use" + "d by the HMAC al" + "gorithm.", + .psize = 152, + .digest = "\x66\x17\x17\x8e\x94\x1f\x02\x0d" + "\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c" + "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a" + "\xdc\xce\xbb\x82\x46\x1e\x99\xc5" + "\xa6\x78\xcc\x31\xe7\x99\x17\x6d" + "\x38\x60\xe6\x11\x0c\x46\x52\x3e", + }, +}; + +/* + * SHA512 HMAC test vectors from RFC4231 + */ + +#define HMAC_SHA512_TEST_VECTORS 4 + +static struct hash_testvec hmac_sha512_tv_template[] = { + { + .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + .ksize = 20, + .plaintext = "Hi There", + .psize = 8, + .digest = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d" + "\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0" + "\x23\x79\xf4\xe2\xce\x4e\xc2\x78" + "\x7a\xd0\xb3\x05\x45\xe1\x7c\xde" + "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02" + "\x03\x8b\x27\x4e\xae\xa3\xf4\xe4" + "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70" + "\x2e\x69\x6c\x20\x3a\x12\x68\x54", + }, { + .key = "Jefe", + .ksize = 4, + .plaintext = "what do ya want for nothing?", + .psize = 28, + .digest = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2" + "\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" + "\x87\xbd\x64\x22\x2e\x83\x1f\xd6" + "\x10\x27\x0c\xd7\xea\x25\x05\x54" + "\x97\x58\xbf\x75\xc0\x5a\x99\x4a" + "\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" + "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b" + "\x63\x6e\x07\x0a\x38\xbc\xe7\x37", + .np = 4, + .tap = { 7, 7, 7, 7 } + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 131, + .plaintext = "Test Using Large" + "r Than Block-Siz" + "e Key - Hash Key" + " First", + .psize = 54, + .digest = "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb" + "\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4" + "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1" + "\x12\x1b\x01\x37\x83\xf8\xf3\x52" + "\x6b\x56\xd0\x37\xe0\x5f\x25\x98" + "\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52" + "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec" + "\x8b\x91\x5a\x98\x5d\x78\x65\x98", + }, { + .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + .ksize = 131, + .plaintext = + "This is a test u" + "sing a larger th" + "an block-size ke" + "y and a larger t" + "han block-size d" + "ata. The key nee" + "ds to be hashed " + "before being use" + "d by the HMAC al" + "gorithm.", + .psize = 152, + .digest = "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba" + "\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd" + "\xde\xbd\x71\xf8\x86\x72\x89\x86" + "\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" + "\xb6\x02\x2c\xac\x3c\x49\x82\xb1" + "\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" + "\x13\x46\x76\xfb\x6d\xe0\x44\x60" + "\x65\xc9\x74\x40\xfa\x8c\x6a\x58", + }, +}; + +/* + * DES test vectors. + */ +#define DES_ENC_TEST_VECTORS 10 +#define DES_DEC_TEST_VECTORS 4 +#define DES_CBC_ENC_TEST_VECTORS 5 +#define DES_CBC_DEC_TEST_VECTORS 4 +#define DES3_EDE_ENC_TEST_VECTORS 3 +#define DES3_EDE_DEC_TEST_VECTORS 3 +#define DES3_EDE_CBC_ENC_TEST_VECTORS 1 +#define DES3_EDE_CBC_DEC_TEST_VECTORS 1 + +static struct cipher_testvec des_enc_tv_template[] = { + { /* From Applied Cryptography */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7", + .ilen = 8, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", + .rlen = 8, + }, { /* Same key, different plaintext block */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x22\x33\x44\x55\x66\x77\x88\x99", + .ilen = 8, + .result = "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", + .rlen = 8, + }, { /* Sbox test from NBS */ + .key = "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57", + .klen = 8, + .input = "\x01\xa1\xd6\xd0\x39\x77\x67\x42", + .ilen = 8, + .result = "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", + .rlen = 8, + }, { /* Three blocks */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xca\xfe\xba\xbe\xfe\xed\xbe\xef", + .ilen = 24, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" + "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b" + "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90", + .rlen = 24, + }, { /* Weak key */ + .fail = 1, + .wk = 1, + .key = "\x01\x01\x01\x01\x01\x01\x01\x01", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7", + .ilen = 8, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", + .rlen = 8, + }, { /* Two blocks -- for testing encryption across pages */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" + "\x22\x33\x44\x55\x66\x77\x88\x99", + .ilen = 16, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" + "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", + .rlen = 16, + .np = 2, + .tap = { 8, 8 } + }, { /* Four blocks -- for testing encryption with chunking */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xca\xfe\xba\xbe\xfe\xed\xbe\xef" + "\x22\x33\x44\x55\x66\x77\x88\x99", + .ilen = 32, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" + "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b" + "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90" + "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", + .rlen = 32, + .np = 3, + .tap = { 14, 10, 8 } + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" + "\x22\x33\x44\x55\x66\x77\x88\x99" + "\xca\xfe\xba\xbe\xfe\xed\xbe\xef", + .ilen = 24, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" + "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b" + "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90", + .rlen = 24, + .np = 4, + .tap = { 2, 1, 3, 18 } + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7" + "\x22\x33\x44\x55\x66\x77\x88\x99", + .ilen = 16, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" + "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b", + .rlen = 16, + .np = 5, + .tap = { 2, 2, 2, 2, 8 } + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7", + .ilen = 8, + .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", + .rlen = 8, + .np = 8, + .tap = { 1, 1, 1, 1, 1, 1, 1, 1 } + }, +}; + +static struct cipher_testvec des_dec_tv_template[] = { + { /* From Applied Cryptography */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d", + .ilen = 8, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7", + .rlen = 8, + }, { /* Sbox test from NBS */ + .key = "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57", + .klen = 8, + .input = "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", + .ilen = 8, + .result = "\x01\xa1\xd6\xd0\x39\x77\x67\x42", + .rlen = 8, + }, { /* Two blocks, for chunking test */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" + "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", + .ilen = 16, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7" + "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5", + .rlen = 16, + .np = 2, + .tap = { 8, 8 } + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d" + "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b", + .ilen = 16, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7" + "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5", + .rlen = 16, + .np = 3, + .tap = { 3, 12, 1 } + }, +}; + +static struct cipher_testvec des_cbc_enc_tv_template[] = { + { /* From OpenSSL */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .input = "\x37\x36\x35\x34\x33\x32\x31\x20" + "\x4e\x6f\x77\x20\x69\x73\x20\x74" + "\x68\x65\x20\x74\x69\x6d\x65\x20", + .ilen = 24, + .result = "\xcc\xd1\x73\xff\xab\x20\x39\xf4" + "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb" + "\x46\x8e\x91\x15\x78\x88\xba\x68", + .rlen = 24, + }, { /* FIPS Pub 81 */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\x12\x34\x56\x78\x90\xab\xcd\xef", + .input = "\x4e\x6f\x77\x20\x69\x73\x20\x74", + .ilen = 8, + .result = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", + .input = "\x68\x65\x20\x74\x69\x6d\x65\x20", + .ilen = 8, + .result = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", + .input = "\x66\x6f\x72\x20\x61\x6c\x6c\x20", + .ilen = 8, + .result = "\x68\x37\x88\x49\x9a\x7c\x05\xf6", + .rlen = 8, + }, { /* Copy of openssl vector for chunk testing */ + /* From OpenSSL */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .input = "\x37\x36\x35\x34\x33\x32\x31\x20" + "\x4e\x6f\x77\x20\x69\x73\x20\x74" + "\x68\x65\x20\x74\x69\x6d\x65\x20", + .ilen = 24, + .result = "\xcc\xd1\x73\xff\xab\x20\x39\xf4" + "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb" + "\x46\x8e\x91\x15\x78\x88\xba\x68", + .rlen = 24, + .np = 2, + .tap = { 13, 11 } + }, +}; + +static struct cipher_testvec des_cbc_dec_tv_template[] = { + { /* FIPS Pub 81 */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\x12\x34\x56\x78\x90\xab\xcd\xef", + .input = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", + .ilen = 8, + .result = "\x4e\x6f\x77\x20\x69\x73\x20\x74", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c", + .input = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", + .ilen = 8, + .result = "\x68\x65\x20\x74\x69\x6d\x65\x20", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", + .input = "\x68\x37\x88\x49\x9a\x7c\x05\xf6", + .ilen = 8, + .result = "\x66\x6f\x72\x20\x61\x6c\x6c\x20", + .rlen = 8, + }, { /* Copy of above, for chunk testing */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f", + .input = "\x68\x37\x88\x49\x9a\x7c\x05\xf6", + .ilen = 8, + .result = "\x66\x6f\x72\x20\x61\x6c\x6c\x20", + .rlen = 8, + .np = 2, + .tap = { 4, 4 } + }, +}; + +static struct cipher_testvec des3_ede_enc_tv_template[] = { + { /* These are from openssl */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\x55\x55\x55\x55\x55\x55\x55\x55" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 24, + .input = "\x73\x6f\x6d\x65\x64\x61\x74\x61", + .ilen = 8, + .result = "\x18\xd7\x48\xe5\x63\x62\x05\x72", + .rlen = 8, + }, { + .key = "\x03\x52\x02\x07\x67\x20\x82\x17" + "\x86\x02\x87\x66\x59\x08\x21\x98" + "\x64\x05\x6a\xbd\xfe\xa9\x34\x57", + .klen = 24, + .input = "\x73\x71\x75\x69\x67\x67\x6c\x65", + .ilen = 8, + .result = "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30", + .rlen = 8, + }, { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01" + "\x19\x07\x92\x10\x98\x1a\x01\x01", + .klen = 24, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 8, + .result = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b", + .rlen = 8, + }, +}; + +static struct cipher_testvec des3_ede_dec_tv_template[] = { + { /* These are from openssl */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\x55\x55\x55\x55\x55\x55\x55\x55" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 24, + .input = "\x18\xd7\x48\xe5\x63\x62\x05\x72", + .ilen = 8, + .result = "\x73\x6f\x6d\x65\x64\x61\x74\x61", + .rlen = 8, + }, { + .key = "\x03\x52\x02\x07\x67\x20\x82\x17" + "\x86\x02\x87\x66\x59\x08\x21\x98" + "\x64\x05\x6a\xbd\xfe\xa9\x34\x57", + .klen = 24, + .input = "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30", + .ilen = 8, + .result = "\x73\x71\x75\x69\x67\x67\x6c\x65", + .rlen = 8, + }, { + .key = "\x10\x46\x10\x34\x89\x98\x80\x20" + "\x91\x07\xd0\x15\x89\x19\x01\x01" + "\x19\x07\x92\x10\x98\x1a\x01\x01", + .klen = 24, + .input = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b", + .ilen = 8, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00", + .rlen = 8, + }, +}; + +static struct cipher_testvec des3_ede_cbc_enc_tv_template[] = { + { /* Generated from openssl */ + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0" + "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8", + .klen = 24, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .input = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .ilen = 128, + .result = "\x0e\x2d\xb6\x97\x3c\x56\x33\xf4" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\x74\xb3\x49\x05\xc5\x1c\xd0\xed" + "\x12\x56\x5c\x53\x96\xb6\x00\x7d" + "\x90\x48\xfc\xf5\x8d\x29\x39\xcc" + "\x8a\xd5\x35\x18\x36\x23\x4e\xd7" + "\x76\xd1\xda\x0c\x94\x67\xbb\x04" + "\x8b\xf2\x03\x6c\xa8\xcf\xb6\xea" + "\x22\x64\x47\xaa\x8f\x75\x13\xbf" + "\x9f\xc2\xc3\xf0\xc9\x56\xc5\x7a" + "\x71\x63\x2e\x89\x7b\x1e\x12\xca" + "\xe2\x5f\xaf\xd8\xa4\xf8\xc9\x7a" + "\xd6\xf9\x21\x31\x62\x44\x45\xa6" + "\xd6\xbc\x5a\xd3\x2d\x54\x43\xcc" + "\x9d\xde\xa5\x70\xe9\x42\x45\x8a" + "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .rlen = 128, + }, +}; + +static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = { + { /* Generated from openssl */ + .key = "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24" + "\x44\x4D\x99\x5A\x12\xD6\x40\xC0" + "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8", + .klen = 24, + .iv = "\x7D\x33\x88\x93\x0F\x93\xB2\x42", + .input = "\x0e\x2d\xb6\x97\x3c\x56\x33\xf4" + "\x67\x17\x21\xc7\x6e\x8a\xd5\x49" + "\x74\xb3\x49\x05\xc5\x1c\xd0\xed" + "\x12\x56\x5c\x53\x96\xb6\x00\x7d" + "\x90\x48\xfc\xf5\x8d\x29\x39\xcc" + "\x8a\xd5\x35\x18\x36\x23\x4e\xd7" + "\x76\xd1\xda\x0c\x94\x67\xbb\x04" + "\x8b\xf2\x03\x6c\xa8\xcf\xb6\xea" + "\x22\x64\x47\xaa\x8f\x75\x13\xbf" + "\x9f\xc2\xc3\xf0\xc9\x56\xc5\x7a" + "\x71\x63\x2e\x89\x7b\x1e\x12\xca" + "\xe2\x5f\xaf\xd8\xa4\xf8\xc9\x7a" + "\xd6\xf9\x21\x31\x62\x44\x45\xa6" + "\xd6\xbc\x5a\xd3\x2d\x54\x43\xcc" + "\x9d\xde\xa5\x70\xe9\x42\x45\x8a" + "\x6b\xfa\xb1\x91\x13\xb0\xd9\x19", + .ilen = 128, + .result = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e" + "\x53\x20\x63\x65\x65\x72\x73\x74" + "\x54\x20\x6f\x6f\x4d\x20\x6e\x61" + "\x20\x79\x65\x53\x72\x63\x74\x65" + "\x20\x73\x6f\x54\x20\x6f\x61\x4d" + "\x79\x6e\x53\x20\x63\x65\x65\x72" + "\x73\x74\x54\x20\x6f\x6f\x4d\x20" + "\x6e\x61\x20\x79\x65\x53\x72\x63" + "\x74\x65\x20\x73\x6f\x54\x20\x6f" + "\x61\x4d\x79\x6e\x53\x20\x63\x65" + "\x65\x72\x73\x74\x54\x20\x6f\x6f" + "\x4d\x20\x6e\x61\x20\x79\x65\x53" + "\x72\x63\x74\x65\x20\x73\x6f\x54" + "\x20\x6f\x61\x4d\x79\x6e\x53\x20" + "\x63\x65\x65\x72\x73\x74\x54\x20" + "\x6f\x6f\x4d\x20\x6e\x61\x0a\x79", + .rlen = 128, + }, +}; + +/* + * Blowfish test vectors. + */ +#define BF_ENC_TEST_VECTORS 6 +#define BF_DEC_TEST_VECTORS 6 +#define BF_CBC_ENC_TEST_VECTORS 1 +#define BF_CBC_DEC_TEST_VECTORS 1 + +static struct cipher_testvec bf_enc_tv_template[] = { + { /* DES test vectors from OpenSSL */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 8, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 8, + .result = "\x4e\xf9\x97\x45\x61\x98\xdd\x78", + .rlen = 8, + }, { + .key = "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .ilen = 8, + .result = "\xa7\x90\x79\x51\x08\xea\x3c\xae", + .rlen = 8, + }, { + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .klen = 8, + .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .ilen = 8, + .result = "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82", + .rlen = 8, + }, { /* Vary the keylength... */ + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" + "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f", + .klen = 16, + .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .ilen = 8, + .result = "\x93\x14\x28\x87\xee\x3b\xe1\x5c", + .rlen = 8, + }, { + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" + "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" + "\x00\x11\x22\x33\x44", + .klen = 21, + .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .ilen = 8, + .result = "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f", + .rlen = 8, + }, { /* Generated with bf488 */ + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" + "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x04\x68\x91\x04\xc2\xfd\x3b\x2f" + "\x58\x40\x23\x64\x1a\xba\x61\x76" + "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e" + "\xff\xff\xff\xff\xff\xff\xff\xff", + .klen = 56, + .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .ilen = 8, + .result = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53", + .rlen = 8, + }, +}; + +static struct cipher_testvec bf_dec_tv_template[] = { + { /* DES test vectors from OpenSSL */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 8, + .input = "\x4e\xf9\x97\x45\x61\x98\xdd\x78", + .ilen = 8, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00", + .rlen = 8, + }, { + .key = "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e", + .klen = 8, + .input = "\xa7\x90\x79\x51\x08\xea\x3c\xae", + .ilen = 8, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .rlen = 8, + }, { + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .klen = 8, + .input = "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82", + .ilen = 8, + .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .rlen = 8, + }, { /* Vary the keylength... */ + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" + "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f", + .klen = 16, + .input = "\x93\x14\x28\x87\xee\x3b\xe1\x5c", + .ilen = 8, + .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .rlen = 8, + }, { + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" + "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" + "\x00\x11\x22\x33\x44", + .klen = 21, + .input = "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f", + .ilen = 8, + .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .rlen = 8, + }, { /* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */ + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87" + "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x04\x68\x91\x04\xc2\xfd\x3b\x2f" + "\x58\x40\x23\x64\x1a\xba\x61\x76" + "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e" + "\xff\xff\xff\xff\xff\xff\xff\xff", + .klen = 56, + .input = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53", + .ilen = 8, + .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .rlen = 8, + }, +}; + +static struct cipher_testvec bf_cbc_enc_tv_template[] = { + { /* From OpenSSL */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .klen = 16, + .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .input = "\x37\x36\x35\x34\x33\x32\x31\x20" + "\x4e\x6f\x77\x20\x69\x73\x20\x74" + "\x68\x65\x20\x74\x69\x6d\x65\x20" + "\x66\x6f\x72\x20\x00\x00\x00\x00", + .ilen = 32, + .result = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6" + "\x05\xb1\x56\xe2\x74\x03\x97\x93" + "\x58\xde\xb9\xe7\x15\x46\x16\xd9" + "\x59\xf1\x65\x2b\xd5\xff\x92\xcc", + .rlen = 32, + }, +}; + +static struct cipher_testvec bf_cbc_dec_tv_template[] = { + { /* From OpenSSL */ + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .klen = 16, + .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .input = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6" + "\x05\xb1\x56\xe2\x74\x03\x97\x93" + "\x58\xde\xb9\xe7\x15\x46\x16\xd9" + "\x59\xf1\x65\x2b\xd5\xff\x92\xcc", + .ilen = 32, + .result = "\x37\x36\x35\x34\x33\x32\x31\x20" + "\x4e\x6f\x77\x20\x69\x73\x20\x74" + "\x68\x65\x20\x74\x69\x6d\x65\x20" + "\x66\x6f\x72\x20\x00\x00\x00\x00", + .rlen = 32, + }, +}; + +/* + * Twofish test vectors. + */ +#define TF_ENC_TEST_VECTORS 3 +#define TF_DEC_TEST_VECTORS 3 +#define TF_CBC_ENC_TEST_VECTORS 4 +#define TF_CBC_DEC_TEST_VECTORS 4 + +static struct cipher_testvec tf_enc_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = zeroed_string, + .ilen = 16, + .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77", + .klen = 24, + .input = zeroed_string, + .ilen = 16, + .result = "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf" + "\x50\x1f\x13\xb8\x92\xbd\x22\x48", + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .klen = 32, + .input = zeroed_string, + .ilen = 16, + .result = "\x37\x52\x7b\xe0\x05\x23\x34\xb8" + "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20", + .rlen = 16, + }, +}; + +static struct cipher_testvec tf_dec_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77", + .klen = 24, + .input = "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf" + "\x50\x1f\x13\xb8\x92\xbd\x22\x48", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .klen = 32, + .input = "\x37\x52\x7b\xe0\x05\x23\x34\xb8" + "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, +}; + +static struct cipher_testvec tf_cbc_enc_tv_template[] = { + { /* Generated with Nettle */ + .key = zeroed_string, + .klen = 16, + .iv = zeroed_string, + .input = zeroed_string, + .ilen = 16, + .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 16, + .iv = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", + .input = zeroed_string, + .ilen = 16, + .result = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" + "\x86\xcb\x08\x6b\x78\x9f\x54\x19", + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 16, + .iv = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" + "\x86\xcb\x08\x6b\x78\x9f\x54\x19", + .input = zeroed_string, + .ilen = 16, + .result = "\x05\xef\x8c\x61\xa8\x11\x58\x26" + "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 16, + .iv = zeroed_string, + .input = zeroed_string, + .ilen = 48, + .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a" + "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" + "\x86\xcb\x08\x6b\x78\x9f\x54\x19" + "\x05\xef\x8c\x61\xa8\x11\x58\x26" + "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", + .rlen = 48, + }, +}; + +static struct cipher_testvec tf_cbc_dec_tv_template[] = { + { /* Reverse of the first four above */ + .key = zeroed_string, + .klen = 16, + .iv = zeroed_string, + .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 16, + .iv = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a", + .input = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" + "\x86\xcb\x08\x6b\x78\x9f\x54\x19", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 16, + .iv = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" + "\x86\xcb\x08\x6b\x78\x9f\x54\x19", + .input = "\x05\xef\x8c\x61\xa8\x11\x58\x26" + "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 16, + .iv = zeroed_string, + .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32" + "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a" + "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e" + "\x86\xcb\x08\x6b\x78\x9f\x54\x19" + "\x05\xef\x8c\x61\xa8\x11\x58\x26" + "\x34\xba\x5c\xb7\x10\x6a\xa6\x41", + .ilen = 48, + .result = zeroed_string, + .rlen = 48, + }, +}; + +/* + * Serpent test vectors. These are backwards because Serpent writes + * octet sequences in right-to-left mode. + */ +#define SERPENT_ENC_TEST_VECTORS 4 +#define SERPENT_DEC_TEST_VECTORS 4 + +#define TNEPRES_ENC_TEST_VECTORS 4 +#define TNEPRES_DEC_TEST_VECTORS 4 + +static struct cipher_testvec serpent_enc_tv_template[] = { + { + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ilen = 16, + .result = "\x12\x07\xfc\xce\x9b\xd0\xd6\x47" + "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ilen = 16, + .result = "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c" + "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ilen = 16, + .result = "\xde\x26\x9f\xf8\x33\xe4\x32\xb8" + "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c", + .rlen = 16, + }, { + .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", + .klen = 16, + .input = zeroed_string, + .ilen = 16, + .result = "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c" + "\x05\x34\x5a\x9d\xad\xbf\xaf\x49", + .rlen = 16, + }, +}; + +static struct cipher_testvec tnepres_enc_tv_template[] = { + { /* KeySize=128, PT=0, I=1 */ + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .key = "\x80\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 16, + .ilen = 16, + .result = "\x49\xaf\xbf\xad\x9d\x5a\x34\x05" + "\x2c\xd8\xff\xa5\x98\x6b\xd2\xdd", + .rlen = 16, + }, { /* KeySize=192, PT=0, I=1 */ + .key = "\x80\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 24, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 16, + .result = "\xe7\x8e\x54\x02\xc7\x19\x55\x68" + "\xac\x36\x78\xf7\xa3\xf6\x0c\x66", + .rlen = 16, + }, { /* KeySize=256, PT=0, I=1 */ + .key = "\x80\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 32, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 16, + .result = "\xab\xed\x96\xe7\x66\xbf\x28\xcb" + "\xc0\xeb\xd2\x1a\x82\xef\x08\x19", + .rlen = 16, + }, { /* KeySize=256, I=257 */ + .key = "\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18" + "\x17\x16\x15\x14\x13\x12\x11\x10" + "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08" + "\x07\x06\x05\x04\x03\x02\x01\x00", + .klen = 32, + .input = "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08" + "\x07\x06\x05\x04\x03\x02\x01\x00", + .ilen = 16, + .result = "\x5c\xe7\x1c\x70\xd2\x88\x2e\x5b" + "\xb8\x32\xe4\x33\xf8\x9f\x26\xde", + .rlen = 16, + }, +}; + + +static struct cipher_testvec serpent_dec_tv_template[] = { + { + .input = "\x12\x07\xfc\xce\x9b\xd0\xd6\x47" + "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2", + .ilen = 16, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .input = "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c" + "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d", + .ilen = 16, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .input = "\xde\x26\x9f\xf8\x33\xe4\x32\xb8" + "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c", + .ilen = 16, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .rlen = 16, + }, { + .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", + .klen = 16, + .input = "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c" + "\x05\x34\x5a\x9d\xad\xbf\xaf\x49", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, +}; + +static struct cipher_testvec tnepres_dec_tv_template[] = { + { + .input = "\x41\xcc\x6b\x31\x59\x31\x45\x97" + "\x6d\x6f\xbb\x38\x4b\x37\x21\x28", + .ilen = 16, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .input = "\xea\xf4\xd7\xfc\xd8\x01\x34\x47" + "\x81\x45\x0b\xfa\x0c\xd6\xad\x6e", + .ilen = 16, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .input = "\x64\xa9\x1a\x37\xed\x9f\xe7\x49" + "\xa8\x4e\x76\xd6\xf5\x0d\x78\xee", + .ilen = 16, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .rlen = 16, + }, { /* KeySize=128, I=121 */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", + .klen = 16, + .input = "\x3d\xda\xbf\xc0\x06\xda\xab\x06" + "\x46\x2a\xf4\xef\x81\x54\x4e\x26", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, +}; + + +/* Cast6 test vectors from RFC 2612 */ +#define CAST6_ENC_TEST_VECTORS 3 +#define CAST6_DEC_TEST_VECTORS 3 + +static struct cipher_testvec cast6_enc_tv_template[] = { + { + .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" + "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d", + .klen = 16, + .input = zeroed_string, + .ilen = 16, + .result = "\xc8\x42\xa0\x89\x72\xb4\x3d\x20" + "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b", + .rlen = 16, + }, { + .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" + "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" + "\xba\xc7\x7a\x77\x17\x94\x28\x63", + .klen = 24, + .input = zeroed_string, + .ilen = 16, + .result = "\x1b\x38\x6c\x02\x10\xdc\xad\xcb" + "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8", + .rlen = 16, + }, { + .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" + "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" + "\x8d\x7c\x47\xce\x26\x49\x08\x46" + "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04", + .klen = 32, + .input = zeroed_string, + .ilen = 16, + .result = "\x4f\x6a\x20\x38\x28\x68\x97\xb9" + "\xc9\x87\x01\x36\x55\x33\x17\xfa", + .rlen = 16, + }, +}; + +static struct cipher_testvec cast6_dec_tv_template[] = { + { + .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" + "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d", + .klen = 16, + .input = "\xc8\x42\xa0\x89\x72\xb4\x3d\x20" + "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" + "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" + "\xba\xc7\x7a\x77\x17\x94\x28\x63", + .klen = 24, + .input = "\x1b\x38\x6c\x02\x10\xdc\xad\xcb" + "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c" + "\xbe\xd0\xac\x83\x94\x0a\xc2\x98" + "\x8d\x7c\x47\xce\x26\x49\x08\x46" + "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04", + .klen = 32, + .input = "\x4f\x6a\x20\x38\x28\x68\x97\xb9" + "\xc9\x87\x01\x36\x55\x33\x17\xfa", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, +}; + + +/* + * AES test vectors. + */ +#define AES_ENC_TEST_VECTORS 3 +#define AES_DEC_TEST_VECTORS 3 +#define AES_CBC_ENC_TEST_VECTORS 4 +#define AES_CBC_DEC_TEST_VECTORS 4 +#define AES_LRW_ENC_TEST_VECTORS 8 +#define AES_LRW_DEC_TEST_VECTORS 8 +#define AES_XTS_ENC_TEST_VECTORS 4 +#define AES_XTS_DEC_TEST_VECTORS 4 +#define AES_CTR_ENC_TEST_VECTORS 7 +#define AES_CTR_DEC_TEST_VECTORS 6 +#define AES_GCM_ENC_TEST_VECTORS 9 +#define AES_GCM_DEC_TEST_VECTORS 8 +#define AES_CCM_ENC_TEST_VECTORS 7 +#define AES_CCM_DEC_TEST_VECTORS 7 + +static struct cipher_testvec aes_enc_tv_template[] = { + { /* From FIPS-197 */ + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .input = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ilen = 16, + .result = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" + "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17", + .klen = 24, + .input = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ilen = 16, + .result = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" + "\x6e\xaf\x70\xa0\xec\x0d\x71\x91", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .input = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .ilen = 16, + .result = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf" + "\xea\xfc\x49\x90\x4b\x49\x60\x89", + .rlen = 16, + }, +}; + +static struct cipher_testvec aes_dec_tv_template[] = { + { /* From FIPS-197 */ + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .input = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30" + "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a", + .ilen = 16, + .result = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17", + .klen = 24, + .input = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0" + "\x6e\xaf\x70\xa0\xec\x0d\x71\x91", + .ilen = 16, + .result = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .input = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf" + "\xea\xfc\x49\x90\x4b\x49\x60\x89", + .ilen = 16, + .result = "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .rlen = 16, + }, +}; + +static struct cipher_testvec aes_cbc_enc_tv_template[] = { + { /* From RFC 3602 */ + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .input = "Single block msg", + .ilen = 16, + .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .rlen = 16, + }, { + .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1", + .rlen = 32, + }, { /* From NIST SP800-38A */ + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .rlen = 64, + }, { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .ilen = 64, + .result = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .rlen = 64, + }, +}; + +static struct cipher_testvec aes_cbc_dec_tv_template[] = { + { /* From RFC 3602 */ + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .input = "\xe3\x53\x77\x9c\x10\x79\xae\xb8" + "\x27\x08\x94\x2d\xbe\x77\x18\x1a", + .ilen = 16, + .result = "Single block msg", + .rlen = 16, + }, { + .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .input = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a" + "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a" + "\x75\x86\x60\x2d\x25\x3c\xff\xf9" + "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1", + .ilen = 32, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .rlen = 32, + }, { /* From NIST SP800-38A */ + .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52" + "\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", + .klen = 24, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d" + "\x71\x78\x18\x3a\x9f\xa0\x71\xe8" + "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4" + "\xe5\xe7\x38\x76\x3f\x69\x14\x5a" + "\x57\x1b\x24\x20\x12\xfb\x7a\xe0" + "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0" + "\x08\xb0\xe2\x79\x88\x59\x88\x81" + "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", + .ilen = 64, + .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .rlen = 64, + }, { + .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe" + "\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7" + "\x2d\x98\x10\xa3\x09\x14\xdf\xf4", + .klen = 32, + .iv = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .input = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba" + "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6" + "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d" + "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d" + "\x39\xf2\x33\x69\xa9\xd9\xba\xcf" + "\xa5\x30\xe2\x63\x04\x23\x14\x61" + "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc" + "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", + .ilen = 64, + .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96" + "\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d\x8a\x57\x1e\x03\xac\x9c" + "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" + "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11" + "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" + "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17" + "\xad\x2b\x41\x7b\xe6\x6c\x37\x10", + .rlen = 64, + }, +}; + +static struct cipher_testvec aes_lrw_enc_tv_template[] = { + /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */ + { /* LRW-32-AES 1 */ + .key = "\x45\x62\xac\x25\xf8\x28\x17\x6d" + "\x4c\x26\x84\x14\xb5\x68\x01\x85" + "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03" + "\xee\x5a\x83\x0c\xcc\x09\x4c\x87", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .ilen = 16, + .result = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f" + "\xe9\x5d\x48\x92\x54\x63\x4e\xb8", + .rlen = 16, + }, { /* LRW-32-AES 2 */ + .key = "\x59\x70\x47\x14\xf5\x57\x47\x8c" + "\xd7\x79\xe8\x0f\x54\x88\x79\x44" + "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea" + "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x02", + .input = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .ilen = 16, + .result = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5" + "\x27\x4f\x07\x69\xb2\x60\xe1\x36", + .rlen = 16, + }, { /* LRW-32-AES 3 */ + .key = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50" + "\x30\xfe\x69\xe2\x37\x7f\x98\x47" + "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6" + "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x02\x00\x00\x00\x00", + .input = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .ilen = 16, + .result = "\x76\x32\x21\x83\xed\x8f\xf1\x82" + "\xf9\x59\x62\x03\x69\x0e\x5e\x01", + .rlen = 16, + }, { /* LRW-32-AES 4 */ + .key = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15" + "\x25\x83\xf7\x3c\x1f\x01\x28\x74" + "\xca\xc6\xbc\x35\x4d\x4a\x65\x54" + "\x90\xae\x61\xcf\x7b\xae\xbd\xcc" + "\xad\xe4\x94\xc5\x4a\x29\xae\x70", + .klen = 40, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .ilen = 16, + .result = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0" + "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41", + .rlen = 16, + }, { /* LRW-32-AES 5 */ + .key = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff" + "\xf8\x86\xce\xac\x93\xc5\xad\xc6" + "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd" + "\x52\x13\xb2\xb7\xf0\xff\x11\xd8" + "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f", + .klen = 40, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x02\x00\x00\x00\x00", + .input = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .ilen = 16, + .result = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65" + "\xc8\x60\x48\x02\x87\xe3\x34\x06", + .rlen = 16, + }, { /* LRW-32-AES 6 */ + .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" + "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" + "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" + "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" + "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" + "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", + .klen = 48, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .ilen = 16, + .result = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e" + "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b", + .rlen = 16, + }, { /* LRW-32-AES 7 */ + .key = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d" + "\xd4\x70\x98\x0b\xc7\x95\x84\xc8" + "\xb2\xfb\x64\xce\x60\x97\x87\x8d" + "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7" + "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4" + "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c", + .klen = 48, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x02\x00\x00\x00\x00", + .input = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .ilen = 16, + .result = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f" + "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5", + .rlen = 16, + }, { +/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */ + .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" + "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" + "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" + "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" + "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" + "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", + .klen = 48, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\x05\x11\xb7\x18\xab\xc6\x2d\xac" + "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c" + "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8" + "\x50\x38\x1f\x71\x49\xb6\x57\xd6" + "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90" + "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6" + "\xad\x1e\x9e\x20\x5f\x38\xbe\x04" + "\xda\x10\x8e\xed\xa2\xa4\x87\xab" + "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c" + "\xc9\xac\x42\x31\x95\x7c\xc9\x04" + "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6" + "\x15\xd7\x3f\x4f\x2f\x66\x69\x03" + "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65" + "\x4c\x96\x12\xed\x7c\x92\x03\x01" + "\x6f\xbc\x35\x93\xac\xf1\x27\xf1" + "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50" + "\x89\xa4\x8e\x66\x44\x85\xcc\xfd" + "\x33\x14\x70\xe3\x96\xb2\xc3\xd3" + "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5" + "\x2d\x64\x75\xdd\xb4\x54\xe6\x74" + "\x8c\xd3\x9d\x9e\x86\xab\x51\x53" + "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40" + "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5" + "\x76\x12\x73\x44\x1a\x56\xd7\x72" + "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda" + "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd" + "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60" + "\x1a\xe2\x70\x85\x58\xc2\x1b\x09" + "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9" + "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8" + "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8" + "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10" + "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1" + "\x90\x3e\x76\x4a\x74\xa4\x21\x2c" + "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e" + "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f" + "\x8d\x23\x31\x74\x84\xeb\x88\x6e" + "\xcc\xb9\xbc\x22\x83\x19\x07\x22" + "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78" + "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5" + "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41" + "\x3c\xce\x8f\x42\x60\x71\xa7\x75" + "\x08\x40\x65\x8a\x82\xbf\xf5\x43" + "\x71\x96\xa9\x4d\x44\x8a\x20\xbe" + "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65" + "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9" + "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4" + "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a" + "\x62\x73\x65\xfd\x46\x63\x25\x3d" + "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf" + "\x24\xf3\xb4\xac\x64\xba\xdf\x4b" + "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7" + "\xc5\x68\x77\x84\x32\x2b\xcc\x85" + "\x74\x96\xf0\x12\x77\x61\xb9\xeb" + "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8" + "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24" + "\xda\x39\x87\x45\xc0\x2b\xbb\x01" + "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce" + "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6" + "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32" + "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45" + "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6" + "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4" + "\x21\xc4\xc2\x75\x67\x89\x37\x0a", + .ilen = 512, + .result = "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b" + "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a" + "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23" + "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e" + "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c" + "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d" + "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3" + "\xe8\x58\x46\x97\x39\x51\x07\xde" + "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3" + "\x0e\x84\x23\x1d\x16\xd4\x1c\x59" + "\x9c\x1a\x02\x55\xab\x3a\x97\x1d" + "\xdf\xdd\xc7\x06\x51\xd7\x70\xae" + "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82" + "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68" + "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce" + "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98" + "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2" + "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f" + "\xea\x20\xe7\xcb\x65\x77\x3a\xdf" + "\xc8\x97\x67\x15\xc2\x2a\x27\xcc" + "\x18\x55\xa1\x24\x0b\x24\x24\xaf" + "\x5b\xec\x68\xb8\xc8\xf5\xba\x63" + "\xff\xed\x89\xce\xd5\x3d\x88\xf3" + "\x25\xef\x05\x7c\x3a\xef\xeb\xd8" + "\x7a\x32\x0d\xd1\x1e\x58\x59\x99" + "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c" + "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50" + "\x41\x30\x58\xc5\x62\x74\x52\x1d" + "\x45\x24\x6a\x42\x64\x4f\x97\x1c" + "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48" + "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1" + "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46" + "\xe4\x81\x84\x95\x36\x59\x7a\x6b" + "\xaa\xb3\x60\xad\xce\x9f\x9f\x28" + "\xe0\x01\x75\x22\xc4\x4e\xa9\x62" + "\x5c\x62\x0d\x00\xcb\x13\xe8\x43" + "\x72\xd4\x2d\x53\x46\xb5\xd1\x16" + "\x22\x18\xdf\x34\x33\xf5\xd6\x1c" + "\xb8\x79\x78\x97\x94\xff\x72\x13" + "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6" + "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4" + "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f" + "\x2d\x14\x8e\x24\x61\x2c\xe1\x17" + "\xcc\xce\x51\x0c\x19\x8a\x82\x30" + "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd" + "\xb7\xeb\xfa\xfd\x27\x51\xde\x85" + "\x1e\x86\x53\x11\x53\x94\x00\xee" + "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11" + "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62" + "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1" + "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a" + "\x9e\xfa\x31\x18\x45\x3c\x21\x33" + "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1" + "\x03\xad\x1b\x48\xd4\x67\x27\xf0" + "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7" + "\xdd\x2b\x01\x39\x04\x5a\x58\x7a" + "\xf7\x11\x90\xec\xbd\x51\x5c\x32" + "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6" + "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d" + "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4" + "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3" + "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29" + "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7" + "\x74\x3f\x7d\x58\x88\x75\xde\x3e", + .rlen = 512, + } +}; + +static struct cipher_testvec aes_lrw_dec_tv_template[] = { + /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */ + /* same as enc vectors with input and result reversed */ + { /* LRW-32-AES 1 */ + .key = "\x45\x62\xac\x25\xf8\x28\x17\x6d" + "\x4c\x26\x84\x14\xb5\x68\x01\x85" + "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03" + "\xee\x5a\x83\x0c\xcc\x09\x4c\x87", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f" + "\xe9\x5d\x48\x92\x54\x63\x4e\xb8", + .ilen = 16, + .result = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .rlen = 16, + }, { /* LRW-32-AES 2 */ + .key = "\x59\x70\x47\x14\xf5\x57\x47\x8c" + "\xd7\x79\xe8\x0f\x54\x88\x79\x44" + "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea" + "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x02", + .input = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5" + "\x27\x4f\x07\x69\xb2\x60\xe1\x36", + .ilen = 16, + .result = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .rlen = 16, + }, { /* LRW-32-AES 3 */ + .key = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50" + "\x30\xfe\x69\xe2\x37\x7f\x98\x47" + "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6" + "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x02\x00\x00\x00\x00", + .input = "\x76\x32\x21\x83\xed\x8f\xf1\x82" + "\xf9\x59\x62\x03\x69\x0e\x5e\x01", + .ilen = 16, + .result = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .rlen = 16, + }, { /* LRW-32-AES 4 */ + .key = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15" + "\x25\x83\xf7\x3c\x1f\x01\x28\x74" + "\xca\xc6\xbc\x35\x4d\x4a\x65\x54" + "\x90\xae\x61\xcf\x7b\xae\xbd\xcc" + "\xad\xe4\x94\xc5\x4a\x29\xae\x70", + .klen = 40, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0" + "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41", + .ilen = 16, + .result = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .rlen = 16, + }, { /* LRW-32-AES 5 */ + .key = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff" + "\xf8\x86\xce\xac\x93\xc5\xad\xc6" + "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd" + "\x52\x13\xb2\xb7\xf0\xff\x11\xd8" + "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f", + .klen = 40, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x02\x00\x00\x00\x00", + .input = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65" + "\xc8\x60\x48\x02\x87\xe3\x34\x06", + .ilen = 16, + .result = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .rlen = 16, + }, { /* LRW-32-AES 6 */ + .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" + "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" + "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" + "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" + "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" + "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", + .klen = 48, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e" + "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b", + .ilen = 16, + .result = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .rlen = 16, + }, { /* LRW-32-AES 7 */ + .key = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d" + "\xd4\x70\x98\x0b\xc7\x95\x84\xc8" + "\xb2\xfb\x64\xce\x60\x97\x87\x8d" + "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7" + "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4" + "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c", + .klen = 48, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x02\x00\x00\x00\x00", + .input = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f" + "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5", + .ilen = 16, + .result = "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x41\x42\x43\x44\x45\x46", + .rlen = 16, + }, { +/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */ + .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c" + "\x23\x84\xcb\x1c\x77\xd6\x19\x5d" + "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21" + "\xa7\x9c\x21\xf8\xcb\x90\x02\x89" + "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1" + "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e", + .klen = 48, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .input = "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b" + "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a" + "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23" + "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e" + "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c" + "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d" + "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3" + "\xe8\x58\x46\x97\x39\x51\x07\xde" + "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3" + "\x0e\x84\x23\x1d\x16\xd4\x1c\x59" + "\x9c\x1a\x02\x55\xab\x3a\x97\x1d" + "\xdf\xdd\xc7\x06\x51\xd7\x70\xae" + "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82" + "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68" + "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce" + "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98" + "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2" + "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f" + "\xea\x20\xe7\xcb\x65\x77\x3a\xdf" + "\xc8\x97\x67\x15\xc2\x2a\x27\xcc" + "\x18\x55\xa1\x24\x0b\x24\x24\xaf" + "\x5b\xec\x68\xb8\xc8\xf5\xba\x63" + "\xff\xed\x89\xce\xd5\x3d\x88\xf3" + "\x25\xef\x05\x7c\x3a\xef\xeb\xd8" + "\x7a\x32\x0d\xd1\x1e\x58\x59\x99" + "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c" + "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50" + "\x41\x30\x58\xc5\x62\x74\x52\x1d" + "\x45\x24\x6a\x42\x64\x4f\x97\x1c" + "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48" + "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1" + "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46" + "\xe4\x81\x84\x95\x36\x59\x7a\x6b" + "\xaa\xb3\x60\xad\xce\x9f\x9f\x28" + "\xe0\x01\x75\x22\xc4\x4e\xa9\x62" + "\x5c\x62\x0d\x00\xcb\x13\xe8\x43" + "\x72\xd4\x2d\x53\x46\xb5\xd1\x16" + "\x22\x18\xdf\x34\x33\xf5\xd6\x1c" + "\xb8\x79\x78\x97\x94\xff\x72\x13" + "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6" + "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4" + "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f" + "\x2d\x14\x8e\x24\x61\x2c\xe1\x17" + "\xcc\xce\x51\x0c\x19\x8a\x82\x30" + "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd" + "\xb7\xeb\xfa\xfd\x27\x51\xde\x85" + "\x1e\x86\x53\x11\x53\x94\x00\xee" + "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11" + "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62" + "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1" + "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a" + "\x9e\xfa\x31\x18\x45\x3c\x21\x33" + "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1" + "\x03\xad\x1b\x48\xd4\x67\x27\xf0" + "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7" + "\xdd\x2b\x01\x39\x04\x5a\x58\x7a" + "\xf7\x11\x90\xec\xbd\x51\x5c\x32" + "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6" + "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d" + "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4" + "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3" + "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29" + "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7" + "\x74\x3f\x7d\x58\x88\x75\xde\x3e", + .ilen = 512, + .result = "\x05\x11\xb7\x18\xab\xc6\x2d\xac" + "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c" + "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8" + "\x50\x38\x1f\x71\x49\xb6\x57\xd6" + "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90" + "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6" + "\xad\x1e\x9e\x20\x5f\x38\xbe\x04" + "\xda\x10\x8e\xed\xa2\xa4\x87\xab" + "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c" + "\xc9\xac\x42\x31\x95\x7c\xc9\x04" + "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6" + "\x15\xd7\x3f\x4f\x2f\x66\x69\x03" + "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65" + "\x4c\x96\x12\xed\x7c\x92\x03\x01" + "\x6f\xbc\x35\x93\xac\xf1\x27\xf1" + "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50" + "\x89\xa4\x8e\x66\x44\x85\xcc\xfd" + "\x33\x14\x70\xe3\x96\xb2\xc3\xd3" + "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5" + "\x2d\x64\x75\xdd\xb4\x54\xe6\x74" + "\x8c\xd3\x9d\x9e\x86\xab\x51\x53" + "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40" + "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5" + "\x76\x12\x73\x44\x1a\x56\xd7\x72" + "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda" + "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd" + "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60" + "\x1a\xe2\x70\x85\x58\xc2\x1b\x09" + "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9" + "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8" + "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8" + "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10" + "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1" + "\x90\x3e\x76\x4a\x74\xa4\x21\x2c" + "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e" + "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f" + "\x8d\x23\x31\x74\x84\xeb\x88\x6e" + "\xcc\xb9\xbc\x22\x83\x19\x07\x22" + "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78" + "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5" + "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41" + "\x3c\xce\x8f\x42\x60\x71\xa7\x75" + "\x08\x40\x65\x8a\x82\xbf\xf5\x43" + "\x71\x96\xa9\x4d\x44\x8a\x20\xbe" + "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65" + "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9" + "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4" + "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a" + "\x62\x73\x65\xfd\x46\x63\x25\x3d" + "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf" + "\x24\xf3\xb4\xac\x64\xba\xdf\x4b" + "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7" + "\xc5\x68\x77\x84\x32\x2b\xcc\x85" + "\x74\x96\xf0\x12\x77\x61\xb9\xeb" + "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8" + "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24" + "\xda\x39\x87\x45\xc0\x2b\xbb\x01" + "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce" + "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6" + "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32" + "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45" + "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6" + "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4" + "\x21\xc4\xc2\x75\x67\x89\x37\x0a", + .rlen = 512, + } +}; + +static struct cipher_testvec aes_xts_enc_tv_template[] = { + /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */ + { /* XTS-AES 1 */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 32, + .result = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec" + "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92" + "\xcd\x43\xd2\xf5\x95\x98\xed\x85" + "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e", + .rlen = 32, + }, { /* XTS-AES 2 */ + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ilen = 32, + .result = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e" + "\x39\x33\x40\x38\xac\xef\x83\x8b" + "\xfb\x18\x6f\xff\x74\x80\xad\xc4" + "\x28\x93\x82\xec\xd6\xd3\x94\xf0", + .rlen = 32, + }, { /* XTS-AES 3 */ + .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8" + "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .ilen = 32, + .result = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a" + "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2" + "\x92\xdf\x4c\x04\x7e\x0b\x21\x53" + "\x21\x86\xa5\x97\x1a\x22\x7a\x89", + .rlen = 32, + }, { /* XTS-AES 4 */ + .key = "\x27\x18\x28\x18\x28\x45\x90\x45" + "\x23\x53\x60\x28\x74\x71\x35\x26" + "\x31\x41\x59\x26\x53\x58\x97\x93" + "\x23\x84\x62\x64\x33\x83\x27\x95", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" + "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .ilen = 512, + .result = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76" + "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2" + "\xa9\x6e\x4b\xbe\x32\x08\xff\x25" + "\x28\x7d\xd3\x81\x96\x16\xe8\x9c" + "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f" + "\x83\x33\xd8\xfa\x7f\x56\x00\x00" + "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad" + "\x40\xe7\x36\xdd\xb4\xd3\x54\x12" + "\x32\x80\x63\xfd\x2a\xab\x53\xe5" + "\xea\x1e\x0a\x9f\x33\x25\x00\xa5" + "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc" + "\x51\x2c\x88\x66\xc7\xe8\x60\xce" + "\x93\xfd\xf1\x66\xa2\x49\x12\xb4" + "\x22\x97\x61\x46\xae\x20\xce\x84" + "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a" + "\xae\xf2\x0c\x0d\x61\xad\x02\x65" + "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89" + "\x52\xc6\x51\xd3\x31\x74\xbe\x51" + "\xa1\x0c\x42\x11\x10\xe6\xd8\x15" + "\x88\xed\xe8\x21\x03\xa2\x52\xd8" + "\xa7\x50\xe8\x76\x8d\xef\xff\xed" + "\x91\x22\x81\x0a\xae\xb9\x9f\x91" + "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e" + "\x51\xbc\xb0\x82\x35\xa6\xf4\x34" + "\x13\x32\xe4\xca\x60\x48\x2a\x4b" + "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5" + "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4" + "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c" + "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd" + "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3" + "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f" + "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e" + "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91" + "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19" + "\x7c\x4e\x5b\x03\x39\x36\x97\xe1" + "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc" + "\x1e\x08\x29\x85\x16\xe2\xc9\xed" + "\x03\xff\x3c\x1b\x78\x60\xf6\xde" + "\x76\xd4\xce\xcd\x94\xc8\x11\x98" + "\x55\xef\x52\x97\xca\x67\xe9\xf3" + "\xe7\xff\x72\xb1\xe9\x97\x85\xca" + "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6" + "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc" + "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44" + "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0" + "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95" + "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4" + "\x99\x02\x7a\x78\x57\x2a\xee\xbd" + "\x74\xd2\x0c\xc3\x98\x81\xc2\x13" + "\xee\x77\x0b\x10\x10\xe4\xbe\xa7" + "\x18\x84\x69\x77\xae\x11\x9f\x7a" + "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52" + "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a" + "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38" + "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e" + "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e" + "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad" + "\x15\xb4\xaa\x5b\x65\x50\x16\xa8" + "\x44\x92\x77\xdb\xd4\x77\xef\x2c" + "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d" + "\xeb\x4a\x42\x7d\x19\x23\xce\x3f" + "\xf2\x62\x73\x57\x79\xa4\x18\xf2" + "\x0a\x28\x2d\xf9\x20\x14\x7b\xea" + "\xbe\x42\x1e\xe5\x31\x9d\x05\x68", + .rlen = 512, + } +}; + +static struct cipher_testvec aes_xts_dec_tv_template[] = { + /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */ + { /* XTS-AES 1 */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec" + "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92" + "\xcd\x43\xd2\xf5\x95\x98\xed\x85" + "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e", + .ilen = 32, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .rlen = 32, + }, { /* XTS-AES 2 */ + .key = "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x11\x11\x11\x11\x11\x11\x11\x11" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e" + "\x39\x33\x40\x38\xac\xef\x83\x8b" + "\xfb\x18\x6f\xff\x74\x80\xad\xc4" + "\x28\x93\x82\xec\xd6\xd3\x94\xf0", + .ilen = 32, + .result = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .rlen = 32, + }, { /* XTS-AES 3 */ + .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8" + "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0" + "\x22\x22\x22\x22\x22\x22\x22\x22" + "\x22\x22\x22\x22\x22\x22\x22\x22", + .klen = 32, + .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a" + "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2" + "\x92\xdf\x4c\x04\x7e\x0b\x21\x53" + "\x21\x86\xa5\x97\x1a\x22\x7a\x89", + .ilen = 32, + .result = "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44" + "\x44\x44\x44\x44\x44\x44\x44\x44", + .rlen = 32, + }, { /* XTS-AES 4 */ + .key = "\x27\x18\x28\x18\x28\x45\x90\x45" + "\x23\x53\x60\x28\x74\x71\x35\x26" + "\x31\x41\x59\x26\x53\x58\x97\x93" + "\x23\x84\x62\x64\x33\x83\x27\x95", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76" + "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2" + "\xa9\x6e\x4b\xbe\x32\x08\xff\x25" + "\x28\x7d\xd3\x81\x96\x16\xe8\x9c" + "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f" + "\x83\x33\xd8\xfa\x7f\x56\x00\x00" + "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad" + "\x40\xe7\x36\xdd\xb4\xd3\x54\x12" + "\x32\x80\x63\xfd\x2a\xab\x53\xe5" + "\xea\x1e\x0a\x9f\x33\x25\x00\xa5" + "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc" + "\x51\x2c\x88\x66\xc7\xe8\x60\xce" + "\x93\xfd\xf1\x66\xa2\x49\x12\xb4" + "\x22\x97\x61\x46\xae\x20\xce\x84" + "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a" + "\xae\xf2\x0c\x0d\x61\xad\x02\x65" + "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89" + "\x52\xc6\x51\xd3\x31\x74\xbe\x51" + "\xa1\x0c\x42\x11\x10\xe6\xd8\x15" + "\x88\xed\xe8\x21\x03\xa2\x52\xd8" + "\xa7\x50\xe8\x76\x8d\xef\xff\xed" + "\x91\x22\x81\x0a\xae\xb9\x9f\x91" + "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e" + "\x51\xbc\xb0\x82\x35\xa6\xf4\x34" + "\x13\x32\xe4\xca\x60\x48\x2a\x4b" + "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5" + "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4" + "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c" + "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd" + "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3" + "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f" + "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e" + "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91" + "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19" + "\x7c\x4e\x5b\x03\x39\x36\x97\xe1" + "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc" + "\x1e\x08\x29\x85\x16\xe2\xc9\xed" + "\x03\xff\x3c\x1b\x78\x60\xf6\xde" + "\x76\xd4\xce\xcd\x94\xc8\x11\x98" + "\x55\xef\x52\x97\xca\x67\xe9\xf3" + "\xe7\xff\x72\xb1\xe9\x97\x85\xca" + "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6" + "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc" + "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44" + "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0" + "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95" + "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4" + "\x99\x02\x7a\x78\x57\x2a\xee\xbd" + "\x74\xd2\x0c\xc3\x98\x81\xc2\x13" + "\xee\x77\x0b\x10\x10\xe4\xbe\xa7" + "\x18\x84\x69\x77\xae\x11\x9f\x7a" + "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52" + "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a" + "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38" + "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e" + "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e" + "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad" + "\x15\xb4\xaa\x5b\x65\x50\x16\xa8" + "\x44\x92\x77\xdb\xd4\x77\xef\x2c" + "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d" + "\xeb\x4a\x42\x7d\x19\x23\xce\x3f" + "\xf2\x62\x73\x57\x79\xa4\x18\xf2" + "\x0a\x28\x2d\xf9\x20\x14\x7b\xea" + "\xbe\x42\x1e\xe5\x31\x9d\x05\x68", + .ilen = 512, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" + "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + .rlen = 512, + } +}; + + +static struct cipher_testvec aes_ctr_enc_tv_template[] = { + { /* From RFC 3686 */ + .key = "\xae\x68\x52\xf8\x12\x10\x67\xcc" + "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e" + "\x00\x00\x00\x30", + .klen = 20, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "Single block msg", + .ilen = 16, + .result = "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79" + "\x2d\x61\x75\xa3\x26\x13\x11\xb8", + .rlen = 16, + }, { + .key = "\x7e\x24\x06\x78\x17\xfa\xe0\xd7" + "\x43\xd6\xce\x1f\x32\x53\x91\x63" + "\x00\x6c\xb6\xdb", + .klen = 20, + .iv = "\xc0\x54\x3b\x59\xda\x48\xd9\x0b", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\x51\x04\xa1\x06\x16\x8a\x72\xd9" + "\x79\x0d\x41\xee\x8e\xda\xd3\x88" + "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8" + "\xfc\xe6\x30\xdf\x91\x41\xbe\x28", + .rlen = 32, + }, { + .key = "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79" + "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed" + "\x86\x3d\x06\xcc\xfd\xb7\x85\x15" + "\x00\x00\x00\x48", + .klen = 28, + .iv = "\x36\x73\x3c\x14\x7d\x6d\x93\xcb", + .input = "Single block msg", + .ilen = 16, + .result = "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8" + "\x4e\x79\x35\xa0\x03\xcb\xe9\x28", + .rlen = 16, + }, { + .key = "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c" + "\x19\xe7\x34\x08\x19\xe0\xf6\x9c" + "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a" + "\x00\x96\xb0\x3b", + .klen = 28, + .iv = "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\x45\x32\x43\xfc\x60\x9b\x23\x32" + "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f" + "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c" + "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00", + .rlen = 32, + }, { + .key = "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f" + "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c" + "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3" + "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04" + "\x00\x00\x00\x60", + .klen = 36, + .iv = "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2", + .input = "Single block msg", + .ilen = 16, + .result = "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7" + "\x56\x08\x63\xdc\x71\xe3\xe0\xc0", + .rlen = 16, + }, { + .key = "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb" + "\x07\x96\x36\x58\x79\xef\xf8\x86" + "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74" + "\x4b\x50\x59\x0c\x87\xa2\x38\x84" + "\x00\xfa\xac\x24", + .klen = 36, + .iv = "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\xf0\x5e\x23\x1b\x38\x94\x61\x2c" + "\x49\xee\x00\x0b\x80\x4e\xb2\xa9" + "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a" + "\x55\x30\x83\x1d\x93\x44\xaf\x1c", + .rlen = 32, + }, { + // generated using Crypto++ + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x00\x00\x00\x00", + .klen = 32 + 4, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = + "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" + "\x00\x03\x06\x09\x0c\x0f\x12\x15" + "\x18\x1b\x1e\x21\x24\x27\x2a\x2d" + "\x30\x33\x36\x39\x3c\x3f\x42\x45" + "\x48\x4b\x4e\x51\x54\x57\x5a\x5d" + "\x60\x63\x66\x69\x6c\x6f\x72\x75" + "\x78\x7b\x7e\x81\x84\x87\x8a\x8d" + "\x90\x93\x96\x99\x9c\x9f\xa2\xa5" + "\xa8\xab\xae\xb1\xb4\xb7\xba\xbd" + "\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5" + "\xd8\xdb\xde\xe1\xe4\xe7\xea\xed" + "\xf0\xf3\xf6\xf9\xfc\xff\x02\x05" + "\x08\x0b\x0e\x11\x14\x17\x1a\x1d" + "\x20\x23\x26\x29\x2c\x2f\x32\x35" + "\x38\x3b\x3e\x41\x44\x47\x4a\x4d" + "\x50\x53\x56\x59\x5c\x5f\x62\x65" + "\x68\x6b\x6e\x71\x74\x77\x7a\x7d" + "\x80\x83\x86\x89\x8c\x8f\x92\x95" + "\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad" + "\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5" + "\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd" + "\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5" + "\xf8\xfb\xfe\x01\x04\x07\x0a\x0d" + "\x10\x13\x16\x19\x1c\x1f\x22\x25" + "\x28\x2b\x2e\x31\x34\x37\x3a\x3d" + "\x40\x43\x46\x49\x4c\x4f\x52\x55" + "\x58\x5b\x5e\x61\x64\x67\x6a\x6d" + "\x70\x73\x76\x79\x7c\x7f\x82\x85" + "\x88\x8b\x8e\x91\x94\x97\x9a\x9d" + "\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5" + "\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd" + "\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5" + "\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd" + "\x00\x05\x0a\x0f\x14\x19\x1e\x23" + "\x28\x2d\x32\x37\x3c\x41\x46\x4b" + "\x50\x55\x5a\x5f\x64\x69\x6e\x73" + "\x78\x7d\x82\x87\x8c\x91\x96\x9b" + "\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3" + "\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb" + "\xf0\xf5\xfa\xff\x04\x09\x0e\x13" + "\x18\x1d\x22\x27\x2c\x31\x36\x3b" + "\x40\x45\x4a\x4f\x54\x59\x5e\x63" + "\x68\x6d\x72\x77\x7c\x81\x86\x8b" + "\x90\x95\x9a\x9f\xa4\xa9\xae\xb3" + "\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb" + "\xe0\xe5\xea\xef\xf4\xf9\xfe\x03" + "\x08\x0d\x12\x17\x1c\x21\x26\x2b" + "\x30\x35\x3a\x3f\x44\x49\x4e\x53" + "\x58\x5d\x62\x67\x6c\x71\x76\x7b" + "\x80\x85\x8a\x8f\x94\x99\x9e\xa3" + "\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb" + "\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3" + "\xf8\xfd\x02\x07\x0c\x11\x16\x1b" + "\x20\x25\x2a\x2f\x34\x39\x3e\x43" + "\x48\x4d\x52\x57\x5c\x61\x66\x6b" + "\x70\x75\x7a\x7f\x84\x89\x8e\x93" + "\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb" + "\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3" + "\xe8\xed\xf2\xf7\xfc\x01\x06\x0b" + "\x10\x15\x1a\x1f\x24\x29\x2e\x33" + "\x38\x3d\x42\x47\x4c\x51\x56\x5b" + "\x60\x65\x6a\x6f\x74\x79\x7e\x83" + "\x88\x8d\x92\x97\x9c\xa1\xa6\xab" + "\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3" + "\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb" + "\x00\x07\x0e\x15\x1c\x23\x2a\x31" + "\x38\x3f\x46\x4d\x54\x5b\x62\x69" + "\x70\x77\x7e\x85\x8c\x93\x9a\xa1" + "\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9" + "\xe0\xe7\xee\xf5\xfc\x03\x0a\x11" + "\x18\x1f\x26\x2d\x34\x3b\x42\x49" + "\x50\x57\x5e\x65\x6c\x73\x7a\x81" + "\x88\x8f\x96\x9d\xa4\xab\xb2\xb9" + "\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1" + "\xf8\xff\x06\x0d\x14\x1b\x22\x29" + "\x30\x37\x3e\x45\x4c\x53\x5a\x61" + "\x68\x6f\x76\x7d\x84\x8b\x92\x99" + "\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1" + "\xd8\xdf\xe6\xed\xf4\xfb\x02\x09" + "\x10\x17\x1e\x25\x2c\x33\x3a\x41" + "\x48\x4f\x56\x5d\x64\x6b\x72\x79" + "\x80\x87\x8e\x95\x9c\xa3\xaa\xb1" + "\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9" + "\xf0\xf7\xfe\x05\x0c\x13\x1a\x21" + "\x28\x2f\x36\x3d\x44\x4b\x52\x59" + "\x60\x67\x6e\x75\x7c\x83\x8a\x91" + "\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9" + "\xd0\xd7\xde\xe5\xec\xf3\xfa\x01" + "\x08\x0f\x16\x1d\x24\x2b\x32\x39" + "\x40\x47\x4e\x55\x5c\x63\x6a\x71" + "\x78\x7f\x86\x8d\x94\x9b\xa2\xa9" + "\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1" + "\xe8\xef\xf6\xfd\x04\x0b\x12\x19" + "\x20\x27\x2e\x35\x3c\x43\x4a\x51" + "\x58\x5f\x66\x6d\x74\x7b\x82\x89" + "\x90\x97\x9e\xa5\xac\xb3\xba\xc1" + "\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9" + "\x00\x09\x12\x1b\x24\x2d\x36\x3f" + "\x48\x51\x5a\x63\x6c\x75\x7e\x87" + "\x90\x99\xa2\xab\xb4\xbd\xc6\xcf" + "\xd8\xe1\xea\xf3\xfc\x05\x0e\x17" + "\x20\x29\x32\x3b\x44\x4d\x56\x5f" + "\x68\x71\x7a\x83\x8c\x95\x9e\xa7" + "\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef" + "\xf8\x01\x0a\x13\x1c\x25\x2e\x37" + "\x40\x49\x52\x5b\x64\x6d\x76\x7f" + "\x88\x91\x9a\xa3\xac\xb5\xbe\xc7" + "\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f" + "\x18\x21\x2a\x33\x3c\x45\x4e\x57" + "\x60\x69\x72\x7b\x84\x8d\x96\x9f" + "\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7" + "\xf0\xf9\x02\x0b\x14\x1d\x26\x2f" + "\x38\x41\x4a\x53\x5c\x65\x6e\x77" + "\x80\x89\x92\x9b\xa4\xad\xb6\xbf" + "\xc8\xd1\xda\xe3\xec\xf5\xfe\x07" + "\x10\x19\x22\x2b\x34\x3d\x46\x4f" + "\x58\x61\x6a\x73\x7c\x85\x8e\x97" + "\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf" + "\xe8\xf1\xfa\x03\x0c\x15\x1e\x27" + "\x30\x39\x42\x4b\x54\x5d\x66\x6f" + "\x78\x81\x8a\x93\x9c\xa5\xae\xb7" + "\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff" + "\x08\x11\x1a\x23\x2c\x35\x3e\x47" + "\x50\x59\x62\x6b\x74\x7d\x86\x8f" + "\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7" + "\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f" + "\x28\x31\x3a\x43\x4c\x55\x5e\x67" + "\x70\x79\x82\x8b\x94\x9d\xa6\xaf" + "\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7" + "\x00\x0b\x16\x21\x2c\x37\x42\x4d" + "\x58\x63\x6e\x79\x84\x8f\x9a\xa5" + "\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd" + "\x08\x13\x1e\x29\x34\x3f\x4a\x55" + "\x60\x6b\x76\x81\x8c\x97\xa2\xad" + "\xb8\xc3\xce\xd9\xe4\xef\xfa\x05" + "\x10\x1b\x26\x31\x3c\x47\x52\x5d" + "\x68\x73\x7e\x89\x94\x9f\xaa\xb5" + "\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d" + "\x18\x23\x2e\x39\x44\x4f\x5a\x65" + "\x70\x7b\x86\x91\x9c\xa7\xb2\xbd" + "\xc8\xd3\xde\xe9\xf4\xff\x0a\x15" + "\x20\x2b\x36\x41\x4c\x57\x62\x6d" + "\x78\x83\x8e\x99\xa4\xaf\xba\xc5" + "\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d" + "\x28\x33\x3e\x49\x54\x5f\x6a\x75" + "\x80\x8b\x96\xa1\xac\xb7\xc2\xcd" + "\xd8\xe3\xee\xf9\x04\x0f\x1a\x25" + "\x30\x3b\x46\x51\x5c\x67\x72\x7d" + "\x88\x93\x9e\xa9\xb4\xbf\xca\xd5" + "\xe0\xeb\xf6\x01\x0c\x17\x22\x2d" + "\x38\x43\x4e\x59\x64\x6f\x7a\x85" + "\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd" + "\xe8\xf3\xfe\x09\x14\x1f\x2a\x35" + "\x40\x4b\x56\x61\x6c\x77\x82\x8d" + "\x98\xa3\xae\xb9\xc4\xcf\xda\xe5" + "\xf0\xfb\x06\x11\x1c\x27\x32\x3d" + "\x48\x53\x5e\x69\x74\x7f\x8a\x95" + "\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed" + "\xf8\x03\x0e\x19\x24\x2f\x3a\x45" + "\x50\x5b\x66\x71\x7c\x87\x92\x9d" + "\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5" + "\x00\x0d\x1a\x27\x34\x41\x4e\x5b" + "\x68\x75\x82\x8f\x9c\xa9\xb6\xc3" + "\xd0\xdd\xea\xf7\x04\x11\x1e\x2b" + "\x38\x45\x52\x5f\x6c\x79\x86\x93" + "\xa0\xad\xba\xc7\xd4\xe1\xee\xfb" + "\x08\x15\x22\x2f\x3c\x49\x56\x63" + "\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb" + "\xd8\xe5\xf2\xff\x0c\x19\x26\x33" + "\x40\x4d\x5a\x67\x74\x81\x8e\x9b" + "\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03" + "\x10\x1d\x2a\x37\x44\x51\x5e\x6b" + "\x78\x85\x92\x9f\xac\xb9\xc6\xd3" + "\xe0\xed\xfa\x07\x14\x21\x2e\x3b" + "\x48\x55\x62\x6f\x7c\x89\x96\xa3" + "\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b" + "\x18\x25\x32\x3f\x4c\x59\x66\x73" + "\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb" + "\xe8\xf5\x02\x0f\x1c\x29\x36\x43" + "\x50\x5d\x6a\x77\x84\x91\x9e\xab" + "\xb8\xc5\xd2\xdf\xec\xf9\x06\x13" + "\x20\x2d\x3a\x47\x54\x61\x6e\x7b" + "\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3" + "\xf0\xfd\x0a\x17\x24\x31\x3e\x4b" + "\x58\x65\x72\x7f\x8c\x99\xa6\xb3" + "\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b" + "\x28\x35\x42\x4f\x5c\x69\x76\x83" + "\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb" + "\xf8\x05\x12\x1f\x2c\x39\x46\x53" + "\x60\x6d\x7a\x87\x94\xa1\xae\xbb" + "\xc8\xd5\xe2\xef\xfc\x09\x16\x23" + "\x30\x3d\x4a\x57\x64\x71\x7e\x8b" + "\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3" + "\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69" + "\x78\x87\x96\xa5\xb4\xc3\xd2\xe1" + "\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59" + "\x68\x77\x86\x95\xa4\xb3\xc2\xd1" + "\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49" + "\x58\x67\x76\x85\x94\xa3\xb2\xc1" + "\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39" + "\x48\x57\x66\x75\x84\x93\xa2\xb1" + "\xc0\xcf\xde\xed\xfc\x0b\x1a\x29" + "\x38\x47\x56\x65\x74\x83\x92\xa1" + "\xb0\xbf\xce\xdd\xec\xfb\x0a\x19" + "\x28\x37\x46\x55\x64\x73\x82\x91" + "\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09" + "\x18\x27\x36\x45\x54\x63\x72\x81" + "\x90\x9f\xae\xbd\xcc\xdb\xea\xf9" + "\x08\x17\x26\x35\x44\x53\x62\x71" + "\x80\x8f\x9e\xad\xbc\xcb\xda\xe9" + "\xf8\x07\x16\x25\x34\x43\x52\x61" + "\x70\x7f\x8e\x9d\xac\xbb\xca\xd9" + "\xe8\xf7\x06\x15\x24\x33\x42\x51" + "\x60\x6f\x7e\x8d\x9c\xab\xba\xc9" + "\xd8\xe7\xf6\x05\x14\x23\x32\x41" + "\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9" + "\xc8\xd7\xe6\xf5\x04\x13\x22\x31" + "\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9" + "\xb8\xc7\xd6\xe5\xf4\x03\x12\x21" + "\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99" + "\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11" + "\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89" + "\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01" + "\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79" + "\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff" + "\x10\x21\x32\x43\x54\x65\x76\x87" + "\x98\xa9\xba\xcb\xdc\xed\xfe\x0f" + "\x20\x31\x42\x53\x64\x75\x86\x97" + "\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f" + "\x30\x41\x52\x63\x74\x85\x96\xa7" + "\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f" + "\x40\x51\x62\x73\x84\x95\xa6\xb7" + "\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f" + "\x50\x61\x72\x83\x94\xa5\xb6\xc7" + "\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f" + "\x60\x71\x82\x93\xa4\xb5\xc6\xd7" + "\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f" + "\x70\x81\x92\xa3\xb4\xc5\xd6\xe7" + "\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f" + "\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7" + "\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f" + "\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07" + "\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f" + "\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17" + "\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f" + "\xb0\xc1\xd2\xe3\xf4\x05\x16\x27" + "\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf" + "\xc0\xd1\xe2\xf3\x04\x15\x26\x37" + "\x48\x59\x6a\x7b\x8c\x9d\xae\xbf" + "\xd0\xe1\xf2\x03\x14\x25\x36\x47" + "\x58\x69\x7a\x8b\x9c\xad\xbe\xcf" + "\xe0\xf1\x02\x13\x24\x35\x46\x57" + "\x68\x79\x8a\x9b\xac\xbd\xce\xdf" + "\xf0\x01\x12\x23\x34\x45\x56\x67" + "\x78\x89\x9a\xab\xbc\xcd\xde\xef" + "\x00\x13\x26\x39\x4c\x5f\x72\x85" + "\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d" + "\x30\x43\x56\x69\x7c\x8f\xa2\xb5" + "\xc8\xdb\xee\x01\x14\x27\x3a\x4d" + "\x60\x73\x86\x99\xac\xbf\xd2\xe5" + "\xf8\x0b\x1e\x31\x44\x57\x6a\x7d" + "\x90\xa3\xb6\xc9\xdc\xef\x02\x15" + "\x28\x3b\x4e\x61\x74\x87\x9a\xad" + "\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45" + "\x58\x6b\x7e\x91\xa4\xb7\xca\xdd" + "\xf0\x03\x16\x29\x3c\x4f\x62\x75" + "\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d" + "\x20\x33\x46\x59\x6c\x7f\x92\xa5" + "\xb8\xcb\xde\xf1\x04\x17\x2a\x3d" + "\x50\x63\x76\x89\x9c\xaf\xc2\xd5" + "\xe8\xfb\x0e\x21\x34\x47\x5a\x6d" + "\x80\x93\xa6\xb9\xcc\xdf\xf2\x05" + "\x18\x2b\x3e\x51\x64\x77\x8a\x9d" + "\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35" + "\x48\x5b\x6e\x81\x94\xa7\xba\xcd" + "\xe0\xf3\x06\x19\x2c\x3f\x52\x65" + "\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd" + "\x10\x23\x36\x49\x5c\x6f\x82\x95" + "\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d" + "\x40\x53\x66\x79\x8c\x9f\xb2\xc5" + "\xd8\xeb\xfe\x11\x24\x37\x4a\x5d" + "\x70\x83\x96\xa9\xbc\xcf\xe2\xf5" + "\x08\x1b\x2e\x41\x54\x67\x7a\x8d" + "\xa0\xb3\xc6\xd9\xec\xff\x12\x25" + "\x38\x4b\x5e\x71\x84\x97\xaa\xbd" + "\xd0\xe3\xf6\x09\x1c\x2f\x42\x55" + "\x68\x7b\x8e\xa1\xb4\xc7\xda\xed" + "\x00\x15\x2a\x3f\x54\x69\x7e\x93" + "\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b" + "\x50\x65\x7a\x8f\xa4\xb9\xce\xe3" + "\xf8\x0d\x22\x37\x4c\x61\x76\x8b" + "\xa0\xb5\xca\xdf\xf4\x09\x1e\x33" + "\x48\x5d\x72\x87\x9c\xb1\xc6\xdb" + "\xf0\x05\x1a\x2f\x44\x59\x6e\x83" + "\x98\xad\xc2\xd7\xec\x01\x16\x2b" + "\x40\x55\x6a\x7f\x94\xa9\xbe\xd3" + "\xe8\xfd\x12\x27\x3c\x51\x66\x7b" + "\x90\xa5\xba\xcf\xe4\xf9\x0e\x23" + "\x38\x4d\x62\x77\x8c\xa1\xb6\xcb" + "\xe0\xf5\x0a\x1f\x34\x49\x5e\x73" + "\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b" + "\x30\x45\x5a\x6f\x84\x99\xae\xc3" + "\xd8\xed\x02\x17\x2c\x41\x56\x6b" + "\x80\x95\xaa\xbf\xd4\xe9\xfe\x13" + "\x28\x3d\x52\x67\x7c\x91\xa6\xbb" + "\xd0\xe5\xfa\x0f\x24\x39\x4e\x63" + "\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b" + "\x20\x35\x4a\x5f\x74\x89\x9e\xb3" + "\xc8\xdd\xf2\x07\x1c\x31\x46\x5b" + "\x70\x85\x9a\xaf\xc4\xd9\xee\x03" + "\x18\x2d\x42\x57\x6c\x81\x96\xab" + "\xc0\xd5\xea\xff\x14\x29\x3e\x53" + "\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb" + "\x10\x25\x3a\x4f\x64\x79\x8e\xa3" + "\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b" + "\x60\x75\x8a\x9f\xb4\xc9\xde\xf3" + "\x08\x1d\x32\x47\x5c\x71\x86\x9b" + "\xb0\xc5\xda\xef\x04\x19\x2e\x43" + "\x58\x6d\x82\x97\xac\xc1\xd6\xeb" + "\x00\x17\x2e\x45\x5c\x73\x8a\xa1" + "\xb8\xcf\xe6\xfd\x14\x2b\x42\x59" + "\x70\x87\x9e\xb5\xcc\xe3\xfa\x11" + "\x28\x3f\x56\x6d\x84\x9b\xb2\xc9" + "\xe0\xf7\x0e\x25\x3c\x53\x6a\x81" + "\x98\xaf\xc6\xdd\xf4\x0b\x22\x39" + "\x50\x67\x7e\x95\xac\xc3\xda\xf1" + "\x08\x1f\x36\x4d\x64\x7b\x92\xa9" + "\xc0\xd7\xee\x05\x1c\x33\x4a\x61" + "\x78\x8f\xa6\xbd\xd4\xeb\x02\x19" + "\x30\x47\x5e\x75\x8c\xa3\xba\xd1" + "\xe8\xff\x16\x2d\x44\x5b\x72\x89" + "\xa0\xb7\xce\xe5\xfc\x13\x2a\x41" + "\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9" + "\x10\x27\x3e\x55\x6c\x83\x9a\xb1" + "\xc8\xdf\xf6\x0d\x24\x3b\x52\x69" + "\x80\x97\xae\xc5\xdc\xf3\x0a\x21" + "\x38\x4f\x66\x7d\x94\xab\xc2\xd9" + "\xf0\x07\x1e\x35\x4c\x63\x7a\x91" + "\xa8\xbf\xd6\xed\x04\x1b\x32\x49" + "\x60\x77\x8e\xa5\xbc\xd3\xea\x01" + "\x18\x2f\x46\x5d\x74\x8b\xa2\xb9" + "\xd0\xe7\xfe\x15\x2c\x43\x5a\x71" + "\x88\x9f\xb6\xcd\xe4\xfb\x12\x29" + "\x40\x57\x6e\x85\x9c\xb3\xca\xe1" + "\xf8\x0f\x26\x3d\x54\x6b\x82\x99" + "\xb0\xc7\xde\xf5\x0c\x23\x3a\x51" + "\x68\x7f\x96\xad\xc4\xdb\xf2\x09" + "\x20\x37\x4e\x65\x7c\x93\xaa\xc1" + "\xd8\xef\x06\x1d\x34\x4b\x62\x79" + "\x90\xa7\xbe\xd5\xec\x03\x1a\x31" + "\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9" + "\x00\x19\x32\x4b\x64\x7d\x96\xaf" + "\xc8\xe1\xfa\x13\x2c\x45\x5e\x77" + "\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f" + "\x58\x71\x8a\xa3\xbc\xd5\xee\x07" + "\x20\x39\x52\x6b\x84\x9d\xb6\xcf" + "\xe8\x01\x1a\x33\x4c\x65\x7e\x97" + "\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f" + "\x78\x91\xaa\xc3\xdc\xf5\x0e\x27" + "\x40\x59\x72\x8b\xa4\xbd\xd6\xef" + "\x08\x21\x3a\x53\x6c\x85\x9e\xb7" + "\xd0\xe9\x02\x1b\x34\x4d\x66\x7f" + "\x98\xb1\xca\xe3\xfc\x15\x2e\x47" + "\x60\x79\x92\xab\xc4\xdd\xf6\x0f" + "\x28\x41\x5a\x73\x8c\xa5\xbe\xd7" + "\xf0\x09\x22\x3b\x54\x6d\x86\x9f" + "\xb8\xd1\xea\x03\x1c\x35\x4e\x67" + "\x80\x99\xb2\xcb\xe4\xfd\x16\x2f" + "\x48\x61\x7a\x93\xac\xc5\xde\xf7" + "\x10\x29\x42\x5b\x74\x8d\xa6\xbf" + "\xd8\xf1\x0a\x23\x3c\x55\x6e\x87" + "\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f" + "\x68\x81\x9a\xb3\xcc\xe5\xfe\x17" + "\x30\x49\x62\x7b\x94\xad\xc6\xdf" + "\xf8\x11\x2a\x43\x5c\x75\x8e\xa7" + "\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f" + "\x88\xa1\xba\xd3\xec\x05\x1e\x37" + "\x50\x69\x82\x9b\xb4\xcd\xe6\xff" + "\x18\x31\x4a\x63\x7c\x95\xae\xc7" + "\xe0\xf9\x12\x2b\x44\x5d\x76\x8f" + "\xa8\xc1\xda\xf3\x0c\x25\x3e\x57" + "\x70\x89\xa2\xbb\xd4\xed\x06\x1f" + "\x38\x51\x6a\x83\x9c\xb5\xce\xe7" + "\x00\x1b\x36\x51\x6c\x87\xa2\xbd" + "\xd8\xf3\x0e\x29\x44\x5f\x7a\x95" + "\xb0\xcb\xe6\x01\x1c\x37\x52\x6d" + "\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45" + "\x60\x7b\x96\xb1\xcc\xe7\x02\x1d" + "\x38\x53\x6e\x89\xa4\xbf\xda\xf5" + "\x10\x2b\x46\x61\x7c\x97\xb2\xcd" + "\xe8\x03\x1e\x39\x54\x6f\x8a\xa5" + "\xc0\xdb\xf6\x11\x2c\x47\x62\x7d" + "\x98\xb3\xce\xe9\x04\x1f\x3a\x55" + "\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d" + "\x48\x63\x7e\x99\xb4\xcf\xea\x05" + "\x20\x3b\x56\x71\x8c\xa7\xc2\xdd" + "\xf8\x13\x2e\x49\x64\x7f\x9a\xb5" + "\xd0\xeb\x06\x21\x3c\x57\x72\x8d" + "\xa8\xc3\xde\xf9\x14\x2f\x4a\x65" + "\x80\x9b\xb6\xd1\xec\x07\x22\x3d" + "\x58\x73\x8e\xa9\xc4\xdf\xfa\x15" + "\x30\x4b\x66\x81\x9c\xb7\xd2\xed" + "\x08\x23\x3e\x59\x74\x8f\xaa\xc5" + "\xe0\xfb\x16\x31\x4c\x67\x82\x9d" + "\xb8\xd3\xee\x09\x24\x3f\x5a\x75" + "\x90\xab\xc6\xe1\xfc\x17\x32\x4d" + "\x68\x83\x9e\xb9\xd4\xef\x0a\x25" + "\x40\x5b\x76\x91\xac\xc7\xe2\xfd" + "\x18\x33\x4e\x69\x84\x9f\xba\xd5" + "\xf0\x0b\x26\x41\x5c\x77\x92\xad" + "\xc8\xe3\xfe\x19\x34\x4f\x6a\x85" + "\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d" + "\x78\x93\xae\xc9\xe4\xff\x1a\x35" + "\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d" + "\x28\x43\x5e\x79\x94\xaf\xca\xe5" + "\x00\x1d\x3a\x57\x74\x91\xae\xcb" + "\xe8\x05\x22\x3f\x5c\x79\x96\xb3" + "\xd0\xed\x0a\x27\x44\x61\x7e\x9b" + "\xb8\xd5\xf2\x0f\x2c\x49\x66\x83" + "\xa0\xbd\xda\xf7\x14\x31\x4e\x6b" + "\x88\xa5\xc2\xdf\xfc\x19\x36\x53" + "\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b" + "\x58\x75\x92\xaf\xcc\xe9\x06\x23" + "\x40\x5d\x7a\x97\xb4\xd1\xee\x0b" + "\x28\x45\x62\x7f\x9c\xb9\xd6\xf3" + "\x10\x2d\x4a\x67\x84\xa1\xbe\xdb" + "\xf8\x15\x32\x4f\x6c\x89\xa6\xc3" + "\xe0\xfd\x1a\x37\x54\x71\x8e\xab" + "\xc8\xe5\x02\x1f\x3c\x59\x76\x93" + "\xb0\xcd\xea\x07\x24\x41\x5e\x7b" + "\x98\xb5\xd2\xef\x0c\x29\x46\x63" + "\x80\x9d\xba\xd7\xf4\x11\x2e\x4b" + "\x68\x85\xa2\xbf\xdc\xf9\x16\x33" + "\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b" + "\x38\x55\x72\x8f\xac\xc9\xe6\x03" + "\x20\x3d\x5a\x77\x94\xb1\xce\xeb" + "\x08\x25\x42\x5f\x7c\x99\xb6\xd3" + "\xf0\x0d\x2a\x47\x64\x81\x9e\xbb" + "\xd8\xf5\x12\x2f\x4c\x69\x86\xa3" + "\xc0\xdd\xfa\x17\x34\x51\x6e\x8b" + "\xa8\xc5\xe2\xff\x1c\x39\x56\x73" + "\x90\xad\xca\xe7\x04\x21\x3e\x5b" + "\x78\x95\xb2\xcf\xec\x09\x26\x43" + "\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b" + "\x48\x65\x82\x9f\xbc\xd9\xf6\x13" + "\x30\x4d\x6a\x87\xa4\xc1\xde\xfb" + "\x18\x35\x52\x6f\x8c\xa9\xc6\xe3" + "\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9" + "\xf8\x17\x36\x55\x74\x93\xb2\xd1" + "\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9" + "\xe8\x07\x26\x45\x64\x83\xa2\xc1" + "\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9" + "\xd8\xf7\x16\x35\x54\x73\x92\xb1" + "\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9" + "\xc8\xe7\x06\x25\x44\x63\x82\xa1" + "\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99" + "\xb8\xd7\xf6\x15\x34\x53\x72\x91" + "\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89" + "\xa8\xc7\xe6\x05\x24\x43\x62\x81" + "\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79" + "\x98\xb7\xd6\xf5\x14\x33\x52\x71" + "\x90\xaf\xce\xed\x0c\x2b\x4a\x69" + "\x88\xa7\xc6\xe5\x04\x23\x42\x61" + "\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59" + "\x78\x97\xb6\xd5\xf4\x13\x32\x51" + "\x70\x8f\xae\xcd\xec\x0b\x2a\x49" + "\x68\x87\xa6\xc5\xe4\x03\x22\x41" + "\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39" + "\x58\x77\x96\xb5\xd4\xf3\x12\x31" + "\x50\x6f\x8e\xad\xcc\xeb\x0a\x29" + "\x48\x67\x86\xa5\xc4\xe3\x02\x21" + "\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19" + "\x38\x57\x76\x95\xb4\xd3\xf2\x11" + "\x30\x4f\x6e\x8d\xac\xcb\xea\x09" + "\x28\x47\x66\x85\xa4\xc3\xe2\x01" + "\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9" + "\x18\x37\x56\x75\x94\xb3\xd2\xf1" + "\x10\x2f\x4e\x6d\x8c\xab\xca\xe9" + "\x08\x27\x46\x65\x84\xa3\xc2\xe1" + "\x00\x21\x42\x63", + .ilen = 4100, + .result = + "\xf0\x5c\x74\xad\x4e\xbc\x99\xe2" + "\xae\xff\x91\x3a\x44\xcf\x38\x32" + "\x1e\xad\xa7\xcd\xa1\x39\x95\xaa" + "\x10\xb1\xb3\x2e\x04\x31\x8f\x86" + "\xf2\x62\x74\x70\x0c\xa4\x46\x08" + "\xa8\xb7\x99\xa8\xe9\xd2\x73\x79" + "\x7e\x6e\xd4\x8f\x1e\xc7\x8e\x31" + "\x0b\xfa\x4b\xce\xfd\xf3\x57\x71" + "\xe9\x46\x03\xa5\x3d\x34\x00\xe2" + "\x18\xff\x75\x6d\x06\x2d\x00\xab" + "\xb9\x3e\x6c\x59\xc5\x84\x06\xb5" + "\x8b\xd0\x89\x9c\x4a\x79\x16\xc6" + "\x3d\x74\x54\xfa\x44\xcd\x23\x26" + "\x5c\xcf\x7e\x28\x92\x32\xbf\xdf" + "\xa7\x20\x3c\x74\x58\x2a\x9a\xde" + "\x61\x00\x1c\x4f\xff\x59\xc4\x22" + "\xac\x3c\xd0\xe8\x6c\xf9\x97\x1b" + "\x58\x9b\xad\x71\xe8\xa9\xb5\x0d" + "\xee\x2f\x04\x1f\x7f\xbc\x99\xee" + "\x84\xff\x42\x60\xdc\x3a\x18\xa5" + "\x81\xf9\xef\xdc\x7a\x0f\x65\x41" + "\x2f\xa3\xd3\xf9\xc2\xcb\xc0\x4d" + "\x8f\xd3\x76\x96\xad\x49\x6d\x38" + "\x3d\x39\x0b\x6c\x80\xb7\x54\x69" + "\xf0\x2c\x90\x02\x29\x0d\x1c\x12" + "\xad\x55\xc3\x8b\x68\xd9\xcc\xb3" + "\xb2\x64\x33\x90\x5e\xca\x4b\xe2" + "\xfb\x75\xdc\x63\xf7\x9f\x82\x74" + "\xf0\xc9\xaa\x7f\xe9\x2a\x9b\x33" + "\xbc\x88\x00\x7f\xca\xb2\x1f\x14" + "\xdb\xc5\x8e\x7b\x11\x3c\x3e\x08" + "\xf3\x83\xe8\xe0\x94\x86\x2e\x92" + "\x78\x6b\x01\xc9\xc7\x83\xba\x21" + "\x6a\x25\x15\x33\x4e\x45\x08\xec" + "\x35\xdb\xe0\x6e\x31\x51\x79\xa9" + "\x42\x44\x65\xc1\xa0\xf1\xf9\x2a" + "\x70\xd5\xb6\xc6\xc1\x8c\x39\xfc" + "\x25\xa6\x55\xd9\xdd\x2d\x4c\xec" + "\x49\xc6\xeb\x0e\xa8\x25\x2a\x16" + "\x1b\x66\x84\xda\xe2\x92\xe5\xc0" + "\xc8\x53\x07\xaf\x80\x84\xec\xfd" + "\xcd\xd1\x6e\xcd\x6f\x6a\xf5\x36" + "\xc5\x15\xe5\x25\x7d\x77\xd1\x1a" + "\x93\x36\xa9\xcf\x7c\xa4\x54\x4a" + "\x06\x51\x48\x4e\xf6\x59\x87\xd2" + "\x04\x02\xef\xd3\x44\xde\x76\x31" + "\xb3\x34\x17\x1b\x9d\x66\x11\x9f" + "\x1e\xcc\x17\xe9\xc7\x3c\x1b\xe7" + "\xcb\x50\x08\xfc\xdc\x2b\x24\xdb" + "\x65\x83\xd0\x3b\xe3\x30\xea\x94" + "\x6c\xe7\xe8\x35\x32\xc7\xdb\x64" + "\xb4\x01\xab\x36\x2c\x77\x13\xaf" + "\xf8\x2b\x88\x3f\x54\x39\xc4\x44" + "\xfe\xef\x6f\x68\x34\xbe\x0f\x05" + "\x16\x6d\xf6\x0a\x30\xe7\xe3\xed" + "\xc4\xde\x3c\x1b\x13\xd8\xdb\xfe" + "\x41\x62\xe5\x28\xd4\x8d\xa3\xc7" + "\x93\x97\xc6\x48\x45\x1d\x9f\x83" + "\xdf\x4b\x40\x3e\x42\x25\x87\x80" + "\x4c\x7d\xa8\xd4\x98\x23\x95\x75" + "\x41\x8c\xda\x41\x9b\xd4\xa7\x06" + "\xb5\xf1\x71\x09\x53\xbe\xca\xbf" + "\x32\x03\xed\xf0\x50\x1c\x56\x39" + "\x5b\xa4\x75\x18\xf7\x9b\x58\xef" + "\x53\xfc\x2a\x38\x23\x15\x75\xcd" + "\x45\xe5\x5a\x82\x55\xba\x21\xfa" + "\xd4\xbd\xc6\x94\x7c\xc5\x80\x12" + "\xf7\x4b\x32\xc4\x9a\x82\xd8\x28" + "\x8f\xd9\xc2\x0f\x60\x03\xbe\x5e" + "\x21\xd6\x5f\x58\xbf\x5c\xb1\x32" + "\x82\x8d\xa9\xe5\xf2\x66\x1a\xc0" + "\xa0\xbc\x58\x2f\x71\xf5\x2f\xed" + "\xd1\x26\xb9\xd8\x49\x5a\x07\x19" + "\x01\x7c\x59\xb0\xf8\xa4\xb7\xd3" + "\x7b\x1a\x8c\x38\xf4\x50\xa4\x59" + "\xb0\xcc\x41\x0b\x88\x7f\xe5\x31" + "\xb3\x42\xba\xa2\x7e\xd4\x32\x71" + "\x45\x87\x48\xa9\xc2\xf2\x89\xb3" + "\xe4\xa7\x7e\x52\x15\x61\xfa\xfe" + "\xc9\xdd\x81\xeb\x13\xab\xab\xc3" + "\x98\x59\xd8\x16\x3d\x14\x7a\x1c" + "\x3c\x41\x9a\x16\x16\x9b\xd2\xd2" + "\x69\x3a\x29\x23\xac\x86\x32\xa5" + "\x48\x9c\x9e\xf3\x47\x77\x81\x70" + "\x24\xe8\x85\xd2\xf5\xb5\xfa\xff" + "\x59\x6a\xd3\x50\x59\x43\x59\xde" + "\xd9\xf1\x55\xa5\x0c\xc3\x1a\x1a" + "\x18\x34\x0d\x1a\x63\x33\xed\x10" + "\xe0\x1d\x2a\x18\xd2\xc0\x54\xa8" + "\xca\xb5\x9a\xd3\xdd\xca\x45\x84" + "\x50\xe7\x0f\xfe\xa4\x99\x5a\xbe" + "\x43\x2d\x9a\xcb\x92\x3f\x5a\x1d" + "\x85\xd8\xc9\xdf\x68\xc9\x12\x80" + "\x56\x0c\xdc\x00\xdc\x3a\x7d\x9d" + "\xa3\xa2\xe8\x4d\xbf\xf9\x70\xa0" + "\xa4\x13\x4f\x6b\xaf\x0a\x89\x7f" + "\xda\xf0\xbf\x9b\xc8\x1d\xe5\xf8" + "\x2e\x8b\x07\xb5\x73\x1b\xcc\xa2" + "\xa6\xad\x30\xbc\x78\x3c\x5b\x10" + "\xfa\x5e\x62\x2d\x9e\x64\xb3\x33" + "\xce\xf9\x1f\x86\xe7\x8b\xa2\xb8" + "\xe8\x99\x57\x8c\x11\xed\x66\xd9" + "\x3c\x72\xb9\xc3\xe6\x4e\x17\x3a" + "\x6a\xcb\x42\x24\x06\xed\x3e\x4e" + "\xa3\xe8\x6a\x94\xda\x0d\x4e\xd5" + "\x14\x19\xcf\xb6\x26\xd8\x2e\xcc" + "\x64\x76\x38\x49\x4d\xfe\x30\x6d" + "\xe4\xc8\x8c\x7b\xc4\xe0\x35\xba" + "\x22\x6e\x76\xe1\x1a\xf2\x53\xc3" + "\x28\xa2\x82\x1f\x61\x69\xad\xc1" + "\x7b\x28\x4b\x1e\x6c\x85\x95\x9b" + "\x51\xb5\x17\x7f\x12\x69\x8c\x24" + "\xd5\xc7\x5a\x5a\x11\x54\xff\x5a" + "\xf7\x16\xc3\x91\xa6\xf0\xdc\x0a" + "\xb6\xa7\x4a\x0d\x7a\x58\xfe\xa5" + "\xf5\xcb\x8f\x7b\x0e\xea\x57\xe7" + "\xbd\x79\xd6\x1c\x88\x23\x6c\xf2" + "\x4d\x29\x77\x53\x35\x6a\x00\x8d" + "\xcd\xa3\x58\xbe\x77\x99\x18\xf8" + "\xe6\xe1\x8f\xe9\x37\x8f\xe3\xe2" + "\x5a\x8a\x93\x25\xaf\xf3\x78\x80" + "\xbe\xa6\x1b\xc6\xac\x8b\x1c\x91" + "\x58\xe1\x9f\x89\x35\x9d\x1d\x21" + "\x29\x9f\xf4\x99\x02\x27\x0f\xa8" + "\x4f\x79\x94\x2b\x33\x2c\xda\xa2" + "\x26\x39\x83\x94\xef\x27\xd8\x53" + "\x8f\x66\x0d\xe4\x41\x7d\x34\xcd" + "\x43\x7c\x95\x0a\x53\xef\x66\xda" + "\x7e\x9b\xf3\x93\xaf\xd0\x73\x71" + "\xba\x40\x9b\x74\xf8\xd7\xd7\x41" + "\x6d\xaf\x72\x9c\x8d\x21\x87\x3c" + "\xfd\x0a\x90\xa9\x47\x96\x9e\xd3" + "\x88\xee\x73\xcf\x66\x2f\x52\x56" + "\x6d\xa9\x80\x4c\xe2\x6f\x62\x88" + "\x3f\x0e\x54\x17\x48\x80\x5d\xd3" + "\xc3\xda\x25\x3d\xa1\xc8\xcb\x9f" + "\x9b\x70\xb3\xa1\xeb\x04\x52\xa1" + "\xf2\x22\x0f\xfc\xc8\x18\xfa\xf9" + "\x85\x9c\xf1\xac\xeb\x0c\x02\x46" + "\x75\xd2\xf5\x2c\xe3\xd2\x59\x94" + "\x12\xf3\x3c\xfc\xd7\x92\xfa\x36" + "\xba\x61\x34\x38\x7c\xda\x48\x3e" + "\x08\xc9\x39\x23\x5e\x02\x2c\x1a" + "\x18\x7e\xb4\xd9\xfd\x9e\x40\x02" + "\xb1\x33\x37\x32\xe7\xde\xd6\xd0" + "\x7c\x58\x65\x4b\xf8\x34\x27\x9c" + "\x44\xb4\xbd\xe9\xe9\x4c\x78\x7d" + "\x4b\x9f\xce\xb1\xcd\x47\xa5\x37" + "\xe5\x6d\xbd\xb9\x43\x94\x0a\xd4" + "\xd6\xf9\x04\x5f\xb5\x66\x6c\x1a" + "\x35\x12\xe3\x36\x28\x27\x36\x58" + "\x01\x2b\x79\xe4\xba\x6d\x10\x7d" + "\x65\xdf\x84\x95\xf4\xd5\xb6\x8f" + "\x2b\x9f\x96\x00\x86\x60\xf0\x21" + "\x76\xa8\x6a\x8c\x28\x1c\xb3\x6b" + "\x97\xd7\xb6\x53\x2a\xcc\xab\x40" + "\x9d\x62\x79\x58\x52\xe6\x65\xb7" + "\xab\x55\x67\x9c\x89\x7c\x03\xb0" + "\x73\x59\xc5\x81\xf5\x18\x17\x5c" + "\x89\xf3\x78\x35\x44\x62\x78\x72" + "\xd0\x96\xeb\x31\xe7\x87\x77\x14" + "\x99\x51\xf2\x59\x26\x9e\xb5\xa6" + "\x45\xfe\x6e\xbd\x07\x4c\x94\x5a" + "\xa5\x7d\xfc\xf1\x2b\x77\xe2\xfe" + "\x17\xd4\x84\xa0\xac\xb5\xc7\xda" + "\xa9\x1a\xb6\xf3\x74\x11\xb4\x9d" + "\xfb\x79\x2e\x04\x2d\x50\x28\x83" + "\xbf\xc6\x52\xd3\x34\xd6\xe8\x7a" + "\xb6\xea\xe7\xa8\x6c\x15\x1e\x2c" + "\x57\xbc\x48\x4e\x5f\x5c\xb6\x92" + "\xd2\x49\x77\x81\x6d\x90\x70\xae" + "\x98\xa1\x03\x0d\x6b\xb9\x77\x14" + "\xf1\x4e\x23\xd3\xf8\x68\xbd\xc2" + "\xfe\x04\xb7\x5c\xc5\x17\x60\x8f" + "\x65\x54\xa4\x7a\x42\xdc\x18\x0d" + "\xb5\xcf\x0f\xd3\xc7\x91\x66\x1b" + "\x45\x42\x27\x75\x50\xe5\xee\xb8" + "\x7f\x33\x2c\xba\x4a\x92\x4d\x2c" + "\x3c\xe3\x0d\x80\x01\xba\x0d\x29" + "\xd8\x3c\xe9\x13\x16\x57\xe6\xea" + "\x94\x52\xe7\x00\x4d\x30\xb0\x0f" + "\x35\xb8\xb8\xa7\xb1\xb5\x3b\x44" + "\xe1\x2f\xfd\x88\xed\x43\xe7\x52" + "\x10\x93\xb3\x8a\x30\x6b\x0a\xf7" + "\x23\xc6\x50\x9d\x4a\xb0\xde\xc3" + "\xdc\x9b\x2f\x01\x56\x36\x09\xc5" + "\x2f\x6b\xfe\xf1\xd8\x27\x45\x03" + "\x30\x5e\x5c\x5b\xb4\x62\x0e\x1a" + "\xa9\x21\x2b\x92\x94\x87\x62\x57" + "\x4c\x10\x74\x1a\xf1\x0a\xc5\x84" + "\x3b\x9e\x72\x02\xd7\xcc\x09\x56" + "\xbd\x54\xc1\xf0\xc3\xe3\xb3\xf8" + "\xd2\x0d\x61\xcb\xef\xce\x0d\x05" + "\xb0\x98\xd9\x8e\x4f\xf9\xbc\x93" + "\xa6\xea\xc8\xcf\x10\x53\x4b\xf1" + "\xec\xfc\x89\xf9\x64\xb0\x22\xbf" + "\x9e\x55\x46\x9f\x7c\x50\x8e\x84" + "\x54\x20\x98\xd7\x6c\x40\x1e\xdb" + "\x69\x34\x78\x61\x24\x21\x9c\x8a" + "\xb3\x62\x31\x8b\x6e\xf5\x2a\x35" + "\x86\x13\xb1\x6c\x64\x2e\x41\xa5" + "\x05\xf2\x42\xba\xd2\x3a\x0d\x8e" + "\x8a\x59\x94\x3c\xcf\x36\x27\x82" + "\xc2\x45\xee\x58\xcd\x88\xb4\xec" + "\xde\xb2\x96\x0a\xaf\x38\x6f\x88" + "\xd7\xd8\xe1\xdf\xb9\x96\xa9\x0a" + "\xb1\x95\x28\x86\x20\xe9\x17\x49" + "\xa2\x29\x38\xaa\xa5\xe9\x6e\xf1" + "\x19\x27\xc0\xd5\x2a\x22\xc3\x0b" + "\xdb\x7c\x73\x10\xb9\xba\x89\x76" + "\x54\xae\x7d\x71\xb3\x93\xf6\x32" + "\xe6\x47\x43\x55\xac\xa0\x0d\xc2" + "\x93\x27\x4a\x8e\x0e\x74\x15\xc7" + "\x0b\x85\xd9\x0c\xa9\x30\x7a\x3e" + "\xea\x8f\x85\x6d\x3a\x12\x4f\x72" + "\x69\x58\x7a\x80\xbb\xb5\x97\xf3" + "\xcf\x70\xd2\x5d\xdd\x4d\x21\x79" + "\x54\x4d\xe4\x05\xe8\xbd\xc2\x62" + "\xb1\x3b\x77\x1c\xd6\x5c\xf3\xa0" + "\x79\x00\xa8\x6c\x29\xd9\x18\x24" + "\x36\xa2\x46\xc0\x96\x65\x7f\xbd" + "\x2a\xed\x36\x16\x0c\xaa\x9f\xf4" + "\xc5\xb4\xe2\x12\xed\x69\xed\x4f" + "\x26\x2c\x39\x52\x89\x98\xe7\x2c" + "\x99\xa4\x9e\xa3\x9b\x99\x46\x7a" + "\x3a\xdc\xa8\x59\xa3\xdb\xc3\x3b" + "\x95\x0d\x3b\x09\x6e\xee\x83\x5d" + "\x32\x4d\xed\xab\xfa\x98\x14\x4e" + "\xc3\x15\x45\x53\x61\xc4\x93\xbd" + "\x90\xf4\x99\x95\x4c\xe6\x76\x92" + "\x29\x90\x46\x30\x92\x69\x7d\x13" + "\xf2\xa5\xcd\x69\x49\x44\xb2\x0f" + "\x63\x40\x36\x5f\x09\xe2\x78\xf8" + "\x91\xe3\xe2\xfa\x10\xf7\xc8\x24" + "\xa8\x89\x32\x5c\x37\x25\x1d\xb2" + "\xea\x17\x8a\x0a\xa9\x64\xc3\x7c" + "\x3c\x7c\xbd\xc6\x79\x34\xe7\xe2" + "\x85\x8e\xbf\xf8\xde\x92\xa0\xae" + "\x20\xc4\xf6\xbb\x1f\x38\x19\x0e" + "\xe8\x79\x9c\xa1\x23\xe9\x54\x7e" + "\x37\x2f\xe2\x94\x32\xaf\xa0\x23" + "\x49\xe4\xc0\xb3\xac\x00\x8f\x36" + "\x05\xc4\xa6\x96\xec\x05\x98\x4f" + "\x96\x67\x57\x1f\x20\x86\x1b\x2d" + "\x69\xe4\x29\x93\x66\x5f\xaf\x6b" + "\x88\x26\x2c\x67\x02\x4b\x52\xd0" + "\x83\x7a\x43\x1f\xc0\x71\x15\x25" + "\x77\x65\x08\x60\x11\x76\x4c\x8d" + "\xed\xa9\x27\xc6\xb1\x2a\x2c\x6a" + "\x4a\x97\xf5\xc6\xb7\x70\x42\xd3" + "\x03\xd1\x24\x95\xec\x6d\xab\x38" + "\x72\xce\xe2\x8b\x33\xd7\x51\x09" + "\xdc\x45\xe0\x09\x96\x32\xf3\xc4" + "\x84\xdc\x73\x73\x2d\x1b\x11\x98" + "\xc5\x0e\x69\x28\x94\xc7\xb5\x4d" + "\xc8\x8a\xd0\xaa\x13\x2e\x18\x74" + "\xdd\xd1\x1e\xf3\x90\xe8\xfc\x9a" + "\x72\x4a\x0e\xd1\xe4\xfb\x0d\x96" + "\xd1\x0c\x79\x85\x1b\x1c\xfe\xe1" + "\x62\x8f\x7a\x73\x32\xab\xc8\x18" + "\x69\xe3\x34\x30\xdf\x13\xa6\xe5" + "\xe8\x0e\x67\x7f\x81\x11\xb4\x60" + "\xc7\xbd\x79\x65\x50\xdc\xc4\x5b" + "\xde\x39\xa4\x01\x72\x63\xf3\xd1" + "\x64\x4e\xdf\xfc\x27\x92\x37\x0d" + "\x57\xcd\x11\x4f\x11\x04\x8e\x1d" + "\x16\xf7\xcd\x92\x9a\x99\x30\x14" + "\xf1\x7c\x67\x1b\x1f\x41\x0b\xe8" + "\x32\xe8\xb8\xc1\x4f\x54\x86\x4f" + "\xe5\x79\x81\x73\xcd\x43\x59\x68" + "\x73\x02\x3b\x78\x21\x72\x43\x00" + "\x49\x17\xf7\x00\xaf\x68\x24\x53" + "\x05\x0a\xc3\x33\xe0\x33\x3f\x69" + "\xd2\x84\x2f\x0b\xed\xde\x04\xf4" + "\x11\x94\x13\x69\x51\x09\x28\xde" + "\x57\x5c\xef\xdc\x9a\x49\x1c\x17" + "\x97\xf3\x96\xc1\x7f\x5d\x2e\x7d" + "\x55\xb8\xb3\x02\x09\xb3\x1f\xe7" + "\xc9\x8d\xa3\x36\x34\x8a\x77\x13" + "\x30\x63\x4c\xa5\xcd\xc3\xe0\x7e" + "\x05\xa1\x7b\x0c\xcb\x74\x47\x31" + "\x62\x03\x43\xf1\x87\xb4\xb0\x85" + "\x87\x8e\x4b\x25\xc7\xcf\xae\x4b" + "\x36\x46\x3e\x62\xbc\x6f\xeb\x5f" + "\x73\xac\xe6\x07\xee\xc1\xa1\xd6" + "\xc4\xab\xc9\xd6\x89\x45\xe1\xf1" + "\x04\x4e\x1a\x6f\xbb\x4f\x3a\xa3" + "\xa0\xcb\xa3\x0a\xd8\x71\x35\x55" + "\xe4\xbc\x2e\x04\x06\xe6\xff\x5b" + "\x1c\xc0\x11\x7c\xc5\x17\xf3\x38" + "\xcf\xe9\xba\x0f\x0e\xef\x02\xc2" + "\x8d\xc6\xbc\x4b\x67\x20\x95\xd7" + "\x2c\x45\x5b\x86\x44\x8c\x6f\x2e" + "\x7e\x9f\x1c\x77\xba\x6b\x0e\xa3" + "\x69\xdc\xab\x24\x57\x60\x47\xc1" + "\xd1\xa5\x9d\x23\xe6\xb1\x37\xfe" + "\x93\xd2\x4c\x46\xf9\x0c\xc6\xfb" + "\xd6\x9d\x99\x69\xab\x7a\x07\x0c" + "\x65\xe7\xc4\x08\x96\xe2\xa5\x01" + "\x3f\x46\x07\x05\x7e\xe8\x9a\x90" + "\x50\xdc\xe9\x7a\xea\xa1\x39\x6e" + "\x66\xe4\x6f\xa5\x5f\xb2\xd9\x5b" + "\xf5\xdb\x2a\x32\xf0\x11\x6f\x7c" + "\x26\x10\x8f\x3d\x80\xe9\x58\xf7" + "\xe0\xa8\x57\xf8\xdb\x0e\xce\x99" + "\x63\x19\x3d\xd5\xec\x1b\x77\x69" + "\x98\xf6\xe4\x5f\x67\x17\x4b\x09" + "\x85\x62\x82\x70\x18\xe2\x9a\x78" + "\xe2\x62\xbd\xb4\xf1\x42\xc6\xfb" + "\x08\xd0\xbd\xeb\x4e\x09\xf2\xc8" + "\x1e\xdc\x3d\x32\x21\x56\x9c\x4f" + "\x35\xf3\x61\x06\x72\x84\xc4\x32" + "\xf2\xf1\xfa\x0b\x2f\xc3\xdb\x02" + "\x04\xc2\xde\x57\x64\x60\x8d\xcf" + "\xcb\x86\x5d\x97\x3e\xb1\x9c\x01" + "\xd6\x28\x8f\x99\xbc\x46\xeb\x05" + "\xaf\x7e\xb8\x21\x2a\x56\x85\x1c" + "\xb3\x71\xa0\xde\xca\x96\xf1\x78" + "\x49\xa2\x99\x81\x80\x5c\x01\xf5" + "\xa0\xa2\x56\x63\xe2\x70\x07\xa5" + "\x95\xd6\x85\xeb\x36\x9e\xa9\x51" + "\x66\x56\x5f\x1d\x02\x19\xe2\xf6" + "\x4f\x73\x38\x09\x75\x64\x48\xe0" + "\xf1\x7e\x0e\xe8\x9d\xf9\xed\x94" + "\xfe\x16\x26\x62\x49\x74\xf4\xb0" + "\xd4\xa9\x6c\xb0\xfd\x53\xe9\x81" + "\xe0\x7a\xbf\xcf\xb5\xc4\x01\x81" + "\x79\x99\x77\x01\x3b\xe9\xa2\xb6" + "\xe6\x6a\x8a\x9e\x56\x1c\x8d\x1e" + "\x8f\x06\x55\x2c\x6c\xdc\x92\x87" + "\x64\x3b\x4b\x19\xa1\x13\x64\x1d" + "\x4a\xe9\xc0\x00\xb8\x95\xef\x6b" + "\x1a\x86\x6d\x37\x52\x02\xc2\xe0" + "\xc8\xbb\x42\x0c\x02\x21\x4a\xc9" + "\xef\xa0\x54\xe4\x5e\x16\x53\x81" + "\x70\x62\x10\xaf\xde\xb8\xb5\xd3" + "\xe8\x5e\x6c\xc3\x8a\x3e\x18\x07" + "\xf2\x2f\x7d\xa7\xe1\x3d\x4e\xb4" + "\x26\xa7\xa3\x93\x86\xb2\x04\x1e" + "\x53\x5d\x86\xd6\xde\x65\xca\xe3" + "\x4e\xc1\xcf\xef\xc8\x70\x1b\x83" + "\x13\xdd\x18\x8b\x0d\x76\xd2\xf6" + "\x37\x7a\x93\x7a\x50\x11\x9f\x96" + "\x86\x25\xfd\xac\xdc\xbe\x18\x93" + "\x19\x6b\xec\x58\x4f\xb9\x75\xa7" + "\xdd\x3f\x2f\xec\xc8\x5a\x84\xab" + "\xd5\xe4\x8a\x07\xf6\x4d\x23\xd6" + "\x03\xfb\x03\x6a\xea\x66\xbf\xd4" + "\xb1\x34\xfb\x78\xe9\x55\xdc\x7c" + "\x3d\x9c\xe5\x9a\xac\xc3\x7a\x80" + "\x24\x6d\xa0\xef\x25\x7c\xb7\xea" + "\xce\x4d\x5f\x18\x60\xce\x87\x22" + "\x66\x2f\xd5\xdd\xdd\x02\x21\x75" + "\x82\xa0\x1f\x58\xc6\xd3\x62\xf7" + "\x32\xd8\xaf\x1e\x07\x77\x51\x96" + "\xd5\x6b\x1e\x7e\x80\x02\xe8\x67" + "\xea\x17\x0b\x10\xd2\x3f\x28\x25" + "\x4f\x05\x77\x02\x14\x69\xf0\x2c" + "\xbe\x0c\xf1\x74\x30\xd1\xb9\x9b" + "\xfc\x8c\xbb\x04\x16\xd9\xba\xc3" + "\xbc\x91\x8a\xc4\x30\xa4\xb0\x12" + "\x4c\x21\x87\xcb\xc9\x1d\x16\x96" + "\x07\x6f\x23\x54\xb9\x6f\x79\xe5" + "\x64\xc0\x64\xda\xb1\xae\xdd\x60" + "\x6c\x1a\x9d\xd3\x04\x8e\x45\xb0" + "\x92\x61\xd0\x48\x81\xed\x5e\x1d" + "\xa0\xc9\xa4\x33\xc7\x13\x51\x5d" + "\x7f\x83\x73\xb6\x70\x18\x65\x3e" + "\x2f\x0e\x7a\x12\x39\x98\xab\xd8" + "\x7e\x6f\xa3\xd1\xba\x56\xad\xbd" + "\xf0\x03\x01\x1c\x85\x35\x9f\xeb" + "\x19\x63\xa1\xaf\xfe\x2d\x35\x50" + "\x39\xa0\x65\x7c\x95\x7e\x6b\xfe" + "\xc1\xac\x07\x7c\x98\x4f\xbe\x57" + "\xa7\x22\xec\xe2\x7e\x29\x09\x53" + "\xe8\xbf\xb4\x7e\x3f\x8f\xfc\x14" + "\xce\x54\xf9\x18\x58\xb5\xff\x44" + "\x05\x9d\xce\x1b\xb6\x82\x23\xc8" + "\x2e\xbc\x69\xbb\x4a\x29\x0f\x65" + "\x94\xf0\x63\x06\x0e\xef\x8c\xbd" + "\xff\xfd\xb0\x21\x6e\x57\x05\x75" + "\xda\xd5\xc4\xeb\x8d\x32\xf7\x50" + "\xd3\x6f\x22\xed\x5f\x8e\xa2\x5b" + "\x80\x8c\xc8\x78\x40\x24\x4b\x89" + "\x30\xce\x7a\x97\x0e\xc4\xaf\xef" + "\x9b\xb4\xcd\x66\x74\x14\x04\x2b" + "\xf7\xce\x0b\x1c\x6e\xc2\x78\x8c" + "\xca\xc5\xd0\x1c\x95\x4a\x91\x2d" + "\xa7\x20\xeb\x86\x52\xb7\x67\xd8" + "\x0c\xd6\x04\x14\xde\x51\x74\x75" + "\xe7\x11\xb4\x87\xa3\x3d\x2d\xad" + "\x4f\xef\xa0\x0f\x70\x00\x6d\x13" + "\x19\x1d\x41\x50\xe9\xd8\xf0\x32" + "\x71\xbc\xd3\x11\xf2\xac\xbe\xaf" + "\x75\x46\x65\x4e\x07\x34\x37\xa3" + "\x89\xfe\x75\xd4\x70\x4c\xc6\x3f" + "\x69\x24\x0e\x38\x67\x43\x8c\xde" + "\x06\xb5\xb8\xe7\xc4\xf0\x41\x8f" + "\xf0\xbd\x2f\x0b\xb9\x18\xf8\xde" + "\x64\xb1\xdb\xee\x00\x50\x77\xe1" + "\xc7\xff\xa6\xfa\xdd\x70\xf4\xe3" + "\x93\xe9\x77\x35\x3d\x4b\x2f\x2b" + "\x6d\x55\xf0\xfc\x88\x54\x4e\x89" + "\xc1\x8a\x23\x31\x2d\x14\x2a\xb8" + "\x1b\x15\xdd\x9e\x6e\x7b\xda\x05" + "\x91\x7d\x62\x64\x96\x72\xde\xfc" + "\xc1\xec\xf0\x23\x51\x6f\xdb\x5b" + "\x1d\x08\x57\xce\x09\xb8\xf6\xcd" + "\x8d\x95\xf2\x20\xbf\x0f\x20\x57" + "\x98\x81\x84\x4f\x15\x5c\x76\xe7" + "\x3e\x0a\x3a\x6c\xc4\x8a\xbe\x78" + "\x74\x77\xc3\x09\x4b\x5d\x48\xe4" + "\xc8\xcb\x0b\xea\x17\x28\xcf\xcf" + "\x31\x32\x44\xa4\xe5\x0e\x1a\x98" + "\x94\xc4\xf0\xff\xae\x3e\x44\xe8" + "\xa5\xb3\xb5\x37\x2f\xe8\xaf\x6f" + "\x28\xc1\x37\x5f\x31\xd2\xb9\x33" + "\xb1\xb2\x52\x94\x75\x2c\x29\x59" + "\x06\xc2\x25\xe8\x71\x65\x4e\xed" + "\xc0\x9c\xb1\xbb\x25\xdc\x6c\xe7" + "\x4b\xa5\x7a\x54\x7a\x60\xff\x7a" + "\xe0\x50\x40\x96\x35\x63\xe4\x0b" + "\x76\xbd\xa4\x65\x00\x1b\x57\x88" + "\xae\xed\x39\x88\x42\x11\x3c\xed" + "\x85\x67\x7d\xb9\x68\x82\xe9\x43" + "\x3c\x47\x53\xfa\xe8\xf8\x9f\x1f" + "\x9f\xef\x0f\xf7\x30\xd9\x30\x0e" + "\xb9\x9f\x69\x18\x2f\x7e\xf8\xf8" + "\xf8\x8c\x0f\xd4\x02\x4d\xea\xcd" + "\x0a\x9c\x6f\x71\x6d\x5a\x4c\x60" + "\xce\x20\x56\x32\xc6\xc5\x99\x1f" + "\x09\xe6\x4e\x18\x1a\x15\x13\xa8" + "\x7d\xb1\x6b\xc0\xb2\x6d\xf8\x26" + "\x66\xf8\x3d\x18\x74\x70\x66\x7a" + "\x34\x17\xde\xba\x47\xf1\x06\x18" + "\xcb\xaf\xeb\x4a\x1e\x8f\xa7\x77" + "\xe0\x3b\x78\x62\x66\xc9\x10\xea" + "\x1f\xb7\x29\x0a\x45\xa1\x1d\x1e" + "\x1d\xe2\x65\x61\x50\x9c\xd7\x05" + "\xf2\x0b\x5b\x12\x61\x02\xc8\xe5" + "\x63\x4f\x20\x0c\x07\x17\x33\x5e" + "\x03\x9a\x53\x0f\x2e\x55\xfe\x50" + "\x43\x7d\xd0\xb6\x7e\x5a\xda\xae" + "\x58\xef\x15\xa9\x83\xd9\x46\xb1" + "\x42\xaa\xf5\x02\x6c\xce\x92\x06" + "\x1b\xdb\x66\x45\x91\x79\xc2\x2d" + "\xe6\x53\xd3\x14\xfd\xbb\x44\x63" + "\xc6\xd7\x3d\x7a\x0c\x75\x78\x9d" + "\x5c\xa6\x39\xb3\xe5\x63\xca\x8b" + "\xfe\xd3\xef\x60\x83\xf6\x8e\x70" + "\xb6\x67\xc7\x77\xed\x23\xef\x4c" + "\xf0\xed\x2d\x07\x59\x6f\xc1\x01" + "\x34\x37\x08\xab\xd9\x1f\x09\xb1" + "\xce\x5b\x17\xff\x74\xf8\x9c\xd5" + "\x2c\x56\x39\x79\x0f\x69\x44\x75" + "\x58\x27\x01\xc4\xbf\xa7\xa1\x1d" + "\x90\x17\x77\x86\x5a\x3f\xd9\xd1" + "\x0e\xa0\x10\xf8\xec\x1e\xa5\x7f" + "\x5e\x36\xd1\xe3\x04\x2c\x70\xf7" + "\x8e\xc0\x98\x2f\x6c\x94\x2b\x41" + "\xb7\x60\x00\xb7\x2e\xb8\x02\x8d" + "\xb8\xb0\xd3\x86\xba\x1d\xd7\x90" + "\xd6\xb6\xe1\xfc\xd7\xd8\x28\x06" + "\x63\x9b\xce\x61\x24\x79\xc0\x70" + "\x52\xd0\xb6\xd4\x28\x95\x24\x87" + "\x03\x1f\xb7\x9a\xda\xa3\xfb\x52" + "\x5b\x68\xe7\x4c\x8c\x24\xe1\x42" + "\xf7\xd5\xfd\xad\x06\x32\x9f\xba" + "\xc1\xfc\xdd\xc6\xfc\xfc\xb3\x38" + "\x74\x56\x58\x40\x02\x37\x52\x2c" + "\x55\xcc\xb3\x9e\x7a\xe9\xd4\x38" + "\x41\x5e\x0c\x35\xe2\x11\xd1\x13" + "\xf8\xb7\x8d\x72\x6b\x22\x2a\xb0" + "\xdb\x08\xba\x35\xb9\x3f\xc8\xd3" + "\x24\x90\xec\x58\xd2\x09\xc7\x2d" + "\xed\x38\x80\x36\x72\x43\x27\x49" + "\x4a\x80\x8a\xa2\xe8\xd3\xda\x30" + "\x7d\xb6\x82\x37\x86\x92\x86\x3e" + "\x08\xb2\x28\x5a\x55\x44\x24\x7d" + "\x40\x48\x8a\xb6\x89\x58\x08\xa0" + "\xd6\x6d\x3a\x17\xbf\xf6\x54\xa2" + "\xf5\xd3\x8c\x0f\x78\x12\x57\x8b" + "\xd5\xc2\xfd\x58\x5b\x7f\x38\xe3" + "\xcc\xb7\x7c\x48\xb3\x20\xe8\x81" + "\x14\x32\x45\x05\xe0\xdb\x9f\x75" + "\x85\xb4\x6a\xfc\x95\xe3\x54\x22" + "\x12\xee\x30\xfe\xd8\x30\xef\x34" + "\x50\xab\x46\x30\x98\x2f\xb7\xc0" + "\x15\xa2\x83\xb6\xf2\x06\x21\xa2" + "\xc3\x26\x37\x14\xd1\x4d\xb5\x10" + "\x52\x76\x4d\x6a\xee\xb5\x2b\x15" + "\xb7\xf9\x51\xe8\x2a\xaf\xc7\xfa" + "\x77\xaf\xb0\x05\x4d\xd1\x68\x8e" + "\x74\x05\x9f\x9d\x93\xa5\x3e\x7f" + "\x4e\x5f\x9d\xcb\x09\xc7\x83\xe3" + "\x02\x9d\x27\x1f\xef\x85\x05\x8d" + "\xec\x55\x88\x0f\x0d\x7c\x4c\xe8" + "\xa1\x75\xa0\xd8\x06\x47\x14\xef" + "\xaa\x61\xcf\x26\x15\xad\xd8\xa3" + "\xaa\x75\xf2\x78\x4a\x5a\x61\xdf" + "\x8b\xc7\x04\xbc\xb2\x32\xd2\x7e" + "\x42\xee\xb4\x2f\x51\xff\x7b\x2e" + "\xd3\x02\xe8\xdc\x5d\x0d\x50\xdc" + "\xae\xb7\x46\xf9\xa8\xe6\xd0\x16" + "\xcc\xe6\x2c\x81\xc7\xad\xe9\xf0" + "\x05\x72\x6d\x3d\x0a\x7a\xa9\x02" + "\xac\x82\x93\x6e\xb6\x1c\x28\xfc" + "\x44\x12\xfb\x73\x77\xd4\x13\x39" + "\x29\x88\x8a\xf3\x5c\xa6\x36\xa0" + "\x2a\xed\x7e\xb1\x1d\xd6\x4c\x6b" + "\x41\x01\x18\x5d\x5d\x07\x97\xa6" + "\x4b\xef\x31\x18\xea\xac\xb1\x84" + "\x21\xed\xda\x86", + .rlen = 4100, + .np = 2, + .tap = { 4064, 36 }, + }, +}; + +static struct cipher_testvec aes_ctr_dec_tv_template[] = { + { /* From RFC 3686 */ + .key = "\xae\x68\x52\xf8\x12\x10\x67\xcc" + "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e" + "\x00\x00\x00\x30", + .klen = 20, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79" + "\x2d\x61\x75\xa3\x26\x13\x11\xb8", + .ilen = 16, + .result = "Single block msg", + .rlen = 16, + }, { + .key = "\x7e\x24\x06\x78\x17\xfa\xe0\xd7" + "\x43\xd6\xce\x1f\x32\x53\x91\x63" + "\x00\x6c\xb6\xdb", + .klen = 20, + .iv = "\xc0\x54\x3b\x59\xda\x48\xd9\x0b", + .input = "\x51\x04\xa1\x06\x16\x8a\x72\xd9" + "\x79\x0d\x41\xee\x8e\xda\xd3\x88" + "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8" + "\xfc\xe6\x30\xdf\x91\x41\xbe\x28", + .ilen = 32, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .rlen = 32, + }, { + .key = "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79" + "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed" + "\x86\x3d\x06\xcc\xfd\xb7\x85\x15" + "\x00\x00\x00\x48", + .klen = 28, + .iv = "\x36\x73\x3c\x14\x7d\x6d\x93\xcb", + .input = "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8" + "\x4e\x79\x35\xa0\x03\xcb\xe9\x28", + .ilen = 16, + .result = "Single block msg", + .rlen = 16, + }, { + .key = "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c" + "\x19\xe7\x34\x08\x19\xe0\xf6\x9c" + "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a" + "\x00\x96\xb0\x3b", + .klen = 28, + .iv = "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d", + .input = "\x45\x32\x43\xfc\x60\x9b\x23\x32" + "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f" + "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c" + "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00", + .ilen = 32, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .rlen = 32, + }, { + .key = "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f" + "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c" + "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3" + "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04" + "\x00\x00\x00\x60", + .klen = 36, + .iv = "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2", + .input = "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7" + "\x56\x08\x63\xdc\x71\xe3\xe0\xc0", + .ilen = 16, + .result = "Single block msg", + .rlen = 16, + }, { + .key = "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb" + "\x07\x96\x36\x58\x79\xef\xf8\x86" + "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74" + "\x4b\x50\x59\x0c\x87\xa2\x38\x84" + "\x00\xfa\xac\x24", + .klen = 36, + .iv = "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75", + .input = "\xf0\x5e\x23\x1b\x38\x94\x61\x2c" + "\x49\xee\x00\x0b\x80\x4e\xb2\xa9" + "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a" + "\x55\x30\x83\x1d\x93\x44\xaf\x1c", + .ilen = 32, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .rlen = 32, + }, +}; + +static struct aead_testvec aes_gcm_enc_tv_template[] = { + { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */ + .key = zeroed_string, + .klen = 16, + .result = "\x58\xe2\xfc\xce\xfa\x7e\x30\x61" + "\x36\x7f\x1d\x57\xa4\xe7\x45\x5a", + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 16, + .input = zeroed_string, + .ilen = 16, + .result = "\x03\x88\xda\xce\x60\xb6\xa3\x92" + "\xf3\x28\xc2\xb9\x71\xb2\xfe\x78" + "\xab\x6e\x47\xd4\x2c\xec\x13\xbd" + "\xf5\x3a\x67\xb2\x12\x57\xbd\xdf", + .rlen = 32, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .ilen = 64, + .result = "\x42\x83\x1e\xc2\x21\x77\x74\x24" + "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" + "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c" + "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" + "\x3d\x58\xe0\x91\x47\x3f\x59\x85" + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" + "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", + .rlen = 80, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .ilen = 60, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .result = "\x42\x83\x1e\xc2\x21\x77\x74\x24" + "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" + "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c" + "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" + "\x3d\x58\xe0\x91" + "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb" + "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47", + .rlen = 76, + }, { + .key = zeroed_string, + .klen = 24, + .result = "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b" + "\xa0\x0e\xd1\xf3\x12\x57\x24\x35", + .rlen = 16, + }, { + .key = zeroed_string, + .klen = 24, + .input = zeroed_string, + .ilen = 16, + .result = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41" + "\x1c\x26\x7e\x43\x84\xb0\xf6\x00" + "\x2f\xf5\x8d\x80\x03\x39\x27\xab" + "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb", + .rlen = 32, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + .klen = 24, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .ilen = 64, + .result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" + "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" + "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" + "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" + "\xcc\xda\x27\x10\xac\xad\xe2\x56" + "\x99\x24\xa7\xc8\x58\x73\x36\xbf" + "\xb1\x18\x02\x4d\xb8\x67\x4a\x14", + .rlen = 80, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + .klen = 24, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .ilen = 60, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" + "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" + "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" + "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" + "\xcc\xda\x27\x10" + "\x25\x19\x49\x8e\x80\xf1\x47\x8f" + "\x37\xba\x55\xbd\x6d\x27\x61\x8c", + .rlen = 76, + .np = 2, + .tap = { 32, 28 }, + .anp = 2, + .atap = { 8, 12 } + }, { + .key = zeroed_string, + .klen = 32, + .result = "\x53\x0f\x8a\xfb\xc7\x45\x36\xb9" + "\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b", + .rlen = 16, + } +}; + +static struct aead_testvec aes_gcm_dec_tv_template[] = { + { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */ + .key = zeroed_string, + .klen = 32, + .input = "\xce\xa7\x40\x3d\x4d\x60\x6b\x6e" + "\x07\x4e\xc5\xd3\xba\xf3\x9d\x18" + "\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0" + "\x26\x5b\x98\xb5\xd4\x8a\xb9\x19", + .ilen = 32, + .result = zeroed_string, + .rlen = 16, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 32, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" + "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" + "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" + "\x75\x98\xa2\xbd\x25\x55\xd1\xaa" + "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d" + "\xa7\xb0\x8b\x10\x56\x82\x88\x38" + "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a" + "\xbc\xc9\xf6\x62\x89\x80\x15\xad" + "\xb0\x94\xda\xc5\xd9\x34\x71\xbd" + "\xec\x1a\x50\x22\x70\xe3\xcc\x6c", + .ilen = 80, + .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .rlen = 64, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 32, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" + "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" + "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" + "\x75\x98\xa2\xbd\x25\x55\xd1\xaa" + "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d" + "\xa7\xb0\x8b\x10\x56\x82\x88\x38" + "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a" + "\xbc\xc9\xf6\x62" + "\x76\xfc\x6e\xce\x0f\x4e\x17\x68" + "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b", + .ilen = 76, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .rlen = 60, + .np = 2, + .tap = { 48, 28 }, + .anp = 3, + .atap = { 8, 8, 4 } + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\x42\x83\x1e\xc2\x21\x77\x74\x24" + "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" + "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c" + "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" + "\x3d\x58\xe0\x91\x47\x3f\x59\x85" + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" + "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", + .ilen = 80, + .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .rlen = 64, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08", + .klen = 16, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\x42\x83\x1e\xc2\x21\x77\x74\x24" + "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" + "\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c" + "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97" + "\x3d\x58\xe0\x91" + "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb" + "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47", + .ilen = 76, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .rlen = 60, + }, { + .key = zeroed_string, + .klen = 24, + .input = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41" + "\x1c\x26\x7e\x43\x84\xb0\xf6\x00" + "\x2f\xf5\x8d\x80\x03\x39\x27\xab" + "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb", + .ilen = 32, + .result = zeroed_string, + .rlen = 16, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + .klen = 24, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" + "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" + "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" + "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" + "\xcc\xda\x27\x10\xac\xad\xe2\x56" + "\x99\x24\xa7\xc8\x58\x73\x36\xbf" + "\xb1\x18\x02\x4d\xb8\x67\x4a\x14", + .ilen = 80, + .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + .rlen = 64, + }, { + .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c" + "\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + .klen = 24, + .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad" + "\xde\xca\xf8\x88", + .input = "\x39\x80\xca\x0b\x3c\x00\xe8\x41" + "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" + "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" + "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c" + "\x7d\x77\x3d\x00\xc1\x44\xc5\x25" + "\xac\x61\x9d\x18\xc8\x4a\x3f\x47" + "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9" + "\xcc\xda\x27\x10" + "\x25\x19\x49\x8e\x80\xf1\x47\x8f" + "\x37\xba\x55\xbd\x6d\x27\x61\x8c", + .ilen = 76, + .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", + .alen = 20, + .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5" + "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda" + "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53" + "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" + "\xba\x63\x7b\x39", + .rlen = 60, + } +}; + +static struct aead_testvec aes_ccm_enc_tv_template[] = { + { /* From RFC 3610 */ + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .input = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .ilen = 23, + .result = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2" + "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80" + "\x6d\x5f\x6b\x61\xda\xc3\x84\x17" + "\xe8\xd1\x2c\xfd\xf9\x26\xe0", + .rlen = 31, + }, { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x07\x06\x05\x04" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b", + .alen = 12, + .input = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" + "\x14\x15\x16\x17\x18\x19\x1a\x1b" + "\x1c\x1d\x1e\x1f", + .ilen = 20, + .result = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb" + "\x9d\x4e\x13\x12\x53\x65\x8a\xd8" + "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07" + "\x7d\x9c\x2d\x93", + .rlen = 28, + }, { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x0b\x0a\x09\x08" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .input = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20", + .ilen = 25, + .result = "\x82\x53\x1a\x60\xcc\x24\x94\x5a" + "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d" + "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1" + "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1" + "\x7e\x5f\x4e", + .rlen = 35, + }, { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x0c\x0b\x0a\x09" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b", + .alen = 12, + .input = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" + "\x14\x15\x16\x17\x18\x19\x1a\x1b" + "\x1c\x1d\x1e", + .ilen = 19, + .result = "\x07\x34\x25\x94\x15\x77\x85\x15" + "\x2b\x07\x40\x98\x33\x0a\xbb\x14" + "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b" + "\x4d\x99\x99\x88\xdd", + .rlen = 29, + }, { + .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" + "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", + .klen = 16, + .iv = "\x01\x00\x33\x56\x8e\xf7\xb2\x63" + "\x3c\x96\x96\x76\x6c\xfa\x00\x00", + .assoc = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb", + .alen = 8, + .input = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a" + "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf" + "\xb7\x9c\x70\x28\x94\x9c\xd0\xec", + .ilen = 24, + .result = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa" + "\xa0\x72\x6c\x55\xd3\x78\x06\x12" + "\x98\xc8\x5c\x92\x81\x4a\xbc\x33" + "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a", + .rlen = 32, + }, { + .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" + "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", + .klen = 16, + .iv = "\x01\x00\xd5\x60\x91\x2d\x3f\x70" + "\x3c\x96\x96\x76\x6c\xfa\x00\x00", + .assoc = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81" + "\x20\xea\x60\xc0", + .alen = 12, + .input = "\x64\x35\xac\xba\xfb\x11\xa8\x2e" + "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9" + "\x3a\x80\x3b\xa8\x7f", + .ilen = 21, + .result = "\x00\x97\x69\xec\xab\xdf\x48\x62" + "\x55\x94\xc5\x92\x51\xe6\x03\x57" + "\x22\x67\x5e\x04\xc8\x47\x09\x9e" + "\x5a\xe0\x70\x45\x51", + .rlen = 29, + }, { + .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" + "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", + .klen = 16, + .iv = "\x01\x00\x42\xff\xf8\xf1\x95\x1c" + "\x3c\x96\x96\x76\x6c\xfa\x00\x00", + .assoc = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8", + .alen = 8, + .input = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01" + "\x8e\x5e\x67\x01\xc9\x17\x87\x65" + "\x98\x09\xd6\x7d\xbe\xdd\x18", + .ilen = 23, + .result = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6" + "\xdb\x38\x6a\x99\xac\x1a\xef\x23" + "\xad\xe0\xb5\x29\x39\xcb\x6a\x63" + "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6" + "\xba", + .rlen = 33, + }, +}; + +static struct aead_testvec aes_ccm_dec_tv_template[] = { + { /* From RFC 3610 */ + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x03\x02\x01\x00" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .input = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2" + "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80" + "\x6d\x5f\x6b\x61\xda\xc3\x84\x17" + "\xe8\xd1\x2c\xfd\xf9\x26\xe0", + .ilen = 31, + .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e", + .rlen = 23, + }, { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x07\x06\x05\x04" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b", + .alen = 12, + .input = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb" + "\x9d\x4e\x13\x12\x53\x65\x8a\xd8" + "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07" + "\x7d\x9c\x2d\x93", + .ilen = 28, + .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" + "\x14\x15\x16\x17\x18\x19\x1a\x1b" + "\x1c\x1d\x1e\x1f", + .rlen = 20, + }, { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x0b\x0a\x09\x08" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07", + .alen = 8, + .input = "\x82\x53\x1a\x60\xcc\x24\x94\x5a" + "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d" + "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1" + "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1" + "\x7e\x5f\x4e", + .ilen = 35, + .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20", + .rlen = 25, + }, { + .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + .klen = 16, + .iv = "\x01\x00\x00\x00\x0c\x0b\x0a\x09" + "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00", + .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b", + .alen = 12, + .input = "\x07\x34\x25\x94\x15\x77\x85\x15" + "\x2b\x07\x40\x98\x33\x0a\xbb\x14" + "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b" + "\x4d\x99\x99\x88\xdd", + .ilen = 29, + .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13" + "\x14\x15\x16\x17\x18\x19\x1a\x1b" + "\x1c\x1d\x1e", + .rlen = 19, + }, { + .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" + "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", + .klen = 16, + .iv = "\x01\x00\x33\x56\x8e\xf7\xb2\x63" + "\x3c\x96\x96\x76\x6c\xfa\x00\x00", + .assoc = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb", + .alen = 8, + .input = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa" + "\xa0\x72\x6c\x55\xd3\x78\x06\x12" + "\x98\xc8\x5c\x92\x81\x4a\xbc\x33" + "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a", + .ilen = 32, + .result = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a" + "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf" + "\xb7\x9c\x70\x28\x94\x9c\xd0\xec", + .rlen = 24, + }, { + .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" + "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", + .klen = 16, + .iv = "\x01\x00\xd5\x60\x91\x2d\x3f\x70" + "\x3c\x96\x96\x76\x6c\xfa\x00\x00", + .assoc = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81" + "\x20\xea\x60\xc0", + .alen = 12, + .input = "\x00\x97\x69\xec\xab\xdf\x48\x62" + "\x55\x94\xc5\x92\x51\xe6\x03\x57" + "\x22\x67\x5e\x04\xc8\x47\x09\x9e" + "\x5a\xe0\x70\x45\x51", + .ilen = 29, + .result = "\x64\x35\xac\xba\xfb\x11\xa8\x2e" + "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9" + "\x3a\x80\x3b\xa8\x7f", + .rlen = 21, + }, { + .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3" + "\x25\xa7\x62\x36\xdf\x93\xcc\x6b", + .klen = 16, + .iv = "\x01\x00\x42\xff\xf8\xf1\x95\x1c" + "\x3c\x96\x96\x76\x6c\xfa\x00\x00", + .assoc = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8", + .alen = 8, + .input = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6" + "\xdb\x38\x6a\x99\xac\x1a\xef\x23" + "\xad\xe0\xb5\x29\x39\xcb\x6a\x63" + "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6" + "\xba", + .ilen = 33, + .result = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01" + "\x8e\x5e\x67\x01\xc9\x17\x87\x65" + "\x98\x09\xd6\x7d\xbe\xdd\x18", + .rlen = 23, + }, +}; + +/* Cast5 test vectors from RFC 2144 */ +#define CAST5_ENC_TEST_VECTORS 3 +#define CAST5_DEC_TEST_VECTORS 3 + +static struct cipher_testvec cast5_enc_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x12\x34\x56\x78" + "\x23\x45\x67\x89\x34\x56\x78\x9a", + .klen = 16, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .ilen = 8, + .result = "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x12\x34\x56\x78" + "\x23\x45", + .klen = 10, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .ilen = 8, + .result = "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x12", + .klen = 5, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .ilen = 8, + .result = "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e", + .rlen = 8, + }, +}; + +static struct cipher_testvec cast5_dec_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x12\x34\x56\x78" + "\x23\x45\x67\x89\x34\x56\x78\x9a", + .klen = 16, + .input = "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2", + .ilen = 8, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x12\x34\x56\x78" + "\x23\x45", + .klen = 10, + .input = "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b", + .ilen = 8, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x12", + .klen = 5, + .input = "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e", + .ilen = 8, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .rlen = 8, + }, +}; + +/* + * ARC4 test vectors from OpenSSL + */ +#define ARC4_ENC_TEST_VECTORS 7 +#define ARC4_DEC_TEST_VECTORS 7 + +static struct cipher_testvec arc4_enc_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .ilen = 8, + .result = "\x75\xb7\x87\x80\x99\xe0\xc5\x96", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 8, + .result = "\x74\x94\xc2\xe7\x10\x4b\x08\x79", + .rlen = 8, + }, { + .key = "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 8, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 8, + .result = "\xde\x18\x89\x41\xa3\x37\x5d\x3a", + .rlen = 8, + }, { + .key = "\xef\x01\x23\x45", + .klen = 4, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00", + .ilen = 20, + .result = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" + "\xbd\x61\x5a\x11\x62\xe1\xc7\xba" + "\x36\xb6\x78\x58", + .rlen = 20, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" + "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" + "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" + "\x12\x34\x56\x78", + .ilen = 28, + .result = "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89" + "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c" + "\x89\x2e\xbe\x30\x14\x3c\xe2\x87" + "\x40\x01\x1e\xcf", + .rlen = 28, + }, { + .key = "\xef\x01\x23\x45", + .klen = 4, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00", + .ilen = 10, + .result = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" + "\xbd\x61", + .rlen = 10, + }, { + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 16, + .input = "\x01\x23\x45\x67\x89\xAB\xCD\xEF", + .ilen = 8, + .result = "\x69\x72\x36\x59\x1B\x52\x42\xB1", + .rlen = 8, + }, +}; + +static struct cipher_testvec arc4_dec_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x75\xb7\x87\x80\x99\xe0\xc5\x96", + .ilen = 8, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .rlen = 8, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x74\x94\xc2\xe7\x10\x4b\x08\x79", + .ilen = 8, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00", + .rlen = 8, + }, { + .key = "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 8, + .input = "\xde\x18\x89\x41\xa3\x37\x5d\x3a", + .ilen = 8, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00", + .rlen = 8, + }, { + .key = "\xef\x01\x23\x45", + .klen = 4, + .input = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" + "\xbd\x61\x5a\x11\x62\xe1\xc7\xba" + "\x36\xb6\x78\x58", + .ilen = 20, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00", + .rlen = 20, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef", + .klen = 8, + .input = "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89" + "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c" + "\x89\x2e\xbe\x30\x14\x3c\xe2\x87" + "\x40\x01\x1e\xcf", + .ilen = 28, + .result = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" + "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" + "\x12\x34\x56\x78\x9A\xBC\xDE\xF0" + "\x12\x34\x56\x78", + .rlen = 28, + }, { + .key = "\xef\x01\x23\x45", + .klen = 4, + .input = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf" + "\xbd\x61", + .ilen = 10, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00", + .rlen = 10, + }, { + .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 16, + .input = "\x69\x72\x36\x59\x1B\x52\x42\xB1", + .ilen = 8, + .result = "\x01\x23\x45\x67\x89\xAB\xCD\xEF", + .rlen = 8, + }, +}; + +/* + * TEA test vectors + */ +#define TEA_ENC_TEST_VECTORS 4 +#define TEA_DEC_TEST_VECTORS 4 + +static struct cipher_testvec tea_enc_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = zeroed_string, + .ilen = 8, + .result = "\x0a\x3a\xea\x41\x40\xa9\xba\x94", + .rlen = 8, + }, { + .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" + "\x77\x5d\x0e\x26\x6c\x28\x78\x43", + .klen = 16, + .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e", + .ilen = 8, + .result = "\x77\x5d\x2a\x6a\xf6\xce\x92\x09", + .rlen = 8, + }, { + .key = "\x09\x65\x43\x11\x66\x44\x39\x25" + "\x51\x3a\x16\x10\x0a\x08\x12\x6e", + .klen = 16, + .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" + "\x65\x73\x74\x5f\x76\x65\x63\x74", + .ilen = 16, + .result = "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e" + "\xdd\x89\xa1\x25\x04\x21\xdf\x95", + .rlen = 16, + }, { + .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" + "\x5d\x04\x16\x36\x15\x72\x63\x2f", + .klen = 16, + .input = "\x54\x65\x61\x20\x69\x73\x20\x67" + "\x6f\x6f\x64\x20\x66\x6f\x72\x20" + "\x79\x6f\x75\x21\x21\x21\x20\x72" + "\x65\x61\x6c\x6c\x79\x21\x21\x21", + .ilen = 32, + .result = "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47" + "\x94\x18\x95\x91\xa9\xfc\x49\xf8" + "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a" + "\x07\x89\x73\xc2\x45\x92\xc6\x90", + .rlen = 32, + } +}; + +static struct cipher_testvec tea_dec_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = "\x0a\x3a\xea\x41\x40\xa9\xba\x94", + .ilen = 8, + .result = zeroed_string, + .rlen = 8, + }, { + .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" + "\x77\x5d\x0e\x26\x6c\x28\x78\x43", + .klen = 16, + .input = "\x77\x5d\x2a\x6a\xf6\xce\x92\x09", + .ilen = 8, + .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e", + .rlen = 8, + }, { + .key = "\x09\x65\x43\x11\x66\x44\x39\x25" + "\x51\x3a\x16\x10\x0a\x08\x12\x6e", + .klen = 16, + .input = "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e" + "\xdd\x89\xa1\x25\x04\x21\xdf\x95", + .ilen = 16, + .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" + "\x65\x73\x74\x5f\x76\x65\x63\x74", + .rlen = 16, + }, { + .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" + "\x5d\x04\x16\x36\x15\x72\x63\x2f", + .klen = 16, + .input = "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47" + "\x94\x18\x95\x91\xa9\xfc\x49\xf8" + "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a" + "\x07\x89\x73\xc2\x45\x92\xc6\x90", + .ilen = 32, + .result = "\x54\x65\x61\x20\x69\x73\x20\x67" + "\x6f\x6f\x64\x20\x66\x6f\x72\x20" + "\x79\x6f\x75\x21\x21\x21\x20\x72" + "\x65\x61\x6c\x6c\x79\x21\x21\x21", + .rlen = 32, + } +}; + +/* + * XTEA test vectors + */ +#define XTEA_ENC_TEST_VECTORS 4 +#define XTEA_DEC_TEST_VECTORS 4 + +static struct cipher_testvec xtea_enc_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = zeroed_string, + .ilen = 8, + .result = "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7", + .rlen = 8, + }, { + .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" + "\x77\x5d\x0e\x26\x6c\x28\x78\x43", + .klen = 16, + .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e", + .ilen = 8, + .result = "\x94\xeb\xc8\x96\x84\x6a\x49\xa8", + .rlen = 8, + }, { + .key = "\x09\x65\x43\x11\x66\x44\x39\x25" + "\x51\x3a\x16\x10\x0a\x08\x12\x6e", + .klen = 16, + .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" + "\x65\x73\x74\x5f\x76\x65\x63\x74", + .ilen = 16, + .result = "\x3e\xce\xae\x22\x60\x56\xa8\x9d" + "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a", + .rlen = 16, + }, { + .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" + "\x5d\x04\x16\x36\x15\x72\x63\x2f", + .klen = 16, + .input = "\x54\x65\x61\x20\x69\x73\x20\x67" + "\x6f\x6f\x64\x20\x66\x6f\x72\x20" + "\x79\x6f\x75\x21\x21\x21\x20\x72" + "\x65\x61\x6c\x6c\x79\x21\x21\x21", + .ilen = 32, + .result = "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a" + "\x86\xff\x6f\xd0\xe3\x87\x70\x07" + "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4" + "\x73\xa2\xfa\xc9\x16\x59\x5d\x81", + .rlen = 32, + } +}; + +static struct cipher_testvec xtea_dec_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7", + .ilen = 8, + .result = zeroed_string, + .rlen = 8, + }, { + .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" + "\x77\x5d\x0e\x26\x6c\x28\x78\x43", + .klen = 16, + .input = "\x94\xeb\xc8\x96\x84\x6a\x49\xa8", + .ilen = 8, + .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e", + .rlen = 8, + }, { + .key = "\x09\x65\x43\x11\x66\x44\x39\x25" + "\x51\x3a\x16\x10\x0a\x08\x12\x6e", + .klen = 16, + .input = "\x3e\xce\xae\x22\x60\x56\xa8\x9d" + "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a", + .ilen = 16, + .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" + "\x65\x73\x74\x5f\x76\x65\x63\x74", + .rlen = 16, + }, { + .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" + "\x5d\x04\x16\x36\x15\x72\x63\x2f", + .klen = 16, + .input = "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a" + "\x86\xff\x6f\xd0\xe3\x87\x70\x07" + "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4" + "\x73\xa2\xfa\xc9\x16\x59\x5d\x81", + .ilen = 32, + .result = "\x54\x65\x61\x20\x69\x73\x20\x67" + "\x6f\x6f\x64\x20\x66\x6f\x72\x20" + "\x79\x6f\x75\x21\x21\x21\x20\x72" + "\x65\x61\x6c\x6c\x79\x21\x21\x21", + .rlen = 32, + } +}; + +/* + * KHAZAD test vectors. + */ +#define KHAZAD_ENC_TEST_VECTORS 5 +#define KHAZAD_DEC_TEST_VECTORS 5 + +static struct cipher_testvec khazad_enc_tv_template[] = { + { + .key = "\x80\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 16, + .input = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 8, + .result = "\x49\xa4\xce\x32\xac\x19\x0e\x3f", + .rlen = 8, + }, { + .key = "\x38\x38\x38\x38\x38\x38\x38\x38" + "\x38\x38\x38\x38\x38\x38\x38\x38", + .klen = 16, + .input = "\x38\x38\x38\x38\x38\x38\x38\x38", + .ilen = 8, + .result = "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9", + .rlen = 8, + }, { + .key = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2" + "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", + .klen = 16, + .input = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", + .ilen = 8, + .result = "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c", + .rlen = 8, + }, { + .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" + "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .klen = 16, + .input = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .ilen = 8, + .result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8", + .rlen = 8, + }, { + .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" + "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .klen = 16, + .input = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" + "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .ilen = 16, + .result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8" + "\x04\x74\xf5\x70\x50\x16\xd3\xb8", + .rlen = 16, + }, +}; + +static struct cipher_testvec khazad_dec_tv_template[] = { + { + .key = "\x80\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 16, + .input = "\x49\xa4\xce\x32\xac\x19\x0e\x3f", + .ilen = 8, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00", + .rlen = 8, + }, { + .key = "\x38\x38\x38\x38\x38\x38\x38\x38" + "\x38\x38\x38\x38\x38\x38\x38\x38", + .klen = 16, + .input = "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9", + .ilen = 8, + .result = "\x38\x38\x38\x38\x38\x38\x38\x38", + .rlen = 8, + }, { + .key = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2" + "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", + .klen = 16, + .input = "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c", + .ilen = 8, + .result = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2", + .rlen = 8, + }, { + .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" + "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .klen = 16, + .input = "\x04\x74\xf5\x70\x50\x16\xd3\xb8", + .ilen = 8, + .result = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .rlen = 8, + }, { + .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" + "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .klen = 16, + .input = "\x04\x74\xf5\x70\x50\x16\xd3\xb8" + "\x04\x74\xf5\x70\x50\x16\xd3\xb8", + .ilen = 16, + .result = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f" + "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f", + .rlen = 16, + }, +}; + +/* + * Anubis test vectors. + */ + +#define ANUBIS_ENC_TEST_VECTORS 5 +#define ANUBIS_DEC_TEST_VECTORS 5 +#define ANUBIS_CBC_ENC_TEST_VECTORS 2 +#define ANUBIS_CBC_DEC_TEST_VECTORS 2 + +static struct cipher_testvec anubis_enc_tv_template[] = { + { + .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .klen = 16, + .input = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .ilen = 16, + .result = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" + "\x08\xb7\x52\x8e\x6e\x6e\x86\x90", + .rlen = 16, + }, { + + .key = "\x03\x03\x03\x03\x03\x03\x03\x03" + "\x03\x03\x03\x03\x03\x03\x03\x03" + "\x03\x03\x03\x03", + .klen = 20, + .input = "\x03\x03\x03\x03\x03\x03\x03\x03" + "\x03\x03\x03\x03\x03\x03\x03\x03", + .ilen = 16, + .result = "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49" + "\x87\x41\x6f\x82\x0a\x98\x64\xae", + .rlen = 16, + }, { + .key = "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24", + .klen = 28, + .input = "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24\x24\x24\x24\x24", + .ilen = 16, + .result = "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d" + "\x06\xd3\x61\x27\xfd\x13\x9e\xde", + .rlen = 16, + }, { + .key = "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25", + .klen = 32, + .input = "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25", + .ilen = 16, + .result = "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4" + "\x17\xd9\xff\x40\x3b\x0e\xe5\xfe", + .rlen = 16, + }, { + .key = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .klen = 40, + .input = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .ilen = 16, + .result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" + "\x9e\xc6\x84\x0f\x17\x21\x07\xee", + .rlen = 16, + }, +}; + +static struct cipher_testvec anubis_dec_tv_template[] = { + { + .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .klen = 16, + .input = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" + "\x08\xb7\x52\x8e\x6e\x6e\x86\x90", + .ilen = 16, + .result = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .rlen = 16, + }, { + + .key = "\x03\x03\x03\x03\x03\x03\x03\x03" + "\x03\x03\x03\x03\x03\x03\x03\x03" + "\x03\x03\x03\x03", + .klen = 20, + .input = "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49" + "\x87\x41\x6f\x82\x0a\x98\x64\xae", + .ilen = 16, + .result = "\x03\x03\x03\x03\x03\x03\x03\x03" + "\x03\x03\x03\x03\x03\x03\x03\x03", + .rlen = 16, + }, { + .key = "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24", + .klen = 28, + .input = "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d" + "\x06\xd3\x61\x27\xfd\x13\x9e\xde", + .ilen = 16, + .result = "\x24\x24\x24\x24\x24\x24\x24\x24" + "\x24\x24\x24\x24\x24\x24\x24\x24", + .rlen = 16, + }, { + .key = "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25", + .klen = 32, + .input = "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4" + "\x17\xd9\xff\x40\x3b\x0e\xe5\xfe", + .ilen = 16, + .result = "\x25\x25\x25\x25\x25\x25\x25\x25" + "\x25\x25\x25\x25\x25\x25\x25\x25", + .rlen = 16, + }, { + .key = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" + "\x9e\xc6\x84\x0f\x17\x21\x07\xee", + .klen = 40, + .ilen = 16, + .result = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .rlen = 16, + }, +}; + +static struct cipher_testvec anubis_cbc_enc_tv_template[] = { + { + .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .klen = 16, + .input = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .ilen = 32, + .result = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" + "\x08\xb7\x52\x8e\x6e\x6e\x86\x90" + "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66" + "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe", + .rlen = 32, + }, { + .key = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .klen = 40, + .input = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .ilen = 32, + .result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" + "\x9e\xc6\x84\x0f\x17\x21\x07\xee" + "\xa2\xbc\x06\x98\xc6\x4b\xda\x75" + "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7", + .rlen = 32, + }, +}; + +static struct cipher_testvec anubis_cbc_dec_tv_template[] = { + { + .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .klen = 16, + .input = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f" + "\x08\xb7\x52\x8e\x6e\x6e\x86\x90" + "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66" + "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe", + .ilen = 32, + .result = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe" + "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", + .rlen = 32, + }, { + .key = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .klen = 40, + .input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97" + "\x9e\xc6\x84\x0f\x17\x21\x07\xee" + "\xa2\xbc\x06\x98\xc6\x4b\xda\x75" + "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7", + .ilen = 32, + .result = "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35" + "\x35\x35\x35\x35\x35\x35\x35\x35", + .rlen = 32, + }, +}; + +/* + * XETA test vectors + */ +#define XETA_ENC_TEST_VECTORS 4 +#define XETA_DEC_TEST_VECTORS 4 + +static struct cipher_testvec xeta_enc_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = zeroed_string, + .ilen = 8, + .result = "\xaa\x22\x96\xe5\x6c\x61\xf3\x45", + .rlen = 8, + }, { + .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" + "\x77\x5d\x0e\x26\x6c\x28\x78\x43", + .klen = 16, + .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e", + .ilen = 8, + .result = "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3", + .rlen = 8, + }, { + .key = "\x09\x65\x43\x11\x66\x44\x39\x25" + "\x51\x3a\x16\x10\x0a\x08\x12\x6e", + .klen = 16, + .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" + "\x65\x73\x74\x5f\x76\x65\x63\x74", + .ilen = 16, + .result = "\xe2\x04\xdb\xf2\x89\x85\x9e\xea" + "\x61\x35\xaa\xed\xb5\xcb\x71\x2c", + .rlen = 16, + }, { + .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" + "\x5d\x04\x16\x36\x15\x72\x63\x2f", + .klen = 16, + .input = "\x54\x65\x61\x20\x69\x73\x20\x67" + "\x6f\x6f\x64\x20\x66\x6f\x72\x20" + "\x79\x6f\x75\x21\x21\x21\x20\x72" + "\x65\x61\x6c\x6c\x79\x21\x21\x21", + .ilen = 32, + .result = "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1" + "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4" + "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f" + "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5", + .rlen = 32, + } +}; + +static struct cipher_testvec xeta_dec_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = "\xaa\x22\x96\xe5\x6c\x61\xf3\x45", + .ilen = 8, + .result = zeroed_string, + .rlen = 8, + }, { + .key = "\x2b\x02\x05\x68\x06\x14\x49\x76" + "\x77\x5d\x0e\x26\x6c\x28\x78\x43", + .klen = 16, + .input = "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3", + .ilen = 8, + .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e", + .rlen = 8, + }, { + .key = "\x09\x65\x43\x11\x66\x44\x39\x25" + "\x51\x3a\x16\x10\x0a\x08\x12\x6e", + .klen = 16, + .input = "\xe2\x04\xdb\xf2\x89\x85\x9e\xea" + "\x61\x35\xaa\xed\xb5\xcb\x71\x2c", + .ilen = 16, + .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74" + "\x65\x73\x74\x5f\x76\x65\x63\x74", + .rlen = 16, + }, { + .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c" + "\x5d\x04\x16\x36\x15\x72\x63\x2f", + .klen = 16, + .input = "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1" + "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4" + "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f" + "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5", + .ilen = 32, + .result = "\x54\x65\x61\x20\x69\x73\x20\x67" + "\x6f\x6f\x64\x20\x66\x6f\x72\x20" + "\x79\x6f\x75\x21\x21\x21\x20\x72" + "\x65\x61\x6c\x6c\x79\x21\x21\x21", + .rlen = 32, + } +}; + +/* + * FCrypt test vectors + */ +#define FCRYPT_ENC_TEST_VECTORS ARRAY_SIZE(fcrypt_pcbc_enc_tv_template) +#define FCRYPT_DEC_TEST_VECTORS ARRAY_SIZE(fcrypt_pcbc_dec_tv_template) + +static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = { + { /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 8, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 8, + .result = "\x0E\x09\x00\xC7\x3E\xF7\xED\x41", + .rlen = 8, + }, { + .key = "\x11\x44\x77\xAA\xDD\x00\x33\x66", + .klen = 8, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0", + .ilen = 8, + .result = "\xD8\xED\x78\x74\x77\xEC\x06\x80", + .rlen = 8, + }, { /* From Arla */ + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .klen = 8, + .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .input = "The quick brown fox jumps over the lazy dogs.\0\0", + .ilen = 48, + .result = "\x00\xf0\x0e\x11\x75\xe6\x23\x82" + "\xee\xac\x98\x62\x44\x51\xe4\x84" + "\xc3\x59\xd8\xaa\x64\x60\xae\xf7" + "\xd2\xd9\x13\x79\x72\xa3\x45\x03" + "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1" + "\xf8\x91\x3c\xac\x44\x22\x92\xef", + .rlen = 48, + }, { + .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 8, + .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .input = "The quick brown fox jumps over the lazy dogs.\0\0", + .ilen = 48, + .result = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" + "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" + "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" + "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" + "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" + "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", + .rlen = 48, + }, { /* split-page version */ + .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 8, + .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .input = "The quick brown fox jumps over the lazy dogs.\0\0", + .ilen = 48, + .result = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" + "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" + "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" + "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" + "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" + "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", + .rlen = 48, + .np = 2, + .tap = { 20, 28 }, + } +}; + +static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = { + { /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 8, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x0E\x09\x00\xC7\x3E\xF7\xED\x41", + .ilen = 8, + .result = "\x00\x00\x00\x00\x00\x00\x00\x00", + .rlen = 8, + }, { + .key = "\x11\x44\x77\xAA\xDD\x00\x33\x66", + .klen = 8, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\xD8\xED\x78\x74\x77\xEC\x06\x80", + .ilen = 8, + .result = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0", + .rlen = 8, + }, { /* From Arla */ + .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .klen = 8, + .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .input = "\x00\xf0\x0e\x11\x75\xe6\x23\x82" + "\xee\xac\x98\x62\x44\x51\xe4\x84" + "\xc3\x59\xd8\xaa\x64\x60\xae\xf7" + "\xd2\xd9\x13\x79\x72\xa3\x45\x03" + "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1" + "\xf8\x91\x3c\xac\x44\x22\x92\xef", + .ilen = 48, + .result = "The quick brown fox jumps over the lazy dogs.\0\0", + .rlen = 48, + }, { + .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 8, + .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .input = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" + "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" + "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" + "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" + "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" + "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", + .ilen = 48, + .result = "The quick brown fox jumps over the lazy dogs.\0\0", + .rlen = 48, + }, { /* split-page version */ + .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 8, + .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87", + .input = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c" + "\x01\x88\x7f\x3e\x31\x6e\x62\x9d" + "\xd8\xe0\x57\xa3\x06\x3a\x42\x58" + "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0" + "\x19\x89\x09\x1c\x2a\x8e\x8c\x94" + "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f", + .ilen = 48, + .result = "The quick brown fox jumps over the lazy dogs.\0\0", + .rlen = 48, + .np = 2, + .tap = { 20, 28 }, + } +}; + +/* + * CAMELLIA test vectors. + */ +#define CAMELLIA_ENC_TEST_VECTORS 3 +#define CAMELLIA_DEC_TEST_VECTORS 3 +#define CAMELLIA_CBC_ENC_TEST_VECTORS 2 +#define CAMELLIA_CBC_DEC_TEST_VECTORS 2 + +static struct cipher_testvec camellia_enc_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 16, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .ilen = 16, + .result = "\x67\x67\x31\x38\x54\x96\x69\x73" + "\x08\x57\x06\x56\x48\xea\xbe\x43", + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77", + .klen = 24, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .ilen = 16, + .result = "\xb4\x99\x34\x01\xb3\xe9\x96\xf8" + "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9", + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .klen = 32, + .input = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .ilen = 16, + .result = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c" + "\x20\xef\x7c\x91\x9e\x3a\x75\x09", + .rlen = 16, + }, +}; + +static struct cipher_testvec camellia_dec_tv_template[] = { + { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .klen = 16, + .input = "\x67\x67\x31\x38\x54\x96\x69\x73" + "\x08\x57\x06\x56\x48\xea\xbe\x43", + .ilen = 16, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77", + .klen = 24, + .input = "\xb4\x99\x34\x01\xb3\xe9\x96\xf8" + "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9", + .ilen = 16, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .rlen = 16, + }, { + .key = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff", + .klen = 32, + .input = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c" + "\x20\xef\x7c\x91\x9e\x3a\x75\x09", + .ilen = 16, + .result = "\x01\x23\x45\x67\x89\xab\xcd\xef" + "\xfe\xdc\xba\x98\x76\x54\x32\x10", + .rlen = 16, + }, +}; + +static struct cipher_testvec camellia_cbc_enc_tv_template[] = { + { + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .input = "Single block msg", + .ilen = 16, + .result = "\xea\x32\x12\x76\x3b\x50\x10\xe7" + "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51", + .rlen = 16, + }, { + .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .ilen = 32, + .result = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01" + "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd" + "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0" + "\x15\x78\xe0\x5e\xf2\xcb\x87\x16", + .rlen = 32, + }, +}; + +static struct cipher_testvec camellia_cbc_dec_tv_template[] = { + { + .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b" + "\x51\x2e\x03\xd5\x34\x12\x00\x06", + .klen = 16, + .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30" + "\xb4\x22\xda\x80\x2c\x9f\xac\x41", + .input = "\xea\x32\x12\x76\x3b\x50\x10\xe7" + "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51", + .ilen = 16, + .result = "Single block msg", + .rlen = 16, + }, { + .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0" + "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a", + .klen = 16, + .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28" + "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58", + .input = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01" + "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd" + "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0" + "\x15\x78\xe0\x5e\xf2\xcb\x87\x16", + .ilen = 32, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .rlen = 32, + }, +}; + +/* + * SEED test vectors + */ +#define SEED_ENC_TEST_VECTORS 4 +#define SEED_DEC_TEST_VECTORS 4 + +static struct cipher_testvec seed_enc_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .ilen = 16, + .result = "\x5e\xba\xc6\xe0\x05\x4e\x16\x68" + "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .input = zeroed_string, + .ilen = 16, + .result = "\xc1\x1f\x22\xf2\x01\x40\x50\x50" + "\x84\x48\x35\x97\xe4\x37\x0f\x43", + .rlen = 16, + }, { + .key = "\x47\x06\x48\x08\x51\xe6\x1b\xe8" + "\x5d\x74\xbf\xb3\xfd\x95\x61\x85", + .klen = 16, + .input = "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9" + "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d", + .ilen = 16, + .result = "\xee\x54\xd1\x3e\xbc\xae\x70\x6d" + "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a", + .rlen = 16, + }, { + .key = "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d" + "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7", + .klen = 16, + .input = "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14" + "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7", + .ilen = 16, + .result = "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9" + "\x5d\x0b\x36\x18\xf4\x0f\x51\x22", + .rlen = 16, + } +}; + +static struct cipher_testvec seed_dec_tv_template[] = { + { + .key = zeroed_string, + .klen = 16, + .input = "\x5e\xba\xc6\xe0\x05\x4e\x16\x68" + "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb", + .ilen = 16, + .result = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .rlen = 16, + }, { + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", + .klen = 16, + .input = "\xc1\x1f\x22\xf2\x01\x40\x50\x50" + "\x84\x48\x35\x97\xe4\x37\x0f\x43", + .ilen = 16, + .result = zeroed_string, + .rlen = 16, + }, { + .key = "\x47\x06\x48\x08\x51\xe6\x1b\xe8" + "\x5d\x74\xbf\xb3\xfd\x95\x61\x85", + .klen = 16, + .input = "\xee\x54\xd1\x3e\xbc\xae\x70\x6d" + "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a", + .ilen = 16, + .result = "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9" + "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d", + .rlen = 16, + }, { + .key = "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d" + "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7", + .klen = 16, + .input = "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9" + "\x5d\x0b\x36\x18\xf4\x0f\x51\x22", + .ilen = 16, + .result = "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14" + "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7", + .rlen = 16, + } +}; + +#define SALSA20_STREAM_ENC_TEST_VECTORS 5 +static struct cipher_testvec salsa20_stream_enc_tv_template[] = { + /* + * Testvectors from verified.test-vectors submitted to ECRYPT. + * They are truncated to size 39, 64, 111, 129 to test a variety + * of input length. + */ + { /* Set 3, vector 0 */ + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", + .klen = 16, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00", + .ilen = 39, + .result = "\x2D\xD5\xC3\xF7\xBA\x2B\x20\xF7" + "\x68\x02\x41\x0C\x68\x86\x88\x89" + "\x5A\xD8\xC1\xBD\x4E\xA6\xC9\xB1" + "\x40\xFB\x9B\x90\xE2\x10\x49\xBF" + "\x58\x3F\x52\x79\x70\xEB\xC1", + .rlen = 39, + }, { /* Set 5, vector 0 */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 16, + .iv = "\x80\x00\x00\x00\x00\x00\x00\x00", + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .ilen = 64, + .result = "\xB6\x6C\x1E\x44\x46\xDD\x95\x57" + "\xE5\x78\xE2\x23\xB0\xB7\x68\x01" + "\x7B\x23\xB2\x67\xBB\x02\x34\xAE" + "\x46\x26\xBF\x44\x3F\x21\x97\x76" + "\x43\x6F\xB1\x9F\xD0\xE8\x86\x6F" + "\xCD\x0D\xE9\xA9\x53\x8F\x4A\x09" + "\xCA\x9A\xC0\x73\x2E\x30\xBC\xF9" + "\x8E\x4F\x13\xE4\xB9\xE2\x01\xD9", + .rlen = 64, + }, { /* Set 3, vector 27 */ + .key = "\x1B\x1C\x1D\x1E\x1F\x20\x21\x22" + "\x23\x24\x25\x26\x27\x28\x29\x2A" + "\x2B\x2C\x2D\x2E\x2F\x30\x31\x32" + "\x33\x34\x35\x36\x37\x38\x39\x3A", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00", + .ilen = 111, + .result = "\xAE\x39\x50\x8E\xAC\x9A\xEC\xE7" + "\xBF\x97\xBB\x20\xB9\xDE\xE4\x1F" + "\x87\xD9\x47\xF8\x28\x91\x35\x98" + "\xDB\x72\xCC\x23\x29\x48\x56\x5E" + "\x83\x7E\x0B\xF3\x7D\x5D\x38\x7B" + "\x2D\x71\x02\xB4\x3B\xB5\xD8\x23" + "\xB0\x4A\xDF\x3C\xEC\xB6\xD9\x3B" + "\x9B\xA7\x52\xBE\xC5\xD4\x50\x59" + "\x15\x14\xB4\x0E\x40\xE6\x53\xD1" + "\x83\x9C\x5B\xA0\x92\x29\x6B\x5E" + "\x96\x5B\x1E\x2F\xD3\xAC\xC1\x92" + "\xB1\x41\x3F\x19\x2F\xC4\x3B\xC6" + "\x95\x46\x45\x54\xE9\x75\x03\x08" + "\x44\xAF\xE5\x8A\x81\x12\x09", + .rlen = 111, + }, { /* Set 5, vector 27 */ + .key = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .klen = 32, + .iv = "\x00\x00\x00\x10\x00\x00\x00\x00", + .input = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00", + .ilen = 129, + .result = "\xD2\xDB\x1A\x5C\xF1\xC1\xAC\xDB" + "\xE8\x1A\x7A\x43\x40\xEF\x53\x43" + "\x5E\x7F\x4B\x1A\x50\x52\x3F\x8D" + "\x28\x3D\xCF\x85\x1D\x69\x6E\x60" + "\xF2\xDE\x74\x56\x18\x1B\x84\x10" + "\xD4\x62\xBA\x60\x50\xF0\x61\xF2" + "\x1C\x78\x7F\xC1\x24\x34\xAF\x58" + "\xBF\x2C\x59\xCA\x90\x77\xF3\xB0" + "\x5B\x4A\xDF\x89\xCE\x2C\x2F\xFC" + "\x67\xF0\xE3\x45\xE8\xB3\xB3\x75" + "\xA0\x95\x71\xA1\x29\x39\x94\xCA" + "\x45\x2F\xBD\xCB\x10\xB6\xBE\x9F" + "\x8E\xF9\xB2\x01\x0A\x5A\x0A\xB7" + "\x6B\x9D\x70\x8E\x4B\xD6\x2F\xCD" + "\x2E\x40\x48\x75\xE9\xE2\x21\x45" + "\x0B\xC9\xB6\xB5\x66\xBC\x9A\x59" + "\x5A", + .rlen = 129, + }, { /* large test vector generated using Crypto++ */ + .key = "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", + .klen = 32, + .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + .input = + "\x00\x01\x02\x03\x04\x05\x06\x07" + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x11\x12\x13\x14\x15\x16\x17" + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x21\x22\x23\x24\x25\x26\x27" + "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + "\x30\x31\x32\x33\x34\x35\x36\x37" + "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + "\x40\x41\x42\x43\x44\x45\x46\x47" + "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" + "\x50\x51\x52\x53\x54\x55\x56\x57" + "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" + "\x60\x61\x62\x63\x64\x65\x66\x67" + "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" + "\x70\x71\x72\x73\x74\x75\x76\x77" + "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87" + "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97" + "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" + "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" + "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" + "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" + "\xe8\xe9\xea\xeb\xec\xed\xee\xef" + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" + "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" + "\x00\x03\x06\x09\x0c\x0f\x12\x15" + "\x18\x1b\x1e\x21\x24\x27\x2a\x2d" + "\x30\x33\x36\x39\x3c\x3f\x42\x45" + "\x48\x4b\x4e\x51\x54\x57\x5a\x5d" + "\x60\x63\x66\x69\x6c\x6f\x72\x75" + "\x78\x7b\x7e\x81\x84\x87\x8a\x8d" + "\x90\x93\x96\x99\x9c\x9f\xa2\xa5" + "\xa8\xab\xae\xb1\xb4\xb7\xba\xbd" + "\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5" + "\xd8\xdb\xde\xe1\xe4\xe7\xea\xed" + "\xf0\xf3\xf6\xf9\xfc\xff\x02\x05" + "\x08\x0b\x0e\x11\x14\x17\x1a\x1d" + "\x20\x23\x26\x29\x2c\x2f\x32\x35" + "\x38\x3b\x3e\x41\x44\x47\x4a\x4d" + "\x50\x53\x56\x59\x5c\x5f\x62\x65" + "\x68\x6b\x6e\x71\x74\x77\x7a\x7d" + "\x80\x83\x86\x89\x8c\x8f\x92\x95" + "\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad" + "\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5" + "\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd" + "\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5" + "\xf8\xfb\xfe\x01\x04\x07\x0a\x0d" + "\x10\x13\x16\x19\x1c\x1f\x22\x25" + "\x28\x2b\x2e\x31\x34\x37\x3a\x3d" + "\x40\x43\x46\x49\x4c\x4f\x52\x55" + "\x58\x5b\x5e\x61\x64\x67\x6a\x6d" + "\x70\x73\x76\x79\x7c\x7f\x82\x85" + "\x88\x8b\x8e\x91\x94\x97\x9a\x9d" + "\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5" + "\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd" + "\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5" + "\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd" + "\x00\x05\x0a\x0f\x14\x19\x1e\x23" + "\x28\x2d\x32\x37\x3c\x41\x46\x4b" + "\x50\x55\x5a\x5f\x64\x69\x6e\x73" + "\x78\x7d\x82\x87\x8c\x91\x96\x9b" + "\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3" + "\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb" + "\xf0\xf5\xfa\xff\x04\x09\x0e\x13" + "\x18\x1d\x22\x27\x2c\x31\x36\x3b" + "\x40\x45\x4a\x4f\x54\x59\x5e\x63" + "\x68\x6d\x72\x77\x7c\x81\x86\x8b" + "\x90\x95\x9a\x9f\xa4\xa9\xae\xb3" + "\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb" + "\xe0\xe5\xea\xef\xf4\xf9\xfe\x03" + "\x08\x0d\x12\x17\x1c\x21\x26\x2b" + "\x30\x35\x3a\x3f\x44\x49\x4e\x53" + "\x58\x5d\x62\x67\x6c\x71\x76\x7b" + "\x80\x85\x8a\x8f\x94\x99\x9e\xa3" + "\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb" + "\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3" + "\xf8\xfd\x02\x07\x0c\x11\x16\x1b" + "\x20\x25\x2a\x2f\x34\x39\x3e\x43" + "\x48\x4d\x52\x57\x5c\x61\x66\x6b" + "\x70\x75\x7a\x7f\x84\x89\x8e\x93" + "\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb" + "\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3" + "\xe8\xed\xf2\xf7\xfc\x01\x06\x0b" + "\x10\x15\x1a\x1f\x24\x29\x2e\x33" + "\x38\x3d\x42\x47\x4c\x51\x56\x5b" + "\x60\x65\x6a\x6f\x74\x79\x7e\x83" + "\x88\x8d\x92\x97\x9c\xa1\xa6\xab" + "\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3" + "\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb" + "\x00\x07\x0e\x15\x1c\x23\x2a\x31" + "\x38\x3f\x46\x4d\x54\x5b\x62\x69" + "\x70\x77\x7e\x85\x8c\x93\x9a\xa1" + "\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9" + "\xe0\xe7\xee\xf5\xfc\x03\x0a\x11" + "\x18\x1f\x26\x2d\x34\x3b\x42\x49" + "\x50\x57\x5e\x65\x6c\x73\x7a\x81" + "\x88\x8f\x96\x9d\xa4\xab\xb2\xb9" + "\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1" + "\xf8\xff\x06\x0d\x14\x1b\x22\x29" + "\x30\x37\x3e\x45\x4c\x53\x5a\x61" + "\x68\x6f\x76\x7d\x84\x8b\x92\x99" + "\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1" + "\xd8\xdf\xe6\xed\xf4\xfb\x02\x09" + "\x10\x17\x1e\x25\x2c\x33\x3a\x41" + "\x48\x4f\x56\x5d\x64\x6b\x72\x79" + "\x80\x87\x8e\x95\x9c\xa3\xaa\xb1" + "\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9" + "\xf0\xf7\xfe\x05\x0c\x13\x1a\x21" + "\x28\x2f\x36\x3d\x44\x4b\x52\x59" + "\x60\x67\x6e\x75\x7c\x83\x8a\x91" + "\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9" + "\xd0\xd7\xde\xe5\xec\xf3\xfa\x01" + "\x08\x0f\x16\x1d\x24\x2b\x32\x39" + "\x40\x47\x4e\x55\x5c\x63\x6a\x71" + "\x78\x7f\x86\x8d\x94\x9b\xa2\xa9" + "\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1" + "\xe8\xef\xf6\xfd\x04\x0b\x12\x19" + "\x20\x27\x2e\x35\x3c\x43\x4a\x51" + "\x58\x5f\x66\x6d\x74\x7b\x82\x89" + "\x90\x97\x9e\xa5\xac\xb3\xba\xc1" + "\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9" + "\x00\x09\x12\x1b\x24\x2d\x36\x3f" + "\x48\x51\x5a\x63\x6c\x75\x7e\x87" + "\x90\x99\xa2\xab\xb4\xbd\xc6\xcf" + "\xd8\xe1\xea\xf3\xfc\x05\x0e\x17" + "\x20\x29\x32\x3b\x44\x4d\x56\x5f" + "\x68\x71\x7a\x83\x8c\x95\x9e\xa7" + "\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef" + "\xf8\x01\x0a\x13\x1c\x25\x2e\x37" + "\x40\x49\x52\x5b\x64\x6d\x76\x7f" + "\x88\x91\x9a\xa3\xac\xb5\xbe\xc7" + "\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f" + "\x18\x21\x2a\x33\x3c\x45\x4e\x57" + "\x60\x69\x72\x7b\x84\x8d\x96\x9f" + "\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7" + "\xf0\xf9\x02\x0b\x14\x1d\x26\x2f" + "\x38\x41\x4a\x53\x5c\x65\x6e\x77" + "\x80\x89\x92\x9b\xa4\xad\xb6\xbf" + "\xc8\xd1\xda\xe3\xec\xf5\xfe\x07" + "\x10\x19\x22\x2b\x34\x3d\x46\x4f" + "\x58\x61\x6a\x73\x7c\x85\x8e\x97" + "\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf" + "\xe8\xf1\xfa\x03\x0c\x15\x1e\x27" + "\x30\x39\x42\x4b\x54\x5d\x66\x6f" + "\x78\x81\x8a\x93\x9c\xa5\xae\xb7" + "\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff" + "\x08\x11\x1a\x23\x2c\x35\x3e\x47" + "\x50\x59\x62\x6b\x74\x7d\x86\x8f" + "\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7" + "\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f" + "\x28\x31\x3a\x43\x4c\x55\x5e\x67" + "\x70\x79\x82\x8b\x94\x9d\xa6\xaf" + "\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7" + "\x00\x0b\x16\x21\x2c\x37\x42\x4d" + "\x58\x63\x6e\x79\x84\x8f\x9a\xa5" + "\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd" + "\x08\x13\x1e\x29\x34\x3f\x4a\x55" + "\x60\x6b\x76\x81\x8c\x97\xa2\xad" + "\xb8\xc3\xce\xd9\xe4\xef\xfa\x05" + "\x10\x1b\x26\x31\x3c\x47\x52\x5d" + "\x68\x73\x7e\x89\x94\x9f\xaa\xb5" + "\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d" + "\x18\x23\x2e\x39\x44\x4f\x5a\x65" + "\x70\x7b\x86\x91\x9c\xa7\xb2\xbd" + "\xc8\xd3\xde\xe9\xf4\xff\x0a\x15" + "\x20\x2b\x36\x41\x4c\x57\x62\x6d" + "\x78\x83\x8e\x99\xa4\xaf\xba\xc5" + "\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d" + "\x28\x33\x3e\x49\x54\x5f\x6a\x75" + "\x80\x8b\x96\xa1\xac\xb7\xc2\xcd" + "\xd8\xe3\xee\xf9\x04\x0f\x1a\x25" + "\x30\x3b\x46\x51\x5c\x67\x72\x7d" + "\x88\x93\x9e\xa9\xb4\xbf\xca\xd5" + "\xe0\xeb\xf6\x01\x0c\x17\x22\x2d" + "\x38\x43\x4e\x59\x64\x6f\x7a\x85" + "\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd" + "\xe8\xf3\xfe\x09\x14\x1f\x2a\x35" + "\x40\x4b\x56\x61\x6c\x77\x82\x8d" + "\x98\xa3\xae\xb9\xc4\xcf\xda\xe5" + "\xf0\xfb\x06\x11\x1c\x27\x32\x3d" + "\x48\x53\x5e\x69\x74\x7f\x8a\x95" + "\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed" + "\xf8\x03\x0e\x19\x24\x2f\x3a\x45" + "\x50\x5b\x66\x71\x7c\x87\x92\x9d" + "\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5" + "\x00\x0d\x1a\x27\x34\x41\x4e\x5b" + "\x68\x75\x82\x8f\x9c\xa9\xb6\xc3" + "\xd0\xdd\xea\xf7\x04\x11\x1e\x2b" + "\x38\x45\x52\x5f\x6c\x79\x86\x93" + "\xa0\xad\xba\xc7\xd4\xe1\xee\xfb" + "\x08\x15\x22\x2f\x3c\x49\x56\x63" + "\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb" + "\xd8\xe5\xf2\xff\x0c\x19\x26\x33" + "\x40\x4d\x5a\x67\x74\x81\x8e\x9b" + "\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03" + "\x10\x1d\x2a\x37\x44\x51\x5e\x6b" + "\x78\x85\x92\x9f\xac\xb9\xc6\xd3" + "\xe0\xed\xfa\x07\x14\x21\x2e\x3b" + "\x48\x55\x62\x6f\x7c\x89\x96\xa3" + "\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b" + "\x18\x25\x32\x3f\x4c\x59\x66\x73" + "\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb" + "\xe8\xf5\x02\x0f\x1c\x29\x36\x43" + "\x50\x5d\x6a\x77\x84\x91\x9e\xab" + "\xb8\xc5\xd2\xdf\xec\xf9\x06\x13" + "\x20\x2d\x3a\x47\x54\x61\x6e\x7b" + "\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3" + "\xf0\xfd\x0a\x17\x24\x31\x3e\x4b" + "\x58\x65\x72\x7f\x8c\x99\xa6\xb3" + "\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b" + "\x28\x35\x42\x4f\x5c\x69\x76\x83" + "\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb" + "\xf8\x05\x12\x1f\x2c\x39\x46\x53" + "\x60\x6d\x7a\x87\x94\xa1\xae\xbb" + "\xc8\xd5\xe2\xef\xfc\x09\x16\x23" + "\x30\x3d\x4a\x57\x64\x71\x7e\x8b" + "\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3" + "\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69" + "\x78\x87\x96\xa5\xb4\xc3\xd2\xe1" + "\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59" + "\x68\x77\x86\x95\xa4\xb3\xc2\xd1" + "\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49" + "\x58\x67\x76\x85\x94\xa3\xb2\xc1" + "\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39" + "\x48\x57\x66\x75\x84\x93\xa2\xb1" + "\xc0\xcf\xde\xed\xfc\x0b\x1a\x29" + "\x38\x47\x56\x65\x74\x83\x92\xa1" + "\xb0\xbf\xce\xdd\xec\xfb\x0a\x19" + "\x28\x37\x46\x55\x64\x73\x82\x91" + "\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09" + "\x18\x27\x36\x45\x54\x63\x72\x81" + "\x90\x9f\xae\xbd\xcc\xdb\xea\xf9" + "\x08\x17\x26\x35\x44\x53\x62\x71" + "\x80\x8f\x9e\xad\xbc\xcb\xda\xe9" + "\xf8\x07\x16\x25\x34\x43\x52\x61" + "\x70\x7f\x8e\x9d\xac\xbb\xca\xd9" + "\xe8\xf7\x06\x15\x24\x33\x42\x51" + "\x60\x6f\x7e\x8d\x9c\xab\xba\xc9" + "\xd8\xe7\xf6\x05\x14\x23\x32\x41" + "\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9" + "\xc8\xd7\xe6\xf5\x04\x13\x22\x31" + "\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9" + "\xb8\xc7\xd6\xe5\xf4\x03\x12\x21" + "\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99" + "\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11" + "\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89" + "\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01" + "\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79" + "\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1" + "\x00\x11\x22\x33\x44\x55\x66\x77" + "\x88\x99\xaa\xbb\xcc\xdd\xee\xff" + "\x10\x21\x32\x43\x54\x65\x76\x87" + "\x98\xa9\xba\xcb\xdc\xed\xfe\x0f" + "\x20\x31\x42\x53\x64\x75\x86\x97" + "\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f" + "\x30\x41\x52\x63\x74\x85\x96\xa7" + "\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f" + "\x40\x51\x62\x73\x84\x95\xa6\xb7" + "\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f" + "\x50\x61\x72\x83\x94\xa5\xb6\xc7" + "\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f" + "\x60\x71\x82\x93\xa4\xb5\xc6\xd7" + "\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f" + "\x70\x81\x92\xa3\xb4\xc5\xd6\xe7" + "\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f" + "\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7" + "\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f" + "\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07" + "\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f" + "\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17" + "\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f" + "\xb0\xc1\xd2\xe3\xf4\x05\x16\x27" + "\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf" + "\xc0\xd1\xe2\xf3\x04\x15\x26\x37" + "\x48\x59\x6a\x7b\x8c\x9d\xae\xbf" + "\xd0\xe1\xf2\x03\x14\x25\x36\x47" + "\x58\x69\x7a\x8b\x9c\xad\xbe\xcf" + "\xe0\xf1\x02\x13\x24\x35\x46\x57" + "\x68\x79\x8a\x9b\xac\xbd\xce\xdf" + "\xf0\x01\x12\x23\x34\x45\x56\x67" + "\x78\x89\x9a\xab\xbc\xcd\xde\xef" + "\x00\x13\x26\x39\x4c\x5f\x72\x85" + "\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d" + "\x30\x43\x56\x69\x7c\x8f\xa2\xb5" + "\xc8\xdb\xee\x01\x14\x27\x3a\x4d" + "\x60\x73\x86\x99\xac\xbf\xd2\xe5" + "\xf8\x0b\x1e\x31\x44\x57\x6a\x7d" + "\x90\xa3\xb6\xc9\xdc\xef\x02\x15" + "\x28\x3b\x4e\x61\x74\x87\x9a\xad" + "\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45" + "\x58\x6b\x7e\x91\xa4\xb7\xca\xdd" + "\xf0\x03\x16\x29\x3c\x4f\x62\x75" + "\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d" + "\x20\x33\x46\x59\x6c\x7f\x92\xa5" + "\xb8\xcb\xde\xf1\x04\x17\x2a\x3d" + "\x50\x63\x76\x89\x9c\xaf\xc2\xd5" + "\xe8\xfb\x0e\x21\x34\x47\x5a\x6d" + "\x80\x93\xa6\xb9\xcc\xdf\xf2\x05" + "\x18\x2b\x3e\x51\x64\x77\x8a\x9d" + "\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35" + "\x48\x5b\x6e\x81\x94\xa7\xba\xcd" + "\xe0\xf3\x06\x19\x2c\x3f\x52\x65" + "\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd" + "\x10\x23\x36\x49\x5c\x6f\x82\x95" + "\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d" + "\x40\x53\x66\x79\x8c\x9f\xb2\xc5" + "\xd8\xeb\xfe\x11\x24\x37\x4a\x5d" + "\x70\x83\x96\xa9\xbc\xcf\xe2\xf5" + "\x08\x1b\x2e\x41\x54\x67\x7a\x8d" + "\xa0\xb3\xc6\xd9\xec\xff\x12\x25" + "\x38\x4b\x5e\x71\x84\x97\xaa\xbd" + "\xd0\xe3\xf6\x09\x1c\x2f\x42\x55" + "\x68\x7b\x8e\xa1\xb4\xc7\xda\xed" + "\x00\x15\x2a\x3f\x54\x69\x7e\x93" + "\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b" + "\x50\x65\x7a\x8f\xa4\xb9\xce\xe3" + "\xf8\x0d\x22\x37\x4c\x61\x76\x8b" + "\xa0\xb5\xca\xdf\xf4\x09\x1e\x33" + "\x48\x5d\x72\x87\x9c\xb1\xc6\xdb" + "\xf0\x05\x1a\x2f\x44\x59\x6e\x83" + "\x98\xad\xc2\xd7\xec\x01\x16\x2b" + "\x40\x55\x6a\x7f\x94\xa9\xbe\xd3" + "\xe8\xfd\x12\x27\x3c\x51\x66\x7b" + "\x90\xa5\xba\xcf\xe4\xf9\x0e\x23" + "\x38\x4d\x62\x77\x8c\xa1\xb6\xcb" + "\xe0\xf5\x0a\x1f\x34\x49\x5e\x73" + "\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b" + "\x30\x45\x5a\x6f\x84\x99\xae\xc3" + "\xd8\xed\x02\x17\x2c\x41\x56\x6b" + "\x80\x95\xaa\xbf\xd4\xe9\xfe\x13" + "\x28\x3d\x52\x67\x7c\x91\xa6\xbb" + "\xd0\xe5\xfa\x0f\x24\x39\x4e\x63" + "\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b" + "\x20\x35\x4a\x5f\x74\x89\x9e\xb3" + "\xc8\xdd\xf2\x07\x1c\x31\x46\x5b" + "\x70\x85\x9a\xaf\xc4\xd9\xee\x03" + "\x18\x2d\x42\x57\x6c\x81\x96\xab" + "\xc0\xd5\xea\xff\x14\x29\x3e\x53" + "\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb" + "\x10\x25\x3a\x4f\x64\x79\x8e\xa3" + "\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b" + "\x60\x75\x8a\x9f\xb4\xc9\xde\xf3" + "\x08\x1d\x32\x47\x5c\x71\x86\x9b" + "\xb0\xc5\xda\xef\x04\x19\x2e\x43" + "\x58\x6d\x82\x97\xac\xc1\xd6\xeb" + "\x00\x17\x2e\x45\x5c\x73\x8a\xa1" + "\xb8\xcf\xe6\xfd\x14\x2b\x42\x59" + "\x70\x87\x9e\xb5\xcc\xe3\xfa\x11" + "\x28\x3f\x56\x6d\x84\x9b\xb2\xc9" + "\xe0\xf7\x0e\x25\x3c\x53\x6a\x81" + "\x98\xaf\xc6\xdd\xf4\x0b\x22\x39" + "\x50\x67\x7e\x95\xac\xc3\xda\xf1" + "\x08\x1f\x36\x4d\x64\x7b\x92\xa9" + "\xc0\xd7\xee\x05\x1c\x33\x4a\x61" + "\x78\x8f\xa6\xbd\xd4\xeb\x02\x19" + "\x30\x47\x5e\x75\x8c\xa3\xba\xd1" + "\xe8\xff\x16\x2d\x44\x5b\x72\x89" + "\xa0\xb7\xce\xe5\xfc\x13\x2a\x41" + "\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9" + "\x10\x27\x3e\x55\x6c\x83\x9a\xb1" + "\xc8\xdf\xf6\x0d\x24\x3b\x52\x69" + "\x80\x97\xae\xc5\xdc\xf3\x0a\x21" + "\x38\x4f\x66\x7d\x94\xab\xc2\xd9" + "\xf0\x07\x1e\x35\x4c\x63\x7a\x91" + "\xa8\xbf\xd6\xed\x04\x1b\x32\x49" + "\x60\x77\x8e\xa5\xbc\xd3\xea\x01" + "\x18\x2f\x46\x5d\x74\x8b\xa2\xb9" + "\xd0\xe7\xfe\x15\x2c\x43\x5a\x71" + "\x88\x9f\xb6\xcd\xe4\xfb\x12\x29" + "\x40\x57\x6e\x85\x9c\xb3\xca\xe1" + "\xf8\x0f\x26\x3d\x54\x6b\x82\x99" + "\xb0\xc7\xde\xf5\x0c\x23\x3a\x51" + "\x68\x7f\x96\xad\xc4\xdb\xf2\x09" + "\x20\x37\x4e\x65\x7c\x93\xaa\xc1" + "\xd8\xef\x06\x1d\x34\x4b\x62\x79" + "\x90\xa7\xbe\xd5\xec\x03\x1a\x31" + "\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9" + "\x00\x19\x32\x4b\x64\x7d\x96\xaf" + "\xc8\xe1\xfa\x13\x2c\x45\x5e\x77" + "\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f" + "\x58\x71\x8a\xa3\xbc\xd5\xee\x07" + "\x20\x39\x52\x6b\x84\x9d\xb6\xcf" + "\xe8\x01\x1a\x33\x4c\x65\x7e\x97" + "\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f" + "\x78\x91\xaa\xc3\xdc\xf5\x0e\x27" + "\x40\x59\x72\x8b\xa4\xbd\xd6\xef" + "\x08\x21\x3a\x53\x6c\x85\x9e\xb7" + "\xd0\xe9\x02\x1b\x34\x4d\x66\x7f" + "\x98\xb1\xca\xe3\xfc\x15\x2e\x47" + "\x60\x79\x92\xab\xc4\xdd\xf6\x0f" + "\x28\x41\x5a\x73\x8c\xa5\xbe\xd7" + "\xf0\x09\x22\x3b\x54\x6d\x86\x9f" + "\xb8\xd1\xea\x03\x1c\x35\x4e\x67" + "\x80\x99\xb2\xcb\xe4\xfd\x16\x2f" + "\x48\x61\x7a\x93\xac\xc5\xde\xf7" + "\x10\x29\x42\x5b\x74\x8d\xa6\xbf" + "\xd8\xf1\x0a\x23\x3c\x55\x6e\x87" + "\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f" + "\x68\x81\x9a\xb3\xcc\xe5\xfe\x17" + "\x30\x49\x62\x7b\x94\xad\xc6\xdf" + "\xf8\x11\x2a\x43\x5c\x75\x8e\xa7" + "\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f" + "\x88\xa1\xba\xd3\xec\x05\x1e\x37" + "\x50\x69\x82\x9b\xb4\xcd\xe6\xff" + "\x18\x31\x4a\x63\x7c\x95\xae\xc7" + "\xe0\xf9\x12\x2b\x44\x5d\x76\x8f" + "\xa8\xc1\xda\xf3\x0c\x25\x3e\x57" + "\x70\x89\xa2\xbb\xd4\xed\x06\x1f" + "\x38\x51\x6a\x83\x9c\xb5\xce\xe7" + "\x00\x1b\x36\x51\x6c\x87\xa2\xbd" + "\xd8\xf3\x0e\x29\x44\x5f\x7a\x95" + "\xb0\xcb\xe6\x01\x1c\x37\x52\x6d" + "\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45" + "\x60\x7b\x96\xb1\xcc\xe7\x02\x1d" + "\x38\x53\x6e\x89\xa4\xbf\xda\xf5" + "\x10\x2b\x46\x61\x7c\x97\xb2\xcd" + "\xe8\x03\x1e\x39\x54\x6f\x8a\xa5" + "\xc0\xdb\xf6\x11\x2c\x47\x62\x7d" + "\x98\xb3\xce\xe9\x04\x1f\x3a\x55" + "\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d" + "\x48\x63\x7e\x99\xb4\xcf\xea\x05" + "\x20\x3b\x56\x71\x8c\xa7\xc2\xdd" + "\xf8\x13\x2e\x49\x64\x7f\x9a\xb5" + "\xd0\xeb\x06\x21\x3c\x57\x72\x8d" + "\xa8\xc3\xde\xf9\x14\x2f\x4a\x65" + "\x80\x9b\xb6\xd1\xec\x07\x22\x3d" + "\x58\x73\x8e\xa9\xc4\xdf\xfa\x15" + "\x30\x4b\x66\x81\x9c\xb7\xd2\xed" + "\x08\x23\x3e\x59\x74\x8f\xaa\xc5" + "\xe0\xfb\x16\x31\x4c\x67\x82\x9d" + "\xb8\xd3\xee\x09\x24\x3f\x5a\x75" + "\x90\xab\xc6\xe1\xfc\x17\x32\x4d" + "\x68\x83\x9e\xb9\xd4\xef\x0a\x25" + "\x40\x5b\x76\x91\xac\xc7\xe2\xfd" + "\x18\x33\x4e\x69\x84\x9f\xba\xd5" + "\xf0\x0b\x26\x41\x5c\x77\x92\xad" + "\xc8\xe3\xfe\x19\x34\x4f\x6a\x85" + "\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d" + "\x78\x93\xae\xc9\xe4\xff\x1a\x35" + "\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d" + "\x28\x43\x5e\x79\x94\xaf\xca\xe5" + "\x00\x1d\x3a\x57\x74\x91\xae\xcb" + "\xe8\x05\x22\x3f\x5c\x79\x96\xb3" + "\xd0\xed\x0a\x27\x44\x61\x7e\x9b" + "\xb8\xd5\xf2\x0f\x2c\x49\x66\x83" + "\xa0\xbd\xda\xf7\x14\x31\x4e\x6b" + "\x88\xa5\xc2\xdf\xfc\x19\x36\x53" + "\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b" + "\x58\x75\x92\xaf\xcc\xe9\x06\x23" + "\x40\x5d\x7a\x97\xb4\xd1\xee\x0b" + "\x28\x45\x62\x7f\x9c\xb9\xd6\xf3" + "\x10\x2d\x4a\x67\x84\xa1\xbe\xdb" + "\xf8\x15\x32\x4f\x6c\x89\xa6\xc3" + "\xe0\xfd\x1a\x37\x54\x71\x8e\xab" + "\xc8\xe5\x02\x1f\x3c\x59\x76\x93" + "\xb0\xcd\xea\x07\x24\x41\x5e\x7b" + "\x98\xb5\xd2\xef\x0c\x29\x46\x63" + "\x80\x9d\xba\xd7\xf4\x11\x2e\x4b" + "\x68\x85\xa2\xbf\xdc\xf9\x16\x33" + "\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b" + "\x38\x55\x72\x8f\xac\xc9\xe6\x03" + "\x20\x3d\x5a\x77\x94\xb1\xce\xeb" + "\x08\x25\x42\x5f\x7c\x99\xb6\xd3" + "\xf0\x0d\x2a\x47\x64\x81\x9e\xbb" + "\xd8\xf5\x12\x2f\x4c\x69\x86\xa3" + "\xc0\xdd\xfa\x17\x34\x51\x6e\x8b" + "\xa8\xc5\xe2\xff\x1c\x39\x56\x73" + "\x90\xad\xca\xe7\x04\x21\x3e\x5b" + "\x78\x95\xb2\xcf\xec\x09\x26\x43" + "\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b" + "\x48\x65\x82\x9f\xbc\xd9\xf6\x13" + "\x30\x4d\x6a\x87\xa4\xc1\xde\xfb" + "\x18\x35\x52\x6f\x8c\xa9\xc6\xe3" + "\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9" + "\xf8\x17\x36\x55\x74\x93\xb2\xd1" + "\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9" + "\xe8\x07\x26\x45\x64\x83\xa2\xc1" + "\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9" + "\xd8\xf7\x16\x35\x54\x73\x92\xb1" + "\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9" + "\xc8\xe7\x06\x25\x44\x63\x82\xa1" + "\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99" + "\xb8\xd7\xf6\x15\x34\x53\x72\x91" + "\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89" + "\xa8\xc7\xe6\x05\x24\x43\x62\x81" + "\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79" + "\x98\xb7\xd6\xf5\x14\x33\x52\x71" + "\x90\xaf\xce\xed\x0c\x2b\x4a\x69" + "\x88\xa7\xc6\xe5\x04\x23\x42\x61" + "\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59" + "\x78\x97\xb6\xd5\xf4\x13\x32\x51" + "\x70\x8f\xae\xcd\xec\x0b\x2a\x49" + "\x68\x87\xa6\xc5\xe4\x03\x22\x41" + "\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39" + "\x58\x77\x96\xb5\xd4\xf3\x12\x31" + "\x50\x6f\x8e\xad\xcc\xeb\x0a\x29" + "\x48\x67\x86\xa5\xc4\xe3\x02\x21" + "\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19" + "\x38\x57\x76\x95\xb4\xd3\xf2\x11" + "\x30\x4f\x6e\x8d\xac\xcb\xea\x09" + "\x28\x47\x66\x85\xa4\xc3\xe2\x01" + "\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9" + "\x18\x37\x56\x75\x94\xb3\xd2\xf1" + "\x10\x2f\x4e\x6d\x8c\xab\xca\xe9" + "\x08\x27\x46\x65\x84\xa3\xc2\xe1" + "\x00\x21\x42\x63", + .ilen = 4100, + .result = + "\xb5\x81\xf5\x64\x18\x73\xe3\xf0" + "\x4c\x13\xf2\x77\x18\x60\x65\x5e" + "\x29\x01\xce\x98\x55\x53\xf9\x0c" + "\x2a\x08\xd5\x09\xb3\x57\x55\x56" + "\xc5\xe9\x56\x90\xcb\x6a\xa3\xc0" + "\xff\xc4\x79\xb4\xd2\x97\x5d\xc4" + "\x43\xd1\xfe\x94\x7b\x88\x06\x5a" + "\xb2\x9e\x2c\xfc\x44\x03\xb7\x90" + "\xa0\xc1\xba\x6a\x33\xb8\xc7\xb2" + "\x9d\xe1\x12\x4f\xc0\x64\xd4\x01" + "\xfe\x8c\x7a\x66\xf7\xe6\x5a\x91" + "\xbb\xde\x56\x86\xab\x65\x21\x30" + "\x00\x84\x65\x24\xa5\x7d\x85\xb4" + "\xe3\x17\xed\x3a\xb7\x6f\xb4\x0b" + "\x0b\xaf\x15\xae\x5a\x8f\xf2\x0c" + "\x2f\x27\xf4\x09\xd8\xd2\x96\xb7" + "\x71\xf2\xc5\x99\x4d\x7e\x7f\x75" + "\x77\x89\x30\x8b\x59\xdb\xa2\xb2" + "\xa0\xf3\x19\x39\x2b\xc5\x7e\x3f" + "\x4f\xd9\xd3\x56\x28\x97\x44\xdc" + "\xc0\x8b\x77\x24\xd9\x52\xe7\xc5" + "\xaf\xf6\x7d\x59\xb2\x44\x05\x1d" + "\xb1\xb0\x11\xa5\x0f\xec\x33\xe1" + "\x6d\x1b\x4e\x1f\xff\x57\x91\xb4" + "\x5b\x9a\x96\xc5\x53\xbc\xae\x20" + "\x3c\xbb\x14\xe2\xe8\x22\x33\xc1" + "\x5e\x76\x9e\x46\x99\xf6\x2a\x15" + "\xc6\x97\x02\xa0\x66\x43\xd1\xa6" + "\x31\xa6\x9f\xfb\xf4\xd3\x69\xe5" + "\xcd\x76\x95\xb8\x7a\x82\x7f\x21" + "\x45\xff\x3f\xce\x55\xf6\x95\x10" + "\x08\x77\x10\x43\xc6\xf3\x09\xe5" + "\x68\xe7\x3c\xad\x00\x52\x45\x0d" + "\xfe\x2d\xc6\xc2\x94\x8c\x12\x1d" + "\xe6\x25\xae\x98\x12\x8e\x19\x9c" + "\x81\x68\xb1\x11\xf6\x69\xda\xe3" + "\x62\x08\x18\x7a\x25\x49\x28\xac" + "\xba\x71\x12\x0b\xe4\xa2\xe5\xc7" + "\x5d\x8e\xec\x49\x40\x21\xbf\x5a" + "\x98\xf3\x02\x68\x55\x03\x7f\x8a" + "\xe5\x94\x0c\x32\x5c\x07\x82\x63" + "\xaf\x6f\x91\x40\x84\x8e\x52\x25" + "\xd0\xb0\x29\x53\x05\xe2\x50\x7a" + "\x34\xeb\xc9\x46\x20\xa8\x3d\xde" + "\x7f\x16\x5f\x36\xc5\x2e\xdc\xd1" + "\x15\x47\xc7\x50\x40\x6d\x91\xc5" + "\xe7\x93\x95\x1a\xd3\x57\xbc\x52" + "\x33\xee\x14\x19\x22\x52\x89\xa7" + "\x4a\x25\x56\x77\x4b\xca\xcf\x0a" + "\xe1\xf5\x35\x85\x30\x7e\x59\x4a" + "\xbd\x14\x5b\xdf\xe3\x46\xcb\xac" + "\x1f\x6c\x96\x0e\xf4\x81\xd1\x99" + "\xca\x88\x63\x3d\x02\x58\x6b\xa9" + "\xe5\x9f\xb3\x00\xb2\x54\xc6\x74" + "\x1c\xbf\x46\xab\x97\xcc\xf8\x54" + "\x04\x07\x08\x52\xe6\xc0\xda\x93" + "\x74\x7d\x93\x99\x5d\x78\x68\xa6" + "\x2e\x6b\xd3\x6a\x69\xcc\x12\x6b" + "\xd4\xc7\xa5\xc6\xe7\xf6\x03\x04" + "\x5d\xcd\x61\x5e\x17\x40\xdc\xd1" + "\x5c\xf5\x08\xdf\x5c\x90\x85\xa4" + "\xaf\xf6\x78\xbb\x0d\xf1\xf4\xa4" + "\x54\x26\x72\x9e\x61\xfa\x86\xcf" + "\xe8\x9e\xa1\xe0\xc7\x48\x23\xae" + "\x5a\x90\xae\x75\x0a\x74\x18\x89" + "\x05\xb1\x92\xb2\x7f\xd0\x1b\xa6" + "\x62\x07\x25\x01\xc7\xc2\x4f\xf9" + "\xe8\xfe\x63\x95\x80\x07\xb4\x26" + "\xcc\xd1\x26\xb6\xc4\x3f\x9e\xcb" + "\x8e\x3b\x2e\x44\x16\xd3\x10\x9a" + "\x95\x08\xeb\xc8\xcb\xeb\xbf\x6f" + "\x0b\xcd\x1f\xc8\xca\x86\xaa\xec" + "\x33\xe6\x69\xf4\x45\x25\x86\x3a" + "\x22\x94\x4f\x00\x23\x6a\x44\xc2" + "\x49\x97\x33\xab\x36\x14\x0a\x70" + "\x24\xc3\xbe\x04\x3b\x79\xa0\xf9" + "\xb8\xe7\x76\x29\x22\x83\xd7\xf2" + "\x94\xf4\x41\x49\xba\x5f\x7b\x07" + "\xb5\xfb\xdb\x03\x1a\x9f\xb6\x4c" + "\xc2\x2e\x37\x40\x49\xc3\x38\x16" + "\xe2\x4f\x77\x82\xb0\x68\x4c\x71" + "\x1d\x57\x61\x9c\xd9\x4e\x54\x99" + "\x47\x13\x28\x73\x3c\xbb\x00\x90" + "\xf3\x4d\xc9\x0e\xfd\xe7\xb1\x71" + "\xd3\x15\x79\xbf\xcc\x26\x2f\xbd" + "\xad\x6c\x50\x69\x6c\x3e\x6d\x80" + "\x9a\xea\x78\xaf\x19\xb2\x0d\x4d" + "\xad\x04\x07\xae\x22\x90\x4a\x93" + "\x32\x0e\x36\x9b\x1b\x46\xba\x3b" + "\xb4\xac\xc6\xd1\xa2\x31\x53\x3b" + "\x2a\x3d\x45\xfe\x03\x61\x10\x85" + "\x17\x69\xa6\x78\xcc\x6c\x87\x49" + "\x53\xf9\x80\x10\xde\x80\xa2\x41" + "\x6a\xc3\x32\x02\xad\x6d\x3c\x56" + "\x00\x71\x51\x06\xa7\xbd\xfb\xef" + "\x3c\xb5\x9f\xfc\x48\x7d\x53\x7c" + "\x66\xb0\x49\x23\xc4\x47\x10\x0e" + "\xe5\x6c\x74\x13\xe6\xc5\x3f\xaa" + "\xde\xff\x07\x44\xdd\x56\x1b\xad" + "\x09\x77\xfb\x5b\x12\xb8\x0d\x38" + "\x17\x37\x35\x7b\x9b\xbc\xfe\xd4" + "\x7e\x8b\xda\x7e\x5b\x04\xa7\x22" + "\xa7\x31\xa1\x20\x86\xc7\x1b\x99" + "\xdb\xd1\x89\xf4\x94\xa3\x53\x69" + "\x8d\xe7\xe8\x74\x11\x8d\x74\xd6" + "\x07\x37\x91\x9f\xfd\x67\x50\x3a" + "\xc9\xe1\xf4\x36\xd5\xa0\x47\xd1" + "\xf9\xe5\x39\xa3\x31\xac\x07\x36" + "\x23\xf8\x66\x18\x14\x28\x34\x0f" + "\xb8\xd0\xe7\x29\xb3\x04\x4b\x55" + "\x01\x41\xb2\x75\x8d\xcb\x96\x85" + "\x3a\xfb\xab\x2b\x9e\xfa\x58\x20" + "\x44\x1f\xc0\x14\x22\x75\x61\xe8" + "\xaa\x19\xcf\xf1\x82\x56\xf4\xd7" + "\x78\x7b\x3d\x5f\xb3\x9e\x0b\x8a" + "\x57\x50\xdb\x17\x41\x65\x4d\xa3" + "\x02\xc9\x9c\x9c\x53\xfb\x39\x39" + "\x9b\x1d\x72\x24\xda\xb7\x39\xbe" + "\x13\x3b\xfa\x29\xda\x9e\x54\x64" + "\x6e\xba\xd8\xa1\xcb\xb3\x36\xfa" + "\xcb\x47\x85\xe9\x61\x38\xbc\xbe" + "\xc5\x00\x38\x2a\x54\xf7\xc4\xb9" + "\xb3\xd3\x7b\xa0\xa0\xf8\x72\x7f" + "\x8c\x8e\x82\x0e\xc6\x1c\x75\x9d" + "\xca\x8e\x61\x87\xde\xad\x80\xd2" + "\xf5\xf9\x80\xef\x15\x75\xaf\xf5" + "\x80\xfb\xff\x6d\x1e\x25\xb7\x40" + "\x61\x6a\x39\x5a\x6a\xb5\x31\xab" + "\x97\x8a\x19\x89\x44\x40\xc0\xa6" + "\xb4\x4e\x30\x32\x7b\x13\xe7\x67" + "\xa9\x8b\x57\x04\xc2\x01\xa6\xf4" + "\x28\x99\xad\x2c\x76\xa3\x78\xc2" + "\x4a\xe6\xca\x5c\x50\x6a\xc1\xb0" + "\x62\x4b\x10\x8e\x7c\x17\x43\xb3" + "\x17\x66\x1c\x3e\x8d\x69\xf0\x5a" + "\x71\xf5\x97\xdc\xd1\x45\xdd\x28" + "\xf3\x5d\xdf\x53\x7b\x11\xe5\xbc" + "\x4c\xdb\x1b\x51\x6b\xe9\xfb\x3d" + "\xc1\xc3\x2c\xb9\x71\xf5\xb6\xb2" + "\x13\x36\x79\x80\x53\xe8\xd3\xa6" + "\x0a\xaf\xfd\x56\x97\xf7\x40\x8e" + "\x45\xce\xf8\xb0\x9e\x5c\x33\x82" + "\xb0\x44\x56\xfc\x05\x09\xe9\x2a" + "\xac\x26\x80\x14\x1d\xc8\x3a\x35" + "\x4c\x82\x97\xfd\x76\xb7\xa9\x0a" + "\x35\x58\x79\x8e\x0f\x66\xea\xaf" + "\x51\x6c\x09\xa9\x6e\x9b\xcb\x9a" + "\x31\x47\xa0\x2f\x7c\x71\xb4\x4a" + "\x11\xaa\x8c\x66\xc5\x64\xe6\x3a" + "\x54\xda\x24\x6a\xc4\x41\x65\x46" + "\x82\xa0\x0a\x0f\x5f\xfb\x25\xd0" + "\x2c\x91\xa7\xee\xc4\x81\x07\x86" + "\x75\x5e\x33\x69\x97\xe4\x2c\xa8" + "\x9d\x9f\x0b\x6a\xbe\xad\x98\xda" + "\x6d\x94\x41\xda\x2c\x1e\x89\xc4" + "\xc2\xaf\x1e\x00\x05\x0b\x83\x60" + "\xbd\x43\xea\x15\x23\x7f\xb9\xac" + "\xee\x4f\x2c\xaf\x2a\xf3\xdf\xd0" + "\xf3\x19\x31\xbb\x4a\x74\x84\x17" + "\x52\x32\x2c\x7d\x61\xe4\xcb\xeb" + "\x80\x38\x15\x52\xcb\x6f\xea\xe5" + "\x73\x9c\xd9\x24\x69\xc6\x95\x32" + "\x21\xc8\x11\xe4\xdc\x36\xd7\x93" + "\x38\x66\xfb\xb2\x7f\x3a\xb9\xaf" + "\x31\xdd\x93\x75\x78\x8a\x2c\x94" + "\x87\x1a\x58\xec\x9e\x7d\x4d\xba" + "\xe1\xe5\x4d\xfc\xbc\xa4\x2a\x14" + "\xef\xcc\xa7\xec\xab\x43\x09\x18" + "\xd3\xab\x68\xd1\x07\x99\x44\x47" + "\xd6\x83\x85\x3b\x30\xea\xa9\x6b" + "\x63\xea\xc4\x07\xfb\x43\x2f\xa4" + "\xaa\xb0\xab\x03\x89\xce\x3f\x8c" + "\x02\x7c\x86\x54\xbc\x88\xaf\x75" + "\xd2\xdc\x63\x17\xd3\x26\xf6\x96" + "\xa9\x3c\xf1\x61\x8c\x11\x18\xcc" + "\xd6\xea\x5b\xe2\xcd\xf0\xf1\xb2" + "\xe5\x35\x90\x1f\x85\x4c\x76\x5b" + "\x66\xce\x44\xa4\x32\x9f\xe6\x7b" + "\x71\x6e\x9f\x58\x15\x67\x72\x87" + "\x64\x8e\x3a\x44\x45\xd4\x76\xfa" + "\xc2\xf6\xef\x85\x05\x18\x7a\x9b" + "\xba\x41\x54\xac\xf0\xfc\x59\x12" + "\x3f\xdf\xa0\xe5\x8a\x65\xfd\x3a" + "\x62\x8d\x83\x2c\x03\xbe\x05\x76" + "\x2e\x53\x49\x97\x94\x33\xae\x40" + "\x81\x15\xdb\x6e\xad\xaa\xf5\x4b" + "\xe3\x98\x70\xdf\xe0\x7c\xcd\xdb" + "\x02\xd4\x7d\x2f\xc1\xe6\xb4\xf3" + "\xd7\x0d\x7a\xd9\x23\x9e\x87\x2d" + "\xce\x87\xad\xcc\x72\x05\x00\x29" + "\xdc\x73\x7f\x64\xc1\x15\x0e\xc2" + "\xdf\xa7\x5f\xeb\x41\xa1\xcd\xef" + "\x5c\x50\x79\x2a\x56\x56\x71\x8c" + "\xac\xc0\x79\x50\x69\xca\x59\x32" + "\x65\xf2\x54\xe4\x52\x38\x76\xd1" + "\x5e\xde\x26\x9e\xfb\x75\x2e\x11" + "\xb5\x10\xf4\x17\x73\xf5\x89\xc7" + "\x4f\x43\x5c\x8e\x7c\xb9\x05\x52" + "\x24\x40\x99\xfe\x9b\x85\x0b\x6c" + "\x22\x3e\x8b\xae\x86\xa1\xd2\x79" + "\x05\x68\x6b\xab\xe3\x41\x49\xed" + "\x15\xa1\x8d\x40\x2d\x61\xdf\x1a" + "\x59\xc9\x26\x8b\xef\x30\x4c\x88" + "\x4b\x10\xf8\x8d\xa6\x92\x9f\x4b" + "\xf3\xc4\x53\x0b\x89\x5d\x28\x92" + "\xcf\x78\xb2\xc0\x5d\xed\x7e\xfc" + "\xc0\x12\x23\x5f\x5a\x78\x86\x43" + "\x6e\x27\xf7\x5a\xa7\x6a\xed\x19" + "\x04\xf0\xb3\x12\xd1\xbd\x0e\x89" + "\x6e\xbc\x96\xa8\xd8\x49\x39\x9f" + "\x7e\x67\xf0\x2e\x3e\x01\xa9\xba" + "\xec\x8b\x62\x8e\xcb\x4a\x70\x43" + "\xc7\xc2\xc4\xca\x82\x03\x73\xe9" + "\x11\xdf\xcf\x54\xea\xc9\xb0\x95" + "\x51\xc0\x13\x3d\x92\x05\xfa\xf4" + "\xa9\x34\xc8\xce\x6c\x3d\x54\xcc" + "\xc4\xaf\xf1\xdc\x11\x44\x26\xa2" + "\xaf\xf1\x85\x75\x7d\x03\x61\x68" + "\x4e\x78\xc6\x92\x7d\x86\x7d\x77" + "\xdc\x71\x72\xdb\xc6\xae\xa1\xcb" + "\x70\x9a\x0b\x19\xbe\x4a\x6c\x2a" + "\xe2\xba\x6c\x64\x9a\x13\x28\xdf" + "\x85\x75\xe6\x43\xf6\x87\x08\x68" + "\x6e\xba\x6e\x79\x9f\x04\xbc\x23" + "\x50\xf6\x33\x5c\x1f\x24\x25\xbe" + "\x33\x47\x80\x45\x56\xa3\xa7\xd7" + "\x7a\xb1\x34\x0b\x90\x3c\x9c\xad" + "\x44\x5f\x9e\x0e\x9d\xd4\xbd\x93" + "\x5e\xfa\x3c\xe0\xb0\xd9\xed\xf3" + "\xd6\x2e\xff\x24\xd8\x71\x6c\xed" + "\xaf\x55\xeb\x22\xac\x93\x68\x32" + "\x05\x5b\x47\xdd\xc6\x4a\xcb\xc7" + "\x10\xe1\x3c\x92\x1a\xf3\x23\x78" + "\x2b\xa1\xd2\x80\xf4\x12\xb1\x20" + "\x8f\xff\x26\x35\xdd\xfb\xc7\x4e" + "\x78\xf1\x2d\x50\x12\x77\xa8\x60" + "\x7c\x0f\xf5\x16\x2f\x63\x70\x2a" + "\xc0\x96\x80\x4e\x0a\xb4\x93\x35" + "\x5d\x1d\x3f\x56\xf7\x2f\xbb\x90" + "\x11\x16\x8f\xa2\xec\x47\xbe\xac" + "\x56\x01\x26\x56\xb1\x8c\xb2\x10" + "\xf9\x1a\xca\xf5\xd1\xb7\x39\x20" + "\x63\xf1\x69\x20\x4f\x13\x12\x1f" + "\x5b\x65\xfc\x98\xf7\xc4\x7a\xbe" + "\xf7\x26\x4d\x2b\x84\x7b\x42\xad" + "\xd8\x7a\x0a\xb4\xd8\x74\xbf\xc1" + "\xf0\x6e\xb4\x29\xa3\xbb\xca\x46" + "\x67\x70\x6a\x2d\xce\x0e\xa2\x8a" + "\xa9\x87\xbf\x05\xc4\xc1\x04\xa3" + "\xab\xd4\x45\x43\x8c\xb6\x02\xb0" + "\x41\xc8\xfc\x44\x3d\x59\xaa\x2e" + "\x44\x21\x2a\x8d\x88\x9d\x57\xf4" + "\xa0\x02\x77\xb8\xa6\xa0\xe6\x75" + "\x5c\x82\x65\x3e\x03\x5c\x29\x8f" + "\x38\x55\xab\x33\x26\xef\x9f\x43" + "\x52\xfd\x68\xaf\x36\xb4\xbb\x9a" + "\x58\x09\x09\x1b\xc3\x65\x46\x46" + "\x1d\xa7\x94\x18\x23\x50\x2c\xca" + "\x2c\x55\x19\x97\x01\x9d\x93\x3b" + "\x63\x86\xf2\x03\x67\x45\xd2\x72" + "\x28\x52\x6c\xf4\xe3\x1c\xb5\x11" + "\x13\xf1\xeb\x21\xc7\xd9\x56\x82" + "\x2b\x82\x39\xbd\x69\x54\xed\x62" + "\xc3\xe2\xde\x73\xd4\x6a\x12\xae" + "\x13\x21\x7f\x4b\x5b\xfc\xbf\xe8" + "\x2b\xbe\x56\xba\x68\x8b\x9a\xb1" + "\x6e\xfa\xbf\x7e\x5a\x4b\xf1\xac" + "\x98\x65\x85\xd1\x93\x53\xd3\x7b" + "\x09\xdd\x4b\x10\x6d\x84\xb0\x13" + "\x65\xbd\xcf\x52\x09\xc4\x85\xe2" + "\x84\x74\x15\x65\xb7\xf7\x51\xaf" + "\x55\xad\xa4\xd1\x22\x54\x70\x94" + "\xa0\x1c\x90\x41\xfd\x99\xd7\x5a" + "\x31\xef\xaa\x25\xd0\x7f\x4f\xea" + "\x1d\x55\x42\xe5\x49\xb0\xd0\x46" + "\x62\x36\x43\xb2\x82\x15\x75\x50" + "\xa4\x72\xeb\x54\x27\x1f\x8a\xe4" + "\x7d\xe9\x66\xc5\xf1\x53\xa4\xd1" + "\x0c\xeb\xb8\xf8\xbc\xd4\xe2\xe7" + "\xe1\xf8\x4b\xcb\xa9\xa1\xaf\x15" + "\x83\xcb\x72\xd0\x33\x79\x00\x2d" + "\x9f\xd7\xf1\x2e\x1e\x10\xe4\x45" + "\xc0\x75\x3a\x39\xea\x68\xf7\x5d" + "\x1b\x73\x8f\xe9\x8e\x0f\x72\x47" + "\xae\x35\x0a\x31\x7a\x14\x4d\x4a" + "\x6f\x47\xf7\x7e\x91\x6e\x74\x8b" + "\x26\x47\xf9\xc3\xf9\xde\x70\xf5" + "\x61\xab\xa9\x27\x9f\x82\xe4\x9c" + "\x89\x91\x3f\x2e\x6a\xfd\xb5\x49" + "\xe9\xfd\x59\x14\x36\x49\x40\x6d" + "\x32\xd8\x85\x42\xf3\xa5\xdf\x0c" + "\xa8\x27\xd7\x54\xe2\x63\x2f\xf2" + "\x7e\x8b\x8b\xe7\xf1\x9a\x95\x35" + "\x43\xdc\x3a\xe4\xb6\xf4\xd0\xdf" + "\x9c\xcb\x94\xf3\x21\xa0\x77\x50" + "\xe2\xc6\xc4\xc6\x5f\x09\x64\x5b" + "\x92\x90\xd8\xe1\xd1\xed\x4b\x42" + "\xd7\x37\xaf\x65\x3d\x11\x39\xb6" + "\x24\x8a\x60\xae\xd6\x1e\xbf\x0e" + "\x0d\xd7\xdc\x96\x0e\x65\x75\x4e" + "\x29\x06\x9d\xa4\x51\x3a\x10\x63" + "\x8f\x17\x07\xd5\x8e\x3c\xf4\x28" + "\x00\x5a\x5b\x05\x19\xd8\xc0\x6c" + "\xe5\x15\xe4\x9c\x9d\x71\x9d\x5e" + "\x94\x29\x1a\xa7\x80\xfa\x0e\x33" + "\x03\xdd\xb7\x3e\x9a\xa9\x26\x18" + "\x37\xa9\x64\x08\x4d\x94\x5a\x88" + "\xca\x35\xce\x81\x02\xe3\x1f\x1b" + "\x89\x1a\x77\x85\xe3\x41\x6d\x32" + "\x42\x19\x23\x7d\xc8\x73\xee\x25" + "\x85\x0d\xf8\x31\x25\x79\x1b\x6f" + "\x79\x25\xd2\xd8\xd4\x23\xfd\xf7" + "\x82\x36\x6a\x0c\x46\x22\x15\xe9" + "\xff\x72\x41\x91\x91\x7d\x3a\xb7" + "\xdd\x65\x99\x70\xf6\x8d\x84\xf8" + "\x67\x15\x20\x11\xd6\xb2\x55\x7b" + "\xdb\x87\xee\xef\x55\x89\x2a\x59" + "\x2b\x07\x8f\x43\x8a\x59\x3c\x01" + "\x8b\x65\x54\xa1\x66\xd5\x38\xbd" + "\xc6\x30\xa9\xcc\x49\xb6\xa8\x1b" + "\xb8\xc0\x0e\xe3\x45\x28\xe2\xff" + "\x41\x9f\x7e\x7c\xd1\xae\x9e\x25" + "\x3f\x4c\x7c\x7c\xf4\xa8\x26\x4d" + "\x5c\xfd\x4b\x27\x18\xf9\x61\x76" + "\x48\xba\x0c\x6b\xa9\x4d\xfc\xf5" + "\x3b\x35\x7e\x2f\x4a\xa9\xc2\x9a" + "\xae\xab\x86\x09\x89\xc9\xc2\x40" + "\x39\x2c\x81\xb3\xb8\x17\x67\xc2" + "\x0d\x32\x4a\x3a\x67\x81\xd7\x1a" + "\x34\x52\xc5\xdb\x0a\xf5\x63\x39" + "\xea\x1f\xe1\x7c\xa1\x9e\xc1\x35" + "\xe3\xb1\x18\x45\x67\xf9\x22\x38" + "\x95\xd9\x34\x34\x86\xc6\x41\x94" + "\x15\xf9\x5b\x41\xa6\x87\x8b\xf8" + "\xd5\xe1\x1b\xe2\x5b\xf3\x86\x10" + "\xff\xe6\xae\x69\x76\xbc\x0d\xb4" + "\x09\x90\x0c\xa2\x65\x0c\xad\x74" + "\xf5\xd7\xff\xda\xc1\xce\x85\xbe" + "\x00\xa7\xff\x4d\x2f\x65\xd3\x8c" + "\x86\x2d\x05\xe8\xed\x3e\x6b\x8b" + "\x0f\x3d\x83\x8c\xf1\x1d\x5b\x96" + "\x2e\xb1\x9c\xc2\x98\xe1\x70\xb9" + "\xba\x5c\x8a\x43\xd6\x34\xa7\x2d" + "\xc9\x92\xae\xf2\xa5\x7b\x05\x49" + "\xa7\x33\x34\x86\xca\xe4\x96\x23" + "\x76\x5b\xf2\xc6\xf1\x51\x28\x42" + "\x7b\xcc\x76\x8f\xfa\xa2\xad\x31" + "\xd4\xd6\x7a\x6d\x25\x25\x54\xe4" + "\x3f\x50\x59\xe1\x5c\x05\xb7\x27" + "\x48\xbf\x07\xec\x1b\x13\xbe\x2b" + "\xa1\x57\x2b\xd5\xab\xd7\xd0\x4c" + "\x1e\xcb\x71\x9b\xc5\x90\x85\xd3" + "\xde\x59\xec\x71\xeb\x89\xbb\xd0" + "\x09\x50\xe1\x16\x3f\xfd\x1c\x34" + "\xc3\x1c\xa1\x10\x77\x53\x98\xef" + "\xf2\xfd\xa5\x01\x59\xc2\x9b\x26" + "\xc7\x42\xd9\x49\xda\x58\x2b\x6e" + "\x9f\x53\x19\x76\x7e\xd9\xc9\x0e" + "\x68\xc8\x7f\x51\x22\x42\xef\x49" + "\xa4\x55\xb6\x36\xac\x09\xc7\x31" + "\x88\x15\x4b\x2e\x8f\x3a\x08\xf7" + "\xd8\xf7\xa8\xc5\xa9\x33\xa6\x45" + "\xe4\xc4\x94\x76\xf3\x0d\x8f\x7e" + "\xc8\xf6\xbc\x23\x0a\xb6\x4c\xd3" + "\x6a\xcd\x36\xc2\x90\x5c\x5c\x3c" + "\x65\x7b\xc2\xd6\xcc\xe6\x0d\x87" + "\x73\x2e\x71\x79\x16\x06\x63\x28" + "\x09\x15\xd8\x89\x38\x38\x3d\xb5" + "\x42\x1c\x08\x24\xf7\x2a\xd2\x9d" + "\xc8\xca\xef\xf9\x27\xd8\x07\x86" + "\xf7\x43\x0b\x55\x15\x3f\x9f\x83" + "\xef\xdc\x49\x9d\x2a\xc1\x54\x62" + "\xbd\x9b\x66\x55\x9f\xb7\x12\xf3" + "\x1b\x4d\x9d\x2a\x5c\xed\x87\x75" + "\x87\x26\xec\x61\x2c\xb4\x0f\x89" + "\xb0\xfb\x2e\x68\x5d\x15\xc7\x8d" + "\x2e\xc0\xd9\xec\xaf\x4f\xd2\x25" + "\x29\xe8\xd2\x26\x2b\x67\xe9\xfc" + "\x2b\xa8\x67\x96\x12\x1f\x5b\x96" + "\xc6\x14\x53\xaf\x44\xea\xd6\xe2" + "\x94\x98\xe4\x12\x93\x4c\x92\xe0" + "\x18\xa5\x8d\x2d\xe4\x71\x3c\x47" + "\x4c\xf7\xe6\x47\x9e\xc0\x68\xdf" + "\xd4\xf5\x5a\x74\xb1\x2b\x29\x03" + "\x19\x07\xaf\x90\x62\x5c\x68\x98" + "\x48\x16\x11\x02\x9d\xee\xb4\x9b" + "\xe5\x42\x7f\x08\xfd\x16\x32\x0b" + "\xd0\xb3\xfa\x2b\xb7\x99\xf9\x29" + "\xcd\x20\x45\x9f\xb3\x1a\x5d\xa2" + "\xaf\x4d\xe0\xbd\x42\x0d\xbc\x74" + "\x99\x9c\x8e\x53\x1a\xb4\x3e\xbd" + "\xa2\x9a\x2d\xf7\xf8\x39\x0f\x67" + "\x63\xfc\x6b\xc0\xaf\xb3\x4b\x4f" + "\x55\xc4\xcf\xa7\xc8\x04\x11\x3e" + "\x14\x32\xbb\x1b\x38\x77\xd6\x7f" + "\x54\x4c\xdf\x75\xf3\x07\x2d\x33" + "\x9b\xa8\x20\xe1\x7b\x12\xb5\xf3" + "\xef\x2f\xce\x72\xe5\x24\x60\xc1" + "\x30\xe2\xab\xa1\x8e\x11\x09\xa8" + "\x21\x33\x44\xfe\x7f\x35\x32\x93" + "\x39\xa7\xad\x8b\x79\x06\xb2\xcb" + "\x4e\xa9\x5f\xc7\xba\x74\x29\xec" + "\x93\xa0\x4e\x54\x93\xc0\xbc\x55" + "\x64\xf0\x48\xe5\x57\x99\xee\x75" + "\xd6\x79\x0f\x66\xb7\xc6\x57\x76" + "\xf7\xb7\xf3\x9c\xc5\x60\xe8\x7f" + "\x83\x76\xd6\x0e\xaa\xe6\x90\x39" + "\x1d\xa6\x32\x6a\x34\xe3\x55\xf8" + "\x58\xa0\x58\x7d\x33\xe0\x22\x39" + "\x44\x64\x87\x86\x5a\x2f\xa7\x7e" + "\x0f\x38\xea\xb0\x30\xcc\x61\xa5" + "\x6a\x32\xae\x1e\xf7\xe9\xd0\xa9" + "\x0c\x32\x4b\xb5\x49\x28\xab\x85" + "\x2f\x8e\x01\x36\x38\x52\xd0\xba" + "\xd6\x02\x78\xf8\x0e\x3e\x9c\x8b" + "\x6b\x45\x99\x3f\x5c\xfe\x58\xf1" + "\x5c\x94\x04\xe1\xf5\x18\x6d\x51" + "\xb2\x5d\x18\x20\xb6\xc2\x9a\x42" + "\x1d\xb3\xab\x3c\xb6\x3a\x13\x03" + "\xb2\x46\x82\x4f\xfc\x64\xbc\x4f" + "\xca\xfa\x9c\xc0\xd5\xa7\xbd\x11" + "\xb7\xe4\x5a\xf6\x6f\x4d\x4d\x54" + "\xea\xa4\x98\x66\xd4\x22\x3b\xd3" + "\x8f\x34\x47\xd9\x7c\xf4\x72\x3b" + "\x4d\x02\x77\xf6\xd6\xdd\x08\x0a" + "\x81\xe1\x86\x89\x3e\x56\x10\x3c" + "\xba\xd7\x81\x8c\x08\xbc\x8b\xe2" + "\x53\xec\xa7\x89\xee\xc8\x56\xb5" + "\x36\x2c\xb2\x03\xba\x99\xdd\x7c" + "\x48\xa0\xb0\xbc\x91\x33\xe9\xa8" + "\xcb\xcd\xcf\x59\x5f\x1f\x15\xe2" + "\x56\xf5\x4e\x01\x35\x27\x45\x77" + "\x47\xc8\xbc\xcb\x7e\x39\xc1\x97" + "\x28\xd3\x84\xfc\x2c\x3e\xc8\xad" + "\x9c\xf8\x8a\x61\x9c\x28\xaa\xc5" + "\x99\x20\x43\x85\x9d\xa5\xe2\x8b" + "\xb8\xae\xeb\xd0\x32\x0d\x52\x78" + "\x09\x56\x3f\xc7\xd8\x7e\x26\xfc" + "\x37\xfb\x6f\x04\xfc\xfa\x92\x10" + "\xac\xf8\x3e\x21\xdc\x8c\x21\x16" + "\x7d\x67\x6e\xf6\xcd\xda\xb6\x98" + "\x23\xab\x23\x3c\xb2\x10\xa0\x53" + "\x5a\x56\x9f\xc5\xd0\xff\xbb\xe4" + "\x98\x3c\x69\x1e\xdb\x38\x8f\x7e" + "\x0f\xd2\x98\x88\x81\x8b\x45\x67" + "\xea\x33\xf1\xeb\xe9\x97\x55\x2e" + "\xd9\xaa\xeb\x5a\xec\xda\xe1\x68" + "\xa8\x9d\x3c\x84\x7c\x05\x3d\x62" + "\x87\x8f\x03\x21\x28\x95\x0c\x89" + "\x25\x22\x4a\xb0\x93\xa9\x50\xa2" + "\x2f\x57\x6e\x18\x42\x19\x54\x0c" + "\x55\x67\xc6\x11\x49\xf4\x5c\xd2" + "\xe9\x3d\xdd\x8b\x48\x71\x21\x00" + "\xc3\x9a\x6c\x85\x74\x28\x83\x4a" + "\x1b\x31\x05\xe1\x06\x92\xe7\xda" + "\x85\x73\x78\x45\x20\x7f\xae\x13" + "\x7c\x33\x06\x22\xf4\x83\xf9\x35" + "\x3f\x6c\x71\xa8\x4e\x48\xbe\x9b" + "\xce\x8a\xba\xda\xbe\x28\x08\xf7" + "\xe2\x14\x8c\x71\xea\x72\xf9\x33" + "\xf2\x88\x3f\xd7\xbb\x69\x6c\x29" + "\x19\xdc\x84\xce\x1f\x12\x4f\xc8" + "\xaf\xa5\x04\xba\x5a\xab\xb0\xd9" + "\x14\x1f\x6c\x68\x98\x39\x89\x7a" + "\xd9\xd8\x2f\xdf\xa8\x47\x4a\x25" + "\xe2\xfb\x33\xf4\x59\x78\xe1\x68" + "\x85\xcf\xfe\x59\x20\xd4\x05\x1d" + "\x80\x99\xae\xbc\xca\xae\x0f\x2f" + "\x65\x43\x34\x8e\x7e\xac\xd3\x93" + "\x2f\xac\x6d\x14\x3d\x02\x07\x70" + "\x9d\xa4\xf3\x1b\x5c\x36\xfc\x01" + "\x73\x34\x85\x0c\x6c\xd6\xf1\xbd" + "\x3f\xdf\xee\xf5\xd9\xba\x56\xef" + "\xf4\x9b\x6b\xee\x9f\x5a\x78\x6d" + "\x32\x19\xf4\xf7\xf8\x4c\x69\x0b" + "\x4b\xbc\xbb\xb7\xf2\x85\xaf\x70" + "\x75\x24\x6c\x54\xa7\x0e\x4d\x1d" + "\x01\xbf\x08\xac\xcf\x7f\x2c\xe3" + "\x14\x89\x5e\x70\x5a\x99\x92\xcd" + "\x01\x84\xc8\xd2\xab\xe5\x4f\x58" + "\xe7\x0f\x2f\x0e\xff\x68\xea\xfd" + "\x15\xb3\x17\xe6\xb0\xe7\x85\xd8" + "\x23\x2e\x05\xc7\xc9\xc4\x46\x1f" + "\xe1\x9e\x49\x20\x23\x24\x4d\x7e" + "\x29\x65\xff\xf4\xb6\xfd\x1a\x85" + "\xc4\x16\xec\xfc\xea\x7b\xd6\x2c" + "\x43\xf8\xb7\xbf\x79\xc0\x85\xcd" + "\xef\xe1\x98\xd3\xa5\xf7\x90\x8c" + "\xe9\x7f\x80\x6b\xd2\xac\x4c\x30" + "\xa7\xc6\x61\x6c\xd2\xf9\x2c\xff" + "\x30\xbc\x22\x81\x7d\x93\x12\xe4" + "\x0a\xcd\xaf\xdd\xe8\xab\x0a\x1e" + "\x13\xa4\x27\xc3\x5f\xf7\x4b\xbb" + "\x37\x09\x4b\x91\x6f\x92\x4f\xaf" + "\x52\xee\xdf\xef\x09\x6f\xf7\x5c" + "\x6e\x12\x17\x72\x63\x57\xc7\xba" + "\x3b\x6b\x38\x32\x73\x1b\x9c\x80" + "\xc1\x7a\xc6\xcf\xcd\x35\xc0\x6b" + "\x31\x1a\x6b\xe9\xd8\x2c\x29\x3f" + "\x96\xfb\xb6\xcd\x13\x91\x3b\xc2" + "\xd2\xa3\x31\x8d\xa4\xcd\x57\xcd" + "\x13\x3d\x64\xfd\x06\xce\xe6\xdc" + "\x0c\x24\x43\x31\x40\x57\xf1\x72" + "\x17\xe3\x3a\x63\x6d\x35\xcf\x5d" + "\x97\x40\x59\xdd\xf7\x3c\x02\xf7" + "\x1c\x7e\x05\xbb\xa9\x0d\x01\xb1" + "\x8e\xc0\x30\xa9\x53\x24\xc9\x89" + "\x84\x6d\xaa\xd0\xcd\x91\xc2\x4d" + "\x91\xb0\x89\xe2\xbf\x83\x44\xaa" + "\x28\x72\x23\xa0\xc2\xad\xad\x1c" + "\xfc\x3f\x09\x7a\x0b\xdc\xc5\x1b" + "\x87\x13\xc6\x5b\x59\x8d\xf2\xc8" + "\xaf\xdf\x11\x95", + .rlen = 4100, + .np = 2, + .tap = { 4064, 36 }, + }, +}; + +/* + * CTS (Cipher Text Stealing) mode tests + */ +#define CTS_MODE_ENC_TEST_VECTORS 6 +#define CTS_MODE_DEC_TEST_VECTORS 6 +static struct cipher_testvec cts_mode_enc_tv_template[] = { + { /* from rfc3962 */ + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .ilen = 17, + .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20", + .rlen = 17, + .result = "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4" + "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f" + "\x97", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .ilen = 31, + .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20", + .rlen = 31, + .result = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1" + "\xd4\x45\xd4\xc8\xef\xf7\xed\x22" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .ilen = 32, + .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43", + .rlen = 32, + .result = "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .ilen = 47, + .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20" + "\x70\x6c\x65\x61\x73\x65\x2c", + .rlen = 47, + .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c" + "\x1b\x55\x49\xd2\xf8\x38\x02\x9e" + "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .ilen = 48, + .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20" + "\x70\x6c\x65\x61\x73\x65\x2c\x20", + .rlen = 48, + .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" + "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8" + "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .ilen = 64, + .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20" + "\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74" + "\x6f\x6e\x20\x73\x6f\x75\x70\x2e", + .rlen = 64, + .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x48\x07\xef\xe8\x36\xee\x89\xa5" + "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" + "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8", + } +}; + +static struct cipher_testvec cts_mode_dec_tv_template[] = { + { /* from rfc3962 */ + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .rlen = 17, + .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20", + .ilen = 17, + .input = "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4" + "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f" + "\x97", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .rlen = 31, + .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20", + .ilen = 31, + .input = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1" + "\xd4\x45\xd4\xc8\xef\xf7\xed\x22" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .rlen = 32, + .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43", + .ilen = 32, + .input = "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .rlen = 47, + .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20" + "\x70\x6c\x65\x61\x73\x65\x2c", + .ilen = 47, + .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c" + "\x1b\x55\x49\xd2\xf8\x38\x02\x9e" + "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .rlen = 48, + .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20" + "\x70\x6c\x65\x61\x73\x65\x2c\x20", + .ilen = 48, + .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" + "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8" + "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8", + }, { + .klen = 16, + .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20" + "\x74\x65\x72\x69\x79\x61\x6b\x69", + .rlen = 64, + .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20" + "\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c" + "\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20" + "\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74" + "\x6f\x6e\x20\x73\x6f\x75\x70\x2e", + .ilen = 64, + .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0" + "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x39\x31\x25\x23\xa7\x86\x62\xd5" + "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x48\x07\xef\xe8\x36\xee\x89\xa5" + "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0" + "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8", + } +}; + +/* + * Compression stuff. + */ +#define COMP_BUF_SIZE 512 + +struct comp_testvec { + int inlen, outlen; + char input[COMP_BUF_SIZE]; + char output[COMP_BUF_SIZE]; +}; + +/* + * Deflate test vectors (null-terminated strings). + * Params: winbits=11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL. + */ +#define DEFLATE_COMP_TEST_VECTORS 2 +#define DEFLATE_DECOMP_TEST_VECTORS 2 + +static struct comp_testvec deflate_comp_tv_template[] = { + { + .inlen = 70, + .outlen = 38, + .input = "Join us now and share the software " + "Join us now and share the software ", + .output = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" + "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" + "\x28\xce\x48\x2c\x4a\x55\x28\xc9" + "\x48\x55\x28\xce\x4f\x2b\x29\x07" + "\x71\xbc\x08\x2b\x01\x00", + }, { + .inlen = 191, + .outlen = 122, + .input = "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + .output = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" + "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" + "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" + "\x24\xdb\x67\xd9\x47\xc1\xef\x49" + "\x68\x12\x51\xae\x76\x67\xd6\x27" + "\x19\x88\x1a\xde\x85\xab\x21\xf2" + "\x08\x5d\x16\x1e\x20\x04\x2d\xad" + "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" + "\x42\x83\x23\xb6\x6c\x89\x71\x9b" + "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" + "\xed\x62\xa9\x4c\x80\xff\x13\xaf" + "\x52\x37\xed\x0e\x52\x6b\x59\x02" + "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" + "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" + "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" + "\xfa\x02", + }, +}; + +static struct comp_testvec deflate_decomp_tv_template[] = { + { + .inlen = 122, + .outlen = 191, + .input = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" + "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" + "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" + "\x24\xdb\x67\xd9\x47\xc1\xef\x49" + "\x68\x12\x51\xae\x76\x67\xd6\x27" + "\x19\x88\x1a\xde\x85\xab\x21\xf2" + "\x08\x5d\x16\x1e\x20\x04\x2d\xad" + "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" + "\x42\x83\x23\xb6\x6c\x89\x71\x9b" + "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" + "\xed\x62\xa9\x4c\x80\xff\x13\xaf" + "\x52\x37\xed\x0e\x52\x6b\x59\x02" + "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" + "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" + "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" + "\xfa\x02", + .output = "This document describes a compression method based on the DEFLATE" + "compression algorithm. This document defines the application of " + "the DEFLATE algorithm to the IP Payload Compression Protocol.", + }, { + .inlen = 38, + .outlen = 70, + .input = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" + "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" + "\x28\xce\x48\x2c\x4a\x55\x28\xc9" + "\x48\x55\x28\xce\x4f\x2b\x29\x07" + "\x71\xbc\x08\x2b\x01\x00", + .output = "Join us now and share the software " + "Join us now and share the software ", + }, +}; + +/* + * LZO test vectors (null-terminated strings). + */ +#define LZO_COMP_TEST_VECTORS 2 +#define LZO_DECOMP_TEST_VECTORS 2 + +static struct comp_testvec lzo_comp_tv_template[] = { + { + .inlen = 70, + .outlen = 46, + .input = "Join us now and share the software " + "Join us now and share the software ", + .output = "\x00\x0d\x4a\x6f\x69\x6e\x20\x75" + "\x73\x20\x6e\x6f\x77\x20\x61\x6e" + "\x64\x20\x73\x68\x61\x72\x65\x20" + "\x74\x68\x65\x20\x73\x6f\x66\x74" + "\x77\x70\x01\x01\x4a\x6f\x69\x6e" + "\x3d\x88\x00\x11\x00\x00", + }, { + .inlen = 159, + .outlen = 133, + .input = "This document describes a compression method based on the LZO " + "compression algorithm. This document defines the application of " + "the LZO algorithm used in UBIFS.", + .output = "\x00\x2b\x54\x68\x69\x73\x20\x64" + "\x6f\x63\x75\x6d\x65\x6e\x74\x20" + "\x64\x65\x73\x63\x72\x69\x62\x65" + "\x73\x20\x61\x20\x63\x6f\x6d\x70" + "\x72\x65\x73\x73\x69\x6f\x6e\x20" + "\x6d\x65\x74\x68\x6f\x64\x20\x62" + "\x61\x73\x65\x64\x20\x6f\x6e\x20" + "\x74\x68\x65\x20\x4c\x5a\x4f\x2b" + "\x8c\x00\x0d\x61\x6c\x67\x6f\x72" + "\x69\x74\x68\x6d\x2e\x20\x20\x54" + "\x68\x69\x73\x2a\x54\x01\x02\x66" + "\x69\x6e\x65\x73\x94\x06\x05\x61" + "\x70\x70\x6c\x69\x63\x61\x74\x76" + "\x0a\x6f\x66\x88\x02\x60\x09\x27" + "\xf0\x00\x0c\x20\x75\x73\x65\x64" + "\x20\x69\x6e\x20\x55\x42\x49\x46" + "\x53\x2e\x11\x00\x00", + }, +}; + +static struct comp_testvec lzo_decomp_tv_template[] = { + { + .inlen = 133, + .outlen = 159, + .input = "\x00\x2b\x54\x68\x69\x73\x20\x64" + "\x6f\x63\x75\x6d\x65\x6e\x74\x20" + "\x64\x65\x73\x63\x72\x69\x62\x65" + "\x73\x20\x61\x20\x63\x6f\x6d\x70" + "\x72\x65\x73\x73\x69\x6f\x6e\x20" + "\x6d\x65\x74\x68\x6f\x64\x20\x62" + "\x61\x73\x65\x64\x20\x6f\x6e\x20" + "\x74\x68\x65\x20\x4c\x5a\x4f\x2b" + "\x8c\x00\x0d\x61\x6c\x67\x6f\x72" + "\x69\x74\x68\x6d\x2e\x20\x20\x54" + "\x68\x69\x73\x2a\x54\x01\x02\x66" + "\x69\x6e\x65\x73\x94\x06\x05\x61" + "\x70\x70\x6c\x69\x63\x61\x74\x76" + "\x0a\x6f\x66\x88\x02\x60\x09\x27" + "\xf0\x00\x0c\x20\x75\x73\x65\x64" + "\x20\x69\x6e\x20\x55\x42\x49\x46" + "\x53\x2e\x11\x00\x00", + .output = "This document describes a compression method based on the LZO " + "compression algorithm. This document defines the application of " + "the LZO algorithm used in UBIFS.", + }, { + .inlen = 46, + .outlen = 70, + .input = "\x00\x0d\x4a\x6f\x69\x6e\x20\x75" + "\x73\x20\x6e\x6f\x77\x20\x61\x6e" + "\x64\x20\x73\x68\x61\x72\x65\x20" + "\x74\x68\x65\x20\x73\x6f\x66\x74" + "\x77\x70\x01\x01\x4a\x6f\x69\x6e" + "\x3d\x88\x00\x11\x00\x00", + .output = "Join us now and share the software " + "Join us now and share the software ", + }, +}; + +/* + * Michael MIC test vectors from IEEE 802.11i + */ +#define MICHAEL_MIC_TEST_VECTORS 6 + +static struct hash_testvec michael_mic_tv_template[] = { + { + .key = "\x00\x00\x00\x00\x00\x00\x00\x00", + .ksize = 8, + .plaintext = zeroed_string, + .psize = 0, + .digest = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8", + }, + { + .key = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8", + .ksize = 8, + .plaintext = "M", + .psize = 1, + .digest = "\x43\x47\x21\xca\x40\x63\x9b\x3f", + }, + { + .key = "\x43\x47\x21\xca\x40\x63\x9b\x3f", + .ksize = 8, + .plaintext = "Mi", + .psize = 2, + .digest = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29", + }, + { + .key = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29", + .ksize = 8, + .plaintext = "Mic", + .psize = 3, + .digest = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb", + }, + { + .key = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb", + .ksize = 8, + .plaintext = "Mich", + .psize = 4, + .digest = "\xd5\x5e\x10\x05\x10\x12\x89\x86", + }, + { + .key = "\xd5\x5e\x10\x05\x10\x12\x89\x86", + .ksize = 8, + .plaintext = "Michael", + .psize = 7, + .digest = "\x0a\x94\x2b\x12\x4e\xca\xa5\x46", + } +}; + +/* + * CRC32C test vectors + */ +#define CRC32C_TEST_VECTORS 14 + +static struct hash_testvec crc32c_tv_template[] = { + { + .psize = 0, + .digest = "\x00\x00\x00\x00", + }, + { + .key = "\x87\xa9\xcb\xed", + .ksize = 4, + .psize = 0, + .digest = "\x78\x56\x34\x12", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25\x26\x27\x28", + .psize = 40, + .digest = "\x7f\x15\x2c\x0e", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" + "\x31\x32\x33\x34\x35\x36\x37\x38" + "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" + "\x41\x42\x43\x44\x45\x46\x47\x48" + "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50", + .psize = 40, + .digest = "\xf6\xeb\x80\xe9", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58" + "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" + "\x61\x62\x63\x64\x65\x66\x67\x68" + "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" + "\x71\x72\x73\x74\x75\x76\x77\x78", + .psize = 40, + .digest = "\xed\xbd\x74\xde", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" + "\x81\x82\x83\x84\x85\x86\x87\x88" + "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98" + "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0", + .psize = 40, + .digest = "\x62\xc8\x79\xd5", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" + "\xa9\xaa\xab\xac\xad\xae\xaf\xb0" + "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" + "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" + "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8", + .psize = 40, + .digest = "\xd0\x9a\x97\xba", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" + "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" + "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" + "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8" + "\xe9\xea\xeb\xec\xed\xee\xef\xf0", + .psize = 40, + .digest = "\x13\xd9\x29\x2b", + }, + { + .key = "\x80\xea\xd3\xf1", + .ksize = 4, + .plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" + "\x31\x32\x33\x34\x35\x36\x37\x38" + "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" + "\x41\x42\x43\x44\x45\x46\x47\x48" + "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50", + .psize = 40, + .digest = "\x0c\xb5\xe2\xa2", + }, + { + .key = "\xf3\x4a\x1d\x5d", + .ksize = 4, + .plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58" + "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" + "\x61\x62\x63\x64\x65\x66\x67\x68" + "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" + "\x71\x72\x73\x74\x75\x76\x77\x78", + .psize = 40, + .digest = "\xd1\x7f\xfb\xa6", + }, + { + .key = "\x2e\x80\x04\x59", + .ksize = 4, + .plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" + "\x81\x82\x83\x84\x85\x86\x87\x88" + "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98" + "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0", + .psize = 40, + .digest = "\x59\x33\xe6\x7a", + }, + { + .key = "\xa6\xcc\x19\x85", + .ksize = 4, + .plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" + "\xa9\xaa\xab\xac\xad\xae\xaf\xb0" + "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" + "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" + "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8", + .psize = 40, + .digest = "\xbe\x03\x01\xd2", + }, + { + .key = "\x41\xfc\xfe\x2d", + .ksize = 4, + .plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" + "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" + "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" + "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8" + "\xe9\xea\xeb\xec\xed\xee\xef\xf0", + .psize = 40, + .digest = "\x75\xd3\xc5\x24", + }, + { + .key = "\xff\xff\xff\xff", + .ksize = 4, + .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18" + "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + "\x21\x22\x23\x24\x25\x26\x27\x28" + "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" + "\x31\x32\x33\x34\x35\x36\x37\x38" + "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" + "\x41\x42\x43\x44\x45\x46\x47\x48" + "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" + "\x51\x52\x53\x54\x55\x56\x57\x58" + "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" + "\x61\x62\x63\x64\x65\x66\x67\x68" + "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" + "\x71\x72\x73\x74\x75\x76\x77\x78" + "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" + "\x81\x82\x83\x84\x85\x86\x87\x88" + "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" + "\x91\x92\x93\x94\x95\x96\x97\x98" + "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" + "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" + "\xa9\xaa\xab\xac\xad\xae\xaf\xb0" + "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8" + "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" + "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8" + "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" + "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" + "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" + "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8" + "\xe9\xea\xeb\xec\xed\xee\xef\xf0", + .psize = 240, + .digest = "\x75\xd3\xc5\x24", + .np = 2, + .tap = { 31, 209 } + }, +}; + +#endif /* _CRYPTO_TESTMGR_H */ diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 11c8c19f0fb7..f17cd4b572f8 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -663,7 +663,7 @@ config HAVE_PATA_PLATFORM config PATA_PLATFORM tristate "Generic platform device PATA support" - depends on EMBEDDED || ARCH_RPC || PPC || HAVE_PATA_PLATFORM + depends on EMBEDDED || PPC || HAVE_PATA_PLATFORM help This option enables support for generic directly connected ATA devices commonly found on embedded systems. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2e1a7cb2ed5f..aeadd00411a1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -267,8 +267,8 @@ struct ahci_port_priv { * per PM slot */ }; -static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc); @@ -316,6 +316,7 @@ static struct device_attribute *ahci_shost_attrs[] = { static struct device_attribute *ahci_sdev_attrs[] = { &dev_attr_sw_activity, + &dev_attr_unload_heads, NULL }; @@ -820,10 +821,10 @@ static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg) return 0; } -static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { - void __iomem *port_mmio = ahci_port_base(ap); - int offset = ahci_scr_offset(ap, sc_reg); + void __iomem *port_mmio = ahci_port_base(link->ap); + int offset = ahci_scr_offset(link->ap, sc_reg); if (offset) { *val = readl(port_mmio + offset); @@ -832,10 +833,10 @@ static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return -EINVAL; } -static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { - void __iomem *port_mmio = ahci_port_base(ap); - int offset = ahci_scr_offset(ap, sc_reg); + void __iomem *port_mmio = ahci_port_base(link->ap); + int offset = ahci_scr_offset(link->ap, sc_reg); if (offset) { writel(val, port_mmio + offset); @@ -973,7 +974,7 @@ static void ahci_disable_alpm(struct ata_port *ap) writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT); /* go ahead and clean out PhyRdy Change from Serror too */ - ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18))); + ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18))); /* * Clear flag to indicate that we should ignore all PhyRdy @@ -1937,8 +1938,8 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat); /* AHCI needs SError cleared; otherwise, it might lock up */ - ahci_scr_read(ap, SCR_ERROR, &serror); - ahci_scr_write(ap, SCR_ERROR, serror); + ahci_scr_read(&ap->link, SCR_ERROR, &serror); + ahci_scr_write(&ap->link, SCR_ERROR, serror); host_ehi->serror |= serror; /* some controllers set IRQ_IF_ERR on device errors, ignore it */ @@ -2027,7 +2028,7 @@ static void ahci_port_intr(struct ata_port *ap) if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) && (status & PORT_IRQ_PHYRDY)) { status &= ~PORT_IRQ_PHYRDY; - ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18))); + ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18))); } if (unlikely(status & PORT_IRQ_ERROR)) { diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index e6b4606e36b6..e9e32ed6b1a3 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -165,8 +165,10 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev); static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev); static int ich_pata_cable_detect(struct ata_port *ap); static u8 piix_vmw_bmdma_status(struct ata_port *ap); -static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val); -static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val); +static int piix_sidpr_scr_read(struct ata_link *link, + unsigned int reg, u32 *val); +static int piix_sidpr_scr_write(struct ata_link *link, + unsigned int reg, u32 val); #ifdef CONFIG_PM static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int piix_pci_device_resume(struct pci_dev *pdev); @@ -278,12 +280,15 @@ static const struct pci_device_id piix_pci_tbl[] = { /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (PCH) */ { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, - { } /* terminate list */ }; @@ -582,6 +587,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ + { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ @@ -885,23 +891,9 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev) * Serial ATA Index/Data Pair Superset Registers access * * Beginning from ICH8, there's a sane way to access SCRs using index - * and data register pair located at BAR5. This creates an - * interesting problem of mapping two SCRs to one port. - * - * Although they have separate SCRs, the master and slave aren't - * independent enough to be treated as separate links - e.g. softreset - * resets both. Also, there's no protocol defined for hard resetting - * singled device sharing the virtual port (no defined way to acquire - * device signature). This is worked around by merging the SCR values - * into one sensible value and requesting follow-up SRST after - * hardreset. - * - * SCR merging is perfomed in nibbles which is the unit contents in - * SCRs are organized. If two values are equal, the value is used. - * When they differ, merge table which lists precedence of possible - * values is consulted and the first match or the last entry when - * nothing matches is used. When there's no merge table for the - * specific nibble, value from the first port is used. + * and data register pair located at BAR5 which means that we have + * separate SCRs for master and slave. This is handled using libata + * slave_link facility. */ static const int piix_sidx_map[] = { [SCR_STATUS] = 0, @@ -909,120 +901,38 @@ static const int piix_sidx_map[] = { [SCR_CONTROL] = 1, }; -static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg) +static void piix_sidpr_sel(struct ata_link *link, unsigned int reg) { - struct ata_port *ap = dev->link->ap; + struct ata_port *ap = link->ap; struct piix_host_priv *hpriv = ap->host->private_data; - iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg], + iowrite32(((ap->port_no * 2 + link->pmp) << 8) | piix_sidx_map[reg], hpriv->sidpr + PIIX_SIDPR_IDX); } -static int piix_sidpr_read(struct ata_device *dev, unsigned int reg) -{ - struct piix_host_priv *hpriv = dev->link->ap->host->private_data; - - piix_sidpr_sel(dev, reg); - return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); -} - -static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val) -{ - struct piix_host_priv *hpriv = dev->link->ap->host->private_data; - - piix_sidpr_sel(dev, reg); - iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); -} - -static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl) -{ - u32 val = 0; - int i, mi; - - for (i = 0, mi = 0; i < 32 / 4; i++) { - u8 c0 = (val0 >> (i * 4)) & 0xf; - u8 c1 = (val1 >> (i * 4)) & 0xf; - u8 merged = c0; - const int *cur; - - /* if no merge preference, assume the first value */ - cur = merge_tbl[mi]; - if (!cur) - goto done; - mi++; - - /* if two values equal, use it */ - if (c0 == c1) - goto done; - - /* choose the first match or the last from the merge table */ - while (*cur != -1) { - if (c0 == *cur || c1 == *cur) - break; - cur++; - } - if (*cur == -1) - cur--; - merged = *cur; - done: - val |= merged << (i * 4); - } - - return val; -} - -static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val) +static int piix_sidpr_scr_read(struct ata_link *link, + unsigned int reg, u32 *val) { - const int * const sstatus_merge_tbl[] = { - /* DET */ (const int []){ 1, 3, 0, 4, 3, -1 }, - /* SPD */ (const int []){ 2, 1, 0, -1 }, - /* IPM */ (const int []){ 6, 2, 1, 0, -1 }, - NULL, - }; - const int * const scontrol_merge_tbl[] = { - /* DET */ (const int []){ 1, 0, 4, 0, -1 }, - /* SPD */ (const int []){ 0, 2, 1, 0, -1 }, - /* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 }, - NULL, - }; - u32 v0, v1; + struct piix_host_priv *hpriv = link->ap->host->private_data; if (reg >= ARRAY_SIZE(piix_sidx_map)) return -EINVAL; - if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) { - *val = piix_sidpr_read(&ap->link.device[0], reg); - return 0; - } - - v0 = piix_sidpr_read(&ap->link.device[0], reg); - v1 = piix_sidpr_read(&ap->link.device[1], reg); - - switch (reg) { - case SCR_STATUS: - *val = piix_merge_scr(v0, v1, sstatus_merge_tbl); - break; - case SCR_ERROR: - *val = v0 | v1; - break; - case SCR_CONTROL: - *val = piix_merge_scr(v0, v1, scontrol_merge_tbl); - break; - } - + piix_sidpr_sel(link, reg); + *val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA); return 0; } -static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val) +static int piix_sidpr_scr_write(struct ata_link *link, + unsigned int reg, u32 val) { + struct piix_host_priv *hpriv = link->ap->host->private_data; + if (reg >= ARRAY_SIZE(piix_sidx_map)) return -EINVAL; - piix_sidpr_write(&ap->link.device[0], reg, val); - - if (ap->flags & ATA_FLAG_SLAVE_POSS) - piix_sidpr_write(&ap->link.device[1], reg, val); - + piix_sidpr_sel(link, reg); + iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA); return 0; } @@ -1363,28 +1273,28 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, return map; } -static void __devinit piix_init_sidpr(struct ata_host *host) +static int __devinit piix_init_sidpr(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); struct piix_host_priv *hpriv = host->private_data; - struct ata_device *dev0 = &host->ports[0]->link.device[0]; + struct ata_link *link0 = &host->ports[0]->link; u32 scontrol; - int i; + int i, rc; /* check for availability */ for (i = 0; i < 4; i++) if (hpriv->map[i] == IDE) - return; + return 0; if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) - return; + return 0; if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 || pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN) - return; + return 0; if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME)) - return; + return 0; hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR]; @@ -1392,7 +1302,7 @@ static void __devinit piix_init_sidpr(struct ata_host *host) * Give it a test drive by inhibiting power save modes which * we'll do anyway. */ - scontrol = piix_sidpr_read(dev0, SCR_CONTROL); + piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); /* if IPM is already 3, SCR access is probably working. Don't * un-inhibit power save modes as BIOS might have inhibited @@ -1400,18 +1310,30 @@ static void __devinit piix_init_sidpr(struct ata_host *host) */ if ((scontrol & 0xf00) != 0x300) { scontrol |= 0x300; - piix_sidpr_write(dev0, SCR_CONTROL, scontrol); - scontrol = piix_sidpr_read(dev0, SCR_CONTROL); + piix_sidpr_scr_write(link0, SCR_CONTROL, scontrol); + piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol); if ((scontrol & 0xf00) != 0x300) { dev_printk(KERN_INFO, host->dev, "SCR access via " "SIDPR is available but doesn't work\n"); - return; + return 0; } } - host->ports[0]->ops = &piix_sidpr_sata_ops; - host->ports[1]->ops = &piix_sidpr_sata_ops; + /* okay, SCRs available, set ops and ask libata for slave_link */ + for (i = 0; i < 2; i++) { + struct ata_port *ap = host->ports[i]; + + ap->ops = &piix_sidpr_sata_ops; + + if (ap->flags & ATA_FLAG_SLAVE_POSS) { + rc = ata_slave_link_init(ap); + if (rc) + return rc; + } + } + + return 0; } static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) @@ -1521,7 +1443,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev, /* initialize controller */ if (port_flags & ATA_FLAG_SATA) { piix_init_pcs(host, piix_map_db_table[ent->driver_data]); - piix_init_sidpr(host); + rc = piix_init_sidpr(host); + if (rc) + return rc; } /* apply IOCFG bit18 quirk */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 79e3a8e7a84a..1ee9499bd343 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -163,6 +163,67 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +/* + * Iterator helpers. Don't use directly. + * + * LOCKING: + * Host lock or EH context. + */ +struct ata_link *__ata_port_next_link(struct ata_port *ap, + struct ata_link *link, bool dev_only) +{ + /* NULL link indicates start of iteration */ + if (!link) { + if (dev_only && sata_pmp_attached(ap)) + return ap->pmp_link; + return &ap->link; + } + + /* we just iterated over the host master link, what's next? */ + if (link == &ap->link) { + if (!sata_pmp_attached(ap)) { + if (unlikely(ap->slave_link) && !dev_only) + return ap->slave_link; + return NULL; + } + return ap->pmp_link; + } + + /* slave_link excludes PMP */ + if (unlikely(link == ap->slave_link)) + return NULL; + + /* iterate to the next PMP link */ + if (++link < ap->pmp_link + ap->nr_pmp_links) + return link; + return NULL; +} + +/** + * ata_dev_phys_link - find physical link for a device + * @dev: ATA device to look up physical link for + * + * Look up physical link which @dev is attached to. Note that + * this is different from @dev->link only when @dev is on slave + * link. For all other cases, it's the same as @dev->link. + * + * LOCKING: + * Don't care. + * + * RETURNS: + * Pointer to the found physical link. + */ +struct ata_link *ata_dev_phys_link(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + + if (!ap->slave_link) + return dev->link; + if (!dev->devno) + return &ap->link; + return ap->slave_link; +} + /** * ata_force_cbl - force cable type according to libata.force * @ap: ATA port of interest @@ -206,7 +267,8 @@ void ata_force_cbl(struct ata_port *ap) * the host link and all fan-out ports connected via PMP. If the * device part is specified as 0 (e.g. 1.00:), it specifies the * first fan-out link not the host link. Device number 15 always - * points to the host link whether PMP is attached or not. + * points to the host link whether PMP is attached or not. If the + * controller has slave link, device number 16 points to it. * * LOCKING: * EH context. @@ -214,12 +276,11 @@ void ata_force_cbl(struct ata_port *ap) static void ata_force_link_limits(struct ata_link *link) { bool did_spd = false; - int linkno, i; + int linkno = link->pmp; + int i; if (ata_is_host_link(link)) - linkno = 15; - else - linkno = link->pmp; + linkno += 15; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; @@ -266,9 +327,9 @@ static void ata_force_xfermask(struct ata_device *dev) int alt_devno = devno; int i; - /* allow n.15 for the first device attached to host port */ - if (ata_is_host_link(dev->link) && devno == 0) - alt_devno = 15; + /* allow n.15/16 for devices attached to host port */ + if (ata_is_host_link(dev->link)) + alt_devno += 15; for (i = ata_force_tbl_size - 1; i >= 0; i--) { const struct ata_force_ent *fe = &ata_force_tbl[i]; @@ -320,9 +381,9 @@ static void ata_force_horkage(struct ata_device *dev) int alt_devno = devno; int i; - /* allow n.15 for the first device attached to host port */ - if (ata_is_host_link(dev->link) && devno == 0) - alt_devno = 15; + /* allow n.15/16 for devices attached to host port */ + if (ata_is_host_link(dev->link)) + alt_devno += 15; for (i = 0; i < ata_force_tbl_size; i++) { const struct ata_force_ent *fe = &ata_force_tbl[i]; @@ -2681,7 +2742,7 @@ static void sata_print_link_status(struct ata_link *link) return; sata_scr_read(link, SCR_CONTROL, &scontrol); - if (ata_link_online(link)) { + if (ata_phys_link_online(link)) { tmp = (sstatus >> 4) & 0xf; ata_link_printk(link, KERN_INFO, "SATA link up %s (SStatus %X SControl %X)\n", @@ -3372,6 +3433,12 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline, unsigned long nodev_deadline = ata_deadline(start, ATA_TMOUT_FF_WAIT); int warned = 0; + /* Slave readiness can't be tested separately from master. On + * M/S emulation configuration, this function should be called + * only on the master and it will handle both master and slave. + */ + WARN_ON(link == link->ap->slave_link); + if (time_after(nodev_deadline, deadline)) nodev_deadline = deadline; @@ -3593,7 +3660,7 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline) } /* no point in trying softreset on offline link */ - if (ata_link_offline(link)) + if (ata_phys_link_offline(link)) ehc->i.action &= ~ATA_EH_SOFTRESET; return 0; @@ -3671,7 +3738,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing, if (rc) goto out; /* if link is offline nothing more to do */ - if (ata_link_offline(link)) + if (ata_phys_link_offline(link)) goto out; /* Link is online. From this point, -ENODEV too is an error. */ @@ -4868,10 +4935,8 @@ int sata_scr_valid(struct ata_link *link) int sata_scr_read(struct ata_link *link, int reg, u32 *val) { if (ata_is_host_link(link)) { - struct ata_port *ap = link->ap; - if (sata_scr_valid(link)) - return ap->ops->scr_read(ap, reg, val); + return link->ap->ops->scr_read(link, reg, val); return -EOPNOTSUPP; } @@ -4897,10 +4962,8 @@ int sata_scr_read(struct ata_link *link, int reg, u32 *val) int sata_scr_write(struct ata_link *link, int reg, u32 val) { if (ata_is_host_link(link)) { - struct ata_port *ap = link->ap; - if (sata_scr_valid(link)) - return ap->ops->scr_write(ap, reg, val); + return link->ap->ops->scr_write(link, reg, val); return -EOPNOTSUPP; } @@ -4925,13 +4988,12 @@ int sata_scr_write(struct ata_link *link, int reg, u32 val) int sata_scr_write_flush(struct ata_link *link, int reg, u32 val) { if (ata_is_host_link(link)) { - struct ata_port *ap = link->ap; int rc; if (sata_scr_valid(link)) { - rc = ap->ops->scr_write(ap, reg, val); + rc = link->ap->ops->scr_write(link, reg, val); if (rc == 0) - rc = ap->ops->scr_read(ap, reg, &val); + rc = link->ap->ops->scr_read(link, reg, &val); return rc; } return -EOPNOTSUPP; @@ -4941,7 +5003,7 @@ int sata_scr_write_flush(struct ata_link *link, int reg, u32 val) } /** - * ata_link_online - test whether the given link is online + * ata_phys_link_online - test whether the given link is online * @link: ATA link to test * * Test whether @link is online. Note that this function returns @@ -4952,20 +5014,20 @@ int sata_scr_write_flush(struct ata_link *link, int reg, u32 val) * None. * * RETURNS: - * 1 if the port online status is available and online. + * True if the port online status is available and online. */ -int ata_link_online(struct ata_link *link) +bool ata_phys_link_online(struct ata_link *link) { u32 sstatus; if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 && (sstatus & 0xf) == 0x3) - return 1; - return 0; + return true; + return false; } /** - * ata_link_offline - test whether the given link is offline + * ata_phys_link_offline - test whether the given link is offline * @link: ATA link to test * * Test whether @link is offline. Note that this function @@ -4976,16 +5038,68 @@ int ata_link_online(struct ata_link *link) * None. * * RETURNS: - * 1 if the port offline status is available and offline. + * True if the port offline status is available and offline. */ -int ata_link_offline(struct ata_link *link) +bool ata_phys_link_offline(struct ata_link *link) { u32 sstatus; if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 && (sstatus & 0xf) != 0x3) - return 1; - return 0; + return true; + return false; +} + +/** + * ata_link_online - test whether the given link is online + * @link: ATA link to test + * + * Test whether @link is online. This is identical to + * ata_phys_link_online() when there's no slave link. When + * there's a slave link, this function should only be called on + * the master link and will return true if any of M/S links is + * online. + * + * LOCKING: + * None. + * + * RETURNS: + * True if the port online status is available and online. + */ +bool ata_link_online(struct ata_link *link) +{ + struct ata_link *slave = link->ap->slave_link; + + WARN_ON(link == slave); /* shouldn't be called on slave link */ + + return ata_phys_link_online(link) || + (slave && ata_phys_link_online(slave)); +} + +/** + * ata_link_offline - test whether the given link is offline + * @link: ATA link to test + * + * Test whether @link is offline. This is identical to + * ata_phys_link_offline() when there's no slave link. When + * there's a slave link, this function should only be called on + * the master link and will return true if both M/S links are + * offline. + * + * LOCKING: + * None. + * + * RETURNS: + * True if the port offline status is available and offline. + */ +bool ata_link_offline(struct ata_link *link) +{ + struct ata_link *slave = link->ap->slave_link; + + WARN_ON(link == slave); /* shouldn't be called on slave link */ + + return ata_phys_link_offline(link) && + (!slave || ata_phys_link_offline(slave)); } #ifdef CONFIG_PM @@ -5127,11 +5241,11 @@ int ata_port_start(struct ata_port *ap) */ void ata_dev_init(struct ata_device *dev) { - struct ata_link *link = dev->link; + struct ata_link *link = ata_dev_phys_link(dev); struct ata_port *ap = link->ap; unsigned long flags; - /* SATA spd limit is bound to the first device */ + /* SATA spd limit is bound to the attached device, reset together */ link->sata_spd_limit = link->hw_sata_spd_limit; link->sata_spd = 0; @@ -5264,6 +5378,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); INIT_LIST_HEAD(&ap->eh_done_q); init_waitqueue_head(&ap->eh_wait_q); + init_completion(&ap->park_req_pending); init_timer_deferrable(&ap->fastdrain_timer); ap->fastdrain_timer.function = ata_eh_fastdrain_timerfn; ap->fastdrain_timer.data = (unsigned long)ap; @@ -5294,6 +5409,7 @@ static void ata_host_release(struct device *gendev, void *res) scsi_host_put(ap->scsi_host); kfree(ap->pmp_link); + kfree(ap->slave_link); kfree(ap); host->ports[i] = NULL; } @@ -5414,6 +5530,68 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, return host; } +/** + * ata_slave_link_init - initialize slave link + * @ap: port to initialize slave link for + * + * Create and initialize slave link for @ap. This enables slave + * link handling on the port. + * + * In libata, a port contains links and a link contains devices. + * There is single host link but if a PMP is attached to it, + * there can be multiple fan-out links. On SATA, there's usually + * a single device connected to a link but PATA and SATA + * controllers emulating TF based interface can have two - master + * and slave. + * + * However, there are a few controllers which don't fit into this + * abstraction too well - SATA controllers which emulate TF + * interface with both master and slave devices but also have + * separate SCR register sets for each device. These controllers + * need separate links for physical link handling + * (e.g. onlineness, link speed) but should be treated like a + * traditional M/S controller for everything else (e.g. command + * issue, softreset). + * + * slave_link is libata's way of handling this class of + * controllers without impacting core layer too much. For + * anything other than physical link handling, the default host + * link is used for both master and slave. For physical link + * handling, separate @ap->slave_link is used. All dirty details + * are implemented inside libata core layer. From LLD's POV, the + * only difference is that prereset, hardreset and postreset are + * called once more for the slave link, so the reset sequence + * looks like the following. + * + * prereset(M) -> prereset(S) -> hardreset(M) -> hardreset(S) -> + * softreset(M) -> postreset(M) -> postreset(S) + * + * Note that softreset is called only for the master. Softreset + * resets both M/S by definition, so SRST on master should handle + * both (the standard method will work just fine). + * + * LOCKING: + * Should be called before host is registered. + * + * RETURNS: + * 0 on success, -errno on failure. + */ +int ata_slave_link_init(struct ata_port *ap) +{ + struct ata_link *link; + + WARN_ON(ap->slave_link); + WARN_ON(ap->flags & ATA_FLAG_PMP); + + link = kzalloc(sizeof(*link), GFP_KERNEL); + if (!link) + return -ENOMEM; + + ata_link_init(ap, link, 1); + ap->slave_link = link; + return 0; +} + static void ata_host_stop(struct device *gendev, void *res) { struct ata_host *host = dev_get_drvdata(gendev); @@ -5640,6 +5818,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) /* init sata_spd_limit to the current value */ sata_link_init_spd(&ap->link); + if (ap->slave_link) + sata_link_init_spd(ap->slave_link); /* print per-port info to dmesg */ xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, @@ -6260,10 +6440,12 @@ EXPORT_SYMBOL_GPL(ata_base_port_ops); EXPORT_SYMBOL_GPL(sata_port_ops); EXPORT_SYMBOL_GPL(ata_dummy_port_ops); EXPORT_SYMBOL_GPL(ata_dummy_port_info); +EXPORT_SYMBOL_GPL(__ata_port_next_link); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_host_init); EXPORT_SYMBOL_GPL(ata_host_alloc); EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo); +EXPORT_SYMBOL_GPL(ata_slave_link_init); EXPORT_SYMBOL_GPL(ata_host_start); EXPORT_SYMBOL_GPL(ata_host_register); EXPORT_SYMBOL_GPL(ata_host_activate); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c1db2f234d2e..a93247cc395a 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -33,6 +33,7 @@ */ #include <linux/kernel.h> +#include <linux/blkdev.h> #include <linux/pci.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> @@ -79,6 +80,8 @@ enum { */ ATA_EH_PRERESET_TIMEOUT = 10000, ATA_EH_FASTDRAIN_INTERVAL = 3000, + + ATA_EH_UA_TRIES = 5, }; /* The following table determines how we sequence resets. Each entry @@ -457,29 +460,29 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev, * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) { struct Scsi_Host *host = cmd->device->host; struct ata_port *ap = ata_shost_to_port(host); unsigned long flags; struct ata_queued_cmd *qc; - enum scsi_eh_timer_return ret; + enum blk_eh_timer_return ret; DPRINTK("ENTER\n"); if (ap->ops->error_handler) { - ret = EH_NOT_HANDLED; + ret = BLK_EH_NOT_HANDLED; goto out; } - ret = EH_HANDLED; + ret = BLK_EH_HANDLED; spin_lock_irqsave(ap->lock, flags); qc = ata_qc_from_tag(ap, ap->link.active_tag); if (qc) { WARN_ON(qc->scsicmd != cmd); qc->flags |= ATA_QCFLAG_EH_SCHEDULED; qc->err_mask |= AC_ERR_TIMEOUT; - ret = EH_NOT_HANDLED; + ret = BLK_EH_NOT_HANDLED; } spin_unlock_irqrestore(ap->lock, flags); @@ -831,7 +834,7 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc) * Note that ATA_QCFLAG_FAILED is unconditionally set after * this function completes. */ - scsi_req_abort_cmd(qc->scsicmd); + blk_abort_request(qc->scsicmd->request); } /** @@ -1357,6 +1360,37 @@ static int ata_eh_read_log_10h(struct ata_device *dev, } /** + * atapi_eh_tur - perform ATAPI TEST_UNIT_READY + * @dev: target ATAPI device + * @r_sense_key: out parameter for sense_key + * + * Perform ATAPI TEST_UNIT_READY. + * + * LOCKING: + * EH context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask on failure. + */ +static unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) +{ + u8 cdb[ATAPI_CDB_LEN] = { TEST_UNIT_READY, 0, 0, 0, 0, 0 }; + struct ata_taskfile tf; + unsigned int err_mask; + + ata_tf_init(dev, &tf); + + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.command = ATA_CMD_PACKET; + tf.protocol = ATAPI_PROT_NODATA; + + err_mask = ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0); + if (err_mask == AC_ERR_DEV) + *r_sense_key = tf.feature >> 4; + return err_mask; +} + +/** * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE * @dev: device to perform REQUEST_SENSE to * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) @@ -1756,7 +1790,7 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev) static unsigned int ata_eh_speed_down(struct ata_device *dev, unsigned int eflags, unsigned int err_mask) { - struct ata_link *link = dev->link; + struct ata_link *link = ata_dev_phys_link(dev); int xfer_ok = 0; unsigned int verdict; unsigned int action = 0; @@ -1880,7 +1914,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); - if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link) + if (!(qc->flags & ATA_QCFLAG_FAILED) || + ata_dev_phys_link(qc->dev) != link) continue; /* inherit upper level err_mask */ @@ -1967,6 +2002,23 @@ void ata_eh_autopsy(struct ata_port *ap) ata_port_for_each_link(link, ap) ata_eh_link_autopsy(link); + /* Handle the frigging slave link. Autopsy is done similarly + * but actions and flags are transferred over to the master + * link and handled from there. + */ + if (ap->slave_link) { + struct ata_eh_context *mehc = &ap->link.eh_context; + struct ata_eh_context *sehc = &ap->slave_link->eh_context; + + ata_eh_link_autopsy(ap->slave_link); + + ata_eh_about_to_do(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS); + mehc->i.action |= sehc->i.action; + mehc->i.dev_action[1] |= sehc->i.dev_action[1]; + mehc->i.flags |= sehc->i.flags; + ata_eh_done(ap->slave_link, NULL, ATA_EH_ALL_ACTIONS); + } + /* Autopsy of fanout ports can affect host link autopsy. * Perform host link autopsy last. */ @@ -2001,7 +2053,8 @@ static void ata_eh_link_report(struct ata_link *link) for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); - if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link || + if (!(qc->flags & ATA_QCFLAG_FAILED) || + ata_dev_phys_link(qc->dev) != link || ((qc->flags & ATA_QCFLAG_QUIET) && qc->err_mask == AC_ERR_DEV)) continue; @@ -2068,7 +2121,7 @@ static void ata_eh_link_report(struct ata_link *link) char cdb_buf[70] = ""; if (!(qc->flags & ATA_QCFLAG_FAILED) || - qc->dev->link != link || !qc->err_mask) + ata_dev_phys_link(qc->dev) != link || !qc->err_mask) continue; if (qc->dma_dir != DMA_NONE) { @@ -2160,12 +2213,14 @@ void ata_eh_report(struct ata_port *ap) } static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, - unsigned int *classes, unsigned long deadline) + unsigned int *classes, unsigned long deadline, + bool clear_classes) { struct ata_device *dev; - ata_link_for_each_dev(dev, link) - classes[dev->devno] = ATA_DEV_UNKNOWN; + if (clear_classes) + ata_link_for_each_dev(dev, link) + classes[dev->devno] = ATA_DEV_UNKNOWN; return reset(link, classes, deadline); } @@ -2187,17 +2242,20 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { struct ata_port *ap = link->ap; + struct ata_link *slave = ap->slave_link; struct ata_eh_context *ehc = &link->eh_context; + struct ata_eh_context *sehc = &slave->eh_context; unsigned int *classes = ehc->classes; unsigned int lflags = link->flags; int verbose = !(ehc->i.flags & ATA_EHI_QUIET); int max_tries = 0, try = 0; + struct ata_link *failed_link; struct ata_device *dev; unsigned long deadline, now; ata_reset_fn_t reset; unsigned long flags; u32 sstatus; - int nr_known, rc; + int nr_unknown, rc; /* * Prepare to reset @@ -2252,8 +2310,30 @@ int ata_eh_reset(struct ata_link *link, int classify, } if (prereset) { - rc = prereset(link, - ata_deadline(jiffies, ATA_EH_PRERESET_TIMEOUT)); + unsigned long deadline = ata_deadline(jiffies, + ATA_EH_PRERESET_TIMEOUT); + + if (slave) { + sehc->i.action &= ~ATA_EH_RESET; + sehc->i.action |= ehc->i.action; + } + + rc = prereset(link, deadline); + + /* If present, do prereset on slave link too. Reset + * is skipped iff both master and slave links report + * -ENOENT or clear ATA_EH_RESET. + */ + if (slave && (rc == 0 || rc == -ENOENT)) { + int tmp; + + tmp = prereset(slave, deadline); + if (tmp != -ENOENT) + rc = tmp; + + ehc->i.action |= sehc->i.action; + } + if (rc) { if (rc == -ENOENT) { ata_link_printk(link, KERN_DEBUG, @@ -2302,25 +2382,51 @@ int ata_eh_reset(struct ata_link *link, int classify, else ehc->i.flags |= ATA_EHI_DID_SOFTRESET; - rc = ata_do_reset(link, reset, classes, deadline); - if (rc && rc != -EAGAIN) + rc = ata_do_reset(link, reset, classes, deadline, true); + if (rc && rc != -EAGAIN) { + failed_link = link; goto fail; + } + + /* hardreset slave link if existent */ + if (slave && reset == hardreset) { + int tmp; + + if (verbose) + ata_link_printk(slave, KERN_INFO, + "hard resetting link\n"); + ata_eh_about_to_do(slave, NULL, ATA_EH_RESET); + tmp = ata_do_reset(slave, reset, classes, deadline, + false); + switch (tmp) { + case -EAGAIN: + rc = -EAGAIN; + case 0: + break; + default: + failed_link = slave; + rc = tmp; + goto fail; + } + } + + /* perform follow-up SRST if necessary */ if (reset == hardreset && ata_eh_followup_srst_needed(link, rc, classes)) { - /* okay, let's do follow-up softreset */ reset = softreset; if (!reset) { ata_link_printk(link, KERN_ERR, "follow-up softreset required " "but no softreset avaliable\n"); + failed_link = link; rc = -EINVAL; goto fail; } ata_eh_about_to_do(link, NULL, ATA_EH_RESET); - rc = ata_do_reset(link, reset, classes, deadline); + rc = ata_do_reset(link, reset, classes, deadline, true); } } else { if (verbose) @@ -2341,7 +2447,7 @@ int ata_eh_reset(struct ata_link *link, int classify, dev->pio_mode = XFER_PIO_0; dev->flags &= ~ATA_DFLAG_SLEEPING; - if (ata_link_offline(link)) + if (ata_phys_link_offline(ata_dev_phys_link(dev))) continue; /* apply class override */ @@ -2354,6 +2460,8 @@ int ata_eh_reset(struct ata_link *link, int classify, /* record current link speed */ if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) link->sata_spd = (sstatus >> 4) & 0xf; + if (slave && sata_scr_read(slave, SCR_STATUS, &sstatus) == 0) + slave->sata_spd = (sstatus >> 4) & 0xf; /* thaw the port */ if (ata_is_host_link(link)) @@ -2366,12 +2474,17 @@ int ata_eh_reset(struct ata_link *link, int classify, * reset and here. This race is mediated by cross checking * link onlineness and classification result later. */ - if (postreset) + if (postreset) { postreset(link, classes); + if (slave) + postreset(slave, classes); + } /* clear cached SError */ spin_lock_irqsave(link->ap->lock, flags); link->eh_info.serror = 0; + if (slave) + slave->eh_info.serror = 0; spin_unlock_irqrestore(link->ap->lock, flags); /* Make sure onlineness and classification result correspond. @@ -2381,19 +2494,21 @@ int ata_eh_reset(struct ata_link *link, int classify, * link onlineness and classification result, those conditions * can be reliably detected and retried. */ - nr_known = 0; + nr_unknown = 0; ata_link_for_each_dev(dev, link) { /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ - if (classes[dev->devno] == ATA_DEV_UNKNOWN) + if (classes[dev->devno] == ATA_DEV_UNKNOWN) { classes[dev->devno] = ATA_DEV_NONE; - else - nr_known++; + if (ata_phys_link_online(ata_dev_phys_link(dev))) + nr_unknown++; + } } - if (classify && !nr_known && ata_link_online(link)) { + if (classify && nr_unknown) { if (try < max_tries) { ata_link_printk(link, KERN_WARNING, "link online but " "device misclassified, retrying\n"); + failed_link = link; rc = -EAGAIN; goto fail; } @@ -2404,6 +2519,8 @@ int ata_eh_reset(struct ata_link *link, int classify, /* reset successful, schedule revalidation */ ata_eh_done(link, NULL, ATA_EH_RESET); + if (slave) + ata_eh_done(slave, NULL, ATA_EH_RESET); ehc->last_reset = jiffies; ehc->i.action |= ATA_EH_REVALIDATE; @@ -2411,6 +2528,8 @@ int ata_eh_reset(struct ata_link *link, int classify, out: /* clear hotplug flag */ ehc->i.flags &= ~ATA_EHI_HOTPLUGGED; + if (slave) + sehc->i.flags &= ~ATA_EHI_HOTPLUGGED; spin_lock_irqsave(ap->lock, flags); ap->pflags &= ~ATA_PFLAG_RESETTING; @@ -2431,7 +2550,7 @@ int ata_eh_reset(struct ata_link *link, int classify, if (time_before(now, deadline)) { unsigned long delta = deadline - now; - ata_link_printk(link, KERN_WARNING, + ata_link_printk(failed_link, KERN_WARNING, "reset failed (errno=%d), retrying in %u secs\n", rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000)); @@ -2439,13 +2558,92 @@ int ata_eh_reset(struct ata_link *link, int classify, delta = schedule_timeout_uninterruptible(delta); } - if (rc == -EPIPE || try == max_tries - 1) + if (try == max_tries - 1) { sata_down_spd_limit(link); + if (slave) + sata_down_spd_limit(slave); + } else if (rc == -EPIPE) + sata_down_spd_limit(failed_link); + if (hardreset) reset = hardreset; goto retry; } +static inline void ata_eh_pull_park_action(struct ata_port *ap) +{ + struct ata_link *link; + struct ata_device *dev; + unsigned long flags; + + /* + * This function can be thought of as an extended version of + * ata_eh_about_to_do() specially crafted to accommodate the + * requirements of ATA_EH_PARK handling. Since the EH thread + * does not leave the do {} while () loop in ata_eh_recover as + * long as the timeout for a park request to *one* device on + * the port has not expired, and since we still want to pick + * up park requests to other devices on the same port or + * timeout updates for the same device, we have to pull + * ATA_EH_PARK actions from eh_info into eh_context.i + * ourselves at the beginning of each pass over the loop. + * + * Additionally, all write accesses to &ap->park_req_pending + * through INIT_COMPLETION() (see below) or complete_all() + * (see ata_scsi_park_store()) are protected by the host lock. + * As a result we have that park_req_pending.done is zero on + * exit from this function, i.e. when ATA_EH_PARK actions for + * *all* devices on port ap have been pulled into the + * respective eh_context structs. If, and only if, + * park_req_pending.done is non-zero by the time we reach + * wait_for_completion_timeout(), another ATA_EH_PARK action + * has been scheduled for at least one of the devices on port + * ap and we have to cycle over the do {} while () loop in + * ata_eh_recover() again. + */ + + spin_lock_irqsave(ap->lock, flags); + INIT_COMPLETION(ap->park_req_pending); + ata_port_for_each_link(link, ap) { + ata_link_for_each_dev(dev, link) { + struct ata_eh_info *ehi = &link->eh_info; + + link->eh_context.i.dev_action[dev->devno] |= + ehi->dev_action[dev->devno] & ATA_EH_PARK; + ata_eh_clear_action(link, dev, ehi, ATA_EH_PARK); + } + } + spin_unlock_irqrestore(ap->lock, flags); +} + +static void ata_eh_park_issue_cmd(struct ata_device *dev, int park) +{ + struct ata_eh_context *ehc = &dev->link->eh_context; + struct ata_taskfile tf; + unsigned int err_mask; + + ata_tf_init(dev, &tf); + if (park) { + ehc->unloaded_mask |= 1 << dev->devno; + tf.command = ATA_CMD_IDLEIMMEDIATE; + tf.feature = 0x44; + tf.lbal = 0x4c; + tf.lbam = 0x4e; + tf.lbah = 0x55; + } else { + ehc->unloaded_mask &= ~(1 << dev->devno); + tf.command = ATA_CMD_CHK_POWER; + } + + tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; + tf.protocol |= ATA_PROT_NODATA; + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + if (park && (err_mask || tf.lbal != 0xc4)) { + ata_dev_printk(dev, KERN_ERR, "head unload failed!\n"); + ehc->unloaded_mask &= ~(1 << dev->devno); + } +} + static int ata_eh_revalidate_and_attach(struct ata_link *link, struct ata_device **r_failed_dev) { @@ -2472,7 +2670,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) { WARN_ON(dev->class == ATA_DEV_PMP); - if (ata_link_offline(link)) { + if (ata_phys_link_offline(ata_dev_phys_link(dev))) { rc = -EIO; goto err; } @@ -2610,6 +2808,53 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) return rc; } +/** + * atapi_eh_clear_ua - Clear ATAPI UNIT ATTENTION after reset + * @dev: ATAPI device to clear UA for + * + * Resets and other operations can make an ATAPI device raise + * UNIT ATTENTION which causes the next operation to fail. This + * function clears UA. + * + * LOCKING: + * EH context (may sleep). + * + * RETURNS: + * 0 on success, -errno on failure. + */ +static int atapi_eh_clear_ua(struct ata_device *dev) +{ + int i; + + for (i = 0; i < ATA_EH_UA_TRIES; i++) { + u8 sense_buffer[SCSI_SENSE_BUFFERSIZE]; + u8 sense_key = 0; + unsigned int err_mask; + + err_mask = atapi_eh_tur(dev, &sense_key); + if (err_mask != 0 && err_mask != AC_ERR_DEV) { + ata_dev_printk(dev, KERN_WARNING, "TEST_UNIT_READY " + "failed (err_mask=0x%x)\n", err_mask); + return -EIO; + } + + if (!err_mask || sense_key != UNIT_ATTENTION) + return 0; + + err_mask = atapi_eh_request_sense(dev, sense_buffer, sense_key); + if (err_mask) { + ata_dev_printk(dev, KERN_WARNING, "failed to clear " + "UNIT ATTENTION (err_mask=0x%x)\n", err_mask); + return -EIO; + } + } + + ata_dev_printk(dev, KERN_WARNING, + "UNIT ATTENTION persists after %d tries\n", ATA_EH_UA_TRIES); + + return 0; +} + static int ata_link_nr_enabled(struct ata_link *link) { struct ata_device *dev; @@ -2697,7 +2942,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) /* This is the last chance, better to slow * down than lose it. */ - sata_down_spd_limit(dev->link); + sata_down_spd_limit(ata_dev_phys_link(dev)); ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); } } @@ -2707,7 +2952,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) ata_dev_disable(dev); /* detach if offline */ - if (ata_link_offline(dev->link)) + if (ata_phys_link_offline(ata_dev_phys_link(dev))) ata_eh_detach_dev(dev); /* schedule probe if necessary */ @@ -2755,7 +3000,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, struct ata_device *dev; int nr_failed_devs; int rc; - unsigned long flags; + unsigned long flags, deadline; DPRINTK("ENTER\n"); @@ -2829,6 +3074,56 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, } } + do { + unsigned long now; + + /* + * clears ATA_EH_PARK in eh_info and resets + * ap->park_req_pending + */ + ata_eh_pull_park_action(ap); + + deadline = jiffies; + ata_port_for_each_link(link, ap) { + ata_link_for_each_dev(dev, link) { + struct ata_eh_context *ehc = &link->eh_context; + unsigned long tmp; + + if (dev->class != ATA_DEV_ATA) + continue; + if (!(ehc->i.dev_action[dev->devno] & + ATA_EH_PARK)) + continue; + tmp = dev->unpark_deadline; + if (time_before(deadline, tmp)) + deadline = tmp; + else if (time_before_eq(tmp, jiffies)) + continue; + if (ehc->unloaded_mask & (1 << dev->devno)) + continue; + + ata_eh_park_issue_cmd(dev, 1); + } + } + + now = jiffies; + if (time_before_eq(deadline, now)) + break; + + deadline = wait_for_completion_timeout(&ap->park_req_pending, + deadline - now); + } while (deadline); + ata_port_for_each_link(link, ap) { + ata_link_for_each_dev(dev, link) { + if (!(link->eh_context.unloaded_mask & + (1 << dev->devno))) + continue; + + ata_eh_park_issue_cmd(dev, 0); + ata_eh_done(link, dev, ATA_EH_PARK); + } + } + /* the rest */ ata_port_for_each_link(link, ap) { struct ata_eh_context *ehc = &link->eh_context; @@ -2852,6 +3147,20 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ehc->i.flags &= ~ATA_EHI_SETMODE; } + /* If reset has been issued, clear UA to avoid + * disrupting the current users of the device. + */ + if (ehc->i.flags & ATA_EHI_DID_RESET) { + ata_link_for_each_dev(dev, link) { + if (dev->class != ATA_DEV_ATAPI) + continue; + rc = atapi_eh_clear_ua(dev); + if (rc) + goto dev_fail; + } + } + + /* configure link power saving */ if (ehc->i.action & ATA_EH_LPM) ata_link_for_each_dev(dev, link) ata_dev_enable_pm(dev, ap->pm_policy); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b9d3ba423cb2..59fe051957ef 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -183,6 +183,105 @@ DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, ata_scsi_lpm_show, ata_scsi_lpm_put); EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); +static ssize_t ata_scsi_park_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(device); + struct ata_port *ap; + struct ata_link *link; + struct ata_device *dev; + unsigned long flags; + unsigned int uninitialized_var(msecs); + int rc = 0; + + ap = ata_shost_to_port(sdev->host); + + spin_lock_irqsave(ap->lock, flags); + dev = ata_scsi_find_dev(ap, sdev); + if (!dev) { + rc = -ENODEV; + goto unlock; + } + if (dev->flags & ATA_DFLAG_NO_UNLOAD) { + rc = -EOPNOTSUPP; + goto unlock; + } + + link = dev->link; + if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS && + link->eh_context.unloaded_mask & (1 << dev->devno) && + time_after(dev->unpark_deadline, jiffies)) + msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies); + else + msecs = 0; + +unlock: + spin_unlock_irq(ap->lock); + + return rc ? rc : snprintf(buf, 20, "%u\n", msecs); +} + +static ssize_t ata_scsi_park_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct scsi_device *sdev = to_scsi_device(device); + struct ata_port *ap; + struct ata_device *dev; + long int input; + unsigned long flags; + int rc; + + rc = strict_strtol(buf, 10, &input); + if (rc || input < -2) + return -EINVAL; + if (input > ATA_TMOUT_MAX_PARK) { + rc = -EOVERFLOW; + input = ATA_TMOUT_MAX_PARK; + } + + ap = ata_shost_to_port(sdev->host); + + spin_lock_irqsave(ap->lock, flags); + dev = ata_scsi_find_dev(ap, sdev); + if (unlikely(!dev)) { + rc = -ENODEV; + goto unlock; + } + if (dev->class != ATA_DEV_ATA) { + rc = -EOPNOTSUPP; + goto unlock; + } + + if (input >= 0) { + if (dev->flags & ATA_DFLAG_NO_UNLOAD) { + rc = -EOPNOTSUPP; + goto unlock; + } + + dev->unpark_deadline = ata_deadline(jiffies, input); + dev->link->eh_info.dev_action[dev->devno] |= ATA_EH_PARK; + ata_port_schedule_eh(ap); + complete(&ap->park_req_pending); + } else { + switch (input) { + case -1: + dev->flags &= ~ATA_DFLAG_NO_UNLOAD; + break; + case -2: + dev->flags |= ATA_DFLAG_NO_UNLOAD; + break; + } + } +unlock: + spin_unlock_irqrestore(ap->lock, flags); + + return rc ? rc : len; +} +DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, + ata_scsi_park_show, ata_scsi_park_store); +EXPORT_SYMBOL_GPL(dev_attr_unload_heads); + static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) { cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; @@ -269,6 +368,12 @@ DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show, ata_scsi_activity_store); EXPORT_SYMBOL_GPL(dev_attr_sw_activity); +struct device_attribute *ata_common_sdev_attrs[] = { + &dev_attr_unload_heads, + NULL +}; +EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { @@ -954,6 +1059,9 @@ static int atapi_drain_needed(struct request *rq) static int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) { + if (!ata_id_has_unload(dev->id)) + dev->flags |= ATA_DFLAG_NO_UNLOAD; + /* configure max sectors */ blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); @@ -977,6 +1085,10 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); } else { + if (ata_id_is_ssd(dev->id)) + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, + sdev->request_queue); + /* ATA devices must be sector aligned */ blk_queue_update_dma_alignment(sdev->request_queue, ATA_SECT_SIZE - 1); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index ade5c75b6144..fe2839e58774 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -70,6 +70,7 @@ extern int atapi_passthru16; extern int libata_fua; extern int libata_noacpi; extern int libata_allow_tpm; +extern struct ata_link *ata_dev_phys_link(struct ata_device *dev); extern void ata_force_cbl(struct ata_port *ap); extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); @@ -107,6 +108,8 @@ extern void ata_qc_issue(struct ata_queued_cmd *qc); extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern int atapi_check_dma(struct ata_queued_cmd *qc); extern void swap_buf_le16(u16 *buf, unsigned int buf_words); +extern bool ata_phys_link_online(struct ata_link *link); +extern bool ata_phys_link_offline(struct ata_link *link); extern void ata_dev_init(struct ata_device *dev); extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp); extern int sata_link_init_spd(struct ata_link *link); @@ -152,7 +155,7 @@ extern int ata_bus_probe(struct ata_port *ap); /* libata-eh.c */ extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd); extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd); -extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); +extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); extern void ata_scsi_error(struct Scsi_Host *host); extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_eh_fastdrain_timerfn(unsigned long arg); diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index d3932901a3b3..1266924c11f9 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1632,6 +1632,8 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev) return -ENODEV; } + dev_set_drvdata(&pdev->dev, host); + return 0; } @@ -1648,6 +1650,7 @@ static int __devexit bfin_atapi_remove(struct platform_device *pdev) struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); + dev_set_drvdata(&pdev->dev, NULL); peripheral_free_list(atapi_io_port); @@ -1655,27 +1658,44 @@ static int __devexit bfin_atapi_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state) +static int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state) { - return 0; + struct ata_host *host = dev_get_drvdata(&pdev->dev); + if (host) + return ata_host_suspend(host, state); + else + return 0; } -int bfin_atapi_resume(struct platform_device *pdev) +static int bfin_atapi_resume(struct platform_device *pdev) { + struct ata_host *host = dev_get_drvdata(&pdev->dev); + int ret; + + if (host) { + ret = bfin_reset_controller(host); + if (ret) { + printk(KERN_ERR DRV_NAME ": Error during HW init\n"); + return ret; + } + ata_host_resume(host); + } + return 0; } +#else +#define bfin_atapi_suspend NULL +#define bfin_atapi_resume NULL #endif static struct platform_driver bfin_atapi_driver = { .probe = bfin_atapi_probe, .remove = __devexit_p(bfin_atapi_remove), + .suspend = bfin_atapi_suspend, + .resume = bfin_atapi_resume, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, -#ifdef CONFIG_PM - .suspend = bfin_atapi_suspend, - .resume = bfin_atapi_resume, -#endif }, }; diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index e970b227fbce..a598bb36aafc 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -230,7 +230,7 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) tmpbyte & 1, tmpbyte & 0x30); *try_mmio = 0; -#ifdef CONFIG_PPC_MERGE +#ifdef CONFIG_PPC if (machine_is(cell)) *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); #endif diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 3924e7209a44..1a56db92ff7a 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -469,10 +469,10 @@ static bool sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc) return true; } -static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in, - u32 val) +static int sata_fsl_scr_write(struct ata_link *link, + unsigned int sc_reg_in, u32 val) { - struct sata_fsl_host_priv *host_priv = ap->host->private_data; + struct sata_fsl_host_priv *host_priv = link->ap->host->private_data; void __iomem *ssr_base = host_priv->ssr_base; unsigned int sc_reg; @@ -493,10 +493,10 @@ static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in, return 0; } -static int sata_fsl_scr_read(struct ata_port *ap, unsigned int sc_reg_in, - u32 *val) +static int sata_fsl_scr_read(struct ata_link *link, + unsigned int sc_reg_in, u32 *val) { - struct sata_fsl_host_priv *host_priv = ap->host->private_data; + struct sata_fsl_host_priv *host_priv = link->ap->host->private_data; void __iomem *ssr_base = host_priv->ssr_base; unsigned int sc_reg; @@ -645,12 +645,12 @@ static int sata_fsl_port_start(struct ata_port *ap) * Workaround for 8315DS board 3gbps link-up issue, * currently limit SATA port to GEN1 speed */ - sata_fsl_scr_read(ap, SCR_CONTROL, &temp); + sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp); temp &= ~(0xF << 4); temp |= (0x1 << 4); - sata_fsl_scr_write(ap, SCR_CONTROL, temp); + sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp); - sata_fsl_scr_read(ap, SCR_CONTROL, &temp); + sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp); dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n", temp); #endif @@ -868,7 +868,7 @@ issue_srst: ioread32(CQ + hcr_base), ioread32(CA + hcr_base), ioread32(CC + hcr_base)); - sata_fsl_scr_read(ap, SCR_ERROR, &Serror); + sata_fsl_scr_read(&ap->link, SCR_ERROR, &Serror); DPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS)); DPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL)); @@ -972,9 +972,9 @@ static void sata_fsl_error_intr(struct ata_port *ap) * Handle & Clear SError */ - sata_fsl_scr_read(ap, SCR_ERROR, &SError); + sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError); if (unlikely(SError & 0xFFFF0000)) { - sata_fsl_scr_write(ap, SCR_ERROR, SError); + sata_fsl_scr_write(&ap->link, SCR_ERROR, SError); } DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n", @@ -1091,7 +1091,7 @@ static void sata_fsl_host_intr(struct ata_port *ap) hstatus = ioread32(hcr_base + HSTATUS); - sata_fsl_scr_read(ap, SCR_ERROR, &SError); + sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError); if (unlikely(SError & 0xFFFF0000)) { DPRINTK("serror @host_intr : 0x%x\n", SError); diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 5032c32fa505..fbbd87c96f10 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -269,9 +269,9 @@ static void inic_reset_port(void __iomem *port_base) writeb(0xff, port_base + PORT_IRQ_STAT); } -static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val) +static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val) { - void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR; + void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR; void __iomem *addr; if (unlikely(sc_reg >= ARRAY_SIZE(scr_map))) @@ -286,9 +286,9 @@ static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val) return 0; } -static int inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) +static int inic_scr_write(struct ata_link *link, unsigned sc_reg, u32 val) { - void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR; + void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR; if (unlikely(sc_reg >= ARRAY_SIZE(scr_map))) return -EINVAL; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index c815f8ecf6e6..2b24ae58b52e 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -493,10 +493,10 @@ struct mv_hw_ops { void (*reset_bus)(struct ata_host *host, void __iomem *mmio); }; -static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val); -static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); -static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val); -static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); +static int mv_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val); +static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val); +static int mv5_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val); +static int mv5_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val); static int mv_port_start(struct ata_port *ap); static void mv_port_stop(struct ata_port *ap); static int mv_qc_defer(struct ata_queued_cmd *qc); @@ -1070,23 +1070,23 @@ static unsigned int mv_scr_offset(unsigned int sc_reg_in) return ofs; } -static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) +static int mv_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val) { unsigned int ofs = mv_scr_offset(sc_reg_in); if (ofs != 0xffffffffU) { - *val = readl(mv_ap_base(ap) + ofs); + *val = readl(mv_ap_base(link->ap) + ofs); return 0; } else return -EINVAL; } -static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) +static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val) { unsigned int ofs = mv_scr_offset(sc_reg_in); if (ofs != 0xffffffffU) { - writelfl(val, mv_ap_base(ap) + ofs); + writelfl(val, mv_ap_base(link->ap) + ofs); return 0; } else return -EINVAL; @@ -2251,11 +2251,11 @@ static unsigned int mv5_scr_offset(unsigned int sc_reg_in) return ofs; } -static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) +static int mv5_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val) { - struct mv_host_priv *hpriv = ap->host->private_data; + struct mv_host_priv *hpriv = link->ap->host->private_data; void __iomem *mmio = hpriv->base; - void __iomem *addr = mv5_phy_base(mmio, ap->port_no); + void __iomem *addr = mv5_phy_base(mmio, link->ap->port_no); unsigned int ofs = mv5_scr_offset(sc_reg_in); if (ofs != 0xffffffffU) { @@ -2265,11 +2265,11 @@ static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) return -EINVAL; } -static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) +static int mv5_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val) { - struct mv_host_priv *hpriv = ap->host->private_data; + struct mv_host_priv *hpriv = link->ap->host->private_data; void __iomem *mmio = hpriv->base; - void __iomem *addr = mv5_phy_base(mmio, ap->port_no); + void __iomem *addr = mv5_phy_base(mmio, link->ap->port_no); unsigned int ofs = mv5_scr_offset(sc_reg_in); if (ofs != 0xffffffffU) { diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 14601dc05e41..fae3841de0d8 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -302,8 +302,8 @@ static void nv_ck804_host_stop(struct ata_host *host); static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance); static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance); -static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static void nv_nf2_freeze(struct ata_port *ap); static void nv_nf2_thaw(struct ata_port *ap); @@ -1511,21 +1511,21 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance) return ret; } -static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4)); + *val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } -static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } @@ -2218,9 +2218,9 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis) if (!pp->qc_active) return; - if (ap->ops->scr_read(ap, SCR_ERROR, &serror)) + if (ap->ops->scr_read(&ap->link, SCR_ERROR, &serror)) return; - ap->ops->scr_write(ap, SCR_ERROR, serror); + ap->ops->scr_write(&ap->link, SCR_ERROR, serror); if (ata_stat & ATA_ERR) { ata_ehi_clear_desc(ehi); diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 030665ba76b7..750d8cdc00cd 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -137,8 +137,8 @@ struct pdc_port_priv { dma_addr_t pkt_dma; }; -static int pdc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int pdc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int pdc_common_port_start(struct ata_port *ap); static int pdc_sata_port_start(struct ata_port *ap); @@ -386,19 +386,21 @@ static int pdc_sata_cable_detect(struct ata_port *ap) return ATA_CBL_SATA; } -static int pdc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int pdc_sata_scr_read(struct ata_link *link, + unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = readl(ap->ioaddr.scr_addr + (sc_reg * 4)); + *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } -static int pdc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int pdc_sata_scr_write(struct ata_link *link, + unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } @@ -731,7 +733,7 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, if (sata_scr_valid(&ap->link)) { u32 serror; - pdc_sata_scr_read(ap, SCR_ERROR, &serror); + pdc_sata_scr_read(&ap->link, SCR_ERROR, &serror); ehi->serror |= serror; } diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 1600107047cf..a000c86ac859 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -111,8 +111,8 @@ struct qs_port_priv { qs_state_t state; }; -static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int qs_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int qs_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int qs_port_start(struct ata_port *ap); static void qs_host_stop(struct ata_host *host); @@ -242,11 +242,11 @@ static int qs_prereset(struct ata_link *link, unsigned long deadline) return ata_sff_prereset(link, deadline); } -static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int qs_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = readl(ap->ioaddr.scr_addr + (sc_reg * 8)); + *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 8)); return 0; } @@ -256,11 +256,11 @@ static void qs_error_handler(struct ata_port *ap) ata_std_error_handler(ap); } -static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int qs_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - writel(val, ap->ioaddr.scr_addr + (sc_reg * 8)); + writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 8)); return 0; } diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 88bf4212590f..031d7b7dee34 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -115,8 +115,8 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int sil_pci_device_resume(struct pci_dev *pdev); #endif static void sil_dev_config(struct ata_device *dev); -static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int sil_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed); static void sil_freeze(struct ata_port *ap); static void sil_thaw(struct ata_port *ap); @@ -317,9 +317,9 @@ static inline void __iomem *sil_scr_addr(struct ata_port *ap, return NULL; } -static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { - void __iomem *mmio = sil_scr_addr(ap, sc_reg); + void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); if (mmio) { *val = readl(mmio); @@ -328,9 +328,9 @@ static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return -EINVAL; } -static int sil_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { - void __iomem *mmio = sil_scr_addr(ap, sc_reg); + void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); if (mmio) { writel(val, mmio); @@ -352,8 +352,8 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) * controllers continue to assert IRQ as long as * SError bits are pending. Clear SError immediately. */ - sil_scr_read(ap, SCR_ERROR, &serror); - sil_scr_write(ap, SCR_ERROR, serror); + sil_scr_read(&ap->link, SCR_ERROR, &serror); + sil_scr_write(&ap->link, SCR_ERROR, serror); /* Sometimes spurious interrupts occur, double check * it's PHYRDY CHG. diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 84ffcc26a74b..4621807a1a6a 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -340,8 +340,8 @@ struct sil24_port_priv { }; static void sil24_dev_config(struct ata_device *dev); -static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); -static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); +static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val); +static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val); static int sil24_qc_defer(struct ata_queued_cmd *qc); static void sil24_qc_prep(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); @@ -504,9 +504,9 @@ static int sil24_scr_map[] = { [SCR_ACTIVE] = 3, }; -static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val) +static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val) { - void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL; + void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL; if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { void __iomem *addr; @@ -517,9 +517,9 @@ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val) return -EINVAL; } -static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) +static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val) { - void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL; + void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL; if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { void __iomem *addr; diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 1010b3069bd5..9c43b4e7c4a6 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -64,8 +64,8 @@ enum { }; static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static const struct pci_device_id sis_pci_tbl[] = { { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */ @@ -134,10 +134,11 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) return addr; } -static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static u32 sis_scr_cfg_read(struct ata_link *link, + unsigned int sc_reg, u32 *val) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg); u32 val2 = 0; u8 pmr; @@ -158,10 +159,11 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } -static int sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int sis_scr_cfg_write(struct ata_link *link, + unsigned int sc_reg, u32 val) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg); u8 pmr; if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ @@ -178,8 +180,9 @@ static int sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val) return 0; } -static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { + struct ata_port *ap = link->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 pmr; @@ -187,7 +190,7 @@ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return -EINVAL; if (ap->flags & SIS_FLAG_CFGSCR) - return sis_scr_cfg_read(ap, sc_reg, val); + return sis_scr_cfg_read(link, sc_reg, val); pci_read_config_byte(pdev, SIS_PMR, &pmr); @@ -202,8 +205,9 @@ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } -static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { + struct ata_port *ap = link->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 pmr; @@ -213,7 +217,7 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) pci_read_config_byte(pdev, SIS_PMR, &pmr); if (ap->flags & SIS_FLAG_CFGSCR) - return sis_scr_cfg_write(ap, sc_reg, val); + return sis_scr_cfg_write(link, sc_reg, val); else { iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)); if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index fb13b82aacba..609d147813ae 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -123,20 +123,22 @@ static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc) } } -static int k2_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int k2_sata_scr_read(struct ata_link *link, + unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = readl(ap->ioaddr.scr_addr + (sc_reg * 4)); + *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } -static int k2_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int k2_sata_scr_write(struct ata_link *link, + unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index db529b849948..019575bb3e08 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -57,8 +57,8 @@ struct uli_priv { }; static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int uli_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static const struct pci_device_id uli_pci_tbl[] = { { PCI_VDEVICE(AL, 0x5289), uli_5289 }, @@ -107,39 +107,39 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg); } -static u32 uli_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg) +static u32 uli_scr_cfg_read(struct ata_link *link, unsigned int sc_reg) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg); u32 val; pci_read_config_dword(pdev, cfg_addr, &val); return val; } -static void uli_scr_cfg_write(struct ata_port *ap, unsigned int scr, u32 val) +static void uli_scr_cfg_write(struct ata_link *link, unsigned int scr, u32 val) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap, scr); + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + unsigned int cfg_addr = get_scr_cfg_addr(link->ap, scr); pci_write_config_dword(pdev, cfg_addr, val); } -static int uli_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int uli_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = uli_scr_cfg_read(ap, sc_reg); + *val = uli_scr_cfg_read(link, sc_reg); return 0; } -static int uli_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0 return -EINVAL; - uli_scr_cfg_write(ap, sc_reg, val); + uli_scr_cfg_write(link, sc_reg, val); return 0; } diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 96deeb354e16..1cfa74535d91 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -68,8 +68,8 @@ enum { }; static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); -static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); +static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); +static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static void svia_noop_freeze(struct ata_port *ap); static int vt6420_prereset(struct ata_link *link, unsigned long deadline); static int vt6421_pata_cable_detect(struct ata_port *ap); @@ -152,19 +152,19 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, svia_pci_tbl); MODULE_VERSION(DRV_VERSION); -static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = ioread32(ap->ioaddr.scr_addr + (4 * sc_reg)); + *val = ioread32(link->ap->ioaddr.scr_addr + (4 * sc_reg)); return 0; } -static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - iowrite32(val, ap->ioaddr.scr_addr + (4 * sc_reg)); + iowrite32(val, link->ap->ioaddr.scr_addr + (4 * sc_reg)); return 0; } @@ -210,20 +210,20 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline) goto skip_scr; /* Resume phy. This is the old SATA resume sequence */ - svia_scr_write(ap, SCR_CONTROL, 0x300); - svia_scr_read(ap, SCR_CONTROL, &scontrol); /* flush */ + svia_scr_write(link, SCR_CONTROL, 0x300); + svia_scr_read(link, SCR_CONTROL, &scontrol); /* flush */ /* wait for phy to become ready, if necessary */ do { msleep(200); - svia_scr_read(ap, SCR_STATUS, &sstatus); + svia_scr_read(link, SCR_STATUS, &sstatus); if ((sstatus & 0xf) != 1) break; } while (time_before(jiffies, timeout)); /* open code sata_print_link_status() */ - svia_scr_read(ap, SCR_STATUS, &sstatus); - svia_scr_read(ap, SCR_CONTROL, &scontrol); + svia_scr_read(link, SCR_STATUS, &sstatus); + svia_scr_read(link, SCR_CONTROL, &scontrol); online = (sstatus & 0xf) == 0x3; @@ -232,7 +232,7 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline) online ? "up" : "down", sstatus, scontrol); /* SStatus is read one more time */ - svia_scr_read(ap, SCR_STATUS, &sstatus); + svia_scr_read(link, SCR_STATUS, &sstatus); if (!online) { /* tell EH to bail */ diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index f3d635c0a2e9..c57cdff9e6bd 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -98,20 +98,22 @@ enum { VSC_SATA_INT_PHY_CHANGE), }; -static int vsc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) +static int vsc_sata_scr_read(struct ata_link *link, + unsigned int sc_reg, u32 *val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - *val = readl(ap->ioaddr.scr_addr + (sc_reg * 4)); + *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } -static int vsc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) +static int vsc_sata_scr_write(struct ata_link *link, + unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) return -EINVAL; - writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4)); return 0; } diff --git a/drivers/base/base.h b/drivers/base/base.h index 31dc0cd84afa..0a5f055dffba 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -54,7 +54,7 @@ struct driver_private { */ struct class_private { struct kset class_subsys; - struct list_head class_devices; + struct klist class_devices; struct list_head class_interfaces; struct kset class_dirs; struct mutex class_mutex; diff --git a/drivers/base/class.c b/drivers/base/class.c index cc5e28c8885c..eb85e4312301 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -135,6 +135,20 @@ static void remove_class_attrs(struct class *cls) } } +static void klist_class_dev_get(struct klist_node *n) +{ + struct device *dev = container_of(n, struct device, knode_class); + + get_device(dev); +} + +static void klist_class_dev_put(struct klist_node *n) +{ + struct device *dev = container_of(n, struct device, knode_class); + + put_device(dev); +} + int __class_register(struct class *cls, struct lock_class_key *key) { struct class_private *cp; @@ -145,7 +159,7 @@ int __class_register(struct class *cls, struct lock_class_key *key) cp = kzalloc(sizeof(*cp), GFP_KERNEL); if (!cp) return -ENOMEM; - INIT_LIST_HEAD(&cp->class_devices); + klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put); INIT_LIST_HEAD(&cp->class_interfaces); kset_init(&cp->class_dirs); __mutex_init(&cp->class_mutex, "struct class mutex", key); @@ -269,6 +283,71 @@ char *make_class_name(const char *name, struct kobject *kobj) #endif /** + * class_dev_iter_init - initialize class device iterator + * @iter: class iterator to initialize + * @class: the class we wanna iterate over + * @start: the device to start iterating from, if any + * @type: device_type of the devices to iterate over, NULL for all + * + * Initialize class iterator @iter such that it iterates over devices + * of @class. If @start is set, the list iteration will start there, + * otherwise if it is NULL, the iteration starts at the beginning of + * the list. + */ +void class_dev_iter_init(struct class_dev_iter *iter, struct class *class, + struct device *start, const struct device_type *type) +{ + struct klist_node *start_knode = NULL; + + if (start) + start_knode = &start->knode_class; + klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode); + iter->type = type; +} +EXPORT_SYMBOL_GPL(class_dev_iter_init); + +/** + * class_dev_iter_next - iterate to the next device + * @iter: class iterator to proceed + * + * Proceed @iter to the next device and return it. Returns NULL if + * iteration is complete. + * + * The returned device is referenced and won't be released till + * iterator is proceed to the next device or exited. The caller is + * free to do whatever it wants to do with the device including + * calling back into class code. + */ +struct device *class_dev_iter_next(struct class_dev_iter *iter) +{ + struct klist_node *knode; + struct device *dev; + + while (1) { + knode = klist_next(&iter->ki); + if (!knode) + return NULL; + dev = container_of(knode, struct device, knode_class); + if (!iter->type || iter->type == dev->type) + return dev; + } +} +EXPORT_SYMBOL_GPL(class_dev_iter_next); + +/** + * class_dev_iter_exit - finish iteration + * @iter: class iterator to finish + * + * Finish an iteration. Always call this function after iteration is + * complete whether the iteration ran till the end or not. + */ +void class_dev_iter_exit(struct class_dev_iter *iter) +{ + klist_iter_exit(&iter->ki); +} +EXPORT_SYMBOL_GPL(class_dev_iter_exit); + +/** * class_for_each_device - device iterator * @class: the class we're iterating * @start: the device to start with in the list, if any. @@ -283,13 +362,13 @@ char *make_class_name(const char *name, struct kobject *kobj) * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * - * Note, we hold class->class_mutex in this function, so it can not be - * re-acquired in @fn, otherwise it will self-deadlocking. For - * example, calls to add or remove class members would be verboten. + * @fn is allowed to do anything including calling back into class + * code. There's no locking restriction. */ int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *, void *)) { + struct class_dev_iter iter; struct device *dev; int error = 0; @@ -301,20 +380,13 @@ int class_for_each_device(struct class *class, struct device *start, return -EINVAL; } - mutex_lock(&class->p->class_mutex); - list_for_each_entry(dev, &class->p->class_devices, node) { - if (start) { - if (start == dev) - start = NULL; - continue; - } - dev = get_device(dev); + class_dev_iter_init(&iter, class, start, NULL); + while ((dev = class_dev_iter_next(&iter))) { error = fn(dev, data); - put_device(dev); if (error) break; } - mutex_unlock(&class->p->class_mutex); + class_dev_iter_exit(&iter); return error; } @@ -337,16 +409,15 @@ EXPORT_SYMBOL_GPL(class_for_each_device); * * Note, you will need to drop the reference with put_device() after use. * - * We hold class->class_mutex in this function, so it can not be - * re-acquired in @match, otherwise it will self-deadlocking. For - * example, calls to add or remove class members would be verboten. + * @fn is allowed to do anything including calling back into class + * code. There's no locking restriction. */ struct device *class_find_device(struct class *class, struct device *start, void *data, int (*match)(struct device *, void *)) { + struct class_dev_iter iter; struct device *dev; - int found = 0; if (!class) return NULL; @@ -356,29 +427,23 @@ struct device *class_find_device(struct class *class, struct device *start, return NULL; } - mutex_lock(&class->p->class_mutex); - list_for_each_entry(dev, &class->p->class_devices, node) { - if (start) { - if (start == dev) - start = NULL; - continue; - } - dev = get_device(dev); + class_dev_iter_init(&iter, class, start, NULL); + while ((dev = class_dev_iter_next(&iter))) { if (match(dev, data)) { - found = 1; + get_device(dev); break; - } else - put_device(dev); + } } - mutex_unlock(&class->p->class_mutex); + class_dev_iter_exit(&iter); - return found ? dev : NULL; + return dev; } EXPORT_SYMBOL_GPL(class_find_device); int class_interface_register(struct class_interface *class_intf) { struct class *parent; + struct class_dev_iter iter; struct device *dev; if (!class_intf || !class_intf->class) @@ -391,8 +456,10 @@ int class_interface_register(struct class_interface *class_intf) mutex_lock(&parent->p->class_mutex); list_add_tail(&class_intf->node, &parent->p->class_interfaces); if (class_intf->add_dev) { - list_for_each_entry(dev, &parent->p->class_devices, node) + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) class_intf->add_dev(dev, class_intf); + class_dev_iter_exit(&iter); } mutex_unlock(&parent->p->class_mutex); @@ -402,6 +469,7 @@ int class_interface_register(struct class_interface *class_intf) void class_interface_unregister(struct class_interface *class_intf) { struct class *parent = class_intf->class; + struct class_dev_iter iter; struct device *dev; if (!parent) @@ -410,8 +478,10 @@ void class_interface_unregister(struct class_interface *class_intf) mutex_lock(&parent->p->class_mutex); list_del_init(&class_intf->node); if (class_intf->remove_dev) { - list_for_each_entry(dev, &parent->p->class_devices, node) + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) class_intf->remove_dev(dev, class_intf); + class_dev_iter_exit(&iter); } mutex_unlock(&parent->p->class_mutex); diff --git a/drivers/base/core.c b/drivers/base/core.c index d021c98605b3..b98cb1416a2d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -536,7 +536,6 @@ void device_initialize(struct device *dev) klist_init(&dev->klist_children, klist_children_get, klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); - INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); @@ -916,7 +915,8 @@ int device_add(struct device *dev) if (dev->class) { mutex_lock(&dev->class->p->class_mutex); /* tie the class to the device */ - list_add_tail(&dev->node, &dev->class->p->class_devices); + klist_add_tail(&dev->knode_class, + &dev->class->p->class_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, @@ -1032,7 +1032,7 @@ void device_del(struct device *dev) if (class_intf->remove_dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ - list_del_init(&dev->node); + klist_del(&dev->knode_class); mutex_unlock(&dev->class->p->class_mutex); } device_remove_file(dev, &uevent_attr); diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 0c39782b2660..aa69556c3485 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -109,12 +109,12 @@ static const struct attribute_group attr_group = { static int aoedisk_add_sysfs(struct aoedev *d) { - return sysfs_create_group(&d->gd->dev.kobj, &attr_group); + return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group); } void aoedisk_rm_sysfs(struct aoedev *d) { - sysfs_remove_group(&d->gd->dev.kobj, &attr_group); + sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group); } static int @@ -276,7 +276,7 @@ aoeblk_gdalloc(void *vp) gd->first_minor = d->sysminor * AOE_PARTITIONS; gd->fops = &aoe_bdops; gd->private_data = d; - gd->capacity = d->ssize; + set_capacity(gd, d->ssize); snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", d->aoemajor, d->aoeminor); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 2f1746295d06..961d29a53cab 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -645,7 +645,7 @@ aoecmd_sleepwork(struct work_struct *work) unsigned long flags; u64 ssize; - ssize = d->gd->capacity; + ssize = get_capacity(d->gd); bd = bdget_disk(d->gd, 0); if (bd) { @@ -707,7 +707,7 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) return; if (d->gd != NULL) { - d->gd->capacity = ssize; + set_capacity(d->gd, ssize); d->flags |= DEVFL_NEWSIZE; } else d->flags |= DEVFL_GDALLOC; @@ -756,12 +756,17 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector unsigned long n_sect = bio->bi_size >> 9; const int rw = bio_data_dir(bio); struct hd_struct *part; + int cpu; - part = get_part(disk, sector); - all_stat_inc(disk, part, ios[rw], sector); - all_stat_add(disk, part, ticks[rw], duration, sector); - all_stat_add(disk, part, sectors[rw], n_sect, sector); - all_stat_add(disk, part, io_ticks, duration, sector); + cpu = part_stat_lock(); + part = disk_map_sector_rcu(disk, sector); + + part_stat_inc(cpu, part, ios[rw]); + part_stat_add(cpu, part, ticks[rw], duration); + part_stat_add(cpu, part, sectors[rw], n_sect); + part_stat_add(cpu, part, io_ticks, duration); + + part_stat_unlock(); } void diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index a1d813ab0d6b..6a8038d115b5 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -91,7 +91,7 @@ aoedev_downdev(struct aoedev *d) } if (d->gd) - d->gd->capacity = 0; + set_capacity(d->gd, 0); d->flags &= ~DEVFL_UP; } diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b73116ef9236..1e1f9153000c 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3460,8 +3460,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not"); hba[i]->cmd_pool_bits = - kmalloc(((hba[i]->nr_cmds + BITS_PER_LONG - - 1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL); + kmalloc(DIV_ROUND_UP(hba[i]->nr_cmds, BITS_PER_LONG) + * sizeof(unsigned long), GFP_KERNEL); hba[i]->cmd_pool = (CommandList_struct *) pci_alloc_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct), @@ -3493,8 +3493,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* command and error info recs zeroed out before they are used */ memset(hba[i]->cmd_pool_bits, 0, - ((hba[i]->nr_cmds + BITS_PER_LONG - - 1) / BITS_PER_LONG) * sizeof(unsigned long)); + DIV_ROUND_UP(hba[i]->nr_cmds, BITS_PER_LONG) + * sizeof(unsigned long)); hba[i]->num_luns = 0; hba[i]->highest_lun = -1; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index e1233aabda77..a3fd87b41444 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -365,7 +365,7 @@ struct scsi2map { static int cciss_scsi_add_entry(int ctlr, int hostno, - unsigned char *scsi3addr, int devtype, + struct cciss_scsi_dev_t *device, struct scsi2map *added, int *nadded) { /* assumes hba[ctlr]->scsi_ctlr->lock is held */ @@ -384,12 +384,12 @@ cciss_scsi_add_entry(int ctlr, int hostno, lun = 0; /* Is this device a non-zero lun of a multi-lun device */ /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */ - if (scsi3addr[4] != 0) { + if (device->scsi3addr[4] != 0) { /* Search through our list and find the device which */ /* has the same 8 byte LUN address, excepting byte 4. */ /* Assign the same bus and target for this new LUN. */ /* Use the logical unit number from the firmware. */ - memcpy(addr1, scsi3addr, 8); + memcpy(addr1, device->scsi3addr, 8); addr1[4] = 0; for (i = 0; i < n; i++) { sd = &ccissscsi[ctlr].dev[i]; @@ -399,7 +399,7 @@ cciss_scsi_add_entry(int ctlr, int hostno, if (memcmp(addr1, addr2, 8) == 0) { bus = sd->bus; target = sd->target; - lun = scsi3addr[4]; + lun = device->scsi3addr[4]; break; } } @@ -420,8 +420,12 @@ cciss_scsi_add_entry(int ctlr, int hostno, added[*nadded].lun = sd->lun; (*nadded)++; - memcpy(&sd->scsi3addr[0], scsi3addr, 8); - sd->devtype = devtype; + memcpy(sd->scsi3addr, device->scsi3addr, 8); + memcpy(sd->vendor, device->vendor, sizeof(sd->vendor)); + memcpy(sd->revision, device->revision, sizeof(sd->revision)); + memcpy(sd->device_id, device->device_id, sizeof(sd->device_id)); + sd->devtype = device->devtype; + ccissscsi[ctlr].ndevices++; /* initially, (before registering with scsi layer) we don't @@ -487,6 +491,22 @@ static void fixup_botched_add(int ctlr, char *scsi3addr) CPQ_TAPE_UNLOCK(ctlr, flags); } +static int device_is_the_same(struct cciss_scsi_dev_t *dev1, + struct cciss_scsi_dev_t *dev2) +{ + return dev1->devtype == dev2->devtype && + memcmp(dev1->scsi3addr, dev2->scsi3addr, + sizeof(dev1->scsi3addr)) == 0 && + memcmp(dev1->device_id, dev2->device_id, + sizeof(dev1->device_id)) == 0 && + memcmp(dev1->vendor, dev2->vendor, + sizeof(dev1->vendor)) == 0 && + memcmp(dev1->model, dev2->model, + sizeof(dev1->model)) == 0 && + memcmp(dev1->revision, dev2->revision, + sizeof(dev1->revision)) == 0; +} + static int adjust_cciss_scsi_table(int ctlr, int hostno, struct cciss_scsi_dev_t sd[], int nsds) @@ -532,7 +552,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, for (j=0;j<nsds;j++) { if (SCSI3ADDR_EQ(sd[j].scsi3addr, csd->scsi3addr)) { - if (sd[j].devtype == csd->devtype) + if (device_is_the_same(&sd[j], csd)) found=2; else found=1; @@ -548,22 +568,26 @@ adjust_cciss_scsi_table(int ctlr, int hostno, cciss_scsi_remove_entry(ctlr, hostno, i, removed, &nremoved); /* remove ^^^, hence i not incremented */ - } - else if (found == 1) { /* device is different kind */ + } else if (found == 1) { /* device is different in some way */ changes++; - printk("cciss%d: device c%db%dt%dl%d type changed " - "(device type now %s).\n", - ctlr, hostno, csd->bus, csd->target, csd->lun, - scsi_device_type(csd->devtype)); + printk("cciss%d: device c%db%dt%dl%d has changed.\n", + ctlr, hostno, csd->bus, csd->target, csd->lun); cciss_scsi_remove_entry(ctlr, hostno, i, removed, &nremoved); /* remove ^^^, hence i not incremented */ - if (cciss_scsi_add_entry(ctlr, hostno, - &sd[j].scsi3addr[0], sd[j].devtype, + if (cciss_scsi_add_entry(ctlr, hostno, &sd[j], added, &nadded) != 0) /* we just removed one, so add can't fail. */ BUG(); csd->devtype = sd[j].devtype; + memcpy(csd->device_id, sd[j].device_id, + sizeof(csd->device_id)); + memcpy(csd->vendor, sd[j].vendor, + sizeof(csd->vendor)); + memcpy(csd->model, sd[j].model, + sizeof(csd->model)); + memcpy(csd->revision, sd[j].revision, + sizeof(csd->revision)); } else /* device is same as it ever was, */ i++; /* so just move along. */ } @@ -577,7 +601,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno, csd = &ccissscsi[ctlr].dev[j]; if (SCSI3ADDR_EQ(sd[i].scsi3addr, csd->scsi3addr)) { - if (sd[i].devtype == csd->devtype) + if (device_is_the_same(&sd[i], csd)) found=2; /* found device */ else found=1; /* found a bug. */ @@ -586,16 +610,14 @@ adjust_cciss_scsi_table(int ctlr, int hostno, } if (!found) { changes++; - if (cciss_scsi_add_entry(ctlr, hostno, - - &sd[i].scsi3addr[0], sd[i].devtype, + if (cciss_scsi_add_entry(ctlr, hostno, &sd[i], added, &nadded) != 0) break; } else if (found == 1) { /* should never happen... */ changes++; - printk("cciss%d: device unexpectedly changed type\n", - ctlr); + printk(KERN_WARNING "cciss%d: device " + "unexpectedly changed\n", ctlr); /* but if it does happen, we just ignore that device */ } } @@ -1012,7 +1034,8 @@ cciss_scsi_interpret_error(CommandList_struct *cp) static int cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, - unsigned char *buf, unsigned char bufsize) + unsigned char page, unsigned char *buf, + unsigned char bufsize) { int rc; CommandList_struct *cp; @@ -1032,8 +1055,8 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, ei = cp->err_info; cdb[0] = CISS_INQUIRY; - cdb[1] = 0; - cdb[2] = 0; + cdb[1] = (page != 0); + cdb[2] = page; cdb[3] = 0; cdb[4] = bufsize; cdb[5] = 0; @@ -1053,6 +1076,25 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, return rc; } +/* Get the device id from inquiry page 0x83 */ +static int cciss_scsi_get_device_id(ctlr_info_t *c, unsigned char *scsi3addr, + unsigned char *device_id, int buflen) +{ + int rc; + unsigned char *buf; + + if (buflen > 16) + buflen = 16; + buf = kzalloc(64, GFP_KERNEL); + if (!buf) + return -1; + rc = cciss_scsi_do_inquiry(c, scsi3addr, 0x83, buf, 64); + if (rc == 0) + memcpy(device_id, &buf[8], buflen); + kfree(buf); + return rc != 0; +} + static int cciss_scsi_do_report_phys_luns(ctlr_info_t *c, ReportLunData_struct *buf, int bufsize) @@ -1142,25 +1184,21 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) ctlr_info_t *c; __u32 num_luns=0; unsigned char *ch; - /* unsigned char found[CCISS_MAX_SCSI_DEVS_PER_HBA]; */ - struct cciss_scsi_dev_t currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; + struct cciss_scsi_dev_t *currentsd, *this_device; int ncurrent=0; int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; int i; c = (ctlr_info_t *) hba[cntl_num]; ld_buff = kzalloc(reportlunsize, GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return; - } inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; + currentsd = kzalloc(sizeof(*currentsd) * + (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL); + if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + goto out; } - + this_device = ¤tsd[CCISS_MAX_SCSI_DEVS_PER_HBA]; if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) { ch = &ld_buff->LUNListLength[0]; num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8; @@ -1179,23 +1217,34 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) /* adjust our table of devices */ - for(i=0; i<num_luns; i++) - { - int devtype; - + for (i = 0; i < num_luns; i++) { /* for each physical lun, do an inquiry */ if (ld_buff->LUN[i][3] & 0xC0) continue; memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE); memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); - if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff, - (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) { + if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 0, inq_buff, + (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) /* Inquiry failed (msg printed already) */ - devtype = 0; /* so we will skip this device. */ - } else /* what kind of device is this? */ - devtype = (inq_buff[0] & 0x1f); - - switch (devtype) + continue; /* so we will skip this device. */ + + this_device->devtype = (inq_buff[0] & 0x1f); + this_device->bus = -1; + this_device->target = -1; + this_device->lun = -1; + memcpy(this_device->scsi3addr, scsi3addr, 8); + memcpy(this_device->vendor, &inq_buff[8], + sizeof(this_device->vendor)); + memcpy(this_device->model, &inq_buff[16], + sizeof(this_device->model)); + memcpy(this_device->revision, &inq_buff[32], + sizeof(this_device->revision)); + memset(this_device->device_id, 0, + sizeof(this_device->device_id)); + cciss_scsi_get_device_id(hba[cntl_num], scsi3addr, + this_device->device_id, sizeof(this_device->device_id)); + + switch (this_device->devtype) { case 0x05: /* CD-ROM */ { @@ -1220,15 +1269,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { printk(KERN_INFO "cciss%d: %s ignored, " "too many devices.\n", cntl_num, - scsi_device_type(devtype)); + scsi_device_type(this_device->devtype)); break; } - memcpy(¤tsd[ncurrent].scsi3addr[0], - &scsi3addr[0], 8); - currentsd[ncurrent].devtype = devtype; - currentsd[ncurrent].bus = -1; - currentsd[ncurrent].target = -1; - currentsd[ncurrent].lun = -1; + currentsd[ncurrent] = *this_device; ncurrent++; break; default: @@ -1240,6 +1284,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) out: kfree(inq_buff); kfree(ld_buff); + kfree(currentsd); return; } diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h index d9c2c586502f..7b750245ae76 100644 --- a/drivers/block/cciss_scsi.h +++ b/drivers/block/cciss_scsi.h @@ -66,6 +66,10 @@ struct cciss_scsi_dev_t { int devtype; int bus, target, lun; /* as presented to the OS */ unsigned char scsi3addr[8]; /* as presented to the HW */ + unsigned char device_id[16]; /* from inquiry pg. 0x83 */ + unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ + unsigned char model[16]; /* bytes 16-31 of inquiry data */ + unsigned char revision[4]; /* bytes 32-35 of inquiry data */ }; struct cciss_scsi_hba_t { diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 09c14341e6e3..3d967525e9a9 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -424,7 +424,7 @@ static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t), &(hba[i]->cmd_pool_dhandle)); hba[i]->cmd_pool_bits = kcalloc( - (NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG, sizeof(unsigned long), + DIV_ROUND_UP(NR_CMDS, BITS_PER_LONG), sizeof(unsigned long), GFP_KERNEL); if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 395f8ea7981c..cf64ddf5d839 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -423,8 +423,15 @@ static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical * side 0 is on physical side 0 (but with the misnamed sector IDs). * 'stretch' should probably be renamed to something more general, like - * 'options'. Other parameters should be self-explanatory (see also - * setfdprm(8)). + * 'options'. + * + * Bits 2 through 9 of 'stretch' tell the number of the first sector. + * The LSB (bit 2) is flipped. For most disks, the first sector + * is 1 (represented by 0x00<<2). For some CP/M and music sampler + * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2). + * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2). + * + * Other parameters should be self-explanatory (see also setfdprm(8)). */ /* Size @@ -1355,20 +1362,20 @@ static void fdc_specify(void) } /* Convert step rate from microseconds to milliseconds and 4 bits */ - srt = 16 - (DP->srt * scale_dtr / 1000 + NOMINAL_DTR - 1) / NOMINAL_DTR; + srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR); if (slow_floppy) { srt = srt / 4; } SUPBOUND(srt, 0xf); INFBOUND(srt, 0); - hlt = (DP->hlt * scale_dtr / 2 + NOMINAL_DTR - 1) / NOMINAL_DTR; + hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR); if (hlt < 0x01) hlt = 0x01; else if (hlt > 0x7f) hlt = hlt_max_code; - hut = (DP->hut * scale_dtr / 16 + NOMINAL_DTR - 1) / NOMINAL_DTR; + hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR); if (hut < 0x1) hut = 0x1; else if (hut > 0xf) @@ -2236,9 +2243,9 @@ static void setup_format_params(int track) } } } - if (_floppy->stretch & FD_ZEROBASED) { + if (_floppy->stretch & FD_SECTBASEMASK) { for (count = 0; count < F_SECT_PER_TRACK; count++) - here[count].sect--; + here[count].sect += FD_SECTBASE(_floppy) - 1; } } @@ -2385,7 +2392,7 @@ static void rw_interrupt(void) #ifdef FLOPPY_SANITY_CHECK if (nr_sectors / ssize > - (in_sector_offset + current_count_sectors + ssize - 1) / ssize) { + DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) { DPRINT("long rw: %x instead of %lx\n", nr_sectors, current_count_sectors); printk("rs=%d s=%d\n", R_SECTOR, SECTOR); @@ -2649,7 +2656,7 @@ static int make_raw_rw_request(void) } HEAD = fsector_t / _floppy->sect; - if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) || + if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) || TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect) max_sector = _floppy->sect; @@ -2679,7 +2686,7 @@ static int make_raw_rw_request(void) CODE2SIZE; SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + - ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1); + FD_SECTBASE(_floppy); /* tracksize describes the size which can be filled up with sectors * of size ssize. @@ -3311,7 +3318,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, g->head <= 0 || g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) || /* check if reserved bits are set */ - (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0) + (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0) return -EINVAL; if (type) { if (!capable(CAP_SYS_ADMIN)) @@ -3356,7 +3363,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, if (DRS->maxblock > user_params[drive].sect || DRS->maxtrack || ((user_params[drive].sect ^ oldStretch) & - (FD_SWAPSIDES | FD_ZEROBASED))) + (FD_SWAPSIDES | FD_SECTBASEMASK))) invalidate_drive(bdev); else process_fd_request(); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 1778e4a2c672..7b3351260d56 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -403,7 +403,7 @@ static int nbd_do_it(struct nbd_device *lo) BUG_ON(lo->magic != LO_MAGIC); lo->pid = current->pid; - ret = sysfs_create_file(&lo->disk->dev.kobj, &pid_attr.attr); + ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); if (ret) { printk(KERN_ERR "nbd: sysfs_create_file failed!"); return ret; @@ -412,7 +412,7 @@ static int nbd_do_it(struct nbd_device *lo) while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); - sysfs_remove_file(&lo->disk->dev.kobj, &pid_attr.attr); + sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); return 0; } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 29b7a648cc6e..0e077150568b 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2544,7 +2544,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) if (last_zone != zone) { BUG_ON(last_zone != zone + pd->settings.size); first_sectors = last_zone - bio->bi_sector; - bp = bio_split(bio, bio_split_pool, first_sectors); + bp = bio_split(bio, first_sectors); BUG_ON(!bp); pkt_make_request(q, &bp->bio1); pkt_make_request(q, &bp->bio2); @@ -2911,7 +2911,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) if (!disk->queue) goto out_mem2; - pd->pkt_dev = MKDEV(disk->major, disk->first_minor); + pd->pkt_dev = MKDEV(pktdev_major, idx); ret = pkt_new_dev(pd, dev); if (ret) goto out_new_dev; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index d797e209951d..936466f62afd 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -199,7 +199,8 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, if (blk_fs_request(req)) { if (ps3disk_submit_request_sg(dev, req)) break; - } else if (req->cmd_type == REQ_TYPE_FLUSH) { + } else if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && + req->cmd[0] == REQ_LB_OP_FLUSH) { if (ps3disk_submit_flush_request(dev, req)) break; } else { @@ -257,7 +258,8 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) return IRQ_HANDLED; } - if (req->cmd_type == REQ_TYPE_FLUSH) { + if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && + req->cmd[0] == REQ_LB_OP_FLUSH) { read = 0; num_sectors = req->hard_cur_sectors; op = "flush"; @@ -405,7 +407,8 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req) dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); - req->cmd_type = REQ_TYPE_FLUSH; + req->cmd_type = REQ_TYPE_LINUX_BLOCK; + req->cmd[0] = REQ_LB_OP_FLUSH; } static unsigned long ps3disk_mask; @@ -538,7 +541,7 @@ static int ps3disk_remove(struct ps3_system_bus_device *_dev) struct ps3disk_private *priv = dev->sbd.core.driver_data; mutex_lock(&ps3disk_mask_mutex); - __clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS, + __clear_bit(MINOR(disk_devt(priv->gendisk)) / PS3DISK_MINORS, &ps3disk_mask); mutex_unlock(&ps3disk_mask_mutex); del_gendisk(priv->gendisk); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 42251095134f..6ec5fc052786 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -47,20 +47,20 @@ static void blk_done(struct virtqueue *vq) spin_lock_irqsave(&vblk->lock, flags); while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) { - int uptodate; + int error; switch (vbr->status) { case VIRTIO_BLK_S_OK: - uptodate = 1; + error = 0; break; case VIRTIO_BLK_S_UNSUPP: - uptodate = -ENOTTY; + error = -ENOTTY; break; default: - uptodate = 0; + error = -EIO; break; } - end_dequeued_request(vbr->req, uptodate); + __blk_end_request(vbr->req, error, blk_rq_bytes(vbr->req)); list_del(&vbr->list); mempool_free(vbr, vblk->pool); } @@ -84,11 +84,11 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, if (blk_fs_request(vbr->req)) { vbr->out_hdr.type = 0; vbr->out_hdr.sector = vbr->req->sector; - vbr->out_hdr.ioprio = vbr->req->ioprio; + vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); } else if (blk_pc_request(vbr->req)) { vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; vbr->out_hdr.sector = 0; - vbr->out_hdr.ioprio = vbr->req->ioprio; + vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); } else { /* We don't put anything else in the queue. */ BUG(); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 3ca643cafccd..bff602ccccf3 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -105,15 +105,17 @@ static DEFINE_SPINLOCK(blkif_io_lock); #define GRANT_INVALID_REF 0 #define PARTS_PER_DISK 16 +#define PARTS_PER_EXT_DISK 256 #define BLKIF_MAJOR(dev) ((dev)>>8) #define BLKIF_MINOR(dev) ((dev) & 0xff) -#define DEV_NAME "xvd" /* name in /dev */ +#define EXT_SHIFT 28 +#define EXTENDED (1<<EXT_SHIFT) +#define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED)) +#define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) -/* Information about our VBDs. */ -#define MAX_VBDS 64 -static LIST_HEAD(vbds_list); +#define DEV_NAME "xvd" /* name in /dev */ static int get_id_from_freelist(struct blkfront_info *info) { @@ -386,31 +388,60 @@ static int xlvbd_barrier(struct blkfront_info *info) } -static int xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity, - int vdevice, u16 vdisk_info, u16 sector_size, - struct blkfront_info *info) +static int xlvbd_alloc_gendisk(blkif_sector_t capacity, + struct blkfront_info *info, + u16 vdisk_info, u16 sector_size) { struct gendisk *gd; int nr_minors = 1; int err = -ENODEV; + unsigned int offset; + int minor; + int nr_parts; BUG_ON(info->gd != NULL); BUG_ON(info->rq != NULL); - if ((minor % PARTS_PER_DISK) == 0) - nr_minors = PARTS_PER_DISK; + if ((info->vdevice>>EXT_SHIFT) > 1) { + /* this is above the extended range; something is wrong */ + printk(KERN_WARNING "blkfront: vdevice 0x%x is above the extended range; ignoring\n", info->vdevice); + return -ENODEV; + } + + if (!VDEV_IS_EXTENDED(info->vdevice)) { + minor = BLKIF_MINOR(info->vdevice); + nr_parts = PARTS_PER_DISK; + } else { + minor = BLKIF_MINOR_EXT(info->vdevice); + nr_parts = PARTS_PER_EXT_DISK; + } + + if ((minor % nr_parts) == 0) + nr_minors = nr_parts; gd = alloc_disk(nr_minors); if (gd == NULL) goto out; - if (nr_minors > 1) - sprintf(gd->disk_name, "%s%c", DEV_NAME, - 'a' + minor / PARTS_PER_DISK); - else - sprintf(gd->disk_name, "%s%c%d", DEV_NAME, - 'a' + minor / PARTS_PER_DISK, - minor % PARTS_PER_DISK); + offset = minor / nr_parts; + + if (nr_minors > 1) { + if (offset < 26) + sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset); + else + sprintf(gd->disk_name, "%s%c%c", DEV_NAME, + 'a' + ((offset / 26)-1), 'a' + (offset % 26)); + } else { + if (offset < 26) + sprintf(gd->disk_name, "%s%c%d", DEV_NAME, + 'a' + offset, + minor & (nr_parts - 1)); + else + sprintf(gd->disk_name, "%s%c%c%d", DEV_NAME, + 'a' + ((offset / 26) - 1), + 'a' + (offset % 26), + minor & (nr_parts - 1)); + } gd->major = XENVBD_MAJOR; gd->first_minor = minor; @@ -699,8 +730,13 @@ static int blkfront_probe(struct xenbus_device *dev, err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device", "%i", &vdevice); if (err != 1) { - xenbus_dev_fatal(dev, err, "reading virtual-device"); - return err; + /* go looking in the extended area instead */ + err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device-ext", + "%i", &vdevice); + if (err != 1) { + xenbus_dev_fatal(dev, err, "reading virtual-device"); + return err; + } } info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -861,9 +897,7 @@ static void blkfront_connect(struct blkfront_info *info) if (err) info->feature_barrier = 0; - err = xlvbd_alloc_gendisk(BLKIF_MINOR(info->vdevice), - sectors, info->vdevice, - binfo, sector_size, info); + err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); if (err) { xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", info->xbdev->otherend); diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 74031de517e6..d47f2f80accd 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2097,7 +2097,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, len = nr * CD_FRAMESIZE_RAW; - ret = blk_rq_map_user(q, rq, ubuf, len); + ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL); if (ret) break; diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 1231d95aa695..d6ba77a2dd7b 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -624,14 +624,14 @@ static void gdrom_readdisk_dma(struct work_struct *work) ctrl_outb(1, GDROM_DMA_STATUS_REG); wait_event_interruptible_timeout(request_queue, gd.transfer == 0, GDROM_DEFAULT_TIMEOUT); - err = gd.transfer; + err = gd.transfer ? -EIO : 0; gd.transfer = 0; gd.pending = 0; /* now seek to take the request spinlock * before handling ending the request */ spin_lock(&gdrom_lock); list_del_init(&req->queuelist); - end_dequeued_request(req, 1 - err); + __blk_end_request(req, err, blk_rq_bytes(req)); } spin_unlock(&gdrom_lock); kfree(read_command); diff --git a/drivers/char/random.c b/drivers/char/random.c index 7ce1ac4baa6d..6af435b89867 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -661,10 +661,10 @@ void add_disk_randomness(struct gendisk *disk) if (!disk || !disk->random) return; /* first major is 1, so we get >= 0x200 here */ - DEBUG_ENT("disk event %d:%d\n", disk->major, disk->first_minor); + DEBUG_ENT("disk event %d:%d\n", + MAJOR(disk_devt(disk)), MINOR(disk_devt(disk))); - add_timer_randomness(disk->random, - 0x100 + MKDEV(disk->major, disk->first_minor)); + add_timer_randomness(disk->random, 0x100 + disk_devt(disk)); } #endif diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 3738cfa209ff..f5fc64f89c5c 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -6,6 +6,7 @@ menuconfig TCG_TPM tristate "TPM Hardware Support" depends on HAS_IOMEM depends on EXPERIMENTAL + select SECURITYFS ---help--- If you have a TPM security chip in your system, which implements the Trusted Computing Group's specification, diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index ae766d868454..1fee7034a386 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -954,72 +954,63 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel); /* * Device file system interface to the TPM + * + * It's assured that the chip will be opened just once, + * by the check of is_open variable, which is protected + * by driver_lock. */ int tpm_open(struct inode *inode, struct file *file) { - int rc = 0, minor = iminor(inode); + int minor = iminor(inode); struct tpm_chip *chip = NULL, *pos; - lock_kernel(); - spin_lock(&driver_lock); - - list_for_each_entry(pos, &tpm_chip_list, list) { + rcu_read_lock(); + list_for_each_entry_rcu(pos, &tpm_chip_list, list) { if (pos->vendor.miscdev.minor == minor) { chip = pos; + get_device(chip->dev); break; } } + rcu_read_unlock(); - if (chip == NULL) { - rc = -ENODEV; - goto err_out; - } + if (!chip) + return -ENODEV; - if (chip->num_opens) { + if (test_and_set_bit(0, &chip->is_open)) { dev_dbg(chip->dev, "Another process owns this TPM\n"); - rc = -EBUSY; - goto err_out; + put_device(chip->dev); + return -EBUSY; } - chip->num_opens++; - get_device(chip->dev); - - spin_unlock(&driver_lock); - chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); if (chip->data_buffer == NULL) { - chip->num_opens--; + clear_bit(0, &chip->is_open); put_device(chip->dev); - unlock_kernel(); return -ENOMEM; } atomic_set(&chip->data_pending, 0); file->private_data = chip; - unlock_kernel(); return 0; - -err_out: - spin_unlock(&driver_lock); - unlock_kernel(); - return rc; } EXPORT_SYMBOL_GPL(tpm_open); +/* + * Called on file close + */ int tpm_release(struct inode *inode, struct file *file) { struct tpm_chip *chip = file->private_data; + del_singleshot_timer_sync(&chip->user_read_timer); flush_scheduled_work(); - spin_lock(&driver_lock); file->private_data = NULL; - del_singleshot_timer_sync(&chip->user_read_timer); atomic_set(&chip->data_pending, 0); - chip->num_opens--; - put_device(chip->dev); kfree(chip->data_buffer); - spin_unlock(&driver_lock); + clear_bit(0, &chip->is_open); + put_device(chip->dev); return 0; } EXPORT_SYMBOL_GPL(tpm_release); @@ -1093,13 +1084,11 @@ void tpm_remove_hardware(struct device *dev) } spin_lock(&driver_lock); - - list_del(&chip->list); - + list_del_rcu(&chip->list); spin_unlock(&driver_lock); + synchronize_rcu(); misc_deregister(&chip->vendor.miscdev); - sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); tpm_bios_log_teardown(chip->bios_dir); @@ -1144,25 +1133,33 @@ int tpm_pm_resume(struct device *dev) } EXPORT_SYMBOL_GPL(tpm_pm_resume); +/* In case vendor provided release function, call it too.*/ + +void tpm_dev_vendor_release(struct tpm_chip *chip) +{ + if (chip->vendor.release) + chip->vendor.release(chip->dev); + + clear_bit(chip->dev_num, dev_mask); + kfree(chip->vendor.miscdev.name); +} +EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); + + /* * Once all references to platform device are down to 0, * release all allocated structures. - * In case vendor provided release function, - * call it too. */ static void tpm_dev_release(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip->vendor.release) - chip->vendor.release(dev); + tpm_dev_vendor_release(chip); chip->release(dev); - - clear_bit(chip->dev_num, dev_mask); - kfree(chip->vendor.miscdev.name); kfree(chip); } +EXPORT_SYMBOL_GPL(tpm_dev_release); /* * Called from tpm_<specific>.c probe function only for devices @@ -1171,8 +1168,8 @@ static void tpm_dev_release(struct device *dev) * upon errant exit from this function specific probe function should call * pci_disable_device */ -struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific - *entry) +struct tpm_chip *tpm_register_hardware(struct device *dev, + const struct tpm_vendor_specific *entry) { #define DEVNAME_SIZE 7 @@ -1231,21 +1228,20 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend return NULL; } - spin_lock(&driver_lock); - - list_add(&chip->list, &tpm_chip_list); - - spin_unlock(&driver_lock); - if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { - list_del(&chip->list); misc_deregister(&chip->vendor.miscdev); put_device(chip->dev); + return NULL; } chip->bios_dir = tpm_bios_log_setup(devname); + /* Make chip available */ + spin_lock(&driver_lock); + list_add_rcu(&chip->list, &tpm_chip_list); + spin_unlock(&driver_lock); + return chip; } EXPORT_SYMBOL_GPL(tpm_register_hardware); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e885148b4cfb..8e30df4a4388 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -90,7 +90,7 @@ struct tpm_chip { struct device *dev; /* Device stuff */ int dev_num; /* /dev/tpm# */ - int num_opens; /* only one allowed */ + unsigned long is_open; /* only one allowed */ int time_expired; /* Data passed to and from the tpm via the read/write calls */ @@ -132,6 +132,7 @@ extern struct tpm_chip* tpm_register_hardware(struct device *, const struct tpm_vendor_specific *); extern int tpm_open(struct inode *, struct file *); extern int tpm_release(struct inode *, struct file *); +extern void tpm_dev_vendor_release(struct tpm_chip *); extern ssize_t tpm_write(struct file *, const char __user *, size_t, loff_t *); extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index ed1879c0dd8d..717af7ad1bdf 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -630,12 +630,23 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { {"", 0} /* Terminator */ }; +static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev) +{ + struct tpm_chip *chip = pnp_get_drvdata(dev); + + tpm_dev_vendor_release(chip); + + kfree(chip); +} + + static struct pnp_driver tis_pnp_driver = { .name = "tpm_tis", .id_table = tpm_pnp_tbl, .probe = tpm_tis_pnp_init, .suspend = tpm_tis_pnp_suspend, .resume = tpm_tis_pnp_resume, + .remove = tpm_tis_pnp_remove, }; #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 @@ -683,6 +694,7 @@ static void __exit cleanup_tis(void) spin_lock(&tis_lock); list_for_each_entry_safe(i, j, &tis_chips, list) { chip = to_tpm_chip(i); + tpm_remove_hardware(chip->dev); iowrite32(~TPM_GLOBAL_INT_ENABLE & ioread32(chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor. @@ -694,9 +706,9 @@ static void __exit cleanup_tis(void) free_irq(chip->vendor.irq, chip); iounmap(i->iobase); list_del(&i->list); - tpm_remove_hardware(chip->dev); } spin_unlock(&tis_lock); + if (force) { platform_device_unregister(pdev); driver_unregister(&tis_drv); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index f16bb4667238..03c2cb6a58bc 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1113,7 +1113,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) if (write) { /* disk has become write protected */ - if (cd->disk->policy) { + if (get_disk_ro(cd->disk)) { cdrom_end_request(drive, 0); return ide_stopped; } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 07ef88bd109b..33ea8c048717 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -41,6 +41,12 @@ #include <asm/io.h> #include <asm/div64.h> +#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) +#define IDE_DISK_MINORS (1 << PARTN_BITS) +#else +#define IDE_DISK_MINORS 0 +#endif + struct ide_disk_obj { ide_drive_t *drive; ide_driver_t *driver; @@ -1151,8 +1157,7 @@ static int ide_disk_probe(ide_drive_t *drive) if (!idkp) goto failed; - g = alloc_disk_node(1 << PARTN_BITS, - hwif_to_node(drive->hwif)); + g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); if (!g) goto out_free_idkp; @@ -1178,9 +1183,11 @@ static int ide_disk_probe(ide_drive_t *drive) } else drive->attach = 1; - g->minors = 1 << PARTN_BITS; + g->minors = IDE_DISK_MINORS; g->driverfs_dev = &drive->gendev; - g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; + g->flags |= GENHD_FL_EXT_DEVT; + if (drive->removable) + g->flags |= GENHD_FL_REMOVABLE; set_capacity(g, idedisk_capacity(drive)); g->fops = &idedisk_ops; add_disk(g); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a51a30e9eab3..70aa86c8807e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1188,7 +1188,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data) { struct gendisk *p = data; *part &= (1 << PARTN_BITS) - 1; - return &p->dev.kobj; + return &disk_to_dev(p)->kobj; } static int exact_lock(dev_t dev, void *data) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 922d35f4fc08..3cab0cedfca2 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3748,6 +3748,7 @@ error1: cm_remove_port_fs(port); } device_unregister(cm_dev->device); + kfree(cm_dev); } static void cm_remove_one(struct ib_device *ib_device) @@ -3776,6 +3777,7 @@ static void cm_remove_one(struct ib_device *ib_device) cm_remove_port_fs(port); } device_unregister(cm_dev->device); + kfree(cm_dev); } static int __init ib_cm_init(void) diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 1adf2efd3cb3..49c45feccd5b 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -1697,9 +1697,8 @@ static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv, u8 port_num = mad_agent_priv->agent.port_num; u8 lmc; - send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> - mad_hdr.method & IB_MGMT_METHOD_RESP; - rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; + send_resp = ib_response_mad((struct ib_mad *)wr->send_buf.mad); + rcv_resp = ib_response_mad(rwc->recv_buf.mad); if (send_resp == rcv_resp) /* both requests, or both responses. GIDs different */ diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c index 2acf9b62cf99..69580e282af0 100644 --- a/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/drivers/infiniband/hw/amso1100/c2_provider.c @@ -272,7 +272,6 @@ static struct ib_qp *c2_create_qp(struct ib_pd *pd, pr_debug("%s: Invalid QP type: %d\n", __func__, init_attr->qp_type); return ERR_PTR(-EINVAL); - break; } if (err) { diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index eb778bfd6f66..ecff98043589 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -1155,13 +1155,11 @@ static int iwch_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props) { PDBG("%s ibdev %p\n", __func__, ibdev); + + memset(props, 0, sizeof(struct ib_port_attr)); props->max_mtu = IB_MTU_4096; - props->lid = 0; - props->lmc = 0; - props->sm_lid = 0; - props->sm_sl = 0; + props->active_mtu = IB_MTU_2048; props->state = IB_PORT_ACTIVE; - props->phys_state = 0; props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_SNMP_TUNNEL_SUP | @@ -1170,7 +1168,6 @@ static int iwch_query_port(struct ib_device *ibdev, IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; props->gid_tbl_len = 1; props->pkey_tbl_len = 1; - props->qkey_viol_cntr = 0; props->active_width = 2; props->active_speed = 2; props->max_msg_sz = -1; diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 1ab919f836a8..5d7b7855afb9 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -164,6 +164,13 @@ struct ehca_qmap_entry { u16 reported; }; +struct ehca_queue_map { + struct ehca_qmap_entry *map; + unsigned int entries; + unsigned int tail; + unsigned int left_to_poll; +}; + struct ehca_qp { union { struct ib_qp ib_qp; @@ -173,8 +180,9 @@ struct ehca_qp { enum ehca_ext_qp_type ext_type; enum ib_qp_state state; struct ipz_queue ipz_squeue; - struct ehca_qmap_entry *sq_map; + struct ehca_queue_map sq_map; struct ipz_queue ipz_rqueue; + struct ehca_queue_map rq_map; struct h_galpas galpas; u32 qkey; u32 real_qp_num; @@ -204,6 +212,8 @@ struct ehca_qp { atomic_t nr_events; /* events seen */ wait_queue_head_t wait_completion; int mig_armed; + struct list_head sq_err_node; + struct list_head rq_err_node; }; #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ) @@ -233,6 +243,8 @@ struct ehca_cq { /* mmap counter for resources mapped into user space */ u32 mm_count_queue; u32 mm_count_galpa; + struct list_head sqp_err_list; + struct list_head rqp_err_list; }; enum ehca_mr_flag { diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c index 5540b276a33c..33647a95eb9a 100644 --- a/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/drivers/infiniband/hw/ehca/ehca_cq.c @@ -276,6 +276,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, for (i = 0; i < QP_HASHTAB_LEN; i++) INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]); + INIT_LIST_HEAD(&my_cq->sqp_err_list); + INIT_LIST_HEAD(&my_cq->rqp_err_list); + if (context) { struct ipz_queue *ipz_queue = &my_cq->ipz_queue; struct ehca_create_cq_resp resp; diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index a8a2ea585d2f..8f7f282ead65 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -197,6 +197,8 @@ void ehca_poll_eqs(unsigned long data); int ehca_calc_ipd(struct ehca_shca *shca, int port, enum ib_rate path_rate, u32 *ipd); +void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq); + #ifdef CONFIG_PPC_64K_PAGES void *ehca_alloc_fw_ctrlblock(gfp_t flags); void ehca_free_fw_ctrlblock(void *ptr); diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index b6bcee036734..4dbe2870e014 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -396,6 +396,50 @@ static void ehca_determine_small_queue(struct ehca_alloc_queue_parms *queue, queue->is_small = (queue->page_size != 0); } +/* needs to be called with cq->spinlock held */ +void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq) +{ + struct list_head *list, *node; + + /* TODO: support low latency QPs */ + if (qp->ext_type == EQPT_LLQP) + return; + + if (on_sq) { + list = &qp->send_cq->sqp_err_list; + node = &qp->sq_err_node; + } else { + list = &qp->recv_cq->rqp_err_list; + node = &qp->rq_err_node; + } + + if (list_empty(node)) + list_add_tail(node, list); + + return; +} + +static void del_from_err_list(struct ehca_cq *cq, struct list_head *node) +{ + unsigned long flags; + + spin_lock_irqsave(&cq->spinlock, flags); + + if (!list_empty(node)) + list_del_init(node); + + spin_unlock_irqrestore(&cq->spinlock, flags); +} + +static void reset_queue_map(struct ehca_queue_map *qmap) +{ + int i; + + qmap->tail = 0; + for (i = 0; i < qmap->entries; i++) + qmap->map[i].reported = 1; +} + /* * Create an ib_qp struct that is either a QP or an SRQ, depending on * the value of the is_srq parameter. If init_attr and srq_init_attr share @@ -407,12 +451,11 @@ static struct ehca_qp *internal_create_qp( struct ib_srq_init_attr *srq_init_attr, struct ib_udata *udata, int is_srq) { - struct ehca_qp *my_qp; + struct ehca_qp *my_qp, *my_srq = NULL; struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, ib_device); struct ib_ucontext *context = NULL; - u32 nr_qes; u64 h_ret; int is_llqp = 0, has_srq = 0; int qp_type, max_send_sge, max_recv_sge, ret; @@ -457,8 +500,7 @@ static struct ehca_qp *internal_create_qp( /* handle SRQ base QPs */ if (init_attr->srq) { - struct ehca_qp *my_srq = - container_of(init_attr->srq, struct ehca_qp, ib_srq); + my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq); has_srq = 1; parms.ext_type = EQPT_SRQBASE; @@ -716,15 +758,19 @@ static struct ehca_qp *internal_create_qp( "and pages ret=%i", ret); goto create_qp_exit2; } - nr_qes = my_qp->ipz_squeue.queue_length / + + my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length / my_qp->ipz_squeue.qe_size; - my_qp->sq_map = vmalloc(nr_qes * + my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries * sizeof(struct ehca_qmap_entry)); - if (!my_qp->sq_map) { + if (!my_qp->sq_map.map) { ehca_err(pd->device, "Couldn't allocate squeue " "map ret=%i", ret); goto create_qp_exit3; } + INIT_LIST_HEAD(&my_qp->sq_err_node); + /* to avoid the generation of bogus flush CQEs */ + reset_queue_map(&my_qp->sq_map); } if (HAS_RQ(my_qp)) { @@ -736,6 +782,25 @@ static struct ehca_qp *internal_create_qp( "and pages ret=%i", ret); goto create_qp_exit4; } + + my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length / + my_qp->ipz_rqueue.qe_size; + my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries * + sizeof(struct ehca_qmap_entry)); + if (!my_qp->rq_map.map) { + ehca_err(pd->device, "Couldn't allocate squeue " + "map ret=%i", ret); + goto create_qp_exit5; + } + INIT_LIST_HEAD(&my_qp->rq_err_node); + /* to avoid the generation of bogus flush CQEs */ + reset_queue_map(&my_qp->rq_map); + } else if (init_attr->srq) { + /* this is a base QP, use the queue map of the SRQ */ + my_qp->rq_map = my_srq->rq_map; + INIT_LIST_HEAD(&my_qp->rq_err_node); + + my_qp->ipz_rqueue = my_srq->ipz_rqueue; } if (is_srq) { @@ -799,7 +864,7 @@ static struct ehca_qp *internal_create_qp( if (ret) { ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%i", ret); - goto create_qp_exit6; + goto create_qp_exit7; } } @@ -825,25 +890,29 @@ static struct ehca_qp *internal_create_qp( if (ib_copy_to_udata(udata, &resp, sizeof resp)) { ehca_err(pd->device, "Copy to udata failed"); ret = -EINVAL; - goto create_qp_exit7; + goto create_qp_exit8; } } return my_qp; -create_qp_exit7: +create_qp_exit8: ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num); -create_qp_exit6: +create_qp_exit7: kfree(my_qp->mod_qp_parm); +create_qp_exit6: + if (HAS_RQ(my_qp)) + vfree(my_qp->rq_map.map); + create_qp_exit5: if (HAS_RQ(my_qp)) ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); create_qp_exit4: if (HAS_SQ(my_qp)) - vfree(my_qp->sq_map); + vfree(my_qp->sq_map.map); create_qp_exit3: if (HAS_SQ(my_qp)) @@ -1035,6 +1104,101 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca, return 0; } +static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, + struct ehca_queue_map *qmap) +{ + void *wqe_v; + u64 q_ofs; + u32 wqe_idx; + + /* convert real to abs address */ + wqe_p = wqe_p & (~(1UL << 63)); + + wqe_v = abs_to_virt(wqe_p); + + if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) { + ehca_gen_err("Invalid offset for calculating left cqes " + "wqe_p=%#lx wqe_v=%p\n", wqe_p, wqe_v); + return -EFAULT; + } + + wqe_idx = q_ofs / ipz_queue->qe_size; + if (wqe_idx < qmap->tail) + qmap->left_to_poll = (qmap->entries - qmap->tail) + wqe_idx; + else + qmap->left_to_poll = wqe_idx - qmap->tail; + + return 0; +} + +static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca) +{ + u64 h_ret; + void *send_wqe_p, *recv_wqe_p; + int ret; + unsigned long flags; + int qp_num = my_qp->ib_qp.qp_num; + + /* this hcall is not supported on base QPs */ + if (my_qp->ext_type != EQPT_SRQBASE) { + /* get send and receive wqe pointer */ + h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle, + my_qp->ipz_qp_handle, &my_qp->pf, + &send_wqe_p, &recv_wqe_p, 4); + if (h_ret != H_SUCCESS) { + ehca_err(&shca->ib_device, "disable_and_get_wqe() " + "failed ehca_qp=%p qp_num=%x h_ret=%li", + my_qp, qp_num, h_ret); + return ehca2ib_return_code(h_ret); + } + + /* + * acquire lock to ensure that nobody is polling the cq which + * could mean that the qmap->tail pointer is in an + * inconsistent state. + */ + spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); + ret = calc_left_cqes((u64)send_wqe_p, &my_qp->ipz_squeue, + &my_qp->sq_map); + spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); + if (ret) + return ret; + + + spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); + ret = calc_left_cqes((u64)recv_wqe_p, &my_qp->ipz_rqueue, + &my_qp->rq_map); + spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); + if (ret) + return ret; + } else { + spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); + my_qp->sq_map.left_to_poll = 0; + spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); + + spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); + my_qp->rq_map.left_to_poll = 0; + spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); + } + + /* this assures flush cqes being generated only for pending wqes */ + if ((my_qp->sq_map.left_to_poll == 0) && + (my_qp->rq_map.left_to_poll == 0)) { + spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); + ehca_add_to_err_list(my_qp, 1); + spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); + + if (HAS_RQ(my_qp)) { + spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); + ehca_add_to_err_list(my_qp, 0); + spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, + flags); + } + } + + return 0; +} + /* * internal_modify_qp with circumvention to handle aqp0 properly * smi_reset2init indicates if this is an internal reset-to-init-call for @@ -1539,10 +1703,27 @@ static int internal_modify_qp(struct ib_qp *ibqp, goto modify_qp_exit2; } } + if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)) { + ret = check_for_left_cqes(my_qp, shca); + if (ret) + goto modify_qp_exit2; + } if (statetrans == IB_QPST_ANY2RESET) { ipz_qeit_reset(&my_qp->ipz_rqueue); ipz_qeit_reset(&my_qp->ipz_squeue); + + if (qp_cur_state == IB_QPS_ERR) { + del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); + + if (HAS_RQ(my_qp)) + del_from_err_list(my_qp->recv_cq, + &my_qp->rq_err_node); + } + reset_queue_map(&my_qp->sq_map); + + if (HAS_RQ(my_qp)) + reset_queue_map(&my_qp->rq_map); } if (attr_mask & IB_QP_QKEY) @@ -1958,6 +2139,16 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, idr_remove(&ehca_qp_idr, my_qp->token); write_unlock_irqrestore(&ehca_qp_idr_lock, flags); + /* + * SRQs will never get into an error list and do not have a recv_cq, + * so we need to skip them here. + */ + if (HAS_RQ(my_qp) && !IS_SRQ(my_qp)) + del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node); + + if (HAS_SQ(my_qp)) + del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node); + /* now wait until all pending events have completed */ wait_event(my_qp->wait_completion, !atomic_read(&my_qp->nr_events)); @@ -1983,7 +2174,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, if (qp_type == IB_QPT_GSI) { struct ib_event event; ehca_info(dev, "device %s: port %x is inactive.", - shca->ib_device.name, port_num); + shca->ib_device.name, port_num); event.device = &shca->ib_device; event.event = IB_EVENT_PORT_ERR; event.element.port_num = port_num; @@ -1991,11 +2182,15 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, ib_dispatch_event(&event); } - if (HAS_RQ(my_qp)) + if (HAS_RQ(my_qp)) { ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); + + vfree(my_qp->rq_map.map); + } if (HAS_SQ(my_qp)) { ipz_queue_dtor(my_pd, &my_qp->ipz_squeue); - vfree(my_qp->sq_map); + + vfree(my_qp->sq_map.map); } kmem_cache_free(qp_cache, my_qp); atomic_dec(&shca->num_qps); diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index 4426d82fe798..64928079eafa 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c @@ -53,9 +53,25 @@ /* in RC traffic, insert an empty RDMA READ every this many packets */ #define ACK_CIRC_THRESHOLD 2000000 +static u64 replace_wr_id(u64 wr_id, u16 idx) +{ + u64 ret; + + ret = wr_id & ~QMAP_IDX_MASK; + ret |= idx & QMAP_IDX_MASK; + + return ret; +} + +static u16 get_app_wr_id(u64 wr_id) +{ + return wr_id & QMAP_IDX_MASK; +} + static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue, struct ehca_wqe *wqe_p, - struct ib_recv_wr *recv_wr) + struct ib_recv_wr *recv_wr, + u32 rq_map_idx) { u8 cnt_ds; if (unlikely((recv_wr->num_sge < 0) || @@ -69,7 +85,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue, /* clear wqe header until sglist */ memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - wqe_p->work_request_id = recv_wr->wr_id; + wqe_p->work_request_id = replace_wr_id(recv_wr->wr_id, rq_map_idx); wqe_p->nr_of_data_seg = recv_wr->num_sge; for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) { @@ -146,6 +162,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, u64 dma_length; struct ehca_av *my_av; u32 remote_qkey = send_wr->wr.ud.remote_qkey; + struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx]; if (unlikely((send_wr->num_sge < 0) || (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) { @@ -158,11 +175,10 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, /* clear wqe header until sglist */ memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - wqe_p->work_request_id = send_wr->wr_id & ~QMAP_IDX_MASK; - wqe_p->work_request_id |= sq_map_idx & QMAP_IDX_MASK; + wqe_p->work_request_id = replace_wr_id(send_wr->wr_id, sq_map_idx); - qp->sq_map[sq_map_idx].app_wr_id = send_wr->wr_id & QMAP_IDX_MASK; - qp->sq_map[sq_map_idx].reported = 0; + qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id); + qmap_entry->reported = 0; switch (send_wr->opcode) { case IB_WR_SEND: @@ -496,7 +512,9 @@ static int internal_post_recv(struct ehca_qp *my_qp, struct ehca_wqe *wqe_p; int wqe_cnt = 0; int ret = 0; + u32 rq_map_idx; unsigned long flags; + struct ehca_qmap_entry *qmap_entry; if (unlikely(!HAS_RQ(my_qp))) { ehca_err(dev, "QP has no RQ ehca_qp=%p qp_num=%x ext_type=%d", @@ -524,8 +542,15 @@ static int internal_post_recv(struct ehca_qp *my_qp, } goto post_recv_exit0; } + /* + * Get the index of the WQE in the recv queue. The same index + * is used for writing into the rq_map. + */ + rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size; + /* write a RECV WQE into the QUEUE */ - ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr); + ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr, + rq_map_idx); /* * if something failed, * reset the free entry pointer to the start value @@ -540,6 +565,11 @@ static int internal_post_recv(struct ehca_qp *my_qp, } goto post_recv_exit0; } + + qmap_entry = &my_qp->rq_map.map[rq_map_idx]; + qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id); + qmap_entry->reported = 0; + wqe_cnt++; } /* eof for cur_recv_wr */ @@ -596,10 +626,12 @@ static const u8 ib_wc_opcode[255] = { /* internal function to poll one entry of cq */ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc) { - int ret = 0; + int ret = 0, qmap_tail_idx; struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); struct ehca_cqe *cqe; struct ehca_qp *my_qp; + struct ehca_qmap_entry *qmap_entry; + struct ehca_queue_map *qmap; int cqe_count = 0, is_error; repoll: @@ -674,27 +706,52 @@ repoll: goto repoll; wc->qp = &my_qp->ib_qp; - if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) { - struct ehca_qmap_entry *qmap_entry; + if (is_error) { /* - * We got a send completion and need to restore the original - * wr_id. + * set left_to_poll to 0 because in error state, we will not + * get any additional CQEs */ - qmap_entry = &my_qp->sq_map[cqe->work_request_id & - QMAP_IDX_MASK]; + ehca_add_to_err_list(my_qp, 1); + my_qp->sq_map.left_to_poll = 0; - if (qmap_entry->reported) { - ehca_warn(cq->device, "Double cqe on qp_num=%#x", - my_qp->real_qp_num); - /* found a double cqe, discard it and read next one */ - goto repoll; - } - wc->wr_id = cqe->work_request_id & ~QMAP_IDX_MASK; - wc->wr_id |= qmap_entry->app_wr_id; - qmap_entry->reported = 1; - } else + if (HAS_RQ(my_qp)) + ehca_add_to_err_list(my_qp, 0); + my_qp->rq_map.left_to_poll = 0; + } + + qmap_tail_idx = get_app_wr_id(cqe->work_request_id); + if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) + /* We got a send completion. */ + qmap = &my_qp->sq_map; + else /* We got a receive completion. */ - wc->wr_id = cqe->work_request_id; + qmap = &my_qp->rq_map; + + qmap_entry = &qmap->map[qmap_tail_idx]; + if (qmap_entry->reported) { + ehca_warn(cq->device, "Double cqe on qp_num=%#x", + my_qp->real_qp_num); + /* found a double cqe, discard it and read next one */ + goto repoll; + } + + wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id); + qmap_entry->reported = 1; + + /* this is a proper completion, we need to advance the tail pointer */ + if (++qmap->tail == qmap->entries) + qmap->tail = 0; + + /* if left_to_poll is decremented to 0, add the QP to the error list */ + if (qmap->left_to_poll > 0) { + qmap->left_to_poll--; + if ((my_qp->sq_map.left_to_poll == 0) && + (my_qp->rq_map.left_to_poll == 0)) { + ehca_add_to_err_list(my_qp, 1); + if (HAS_RQ(my_qp)) + ehca_add_to_err_list(my_qp, 0); + } + } /* eval ib_wc_opcode */ wc->opcode = ib_wc_opcode[cqe->optype]-1; @@ -733,13 +790,88 @@ poll_cq_one_exit0: return ret; } +static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, + struct ib_wc *wc, int num_entries, + struct ipz_queue *ipz_queue, int on_sq) +{ + int nr = 0; + struct ehca_wqe *wqe; + u64 offset; + struct ehca_queue_map *qmap; + struct ehca_qmap_entry *qmap_entry; + + if (on_sq) + qmap = &my_qp->sq_map; + else + qmap = &my_qp->rq_map; + + qmap_entry = &qmap->map[qmap->tail]; + + while ((nr < num_entries) && (qmap_entry->reported == 0)) { + /* generate flush CQE */ + memset(wc, 0, sizeof(*wc)); + + offset = qmap->tail * ipz_queue->qe_size; + wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset); + if (!wqe) { + ehca_err(cq->device, "Invalid wqe offset=%#lx on " + "qp_num=%#x", offset, my_qp->real_qp_num); + return nr; + } + + wc->wr_id = replace_wr_id(wqe->work_request_id, + qmap_entry->app_wr_id); + + if (on_sq) { + switch (wqe->optype) { + case WQE_OPTYPE_SEND: + wc->opcode = IB_WC_SEND; + break; + case WQE_OPTYPE_RDMAWRITE: + wc->opcode = IB_WC_RDMA_WRITE; + break; + case WQE_OPTYPE_RDMAREAD: + wc->opcode = IB_WC_RDMA_READ; + break; + default: + ehca_err(cq->device, "Invalid optype=%x", + wqe->optype); + return nr; + } + } else + wc->opcode = IB_WC_RECV; + + if (wqe->wr_flag & WQE_WRFLAG_IMM_DATA_PRESENT) { + wc->ex.imm_data = wqe->immediate_data; + wc->wc_flags |= IB_WC_WITH_IMM; + } + + wc->status = IB_WC_WR_FLUSH_ERR; + + wc->qp = &my_qp->ib_qp; + + /* mark as reported and advance tail pointer */ + qmap_entry->reported = 1; + if (++qmap->tail == qmap->entries) + qmap->tail = 0; + qmap_entry = &qmap->map[qmap->tail]; + + wc++; nr++; + } + + return nr; + +} + int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc) { struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); int nr; + struct ehca_qp *err_qp; struct ib_wc *current_wc = wc; int ret = 0; unsigned long flags; + int entries_left = num_entries; if (num_entries < 1) { ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p " @@ -749,15 +881,40 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc) } spin_lock_irqsave(&my_cq->spinlock, flags); - for (nr = 0; nr < num_entries; nr++) { + + /* generate flush cqes for send queues */ + list_for_each_entry(err_qp, &my_cq->sqp_err_list, sq_err_node) { + nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left, + &err_qp->ipz_squeue, 1); + entries_left -= nr; + current_wc += nr; + + if (entries_left == 0) + break; + } + + /* generate flush cqes for receive queues */ + list_for_each_entry(err_qp, &my_cq->rqp_err_list, rq_err_node) { + nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left, + &err_qp->ipz_rqueue, 0); + entries_left -= nr; + current_wc += nr; + + if (entries_left == 0) + break; + } + + for (nr = 0; nr < entries_left; nr++) { ret = ehca_poll_cq_one(cq, current_wc); if (ret) break; current_wc++; } /* eof for nr */ + entries_left -= nr; + spin_unlock_irqrestore(&my_cq->spinlock, flags); if (ret == -EAGAIN || !ret) - ret = nr; + ret = num_entries - entries_left; poll_cq_exit0: return ret; diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 97710522624d..7b93cda1a4bd 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -675,7 +675,8 @@ static void send_rc_ack(struct ipath_qp *qp) hdr.lrh[0] = cpu_to_be16(lrh0); hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC); - hdr.lrh[3] = cpu_to_be16(dd->ipath_lid); + hdr.lrh[3] = cpu_to_be16(dd->ipath_lid | + qp->remote_ah_attr.src_path_bits); ohdr->bth[0] = cpu_to_be32(bth0); ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK); diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index af051f757663..fc0f6d9e6030 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -618,7 +618,8 @@ void ipath_make_ruc_header(struct ipath_ibdev *dev, struct ipath_qp *qp, qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC); - qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid); + qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid | + qp->remote_ah_attr.src_path_bits); bth0 |= ipath_get_pkey(dev->dd, qp->s_pkey_index); bth0 |= extra_bytes << 20; ohdr->bth[0] = cpu_to_be32(bth0 | (1 << 22)); diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index b766e40e9ebf..eabc4247860b 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -340,9 +340,16 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr) int acc; int ret; unsigned long flags; + struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd; spin_lock_irqsave(&qp->s_lock, flags); + if (qp->ibqp.qp_type != IB_QPT_SMI && + !(dd->ipath_flags & IPATH_LINKACTIVE)) { + ret = -ENETDOWN; + goto bail; + } + /* Check that state is OK to post send. */ if (unlikely(!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK))) goto bail_inval; diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 9559248f265b..baa01deb2436 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1058,6 +1058,9 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, else sqd_event = 0; + if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) + context->rlkey |= (1 << 4); + /* * Before passing a kernel QP to the HW, make sure that the * ownership bits of the send queue are set and the SQ diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index cc440f90000b..65ad359fdf16 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c @@ -149,18 +149,10 @@ void mthca_start_catas_poll(struct mthca_dev *dev) ((pci_resource_len(dev->pdev, 0) - 1) & dev->catas_err.addr); - if (!request_mem_region(addr, dev->catas_err.size * 4, - DRV_NAME)) { - mthca_warn(dev, "couldn't request catastrophic error region " - "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4); - return; - } - dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4); if (!dev->catas_err.map) { mthca_warn(dev, "couldn't map catastrophic error region " "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4); - release_mem_region(addr, dev->catas_err.size * 4); return; } @@ -175,13 +167,8 @@ void mthca_stop_catas_poll(struct mthca_dev *dev) { del_timer_sync(&dev->catas_err.timer); - if (dev->catas_err.map) { + if (dev->catas_err.map) iounmap(dev->catas_err.map); - release_mem_region(pci_resource_start(dev->pdev, 0) + - ((pci_resource_len(dev->pdev, 0) - 1) & - dev->catas_err.addr), - dev->catas_err.size * 4); - } spin_lock_irq(&catas_lock); list_del(&dev->catas_err.list); diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index cc6858f0b65b..28f0e0c40d7d 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -652,27 +652,13 @@ static int mthca_map_reg(struct mthca_dev *dev, { unsigned long base = pci_resource_start(dev->pdev, 0); - if (!request_mem_region(base + offset, size, DRV_NAME)) - return -EBUSY; - *map = ioremap(base + offset, size); - if (!*map) { - release_mem_region(base + offset, size); + if (!*map) return -ENOMEM; - } return 0; } -static void mthca_unmap_reg(struct mthca_dev *dev, unsigned long offset, - unsigned long size, void __iomem *map) -{ - unsigned long base = pci_resource_start(dev->pdev, 0); - - release_mem_region(base + offset, size); - iounmap(map); -} - static int mthca_map_eq_regs(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) { @@ -699,9 +685,7 @@ static int mthca_map_eq_regs(struct mthca_dev *dev) dev->fw.arbel.eq_arm_base) + 4, 4, &dev->eq_regs.arbel.eq_arm)) { mthca_err(dev, "Couldn't map EQ arm register, aborting.\n"); - mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & - dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE, - dev->clr_base); + iounmap(dev->clr_base); return -ENOMEM; } @@ -710,12 +694,8 @@ static int mthca_map_eq_regs(struct mthca_dev *dev) MTHCA_EQ_SET_CI_SIZE, &dev->eq_regs.arbel.eq_set_ci_base)) { mthca_err(dev, "Couldn't map EQ CI register, aborting.\n"); - mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) & - dev->fw.arbel.eq_arm_base) + 4, 4, - dev->eq_regs.arbel.eq_arm); - mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & - dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE, - dev->clr_base); + iounmap(dev->eq_regs.arbel.eq_arm); + iounmap(dev->clr_base); return -ENOMEM; } } else { @@ -731,8 +711,7 @@ static int mthca_map_eq_regs(struct mthca_dev *dev) &dev->eq_regs.tavor.ecr_base)) { mthca_err(dev, "Couldn't map ecr register, " "aborting.\n"); - mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE, - dev->clr_base); + iounmap(dev->clr_base); return -ENOMEM; } } @@ -744,22 +723,12 @@ static int mthca_map_eq_regs(struct mthca_dev *dev) static void mthca_unmap_eq_regs(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) { - mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & - dev->fw.arbel.eq_set_ci_base, - MTHCA_EQ_SET_CI_SIZE, - dev->eq_regs.arbel.eq_set_ci_base); - mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) & - dev->fw.arbel.eq_arm_base) + 4, 4, - dev->eq_regs.arbel.eq_arm); - mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & - dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE, - dev->clr_base); + iounmap(dev->eq_regs.arbel.eq_set_ci_base); + iounmap(dev->eq_regs.arbel.eq_arm); + iounmap(dev->clr_base); } else { - mthca_unmap_reg(dev, MTHCA_ECR_BASE, - MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE, - dev->eq_regs.tavor.ecr_base); - mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE, - dev->clr_base); + iounmap(dev->eq_regs.tavor.ecr_base); + iounmap(dev->clr_base); } } diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index fb9f91b60f30..52f60f4eea00 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -921,58 +921,6 @@ err_uar_table_free: return err; } -static int mthca_request_regions(struct pci_dev *pdev, int ddr_hidden) -{ - int err; - - /* - * We can't just use pci_request_regions() because the MSI-X - * table is right in the middle of the first BAR. If we did - * pci_request_region and grab all of the first BAR, then - * setting up MSI-X would fail, since the PCI core wants to do - * request_mem_region on the MSI-X vector table. - * - * So just request what we need right now, and request any - * other regions we need when setting up EQs. - */ - if (!request_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, - MTHCA_HCR_SIZE, DRV_NAME)) - return -EBUSY; - - err = pci_request_region(pdev, 2, DRV_NAME); - if (err) - goto err_bar2_failed; - - if (!ddr_hidden) { - err = pci_request_region(pdev, 4, DRV_NAME); - if (err) - goto err_bar4_failed; - } - - return 0; - -err_bar4_failed: - pci_release_region(pdev, 2); - -err_bar2_failed: - release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, - MTHCA_HCR_SIZE); - - return err; -} - -static void mthca_release_regions(struct pci_dev *pdev, - int ddr_hidden) -{ - if (!ddr_hidden) - pci_release_region(pdev, 4); - - pci_release_region(pdev, 2); - - release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, - MTHCA_HCR_SIZE); -} - static int mthca_enable_msi_x(struct mthca_dev *mdev) { struct msix_entry entries[3]; @@ -1059,7 +1007,7 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type) if (!(pci_resource_flags(pdev, 4) & IORESOURCE_MEM)) ddr_hidden = 1; - err = mthca_request_regions(pdev, ddr_hidden); + err = pci_request_regions(pdev, DRV_NAME); if (err) { dev_err(&pdev->dev, "Cannot obtain PCI resources, " "aborting.\n"); @@ -1196,7 +1144,7 @@ err_free_dev: ib_dealloc_device(&mdev->ib_dev); err_free_res: - mthca_release_regions(pdev, ddr_hidden); + pci_release_regions(pdev); err_disable_pdev: pci_disable_device(pdev); @@ -1240,8 +1188,7 @@ static void __mthca_remove_one(struct pci_dev *pdev) pci_disable_msix(pdev); ib_dealloc_device(&mdev->ib_dev); - mthca_release_regions(pdev, mdev->mthca_flags & - MTHCA_FLAG_DDR_HIDDEN); + pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index b0cab64e5e3d..a2b04d62b1a4 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -70,27 +70,31 @@ int interrupt_mod_interval = 0; /* Interoperability */ int mpa_version = 1; -module_param(mpa_version, int, 0); +module_param(mpa_version, int, 0644); MODULE_PARM_DESC(mpa_version, "MPA version to be used int MPA Req/Resp (0 or 1)"); /* Interoperability */ int disable_mpa_crc = 0; -module_param(disable_mpa_crc, int, 0); +module_param(disable_mpa_crc, int, 0644); MODULE_PARM_DESC(disable_mpa_crc, "Disable checking of MPA CRC"); unsigned int send_first = 0; -module_param(send_first, int, 0); +module_param(send_first, int, 0644); MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection"); unsigned int nes_drv_opt = 0; -module_param(nes_drv_opt, int, 0); +module_param(nes_drv_opt, int, 0644); MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters"); unsigned int nes_debug_level = 0; module_param_named(debug_level, nes_debug_level, uint, 0644); MODULE_PARM_DESC(debug_level, "Enable debug output level"); +unsigned int wqm_quanta = 0x10000; +module_param(wqm_quanta, int, 0644); +MODULE_PARM_DESC(wqm_quanta, "WQM quanta"); + LIST_HEAD(nes_adapter_list); static LIST_HEAD(nes_dev_list); @@ -557,12 +561,32 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i goto bail5; } nesdev->nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval; + nesdev->nesadapter->wqm_quanta = wqm_quanta; /* nesdev->base_doorbell_index = nesdev->nesadapter->pd_config_base[PCI_FUNC(nesdev->pcidev->devfn)]; */ nesdev->base_doorbell_index = 1; nesdev->doorbell_start = nesdev->nesadapter->doorbell_start; - nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % nesdev->nesadapter->port_count; + if (nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { + switch (PCI_FUNC(nesdev->pcidev->devfn) % + nesdev->nesadapter->port_count) { + case 1: + nesdev->mac_index = 2; + break; + case 2: + nesdev->mac_index = 1; + break; + case 3: + nesdev->mac_index = 3; + break; + case 0: + default: + nesdev->mac_index = 0; + } + } else { + nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % + nesdev->nesadapter->port_count; + } tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); @@ -581,7 +605,7 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i nesdev->int_req = (0x101 << PCI_FUNC(nesdev->pcidev->devfn)) | (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16)); if (PCI_FUNC(nesdev->pcidev->devfn) < 4) { - nesdev->int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+24)); + nesdev->int_req |= (1 << (PCI_FUNC(nesdev->mac_index)+24)); } /* TODO: This really should be the first driver to load, not function 0 */ @@ -772,14 +796,14 @@ static ssize_t nes_show_adapter(struct device_driver *ddp, char *buf) list_for_each_entry(nesdev, &nes_dev_list, list) { if (i == ee_flsh_adapter) { - devfn = nesdev->nesadapter->devfn; - bus_number = nesdev->nesadapter->bus_number; + devfn = nesdev->pcidev->devfn; + bus_number = nesdev->pcidev->bus->number; break; } i++; } - return snprintf(buf, PAGE_SIZE, "%x:%x", bus_number, devfn); + return snprintf(buf, PAGE_SIZE, "%x:%x\n", bus_number, devfn); } static ssize_t nes_store_adapter(struct device_driver *ddp, @@ -1050,6 +1074,55 @@ static ssize_t nes_store_idx_data(struct device_driver *ddp, return strnlen(buf, count); } + +/** + * nes_show_wqm_quanta + */ +static ssize_t nes_show_wqm_quanta(struct device_driver *ddp, char *buf) +{ + u32 wqm_quanta_value = 0xdead; + u32 i = 0; + struct nes_device *nesdev; + + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + wqm_quanta_value = nesdev->nesadapter->wqm_quanta; + break; + } + i++; + } + + return snprintf(buf, PAGE_SIZE, "0x%X\n", wqm_quanta); +} + + +/** + * nes_store_wqm_quanta + */ +static ssize_t nes_store_wqm_quanta(struct device_driver *ddp, + const char *buf, size_t count) +{ + unsigned long wqm_quanta_value; + u32 wqm_config1; + u32 i = 0; + struct nes_device *nesdev; + + strict_strtoul(buf, 0, &wqm_quanta_value); + list_for_each_entry(nesdev, &nes_dev_list, list) { + if (i == ee_flsh_adapter) { + nesdev->nesadapter->wqm_quanta = wqm_quanta_value; + wqm_config1 = nes_read_indexed(nesdev, + NES_IDX_WQM_CONFIG1); + nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, + ((wqm_quanta_value << 1) | + (wqm_config1 & 0x00000001))); + break; + } + i++; + } + return strnlen(buf, count); +} + static DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR, nes_show_adapter, nes_store_adapter); static DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR, @@ -1068,6 +1141,8 @@ static DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR, nes_show_idx_addr, nes_store_idx_addr); static DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR, nes_show_idx_data, nes_store_idx_data); +static DRIVER_ATTR(wqm_quanta, S_IRUSR | S_IWUSR, + nes_show_wqm_quanta, nes_store_wqm_quanta); static int nes_create_driver_sysfs(struct pci_driver *drv) { @@ -1081,6 +1156,7 @@ static int nes_create_driver_sysfs(struct pci_driver *drv) error |= driver_create_file(&drv->driver, &driver_attr_nonidx_data); error |= driver_create_file(&drv->driver, &driver_attr_idx_addr); error |= driver_create_file(&drv->driver, &driver_attr_idx_data); + error |= driver_create_file(&drv->driver, &driver_attr_wqm_quanta); return error; } @@ -1095,6 +1171,7 @@ static void nes_remove_driver_sysfs(struct pci_driver *drv) driver_remove_file(&drv->driver, &driver_attr_nonidx_data); driver_remove_file(&drv->driver, &driver_attr_idx_addr); driver_remove_file(&drv->driver, &driver_attr_idx_data); + driver_remove_file(&drv->driver, &driver_attr_wqm_quanta); } /** diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 8eb7ae96974d..1595dc7bba9d 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -169,7 +169,7 @@ extern int disable_mpa_crc; extern unsigned int send_first; extern unsigned int nes_drv_opt; extern unsigned int nes_debug_level; - +extern unsigned int wqm_quanta; extern struct list_head nes_adapter_list; extern atomic_t cm_connects; diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 499d3cf83e1f..2caf9da81ad5 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -52,7 +52,7 @@ #include <linux/random.h> #include <linux/list.h> #include <linux/threads.h> - +#include <net/arp.h> #include <net/neighbour.h> #include <net/route.h> #include <net/ip_fib.h> @@ -1019,23 +1019,43 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core, /** - * nes_addr_send_arp + * nes_addr_resolve_neigh */ -static void nes_addr_send_arp(u32 dst_ip) +static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip) { struct rtable *rt; struct flowi fl; + struct neighbour *neigh; + int rc = -1; + DECLARE_MAC_BUF(mac); memset(&fl, 0, sizeof fl); fl.nl_u.ip4_u.daddr = htonl(dst_ip); if (ip_route_output_key(&init_net, &rt, &fl)) { printk("%s: ip_route_output_key failed for 0x%08X\n", __func__, dst_ip); - return; + return rc; + } + + neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, nesvnic->netdev); + if (neigh) { + if (neigh->nud_state & NUD_VALID) { + nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X" + " is %s, Gateway is 0x%08X \n", dst_ip, + print_mac(mac, neigh->ha), ntohl(rt->rt_gateway)); + nes_manage_arp_cache(nesvnic->netdev, neigh->ha, + dst_ip, NES_ARP_ADD); + rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL, + NES_ARP_RESOLVE); + } + neigh_release(neigh); } - neigh_event_send(rt->u.dst.neighbour, NULL); + if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) + neigh_event_send(rt->u.dst.neighbour, NULL); + ip_rt_put(rt); + return rc; } @@ -1108,9 +1128,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, /* get the mac addr for the remote node */ arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE); if (arpindex < 0) { - kfree(cm_node); - nes_addr_send_arp(cm_info->rem_addr); - return NULL; + arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr); + if (arpindex < 0) { + kfree(cm_node); + return NULL; + } } /* copy the mac addr to node context */ @@ -1826,7 +1848,7 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core, /** * mini_cm_connect - make a connection node with params */ -struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, +static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic, u16 private_data_len, void *private_data, struct nes_cm_info *cm_info) { @@ -2007,7 +2029,6 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod ret = rem_ref_cm_node(cm_core, cm_node); break; } - cm_node->cm_id = NULL; return ret; } diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 1513d4066f1b..7c49cc882d75 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -55,18 +55,19 @@ u32 int_mod_cq_depth_24; u32 int_mod_cq_depth_16; u32 int_mod_cq_depth_4; u32 int_mod_cq_depth_1; - +static const u8 nes_max_critical_error_count = 100; #include "nes_cm.h" static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq); static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count); static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, - u8 OneG_Mode); + struct nes_adapter *nesadapter, u8 OneG_Mode); static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq); static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq); static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq); static void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe); +static void process_critical_error(struct nes_device *nesdev); static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); @@ -222,11 +223,10 @@ static void nes_nic_tune_timer(struct nes_device *nesdev) } /* boundary checking */ - if (shared_timer->timer_in_use > NES_NIC_FAST_TIMER_HIGH) - shared_timer->timer_in_use = NES_NIC_FAST_TIMER_HIGH; - else if (shared_timer->timer_in_use < NES_NIC_FAST_TIMER_LOW) { - shared_timer->timer_in_use = NES_NIC_FAST_TIMER_LOW; - } + if (shared_timer->timer_in_use > shared_timer->threshold_high) + shared_timer->timer_in_use = shared_timer->threshold_high; + else if (shared_timer->timer_in_use < shared_timer->threshold_low) + shared_timer->timer_in_use = shared_timer->threshold_low; nesdev->currcq_count = 0; @@ -292,9 +292,6 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0) return NULL; - if (nes_init_serdes(nesdev, hw_rev, port_count, OneG_Mode)) - return NULL; - nes_init_csr_ne020(nesdev, hw_rev, port_count); max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE); nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp); @@ -353,6 +350,22 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n", nesadapter, (u32)sizeof(struct nes_adapter), adapter_size); + if (nes_read_eeprom_values(nesdev, nesadapter)) { + printk(KERN_ERR PFX "Unable to read EEPROM data.\n"); + kfree(nesadapter); + return NULL; + } + + if (nes_init_serdes(nesdev, hw_rev, port_count, nesadapter, + OneG_Mode)) { + kfree(nesadapter); + return NULL; + } + nes_init_csr_ne020(nesdev, hw_rev, port_count); + + memset(nesadapter->pft_mcast_map, 255, + sizeof nesadapter->pft_mcast_map); + /* populate the new nesadapter */ nesadapter->devfn = nesdev->pcidev->devfn; nesadapter->bus_number = nesdev->pcidev->bus->number; @@ -468,20 +481,25 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { /* setup port configuration */ if (nesadapter->port_count == 1) { - u32temp = 0x00000000; + nesadapter->log_port = 0x00000000; if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002); else nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003); } else { - if (nesadapter->port_count == 2) - u32temp = 0x00000044; - else - u32temp = 0x000000e4; + if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { + nesadapter->log_port = 0x000000D8; + } else { + if (nesadapter->port_count == 2) + nesadapter->log_port = 0x00000044; + else + nesadapter->log_port = 0x000000e4; + } nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003); } - nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT, u32temp); + nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT, + nesadapter->log_port); nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n", nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT)); @@ -706,23 +724,43 @@ static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_ * nes_init_serdes */ static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, - u8 OneG_Mode) + struct nes_adapter *nesadapter, u8 OneG_Mode) { int i; u32 u32temp; + u32 serdes_common_control; if (hw_rev != NE020_REV) { /* init serdes 0 */ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF); - if (!OneG_Mode) + if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { + serdes_common_control = nes_read_indexed(nesdev, + NES_IDX_ETH_SERDES_COMMON_CONTROL0); + serdes_common_control |= 0x000000100; + nes_write_indexed(nesdev, + NES_IDX_ETH_SERDES_COMMON_CONTROL0, + serdes_common_control); + } else if (!OneG_Mode) { nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000); - if (port_count > 1) { + } + if (((port_count > 1) && + (nesadapter->phy_type[0] != NES_PHY_TYPE_PUMA_1G)) || + ((port_count > 2) && + (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G))) { /* init serdes 1 */ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF); - if (!OneG_Mode) + if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { + serdes_common_control = nes_read_indexed(nesdev, + NES_IDX_ETH_SERDES_COMMON_CONTROL1); + serdes_common_control |= 0x000000100; + nes_write_indexed(nesdev, + NES_IDX_ETH_SERDES_COMMON_CONTROL1, + serdes_common_control); + } else if (!OneG_Mode) { nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000); } + } } else { /* init serdes 0 */ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); @@ -826,7 +864,8 @@ static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_cou nes_write_indexed(nesdev, 0x00005000, 0x00018000); /* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */ - nes_write_indexed(nesdev, 0x00005004, 0x00020001); + nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, (wqm_quanta << 1) | + 0x00000001); nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F); nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F); nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F); @@ -1226,6 +1265,7 @@ int nes_init_phy(struct nes_device *nesdev) if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) { printk(PFX "%s: Programming mdc config for 1G\n", __func__); tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); + tx_config &= 0xFFFFFFE3; tx_config |= 0x04; nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); } @@ -1291,7 +1331,8 @@ int nes_init_phy(struct nes_device *nesdev) (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) { /* setup 10G MDIO operation */ tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG); - tx_config |= 0x14; + tx_config &= 0xFFFFFFE3; + tx_config |= 0x15; nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); } if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) { @@ -1315,7 +1356,7 @@ int nes_init_phy(struct nes_device *nesdev) nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc319, 0x0008); nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc31a, 0x0098); nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0026, 0x0E00); - nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0000); + nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0001); nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0028, 0xA528); /* @@ -1759,9 +1800,14 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) */ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) { + u64 u64temp; + dma_addr_t bus_address; struct nes_device *nesdev = nesvnic->nesdev; struct nes_hw_cqp_wqe *cqp_wqe; + struct nes_hw_nic_sq_wqe *nic_sqe; struct nes_hw_nic_rq_wqe *nic_rqe; + __le16 *wqe_fragment_length; + u16 wqe_fragment_index; u64 wqe_frag; u32 cqp_head; unsigned long flags; @@ -1770,14 +1816,69 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) /* Free remaining NIC receive buffers */ while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) { nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail]; - wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]); - wqe_frag |= ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32; + wqe_frag = (u64)le32_to_cpu( + nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]); + wqe_frag |= ((u64)le32_to_cpu( + nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32; pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE); dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]); nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1); } + /* Free remaining NIC transmit buffers */ + while (nesvnic->nic.sq_head != nesvnic->nic.sq_tail) { + nic_sqe = &nesvnic->nic.sq_vbase[nesvnic->nic.sq_tail]; + wqe_fragment_index = 1; + wqe_fragment_length = (__le16 *) + &nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX]; + /* bump past the vlan tag */ + wqe_fragment_length++; + if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) { + u64temp = (u64)le32_to_cpu( + nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+ + wqe_fragment_index*2]); + u64temp += ((u64)le32_to_cpu( + nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX + + wqe_fragment_index*2]))<<32; + bus_address = (dma_addr_t)u64temp; + if (test_and_clear_bit(nesvnic->nic.sq_tail, + nesvnic->nic.first_frag_overflow)) { + pci_unmap_single(nesdev->pcidev, + bus_address, + le16_to_cpu(wqe_fragment_length[ + wqe_fragment_index++]), + PCI_DMA_TODEVICE); + } + for (; wqe_fragment_index < 5; wqe_fragment_index++) { + if (wqe_fragment_length[wqe_fragment_index]) { + u64temp = le32_to_cpu( + nic_sqe->wqe_words[ + NES_NIC_SQ_WQE_FRAG0_LOW_IDX+ + wqe_fragment_index*2]); + u64temp += ((u64)le32_to_cpu( + nic_sqe->wqe_words[ + NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+ + wqe_fragment_index*2]))<<32; + bus_address = (dma_addr_t)u64temp; + pci_unmap_page(nesdev->pcidev, + bus_address, + le16_to_cpu( + wqe_fragment_length[ + wqe_fragment_index]), + PCI_DMA_TODEVICE); + } else + break; + } + } + if (nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]) + dev_kfree_skb( + nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]); + + nesvnic->nic.sq_tail = (++nesvnic->nic.sq_tail) + & (nesvnic->nic.sq_size - 1); + } + spin_lock_irqsave(&nesdev->cqp.lock, flags); /* Destroy NIC QP */ @@ -1894,7 +1995,30 @@ int nes_napi_isr(struct nes_device *nesdev) } } - +static void process_critical_error(struct nes_device *nesdev) +{ + u32 debug_error; + u32 nes_idx_debug_error_masks0 = 0; + u16 error_module = 0; + + debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS); + printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n", + (u16)debug_error); + nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS, + 0x01010000 | (debug_error & 0x0000ffff)); + if (crit_err_count++ > 10) + nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17); + error_module = (u16) (debug_error & 0x1F00) >> 8; + if (++nesdev->nesadapter->crit_error_count[error_module-1] >= + nes_max_critical_error_count) { + printk(KERN_ERR PFX "Masking off critical error for module " + "0x%02X\n", (u16)error_module); + nes_idx_debug_error_masks0 = nes_read_indexed(nesdev, + NES_IDX_DEBUG_ERROR_MASKS0); + nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0, + nes_idx_debug_error_masks0 | (1 << error_module)); + } +} /** * nes_dpc */ @@ -1909,7 +2033,6 @@ void nes_dpc(unsigned long param) u32 timer_stat; u32 temp_int_stat; u32 intf_int_stat; - u32 debug_error; u32 processed_intf_int = 0; u16 processed_timer_int = 0; u16 completion_ints = 0; @@ -1987,14 +2110,7 @@ void nes_dpc(unsigned long param) intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT); intf_int_stat &= nesdev->intf_int_req; if (NES_INTF_INT_CRITERR & intf_int_stat) { - debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS); - printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n", - (u16)debug_error); - nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS, - 0x01010000 | (debug_error & 0x0000ffff)); - /* BUG(); */ - if (crit_err_count++ > 10) - nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17); + process_critical_error(nesdev); } if (NES_INTF_INT_PCIERR & intf_int_stat) { printk(KERN_ERR PFX "PCI Error reported by device!!!\n"); @@ -2258,7 +2374,8 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) spin_unlock_irqrestore(&nesadapter->phy_lock, flags); } /* read the PHY interrupt status register */ - if (nesadapter->OneG_Mode) { + if ((nesadapter->OneG_Mode) && + (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) { do { nes_read_1G_phy_reg(nesdev, 0x1a, nesadapter->phy_index[mac_index], &phy_data); @@ -3077,6 +3194,22 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, nes_cm_disconn(nesqp); break; /* TODO: additional AEs need to be here */ + case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION: + nesqp = *((struct nes_qp **)&context); + spin_lock_irqsave(&nesqp->lock, flags); + nesqp->hw_iwarp_state = iwarp_state; + nesqp->hw_tcp_state = tcp_state; + nesqp->last_aeq = async_event_id; + spin_unlock_irqrestore(&nesqp->lock, flags); + if (nesqp->ibqp.event_handler) { + ibevent.device = nesqp->ibqp.device; + ibevent.element.qp = &nesqp->ibqp; + ibevent.event = IB_EVENT_QP_ACCESS_ERR; + nesqp->ibqp.event_handler(&ibevent, + nesqp->ibqp.qp_context); + } + nes_cm_disconn(nesqp); + break; default: nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n", async_event_id); diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 7b81e0ae0076..610b9d859597 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -156,6 +156,7 @@ enum indexed_regs { NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI = 0x7004, NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO = 0x7008, NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI = 0x700c, + NES_IDX_WQM_CONFIG1 = 0x5004, NES_IDX_CM_CONFIG = 0x5100, NES_IDX_NIC_LOGPORT_TO_PHYPORT = 0x6000, NES_IDX_NIC_PHYPORT_TO_USW = 0x6008, @@ -967,6 +968,7 @@ struct nes_arp_entry { #define DEFAULT_JUMBO_NES_QL_TARGET 40 #define DEFAULT_JUMBO_NES_QL_HIGH 128 #define NES_NIC_CQ_DOWNWARD_TREND 16 +#define NES_PFT_SIZE 48 struct nes_hw_tune_timer { /* u16 cq_count; */ @@ -1079,6 +1081,7 @@ struct nes_adapter { u32 et_rx_max_coalesced_frames_high; u32 et_rate_sample_interval; u32 timer_int_limit; + u32 wqm_quanta; /* Adapter base MAC address */ u32 mac_addr_low; @@ -1094,12 +1097,14 @@ struct nes_adapter { u16 pd_config_base[4]; u16 link_interrupt_count[4]; + u8 crit_error_count[32]; /* the phy index for each port */ u8 phy_index[4]; u8 mac_sw_state[4]; u8 mac_link_down[4]; u8 phy_type[4]; + u8 log_port; /* PCI information */ unsigned int devfn; @@ -1113,6 +1118,7 @@ struct nes_adapter { u8 virtwq; u8 et_use_adaptive_rx_coalesce; u8 adapter_fcn_count; + u8 pft_mcast_map[NES_PFT_SIZE]; }; struct nes_pbl { diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 1b0938c87774..730358637bb6 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -91,6 +91,7 @@ static struct nic_qp_map *nic_qp_mapping_per_function[] = { static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN; static int debug = -1; +static int nics_per_function = 1; /** * nes_netdev_poll @@ -201,7 +202,8 @@ static int nes_netdev_open(struct net_device *netdev) nes_debug(NES_DBG_NETDEV, "i=%d, perfect filter table index= %d, PERF FILTER LOW" " (Addr:%08X) = %08X, HIGH = %08X.\n", i, nesvnic->qp_nic_index[i], - NES_IDX_PERFECT_FILTER_LOW+((nesvnic->perfect_filter_index + i) * 8), + NES_IDX_PERFECT_FILTER_LOW+ + (nesvnic->qp_nic_index[i] * 8), macaddr_low, (u32)macaddr_high | NES_MAC_ADDR_VALID | ((((u32)nesvnic->nic_index) << 16))); @@ -272,14 +274,18 @@ static int nes_netdev_stop(struct net_device *netdev) break; } - if (first_nesvnic->netdev_open == 0) + if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic) && + (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) != + PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) { + nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+ + (0x200*nesdev->mac_index), 0xffffffff); + nes_write_indexed(first_nesvnic->nesdev, + NES_IDX_MAC_INT_MASK+ + (0x200*first_nesvnic->nesdev->mac_index), + ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | + NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); + } else { nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff); - else if ((first_nesvnic != nesvnic) && - (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) != PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) { - nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), 0xffffffff); - nes_write_indexed(first_nesvnic->nesdev, NES_IDX_MAC_INT_MASK + (0x200 * first_nesvnic->nesdev->mac_index), - ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | - NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); } nic_active_mask = ~((u32)(1 << nesvnic->nic_index)); @@ -437,7 +443,7 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev) struct nes_hw_nic_sq_wqe *nic_sqe; struct tcphdr *tcph; /* struct udphdr *udph; */ -#define NES_MAX_TSO_FRAGS 18 +#define NES_MAX_TSO_FRAGS MAX_SKB_FRAGS /* 64K segment plus overflow on each side */ dma_addr_t tso_bus_address[NES_MAX_TSO_FRAGS]; dma_addr_t bus_address; @@ -605,6 +611,8 @@ tso_sq_no_longer_full: wqe_fragment_length[wqe_fragment_index] = 0; set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX, bus_address); + tso_wqe_length += skb_headlen(skb) - + original_first_length; } while (wqe_fragment_index < 5) { wqe_fragment_length[wqe_fragment_index] = @@ -827,6 +835,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; + struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; struct dev_mc_list *multicast_addr; u32 nic_active_bit; u32 nic_active; @@ -836,7 +845,12 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) u8 mc_all_on = 0; u8 mc_index; int mc_nic_index = -1; + u8 pft_entries_preallocated = max(nesadapter->adapter_fcn_count * + nics_per_function, 4); + u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated; + unsigned long flags; + spin_lock_irqsave(&nesadapter->resource_lock, flags); nic_active_bit = 1 << nesvnic->nic_index; if (netdev->flags & IFF_PROMISC) { @@ -847,7 +861,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) nic_active |= nic_active_bit; nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); mc_all_on = 1; - } else if ((netdev->flags & IFF_ALLMULTI) || (netdev->mc_count > NES_MULTICAST_PF_MAX) || + } else if ((netdev->flags & IFF_ALLMULTI) || (nesvnic->nic_index > 3)) { nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); nic_active |= nic_active_bit; @@ -866,17 +880,34 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) } nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n", - netdev->mc_count, (netdev->flags & IFF_PROMISC)?1:0, - (netdev->flags & IFF_ALLMULTI)?1:0); + netdev->mc_count, !!(netdev->flags & IFF_PROMISC), + !!(netdev->flags & IFF_ALLMULTI)); if (!mc_all_on) { multicast_addr = netdev->mc_list; - perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + 0x80; - perfect_filter_register_address += nesvnic->nic_index*0x40; - for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) { - while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0)) + perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + + pft_entries_preallocated * 0x8; + for (mc_index = 0; mc_index < max_pft_entries_avaiable; + mc_index++) { + while (multicast_addr && nesvnic->mcrq_mcast_filter && + ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, + multicast_addr->dmi_addr)) == 0)) { multicast_addr = multicast_addr->next; + } if (mc_nic_index < 0) mc_nic_index = nesvnic->nic_index; + while (nesadapter->pft_mcast_map[mc_index] < 16 && + nesadapter->pft_mcast_map[mc_index] != + nesvnic->nic_index && + mc_index < max_pft_entries_avaiable) { + nes_debug(NES_DBG_NIC_RX, + "mc_index=%d skipping nic_index=%d,\ + used for=%d \n", mc_index, + nesvnic->nic_index, + nesadapter->pft_mcast_map[mc_index]); + mc_index++; + } + if (mc_index >= max_pft_entries_avaiable) + break; if (multicast_addr) { DECLARE_MAC_BUF(mac); nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %s to register 0x%04X nic_idx=%d\n", @@ -897,15 +928,33 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) (u32)macaddr_high | NES_MAC_ADDR_VALID | ((((u32)(1<<mc_nic_index)) << 16))); multicast_addr = multicast_addr->next; + nesadapter->pft_mcast_map[mc_index] = + nesvnic->nic_index; } else { nes_debug(NES_DBG_NIC_RX, "Clearing MC Address at register 0x%04X\n", perfect_filter_register_address+(mc_index * 8)); nes_write_indexed(nesdev, perfect_filter_register_address+4+(mc_index * 8), 0); + nesadapter->pft_mcast_map[mc_index] = 255; } } + /* PFT is not large enough */ + if (multicast_addr && multicast_addr->next) { + nic_active = nes_read_indexed(nesdev, + NES_IDX_NIC_MULTICAST_ALL); + nic_active |= nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, + nic_active); + nic_active = nes_read_indexed(nesdev, + NES_IDX_NIC_UNICAST_ALL); + nic_active &= ~nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, + nic_active); + } } + + spin_unlock_irqrestore(&nesadapter->resource_lock, flags); } @@ -918,6 +967,10 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu) struct nes_device *nesdev = nesvnic->nesdev; int ret = 0; u8 jumbomode = 0; + u32 nic_active; + u32 nic_active_bit; + u32 uc_all_active; + u32 mc_all_active; if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu)) return -EINVAL; @@ -931,8 +984,24 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu) nes_nic_init_timer_defaults(nesdev, jumbomode); if (netif_running(netdev)) { + nic_active_bit = 1 << nesvnic->nic_index; + mc_all_active = nes_read_indexed(nesdev, + NES_IDX_NIC_MULTICAST_ALL) & nic_active_bit; + uc_all_active = nes_read_indexed(nesdev, + NES_IDX_NIC_UNICAST_ALL) & nic_active_bit; + nes_netdev_stop(netdev); nes_netdev_open(netdev); + + nic_active = nes_read_indexed(nesdev, + NES_IDX_NIC_MULTICAST_ALL); + nic_active |= mc_all_active; + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, + nic_active); + + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL); + nic_active |= uc_all_active; + nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); } return ret; @@ -1208,10 +1277,12 @@ static void nes_netdev_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct nes_vnic *nesvnic = netdev_priv(netdev); + struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; strcpy(drvinfo->driver, DRV_NAME); strcpy(drvinfo->bus_info, pci_name(nesvnic->nesdev->pcidev)); - strcpy(drvinfo->fw_version, "TBD"); + sprintf(drvinfo->fw_version, "%u.%u", nesadapter->firmware_version>>16, + nesadapter->firmware_version & 0x000000ff); strcpy(drvinfo->version, DRV_VERSION); drvinfo->n_stats = nes_netdev_get_stats_count(netdev); drvinfo->testinfo_len = 0; @@ -1587,7 +1658,9 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, nesvnic, (unsigned long)netdev->features, nesvnic->nic.qp_id, nesvnic->nic_index, nesvnic->logical_port, nesdev->mac_index); - if (nesvnic->nesdev->nesadapter->port_count == 1) { + if (nesvnic->nesdev->nesadapter->port_count == 1 && + nesvnic->nesdev->nesadapter->adapter_fcn_count == 1) { + nesvnic->qp_nic_index[0] = nesvnic->nic_index; nesvnic->qp_nic_index[1] = nesvnic->nic_index + 1; if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) { @@ -1598,11 +1671,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, nesvnic->qp_nic_index[3] = nesvnic->nic_index + 3; } } else { - if (nesvnic->nesdev->nesadapter->port_count == 2) { - nesvnic->qp_nic_index[0] = nesvnic->nic_index; - nesvnic->qp_nic_index[1] = nesvnic->nic_index + 2; - nesvnic->qp_nic_index[2] = 0xf; - nesvnic->qp_nic_index[3] = 0xf; + if (nesvnic->nesdev->nesadapter->port_count == 2 || + (nesvnic->nesdev->nesadapter->port_count == 1 && + nesvnic->nesdev->nesadapter->adapter_fcn_count == 2)) { + nesvnic->qp_nic_index[0] = nesvnic->nic_index; + nesvnic->qp_nic_index[1] = nesvnic->nic_index + + 2; + nesvnic->qp_nic_index[2] = 0xf; + nesvnic->qp_nic_index[3] = 0xf; } else { nesvnic->qp_nic_index[0] = nesvnic->nic_index; nesvnic->qp_nic_index[1] = 0xf; diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index d79942e84979..932e56fcf774 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1467,7 +1467,6 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, default: nes_debug(NES_DBG_QP, "Invalid QP type: %d\n", init_attr->qp_type); return ERR_PTR(-EINVAL); - break; } /* update the QP table */ @@ -2498,7 +2497,6 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, nes_debug(NES_DBG_MR, "Leaving, ibmr=%p", ibmr); return ibmr; - break; case IWNES_MEMREG_TYPE_QP: case IWNES_MEMREG_TYPE_CQ: nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); @@ -2572,7 +2570,6 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, nesmr->ibmr.lkey = -1; nesmr->mode = req.reg_type; return &nesmr->ibmr; - break; } return ERR_PTR(-ENOSYS); diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 05eb41b8ab63..68ba5c3482e4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -268,10 +268,9 @@ struct ipoib_lro { }; /* - * Device private locking: tx_lock protects members used in TX fast - * path (and we use LLTX so upper layers don't do extra locking). - * lock protects everything else. lock nests inside of tx_lock (ie - * tx_lock must be acquired first if needed). + * Device private locking: network stack tx_lock protects members used + * in TX fast path, lock protects everything else. lock nests inside + * of tx_lock (ie tx_lock must be acquired first if needed). */ struct ipoib_dev_priv { spinlock_t lock; @@ -320,7 +319,6 @@ struct ipoib_dev_priv { struct ipoib_rx_buf *rx_ring; - spinlock_t tx_lock; struct ipoib_tx_buf *tx_ring; unsigned tx_head; unsigned tx_tail; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 341ffedafed6..7b14c2c39500 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -786,7 +786,8 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) dev_kfree_skb_any(tx_req->skb); - spin_lock_irqsave(&priv->tx_lock, flags); + netif_tx_lock(dev); + ++tx->tx_tail; if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) && netif_queue_stopped(dev) && @@ -801,7 +802,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) "(status=%d, wrid=%d vend_err %x)\n", wc->status, wr_id, wc->vendor_err); - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); neigh = tx->neigh; if (neigh) { @@ -821,10 +822,10 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags); - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); } - spin_unlock_irqrestore(&priv->tx_lock, flags); + netif_tx_unlock(dev); } int ipoib_cm_dev_open(struct net_device *dev) @@ -1149,7 +1150,6 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) { struct ipoib_dev_priv *priv = netdev_priv(p->dev); struct ipoib_cm_tx_buf *tx_req; - unsigned long flags; unsigned long begin; ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n", @@ -1180,12 +1180,12 @@ timeout: DMA_TO_DEVICE); dev_kfree_skb_any(tx_req->skb); ++p->tx_tail; - spin_lock_irqsave(&priv->tx_lock, flags); + netif_tx_lock_bh(p->dev); if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) && netif_queue_stopped(p->dev) && test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) netif_wake_queue(p->dev); - spin_unlock_irqrestore(&priv->tx_lock, flags); + netif_tx_unlock_bh(p->dev); } if (p->qp) @@ -1202,6 +1202,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, struct ipoib_dev_priv *priv = netdev_priv(tx->dev); struct net_device *dev = priv->dev; struct ipoib_neigh *neigh; + unsigned long flags; int ret; switch (event->event) { @@ -1220,8 +1221,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, case IB_CM_REJ_RECEIVED: case IB_CM_TIMEWAIT_EXIT: ipoib_dbg(priv, "CM error %d.\n", event->event); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); neigh = tx->neigh; if (neigh) { @@ -1239,8 +1240,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, queue_work(ipoib_workqueue, &priv->cm.reap_task); } - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); break; default: break; @@ -1294,19 +1295,24 @@ static void ipoib_cm_tx_start(struct work_struct *work) struct ib_sa_path_rec pathrec; u32 qpn; - spin_lock_irqsave(&priv->tx_lock, flags); - spin_lock(&priv->lock); + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); + while (!list_empty(&priv->cm.start_list)) { p = list_entry(priv->cm.start_list.next, typeof(*p), list); list_del_init(&p->list); neigh = p->neigh; qpn = IPOIB_QPN(neigh->neighbour->ha); memcpy(&pathrec, &p->path->pathrec, sizeof pathrec); - spin_unlock(&priv->lock); - spin_unlock_irqrestore(&priv->tx_lock, flags); + + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); + ret = ipoib_cm_tx_init(p, qpn, &pathrec); - spin_lock_irqsave(&priv->tx_lock, flags); - spin_lock(&priv->lock); + + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); + if (ret) { neigh = p->neigh; if (neigh) { @@ -1320,44 +1326,52 @@ static void ipoib_cm_tx_start(struct work_struct *work) kfree(p); } } - spin_unlock(&priv->lock); - spin_unlock_irqrestore(&priv->tx_lock, flags); + + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); } static void ipoib_cm_tx_reap(struct work_struct *work) { struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, cm.reap_task); + struct net_device *dev = priv->dev; struct ipoib_cm_tx *p; + unsigned long flags; + + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); while (!list_empty(&priv->cm.reap_list)) { p = list_entry(priv->cm.reap_list.next, typeof(*p), list); list_del(&p->list); - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); ipoib_cm_tx_destroy(p); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); } - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); } static void ipoib_cm_skb_reap(struct work_struct *work) { struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, cm.skb_task); + struct net_device *dev = priv->dev; struct sk_buff *skb; - + unsigned long flags; unsigned mtu = priv->mcast_mtu; - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); + while ((skb = skb_dequeue(&priv->cm.skb_queue))) { - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); + if (skb->protocol == htons(ETH_P_IP)) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -1365,11 +1379,13 @@ static void ipoib_cm_skb_reap(struct work_struct *work) icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev); #endif dev_kfree_skb_any(skb); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); } - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); } void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb, diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 66cafa20c246..0e748aeeae99 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -468,21 +468,22 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) static void drain_tx_cq(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); - unsigned long flags; - spin_lock_irqsave(&priv->tx_lock, flags); + netif_tx_lock(dev); while (poll_tx(priv)) ; /* nothing */ if (netif_queue_stopped(dev)) mod_timer(&priv->poll_timer, jiffies + 1); - spin_unlock_irqrestore(&priv->tx_lock, flags); + netif_tx_unlock(dev); } void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr) { - drain_tx_cq((struct net_device *)dev_ptr); + struct ipoib_dev_priv *priv = netdev_priv(dev_ptr); + + mod_timer(&priv->poll_timer, jiffies); } static inline int post_send(struct ipoib_dev_priv *priv, @@ -614,17 +615,20 @@ static void __ipoib_reap_ah(struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_ah *ah, *tah; LIST_HEAD(remove_list); + unsigned long flags; + + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list) if ((int) priv->tx_tail - (int) ah->last_send >= 0) { list_del(&ah->list); ib_destroy_ah(ah->ah); kfree(ah); } - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); } void ipoib_reap_ah(struct work_struct *work) @@ -761,6 +765,14 @@ void ipoib_drain_cq(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); int i, n; + + /* + * We call completion handling routines that expect to be + * called from the BH-disabled NAPI poll context, so disable + * BHs here too. + */ + local_bh_disable(); + do { n = ib_poll_cq(priv->recv_cq, IPOIB_NUM_WC, priv->ibwc); for (i = 0; i < n; ++i) { @@ -784,6 +796,8 @@ void ipoib_drain_cq(struct net_device *dev) while (poll_tx(priv)) ; /* nothing */ + + local_bh_enable(); } int ipoib_ib_dev_stop(struct net_device *dev, int flush) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index e9ca3cb57d52..c0ee514396df 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -373,9 +373,10 @@ void ipoib_flush_paths(struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path, *tp; LIST_HEAD(remove_list); + unsigned long flags; - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); list_splice_init(&priv->path_list, &remove_list); @@ -385,15 +386,16 @@ void ipoib_flush_paths(struct net_device *dev) list_for_each_entry_safe(path, tp, &remove_list, list) { if (path->query) ib_sa_cancel_query(path->query_id, path->query); - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); wait_for_completion(&path->done); path_free(dev, path); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + netif_tx_lock_bh(dev); + spin_lock_irqsave(&priv->lock, flags); } - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); } static void path_rec_completion(int status, @@ -555,6 +557,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path; struct ipoib_neigh *neigh; + unsigned long flags; neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev); if (!neigh) { @@ -563,11 +566,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) return; } - /* - * We can only be called from ipoib_start_xmit, so we're - * inside tx_lock -- no need to save/restore flags. - */ - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); path = __path_find(dev, skb->dst->neighbour->ha + 4); if (!path) { @@ -614,7 +613,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) __skb_queue_tail(&neigh->queue, skb); } - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return; err_list: @@ -626,7 +625,7 @@ err_drop: ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); } static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) @@ -650,12 +649,9 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path; + unsigned long flags; - /* - * We can only be called from ipoib_start_xmit, so we're - * inside tx_lock -- no need to save/restore flags. - */ - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); path = __path_find(dev, phdr->hwaddr + 4); if (!path || !path->valid) { @@ -667,7 +663,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, __skb_queue_tail(&path->queue, skb); if (path_rec_start(dev, path)) { - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); path_free(dev, path); return; } else @@ -677,7 +673,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, dev_kfree_skb_any(skb); } - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -696,7 +692,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, dev_kfree_skb_any(skb); } - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); } static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -705,13 +701,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) struct ipoib_neigh *neigh; unsigned long flags; - if (unlikely(!spin_trylock_irqsave(&priv->tx_lock, flags))) - return NETDEV_TX_LOCKED; - if (likely(skb->dst && skb->dst->neighbour)) { if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) { ipoib_path_lookup(skb, dev); - goto out; + return NETDEV_TX_OK; } neigh = *to_ipoib_neigh(skb->dst->neighbour); @@ -721,7 +714,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->dst->neighbour->ha + 4, sizeof(union ib_gid))) || (neigh->dev != dev))) { - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); /* * It's safe to call ipoib_put_ah() inside * priv->lock here, because we know that @@ -732,25 +725,25 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ipoib_put_ah(neigh->ah); list_del(&neigh->list); ipoib_neigh_free(dev, neigh); - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); ipoib_path_lookup(skb, dev); - goto out; + return NETDEV_TX_OK; } if (ipoib_cm_get(neigh)) { if (ipoib_cm_up(neigh)) { ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); - goto out; + return NETDEV_TX_OK; } } else if (neigh->ah) { ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha)); - goto out; + return NETDEV_TX_OK; } if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); __skb_queue_tail(&neigh->queue, skb); - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); } else { ++dev->stats.tx_dropped; dev_kfree_skb_any(skb); @@ -779,16 +772,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) IPOIB_GID_RAW_ARG(phdr->hwaddr + 4)); dev_kfree_skb_any(skb); ++dev->stats.tx_dropped; - goto out; + return NETDEV_TX_OK; } unicast_arp_send(skb, dev, phdr); } } -out: - spin_unlock_irqrestore(&priv->tx_lock, flags); - return NETDEV_TX_OK; } @@ -1052,7 +1042,6 @@ static void ipoib_setup(struct net_device *dev) dev->type = ARPHRD_INFINIBAND; dev->tx_queue_len = ipoib_sendq_size * 2; dev->features = (NETIF_F_VLAN_CHALLENGED | - NETIF_F_LLTX | NETIF_F_HIGHDMA); memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN); @@ -1064,7 +1053,6 @@ static void ipoib_setup(struct net_device *dev) ipoib_lro_setup(priv); spin_lock_init(&priv->lock); - spin_lock_init(&priv->tx_lock); mutex_init(&priv->vlan_mutex); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index aae28620a6e5..d9d1223c3fd5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -69,14 +69,13 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) struct net_device *dev = mcast->dev; struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_neigh *neigh, *tmp; - unsigned long flags; int tx_dropped = 0; ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group " IPOIB_GID_FMT "\n", IPOIB_GID_ARG(mcast->mcmember.mgid)); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irq(&priv->lock); list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { /* @@ -90,7 +89,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) ipoib_neigh_free(dev, neigh); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irq(&priv->lock); if (mcast->ah) ipoib_put_ah(mcast->ah); @@ -100,9 +99,9 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); } - spin_lock_irqsave(&priv->tx_lock, flags); + netif_tx_lock_bh(dev); dev->stats.tx_dropped += tx_dropped; - spin_unlock_irqrestore(&priv->tx_lock, flags); + netif_tx_unlock_bh(dev); kfree(mcast); } @@ -259,10 +258,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, } /* actually send any queued packets */ - spin_lock_irq(&priv->tx_lock); + netif_tx_lock_bh(dev); while (!skb_queue_empty(&mcast->pkt_queue)) { struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); - spin_unlock_irq(&priv->tx_lock); + netif_tx_unlock_bh(dev); skb->dev = dev; @@ -273,9 +272,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, if (dev_queue_xmit(skb)) ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n"); - spin_lock_irq(&priv->tx_lock); + netif_tx_lock_bh(dev); } - spin_unlock_irq(&priv->tx_lock); + netif_tx_unlock_bh(dev); return 0; } @@ -286,7 +285,6 @@ ipoib_mcast_sendonly_join_complete(int status, { struct ipoib_mcast *mcast = multicast->context; struct net_device *dev = mcast->dev; - struct ipoib_dev_priv *priv = netdev_priv(dev); /* We trap for port events ourselves. */ if (status == -ENETRESET) @@ -302,12 +300,12 @@ ipoib_mcast_sendonly_join_complete(int status, IPOIB_GID_ARG(mcast->mcmember.mgid), status); /* Flush out any queued packets */ - spin_lock_irq(&priv->tx_lock); + netif_tx_lock_bh(dev); while (!skb_queue_empty(&mcast->pkt_queue)) { ++dev->stats.tx_dropped; dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); } - spin_unlock_irq(&priv->tx_lock); + netif_tx_unlock_bh(dev); /* Clear the busy flag so we try again */ status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, @@ -662,12 +660,9 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_mcast *mcast; + unsigned long flags; - /* - * We can only be called from ipoib_start_xmit, so we're - * inside tx_lock -- no need to save/restore flags. - */ - spin_lock(&priv->lock); + spin_lock_irqsave(&priv->lock, flags); if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) || !priv->broadcast || @@ -738,7 +733,7 @@ out: } unlock: - spin_unlock(&priv->lock); + spin_unlock_irqrestore(&priv->lock, flags); } void ipoib_mcast_dev_flush(struct net_device *dev) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 13956437bc81..682ef9e6acd3 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -333,7 +333,6 @@ static void crypt_convert_init(struct crypt_config *cc, ctx->idx_out = bio_out ? bio_out->bi_idx : 0; ctx->sector = sector + cc->iv_offset; init_completion(&ctx->restart); - atomic_set(&ctx->pending, 1); } static int crypt_convert_block(struct crypt_config *cc, @@ -408,6 +407,8 @@ static int crypt_convert(struct crypt_config *cc, { int r; + atomic_set(&ctx->pending, 1); + while(ctx->idx_in < ctx->bio_in->bi_vcnt && ctx->idx_out < ctx->bio_out->bi_vcnt) { @@ -456,9 +457,11 @@ static void dm_crypt_bio_destructor(struct bio *bio) /* * Generate a new unfragmented bio with the given size * This should never violate the device limitations - * May return a smaller bio when running out of pages + * May return a smaller bio when running out of pages, indicated by + * *out_of_pages set to 1. */ -static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) +static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size, + unsigned *out_of_pages) { struct crypt_config *cc = io->target->private; struct bio *clone; @@ -472,11 +475,14 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) return NULL; clone_init(io, clone); + *out_of_pages = 0; for (i = 0; i < nr_iovecs; i++) { page = mempool_alloc(cc->page_pool, gfp_mask); - if (!page) + if (!page) { + *out_of_pages = 1; break; + } /* * if additional pages cannot be allocated without waiting, @@ -517,6 +523,27 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) } } +static struct dm_crypt_io *crypt_io_alloc(struct dm_target *ti, + struct bio *bio, sector_t sector) +{ + struct crypt_config *cc = ti->private; + struct dm_crypt_io *io; + + io = mempool_alloc(cc->io_pool, GFP_NOIO); + io->target = ti; + io->base_bio = bio; + io->sector = sector; + io->error = 0; + atomic_set(&io->pending, 0); + + return io; +} + +static void crypt_inc_pending(struct dm_crypt_io *io) +{ + atomic_inc(&io->pending); +} + /* * One of the bios was finished. Check for completion of * the whole request and correctly clean up the buffer. @@ -591,7 +618,7 @@ static void kcryptd_io_read(struct dm_crypt_io *io) struct bio *base_bio = io->base_bio; struct bio *clone; - atomic_inc(&io->pending); + crypt_inc_pending(io); /* * The block layer might modify the bvec array, so always @@ -653,6 +680,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, crypt_free_buffer_pages(cc, clone); bio_put(clone); io->error = -EIO; + crypt_dec_pending(io); return; } @@ -664,28 +692,34 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, if (async) kcryptd_queue_io(io); - else { - atomic_inc(&io->pending); + else generic_make_request(clone); - } } -static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) +static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) { struct crypt_config *cc = io->target->private; struct bio *clone; + int crypt_finished; + unsigned out_of_pages = 0; unsigned remaining = io->base_bio->bi_size; int r; /* + * Prevent io from disappearing until this function completes. + */ + crypt_inc_pending(io); + crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector); + + /* * The allocated buffers can be smaller than the whole bio, * so repeat the whole process until all the data can be handled. */ while (remaining) { - clone = crypt_alloc_buffer(io, remaining); + clone = crypt_alloc_buffer(io, remaining, &out_of_pages); if (unlikely(!clone)) { io->error = -ENOMEM; - return; + break; } io->ctx.bio_out = clone; @@ -693,37 +727,32 @@ static void kcryptd_crypt_write_convert_loop(struct dm_crypt_io *io) remaining -= clone->bi_size; + crypt_inc_pending(io); r = crypt_convert(cc, &io->ctx); + crypt_finished = atomic_dec_and_test(&io->ctx.pending); - if (atomic_dec_and_test(&io->ctx.pending)) { - /* processed, no running async crypto */ + /* Encryption was already finished, submit io now */ + if (crypt_finished) { kcryptd_crypt_write_io_submit(io, r, 0); - if (unlikely(r < 0)) - return; - } else - atomic_inc(&io->pending); - /* out of memory -> run queues */ - if (unlikely(remaining)) { - /* wait for async crypto then reinitialize pending */ - wait_event(cc->writeq, !atomic_read(&io->ctx.pending)); - atomic_set(&io->ctx.pending, 1); - congestion_wait(WRITE, HZ/100); + /* + * If there was an error, do not try next fragments. + * For async, error is processed in async handler. + */ + if (unlikely(r < 0)) + break; } - } -} -static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) -{ - struct crypt_config *cc = io->target->private; - - /* - * Prevent io from disappearing until this function completes. - */ - atomic_inc(&io->pending); + /* + * Out of memory -> run queues + * But don't wait if split was due to the io size restriction + */ + if (unlikely(out_of_pages)) + congestion_wait(WRITE, HZ/100); - crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, io->sector); - kcryptd_crypt_write_convert_loop(io); + if (unlikely(remaining)) + wait_event(cc->writeq, !atomic_read(&io->ctx.pending)); + } crypt_dec_pending(io); } @@ -741,7 +770,7 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) struct crypt_config *cc = io->target->private; int r = 0; - atomic_inc(&io->pending); + crypt_inc_pending(io); crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio, io->sector); @@ -1108,15 +1137,9 @@ static void crypt_dtr(struct dm_target *ti) static int crypt_map(struct dm_target *ti, struct bio *bio, union map_info *map_context) { - struct crypt_config *cc = ti->private; struct dm_crypt_io *io; - io = mempool_alloc(cc->io_pool, GFP_NOIO); - io->target = ti; - io->base_bio = bio; - io->sector = bio->bi_sector - ti->begin; - io->error = 0; - atomic_set(&io->pending, 0); + io = crypt_io_alloc(ti, bio, bio->bi_sector - ti->begin); if (bio_data_dir(io->base_bio) == READ) kcryptd_queue_io(io); diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 41f408068a7c..769ab677f8e0 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -108,12 +108,12 @@ struct pstore { * Used to keep track of which metadata area the data in * 'chunk' refers to. */ - uint32_t current_area; + chunk_t current_area; /* * The next free chunk for an exception. */ - uint32_t next_free; + chunk_t next_free; /* * The index of next free exception in the current @@ -175,7 +175,7 @@ static void do_metadata(struct work_struct *work) /* * Read or write a chunk aligned and sized block of data from a device. */ -static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata) +static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata) { struct dm_io_region where = { .bdev = ps->snap->cow->bdev, @@ -209,16 +209,23 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata) } /* + * Convert a metadata area index to a chunk index. + */ +static chunk_t area_location(struct pstore *ps, chunk_t area) +{ + return 1 + ((ps->exceptions_per_area + 1) * area); +} + +/* * Read or write a metadata area. Remembering to skip the first * chunk which holds the header. */ -static int area_io(struct pstore *ps, uint32_t area, int rw) +static int area_io(struct pstore *ps, chunk_t area, int rw) { int r; - uint32_t chunk; + chunk_t chunk; - /* convert a metadata area index to a chunk index */ - chunk = 1 + ((ps->exceptions_per_area + 1) * area); + chunk = area_location(ps, area); r = chunk_io(ps, chunk, rw, 0); if (r) @@ -228,7 +235,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw) return 0; } -static int zero_area(struct pstore *ps, uint32_t area) +static int zero_area(struct pstore *ps, chunk_t area) { memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); return area_io(ps, area, WRITE); @@ -404,7 +411,7 @@ static int insert_exceptions(struct pstore *ps, int *full) static int read_exceptions(struct pstore *ps) { - uint32_t area; + chunk_t area; int r, full = 1; /* @@ -517,6 +524,7 @@ static int persistent_prepare(struct exception_store *store, { struct pstore *ps = get_info(store); uint32_t stride; + chunk_t next_free; sector_t size = get_dev_size(store->snap->cow->bdev); /* Is there enough room ? */ @@ -530,7 +538,8 @@ static int persistent_prepare(struct exception_store *store, * into account the location of the metadata chunks. */ stride = (ps->exceptions_per_area + 1); - if ((++ps->next_free % stride) == 1) + next_free = ++ps->next_free; + if (sector_div(next_free, stride) == 1) ps->next_free++; atomic_inc(&ps->pending_count); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index b262c0042de3..dca401dc70a0 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -426,7 +426,7 @@ static int list_devices(struct dm_ioctl *param, size_t param_size) old_nl->next = (uint32_t) ((void *) nl - (void *) old_nl); disk = dm_disk(hc->md); - nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); + nl->dev = huge_encode_dev(disk_devt(disk)); nl->next = 0; strcpy(nl->name, hc->name); @@ -539,7 +539,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) if (dm_suspended(md)) param->flags |= DM_SUSPEND_FLAG; - param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); + param->dev = huge_encode_dev(disk_devt(disk)); /* * Yes, this will be out of date by the time it gets back @@ -548,7 +548,7 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) */ param->open_count = dm_open_count(md); - if (disk->policy) + if (get_disk_ro(disk)) param->flags |= DM_READONLY_FLAG; param->event_nr = dm_get_event_nr(md); @@ -1131,7 +1131,7 @@ static void retrieve_deps(struct dm_table *table, unsigned int count = 0; struct list_head *tmp; size_t len, needed; - struct dm_dev *dd; + struct dm_dev_internal *dd; struct dm_target_deps *deps; deps = get_result_buffer(param, param_size, &len); @@ -1157,7 +1157,7 @@ static void retrieve_deps(struct dm_table *table, deps->count = count; count = 0; list_for_each_entry (dd, dm_table_get_devices(table), list) - deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev); + deps->dev[count++] = huge_encode_dev(dd->dm_dev.bdev->bd_dev); param->data_size = param->data_start + needed; } diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index c2fcf28b4c70..103304c1e3b0 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -30,9 +30,11 @@ struct pgpath { struct list_head list; struct priority_group *pg; /* Owning PG */ + unsigned is_active; /* Path status */ unsigned fail_count; /* Cumulative failure count */ struct dm_path path; + struct work_struct deactivate_path; }; #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path) @@ -112,6 +114,7 @@ static struct workqueue_struct *kmultipathd, *kmpath_handlerd; static void process_queued_ios(struct work_struct *work); static void trigger_event(struct work_struct *work); static void activate_path(struct work_struct *work); +static void deactivate_path(struct work_struct *work); /*----------------------------------------------- @@ -122,8 +125,10 @@ static struct pgpath *alloc_pgpath(void) { struct pgpath *pgpath = kzalloc(sizeof(*pgpath), GFP_KERNEL); - if (pgpath) - pgpath->path.is_active = 1; + if (pgpath) { + pgpath->is_active = 1; + INIT_WORK(&pgpath->deactivate_path, deactivate_path); + } return pgpath; } @@ -133,6 +138,14 @@ static void free_pgpath(struct pgpath *pgpath) kfree(pgpath); } +static void deactivate_path(struct work_struct *work) +{ + struct pgpath *pgpath = + container_of(work, struct pgpath, deactivate_path); + + blk_abort_queue(pgpath->path.dev->bdev->bd_disk->queue); +} + static struct priority_group *alloc_priority_group(void) { struct priority_group *pg; @@ -563,12 +576,12 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, /* we need at least a path arg */ if (as->argc < 1) { ti->error = "no device given"; - return NULL; + return ERR_PTR(-EINVAL); } p = alloc_pgpath(); if (!p) - return NULL; + return ERR_PTR(-ENOMEM); r = dm_get_device(ti, shift(as), ti->begin, ti->len, dm_table_get_mode(ti->table), &p->path.dev); @@ -596,7 +609,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, bad: free_pgpath(p); - return NULL; + return ERR_PTR(r); } static struct priority_group *parse_priority_group(struct arg_set *as, @@ -614,14 +627,14 @@ static struct priority_group *parse_priority_group(struct arg_set *as, if (as->argc < 2) { as->argc = 0; - ti->error = "not enough priority group aruments"; - return NULL; + ti->error = "not enough priority group arguments"; + return ERR_PTR(-EINVAL); } pg = alloc_priority_group(); if (!pg) { ti->error = "couldn't allocate priority group"; - return NULL; + return ERR_PTR(-ENOMEM); } pg->m = m; @@ -654,8 +667,10 @@ static struct priority_group *parse_priority_group(struct arg_set *as, path_args.argv = as->argv; pgpath = parse_path(&path_args, &pg->ps, ti); - if (!pgpath) + if (IS_ERR(pgpath)) { + r = PTR_ERR(pgpath); goto bad; + } pgpath->pg = pg; list_add_tail(&pgpath->list, &pg->pgpaths); @@ -666,7 +681,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as, bad: free_priority_group(pg, ti); - return NULL; + return ERR_PTR(r); } static int parse_hw_handler(struct arg_set *as, struct multipath *m) @@ -785,8 +800,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, struct priority_group *pg; pg = parse_priority_group(&as, m); - if (!pg) { - r = -EINVAL; + if (IS_ERR(pg)) { + r = PTR_ERR(pg); goto bad; } @@ -852,13 +867,13 @@ static int fail_path(struct pgpath *pgpath) spin_lock_irqsave(&m->lock, flags); - if (!pgpath->path.is_active) + if (!pgpath->is_active) goto out; DMWARN("Failing path %s.", pgpath->path.dev->name); pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path); - pgpath->path.is_active = 0; + pgpath->is_active = 0; pgpath->fail_count++; m->nr_valid_paths--; @@ -870,6 +885,7 @@ static int fail_path(struct pgpath *pgpath) pgpath->path.dev->name, m->nr_valid_paths); queue_work(kmultipathd, &m->trigger_event); + queue_work(kmultipathd, &pgpath->deactivate_path); out: spin_unlock_irqrestore(&m->lock, flags); @@ -888,7 +904,7 @@ static int reinstate_path(struct pgpath *pgpath) spin_lock_irqsave(&m->lock, flags); - if (pgpath->path.is_active) + if (pgpath->is_active) goto out; if (!pgpath->pg->ps.type->reinstate_path) { @@ -902,7 +918,7 @@ static int reinstate_path(struct pgpath *pgpath) if (r) goto out; - pgpath->path.is_active = 1; + pgpath->is_active = 1; m->current_pgpath = NULL; if (!m->nr_valid_paths++ && m->queue_size) @@ -1290,7 +1306,7 @@ static int multipath_status(struct dm_target *ti, status_type_t type, list_for_each_entry(p, &pg->pgpaths, list) { DMEMIT("%s %s %u ", p->path.dev->name, - p->path.is_active ? "A" : "F", + p->is_active ? "A" : "F", p->fail_count); if (pg->ps.type->status) sz += pg->ps.type->status(&pg->ps, diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h index c198b856a452..e230f7196259 100644 --- a/drivers/md/dm-mpath.h +++ b/drivers/md/dm-mpath.h @@ -13,8 +13,6 @@ struct dm_dev; struct dm_path { struct dm_dev *dev; /* Read-only */ - unsigned is_active; /* Read-only */ - void *pscontext; /* For path-selector use */ }; diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ff05fe893083..29913e42c4ab 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -842,7 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg) } /* hand to kcopyd */ - set_bit(DM_KCOPYD_IGNORE_ERROR, &flags); + if (!errors_handled(ms)) + set_bit(DM_KCOPYD_IGNORE_ERROR, &flags); + r = dm_kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags, recovery_complete, reg); diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 4de90ab3968b..b745d8ac625b 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -284,8 +284,8 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, memset(major_minor, 0, sizeof(major_minor)); sprintf(major_minor, "%d:%d", - bio->bi_bdev->bd_disk->major, - bio->bi_bdev->bd_disk->first_minor); + MAJOR(disk_devt(bio->bi_bdev->bd_disk)), + MINOR(disk_devt(bio->bi_bdev->bd_disk))); /* * Test to see which stripe drive triggered the event diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 61f441409234..a740a6950f59 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -250,7 +250,8 @@ static void free_devices(struct list_head *devices) struct list_head *tmp, *next; list_for_each_safe(tmp, next, devices) { - struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); + struct dm_dev_internal *dd = + list_entry(tmp, struct dm_dev_internal, list); kfree(dd); } } @@ -327,12 +328,12 @@ static int lookup_device(const char *path, dev_t *dev) /* * See if we've already got a device in the list. */ -static struct dm_dev *find_device(struct list_head *l, dev_t dev) +static struct dm_dev_internal *find_device(struct list_head *l, dev_t dev) { - struct dm_dev *dd; + struct dm_dev_internal *dd; list_for_each_entry (dd, l, list) - if (dd->bdev->bd_dev == dev) + if (dd->dm_dev.bdev->bd_dev == dev) return dd; return NULL; @@ -341,45 +342,47 @@ static struct dm_dev *find_device(struct list_head *l, dev_t dev) /* * Open a device so we can use it as a map destination. */ -static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md) +static int open_dev(struct dm_dev_internal *d, dev_t dev, + struct mapped_device *md) { static char *_claim_ptr = "I belong to device-mapper"; struct block_device *bdev; int r; - BUG_ON(d->bdev); + BUG_ON(d->dm_dev.bdev); - bdev = open_by_devnum(dev, d->mode); + bdev = open_by_devnum(dev, d->dm_dev.mode); if (IS_ERR(bdev)) return PTR_ERR(bdev); r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md)); if (r) blkdev_put(bdev); else - d->bdev = bdev; + d->dm_dev.bdev = bdev; return r; } /* * Close a device that we've been using. */ -static void close_dev(struct dm_dev *d, struct mapped_device *md) +static void close_dev(struct dm_dev_internal *d, struct mapped_device *md) { - if (!d->bdev) + if (!d->dm_dev.bdev) return; - bd_release_from_disk(d->bdev, dm_disk(md)); - blkdev_put(d->bdev); - d->bdev = NULL; + bd_release_from_disk(d->dm_dev.bdev, dm_disk(md)); + blkdev_put(d->dm_dev.bdev); + d->dm_dev.bdev = NULL; } /* * If possible, this checks an area of a destination device is valid. */ -static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) +static int check_device_area(struct dm_dev_internal *dd, sector_t start, + sector_t len) { - sector_t dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT; + sector_t dev_size = dd->dm_dev.bdev->bd_inode->i_size >> SECTOR_SHIFT; if (!dev_size) return 1; @@ -392,16 +395,17 @@ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) * careful to leave things as they were if we fail to reopen the * device. */ -static int upgrade_mode(struct dm_dev *dd, int new_mode, struct mapped_device *md) +static int upgrade_mode(struct dm_dev_internal *dd, int new_mode, + struct mapped_device *md) { int r; - struct dm_dev dd_copy; - dev_t dev = dd->bdev->bd_dev; + struct dm_dev_internal dd_copy; + dev_t dev = dd->dm_dev.bdev->bd_dev; dd_copy = *dd; - dd->mode |= new_mode; - dd->bdev = NULL; + dd->dm_dev.mode |= new_mode; + dd->dm_dev.bdev = NULL; r = open_dev(dd, dev, md); if (!r) close_dev(&dd_copy, md); @@ -421,7 +425,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, { int r; dev_t uninitialized_var(dev); - struct dm_dev *dd; + struct dm_dev_internal *dd; unsigned int major, minor; BUG_ON(!t); @@ -443,20 +447,20 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, if (!dd) return -ENOMEM; - dd->mode = mode; - dd->bdev = NULL; + dd->dm_dev.mode = mode; + dd->dm_dev.bdev = NULL; if ((r = open_dev(dd, dev, t->md))) { kfree(dd); return r; } - format_dev_t(dd->name, dev); + format_dev_t(dd->dm_dev.name, dev); atomic_set(&dd->count, 0); list_add(&dd->list, &t->devices); - } else if (dd->mode != (mode | dd->mode)) { + } else if (dd->dm_dev.mode != (mode | dd->dm_dev.mode)) { r = upgrade_mode(dd, mode, t->md); if (r) return r; @@ -465,11 +469,11 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, if (!check_device_area(dd, start, len)) { DMWARN("device %s too small for target", path); - dm_put_device(ti, dd); + dm_put_device(ti, &dd->dm_dev); return -EINVAL; } - *result = dd; + *result = &dd->dm_dev; return 0; } @@ -478,6 +482,13 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) { struct request_queue *q = bdev_get_queue(bdev); struct io_restrictions *rs = &ti->limits; + char b[BDEVNAME_SIZE]; + + if (unlikely(!q)) { + DMWARN("%s: Cannot set limits for nonexistent device %s", + dm_device_name(ti->table->md), bdevname(bdev, b)); + return; + } /* * Combine the device limits low. @@ -540,8 +551,11 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, /* * Decrement a devices use count and remove it if necessary. */ -void dm_put_device(struct dm_target *ti, struct dm_dev *dd) +void dm_put_device(struct dm_target *ti, struct dm_dev *d) { + struct dm_dev_internal *dd = container_of(d, struct dm_dev_internal, + dm_dev); + if (atomic_dec_and_test(&dd->count)) { close_dev(dd, ti->table->md); list_del(&dd->list); @@ -937,13 +951,20 @@ int dm_table_resume_targets(struct dm_table *t) int dm_table_any_congested(struct dm_table *t, int bdi_bits) { - struct dm_dev *dd; + struct dm_dev_internal *dd; struct list_head *devices = dm_table_get_devices(t); int r = 0; list_for_each_entry(dd, devices, list) { - struct request_queue *q = bdev_get_queue(dd->bdev); - r |= bdi_congested(&q->backing_dev_info, bdi_bits); + struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev); + char b[BDEVNAME_SIZE]; + + if (likely(q)) + r |= bdi_congested(&q->backing_dev_info, bdi_bits); + else + DMWARN_LIMIT("%s: any_congested: nonexistent device %s", + dm_device_name(t->md), + bdevname(dd->dm_dev.bdev, b)); } return r; @@ -951,13 +972,19 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits) void dm_table_unplug_all(struct dm_table *t) { - struct dm_dev *dd; + struct dm_dev_internal *dd; struct list_head *devices = dm_table_get_devices(t); list_for_each_entry(dd, devices, list) { - struct request_queue *q = bdev_get_queue(dd->bdev); - - blk_unplug(q); + struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev); + char b[BDEVNAME_SIZE]; + + if (likely(q)) + blk_unplug(q); + else + DMWARN_LIMIT("%s: Cannot unplug nonexistent device %s", + dm_device_name(t->md), + bdevname(dd->dm_dev.bdev, b)); } } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index ace998ce59f6..327de03a5bdf 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -377,13 +377,14 @@ static void free_tio(struct mapped_device *md, struct dm_target_io *tio) static void start_io_acct(struct dm_io *io) { struct mapped_device *md = io->md; + int cpu; io->start_time = jiffies; - preempt_disable(); - disk_round_stats(dm_disk(md)); - preempt_enable(); - dm_disk(md)->in_flight = atomic_inc_return(&md->pending); + cpu = part_stat_lock(); + part_round_stats(cpu, &dm_disk(md)->part0); + part_stat_unlock(); + dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending); } static int end_io_acct(struct dm_io *io) @@ -391,15 +392,16 @@ static int end_io_acct(struct dm_io *io) struct mapped_device *md = io->md; struct bio *bio = io->bio; unsigned long duration = jiffies - io->start_time; - int pending; + int pending, cpu; int rw = bio_data_dir(bio); - preempt_disable(); - disk_round_stats(dm_disk(md)); - preempt_enable(); - dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + cpu = part_stat_lock(); + part_round_stats(cpu, &dm_disk(md)->part0); + part_stat_add(cpu, &dm_disk(md)->part0, ticks[rw], duration); + part_stat_unlock(); - disk_stat_add(dm_disk(md), ticks[rw], duration); + dm_disk(md)->part0.in_flight = pending = + atomic_dec_return(&md->pending); return !pending; } @@ -885,6 +887,7 @@ static int dm_request(struct request_queue *q, struct bio *bio) int r = -EIO; int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; + int cpu; /* * There is no use in forwarding any barrier request since we can't @@ -897,8 +900,10 @@ static int dm_request(struct request_queue *q, struct bio *bio) down_read(&md->io_lock); - disk_stat_inc(dm_disk(md), ios[rw]); - disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); + cpu = part_stat_lock(); + part_stat_inc(cpu, &dm_disk(md)->part0, ios[rw]); + part_stat_add(cpu, &dm_disk(md)->part0, sectors[rw], bio_sectors(bio)); + part_stat_unlock(); /* * If we're suspended we have to queue @@ -1146,7 +1151,7 @@ static void unlock_fs(struct mapped_device *md); static void free_dev(struct mapped_device *md) { - int minor = md->disk->first_minor; + int minor = MINOR(disk_devt(md->disk)); if (md->suspended_bdev) { unlock_fs(md); @@ -1182,7 +1187,7 @@ static void event_callback(void *context) list_splice_init(&md->uevent_list, &uevents); spin_unlock_irqrestore(&md->uevent_lock, flags); - dm_send_uevents(&uevents, &md->disk->dev.kobj); + dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj); atomic_inc(&md->event_nr); wake_up(&md->eventq); @@ -1267,7 +1272,7 @@ static struct mapped_device *dm_find_md(dev_t dev) md = idr_find(&_minor_idr, minor); if (md && (md == MINOR_ALLOCED || - (dm_disk(md)->first_minor != minor) || + (MINOR(disk_devt(dm_disk(md))) != minor) || test_bit(DMF_FREEING, &md->flags))) { md = NULL; goto out; @@ -1318,7 +1323,8 @@ void dm_put(struct mapped_device *md) if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { map = dm_get_table(md); - idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor); + idr_replace(&_minor_idr, MINOR_ALLOCED, + MINOR(disk_devt(dm_disk(md)))); set_bit(DMF_FREEING, &md->flags); spin_unlock(&_minor_lock); if (!dm_suspended(md)) { @@ -1638,7 +1644,7 @@ out: *---------------------------------------------------------------*/ void dm_kobject_uevent(struct mapped_device *md) { - kobject_uevent(&md->disk->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&disk_to_dev(md->disk)->kobj, KOBJ_CHANGE); } uint32_t dm_next_uevent_seq(struct mapped_device *md) diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 1e59a0b0a78a..cd189da2b2fa 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -25,13 +25,10 @@ /* * List of devices that a metadevice uses and should open/close. */ -struct dm_dev { +struct dm_dev_internal { struct list_head list; - atomic_t count; - int mode; - struct block_device *bdev; - char name[16]; + struct dm_dev dm_dev; }; struct dm_table; @@ -49,7 +46,6 @@ void dm_table_presuspend_targets(struct dm_table *t); void dm_table_postsuspend_targets(struct dm_table *t); int dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); -void dm_table_unplug_all(struct dm_table *t); /* * To check the return value from dm_table_find_target(). @@ -93,8 +89,6 @@ void dm_linear_exit(void); int dm_stripe_init(void); void dm_stripe_exit(void); -void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); -union map_info *dm_get_mapinfo(struct bio *bio); int dm_open_count(struct mapped_device *md); int dm_lock_for_deletion(struct mapped_device *md); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index b1eebf88c209..b9cbee688fae 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -318,14 +318,18 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) mddev_t *mddev = q->queuedata; dev_info_t *tmp_dev; sector_t block; + int cpu; if (unlikely(bio_barrier(bio))) { bio_endio(bio, -EOPNOTSUPP); return 0; } - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); tmp_dev = which_dev(mddev, bio->bi_sector); block = bio->bi_sector >> 1; @@ -349,7 +353,7 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) * split it. */ struct bio_pair *bp; - bp = bio_split(bio, bio_split_pool, + bp = bio_split(bio, ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector); if (linear_make_request(q, &bp->bio1)) generic_make_request(&bp->bio1); diff --git a/drivers/md/md.c b/drivers/md/md.c index deeac4b44173..0a3a4bdcd4af 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1464,10 +1464,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b))) goto fail; - if (rdev->bdev->bd_part) - ko = &rdev->bdev->bd_part->dev.kobj; - else - ko = &rdev->bdev->bd_disk->dev.kobj; + ko = &part_to_dev(rdev->bdev->bd_part)->kobj; if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) { kobject_del(&rdev->kobj); goto fail; @@ -3470,8 +3467,8 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) disk->queue = mddev->queue; add_disk(disk); mddev->gendisk = disk; - error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->dev.kobj, - "%s", "md"); + error = kobject_init_and_add(&mddev->kobj, &md_ktype, + &disk_to_dev(disk)->kobj, "%s", "md"); mutex_unlock(&disks_mutex); if (error) printk(KERN_WARNING "md: cannot register %s/md - name in use\n", @@ -3761,7 +3758,7 @@ static int do_md_run(mddev_t * mddev) sysfs_notify(&mddev->kobj, NULL, "array_state"); sysfs_notify(&mddev->kobj, NULL, "sync_action"); sysfs_notify(&mddev->kobj, NULL, "degraded"); - kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); return 0; } @@ -5549,8 +5546,8 @@ static int is_mddev_idle(mddev_t *mddev) rcu_read_lock(); rdev_for_each_rcu(rdev, mddev) { struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; - curr_events = disk_stat_read(disk, sectors[0]) + - disk_stat_read(disk, sectors[1]) - + curr_events = part_stat_read(&disk->part0, sectors[0]) + + part_stat_read(&disk->part0, sectors[1]) - atomic_read(&disk->sync_io); /* sync IO will cause sync_io to increase before the disk_stats * as sync_io is counted when a request starts, and diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index c4779ccba1c3..8bb8794129b3 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -147,6 +147,7 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) struct multipath_bh * mp_bh; struct multipath_info *multipath; const int rw = bio_data_dir(bio); + int cpu; if (unlikely(bio_barrier(bio))) { bio_endio(bio, -EOPNOTSUPP); @@ -158,8 +159,11 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) mp_bh->master_bio = bio; mp_bh->mddev = mddev; - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); mp_bh->path = multipath_map(conf); if (mp_bh->path < 0) { diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 183610635661..53508a8a981d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -399,14 +399,18 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) sector_t chunk; sector_t block, rsect; const int rw = bio_data_dir(bio); + int cpu; if (unlikely(bio_barrier(bio))) { bio_endio(bio, -EOPNOTSUPP); return 0; } - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); chunk_size = mddev->chunk_size >> 10; chunk_sects = mddev->chunk_size >> 9; @@ -423,7 +427,7 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio) /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. */ - bp = bio_split(bio, bio_split_pool, chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); + bp = bio_split(bio, chunk_sects - (bio->bi_sector & (chunk_sects - 1))); if (raid0_make_request(q, &bp->bio1)) generic_make_request(&bp->bio1); if (raid0_make_request(q, &bp->bio2)) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 03a5ab705c20..b9764429d856 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -779,7 +779,7 @@ static int make_request(struct request_queue *q, struct bio * bio) struct page **behind_pages = NULL; const int rw = bio_data_dir(bio); const int do_sync = bio_sync(bio); - int do_barriers; + int cpu, do_barriers; mdk_rdev_t *blocked_rdev; /* @@ -804,8 +804,11 @@ static int make_request(struct request_queue *q, struct bio * bio) bitmap = mddev->bitmap; - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); /* * make_request() can abort the operation when READA is being @@ -1302,9 +1305,6 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) sbio->bi_size = r1_bio->sectors << 9; sbio->bi_idx = 0; sbio->bi_phys_segments = 0; - sbio->bi_hw_segments = 0; - sbio->bi_hw_front_size = 0; - sbio->bi_hw_back_size = 0; sbio->bi_flags &= ~(BIO_POOL_MASK - 1); sbio->bi_flags |= 1 << BIO_UPTODATE; sbio->bi_next = NULL; @@ -1790,7 +1790,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i bio->bi_vcnt = 0; bio->bi_idx = 0; bio->bi_phys_segments = 0; - bio->bi_hw_segments = 0; bio->bi_size = 0; bio->bi_end_io = NULL; bio->bi_private = NULL; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index e34cd0e62473..8bdc9bfc2887 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -789,6 +789,7 @@ static int make_request(struct request_queue *q, struct bio * bio) mirror_info_t *mirror; r10bio_t *r10_bio; struct bio *read_bio; + int cpu; int i; int chunk_sects = conf->chunk_mask + 1; const int rw = bio_data_dir(bio); @@ -816,7 +817,7 @@ static int make_request(struct request_queue *q, struct bio * bio) /* This is a one page bio that upper layers * refuse to split for us, so we need to split it. */ - bp = bio_split(bio, bio_split_pool, + bp = bio_split(bio, chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); if (make_request(q, &bp->bio1)) generic_make_request(&bp->bio1); @@ -843,8 +844,11 @@ static int make_request(struct request_queue *q, struct bio * bio) */ wait_barrier(conf); - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bio)); + part_stat_unlock(); r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO); @@ -1345,9 +1349,6 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio) tbio->bi_size = r10_bio->sectors << 9; tbio->bi_idx = 0; tbio->bi_phys_segments = 0; - tbio->bi_hw_segments = 0; - tbio->bi_hw_front_size = 0; - tbio->bi_hw_back_size = 0; tbio->bi_flags &= ~(BIO_POOL_MASK - 1); tbio->bi_flags |= 1 << BIO_UPTODATE; tbio->bi_next = NULL; @@ -1947,7 +1948,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i bio->bi_vcnt = 0; bio->bi_idx = 0; bio->bi_phys_segments = 0; - bio->bi_hw_segments = 0; bio->bi_size = 0; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 224de022e7c5..ae16794bef20 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -101,6 +101,40 @@ const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); #endif +/* + * We maintain a biased count of active stripes in the bottom 16 bits of + * bi_phys_segments, and a count of processed stripes in the upper 16 bits + */ +static inline int raid5_bi_phys_segments(struct bio *bio) +{ + return bio->bi_phys_segments & 0xffff; +} + +static inline int raid5_bi_hw_segments(struct bio *bio) +{ + return (bio->bi_phys_segments >> 16) & 0xffff; +} + +static inline int raid5_dec_bi_phys_segments(struct bio *bio) +{ + --bio->bi_phys_segments; + return raid5_bi_phys_segments(bio); +} + +static inline int raid5_dec_bi_hw_segments(struct bio *bio) +{ + unsigned short val = raid5_bi_hw_segments(bio); + + --val; + bio->bi_phys_segments = (val << 16) | raid5_bi_phys_segments(bio); + return val; +} + +static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt) +{ + bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16); +} + static inline int raid6_next_disk(int disk, int raid_disks) { disk++; @@ -507,7 +541,7 @@ static void ops_complete_biofill(void *stripe_head_ref) while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) { rbi2 = r5_next_bio(rbi, dev->sector); - if (--rbi->bi_phys_segments == 0) { + if (!raid5_dec_bi_phys_segments(rbi)) { rbi->bi_next = return_bi; return_bi = rbi; } @@ -1725,7 +1759,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in if (*bip) bi->bi_next = *bip; *bip = bi; - bi->bi_phys_segments ++; + bi->bi_phys_segments++; spin_unlock_irq(&conf->device_lock); spin_unlock(&sh->lock); @@ -1819,7 +1853,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh, sh->dev[i].sector + STRIPE_SECTORS) { struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); - if (--bi->bi_phys_segments == 0) { + if (!raid5_dec_bi_phys_segments(bi)) { md_write_end(conf->mddev); bi->bi_next = *return_bi; *return_bi = bi; @@ -1834,7 +1868,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh, sh->dev[i].sector + STRIPE_SECTORS) { struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); - if (--bi->bi_phys_segments == 0) { + if (!raid5_dec_bi_phys_segments(bi)) { md_write_end(conf->mddev); bi->bi_next = *return_bi; *return_bi = bi; @@ -1858,7 +1892,7 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh, struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); - if (--bi->bi_phys_segments == 0) { + if (!raid5_dec_bi_phys_segments(bi)) { bi->bi_next = *return_bi; *return_bi = bi; } @@ -2033,7 +2067,7 @@ static void handle_stripe_clean_event(raid5_conf_t *conf, while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) { wbi2 = r5_next_bio(wbi, dev->sector); - if (--wbi->bi_phys_segments == 0) { + if (!raid5_dec_bi_phys_segments(wbi)) { md_write_end(conf->mddev); wbi->bi_next = *return_bi; *return_bi = wbi; @@ -2814,7 +2848,7 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) copy_data(0, rbi, dev->page, dev->sector); rbi2 = r5_next_bio(rbi, dev->sector); spin_lock_irq(&conf->device_lock); - if (--rbi->bi_phys_segments == 0) { + if (!raid5_dec_bi_phys_segments(rbi)) { rbi->bi_next = return_bi; return_bi = rbi; } @@ -3155,8 +3189,11 @@ static struct bio *remove_bio_from_retry(raid5_conf_t *conf) if(bi) { conf->retry_read_aligned_list = bi->bi_next; bi->bi_next = NULL; + /* + * this sets the active strip count to 1 and the processed + * strip count to zero (upper 8 bits) + */ bi->bi_phys_segments = 1; /* biased count of active stripes */ - bi->bi_hw_segments = 0; /* count of processed stripes */ } return bi; @@ -3206,8 +3243,7 @@ static int bio_fits_rdev(struct bio *bi) if ((bi->bi_size>>9) > q->max_sectors) return 0; blk_recount_segments(q, bi); - if (bi->bi_phys_segments > q->max_phys_segments || - bi->bi_hw_segments > q->max_hw_segments) + if (bi->bi_phys_segments > q->max_phys_segments) return 0; if (q->merge_bvec_fn) @@ -3351,7 +3387,7 @@ static int make_request(struct request_queue *q, struct bio * bi) sector_t logical_sector, last_sector; struct stripe_head *sh; const int rw = bio_data_dir(bi); - int remaining; + int cpu, remaining; if (unlikely(bio_barrier(bi))) { bio_endio(bi, -EOPNOTSUPP); @@ -3360,8 +3396,11 @@ static int make_request(struct request_queue *q, struct bio * bi) md_write_start(mddev, bi); - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi)); + cpu = part_stat_lock(); + part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); + part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], + bio_sectors(bi)); + part_stat_unlock(); if (rw == READ && mddev->reshape_position == MaxSector && @@ -3468,7 +3507,7 @@ static int make_request(struct request_queue *q, struct bio * bi) } spin_lock_irq(&conf->device_lock); - remaining = --bi->bi_phys_segments; + remaining = raid5_dec_bi_phys_segments(bi); spin_unlock_irq(&conf->device_lock); if (remaining == 0) { @@ -3752,7 +3791,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) sector += STRIPE_SECTORS, scnt++) { - if (scnt < raid_bio->bi_hw_segments) + if (scnt < raid5_bi_hw_segments(raid_bio)) /* already done this stripe */ continue; @@ -3760,7 +3799,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) if (!sh) { /* failed to get a stripe - must wait */ - raid_bio->bi_hw_segments = scnt; + raid5_set_bi_hw_segments(raid_bio, scnt); conf->retry_read_aligned = raid_bio; return handled; } @@ -3768,7 +3807,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) set_bit(R5_ReadError, &sh->dev[dd_idx].flags); if (!add_stripe_bio(sh, raid_bio, dd_idx, 0)) { release_stripe(sh); - raid_bio->bi_hw_segments = scnt; + raid5_set_bi_hw_segments(raid_bio, scnt); conf->retry_read_aligned = raid_bio; return handled; } @@ -3778,7 +3817,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) handled++; } spin_lock_irq(&conf->device_lock); - remaining = --raid_bio->bi_phys_segments; + remaining = raid5_dec_bi_phys_segments(raid_bio); spin_unlock_irq(&conf->device_lock); if (remaining == 0) bio_endio(raid_bio, 0); diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index d2d2318dafa4..6e291bf8237a 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -197,7 +197,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp) static int mspro_block_disk_release(struct gendisk *disk) { struct mspro_block_data *msb = disk->private_data; - int disk_id = disk->first_minor >> MSPRO_BLOCK_PART_SHIFT; + int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT; mutex_lock(&mspro_block_disk_lock); @@ -828,7 +828,7 @@ static void mspro_block_submit_req(struct request_queue *q) if (msb->eject) { while ((req = elv_next_request(q)) != NULL) - end_queued_request(req, -ENODEV); + __blk_end_request(req, -ENODEV, blk_rq_bytes(req)); return; } diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index ebc8b9d77613..efacee0404a0 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -29,6 +29,7 @@ #include <linux/blkdev.h> #include <linux/mutex.h> #include <linux/scatterlist.h> +#include <linux/string_helpers.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> @@ -83,7 +84,7 @@ static void mmc_blk_put(struct mmc_blk_data *md) mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { - int devidx = md->disk->first_minor >> MMC_SHIFT; + int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; __clear_bit(devidx, dev_use); put_disk(md->disk); @@ -532,6 +533,8 @@ static int mmc_blk_probe(struct mmc_card *card) struct mmc_blk_data *md; int err; + char cap_str[10]; + /* * Check that the card supports the command class(es) we need. */ @@ -546,10 +549,11 @@ static int mmc_blk_probe(struct mmc_card *card) if (err) goto out; - printk(KERN_INFO "%s: %s %s %lluKiB %s\n", + string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2, + cap_str, sizeof(cap_str)); + printk(KERN_INFO "%s: %s %s %s %s\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), - (unsigned long long)(get_capacity(md->disk) >> 1), - md->read_only ? "(ro)" : ""); + cap_str, md->read_only ? "(ro)" : ""); mmc_set_drvdata(card, md); add_disk(md->disk); diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index f34f20c78911..9bf581c4f740 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -1005,6 +1005,29 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev, return ftl_write((void *)dev, buf, block, 1); } +static int ftl_discardsect(struct mtd_blktrans_dev *dev, + unsigned long sector, unsigned nr_sects) +{ + partition_t *part = (void *)dev; + uint32_t bsize = 1 << part->header.EraseUnitSize; + + DEBUG(1, "FTL erase sector %ld for %d sectors\n", + sector, nr_sects); + + while (nr_sects) { + uint32_t old_addr = part->VirtualBlockMap[sector]; + if (old_addr != 0xffffffff) { + part->VirtualBlockMap[sector] = 0xffffffff; + part->EUNInfo[old_addr/bsize].Deleted++; + if (set_bam_entry(part, old_addr, 0)) + return -EIO; + } + nr_sects--; + sector++; + } + + return 0; +} /*====================================================================*/ static void ftl_freepart(partition_t *part) @@ -1069,6 +1092,7 @@ static struct mtd_blktrans_ops ftl_tr = { .blksize = SECTOR_SIZE, .readsect = ftl_readsect, .writesect = ftl_writesect, + .discard = ftl_discardsect, .getgeo = ftl_getgeo, .add_mtd = ftl_add_mtd, .remove_dev = ftl_remove_dev, diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 9ff007c4962c..681d5aca2af4 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -32,6 +32,14 @@ struct mtd_blkcore_priv { spinlock_t queue_lock; }; +static int blktrans_discard_request(struct request_queue *q, + struct request *req) +{ + req->cmd_type = REQ_TYPE_LINUX_BLOCK; + req->cmd[0] = REQ_LB_OP_DISCARD; + return 0; +} + static int do_blktrans_request(struct mtd_blktrans_ops *tr, struct mtd_blktrans_dev *dev, struct request *req) @@ -44,6 +52,10 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, buf = req->buffer; + if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && + req->cmd[0] == REQ_LB_OP_DISCARD) + return !tr->discard(dev, block, nsect); + if (!blk_fs_request(req)) return 0; @@ -367,6 +379,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) tr->blkcore_priv->rq->queuedata = tr; blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); + if (tr->discard) + blk_queue_set_discard(tr->blkcore_priv->rq, + blktrans_discard_request); + tr->blkshift = ffs(tr->blksize) - 1; tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr, diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile index 26f5abc9c3f7..e83f34f1b5ba 100644 --- a/drivers/pnp/Makefile +++ b/drivers/pnp/Makefile @@ -2,12 +2,15 @@ # Makefile for the Linux Plug-and-Play Support. # -obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o system.o +obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o obj-$(CONFIG_PNPACPI) += pnpacpi/ obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ +# pnp_system_init goes after pnpacpi/pnpbios init +obj-y += system.o + ifeq ($(CONFIG_PNP_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index c1b9ea34977b..53561d72b4ee 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -268,7 +268,7 @@ static int __init pnpacpi_init(void) return 0; } -subsys_initcall(pnpacpi_init); +fs_initcall(pnpacpi_init); static int __init pnpacpi_setup(char *str) { diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 19a4be1a9a31..662dfcddedc6 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -571,7 +571,7 @@ static int __init pnpbios_init(void) return 0; } -subsys_initcall(pnpbios_init); +fs_initcall(pnpbios_init); static int __init pnpbios_thread_init(void) { diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 03c0e40a92ff..e3b5c4d3036e 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -76,7 +76,8 @@ dasd_devices_show(struct seq_file *m, void *v) /* Print kdev. */ if (block->gdp) seq_printf(m, " at (%3d:%6d)", - block->gdp->major, block->gdp->first_minor); + MAJOR(disk_devt(block->gdp)), + MINOR(disk_devt(block->gdp))); else seq_printf(m, " at (???:??????)"); /* Print device name. */ diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 711b3004b3e6..9481e4a3f76e 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -114,7 +114,7 @@ dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) found = 0; // test if minor available list_for_each_entry(entry, &dcssblk_devices, lh) - if (minor == entry->gd->first_minor) + if (minor == MINOR(disk_devt(entry->gd))) found++; if (!found) break; // got unused minor } @@ -397,7 +397,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char goto unload_seg; } sprintf(dev_info->gd->disk_name, "dcssblk%d", - dev_info->gd->first_minor); + MINOR(disk_devt(dev_info->gd))); list_add_tail(&dev_info->lh, &dcssblk_devices); if (!try_module_get(THIS_MODULE)) { diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 90abfd06ed55..24255e42dc30 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -88,11 +88,13 @@ static int __init zfcp_device_setup(char *devstr) strncpy(zfcp_data.init_busid, token, BUS_ID_SIZE); token = strsep(&str, ","); - if (!token || strict_strtoull(token, 0, &zfcp_data.init_wwpn)) + if (!token || strict_strtoull(token, 0, + (unsigned long long *) &zfcp_data.init_wwpn)) goto err_out; token = strsep(&str, ","); - if (!token || strict_strtoull(token, 0, &zfcp_data.init_fcp_lun)) + if (!token || strict_strtoull(token, 0, + (unsigned long long *) &zfcp_data.init_fcp_lun)) goto err_out; kfree(str); @@ -100,24 +102,10 @@ static int __init zfcp_device_setup(char *devstr) err_out: kfree(str); - pr_err("zfcp: Parse error for device parameter string %s, " - "device not attached.\n", devstr); + pr_err("zfcp: %s is not a valid SCSI device\n", devstr); return 0; } -static struct zfcp_adapter *zfcp_get_adapter_by_busid(char *bus_id) -{ - struct zfcp_adapter *adapter; - - list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) - if ((strncmp(bus_id, adapter->ccw_device->dev.bus_id, - BUS_ID_SIZE) == 0) && - !(atomic_read(&adapter->status) & - ZFCP_STATUS_COMMON_REMOVE)) - return adapter; - return NULL; -} - static void __init zfcp_init_device_configure(void) { struct zfcp_adapter *adapter; @@ -141,7 +129,12 @@ static void __init zfcp_init_device_configure(void) goto out_unit; up(&zfcp_data.config_sema); ccw_device_set_online(adapter->ccw_device); + zfcp_erp_wait(adapter); + wait_event(adapter->erp_done_wqh, + !(atomic_read(&unit->status) & + ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)); + down(&zfcp_data.config_sema); zfcp_unit_put(unit); out_unit: @@ -180,9 +173,9 @@ static int __init zfcp_module_init(void) if (!zfcp_data.gid_pn_cache) goto out_gid_cache; - INIT_LIST_HEAD(&zfcp_data.adapter_list_head); - INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh); + zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq"); + INIT_LIST_HEAD(&zfcp_data.adapter_list_head); sema_init(&zfcp_data.config_sema, 1); rwlock_init(&zfcp_data.config_lock); @@ -193,13 +186,14 @@ static int __init zfcp_module_init(void) retval = misc_register(&zfcp_cfdc_misc); if (retval) { - pr_err("zfcp: registration of misc device zfcp_cfdc failed\n"); + pr_err("zfcp: Registering the misc device zfcp_cfdc failed\n"); goto out_misc; } retval = zfcp_ccw_register(); if (retval) { - pr_err("zfcp: Registration with common I/O layer failed.\n"); + pr_err("zfcp: The zfcp device driver could not register with " + "the common I/O layer\n"); goto out_ccw_register; } @@ -231,8 +225,7 @@ module_init(zfcp_module_init); * * Returns: pointer to zfcp_unit or NULL */ -struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, - fcp_lun_t fcp_lun) +struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) { struct zfcp_unit *unit; @@ -251,7 +244,7 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, * Returns: pointer to zfcp_port or NULL */ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, - wwn_t wwpn) + u64 wwpn) { struct zfcp_port *port; @@ -276,7 +269,7 @@ static void zfcp_sysfs_unit_release(struct device *dev) * * Sets up some unit internal structures and creates sysfs entry. */ -struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) +struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) { struct zfcp_unit *unit; @@ -290,7 +283,8 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) unit->port = port; unit->fcp_lun = fcp_lun; - snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun); + snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", + (unsigned long long) fcp_lun); unit->sysfs_device.parent = &port->sysfs_device; unit->sysfs_device.release = zfcp_sysfs_unit_release; dev_set_drvdata(&unit->sysfs_device, unit); @@ -323,7 +317,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) } zfcp_unit_get(unit); - unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun); write_lock_irq(&zfcp_data.config_lock); list_add_tail(&unit->list, &port->unit_list_head); @@ -332,7 +325,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) write_unlock_irq(&zfcp_data.config_lock); - port->units++; zfcp_port_get(port); return unit; @@ -351,11 +343,10 @@ err_out_free: */ void zfcp_unit_dequeue(struct zfcp_unit *unit) { - zfcp_unit_wait(unit); + wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0); write_lock_irq(&zfcp_data.config_lock); list_del(&unit->list); write_unlock_irq(&zfcp_data.config_lock); - unit->port->units--; zfcp_port_put(unit->port); sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs); device_unregister(&unit->sysfs_device); @@ -416,11 +407,6 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) mempool_destroy(adapter->pool.data_gid_pn); } -static void zfcp_dummy_release(struct device *dev) -{ - return; -} - /** * zfcp_status_read_refill - refill the long running status_read_requests * @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled @@ -450,19 +436,6 @@ static void _zfcp_status_read_scheduler(struct work_struct *work) stat_work)); } -static int zfcp_nameserver_enqueue(struct zfcp_adapter *adapter) -{ - struct zfcp_port *port; - - port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA, - ZFCP_DID_DIRECTORY_SERVICE); - if (IS_ERR(port)) - return PTR_ERR(port); - zfcp_port_put(port); - - return 0; -} - /** * zfcp_adapter_enqueue - enqueue a new adapter to the list * @ccw_device: pointer to the struct cc_device @@ -508,7 +481,6 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) init_waitqueue_head(&adapter->erp_done_wqh); INIT_LIST_HEAD(&adapter->port_list_head); - INIT_LIST_HEAD(&adapter->port_remove_lh); INIT_LIST_HEAD(&adapter->erp_ready_head); INIT_LIST_HEAD(&adapter->erp_running_head); @@ -518,7 +490,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) spin_lock_init(&adapter->san_dbf_lock); spin_lock_init(&adapter->scsi_dbf_lock); spin_lock_init(&adapter->rec_dbf_lock); - spin_lock_init(&adapter->req_q.lock); + spin_lock_init(&adapter->req_q_lock); rwlock_init(&adapter->erp_lock); rwlock_init(&adapter->abort_lock); @@ -537,28 +509,15 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) &zfcp_sysfs_adapter_attrs)) goto sysfs_failed; - adapter->generic_services.parent = &adapter->ccw_device->dev; - adapter->generic_services.release = zfcp_dummy_release; - snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE, - "generic_services"); - - if (device_register(&adapter->generic_services)) - goto generic_services_failed; - write_lock_irq(&zfcp_data.config_lock); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); list_add_tail(&adapter->list, &zfcp_data.adapter_list_head); write_unlock_irq(&zfcp_data.config_lock); - zfcp_data.adapters++; - - zfcp_nameserver_enqueue(adapter); + zfcp_fc_nameserver_init(adapter); return 0; -generic_services_failed: - sysfs_remove_group(&ccw_device->dev.kobj, - &zfcp_sysfs_adapter_attrs); sysfs_failed: zfcp_adapter_debug_unregister(adapter); debug_register_failed: @@ -585,7 +544,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) cancel_work_sync(&adapter->scan_work); cancel_work_sync(&adapter->stat_work); zfcp_adapter_scsi_unregister(adapter); - device_unregister(&adapter->generic_services); sysfs_remove_group(&adapter->ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs); dev_set_drvdata(&adapter->ccw_device->dev, NULL); @@ -603,9 +561,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) list_del(&adapter->list); write_unlock_irq(&zfcp_data.config_lock); - /* decrease number of adapters in list */ - zfcp_data.adapters--; - zfcp_qdio_free(adapter); zfcp_free_low_mem_buffers(adapter); @@ -633,21 +588,19 @@ static void zfcp_sysfs_port_release(struct device *dev) * d_id is used to enqueue ports with a well known address like the Directory * Service for nameserver lookup. */ -struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, +struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, u32 status, u32 d_id) { struct zfcp_port *port; int retval; - char *bus_id; port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); if (!port) return ERR_PTR(-ENOMEM); init_waitqueue_head(&port->remove_wq); - INIT_LIST_HEAD(&port->unit_list_head); - INIT_LIST_HEAD(&port->unit_remove_lh); + INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup); port->adapter = adapter; port->d_id = d_id; @@ -657,34 +610,9 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set(&port->refcount, 0); - if (status & ZFCP_STATUS_PORT_WKA) { - switch (d_id) { - case ZFCP_DID_DIRECTORY_SERVICE: - bus_id = "directory"; - break; - case ZFCP_DID_MANAGEMENT_SERVICE: - bus_id = "management"; - break; - case ZFCP_DID_KEY_DISTRIBUTION_SERVICE: - bus_id = "key_distribution"; - break; - case ZFCP_DID_ALIAS_SERVICE: - bus_id = "alias"; - break; - case ZFCP_DID_TIME_SERVICE: - bus_id = "time"; - break; - default: - kfree(port); - return ERR_PTR(-EINVAL); - } - snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "%s", bus_id); - port->sysfs_device.parent = &adapter->generic_services; - } else { - snprintf(port->sysfs_device.bus_id, - BUS_ID_SIZE, "0x%016llx", wwpn); - port->sysfs_device.parent = &adapter->ccw_device->dev; - } + snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", + (unsigned long long) wwpn); + port->sysfs_device.parent = &adapter->ccw_device->dev; port->sysfs_device.release = zfcp_sysfs_port_release; dev_set_drvdata(&port->sysfs_device, port); @@ -700,12 +628,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, if (device_register(&port->sysfs_device)) goto err_out_free; - if (status & ZFCP_STATUS_PORT_WKA) - retval = sysfs_create_group(&port->sysfs_device.kobj, - &zfcp_sysfs_ns_port_attrs); - else - retval = sysfs_create_group(&port->sysfs_device.kobj, - &zfcp_sysfs_port_attrs); + retval = sysfs_create_group(&port->sysfs_device.kobj, + &zfcp_sysfs_port_attrs); if (retval) { device_unregister(&port->sysfs_device); @@ -718,10 +642,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, list_add_tail(&port->list, &adapter->port_list_head); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); - if (d_id == ZFCP_DID_DIRECTORY_SERVICE) - if (!adapter->nameserver_port) - adapter->nameserver_port = port; - adapter->ports++; write_unlock_irq(&zfcp_data.config_lock); @@ -740,21 +660,15 @@ err_out: */ void zfcp_port_dequeue(struct zfcp_port *port) { - zfcp_port_wait(port); + wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); write_lock_irq(&zfcp_data.config_lock); list_del(&port->list); - port->adapter->ports--; write_unlock_irq(&zfcp_data.config_lock); if (port->rport) fc_remote_port_delete(port->rport); port->rport = NULL; zfcp_adapter_put(port->adapter); - if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) - sysfs_remove_group(&port->sysfs_device.kobj, - &zfcp_sysfs_ns_port_attrs); - else - sysfs_remove_group(&port->sysfs_device.kobj, - &zfcp_sysfs_port_attrs); + sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); device_unregister(&port->sysfs_device); } diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 51b6a05f4d12..b04038c74786 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -25,7 +25,8 @@ static int zfcp_ccw_probe(struct ccw_device *ccw_device) down(&zfcp_data.config_sema); if (zfcp_adapter_enqueue(ccw_device)) { dev_err(&ccw_device->dev, - "Setup of data structures failed.\n"); + "Setting up data structures for the " + "FCP adapter failed\n"); retval = -EINVAL; } up(&zfcp_data.config_sema); @@ -46,6 +47,8 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) struct zfcp_adapter *adapter; struct zfcp_port *port, *p; struct zfcp_unit *unit, *u; + LIST_HEAD(unit_remove_lh); + LIST_HEAD(port_remove_lh); ccw_device_set_offline(ccw_device); down(&zfcp_data.config_sema); @@ -54,26 +57,26 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) write_lock_irq(&zfcp_data.config_lock); list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { - list_move(&unit->list, &port->unit_remove_lh); + list_move(&unit->list, &unit_remove_lh); atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); } - list_move(&port->list, &adapter->port_remove_lh); + list_move(&port->list, &port_remove_lh); atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); } atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); write_unlock_irq(&zfcp_data.config_lock); - list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) { - list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) { - if (atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED, - &unit->status)) + list_for_each_entry_safe(port, p, &port_remove_lh, list) { + list_for_each_entry_safe(unit, u, &unit_remove_lh, list) { + if (atomic_read(&unit->status) & + ZFCP_STATUS_UNIT_REGISTERED) scsi_remove_device(unit->device); zfcp_unit_dequeue(unit); } zfcp_port_dequeue(port); } - zfcp_adapter_wait(adapter); + wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); zfcp_adapter_dequeue(adapter); up(&zfcp_data.config_sema); @@ -156,15 +159,18 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) switch (event) { case CIO_GONE: - dev_warn(&adapter->ccw_device->dev, "device gone\n"); + dev_warn(&adapter->ccw_device->dev, + "The FCP device has been detached\n"); zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL); break; case CIO_NO_PATH: - dev_warn(&adapter->ccw_device->dev, "no path\n"); + dev_warn(&adapter->ccw_device->dev, + "The CHPID for the FCP device is offline\n"); zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL); break; case CIO_OPER: - dev_info(&adapter->ccw_device->dev, "operational again\n"); + dev_info(&adapter->ccw_device->dev, + "The FCP device is operational again\n"); zfcp_erp_modify_adapter_status(adapter, 11, NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); @@ -220,3 +226,20 @@ int __init zfcp_ccw_register(void) { return ccw_driver_register(&zfcp_ccw_driver); } + +/** + * zfcp_get_adapter_by_busid - find zfcp_adapter struct + * @busid: bus id string of zfcp adapter to find + */ +struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid) +{ + struct ccw_device *ccw_device; + struct zfcp_adapter *adapter = NULL; + + ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); + if (ccw_device) { + adapter = dev_get_drvdata(&ccw_device->dev); + put_device(&ccw_device->dev); + } + return adapter; +} diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index fca48b88fc53..060f5f2352ec 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -318,6 +318,26 @@ void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); } +/** + * zfcp_hba_dbf_event_berr - trace event for bit error threshold + * @adapter: adapter affected by this QDIO related event + * @req: fsf request + */ +void zfcp_hba_dbf_event_berr(struct zfcp_adapter *adapter, + struct zfcp_fsf_req *req) +{ + struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf; + struct fsf_status_read_buffer *sr_buf = req->data; + struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error; + unsigned long flags; + + spin_lock_irqsave(&adapter->hba_dbf_lock, flags); + memset(r, 0, sizeof(*r)); + strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE); + memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload)); + debug_event(adapter->hba_dbf, 0, r, sizeof(*r)); + spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); +} static void zfcp_hba_dbf_view_response(char **p, struct zfcp_hba_dbf_record_response *r) { @@ -399,6 +419,30 @@ static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r) zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count); } +static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r) +{ + zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count); + zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count); + zfcp_dbf_out(p, "loss_of_sig_err", "%d", r->loss_of_signal_error_count); + zfcp_dbf_out(p, "prim_seq_err", "%d", + r->primitive_sequence_error_count); + zfcp_dbf_out(p, "inval_trans_word_err", "%d", + r->invalid_transmission_word_error_count); + zfcp_dbf_out(p, "CRC_errors", "%d", r->crc_error_count); + zfcp_dbf_out(p, "prim_seq_event_to", "%d", + r->primitive_sequence_event_timeout_count); + zfcp_dbf_out(p, "elast_buf_overrun_err", "%d", + r->elastic_buffer_overrun_error_count); + zfcp_dbf_out(p, "adv_rec_buf2buf_cred", "%d", + r->advertised_receive_b2b_credit); + zfcp_dbf_out(p, "curr_rec_buf2buf_cred", "%d", + r->current_receive_b2b_credit); + zfcp_dbf_out(p, "adv_trans_buf2buf_cred", "%d", + r->advertised_transmit_b2b_credit); + zfcp_dbf_out(p, "curr_trans_buf2buf_cred", "%d", + r->current_transmit_b2b_credit); +} + static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view, char *out_buf, const char *in_buf) { @@ -418,6 +462,8 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view, zfcp_hba_dbf_view_status(&p, &r->u.status); else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0) zfcp_hba_dbf_view_qdio(&p, &r->u.qdio); + else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0) + zfcp_hba_dbf_view_berr(&p, &r->u.berr); p += sprintf(p, "\n"); return p - out_buf; @@ -519,14 +565,14 @@ static const char *zfcp_rec_dbf_ids[] = { [75] = "physical port recovery escalation after failed port " "recovery", [76] = "port recovery escalation after failed unit recovery", - [77] = "recovery opening nameserver port", + [77] = "", [78] = "duplicate request id", [79] = "link down", [80] = "exclusive read-only unit access unsupported", [81] = "shared read-write unit access unsupported", [82] = "incoming rscn", [83] = "incoming wwpn", - [84] = "", + [84] = "wka port handle not valid close port", [85] = "online", [86] = "offline", [87] = "ccw device gone", @@ -570,7 +616,7 @@ static const char *zfcp_rec_dbf_ids[] = { [125] = "need newer zfcp", [126] = "need newer microcode", [127] = "arbitrated loop not supported", - [128] = "unknown topology", + [128] = "", [129] = "qtcb size mismatch", [130] = "unknown fsf status ecd", [131] = "fcp request too big", @@ -829,9 +875,9 @@ void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action) void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; - struct zfcp_port *port = ct->port; - struct zfcp_adapter *adapter = port->adapter; - struct ct_hdr *hdr = zfcp_sg_to_address(ct->req); + struct zfcp_wka_port *wka_port = ct->wka_port; + struct zfcp_adapter *adapter = wka_port->adapter; + struct ct_hdr *hdr = sg_virt(ct->req); struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req; unsigned long flags; @@ -842,7 +888,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) r->fsf_reqid = (unsigned long)fsf_req; r->fsf_seqno = fsf_req->seq_no; r->s_id = fc_host_port_id(adapter->scsi_host); - r->d_id = port->d_id; + r->d_id = wka_port->d_id; oct->cmd_req_code = hdr->cmd_rsp_code; oct->revision = hdr->revision; oct->gs_type = hdr->gs_type; @@ -863,9 +909,9 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; - struct zfcp_port *port = ct->port; - struct zfcp_adapter *adapter = port->adapter; - struct ct_hdr *hdr = zfcp_sg_to_address(ct->resp); + struct zfcp_wka_port *wka_port = ct->wka_port; + struct zfcp_adapter *adapter = wka_port->adapter; + struct ct_hdr *hdr = sg_virt(ct->resp); struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp; unsigned long flags; @@ -875,7 +921,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE); r->fsf_reqid = (unsigned long)fsf_req; r->fsf_seqno = fsf_req->seq_no; - r->s_id = port->d_id; + r->s_id = wka_port->d_id; r->d_id = fc_host_port_id(adapter->scsi_host); rct->cmd_rsp_code = hdr->cmd_rsp_code; rct->revision = hdr->revision; @@ -922,8 +968,8 @@ void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) zfcp_san_dbf_event_els("oels", 2, fsf_req, fc_host_port_id(els->adapter->scsi_host), - els->d_id, *(u8 *) zfcp_sg_to_address(els->req), - zfcp_sg_to_address(els->req), els->req->length); + els->d_id, *(u8 *) sg_virt(els->req), + sg_virt(els->req), els->req->length); } /** @@ -936,8 +982,7 @@ void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id, fc_host_port_id(els->adapter->scsi_host), - *(u8 *)zfcp_sg_to_address(els->req), - zfcp_sg_to_address(els->resp), + *(u8 *)sg_virt(els->req), sg_virt(els->resp), els->resp->length); } diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 0ddb18449d11..e8f450801fea 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -151,6 +151,7 @@ struct zfcp_hba_dbf_record { struct zfcp_hba_dbf_record_response response; struct zfcp_hba_dbf_record_status status; struct zfcp_hba_dbf_record_qdio qdio; + struct fsf_bit_error_payload berr; } u; } __attribute__ ((packed)); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 67f45fc62f53..73eb41580f25 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -39,29 +39,6 @@ /********************* GENERAL DEFINES *********************************/ -/** - * zfcp_sg_to_address - determine kernel address from struct scatterlist - * @list: struct scatterlist - * Return: kernel address - */ -static inline void * -zfcp_sg_to_address(struct scatterlist *list) -{ - return sg_virt(list); -} - -/** - * zfcp_address_to_sg - set up struct scatterlist from kernel address - * @address: kernel address - * @list: struct scatterlist - * @size: buffer size - */ -static inline void -zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) -{ - sg_set_buf(list, address, size); -} - #define REQUEST_LIST_SIZE 128 /********************* SCSI SPECIFIC DEFINES *********************************/ @@ -101,11 +78,6 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size) /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ -typedef unsigned long long wwn_t; -typedef unsigned long long fcp_lun_t; -/* data length field may be at variable position in FCP-2 FCP_CMND IU */ -typedef unsigned int fcp_dl_t; - /* timeout for name-server lookup (in seconds) */ #define ZFCP_NS_GID_PN_TIMEOUT 10 @@ -129,7 +101,7 @@ typedef unsigned int fcp_dl_t; /* FCP(-2) FCP_CMND IU */ struct fcp_cmnd_iu { - fcp_lun_t fcp_lun; /* FCP logical unit number */ + u64 fcp_lun; /* FCP logical unit number */ u8 crn; /* command reference number */ u8 reserved0:5; /* reserved */ u8 task_attribute:3; /* task attribute */ @@ -204,7 +176,7 @@ struct fcp_rscn_element { struct fcp_logo { u32 command; u32 nport_did; - wwn_t nport_wwpn; + u64 nport_wwpn; } __attribute__((packed)); /* @@ -218,13 +190,6 @@ struct fcp_logo { #define ZFCP_LS_RSCN 0x61 #define ZFCP_LS_RNID 0x78 -struct zfcp_ls_rjt_par { - u8 action; - u8 reason_code; - u8 reason_expl; - u8 vendor_unique; -} __attribute__ ((packed)); - struct zfcp_ls_adisc { u8 code; u8 field[3]; @@ -234,20 +199,6 @@ struct zfcp_ls_adisc { u32 nport_id; } __attribute__ ((packed)); -struct zfcp_ls_adisc_acc { - u8 code; - u8 field[3]; - u32 hard_nport_id; - u64 wwpn; - u64 wwnn; - u32 nport_id; -} __attribute__ ((packed)); - -struct zfcp_rc_entry { - u8 code; - const char *description; -}; - /* * FC-GS-2 stuff */ @@ -281,9 +232,7 @@ struct zfcp_rc_entry { #define ZFCP_STATUS_COMMON_RUNNING 0x40000000 #define ZFCP_STATUS_COMMON_ERP_FAILED 0x20000000 #define ZFCP_STATUS_COMMON_UNBLOCKED 0x10000000 -#define ZFCP_STATUS_COMMON_OPENING 0x08000000 #define ZFCP_STATUS_COMMON_OPEN 0x04000000 -#define ZFCP_STATUS_COMMON_CLOSING 0x02000000 #define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000 #define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000 #define ZFCP_STATUS_COMMON_ACCESS_BOXED 0x00400000 @@ -291,16 +240,15 @@ struct zfcp_rc_entry { /* adapter status */ #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 -#define ZFCP_STATUS_ADAPTER_REGISTERED 0x00000004 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 #define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP 0x00000020 #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 -#define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800 /* FC-PH/FC-GS well-known address identifiers for generic services */ +#define ZFCP_DID_WKA 0xFFFFF0 #define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA #define ZFCP_DID_TIME_SERVICE 0xFFFFFB #define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC @@ -312,29 +260,27 @@ struct zfcp_rc_entry { #define ZFCP_STATUS_PORT_DID_DID 0x00000002 #define ZFCP_STATUS_PORT_PHYS_CLOSING 0x00000004 #define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 -#define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010 #define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020 -/* for ports with well known addresses */ -#define ZFCP_STATUS_PORT_WKA \ - (ZFCP_STATUS_PORT_NO_WWPN | \ - ZFCP_STATUS_PORT_NO_SCSI_ID) +/* well known address (WKA) port status*/ +enum zfcp_wka_status { + ZFCP_WKA_PORT_OFFLINE, + ZFCP_WKA_PORT_CLOSING, + ZFCP_WKA_PORT_OPENING, + ZFCP_WKA_PORT_ONLINE, +}; /* logical unit status */ -#define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 #define ZFCP_STATUS_UNIT_SHARED 0x00000004 #define ZFCP_STATUS_UNIT_READONLY 0x00000008 #define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 #define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020 /* FSF request status (this does not have a common part) */ -#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000 -#define ZFCP_STATUS_FSFREQ_POOL 0x00000001 #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 #define ZFCP_STATUS_FSFREQ_COMPLETED 0x00000004 #define ZFCP_STATUS_FSFREQ_ERROR 0x00000008 #define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010 -#define ZFCP_STATUS_FSFREQ_ABORTING 0x00000020 #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040 #define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080 #define ZFCP_STATUS_FSFREQ_ABORTED 0x00000100 @@ -379,7 +325,7 @@ struct ct_hdr { * a port name is required */ struct ct_iu_gid_pn_req { struct ct_hdr header; - wwn_t wwpn; + u64 wwpn; } __attribute__ ((packed)); /* FS_ACC IU and data unit for GID_PN nameserver request */ @@ -388,11 +334,9 @@ struct ct_iu_gid_pn_resp { u32 d_id; } __attribute__ ((packed)); -typedef void (*zfcp_send_ct_handler_t)(unsigned long); - /** * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct - * @port: port where the request is sent to + * @wka_port: port where the request is sent to * @req: scatter-gather list for request * @resp: scatter-gather list for response * @req_count: number of elements in request scatter-gather list @@ -404,12 +348,12 @@ typedef void (*zfcp_send_ct_handler_t)(unsigned long); * @status: used to pass error status to calling function */ struct zfcp_send_ct { - struct zfcp_port *port; + struct zfcp_wka_port *wka_port; struct scatterlist *req; struct scatterlist *resp; unsigned int req_count; unsigned int resp_count; - zfcp_send_ct_handler_t handler; + void (*handler)(unsigned long); unsigned long handler_data; int timeout; struct completion *completion; @@ -426,8 +370,6 @@ struct zfcp_gid_pn_data { struct zfcp_port *port; }; -typedef void (*zfcp_send_els_handler_t)(unsigned long); - /** * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els * @adapter: adapter where request is sent from @@ -451,22 +393,28 @@ struct zfcp_send_els { struct scatterlist *resp; unsigned int req_count; unsigned int resp_count; - zfcp_send_els_handler_t handler; + void (*handler)(unsigned long); unsigned long handler_data; struct completion *completion; int ls_code; int status; }; +struct zfcp_wka_port { + struct zfcp_adapter *adapter; + wait_queue_head_t completion_wq; + enum zfcp_wka_status status; + atomic_t refcount; + u32 d_id; + u32 handle; + struct mutex mutex; + struct delayed_work work; +}; + struct zfcp_qdio_queue { - struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */ - u8 first; /* index of next free bfr - in queue (free_count>0) */ - atomic_t count; /* number of free buffers - in queue */ - spinlock_t lock; /* lock for operations on queue */ - int pci_batch; /* SBALs since PCI indication - was last set */ + struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; + u8 first; /* index of next free bfr in queue */ + atomic_t count; /* number of free buffers in queue */ }; struct zfcp_erp_action { @@ -475,7 +423,7 @@ struct zfcp_erp_action { struct zfcp_adapter *adapter; /* device which should be recovered */ struct zfcp_port *port; struct zfcp_unit *unit; - volatile u32 status; /* recovery status */ + u32 status; /* recovery status */ u32 step; /* active step of this erp action */ struct zfcp_fsf_req *fsf_req; /* fsf request currently pending for this action */ @@ -506,8 +454,8 @@ struct zfcp_adapter { atomic_t refcount; /* reference count */ wait_queue_head_t remove_wq; /* can be used to wait for refcount drop to zero */ - wwn_t peer_wwnn; /* P2P peer WWNN */ - wwn_t peer_wwpn; /* P2P peer WWPN */ + u64 peer_wwnn; /* P2P peer WWNN */ + u64 peer_wwpn; /* P2P peer WWPN */ u32 peer_d_id; /* P2P peer D_ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ u32 hydra_version; /* Hydra version */ @@ -518,13 +466,13 @@ struct zfcp_adapter { u16 timer_ticks; /* time int for a tick */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ struct list_head port_list_head; /* remote port list */ - struct list_head port_remove_lh; /* head of ports to be - removed */ - u32 ports; /* number of remote ports */ unsigned long req_no; /* unique FSF req number */ struct list_head *req_list; /* list of pending reqs */ spinlock_t req_list_lock; /* request list lock */ struct zfcp_qdio_queue req_q; /* request queue */ + spinlock_t req_q_lock; /* for operations on queue */ + int req_q_pci_batch; /* SBALs since PCI indication + was last set */ u32 fsf_req_seq_no; /* FSF cmnd seq number */ wait_queue_head_t request_wq; /* can be used to wait for more avaliable SBALs */ @@ -548,7 +496,7 @@ struct zfcp_adapter { actions */ u32 erp_low_mem_count; /* nr of erp actions waiting for memory */ - struct zfcp_port *nameserver_port; /* adapter's nameserver */ + struct zfcp_wka_port nsp; /* adapter's nameserver */ debug_info_t *rec_dbf; debug_info_t *hba_dbf; debug_info_t *san_dbf; /* debug feature areas */ @@ -563,11 +511,11 @@ struct zfcp_adapter { struct zfcp_scsi_dbf_record scsi_dbf_buf; struct zfcp_adapter_mempool pool; /* Adapter memory pools */ struct qdio_initialize qdio_init_data; /* for qdio_establish */ - struct device generic_services; /* directory for WKA ports */ struct fc_host_statistics *fc_stats; struct fsf_qtcb_bottom_port *stats_reset_data; unsigned long stats_reset; struct work_struct scan_work; + atomic_t qdio_outb_full; /* queue full incidents */ }; struct zfcp_port { @@ -579,18 +527,16 @@ struct zfcp_port { refcount drop to zero */ struct zfcp_adapter *adapter; /* adapter used to access port */ struct list_head unit_list_head; /* head of logical unit list */ - struct list_head unit_remove_lh; /* head of luns to be removed - list */ - u32 units; /* # of logical units in list */ atomic_t status; /* status of this remote port */ - wwn_t wwnn; /* WWNN if known */ - wwn_t wwpn; /* WWPN */ + u64 wwnn; /* WWNN if known */ + u64 wwpn; /* WWPN */ u32 d_id; /* D_ID */ u32 handle; /* handle assigned by FSF */ struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; u32 maxframe_size; u32 supported_classes; + struct work_struct gid_pn_work; }; struct zfcp_unit { @@ -601,8 +547,7 @@ struct zfcp_unit { refcount drop to zero */ struct zfcp_port *port; /* remote port of unit */ atomic_t status; /* status of this logical unit */ - unsigned int scsi_lun; /* own SCSI LUN */ - fcp_lun_t fcp_lun; /* own FCP_LUN */ + u64 fcp_lun; /* own FCP_LUN */ u32 handle; /* handle assigned by FSF */ struct scsi_device *device; /* scsi device struct pointer */ struct zfcp_erp_action erp_action; /* pending error recovery */ @@ -625,7 +570,7 @@ struct zfcp_fsf_req { u8 sbal_response; /* SBAL used in interrupt */ wait_queue_head_t completion_wq; /* can be used by a routine to wait for completion */ - volatile u32 status; /* status of this request */ + u32 status; /* status of this request */ u32 fsf_command; /* FSF Command copy */ struct fsf_qtcb *qtcb; /* address of associated QTCB */ u32 seq_no; /* Sequence number of request */ @@ -644,11 +589,7 @@ struct zfcp_fsf_req { struct zfcp_data { struct scsi_host_template scsi_host_template; struct scsi_transport_template *scsi_transport_template; - atomic_t status; /* Module status flags */ struct list_head adapter_list_head; /* head of adapter list */ - struct list_head adapter_remove_lh; /* head of adapters to be - removed */ - u32 adapters; /* # of adapters in list */ rwlock_t config_lock; /* serialises changes to adapter/port/unit lists */ @@ -656,11 +597,12 @@ struct zfcp_data { changes */ atomic_t loglevel; /* current loglevel */ char init_busid[BUS_ID_SIZE]; - wwn_t init_wwpn; - fcp_lun_t init_fcp_lun; - struct kmem_cache *fsf_req_qtcb_cache; - struct kmem_cache *sr_buffer_cache; - struct kmem_cache *gid_pn_cache; + u64 init_wwpn; + u64 init_fcp_lun; + struct kmem_cache *fsf_req_qtcb_cache; + struct kmem_cache *sr_buffer_cache; + struct kmem_cache *gid_pn_cache; + struct workqueue_struct *work_queue; }; /* struct used by memory pools for fsf_requests */ @@ -677,14 +619,7 @@ struct zfcp_fsf_req_qtcb { #define ZFCP_SET 0x00000100 #define ZFCP_CLEAR 0x00000200 -#ifndef atomic_test_mask -#define atomic_test_mask(mask, target) \ - ((atomic_read(target) & mask) == mask) -#endif - #define zfcp_get_busid_by_adapter(adapter) (adapter->ccw_device->dev.bus_id) -#define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter)) -#define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port)) /* * Helper functions for request ID management. @@ -745,12 +680,6 @@ zfcp_unit_put(struct zfcp_unit *unit) } static inline void -zfcp_unit_wait(struct zfcp_unit *unit) -{ - wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0); -} - -static inline void zfcp_port_get(struct zfcp_port *port) { atomic_inc(&port->refcount); @@ -764,12 +693,6 @@ zfcp_port_put(struct zfcp_port *port) } static inline void -zfcp_port_wait(struct zfcp_port *port) -{ - wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); -} - -static inline void zfcp_adapter_get(struct zfcp_adapter *adapter) { atomic_inc(&adapter->refcount); @@ -782,10 +705,4 @@ zfcp_adapter_put(struct zfcp_adapter *adapter) wake_up(&adapter->remove_wq); } -static inline void -zfcp_adapter_wait(struct zfcp_adapter *adapter) -{ - wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); -} - #endif /* ZFCP_DEF_H */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 643ac4bba5b5..782313131870 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -23,7 +23,6 @@ enum zfcp_erp_steps { ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001, ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010, ZFCP_ERP_STEP_PORT_CLOSING = 0x0100, - ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200, ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400, ZFCP_ERP_STEP_PORT_OPENING = 0x0800, ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000, @@ -532,8 +531,7 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, struct zfcp_port *port; list_for_each_entry(port, &adapter->port_list_head, list) - if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)) - _zfcp_erp_port_reopen(port, clear, id, ref); + _zfcp_erp_port_reopen(port, clear, id, ref); } static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id, @@ -669,8 +667,6 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) int ret; struct zfcp_adapter *adapter = act->adapter; - atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - write_lock_irq(&adapter->erp_lock); zfcp_erp_action_to_running(act); write_unlock_irq(&adapter->erp_lock); @@ -741,8 +737,7 @@ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act, ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); failed_qdio: atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | - ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | - ZFCP_STATUS_ADAPTER_XPORT_OK, + ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &act->adapter->status); return retval; } @@ -751,15 +746,11 @@ static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act) { int retval; - atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); zfcp_erp_adapter_strategy_generic(act, 1); /* close */ - atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status); if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY) return ZFCP_ERP_EXIT; - atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */ - atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status); if (retval == ZFCP_ERP_FAILED) ssleep(8); @@ -783,10 +774,7 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act) static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) { - atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | - ZFCP_STATUS_COMMON_CLOSING | - ZFCP_STATUS_COMMON_ACCESS_DENIED | - ZFCP_STATUS_PORT_DID_DID | + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_PORT_PHYS_CLOSING | ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); @@ -839,73 +827,12 @@ static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) return ZFCP_ERP_CONTINUES; } -static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act) -{ - unsigned long flags; - struct zfcp_adapter *adapter = ns_act->adapter; - struct zfcp_erp_action *act, *tmp; - int status; - - read_lock_irqsave(&adapter->erp_lock, flags); - list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) { - if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) { - status = atomic_read(&adapter->nameserver_port->status); - if (status & ZFCP_STATUS_COMMON_ERP_FAILED) - zfcp_erp_port_failed(act->port, 27, NULL); - zfcp_erp_action_ready(act); - } - } - read_unlock_irqrestore(&adapter->erp_lock, flags); -} - -static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act) -{ - int retval; - - switch (act->step) { - case ZFCP_ERP_STEP_UNINITIALIZED: - case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: - case ZFCP_ERP_STEP_PORT_CLOSING: - return zfcp_erp_port_strategy_open_port(act); - - case ZFCP_ERP_STEP_PORT_OPENING: - if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN) - retval = ZFCP_ERP_SUCCEEDED; - else - retval = ZFCP_ERP_FAILED; - /* this is needed anyway */ - zfcp_erp_port_strategy_open_ns_wake(act); - return retval; - - default: - return ZFCP_ERP_FAILED; - } -} - -static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act) -{ - int retval; - - retval = zfcp_fc_ns_gid_pn_request(act); - if (retval == -ENOMEM) - return ZFCP_ERP_NOMEM; - act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; - if (retval) - return ZFCP_ERP_FAILED; - return ZFCP_ERP_CONTINUES; -} - static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; if (port->wwpn != adapter->peer_wwpn) { - dev_err(&adapter->ccw_device->dev, - "Failed to open port 0x%016Lx, " - "Peer WWPN 0x%016Lx does not " - "match.\n", port->wwpn, - adapter->peer_wwpn); zfcp_erp_port_failed(port, 25, NULL); return ZFCP_ERP_FAILED; } @@ -914,11 +841,25 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act) return zfcp_erp_port_strategy_open_port(act); } +void zfcp_erp_port_strategy_open_lookup(struct work_struct *work) +{ + int retval; + struct zfcp_port *port = container_of(work, struct zfcp_port, + gid_pn_work); + + retval = zfcp_fc_ns_gid_pn(&port->erp_action); + if (retval == -ENOMEM) + zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM); + port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP; + if (retval) + zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED); + +} + static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; - struct zfcp_port *ns_port = adapter->nameserver_port; int p_status = atomic_read(&port->status); switch (act->step) { @@ -927,28 +868,10 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) case ZFCP_ERP_STEP_PORT_CLOSING: if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) return zfcp_erp_open_ptp_port(act); - if (!ns_port) { - dev_err(&adapter->ccw_device->dev, - "Nameserver port unavailable.\n"); - return ZFCP_ERP_FAILED; - } - if (!(atomic_read(&ns_port->status) & - ZFCP_STATUS_COMMON_UNBLOCKED)) { - /* nameserver port may live again */ - atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, - &ns_port->status); - if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) { - act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; - return ZFCP_ERP_CONTINUES; - } - return ZFCP_ERP_FAILED; + if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { + queue_work(zfcp_data.work_queue, &port->gid_pn_work); + return ZFCP_ERP_CONTINUES; } - /* else nameserver port is already open, fall through */ - case ZFCP_ERP_STEP_NAMESERVER_OPEN: - if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN)) - return ZFCP_ERP_FAILED; - return zfcp_erp_port_strategy_open_lookup(act); - case ZFCP_ERP_STEP_NAMESERVER_LOOKUP: if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) { if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) { @@ -961,25 +884,26 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) case ZFCP_ERP_STEP_PORT_OPENING: /* D_ID might have changed during open */ - if ((p_status & ZFCP_STATUS_COMMON_OPEN) && - (p_status & ZFCP_STATUS_PORT_DID_DID)) - return ZFCP_ERP_SUCCEEDED; + if (p_status & ZFCP_STATUS_COMMON_OPEN) { + if (p_status & ZFCP_STATUS_PORT_DID_DID) + return ZFCP_ERP_SUCCEEDED; + else { + act->step = ZFCP_ERP_STEP_PORT_CLOSING; + return ZFCP_ERP_CONTINUES; + } /* fall through otherwise */ + } } return ZFCP_ERP_FAILED; } -static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act) -{ - if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA)) - return zfcp_erp_port_strategy_open_nameserver(act); - return zfcp_erp_port_strategy_open_common(act); -} - static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) { struct zfcp_port *port = erp_action->port; + if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) + goto close_init_done; + switch (erp_action->step) { case ZFCP_ERP_STEP_UNINITIALIZED: zfcp_erp_port_strategy_clearstati(port); @@ -992,19 +916,17 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) return ZFCP_ERP_FAILED; break; } + +close_init_done: if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY) return ZFCP_ERP_EXIT; - else - return zfcp_erp_port_strategy_open(erp_action); - return ZFCP_ERP_FAILED; + return zfcp_erp_port_strategy_open_common(erp_action); } static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) { - atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | - ZFCP_STATUS_COMMON_CLOSING | - ZFCP_STATUS_COMMON_ACCESS_DENIED | + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_UNIT_SHARED | ZFCP_STATUS_UNIT_READONLY, &unit->status); @@ -1065,8 +987,14 @@ static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) break; case ZFCP_ERP_FAILED : atomic_inc(&unit->erp_counter); - if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) + if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) { + dev_err(&unit->port->adapter->ccw_device->dev, + "ERP failed for unit 0x%016Lx on " + "port 0x%016Lx\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_erp_unit_failed(unit, 21, NULL); + } break; } @@ -1091,8 +1019,12 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) result = ZFCP_ERP_EXIT; } atomic_inc(&port->erp_counter); - if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) + if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) { + dev_err(&port->adapter->ccw_device->dev, + "ERP failed for remote port 0x%016Lx\n", + (unsigned long long)port->wwpn); zfcp_erp_port_failed(port, 22, NULL); + } break; } @@ -1114,8 +1046,12 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, case ZFCP_ERP_FAILED : atomic_inc(&adapter->erp_counter); - if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) + if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) { + dev_err(&adapter->ccw_device->dev, + "ERP cannot recover an error " + "on the FCP device\n"); zfcp_erp_adapter_failed(adapter, 23, NULL); + } break; } @@ -1250,9 +1186,10 @@ static void zfcp_erp_scsi_scan(struct work_struct *work) struct zfcp_unit *unit = p->unit; struct fc_rport *rport = unit->port->rport; scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, - unit->scsi_lun, 0); + scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0); atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); zfcp_unit_put(unit); + wake_up(&unit->port->adapter->erp_done_wqh); kfree(p); } @@ -1263,9 +1200,9 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit) p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) { dev_err(&unit->port->adapter->ccw_device->dev, - "Out of resources. Could not register unit " - "0x%016Lx on port 0x%016Lx with SCSI stack.\n", - unit->fcp_lun, unit->port->wwpn); + "Registering unit 0x%016Lx on port 0x%016Lx failed\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); return; } @@ -1273,7 +1210,7 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit) atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); INIT_WORK(&p->work, zfcp_erp_scsi_scan); p->unit = unit; - schedule_work(&p->work); + queue_work(zfcp_data.work_queue, &p->work); } static void zfcp_erp_rport_register(struct zfcp_port *port) @@ -1286,8 +1223,8 @@ static void zfcp_erp_rport_register(struct zfcp_port *port) port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); if (!port->rport) { dev_err(&port->adapter->ccw_device->dev, - "Failed registration of rport " - "0x%016Lx.\n", port->wwpn); + "Registering port 0x%016Lx failed\n", + (unsigned long long)port->wwpn); return; } @@ -1299,12 +1236,12 @@ static void zfcp_erp_rport_register(struct zfcp_port *port) static void zfcp_erp_rports_del(struct zfcp_adapter *adapter) { struct zfcp_port *port; - list_for_each_entry(port, &adapter->port_list_head, list) - if (port->rport && !(atomic_read(&port->status) & - ZFCP_STATUS_PORT_WKA)) { - fc_remote_port_delete(port->rport); - port->rport = NULL; - } + list_for_each_entry(port, &adapter->port_list_head, list) { + if (!port->rport) + continue; + fc_remote_port_delete(port->rport); + port->rport = NULL; + } } static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) @@ -1459,9 +1396,9 @@ static int zfcp_erp_thread(void *data) zfcp_erp_wakeup(adapter); } - zfcp_rec_dbf_event_thread(4, adapter); + zfcp_rec_dbf_event_thread_lock(4, adapter); down_interruptible(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread(5, adapter); + zfcp_rec_dbf_event_thread_lock(5, adapter); } atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); @@ -1484,7 +1421,7 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter) retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); if (retval < 0) { dev_err(&adapter->ccw_device->dev, - "Creation of ERP thread failed.\n"); + "Creating an ERP thread for the FCP device failed.\n"); return retval; } wait_event(adapter->erp_thread_wqh, @@ -1506,7 +1443,7 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter) { atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status); up(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread_lock(2, adapter); + zfcp_rec_dbf_event_thread_lock(3, adapter); wait_event(adapter->erp_thread_wqh, !(atomic_read(&adapter->status) & @@ -1526,7 +1463,6 @@ void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref) { zfcp_erp_modify_adapter_status(adapter, id, ref, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); - dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n"); } /** @@ -1539,15 +1475,6 @@ void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref) { zfcp_erp_modify_port_status(port, id, ref, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); - - if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) - dev_err(&port->adapter->ccw_device->dev, - "Port ERP failed for WKA port d_id=0x%06x.\n", - port->d_id); - else - dev_err(&port->adapter->ccw_device->dev, - "Port ERP failed for port wwpn=0x%016Lx.\n", - port->wwpn); } /** @@ -1560,10 +1487,6 @@ void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref) { zfcp_erp_modify_unit_status(unit, id, ref, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); - - dev_err(&unit->port->adapter->ccw_device->dev, - "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n", - unit->fcp_lun, unit->port->wwpn); } /** @@ -1754,9 +1677,8 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_COMMON_ACCESS_BOXED))) { - if (!(status & ZFCP_STATUS_PORT_WKA)) - list_for_each_entry(unit, &port->unit_list_head, list) - zfcp_erp_unit_access_changed(unit, id, ref); + list_for_each_entry(unit, &port->unit_list_head, list) + zfcp_erp_unit_access_changed(unit, id, ref); return; } @@ -1779,10 +1701,7 @@ void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id, return; read_lock_irqsave(&zfcp_data.config_lock, flags); - if (adapter->nameserver_port) - zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref); list_for_each_entry(port, &adapter->port_list_head, list) - if (port != adapter->nameserver_port) - zfcp_erp_port_access_changed(port, id, ref); + zfcp_erp_port_access_changed(port, id, ref); read_unlock_irqrestore(&zfcp_data.config_lock, flags); } diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index edfdb21591f3..b5adeda93e1d 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -12,16 +12,14 @@ #include "zfcp_def.h" /* zfcp_aux.c */ -extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, - fcp_lun_t); -extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, - wwn_t); +extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); +extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); extern int zfcp_adapter_enqueue(struct ccw_device *); extern void zfcp_adapter_dequeue(struct zfcp_adapter *); -extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32, +extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, u32); extern void zfcp_port_dequeue(struct zfcp_port *); -extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t); +extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); extern void zfcp_unit_dequeue(struct zfcp_unit *); extern int zfcp_reqlist_isempty(struct zfcp_adapter *); extern void zfcp_sg_free_table(struct scatterlist *, int); @@ -29,6 +27,7 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int); /* zfcp_ccw.c */ extern int zfcp_ccw_register(void); +extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *); /* zfcp_cfdc.c */ extern struct miscdevice zfcp_cfdc_misc; @@ -50,6 +49,8 @@ extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *, struct fsf_status_read_buffer *); extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int, int); +extern void zfcp_hba_dbf_event_berr(struct zfcp_adapter *, + struct zfcp_fsf_req *); extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *); extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *); extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *); @@ -91,17 +92,21 @@ extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8, void *); extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8, void *); extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *); extern void zfcp_erp_timeout_handler(unsigned long); +extern void zfcp_erp_port_strategy_open_lookup(struct work_struct *); /* zfcp_fc.c */ extern int zfcp_scan_ports(struct zfcp_adapter *); extern void _zfcp_scan_ports_later(struct work_struct *); extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); -extern int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *); +extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *); extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); extern void zfcp_test_link(struct zfcp_port *); +extern void zfcp_fc_nameserver_init(struct zfcp_adapter *); /* zfcp_fsf.c */ extern int zfcp_fsf_open_port(struct zfcp_erp_action *); +extern int zfcp_fsf_open_wka_port(struct zfcp_wka_port *); +extern int zfcp_fsf_close_wka_port(struct zfcp_wka_port *); extern int zfcp_fsf_close_port(struct zfcp_erp_action *); extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *); extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); @@ -135,10 +140,8 @@ extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long, extern int zfcp_qdio_allocate(struct zfcp_adapter *); extern void zfcp_qdio_free(struct zfcp_adapter *); extern int zfcp_qdio_send(struct zfcp_fsf_req *); -extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req( - struct zfcp_fsf_req *); -extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_curr( - struct zfcp_fsf_req *); +extern struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *); +extern struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *); extern int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *, unsigned long, struct scatterlist *, int); extern int zfcp_qdio_open(struct zfcp_adapter *); @@ -148,14 +151,12 @@ extern void zfcp_qdio_close(struct zfcp_adapter *); extern struct zfcp_data zfcp_data; extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); -extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t); extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); extern struct fc_function_template zfcp_transport_functions; /* zfcp_sysfs.c */ extern struct attribute_group zfcp_sysfs_unit_attrs; extern struct attribute_group zfcp_sysfs_adapter_attrs; -extern struct attribute_group zfcp_sysfs_ns_port_attrs; extern struct attribute_group zfcp_sysfs_port_attrs; extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; extern struct device_attribute *zfcp_sysfs_shost_attrs[]; diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 56196c98c07b..1a7c80a77ff5 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -39,6 +39,84 @@ struct zfcp_gpn_ft { struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS]; }; +struct zfcp_fc_ns_handler_data { + struct completion done; + void (*handler)(unsigned long); + unsigned long handler_data; +}; + +static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port) +{ + if (mutex_lock_interruptible(&wka_port->mutex)) + return -ERESTARTSYS; + + if (wka_port->status != ZFCP_WKA_PORT_ONLINE) { + wka_port->status = ZFCP_WKA_PORT_OPENING; + if (zfcp_fsf_open_wka_port(wka_port)) + wka_port->status = ZFCP_WKA_PORT_OFFLINE; + } + + mutex_unlock(&wka_port->mutex); + + wait_event_timeout( + wka_port->completion_wq, + wka_port->status == ZFCP_WKA_PORT_ONLINE || + wka_port->status == ZFCP_WKA_PORT_OFFLINE, + HZ >> 1); + + if (wka_port->status == ZFCP_WKA_PORT_ONLINE) { + atomic_inc(&wka_port->refcount); + return 0; + } + return -EIO; +} + +static void zfcp_wka_port_offline(struct work_struct *work) +{ + struct delayed_work *dw = container_of(work, struct delayed_work, work); + struct zfcp_wka_port *wka_port = + container_of(dw, struct zfcp_wka_port, work); + + wait_event(wka_port->completion_wq, + atomic_read(&wka_port->refcount) == 0); + + mutex_lock(&wka_port->mutex); + if ((atomic_read(&wka_port->refcount) != 0) || + (wka_port->status != ZFCP_WKA_PORT_ONLINE)) + goto out; + + wka_port->status = ZFCP_WKA_PORT_CLOSING; + if (zfcp_fsf_close_wka_port(wka_port)) { + wka_port->status = ZFCP_WKA_PORT_OFFLINE; + wake_up(&wka_port->completion_wq); + } +out: + mutex_unlock(&wka_port->mutex); +} + +static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port) +{ + if (atomic_dec_return(&wka_port->refcount) != 0) + return; + /* wait 10 miliseconds, other reqs might pop in */ + schedule_delayed_work(&wka_port->work, HZ / 100); +} + +void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter) +{ + struct zfcp_wka_port *wka_port = &adapter->nsp; + + init_waitqueue_head(&wka_port->completion_wq); + + wka_port->adapter = adapter; + wka_port->d_id = ZFCP_DID_DIRECTORY_SERVICE; + + wka_port->status = ZFCP_WKA_PORT_OFFLINE; + atomic_set(&wka_port->refcount, 0); + mutex_init(&wka_port->mutex); + INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline); +} + static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, struct fcp_rscn_element *elem) { @@ -47,10 +125,8 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { - if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) - continue; /* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */ - if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status)) + if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID)) /* Try to connect to unused ports anyway. */ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, @@ -102,7 +178,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) schedule_work(&fsf_req->adapter->scan_work); } -static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, wwn_t wwpn) +static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) { struct zfcp_adapter *adapter = req->adapter; struct zfcp_port *port; @@ -157,7 +233,18 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) zfcp_fc_incoming_rscn(fsf_req); } -static void zfcp_ns_gid_pn_handler(unsigned long data) +static void zfcp_fc_ns_handler(unsigned long data) +{ + struct zfcp_fc_ns_handler_data *compl_rec = + (struct zfcp_fc_ns_handler_data *) data; + + if (compl_rec->handler) + compl_rec->handler(compl_rec->handler_data); + + complete(&compl_rec->done); +} + +static void zfcp_fc_ns_gid_pn_eval(unsigned long data) { struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data; struct zfcp_send_ct *ct = &gid_pn->ct; @@ -166,43 +253,31 @@ static void zfcp_ns_gid_pn_handler(unsigned long data) struct zfcp_port *port = gid_pn->port; if (ct->status) - goto out; + return; if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); - goto out; + return; } /* paranoia */ if (ct_iu_req->wwpn != port->wwpn) - goto out; + return; /* looks like a valid d_id */ port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); -out: - mempool_free(gid_pn, port->adapter->pool.data_gid_pn); } -/** - * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request - * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed - * return: -ENOMEM on error, 0 otherwise - */ -int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action) +int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action, + struct zfcp_gid_pn_data *gid_pn) { - int ret; - struct zfcp_gid_pn_data *gid_pn; struct zfcp_adapter *adapter = erp_action->adapter; - - gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC); - if (!gid_pn) - return -ENOMEM; - - memset(gid_pn, 0, sizeof(*gid_pn)); + struct zfcp_fc_ns_handler_data compl_rec; + int ret; /* setup parameters for send generic command */ gid_pn->port = erp_action->port; - gid_pn->ct.port = adapter->nameserver_port; - gid_pn->ct.handler = zfcp_ns_gid_pn_handler; - gid_pn->ct.handler_data = (unsigned long) gid_pn; + gid_pn->ct.wka_port = &adapter->nsp; + gid_pn->ct.handler = zfcp_fc_ns_handler; + gid_pn->ct.handler_data = (unsigned long) &compl_rec; gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; gid_pn->ct.req = &gid_pn->req; gid_pn->ct.resp = &gid_pn->resp; @@ -222,10 +297,42 @@ int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action) gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE; gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn; + init_completion(&compl_rec.done); + compl_rec.handler = zfcp_fc_ns_gid_pn_eval; + compl_rec.handler_data = (unsigned long) gid_pn; ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp, erp_action); + if (!ret) + wait_for_completion(&compl_rec.done); + return ret; +} + +/** + * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request + * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed + * return: -ENOMEM on error, 0 otherwise + */ +int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action) +{ + int ret; + struct zfcp_gid_pn_data *gid_pn; + struct zfcp_adapter *adapter = erp_action->adapter; + + gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC); + if (!gid_pn) + return -ENOMEM; + + memset(gid_pn, 0, sizeof(*gid_pn)); + + ret = zfcp_wka_port_get(&adapter->nsp); if (ret) - mempool_free(gid_pn, adapter->pool.data_gid_pn); + goto out; + + ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn); + + zfcp_wka_port_put(&adapter->nsp); +out: + mempool_free(gid_pn, adapter->pool.data_gid_pn); return ret; } @@ -255,14 +362,14 @@ struct zfcp_els_adisc { struct scatterlist req; struct scatterlist resp; struct zfcp_ls_adisc ls_adisc; - struct zfcp_ls_adisc_acc ls_adisc_acc; + struct zfcp_ls_adisc ls_adisc_acc; }; static void zfcp_fc_adisc_handler(unsigned long data) { struct zfcp_els_adisc *adisc = (struct zfcp_els_adisc *) data; struct zfcp_port *port = adisc->els.port; - struct zfcp_ls_adisc_acc *ls_adisc = &adisc->ls_adisc_acc; + struct zfcp_ls_adisc *ls_adisc = &adisc->ls_adisc_acc; if (adisc->els.status) { /* request rejected or timed out */ @@ -295,7 +402,7 @@ static int zfcp_fc_adisc(struct zfcp_port *port) sg_init_one(adisc->els.req, &adisc->ls_adisc, sizeof(struct zfcp_ls_adisc)); sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc, - sizeof(struct zfcp_ls_adisc_acc)); + sizeof(struct zfcp_ls_adisc)); adisc->els.req_count = 1; adisc->els.resp_count = 1; @@ -338,30 +445,6 @@ void zfcp_test_link(struct zfcp_port *port) zfcp_erp_port_forced_reopen(port, 0, 65, NULL); } -static int zfcp_scan_get_nameserver(struct zfcp_adapter *adapter) -{ - int ret; - - if (!adapter->nameserver_port) - return -EINTR; - - if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, - &adapter->nameserver_port->status)) { - ret = zfcp_erp_port_reopen(adapter->nameserver_port, 0, 148, - NULL); - if (ret) - return ret; - zfcp_erp_wait(adapter); - } - return !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, - &adapter->nameserver_port->status); -} - -static void zfcp_gpn_ft_handler(unsigned long _done) -{ - complete((struct completion *)_done); -} - static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft) { struct scatterlist *sg = &gpn_ft->sg_req; @@ -403,7 +486,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft, { struct zfcp_send_ct *ct = &gpn_ft->ct; struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); - struct completion done; + struct zfcp_fc_ns_handler_data compl_rec; int ret; /* prepare CT IU for GPN_FT */ @@ -420,19 +503,20 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft, req->fc4_type = ZFCP_CT_SCSI_FCP; /* prepare zfcp_send_ct */ - ct->port = adapter->nameserver_port; - ct->handler = zfcp_gpn_ft_handler; - ct->handler_data = (unsigned long)&done; + ct->wka_port = &adapter->nsp; + ct->handler = zfcp_fc_ns_handler; + ct->handler_data = (unsigned long)&compl_rec; ct->timeout = 10; ct->req = &gpn_ft->sg_req; ct->resp = gpn_ft->sg_resp; ct->req_count = 1; ct->resp_count = ZFCP_GPN_FT_BUFFERS; - init_completion(&done); + init_completion(&compl_rec.done); + compl_rec.handler = NULL; ret = zfcp_fsf_send_ct(ct, NULL, NULL); if (!ret) - wait_for_completion(&done); + wait_for_completion(&compl_rec.done); return ret; } @@ -442,9 +526,8 @@ static void zfcp_validate_port(struct zfcp_port *port) atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); - if (port == adapter->nameserver_port) - return; - if ((port->supported_classes != 0) || (port->units != 0)) { + if ((port->supported_classes != 0) || + !list_empty(&port->unit_list_head)) { zfcp_port_put(port); return; } @@ -460,7 +543,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) struct scatterlist *sg = gpn_ft->sg_resp; struct ct_hdr *hdr = sg_virt(sg); struct gpn_ft_resp_acc *acc = sg_virt(sg); - struct zfcp_adapter *adapter = ct->port->adapter; + struct zfcp_adapter *adapter = ct->wka_port->adapter; struct zfcp_port *port, *tmp; u32 d_id; int ret = 0, x, last = 0; @@ -490,6 +573,9 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft) d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 | acc->port_id[2]; + /* don't attach ports with a well known address */ + if ((d_id & ZFCP_DID_WKA) == ZFCP_DID_WKA) + continue; /* skip the adapter's port and known remote ports */ if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) continue; @@ -528,13 +614,15 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) return 0; - ret = zfcp_scan_get_nameserver(adapter); + ret = zfcp_wka_port_get(&adapter->nsp); if (ret) return ret; gpn_ft = zfcp_alloc_sg_env(); - if (!gpn_ft) - return -ENOMEM; + if (!gpn_ft) { + ret = -ENOMEM; + goto out; + } for (i = 0; i < 3; i++) { ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter); @@ -547,7 +635,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) } } zfcp_free_sg_env(gpn_ft); - +out: + zfcp_wka_port_put(&adapter->nsp); return ret; } diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 49dbeb754e5f..739356a5c123 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -50,19 +50,16 @@ static u32 fsf_qtcb_type[] = { [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND }; -static const char *zfcp_act_subtable_type[] = { - "unknown", "OS", "WWPN", "DID", "LUN" -}; - static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table) { u16 subtable = table >> 16; u16 rule = table & 0xffff; + const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" }; - if (subtable && subtable < ARRAY_SIZE(zfcp_act_subtable_type)) + if (subtable && subtable < ARRAY_SIZE(act_type)) dev_warn(&adapter->ccw_device->dev, - "Access denied in subtable %s, rule %d.\n", - zfcp_act_subtable_type[subtable], rule); + "Access denied according to ACT rule type %s, " + "rule %d\n", act_type[subtable], rule); } static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req, @@ -70,8 +67,8 @@ static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req, { struct fsf_qtcb_header *header = &req->qtcb->header; dev_warn(&req->adapter->ccw_device->dev, - "Access denied, cannot send command to port 0x%016Lx.\n", - port->wwpn); + "Access denied to port 0x%016Lx\n", + (unsigned long long)port->wwpn); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); zfcp_erp_port_access_denied(port, 55, req); @@ -83,8 +80,9 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req, { struct fsf_qtcb_header *header = &req->qtcb->header; dev_warn(&req->adapter->ccw_device->dev, - "Access denied for unit 0x%016Lx on port 0x%016Lx.\n", - unit->fcp_lun, unit->port->wwpn); + "Access denied to unit 0x%016Lx on port 0x%016Lx\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]); zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]); zfcp_erp_unit_access_denied(unit, 59, req); @@ -93,9 +91,8 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req, static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) { - dev_err(&req->adapter->ccw_device->dev, - "Required FC class not supported by adapter, " - "shutting down adapter.\n"); + dev_err(&req->adapter->ccw_device->dev, "FCP device not " + "operational because of an unsupported FC class\n"); zfcp_erp_adapter_shutdown(req->adapter, 0, 123, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -171,42 +168,6 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -static void zfcp_fsf_bit_error_threshold(struct zfcp_fsf_req *req) -{ - struct zfcp_adapter *adapter = req->adapter; - struct fsf_status_read_buffer *sr_buf = req->data; - struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error; - - dev_warn(&adapter->ccw_device->dev, - "Warning: bit error threshold data " - "received for the adapter: " - "link failures = %i, loss of sync errors = %i, " - "loss of signal errors = %i, " - "primitive sequence errors = %i, " - "invalid transmission word errors = %i, " - "CRC errors = %i).\n", - err->link_failure_error_count, - err->loss_of_sync_error_count, - err->loss_of_signal_error_count, - err->primitive_sequence_error_count, - err->invalid_transmission_word_error_count, - err->crc_error_count); - dev_warn(&adapter->ccw_device->dev, - "Additional bit error threshold data of the adapter: " - "primitive sequence event time-outs = %i, " - "elastic buffer overrun errors = %i, " - "advertised receive buffer-to-buffer credit = %i, " - "current receice buffer-to-buffer credit = %i, " - "advertised transmit buffer-to-buffer credit = %i, " - "current transmit buffer-to-buffer credit = %i).\n", - err->primitive_sequence_event_timeout_count, - err->elastic_buffer_overrun_error_count, - err->advertised_receive_b2b_credit, - err->current_receive_b2b_credit, - err->advertised_transmit_b2b_credit, - err->current_transmit_b2b_credit); -} - static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id, struct fsf_link_down_info *link_down) { @@ -223,62 +184,66 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id, switch (link_down->error_code) { case FSF_PSQ_LINK_NO_LIGHT: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: no light detected.\n"); + "There is no light signal from the local " + "fibre channel cable\n"); break; case FSF_PSQ_LINK_WRAP_PLUG: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: wrap plug detected.\n"); + "There is a wrap plug instead of a fibre " + "channel cable\n"); break; case FSF_PSQ_LINK_NO_FCP: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: " - "adjacent node on link does not support FCP.\n"); + "The adjacent fibre channel node does not " + "support FCP\n"); break; case FSF_PSQ_LINK_FIRMWARE_UPDATE: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: " - "firmware update in progress.\n"); + "The FCP device is suspended because of a " + "firmware update\n"); break; case FSF_PSQ_LINK_INVALID_WWPN: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: " - "duplicate or invalid WWPN detected.\n"); + "The FCP device detected a WWPN that is " + "duplicate or not valid\n"); break; case FSF_PSQ_LINK_NO_NPIV_SUPPORT: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: " - "no support for NPIV by Fabric.\n"); + "The fibre channel fabric does not support NPIV\n"); break; case FSF_PSQ_LINK_NO_FCP_RESOURCES: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: " - "out of resource in FCP daughtercard.\n"); + "The FCP adapter cannot support more NPIV ports\n"); break; case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: " - "out of resource in Fabric.\n"); + "The adjacent switch cannot support " + "more NPIV ports\n"); break; case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: dev_warn(&req->adapter->ccw_device->dev, - "The local link is down: " - "unable to login to Fabric.\n"); + "The FCP adapter could not log in to the " + "fibre channel fabric\n"); break; case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: dev_warn(&req->adapter->ccw_device->dev, - "WWPN assignment file corrupted on adapter.\n"); + "The WWPN assignment file on the FCP adapter " + "has been damaged\n"); break; case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: dev_warn(&req->adapter->ccw_device->dev, - "Mode table corrupted on adapter.\n"); + "The mode table on the FCP adapter " + "has been damaged\n"); break; case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: dev_warn(&req->adapter->ccw_device->dev, - "No WWPN for assignment table on adapter.\n"); + "All NPIV ports on the FCP adapter have " + "been assigned\n"); break; default: dev_warn(&req->adapter->ccw_device->dev, - "The local link to adapter is down.\n"); + "The link between the FCP adapter and " + "the FC fabric is down\n"); } out: zfcp_erp_adapter_failed(adapter, id, req); @@ -286,27 +251,18 @@ out: static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) { - struct zfcp_adapter *adapter = req->adapter; struct fsf_status_read_buffer *sr_buf = req->data; struct fsf_link_down_info *ldi = (struct fsf_link_down_info *) &sr_buf->payload; switch (sr_buf->status_subtype) { case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: - dev_warn(&adapter->ccw_device->dev, - "Physical link is down.\n"); zfcp_fsf_link_down_info_eval(req, 38, ldi); break; case FSF_STATUS_READ_SUB_FDISC_FAILED: - dev_warn(&adapter->ccw_device->dev, - "Local link is down " - "due to failed FDISC login.\n"); zfcp_fsf_link_down_info_eval(req, 39, ldi); break; case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: - dev_warn(&adapter->ccw_device->dev, - "Local link is down " - "due to firmware update on adapter.\n"); zfcp_fsf_link_down_info_eval(req, 40, NULL); }; } @@ -335,14 +291,17 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) case FSF_STATUS_READ_SENSE_DATA_AVAIL: break; case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: - zfcp_fsf_bit_error_threshold(req); + dev_warn(&adapter->ccw_device->dev, + "The error threshold for checksum statistics " + "has been exceeded\n"); + zfcp_hba_dbf_event_berr(adapter, req); break; case FSF_STATUS_READ_LINK_DOWN: zfcp_fsf_status_read_link_down(req); break; case FSF_STATUS_READ_LINK_UP: dev_info(&adapter->ccw_device->dev, - "Local link was replugged.\n"); + "The local link has been restored\n"); /* All ports should be marked as ready to run again */ zfcp_erp_modify_adapter_status(adapter, 30, NULL, ZFCP_STATUS_COMMON_RUNNING, @@ -370,7 +329,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) zfcp_fsf_req_free(req); atomic_inc(&adapter->stat_miss); - schedule_work(&adapter->stat_work); + queue_work(zfcp_data.work_queue, &adapter->stat_work); } static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) @@ -386,8 +345,8 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) break; case FSF_SQ_NO_RECOM: dev_err(&req->adapter->ccw_device->dev, - "No recommendation could be given for a " - "problem on the adapter.\n"); + "The FCP adapter reported a problem " + "that cannot be recovered\n"); zfcp_erp_adapter_shutdown(req->adapter, 0, 121, req); break; } @@ -403,8 +362,7 @@ static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req) switch (req->qtcb->header.fsf_status) { case FSF_UNKNOWN_COMMAND: dev_err(&req->adapter->ccw_device->dev, - "Command issued by the device driver (0x%x) is " - "not known by the adapter.\n", + "The FCP adapter does not recognize the command 0x%x\n", req->qtcb->header.fsf_command); zfcp_erp_adapter_shutdown(req->adapter, 0, 120, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; @@ -435,11 +393,9 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) return; case FSF_PROT_QTCB_VERSION_ERROR: dev_err(&adapter->ccw_device->dev, - "The QTCB version requested by zfcp (0x%x) is not " - "supported by the FCP adapter (lowest supported " - "0x%x, highest supported 0x%x).\n", - FSF_QTCB_CURRENT_VERSION, psq->word[0], - psq->word[1]); + "QTCB version 0x%x not supported by FCP adapter " + "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION, + psq->word[0], psq->word[1]); zfcp_erp_adapter_shutdown(adapter, 0, 117, req); break; case FSF_PROT_ERROR_STATE: @@ -449,8 +405,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) break; case FSF_PROT_UNSUPP_QTCB_TYPE: dev_err(&adapter->ccw_device->dev, - "Packet header type used by the device driver is " - "incompatible with that used on the adapter.\n"); + "The QTCB type is not supported by the FCP adapter\n"); zfcp_erp_adapter_shutdown(adapter, 0, 118, req); break; case FSF_PROT_HOST_CONNECTION_INITIALIZING: @@ -459,7 +414,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) break; case FSF_PROT_DUPLICATE_REQUEST_ID: dev_err(&adapter->ccw_device->dev, - "The request identifier 0x%Lx is ambiguous.\n", + "0x%Lx is an ambiguous request identifier\n", (unsigned long long)qtcb->bottom.support.req_handle); zfcp_erp_adapter_shutdown(adapter, 0, 78, req); break; @@ -479,9 +434,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) break; default: dev_err(&adapter->ccw_device->dev, - "Transfer protocol status information" - "provided by the adapter (0x%x) " - "is not compatible with the device driver.\n", + "0x%x is not a valid transfer protocol status\n", qtcb->prefix.prot_status); zfcp_erp_adapter_shutdown(adapter, 0, 119, req); } @@ -559,33 +512,17 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) adapter->peer_wwpn = bottom->plogi_payload.wwpn; adapter->peer_wwnn = bottom->plogi_payload.wwnn; fc_host_port_type(shost) = FC_PORTTYPE_PTP; - if (req->erp_action) - dev_info(&adapter->ccw_device->dev, - "Point-to-Point fibrechannel " - "configuration detected.\n"); break; case FSF_TOPO_FABRIC: fc_host_port_type(shost) = FC_PORTTYPE_NPORT; - if (req->erp_action) - dev_info(&adapter->ccw_device->dev, - "Switched fabric fibrechannel " - "network detected.\n"); break; case FSF_TOPO_AL: fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; - dev_err(&adapter->ccw_device->dev, - "Unsupported arbitrated loop fibrechannel " - "topology detected, shutting down " - "adapter.\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 127, req); - return -EIO; default: - fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; dev_err(&adapter->ccw_device->dev, - "The fibrechannel topology reported by the" - " adapter is not known by the zfcp driver," - " shutting down adapter.\n"); - zfcp_erp_adapter_shutdown(adapter, 0, 128, req); + "Unknown or unsupported arbitrated loop " + "fibre channel topology detected\n"); + zfcp_erp_adapter_shutdown(adapter, 0, 127, req); return -EIO; } @@ -616,11 +553,9 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { dev_err(&adapter->ccw_device->dev, - "Maximum QTCB size (%d bytes) allowed by " - "the adapter is lower than the minimum " - "required by the driver (%ld bytes).\n", - bottom->max_qtcb_size, - sizeof(struct fsf_qtcb)); + "FCP adapter maximum QTCB size (%d bytes) " + "is too small\n", + bottom->max_qtcb_size); zfcp_erp_adapter_shutdown(adapter, 0, 129, req); return; } @@ -656,15 +591,15 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) { dev_err(&adapter->ccw_device->dev, - "The adapter only supports newer control block " - "versions, try updated device driver.\n"); + "The FCP adapter only supports newer " + "control block versions\n"); zfcp_erp_adapter_shutdown(adapter, 0, 125, req); return; } if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { dev_err(&adapter->ccw_device->dev, - "The adapter only supports older control block " - "versions, consider a microcode upgrade.\n"); + "The FCP adapter only supports older " + "control block versions\n"); zfcp_erp_adapter_shutdown(adapter, 0, 126, req); } } @@ -688,7 +623,6 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) { - struct zfcp_adapter *adapter = req->adapter; struct fsf_qtcb *qtcb = req->qtcb; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) @@ -697,38 +631,47 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) switch (qtcb->header.fsf_status) { case FSF_GOOD: zfcp_fsf_exchange_port_evaluate(req); - atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: zfcp_fsf_exchange_port_evaluate(req); - atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); zfcp_fsf_link_down_info_eval(req, 43, &qtcb->header.fsf_status_qual.link_down_info); break; } } -static int zfcp_fsf_sbal_check(struct zfcp_qdio_queue *queue) +static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter) { - spin_lock_bh(&queue->lock); - if (atomic_read(&queue->count)) + struct zfcp_qdio_queue *req_q = &adapter->req_q; + + spin_lock_bh(&adapter->req_q_lock); + if (atomic_read(&req_q->count)) return 1; - spin_unlock_bh(&queue->lock); + spin_unlock_bh(&adapter->req_q_lock); return 0; } +static int zfcp_fsf_sbal_available(struct zfcp_adapter *adapter) +{ + unsigned int count = atomic_read(&adapter->req_q.count); + if (!count) + atomic_inc(&adapter->qdio_outb_full); + return count > 0; +} + static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) { long ret; - struct zfcp_qdio_queue *req_q = &adapter->req_q; - spin_unlock_bh(&req_q->lock); + spin_unlock_bh(&adapter->req_q_lock); ret = wait_event_interruptible_timeout(adapter->request_wq, - zfcp_fsf_sbal_check(req_q), 5 * HZ); + zfcp_fsf_sbal_check(adapter), 5 * HZ); if (ret > 0) return 0; + if (!ret) + atomic_inc(&adapter->qdio_outb_full); - spin_lock_bh(&req_q->lock); + spin_lock_bh(&adapter->req_q_lock); return -EIO; } @@ -765,7 +708,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, mempool_t *pool) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req; struct zfcp_qdio_queue *req_q = &adapter->req_q; @@ -867,10 +810,10 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter) { struct zfcp_fsf_req *req; struct fsf_status_read_buffer *sr_buf; - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -910,7 +853,7 @@ failed_buf: zfcp_fsf_req_free(req); zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -980,11 +923,11 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, struct zfcp_unit *unit, int req_flags) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; - spin_lock(&adapter->req_q.lock); - if (!atomic_read(&adapter->req_q.count)) + spin_lock(&adapter->req_q_lock); + if (!zfcp_fsf_sbal_available(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, req_flags, adapter->pool.fsf_req_abort); @@ -1013,7 +956,7 @@ out_error_free: zfcp_fsf_req_free(req); req = NULL; out: - spin_unlock(&adapter->req_q.lock); + spin_unlock(&adapter->req_q_lock); return req; } @@ -1021,7 +964,6 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; struct zfcp_send_ct *send_ct = req->data; - struct zfcp_port *port = send_ct->port; struct fsf_qtcb_header *header = &req->qtcb->header; send_ct->status = -EINVAL; @@ -1040,17 +982,14 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) case FSF_ADAPTER_STATUS_AVAILABLE: switch (header->fsf_status_qual.word[0]){ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: - zfcp_test_link(port); case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; } break; case FSF_ACCESS_DENIED: - zfcp_fsf_access_denied_port(req, port); break; case FSF_PORT_BOXED: - zfcp_erp_port_boxed(port, 49, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; @@ -1101,12 +1040,12 @@ static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req, int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, struct zfcp_erp_action *erp_action) { - struct zfcp_port *port = ct->port; - struct zfcp_adapter *adapter = port->adapter; + struct zfcp_wka_port *wka_port = ct->wka_port; + struct zfcp_adapter *adapter = wka_port->adapter; struct zfcp_fsf_req *req; int ret = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1123,7 +1062,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, goto failed_send; req->handler = zfcp_fsf_send_ct_handler; - req->qtcb->header.port_handle = port->handle; + req->qtcb->header.port_handle = wka_port->handle; req->qtcb->bottom.support.service_class = FSF_CLASS_3; req->qtcb->bottom.support.timeout = ct->timeout; req->data = ct; @@ -1148,7 +1087,7 @@ failed_send: if (erp_action) erp_action->fsf_req = NULL; out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return ret; } @@ -1218,8 +1157,8 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) ZFCP_STATUS_COMMON_UNBLOCKED))) return -EBUSY; - spin_lock(&adapter->req_q.lock); - if (!atomic_read(&adapter->req_q.count)) + spin_lock(&adapter->req_q_lock); + if (!zfcp_fsf_sbal_available(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, ZFCP_REQ_AUTO_CLEANUP, NULL); @@ -1228,8 +1167,8 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) goto out; } - ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, - FSF_MAX_SBALS_PER_ELS_REQ); + ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, 2); + if (ret) goto failed_send; @@ -1252,19 +1191,19 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els) failed_send: zfcp_fsf_req_free(req); out: - spin_unlock(&adapter->req_q.lock); + spin_unlock(&adapter->req_q_lock); return ret; } int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req; struct zfcp_adapter *adapter = erp_action->adapter; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); - if (!atomic_read(&adapter->req_q.count)) + spin_lock_bh(&adapter->req_q_lock); + if (!zfcp_fsf_sbal_available(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, @@ -1295,18 +1234,18 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return retval; } int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, struct fsf_qtcb_bottom_config *data) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1334,7 +1273,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); if (!retval) wait_event(req->completion_wq, req->status & ZFCP_STATUS_FSFREQ_COMPLETED); @@ -1351,7 +1290,7 @@ out: */ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req; struct zfcp_adapter *adapter = erp_action->adapter; int retval = -EIO; @@ -1359,8 +1298,8 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) return -EOPNOTSUPP; - spin_lock_bh(&adapter->req_q.lock); - if (!atomic_read(&adapter->req_q.count)) + spin_lock_bh(&adapter->req_q_lock); + if (!zfcp_fsf_sbal_available(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, ZFCP_REQ_AUTO_CLEANUP, @@ -1385,7 +1324,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -1398,15 +1337,15 @@ out: int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, struct fsf_qtcb_bottom_port *data) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; int retval = -EIO; if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) return -EOPNOTSUPP; - spin_lock_bh(&adapter->req_q.lock); - if (!atomic_read(&adapter->req_q.count)) + spin_lock_bh(&adapter->req_q_lock); + if (!zfcp_fsf_sbal_available(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, @@ -1427,7 +1366,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); if (!retval) wait_event(req->completion_wq, req->status & ZFCP_STATUS_FSFREQ_COMPLETED); @@ -1443,7 +1382,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) struct fsf_plogi *plogi; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) - goto skip_fsfstatus; + return; switch (header->fsf_status) { case FSF_PORT_ALREADY_OPEN: @@ -1453,9 +1392,9 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) break; case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: dev_warn(&req->adapter->ccw_device->dev, - "The adapter is out of resources. The remote port " - "0x%016Lx could not be opened, disabling it.\n", - port->wwpn); + "Not enough FCP adapter resources to open " + "remote port 0x%016Lx\n", + (unsigned long long)port->wwpn); zfcp_erp_port_failed(port, 31, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -1467,8 +1406,8 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) break; case FSF_SQ_NO_RETRY_POSSIBLE: dev_warn(&req->adapter->ccw_device->dev, - "The remote port 0x%016Lx could not be " - "opened. Disabling it.\n", port->wwpn); + "Remote port 0x%016Lx could not be opened\n", + (unsigned long long)port->wwpn); zfcp_erp_port_failed(port, 32, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -1496,9 +1435,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) * another GID_PN straight after a port has been opened. * Alternately, an ADISC/PDISC ELS should suffice, as well. */ - if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN) - break; - plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) { if (plogi->serv_param.wwpn != port->wwpn) @@ -1514,9 +1450,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; } - -skip_fsfstatus: - atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &port->status); } /** @@ -1526,12 +1459,12 @@ skip_fsfstatus: */ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1553,7 +1486,6 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) req->data = erp_action->port; req->erp_action = erp_action; erp_action->fsf_req = req; - atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); zfcp_fsf_start_erp_timer(req); retval = zfcp_fsf_req_send(req); @@ -1562,7 +1494,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -1571,7 +1503,7 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) struct zfcp_port *port = req->data; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) - goto skip_fsfstatus; + return; switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: @@ -1586,9 +1518,6 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) ZFCP_CLEAR); break; } - -skip_fsfstatus: - atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &port->status); } /** @@ -1598,12 +1527,12 @@ skip_fsfstatus: */ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1624,7 +1553,6 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) req->erp_action = erp_action; req->qtcb->header.port_handle = erp_action->port->handle; erp_action->fsf_req = req; - atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); zfcp_fsf_start_erp_timer(req); retval = zfcp_fsf_req_send(req); @@ -1633,7 +1561,131 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); + return retval; +} + +static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req) +{ + struct zfcp_wka_port *wka_port = req->data; + struct fsf_qtcb_header *header = &req->qtcb->header; + + if (req->status & ZFCP_STATUS_FSFREQ_ERROR) { + wka_port->status = ZFCP_WKA_PORT_OFFLINE; + goto out; + } + + switch (header->fsf_status) { + case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: + dev_warn(&req->adapter->ccw_device->dev, + "Opening WKA port 0x%x failed\n", wka_port->d_id); + case FSF_ADAPTER_STATUS_AVAILABLE: + req->status |= ZFCP_STATUS_FSFREQ_ERROR; + case FSF_ACCESS_DENIED: + wka_port->status = ZFCP_WKA_PORT_OFFLINE; + break; + case FSF_PORT_ALREADY_OPEN: + case FSF_GOOD: + wka_port->handle = header->port_handle; + wka_port->status = ZFCP_WKA_PORT_ONLINE; + } +out: + wake_up(&wka_port->completion_wq); +} + +/** + * zfcp_fsf_open_wka_port - create and send open wka-port request + * @wka_port: pointer to struct zfcp_wka_port + * Returns: 0 on success, error otherwise + */ +int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port) +{ + struct qdio_buffer_element *sbale; + struct zfcp_adapter *adapter = wka_port->adapter; + struct zfcp_fsf_req *req; + int retval = -EIO; + + spin_lock_bh(&adapter->req_q_lock); + if (zfcp_fsf_req_sbal_get(adapter)) + goto out; + + req = zfcp_fsf_req_create(adapter, + FSF_QTCB_OPEN_PORT_WITH_DID, + ZFCP_REQ_AUTO_CLEANUP, + adapter->pool.fsf_req_erp); + if (unlikely(IS_ERR(req))) { + retval = PTR_ERR(req); + goto out; + } + + sbale = zfcp_qdio_sbale_req(req); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + + req->handler = zfcp_fsf_open_wka_port_handler; + req->qtcb->bottom.support.d_id = wka_port->d_id; + req->data = wka_port; + + zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); + retval = zfcp_fsf_req_send(req); + if (retval) + zfcp_fsf_req_free(req); +out: + spin_unlock_bh(&adapter->req_q_lock); + return retval; +} + +static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) +{ + struct zfcp_wka_port *wka_port = req->data; + + if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { + req->status |= ZFCP_STATUS_FSFREQ_ERROR; + zfcp_erp_adapter_reopen(wka_port->adapter, 0, 84, req); + } + + wka_port->status = ZFCP_WKA_PORT_OFFLINE; + wake_up(&wka_port->completion_wq); +} + +/** + * zfcp_fsf_close_wka_port - create and send close wka port request + * @erp_action: pointer to struct zfcp_erp_action + * Returns: 0 on success, error otherwise + */ +int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port) +{ + struct qdio_buffer_element *sbale; + struct zfcp_adapter *adapter = wka_port->adapter; + struct zfcp_fsf_req *req; + int retval = -EIO; + + spin_lock_bh(&adapter->req_q_lock); + if (zfcp_fsf_req_sbal_get(adapter)) + goto out; + + req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT, + ZFCP_REQ_AUTO_CLEANUP, + adapter->pool.fsf_req_erp); + if (unlikely(IS_ERR(req))) { + retval = PTR_ERR(req); + goto out; + } + + sbale = zfcp_qdio_sbale_req(req); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + + req->handler = zfcp_fsf_close_wka_port_handler; + req->data = wka_port; + req->qtcb->header.port_handle = wka_port->handle; + + zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); + retval = zfcp_fsf_req_send(req); + if (retval) + zfcp_fsf_req_free(req); +out: + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -1695,12 +1747,12 @@ skip_fsfstatus: */ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1731,7 +1783,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -1746,7 +1798,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) int exclusive, readwrite; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) - goto skip_fsfstatus; + return; atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_COMMON_ACCESS_BOXED | @@ -1774,14 +1826,12 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) case FSF_LUN_SHARING_VIOLATION: if (header->fsf_status_qual.word[0]) dev_warn(&adapter->ccw_device->dev, - "FCP-LUN 0x%Lx at the remote port " - "with WWPN 0x%Lx " - "connected to the adapter " - "is already in use in LPAR%d, CSS%d.\n", - unit->fcp_lun, - unit->port->wwpn, - queue_designator->hla, - queue_designator->cssid); + "LUN 0x%Lx on port 0x%Lx is already in " + "use by CSS%d, MIF Image ID %x\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn, + queue_designator->cssid, + queue_designator->hla); else zfcp_act_eval_err(adapter, header->fsf_status_qual.word[2]); @@ -1792,9 +1842,10 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) break; case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED: dev_warn(&adapter->ccw_device->dev, - "The adapter ran out of resources. There is no " - "handle available for unit 0x%016Lx on port 0x%016Lx.", - unit->fcp_lun, unit->port->wwpn); + "No handle is available for LUN " + "0x%016Lx on port 0x%016Lx\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_erp_unit_failed(unit, 34, req); /* fall through */ case FSF_INVALID_COMMAND_OPTION: @@ -1831,26 +1882,29 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); dev_info(&adapter->ccw_device->dev, - "Read-only access for unit 0x%016Lx " - "on port 0x%016Lx.\n", - unit->fcp_lun, unit->port->wwpn); + "SCSI device at LUN 0x%016Lx on port " + "0x%016Lx opened read-only\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); } if (exclusive && !readwrite) { dev_err(&adapter->ccw_device->dev, - "Exclusive access of read-only unit " - "0x%016Lx on port 0x%016Lx not " - "supported, disabling unit.\n", - unit->fcp_lun, unit->port->wwpn); + "Exclusive read-only access not " + "supported (unit 0x%016Lx, " + "port 0x%016Lx)\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_erp_unit_failed(unit, 35, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; zfcp_erp_unit_shutdown(unit, 0, 80, req); } else if (!exclusive && readwrite) { dev_err(&adapter->ccw_device->dev, - "Shared access of read-write unit " - "0x%016Lx on port 0x%016Lx not " - "supported, disabling unit.\n", - unit->fcp_lun, unit->port->wwpn); + "Shared read-write access not " + "supported (unit 0x%016Lx, port " + "0x%016Lx\n)", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_erp_unit_failed(unit, 36, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; zfcp_erp_unit_shutdown(unit, 0, 81, req); @@ -1858,9 +1912,6 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req) } break; } - -skip_fsfstatus: - atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status); } /** @@ -1870,12 +1921,12 @@ skip_fsfstatus: */ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -1901,8 +1952,6 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; - atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); - zfcp_fsf_start_erp_timer(req); retval = zfcp_fsf_req_send(req); if (retval) { @@ -1910,7 +1959,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -1919,7 +1968,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) struct zfcp_unit *unit = req->data; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) - goto skip_fsfstatus; + return; switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: @@ -1949,8 +1998,6 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req) atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); break; } -skip_fsfstatus: - atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &unit->status); } /** @@ -1960,12 +2007,12 @@ skip_fsfstatus: */ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_fsf_req *req; int retval = -EIO; - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN, @@ -1986,7 +2033,6 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) req->data = erp_action->unit; req->erp_action = erp_action; erp_action->fsf_req = req; - atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); zfcp_fsf_start_erp_timer(req); retval = zfcp_fsf_req_send(req); @@ -1995,7 +2041,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req = NULL; } out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -2156,21 +2202,21 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req) break; case FSF_DIRECTION_INDICATOR_NOT_VALID: dev_err(&req->adapter->ccw_device->dev, - "Invalid data direction (%d) given for unit " - "0x%016Lx on port 0x%016Lx, shutting down " - "adapter.\n", + "Incorrect direction %d, unit 0x%016Lx on port " + "0x%016Lx closed\n", req->qtcb->bottom.io.data_direction, - unit->fcp_lun, unit->port->wwpn); + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_CMND_LENGTH_NOT_VALID: dev_err(&req->adapter->ccw_device->dev, - "An invalid control-data-block length field (%d) " - "was found in a command for unit 0x%016Lx on port " - "0x%016Lx. Shutting down adapter.\n", + "Incorrect CDB length %d, unit 0x%016Lx on " + "port 0x%016Lx closed\n", req->qtcb->bottom.io.fcp_cmnd_length, - unit->fcp_lun, unit->port->wwpn); + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, req); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -2201,6 +2247,20 @@ skip_fsfstatus: } } +static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl) +{ + u32 *fcp_dl_ptr; + + /* + * fcp_dl_addr = start address of fcp_cmnd structure + + * size of fixed part + size of dynamically sized add_dcp_cdb field + * SEE FCP-2 documentation + */ + fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] + + (fcp_cmd->add_fcp_cdb_length << 2)); + *fcp_dl_ptr = fcp_dl; +} + /** * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) * @adapter: adapter where scsi command is issued @@ -2223,8 +2283,8 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, ZFCP_STATUS_COMMON_UNBLOCKED))) return -EBUSY; - spin_lock(&adapter->req_q.lock); - if (!atomic_read(&adapter->req_q.count)) + spin_lock(&adapter->req_q_lock); + if (!zfcp_fsf_sbal_available(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, adapter->pool.fsf_req_scsi); @@ -2286,7 +2346,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + - fcp_cmnd_iu->add_fcp_cdb_length + sizeof(fcp_dl_t); + fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32); real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype, scsi_sglist(scsi_cmnd), @@ -2296,10 +2356,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, retval = -EIO; else { dev_err(&adapter->ccw_device->dev, - "SCSI request too large. " - "Shutting down unit 0x%016Lx on port " - "0x%016Lx.\n", unit->fcp_lun, - unit->port->wwpn); + "Oversize data package, unit 0x%016Lx " + "on port 0x%016Lx closed\n", + (unsigned long long)unit->fcp_lun, + (unsigned long long)unit->port->wwpn); zfcp_erp_unit_shutdown(unit, 0, 131, req); retval = -EINVAL; } @@ -2322,7 +2382,7 @@ failed_scsi_cmnd: zfcp_fsf_req_free(req); scsi_cmnd->host_scribble = NULL; out: - spin_unlock(&adapter->req_q.lock); + spin_unlock(&adapter->req_q_lock); return retval; } @@ -2338,7 +2398,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, struct zfcp_unit *unit, u8 tm_flags, int req_flags) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; struct fcp_cmnd_iu *fcp_cmnd_iu; @@ -2346,8 +2406,8 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, ZFCP_STATUS_COMMON_UNBLOCKED))) return NULL; - spin_lock(&adapter->req_q.lock); - if (!atomic_read(&adapter->req_q.count)) + spin_lock(&adapter->req_q_lock); + if (!zfcp_fsf_sbal_available(adapter)) goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, adapter->pool.fsf_req_scsi); @@ -2362,7 +2422,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; req->qtcb->bottom.io.service_class = FSF_CLASS_3; req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) + - sizeof(fcp_dl_t); + sizeof(u32); sbale = zfcp_qdio_sbale_req(req); sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; @@ -2379,7 +2439,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, zfcp_fsf_req_free(req); req = NULL; out: - spin_unlock(&adapter->req_q.lock); + spin_unlock(&adapter->req_q_lock); return req; } @@ -2398,7 +2458,7 @@ static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req) struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, struct zfcp_fsf_cfdc *fsf_cfdc) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; struct zfcp_fsf_req *req = NULL; struct fsf_qtcb_bottom_support *bottom; int direction, retval = -EIO, bytes; @@ -2417,7 +2477,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, return ERR_PTR(-EINVAL); } - spin_lock_bh(&adapter->req_q.lock); + spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) goto out; @@ -2447,7 +2507,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); out: - spin_unlock_bh(&adapter->req_q.lock); + spin_unlock_bh(&adapter->req_q_lock); if (!retval) { wait_event(req->completion_wq, diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index bf94b4da0763..fd3a88777ac8 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -71,13 +71,6 @@ #define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED 0x00000041 #define FSF_ELS_COMMAND_REJECTED 0x00000050 #define FSF_GENERIC_COMMAND_REJECTED 0x00000051 -#define FSF_OPERATION_PARTIALLY_SUCCESSFUL 0x00000052 -#define FSF_AUTHORIZATION_FAILURE 0x00000053 -#define FSF_CFDC_ERROR_DETECTED 0x00000054 -#define FSF_CONTROL_FILE_UPDATE_ERROR 0x00000055 -#define FSF_CONTROL_FILE_TOO_LARGE 0x00000056 -#define FSF_ACCESS_CONFLICT_DETECTED 0x00000057 -#define FSF_CONFLICTS_OVERRULED 0x00000058 #define FSF_PORT_BOXED 0x00000059 #define FSF_LUN_BOXED 0x0000005A #define FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE 0x0000005B @@ -85,9 +78,7 @@ #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 #define FSF_SBAL_MISMATCH 0x00000063 -#define FSF_OPEN_PORT_WITHOUT_PRLI 0x00000064 #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD -#define FSF_FCP_RSP_AVAILABLE 0x000000AF #define FSF_UNKNOWN_COMMAND 0x000000E2 #define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3 #define FSF_INVALID_COMMAND_OPTION 0x000000E5 @@ -102,20 +93,9 @@ #define FSF_SQ_RETRY_IF_POSSIBLE 0x02 #define FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED 0x03 #define FSF_SQ_INVOKE_LINK_TEST_PROCEDURE 0x04 -#define FSF_SQ_ULP_PROGRAMMING_ERROR 0x05 #define FSF_SQ_COMMAND_ABORTED 0x06 #define FSF_SQ_NO_RETRY_POSSIBLE 0x07 -/* FSF status qualifier for CFDC commands */ -#define FSF_SQ_CFDC_HARDENED_ON_SE 0x00000000 -#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE 0x00000001 -#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2 0x00000002 -/* CFDC subtable codes */ -#define FSF_SQ_CFDC_SUBTABLE_OS 0x0001 -#define FSF_SQ_CFDC_SUBTABLE_PORT_WWPN 0x0002 -#define FSF_SQ_CFDC_SUBTABLE_PORT_DID 0x0003 -#define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 - /* FSF status qualifier (most significant 4 bytes), local link down */ #define FSF_PSQ_LINK_NO_LIGHT 0x00000004 #define FSF_PSQ_LINK_WRAP_PLUG 0x00000008 @@ -145,7 +125,6 @@ #define FSF_STATUS_READ_LINK_UP 0x00000006 #define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009 #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A -#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C /* status subtypes in status read buffer */ @@ -159,20 +138,9 @@ /* status subtypes for unsolicited status notification lost */ #define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001 -#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002 -#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004 -#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008 -#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010 #define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020 -#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040 -#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080 - -/* status subtypes for CFDC */ -#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 -#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F /* topologie that is detected by the adapter */ -#define FSF_TOPO_ERROR 0x00000000 #define FSF_TOPO_P2P 0x00000001 #define FSF_TOPO_FABRIC 0x00000002 #define FSF_TOPO_AL 0x00000003 @@ -180,17 +148,13 @@ /* data direction for FCP commands */ #define FSF_DATADIR_WRITE 0x00000001 #define FSF_DATADIR_READ 0x00000002 -#define FSF_DATADIR_READ_WRITE 0x00000003 #define FSF_DATADIR_CMND 0x00000004 /* fc service class */ -#define FSF_CLASS_1 0x00000001 -#define FSF_CLASS_2 0x00000002 #define FSF_CLASS_3 0x00000003 /* SBAL chaining */ #define FSF_MAX_SBALS_PER_REQ 36 -#define FSF_MAX_SBALS_PER_ELS_REQ 2 /* logging space behind QTCB */ #define FSF_QTCB_LOG_SIZE 1024 @@ -200,50 +164,16 @@ #define FSF_FEATURE_LUN_SHARING 0x00000004 #define FSF_FEATURE_NOTIFICATION_LOST 0x00000008 #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 -#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 #define FSF_FEATURE_UPDATE_ALERT 0x00000100 #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 /* host connection features */ #define FSF_FEATURE_NPIV_MODE 0x00000001 -#define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002 /* option */ #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 -#define FSF_OPEN_LUN_REPLICATE_SENSE 0x00000002 - -/* adapter types */ -#define FSF_ADAPTER_TYPE_FICON 0x00000001 -#define FSF_ADAPTER_TYPE_FICON_EXPRESS 0x00000002 - -/* port types */ -#define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001 -#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003 -#define FSF_HBA_PORTTYPE_NPORT 0x00000005 -#define FSF_HBA_PORTTYPE_PTP 0x00000021 -/* following are not defined and used by FSF Spec - but are additionally defined by FC-HBA */ -#define FSF_HBA_PORTTYPE_OTHER 0x00000002 -#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003 -#define FSF_HBA_PORTTYPE_NLPORT 0x00000006 -#define FSF_HBA_PORTTYPE_FLPORT 0x00000007 -#define FSF_HBA_PORTTYPE_FPORT 0x00000008 -#define FSF_HBA_PORTTYPE_LPORT 0x00000020 - -/* port states */ -#define FSF_HBA_PORTSTATE_UNKNOWN 0x00000001 -#define FSF_HBA_PORTSTATE_ONLINE 0x00000002 -#define FSF_HBA_PORTSTATE_OFFLINE 0x00000003 -#define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006 -#define FSF_HBA_PORTSTATE_ERROR 0x00000007 - -/* IO states of adapter */ -#define FSF_IOSTAT_NPORT_RJT 0x00000004 -#define FSF_IOSTAT_FABRIC_RJT 0x00000005 -#define FSF_IOSTAT_LS_RJT 0x00000009 /* open LUN access flags*/ -#define FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED 0x01000000 #define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000 #define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000 @@ -265,11 +195,6 @@ struct fsf_queue_designator { u32 res1; } __attribute__ ((packed)); -struct fsf_port_closed_payload { - struct fsf_queue_designator queue_designator; - u32 port_handle; -} __attribute__ ((packed)); - struct fsf_bit_error_payload { u32 res1; u32 link_failure_error_count; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 69d632d851d9..3e05080e62d4 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -28,7 +28,7 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) return 0; } -static volatile struct qdio_buffer_element * +static struct qdio_buffer_element * zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx) { return &q->sbal[sbal_idx]->element[sbale_idx]; @@ -57,7 +57,7 @@ void zfcp_qdio_free(struct zfcp_adapter *adapter) static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id) { - dev_warn(&adapter->ccw_device->dev, "QDIO problem occurred.\n"); + dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n"); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | @@ -145,7 +145,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, { struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm; struct zfcp_qdio_queue *queue = &adapter->resp_q; - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; int sbal_idx, sbale_idx, sbal_no; if (unlikely(qdio_err)) { @@ -174,8 +174,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY))) dev_warn(&adapter->ccw_device->dev, - "Protocol violation by adapter. " - "Continuing operations.\n"); + "A QDIO protocol error occurred, " + "operations continue\n"); } /* @@ -190,8 +190,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, * @fsf_req: pointer to struct fsf_req * Returns: pointer to qdio_buffer_element (SBALE) structure */ -volatile struct qdio_buffer_element * -zfcp_qdio_sbale_req(struct zfcp_fsf_req *req) +struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req) { return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0); } @@ -201,8 +200,7 @@ zfcp_qdio_sbale_req(struct zfcp_fsf_req *req) * @fsf_req: pointer to struct fsf_req * Returns: pointer to qdio_buffer_element (SBALE) structure */ -volatile struct qdio_buffer_element * -zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req) +struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req) { return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, req->sbale_curr); @@ -216,10 +214,10 @@ static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) % QDIO_MAX_BUFFERS_PER_Q; } -static volatile struct qdio_buffer_element * +static struct qdio_buffer_element * zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; /* set last entry flag in current SBALE of current SBAL */ sbale = zfcp_qdio_sbale_curr(fsf_req); @@ -250,7 +248,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) return sbale; } -static volatile struct qdio_buffer_element * +static struct qdio_buffer_element * zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) { if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) @@ -273,7 +271,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req, unsigned int sbtype, void *start_addr, unsigned int total_length) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; unsigned long remaining, length; void *addr; @@ -282,6 +280,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req, addr += length, remaining -= length) { sbale = zfcp_qdio_sbale_next(fsf_req, sbtype); if (!sbale) { + atomic_inc(&fsf_req->adapter->qdio_outb_full); zfcp_qdio_undo_sbals(fsf_req); return -EINVAL; } @@ -307,7 +306,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req, int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, struct scatterlist *sg, int max_sbals) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; int retval, bytes = 0; /* figure out last allowed SBAL */ @@ -344,10 +343,10 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) int first = fsf_req->sbal_first; int count = fsf_req->sbal_number; int retval, pci, pci_batch; - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; /* acknowledgements for transferred buffers */ - pci_batch = req_q->pci_batch + count; + pci_batch = adapter->req_q_pci_batch + count; if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) { pci_batch %= ZFCP_QDIO_PCI_INTERVAL; pci = first + count - (pci_batch + 1); @@ -367,7 +366,7 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req) atomic_sub(count, &req_q->count); req_q->first += count; req_q->first %= QDIO_MAX_BUFFERS_PER_Q; - req_q->pci_batch = pci_batch; + adapter->req_q_pci_batch = pci_batch; return 0; } @@ -418,14 +417,14 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) struct zfcp_qdio_queue *req_q; int first, count; - if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) + if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) return; /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */ req_q = &adapter->req_q; - spin_lock_bh(&req_q->lock); + spin_lock_bh(&adapter->req_q_lock); atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); - spin_unlock_bh(&req_q->lock); + spin_unlock_bh(&adapter->req_q_lock); qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); @@ -438,7 +437,7 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) } req_q->first = 0; atomic_set(&req_q->count, 0); - req_q->pci_batch = 0; + adapter->req_q_pci_batch = 0; adapter->resp_q.first = 0; atomic_set(&adapter->resp_q.count, 0); } @@ -450,23 +449,17 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter) */ int zfcp_qdio_open(struct zfcp_adapter *adapter) { - volatile struct qdio_buffer_element *sbale; + struct qdio_buffer_element *sbale; int cc; - if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) + if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP) return -EIO; - if (qdio_establish(&adapter->qdio_init_data)) { - dev_err(&adapter->ccw_device->dev, - "Establish of QDIO queues failed.\n"); - return -EIO; - } + if (qdio_establish(&adapter->qdio_init_data)) + goto failed_establish; - if (qdio_activate(adapter->ccw_device)) { - dev_err(&adapter->ccw_device->dev, - "Activate of QDIO queues failed.\n"); + if (qdio_activate(adapter->ccw_device)) goto failed_qdio; - } for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) { sbale = &(adapter->resp_q.sbal[cc]->element[0]); @@ -476,20 +469,20 @@ int zfcp_qdio_open(struct zfcp_adapter *adapter) } if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0, - QDIO_MAX_BUFFERS_PER_Q)) { - dev_err(&adapter->ccw_device->dev, - "Init of QDIO response queue failed.\n"); + QDIO_MAX_BUFFERS_PER_Q)) goto failed_qdio; - } /* set index of first avalable SBALS / number of available SBALS */ adapter->req_q.first = 0; atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q); - adapter->req_q.pci_batch = 0; + adapter->req_q_pci_batch = 0; return 0; failed_qdio: qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); +failed_establish: + dev_err(&adapter->ccw_device->dev, + "Setting up the QDIO connection to the FCP adapter failed\n"); return -EIO; } diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index aeae56b00b45..ca8f85f3dad4 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -21,20 +21,6 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) return fcp_sns_info_ptr; } -void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, fcp_dl_t fcp_dl) -{ - fcp_dl_t *fcp_dl_ptr; - - /* - * fcp_dl_addr = start address of fcp_cmnd structure + - * size of fixed part + size of dynamically sized add_dcp_cdb field - * SEE FCP-2 documentation - */ - fcp_dl_ptr = (fcp_dl_t *) ((unsigned char *) &fcp_cmd[1] + - (fcp_cmd->add_fcp_cdb_length << 2)); - *fcp_dl_ptr = fcp_dl; -} - static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; @@ -119,13 +105,17 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter, { struct zfcp_port *port; struct zfcp_unit *unit; + int scsi_lun; list_for_each_entry(port, &adapter->port_list_head, list) { if (!port->rport || (id != port->rport->scsi_target_id)) continue; - list_for_each_entry(unit, &port->unit_list_head, list) - if (lun == unit->scsi_lun) + list_for_each_entry(unit, &port->unit_list_head, list) { + scsi_lun = scsilun_to_int( + (struct scsi_lun *)&unit->fcp_lun); + if (lun == scsi_lun) return unit; + } } return NULL; @@ -183,7 +173,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) return retval; } fsf_req->data = NULL; - fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; /* don't access old fsf_req after releasing the abort_lock */ write_unlock_irqrestore(&adapter->abort_lock, flags); @@ -294,7 +283,8 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) sizeof (struct zfcp_adapter *)); if (!adapter->scsi_host) { dev_err(&adapter->ccw_device->dev, - "registration with SCSI stack failed."); + "Registering the FCP device with the " + "SCSI stack failed\n"); return -EIO; } @@ -312,7 +302,6 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) scsi_host_put(adapter->scsi_host); return -EIO; } - atomic_set_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); return 0; } @@ -336,7 +325,6 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) scsi_remove_host(shost); scsi_host_put(shost); adapter->scsi_host = NULL; - atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); return; } diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 2e85c6c49e7d..2809d789b55c 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -26,9 +26,9 @@ static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n", atomic_read(&adapter->status)); ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n", - adapter->peer_wwnn); + (unsigned long long) adapter->peer_wwnn); ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n", - adapter->peer_wwpn); + (unsigned long long) adapter->peer_wwpn); ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n", adapter->peer_d_id); ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n", @@ -135,8 +135,9 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, { struct zfcp_adapter *adapter = dev_get_drvdata(dev); struct zfcp_port *port; - wwn_t wwpn; + u64 wwpn; int retval = 0; + LIST_HEAD(port_remove_lh); down(&zfcp_data.config_sema); if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { @@ -144,7 +145,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, goto out; } - if (strict_strtoull(buf, 0, &wwpn)) { + if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) { retval = -EINVAL; goto out; } @@ -154,7 +155,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, if (port && (atomic_read(&port->refcount) == 0)) { zfcp_port_get(port); atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); - list_move(&port->list, &adapter->port_remove_lh); + list_move(&port->list, &port_remove_lh); } else port = NULL; write_unlock_irq(&zfcp_data.config_lock); @@ -200,7 +201,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, { struct zfcp_port *port = dev_get_drvdata(dev); struct zfcp_unit *unit; - fcp_lun_t fcp_lun; + u64 fcp_lun; int retval = -EINVAL; down(&zfcp_data.config_sema); @@ -209,7 +210,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, goto out; } - if (strict_strtoull(buf, 0, &fcp_lun)) + if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) goto out; unit = zfcp_unit_enqueue(port, fcp_lun); @@ -233,8 +234,9 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, { struct zfcp_port *port = dev_get_drvdata(dev); struct zfcp_unit *unit; - fcp_lun_t fcp_lun; + u64 fcp_lun; int retval = 0; + LIST_HEAD(unit_remove_lh); down(&zfcp_data.config_sema); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { @@ -242,7 +244,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, goto out; } - if (strict_strtoull(buf, 0, &fcp_lun)) { + if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) { retval = -EINVAL; goto out; } @@ -252,7 +254,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, if (unit && (atomic_read(&unit->refcount) == 0)) { zfcp_unit_get(unit); atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); - list_move(&unit->list, &port->unit_remove_lh); + list_move(&unit->list, &unit_remove_lh); } else unit = NULL; @@ -273,22 +275,7 @@ out: } static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); -static struct attribute *zfcp_port_ns_attrs[] = { - &dev_attr_port_failed.attr, - &dev_attr_port_in_recovery.attr, - &dev_attr_port_status.attr, - &dev_attr_port_access_denied.attr, - NULL -}; - -/** - * zfcp_sysfs_ns_port_attrs - sysfs attributes for nameserver - */ -struct attribute_group zfcp_sysfs_ns_port_attrs = { - .attrs = zfcp_port_ns_attrs, -}; - -static struct attribute *zfcp_port_no_ns_attrs[] = { +static struct attribute *zfcp_port_attrs[] = { &dev_attr_unit_add.attr, &dev_attr_unit_remove.attr, &dev_attr_port_failed.attr, @@ -302,7 +289,7 @@ static struct attribute *zfcp_port_no_ns_attrs[] = { * zfcp_sysfs_port_attrs - sysfs attributes for all other ports */ struct attribute_group zfcp_sysfs_port_attrs = { - .attrs = zfcp_port_no_ns_attrs, + .attrs = zfcp_port_attrs, }; static struct attribute *zfcp_unit_attrs[] = { @@ -395,8 +382,10 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL); ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", unit->port->adapter->ccw_device->dev.bus_id); -ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn); -ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun); +ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", + (unsigned long long) unit->port->wwpn); +ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", + (unsigned long long) unit->fcp_lun); struct device_attribute *zfcp_sysfs_sdev_attrs[] = { &dev_attr_fcp_lun, @@ -487,10 +476,23 @@ ZFCP_SHOST_ATTR(megabytes, "%llu %llu\n", ZFCP_SHOST_ATTR(seconds_active, "%llu\n", (unsigned long long) stat_info.seconds_act); +static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *scsi_host = class_to_shost(dev); + struct zfcp_adapter *adapter = + (struct zfcp_adapter *) scsi_host->hostdata[0]; + + return sprintf(buf, "%d\n", atomic_read(&adapter->qdio_outb_full)); +} +static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL); + struct device_attribute *zfcp_sysfs_shost_attrs[] = { &dev_attr_utilization, &dev_attr_requests, &dev_attr_megabytes, &dev_attr_seconds_active, + &dev_attr_queue_full, NULL }; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4e0322b1c1ea..d3b211af4e1c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1325,14 +1325,6 @@ config SCSI_QLOGIC_FAS To compile this driver as a module, choose M here: the module will be called qlogicfas. -config SCSI_QLOGIC_FC_FIRMWARE - bool "Include loadable firmware in driver" - depends on SCSI_QLOGIC_FC - help - Say Y to include ISP2X00 Fabric Initiator/Target Firmware, with - expanded LUN addressing and FcTape (FCP-2) support, in the - qlogicfc driver. This is required on some platforms. - config SCSI_QLOGIC_1280 tristate "Qlogic QLA 1240/1x80/1x160 SCSI support" depends on PCI && SCSI diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index aa4e77c25273..8abfd06b5a72 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1139,7 +1139,7 @@ static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd srbcmd->id = cpu_to_le32(scmd_id(cmd)); srbcmd->lun = cpu_to_le32(cmd->device->lun); srbcmd->flags = cpu_to_le32(flag); - timeout = cmd->timeout_per_command/HZ; + timeout = cmd->request->timeout/HZ; if (timeout == 0) timeout = 1; srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index ef693e8412e9..8f45570a8a01 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -84,7 +84,7 @@ struct clariion_dh_data { /* * I/O buffer for both MODE_SELECT and INQUIRY commands. */ - char buffer[CLARIION_BUFFER_SIZE]; + unsigned char buffer[CLARIION_BUFFER_SIZE]; /* * SCSI sense buffer for commands -- assumes serial issuance * and completion sequence of all commands for same multipath. @@ -176,7 +176,7 @@ static int parse_sp_info_reply(struct scsi_device *sdev, err = SCSI_DH_DEV_TEMP_BUSY; goto out; } - if (csdev->buffer[4] < 0 || csdev->buffer[4] > 2) { + if (csdev->buffer[4] > 2) { /* Invalid buffer format */ sdev_printk(KERN_NOTICE, sdev, "%s: invalid VPD page 0xC0 format\n", @@ -278,7 +278,6 @@ static struct request *get_req(struct scsi_device *sdev, int cmd, return NULL; } - memset(rq->cmd, 0, BLK_MAX_CDB); rq->cmd_len = COMMAND_SIZE(cmd); rq->cmd[0] = cmd; diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index a6a4ef3ad51c..5e93c88ad66b 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -114,7 +114,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) req->cmd_type = REQ_TYPE_BLOCK_PC; req->cmd_flags |= REQ_FAILFAST; req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY); - memset(req->cmd, 0, MAX_COMMAND_SIZE); req->cmd[0] = TEST_UNIT_READY; req->timeout = HP_SW_TIMEOUT; req->sense = h->sense; @@ -207,7 +206,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) req->cmd_type = REQ_TYPE_BLOCK_PC; req->cmd_flags |= REQ_FAILFAST; req->cmd_len = COMMAND_SIZE(START_STOP); - memset(req->cmd, 0, MAX_COMMAND_SIZE); req->cmd[0] = START_STOP; req->cmd[4] = 1; /* Start spin cycle */ req->timeout = HP_SW_TIMEOUT; diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 6e2f130d56de..50bf95f3b5c4 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -225,8 +225,6 @@ static struct request *get_rdac_req(struct scsi_device *sdev, return NULL; } - memset(rq->cmd, 0, BLK_MAX_CDB); - rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; rq->retries = RDAC_RETRIES; @@ -590,6 +588,8 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { {"STK", "OPENstorage D280"}, {"SUN", "CSM200_R"}, {"SUN", "LCSM100_F"}, + {"DELL", "MD3000"}, + {"DELL", "MD3000i"}, {NULL, NULL}, }; diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 822d5214692b..c387c15a2128 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -464,7 +464,6 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, /* use request field to save the ptr. to completion struct. */ scp->request = (struct request *)&wait; - scp->timeout_per_command = timeout*HZ; scp->cmd_len = 12; scp->cmnd = cmnd; cmndinfo.priority = IOCTL_PRI; @@ -1995,23 +1994,12 @@ static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority) register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; ulong flags; - unchar b, t; TRACE(("gdth_putq() priority %d\n",priority)); spin_lock_irqsave(&ha->smp_lock, flags); - if (!cmndinfo->internal_command) { + if (!cmndinfo->internal_command) cmndinfo->priority = priority; - b = scp->device->channel; - t = scp->device->id; - if (priority >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) { - TRACE2(("gdth_putq(): locked IO ->update_timeout()\n")); - cmndinfo->timeout = gdth_update_timeout(scp, 0); - } - } - } if (ha->req_first==NULL) { ha->req_first = scp; /* queue was empty */ @@ -3899,6 +3887,39 @@ static const char *gdth_info(struct Scsi_Host *shp) return ((const char *)ha->binfo.type_string); } +static enum blk_eh_timer_return gdth_timed_out(struct scsi_cmnd *scp) +{ + gdth_ha_str *ha = shost_priv(scp->device->host); + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); + unchar b, t; + ulong flags; + enum blk_eh_timer_return retval = BLK_EH_NOT_HANDLED; + + TRACE(("%s() cmd 0x%x\n", scp->cmnd[0], __func__)); + b = scp->device->channel; + t = scp->device->id; + + /* + * We don't really honor the command timeout, but we try to + * honor 6 times of the actual command timeout! So reset the + * timer if this is less than 6th timeout on this command! + */ + if (++cmndinfo->timeout_count < 6) + retval = BLK_EH_RESET_TIMER; + + /* Reset the timeout if it is locked IO */ + spin_lock_irqsave(&ha->smp_lock, flags); + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha, b)].lock) || + (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { + TRACE2(("%s(): locked IO, reset timeout\n", __func__)); + retval = BLK_EH_RESET_TIMER; + } + spin_unlock_irqrestore(&ha->smp_lock, flags); + + return retval; +} + + static int gdth_eh_bus_reset(Scsi_Cmnd *scp) { gdth_ha_str *ha = shost_priv(scp->device->host); @@ -3992,7 +4013,7 @@ static int gdth_queuecommand(struct scsi_cmnd *scp, BUG_ON(!cmndinfo); scp->scsi_done = done; - gdth_update_timeout(scp, scp->timeout_per_command * 6); + cmndinfo->timeout_count = 0; cmndinfo->priority = DEFAULT_PRI; return __gdth_queuecommand(ha, scp, cmndinfo); @@ -4096,12 +4117,10 @@ static int ioc_lockdrv(void __user *arg) ha->hdr[j].lock = 1; spin_unlock_irqrestore(&ha->smp_lock, flags); gdth_wait_completion(ha, ha->bus_cnt, j); - gdth_stop_timeout(ha, ha->bus_cnt, j); } else { spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[j].lock = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); - gdth_start_timeout(ha, ha->bus_cnt, j); gdth_next(ha); } } @@ -4539,18 +4558,14 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, spin_lock_irqsave(&ha->smp_lock, flags); ha->raw[i].lock = 1; spin_unlock_irqrestore(&ha->smp_lock, flags); - for (j = 0; j < ha->tid_cnt; ++j) { + for (j = 0; j < ha->tid_cnt; ++j) gdth_wait_completion(ha, i, j); - gdth_stop_timeout(ha, i, j); - } } else { spin_lock_irqsave(&ha->smp_lock, flags); ha->raw[i].lock = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); - for (j = 0; j < ha->tid_cnt; ++j) { - gdth_start_timeout(ha, i, j); + for (j = 0; j < ha->tid_cnt; ++j) gdth_next(ha); - } } } break; @@ -4644,6 +4659,7 @@ static struct scsi_host_template gdth_template = { .slave_configure = gdth_slave_configure, .bios_param = gdth_bios_param, .proc_info = gdth_proc_info, + .eh_timed_out = gdth_timed_out, .proc_name = "gdth", .can_queue = GDTH_MAXCMDS, .this_id = -1, diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index ca92476727cf..1646444e9bd5 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -916,7 +916,7 @@ typedef struct { gdth_cmd_str *internal_cmd_str; /* crier for internal messages*/ dma_addr_t sense_paddr; /* sense dma-addr */ unchar priority; - int timeout; + int timeout_count; /* # of timeout calls */ volatile int wait_for_completion; ushort status; ulong32 info; diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index ce0228e26aec..59349a316e13 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -748,69 +748,3 @@ static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id) } spin_unlock_irqrestore(&ha->smp_lock, flags); } - -static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id) -{ - ulong flags; - Scsi_Cmnd *scp; - unchar b, t; - - spin_lock_irqsave(&ha->smp_lock, flags); - - for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - if (!cmndinfo->internal_command) { - b = scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_stop_timeout(): update_timeout()\n")); - cmndinfo->timeout = gdth_update_timeout(scp, 0); - } - } - } - spin_unlock_irqrestore(&ha->smp_lock, flags); -} - -static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id) -{ - ulong flags; - Scsi_Cmnd *scp; - unchar b, t; - - spin_lock_irqsave(&ha->smp_lock, flags); - - for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - if (!cmndinfo->internal_command) { - b = scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_start_timeout(): update_timeout()\n")); - gdth_update_timeout(scp, cmndinfo->timeout); - } - } - } - spin_unlock_irqrestore(&ha->smp_lock, flags); -} - -static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout) -{ - int oldto; - - oldto = scp->timeout_per_command; - scp->timeout_per_command = timeout; - - if (timeout == 0) { - del_timer(&scp->eh_timeout); - scp->eh_timeout.data = (unsigned long) NULL; - scp->eh_timeout.expires = 0; - } else { - if (scp->eh_timeout.data != (unsigned long) NULL) - del_timer(&scp->eh_timeout); - scp->eh_timeout.data = (unsigned long) scp; - scp->eh_timeout.expires = jiffies + timeout; - add_timer(&scp->eh_timeout); - } - - return oldto; -} diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h index 45e6fdacf36e..9b900cc9ebe8 100644 --- a/drivers/scsi/gdth_proc.h +++ b/drivers/scsi/gdth_proc.h @@ -20,9 +20,6 @@ static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, ulong64 *paddr); static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr); static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id); -static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id); -static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id); -static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout); #endif diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index fed0b02ebc1d..3fdbb13e80a8 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -464,7 +464,7 @@ static int __scsi_host_match(struct device *dev, void *data) struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) { struct device *cdev; - struct Scsi_Host *shost = ERR_PTR(-ENXIO); + struct Scsi_Host *shost = NULL; cdev = class_find_device(&shost_class, NULL, &hostnum, __scsi_host_match); diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 7b1502c0ab6e..87e09f35d3d4 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -756,7 +756,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, init_event_struct(evt_struct, handle_cmd_rsp, VIOSRP_SRP_FORMAT, - cmnd->timeout_per_command/HZ); + cmnd->request->timeout/HZ); evt_struct->cmnd = cmnd; evt_struct->cmnd_done = done; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 461331d3dc45..81c16cba5417 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -612,7 +612,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd, pc->req_xfer = pc->buf_size = scsi_bufflen(cmd); pc->scsi_cmd = cmd; pc->done = done; - pc->timeout = jiffies + cmd->timeout_per_command; + pc->timeout = jiffies + cmd->request->timeout; if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index e7a3a6554425..d30eb7ba018e 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3670,7 +3670,8 @@ static int ipr_slave_configure(struct scsi_device *sdev) sdev->no_uld_attach = 1; } if (ipr_is_vset_device(res)) { - sdev->timeout = IPR_VSET_RW_TIMEOUT; + blk_queue_rq_timeout(sdev->request_queue, + IPR_VSET_RW_TIMEOUT); blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS); } if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index bc9e6ddf41df..ef683f0d2b5a 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -3818,7 +3818,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb) scb->cmd.dcdb.segment_4G = 0; scb->cmd.dcdb.enhanced_sg = 0; - TimeOut = scb->scsi_cmd->timeout_per_command; + TimeOut = scb->scsi_cmd->request->timeout; if (ha->subsys->param[4] & 0x00100000) { /* If NEW Tape DCDB is Supported */ if (!scb->sg_len) { diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 299e075a7b34..da7b67d30d9a 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1456,7 +1456,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, if (lun == task->sc->device->lun || lun == -1) { debug_scsi("failing in progress sc %p itt 0x%x\n", task->sc, task->itt); - fail_command(conn, task, DID_BUS_BUSY << 16); + fail_command(conn, task, error << 16); } } } @@ -1476,12 +1476,12 @@ static void iscsi_start_tx(struct iscsi_conn *conn) scsi_queue_work(conn->session->host, &conn->xmitwork); } -static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) +static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) { struct iscsi_cls_session *cls_session; struct iscsi_session *session; struct iscsi_conn *conn; - enum scsi_eh_timer_return rc = EH_NOT_HANDLED; + enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; cls_session = starget_to_session(scsi_target(scmd->device)); session = cls_session->dd_data; @@ -1494,14 +1494,14 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) * We are probably in the middle of iscsi recovery so let * that complete and handle the error. */ - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; goto done; } conn = session->leadconn; if (!conn) { /* In the middle of shuting down */ - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; goto done; } @@ -1513,20 +1513,21 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) */ if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + (conn->ping_timeout * HZ), jiffies)) - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; /* * if we are about to check the transport then give the command * more time */ if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), jiffies)) - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; /* if in the middle of checking the transport then give us more time */ if (conn->ping_task) - rc = EH_RESET_TIMER; + rc = BLK_EH_RESET_TIMER; done: spin_unlock(&session->lock); - debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh"); + debug_scsi("return %s\n", rc == BLK_EH_RESET_TIMER ? + "timer reset" : "nh"); return rc; } diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 48ee8c7f5bdd..e15501170698 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -294,10 +294,10 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc) } } -static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in, +static int sas_ata_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val) { - struct domain_device *dev = ap->private_data; + struct domain_device *dev = link->ap->private_data; SAS_DPRINTK("STUB %s\n", __func__); switch (sc_reg_in) { @@ -319,10 +319,10 @@ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in, return 0; } -static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in, +static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val) { - struct domain_device *dev = ap->private_data; + struct domain_device *dev = link->ap->private_data; SAS_DPRINTK("STUB %s\n", __func__); switch (sc_reg_in) { @@ -398,7 +398,7 @@ void sas_ata_task_abort(struct sas_task *task) /* Bounce SCSI-initiated commands to the SCSI EH */ if (qc->scsicmd) { - scsi_req_abort_cmd(qc->scsicmd); + blk_abort_request(qc->scsicmd->request); scsi_schedule_eh(qc->scsicmd->device->host); return; } diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index b4f9368f116a..0001374bd6b2 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -55,7 +55,7 @@ void sas_unregister_phys(struct sas_ha_struct *sas_ha); int sas_register_ports(struct sas_ha_struct *sas_ha); void sas_unregister_ports(struct sas_ha_struct *sas_ha); -enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *); +enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *); int sas_init_queue(struct sas_ha_struct *sas_ha); int sas_init_events(struct sas_ha_struct *sas_ha); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index a8e3ef309070..744838780ada 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -673,43 +673,43 @@ out: return; } -enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) +enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) { struct sas_task *task = TO_SAS_TASK(cmd); unsigned long flags; if (!task) { - cmd->timeout_per_command /= 2; + cmd->request->timeout /= 2; SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n", - cmd, task, (cmd->timeout_per_command ? - "EH_RESET_TIMER" : "EH_NOT_HANDLED")); - if (!cmd->timeout_per_command) - return EH_NOT_HANDLED; - return EH_RESET_TIMER; + cmd, task, (cmd->request->timeout ? + "BLK_EH_RESET_TIMER" : "BLK_EH_NOT_HANDLED")); + if (!cmd->request->timeout) + return BLK_EH_NOT_HANDLED; + return BLK_EH_RESET_TIMER; } spin_lock_irqsave(&task->task_state_lock, flags); BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED); if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", - cmd, task); - return EH_HANDLED; + SAS_DPRINTK("command 0x%p, task 0x%p, timed out: " + "BLK_EH_HANDLED\n", cmd, task); + return BLK_EH_HANDLED; } if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) { spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: " - "EH_RESET_TIMER\n", + "BLK_EH_RESET_TIMER\n", cmd, task); - return EH_RESET_TIMER; + return BLK_EH_RESET_TIMER; } task->task_state_flags |= SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_NOT_HANDLED\n", + SAS_DPRINTK("command 0x%p, task 0x%p, timed out: BLK_EH_NOT_HANDLED\n", cmd, task); - return EH_NOT_HANDLED; + return BLK_EH_NOT_HANDLED; } int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) @@ -1039,7 +1039,7 @@ void sas_task_abort(struct sas_task *task) return; } - scsi_req_abort_cmd(sc); + blk_abort_request(sc->request); scsi_schedule_eh(sc->device->host); } diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 97b763378e7d..afe1de998763 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -1167,7 +1167,7 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd) * cmd has not been completed within the timeout period. */ static enum -scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) +blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) { struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr; struct megasas_instance *instance; @@ -1175,7 +1175,7 @@ scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) if (time_after(jiffies, scmd->jiffies_at_alloc + (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) { - return EH_NOT_HANDLED; + return BLK_EH_NOT_HANDLED; } instance = cmd->instance; @@ -1189,7 +1189,7 @@ scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) spin_unlock_irqrestore(instance->host->host_lock, flags); } - return EH_RESET_TIMER; + return BLK_EH_RESET_TIMER; } /** diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index c57c94c0ffd2..3b7240e40819 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -4170,8 +4170,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) ** **---------------------------------------------------- */ - if (np->settle_time && cmd->timeout_per_command >= HZ) { - u_long tlimit = jiffies + cmd->timeout_per_command - HZ; + if (np->settle_time && cmd->request->timeout >= HZ) { + u_long tlimit = jiffies + cmd->request->timeout - HZ; if (time_after(np->settle_time, tlimit)) np->settle_time = tlimit; } diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 37f9ba0cd798..b6cd12b2e996 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2845,7 +2845,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); /* Set ISP command timeout. */ - pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ); + pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ); /* Set device target ID and LUN */ pkt->lun = SCSI_LUN_32(cmd); @@ -3114,7 +3114,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8)); /* Set ISP command timeout. */ - pkt->timeout = cpu_to_le16(cmd->timeout_per_command/HZ); + pkt->timeout = cpu_to_le16(cmd->request->timeout/HZ); /* Set device target ID and LUN */ pkt->lun = SCSI_LUN_32(cmd); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 45e7dcb4b34d..0ddfe7106b3b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -292,10 +292,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, valid = 0; if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) valid = 1; - else if (start == (FA_BOOT_CODE_ADDR*4) || - start == (FA_RISC_CODE_ADDR*4)) + else if (start == (ha->flt_region_boot * 4) || + start == (ha->flt_region_fw * 4)) valid = 1; - else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) + else if (IS_QLA25XX(ha) && + start == (ha->flt_region_vpd_nvram * 4)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, @@ -1065,6 +1066,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat->dumped_frames = stats->dumped_frames; pfc_host_stat->nos_count = stats->nos_rcvd; } + pfc_host_stat->fcp_input_megabytes = ha->qla_stats.input_bytes >> 20; + pfc_host_stat->fcp_output_megabytes = ha->qla_stats.output_bytes >> 20; done_free: dma_pool_free(ha->s_dma_pool, stats, stats_dma); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 94a720eabfd8..83c819216771 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -25,7 +25,6 @@ #include <linux/firmware.h> #include <linux/aer.h> #include <linux/mutex.h> -#include <linux/semaphore.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> @@ -2157,6 +2156,8 @@ struct qla_chip_state_84xx { struct qla_statistics { uint32_t total_isp_aborts; + uint64_t input_bytes; + uint64_t output_bytes; }; /* @@ -2238,6 +2239,7 @@ typedef struct scsi_qla_host { #define FCPORT_UPDATE_NEEDED 27 #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ #define UNLOADING 29 +#define NPIV_CONFIG_NEEDED 30 uint32_t device_flags; #define DFLG_LOCAL_DEVICES BIT_0 @@ -2507,7 +2509,6 @@ typedef struct scsi_qla_host { uint64_t fce_wr, fce_rd; struct mutex fce_mutex; - uint32_t hw_event_start; uint32_t hw_event_ptr; uint32_t hw_event_pause_errors; @@ -2553,6 +2554,14 @@ typedef struct scsi_qla_host { uint32_t fdt_unprotect_sec_cmd; uint32_t fdt_protect_sec_cmd; + uint32_t flt_region_flt; + uint32_t flt_region_fdt; + uint32_t flt_region_boot; + uint32_t flt_region_fw; + uint32_t flt_region_vpd_nvram; + uint32_t flt_region_hw_event; + uint32_t flt_region_npiv_conf; + /* Needed for BEACON */ uint16_t beacon_blink_led; uint8_t beacon_color_state; diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index cf194517400d..d1d14202575a 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -789,14 +789,23 @@ struct device_reg_24xx { #define FA_RISC_CODE_ADDR 0x20000 #define FA_RISC_CODE_SEGMENTS 2 +#define FA_FLASH_DESCR_ADDR_24 0x11000 +#define FA_FLASH_LAYOUT_ADDR_24 0x11400 +#define FA_NPIV_CONF0_ADDR_24 0x16000 +#define FA_NPIV_CONF1_ADDR_24 0x17000 + #define FA_FW_AREA_ADDR 0x40000 #define FA_VPD_NVRAM_ADDR 0x48000 #define FA_FEATURE_ADDR 0x4C000 #define FA_FLASH_DESCR_ADDR 0x50000 +#define FA_FLASH_LAYOUT_ADDR 0x50400 #define FA_HW_EVENT0_ADDR 0x54000 -#define FA_HW_EVENT1_ADDR 0x54200 +#define FA_HW_EVENT1_ADDR 0x54400 #define FA_HW_EVENT_SIZE 0x200 #define FA_HW_EVENT_ENTRY_SIZE 4 +#define FA_NPIV_CONF0_ADDR 0x5C000 +#define FA_NPIV_CONF1_ADDR 0x5D000 + /* * Flash Error Log Event Codes. */ @@ -806,10 +815,6 @@ struct device_reg_24xx { #define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023 #define HW_EVENT_FLASH_FW_ERR 0xF024 -#define FA_BOOT_LOG_ADDR 0x58000 -#define FA_FW_DUMP0_ADDR 0x60000 -#define FA_FW_DUMP1_ADDR 0x70000 - uint32_t flash_data; /* Flash/NVRAM BIOS data. */ uint32_t ctrl_status; /* Control/Status. */ @@ -1203,6 +1208,62 @@ struct qla_fdt_layout { uint8_t unused2[65]; }; +/* Flash Layout Table ********************************************************/ + +struct qla_flt_location { + uint8_t sig[4]; + uint32_t start_lo; + uint32_t start_hi; + uint16_t unused; + uint16_t checksum; +}; + +struct qla_flt_header { + uint16_t version; + uint16_t length; + uint16_t checksum; + uint16_t unused; +}; + +#define FLT_REG_FW 0x01 +#define FLT_REG_BOOT_CODE 0x07 +#define FLT_REG_VPD_0 0x14 +#define FLT_REG_NVRAM_0 0x15 +#define FLT_REG_VPD_1 0x16 +#define FLT_REG_NVRAM_1 0x17 +#define FLT_REG_FDT 0x1a +#define FLT_REG_FLT 0x1c +#define FLT_REG_HW_EVENT_0 0x1d +#define FLT_REG_HW_EVENT_1 0x1f +#define FLT_REG_NPIV_CONF_0 0x29 +#define FLT_REG_NPIV_CONF_1 0x2a + +struct qla_flt_region { + uint32_t code; + uint32_t size; + uint32_t start; + uint32_t end; +}; + +/* Flash NPIV Configuration Table ********************************************/ + +struct qla_npiv_header { + uint8_t sig[2]; + uint16_t version; + uint16_t entries; + uint16_t unused[4]; + uint16_t checksum; +}; + +struct qla_npiv_entry { + uint16_t flags; + uint16_t vf_id; + uint16_t qos; + uint16_t unused1; + uint8_t port_name[WWN_SIZE]; + uint8_t node_name[WWN_SIZE]; +}; + /* 84XX Support **************************************************************/ #define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0b156735e9a6..753dbe6cce6e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -313,9 +313,11 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, uint16_t, uint16_t); -extern void qla2xxx_get_flash_info(scsi_qla_host_t *); +extern int qla2xxx_get_flash_info(scsi_qla_host_t *); extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); +extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); + /* * Global Function Prototypes in qla_dbg.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ee89ddd64aae..a470f2d3270d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -83,6 +83,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ha->isp_ops->reset_chip(ha); + rval = qla2xxx_get_flash_info(ha); + if (rval) { + DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n", + ha->host_no)); + return (rval); + } + ha->isp_ops->get_flash_version(ha, ha->request_ring); qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); @@ -109,7 +116,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) rval = qla2x00_setup_chip(ha); if (rval) return (rval); - qla2xxx_get_flash_info(ha); } if (IS_QLA84XX(ha)) { ha->cs84xx = qla84xx_get_chip(ha); @@ -2016,7 +2022,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) DEBUG3(printk("%s: exiting normally\n", __func__)); } - /* Restore state if a resync event occured during processing */ + /* Restore state if a resync event occurred during processing */ if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); @@ -2561,7 +2567,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) rval = QLA_SUCCESS; /* Try GID_PT to get device list, else GAN. */ - swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC); + swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_KERNEL); if (!swl) { /*EMPTY*/ DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " @@ -3751,7 +3757,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) rval = QLA_SUCCESS; segments = FA_RISC_CODE_SEGMENTS; - faddr = FA_RISC_CODE_ADDR; + faddr = ha->flt_region_fw; dcode = (uint32_t *)ha->request_ring; *srisc_addr = 0; diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 92fafbdbbaab..e90afad120ee 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -52,7 +52,7 @@ to_qla_parent(scsi_qla_host_t *ha) * @ha: HA context * @ha_locked: is function called with the hardware lock * - * Returns non-zero if a failure occured, else zero. + * Returns non-zero if a failure occurred, else zero. */ static inline int qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d57669aa4615..85bc0a48598b 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -21,17 +21,22 @@ static void qla2x00_isp_cmd(scsi_qla_host_t *ha); * Returns the proper CF_* direction based on CDB. */ static inline uint16_t -qla2x00_get_cmd_direction(struct scsi_cmnd *cmd) +qla2x00_get_cmd_direction(srb_t *sp) { uint16_t cflags; cflags = 0; /* Set transfer direction */ - if (cmd->sc_data_direction == DMA_TO_DEVICE) + if (sp->cmd->sc_data_direction == DMA_TO_DEVICE) { cflags = CF_WRITE; - else if (cmd->sc_data_direction == DMA_FROM_DEVICE) + sp->fcport->ha->qla_stats.output_bytes += + scsi_bufflen(sp->cmd); + } else if (sp->cmd->sc_data_direction == DMA_FROM_DEVICE) { cflags = CF_READ; + sp->fcport->ha->qla_stats.input_bytes += + scsi_bufflen(sp->cmd); + } return (cflags); } @@ -169,7 +174,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, ha = sp->ha; - cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd)); + cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); /* Three DSDs are available in the Command Type 2 IOCB */ avail_dsds = 3; @@ -228,7 +233,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, ha = sp->ha; - cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd)); + cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); /* Two DSDs are available in the Command Type 3 IOCB */ avail_dsds = 2; @@ -262,7 +267,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, * qla2x00_start_scsi() - Send a SCSI command to the ISP * @sp: command to send to the ISP * - * Returns non-zero if a failure occured, else zero. + * Returns non-zero if a failure occurred, else zero. */ int qla2x00_start_scsi(srb_t *sp) @@ -407,7 +412,7 @@ queuing_error: * * Can be called from both normal and interrupt context. * - * Returns non-zero if a failure occured, else zero. + * Returns non-zero if a failure occurred, else zero. */ int __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, @@ -625,12 +630,17 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, ha = sp->ha; /* Set transfer direction */ - if (cmd->sc_data_direction == DMA_TO_DEVICE) + if (cmd->sc_data_direction == DMA_TO_DEVICE) { cmd_pkt->task_mgmt_flags = __constant_cpu_to_le16(TMF_WRITE_DATA); - else if (cmd->sc_data_direction == DMA_FROM_DEVICE) + sp->fcport->ha->qla_stats.output_bytes += + scsi_bufflen(sp->cmd); + } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { cmd_pkt->task_mgmt_flags = __constant_cpu_to_le16(TMF_READ_DATA); + sp->fcport->ha->qla_stats.input_bytes += + scsi_bufflen(sp->cmd); + } /* One DSD is available in the Command Type 3 IOCB */ avail_dsds = 1; @@ -666,7 +676,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, * qla24xx_start_scsi() - Send a SCSI command to the ISP * @sp: command to send to the ISP * - * Returns non-zero if a failure occured, else zero. + * Returns non-zero if a failure occurred, else zero. */ int qla24xx_start_scsi(srb_t *sp) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index bf41887cdd65..fc4bfa7f839c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -391,9 +391,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ - DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, + DEBUG2(printk("scsi(%ld): LIP occurred (%x).\n", ha->host_no, mb[1])); - qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); + qla_printk(KERN_INFO, ha, "LIP occurred (%x).\n", mb[1]); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); @@ -460,7 +460,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", ha->host_no, mb[1])); qla_printk(KERN_INFO, ha, - "LIP reset occured (%x).\n", mb[1]); + "LIP reset occurred (%x).\n", mb[1]); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); @@ -543,7 +543,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) case MBA_PORT_UPDATE: /* Port database update */ /* - * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET + * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET * event etc. earlier indicating loop is down) then process * it. Otherwise ignore it and Wait for RSCN to come in. */ @@ -589,7 +589,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n", ha->host_no, mb[1], mb[2], mb[3])); - rscn_entry = (mb[1] << 16) | mb[2]; + rscn_entry = ((mb[1] & 0xff) << 16) | mb[2]; host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) | ha->d_id.b.al_pa; if (rscn_entry == host_pid) { @@ -600,6 +600,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; } + /* Ignore reserved bits from RSCN-payload. */ + rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2]; rscn_queue_index = ha->rscn_in_ptr + 1; if (rscn_queue_index == MAX_RSCN_COUNT) rscn_queue_index = 0; @@ -1060,8 +1062,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) resid = resid_len; /* Use F/W calculated residual length. */ if (IS_FWI2_CAPABLE(ha)) { - if (scsi_status & SS_RESIDUAL_UNDER && - resid != fw_resid_len) { + if (!(scsi_status & SS_RESIDUAL_UNDER)) { + lscsi_status = 0; + } else if (resid != fw_resid_len) { scsi_status &= ~SS_RESIDUAL_UNDER; lscsi_status = 0; } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 813bc7784c0a..36bc6851e23d 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -233,7 +233,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) DEBUG2_3_11(printk("%s(%ld): timeout schedule " "isp_abort_needed.\n", __func__, ha->host_no)); qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occured. Scheduling ISP " + "Mailbox command timeout occurred. Scheduling ISP " "abort.\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); qla2xxx_wake_dpc(ha); @@ -244,7 +244,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) DEBUG2_3_11(printk("%s(%ld): timeout calling " "abort_isp\n", __func__, ha->host_no)); qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occured. Issuing ISP " + "Mailbox command timeout occurred. Issuing ISP " "abort.\n"); set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); @@ -1995,7 +1995,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) char *pmap; dma_addr_t pmap_dma; - pmap = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pmap_dma); + pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); if (pmap == NULL) { DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", __func__, ha->host_no)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6d0f0e5f2827..3433441b956a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1517,6 +1517,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost) set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); set_bit(RSCN_UPDATE, &ha->dpc_flags); + set_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags); } static int @@ -1663,8 +1664,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->gid_list_info_size = 8; ha->optrom_size = OPTROM_SIZE_25XX; ha->isp_ops = &qla25xx_isp_ops; - ha->hw_event_start = PCI_FUNC(pdev->devfn) ? - FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR; } host->can_queue = ha->request_q_length + 128; @@ -2433,6 +2432,12 @@ qla2x00_do_dpc(void *data) ha->host_no)); } + if (test_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags) && + atomic_read(&ha->loop_state) == LOOP_READY) { + clear_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags); + qla2xxx_flash_npiv_conf(ha); + } + if (!ha->interrupts_on) ha->isp_ops->enable_intrs(ha); diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 1bca74474935..90a13211717f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -543,23 +543,198 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, } } -void -qla2xxx_get_flash_info(scsi_qla_host_t *ha) +static int +qla2xxx_find_flt_start(scsi_qla_host_t *ha, uint32_t *start) +{ + const char *loc, *locations[] = { "DEF", "PCI" }; + uint32_t pcihdr, pcids; + uint32_t *dcode; + uint8_t *buf, *bcode, last_image; + uint16_t cnt, chksum, *wptr; + struct qla_flt_location *fltl; + + /* + * FLT-location structure resides after the last PCI region. + */ + + /* Begin with sane defaults. */ + loc = locations[0]; + *start = IS_QLA24XX_TYPE(ha) ? FA_FLASH_LAYOUT_ADDR_24: + FA_FLASH_LAYOUT_ADDR; + + /* Begin with first PCI expansion ROM header. */ + buf = (uint8_t *)ha->request_ring; + dcode = (uint32_t *)ha->request_ring; + pcihdr = 0; + last_image = 1; + do { + /* Verify PCI expansion ROM header. */ + qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); + bcode = buf + (pcihdr % 4); + if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) + goto end; + + /* Locate PCI data structure. */ + pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); + qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); + bcode = buf + (pcihdr % 4); + + /* Validate signature of PCI data structure. */ + if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || + bcode[0x2] != 'I' || bcode[0x3] != 'R') + goto end; + + last_image = bcode[0x15] & BIT_7; + + /* Locate next PCI expansion ROM. */ + pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; + } while (!last_image); + + /* Now verify FLT-location structure. */ + fltl = (struct qla_flt_location *)ha->request_ring; + qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, + sizeof(struct qla_flt_location) >> 2); + if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' || + fltl->sig[2] != 'L' || fltl->sig[3] != 'T') + goto end; + + wptr = (uint16_t *)ha->request_ring; + cnt = sizeof(struct qla_flt_location) >> 1; + for (chksum = 0; cnt; cnt--) + chksum += le16_to_cpu(*wptr++); + if (chksum) { + qla_printk(KERN_ERR, ha, + "Inconsistent FLTL detected: checksum=0x%x.\n", chksum); + qla2x00_dump_buffer(buf, sizeof(struct qla_flt_location)); + return QLA_FUNCTION_FAILED; + } + + /* Good data. Use specified location. */ + loc = locations[1]; + *start = le16_to_cpu(fltl->start_hi) << 16 | + le16_to_cpu(fltl->start_lo); +end: + DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start)); + return QLA_SUCCESS; +} + +static void +qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr) +{ + const char *loc, *locations[] = { "DEF", "FLT" }; + uint16_t *wptr; + uint16_t cnt, chksum; + uint32_t start; + struct qla_flt_header *flt; + struct qla_flt_region *region; + + ha->flt_region_flt = flt_addr; + wptr = (uint16_t *)ha->request_ring; + flt = (struct qla_flt_header *)ha->request_ring; + region = (struct qla_flt_region *)&flt[1]; + ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, + flt_addr << 2, OPTROM_BURST_SIZE); + if (*wptr == __constant_cpu_to_le16(0xffff)) + goto no_flash_data; + if (flt->version != __constant_cpu_to_le16(1)) { + DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported FLT detected: " + "version=0x%x length=0x%x checksum=0x%x.\n", + le16_to_cpu(flt->version), le16_to_cpu(flt->length), + le16_to_cpu(flt->checksum))); + goto no_flash_data; + } + + cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; + for (chksum = 0; cnt; cnt--) + chksum += le16_to_cpu(*wptr++); + if (chksum) { + DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FLT detected: " + "version=0x%x length=0x%x checksum=0x%x.\n", + le16_to_cpu(flt->version), le16_to_cpu(flt->length), + chksum)); + goto no_flash_data; + } + + loc = locations[1]; + cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); + for ( ; cnt; cnt--, region++) { + /* Store addresses as DWORD offsets. */ + start = le32_to_cpu(region->start) >> 2; + + DEBUG3(qla_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x " + "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start, + le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size))); + + switch (le32_to_cpu(region->code)) { + case FLT_REG_FW: + ha->flt_region_fw = start; + break; + case FLT_REG_BOOT_CODE: + ha->flt_region_boot = start; + break; + case FLT_REG_VPD_0: + ha->flt_region_vpd_nvram = start; + break; + case FLT_REG_FDT: + ha->flt_region_fdt = start; + break; + case FLT_REG_HW_EVENT_0: + if (!PCI_FUNC(ha->pdev->devfn)) + ha->flt_region_hw_event = start; + break; + case FLT_REG_HW_EVENT_1: + if (PCI_FUNC(ha->pdev->devfn)) + ha->flt_region_hw_event = start; + break; + case FLT_REG_NPIV_CONF_0: + if (!PCI_FUNC(ha->pdev->devfn)) + ha->flt_region_npiv_conf = start; + break; + case FLT_REG_NPIV_CONF_1: + if (PCI_FUNC(ha->pdev->devfn)) + ha->flt_region_npiv_conf = start; + break; + } + } + goto done; + +no_flash_data: + /* Use hardcoded defaults. */ + loc = locations[0]; + ha->flt_region_fw = FA_RISC_CODE_ADDR; + ha->flt_region_boot = FA_BOOT_CODE_ADDR; + ha->flt_region_vpd_nvram = FA_VPD_NVRAM_ADDR; + ha->flt_region_fdt = IS_QLA24XX_TYPE(ha) ? FA_FLASH_DESCR_ADDR_24: + FA_FLASH_DESCR_ADDR; + ha->flt_region_hw_event = !PCI_FUNC(ha->pdev->devfn) ? + FA_HW_EVENT0_ADDR: FA_HW_EVENT1_ADDR; + ha->flt_region_npiv_conf = !PCI_FUNC(ha->pdev->devfn) ? + (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF0_ADDR_24: FA_NPIV_CONF0_ADDR): + (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF1_ADDR_24: FA_NPIV_CONF1_ADDR); +done: + DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " + "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x npiv=0x%x.\n", loc, + ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram, + ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event, + ha->flt_region_npiv_conf)); +} + +static void +qla2xxx_get_fdt_info(scsi_qla_host_t *ha) { #define FLASH_BLK_SIZE_32K 0x8000 #define FLASH_BLK_SIZE_64K 0x10000 + const char *loc, *locations[] = { "MID", "FDT" }; uint16_t cnt, chksum; uint16_t *wptr; struct qla_fdt_layout *fdt; uint8_t man_id, flash_id; - - if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) - return; + uint16_t mid, fid; wptr = (uint16_t *)ha->request_ring; fdt = (struct qla_fdt_layout *)ha->request_ring; ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, - FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE); + ha->flt_region_fdt << 2, OPTROM_BURST_SIZE); if (*wptr == __constant_cpu_to_le16(0xffff)) goto no_flash_data; if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || @@ -577,7 +752,10 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) goto no_flash_data; } - ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f; + loc = locations[1]; + mid = le16_to_cpu(fdt->man_id); + fid = le16_to_cpu(fdt->id); + ha->fdt_odd_index = mid == 0x1f; ha->fdt_wrt_disable = fdt->wrt_disable_bits; ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); ha->fdt_block_size = le32_to_cpu(fdt->block_size); @@ -588,16 +766,12 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd): flash_conf_to_access_addr(0x0336); } - - DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x " - "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", - le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd, - ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd, - ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size)); - return; - + goto done; no_flash_data: + loc = locations[0]; qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); + mid = man_id; + fid = flash_id; ha->fdt_wrt_disable = 0x9c; ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8); switch (man_id) { @@ -625,14 +799,117 @@ no_flash_data: ha->fdt_block_size = FLASH_BLK_SIZE_64K; break; } - - DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x " - "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id, +done: + DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " + "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid, ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size)); } +int +qla2xxx_get_flash_info(scsi_qla_host_t *ha) +{ + int ret; + uint32_t flt_addr; + + if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) + return QLA_SUCCESS; + + ret = qla2xxx_find_flt_start(ha, &flt_addr); + if (ret != QLA_SUCCESS) + return ret; + + qla2xxx_get_flt_info(ha, flt_addr); + qla2xxx_get_fdt_info(ha); + + return QLA_SUCCESS; +} + +void +qla2xxx_flash_npiv_conf(scsi_qla_host_t *ha) +{ +#define NPIV_CONFIG_SIZE (16*1024) + void *data; + uint16_t *wptr; + uint16_t cnt, chksum; + struct qla_npiv_header hdr; + struct qla_npiv_entry *entry; + + if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) + return; + + ha->isp_ops->read_optrom(ha, (uint8_t *)&hdr, + ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header)); + if (hdr.version == __constant_cpu_to_le16(0xffff)) + return; + if (hdr.version != __constant_cpu_to_le16(1)) { + DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported NPIV-Config " + "detected: version=0x%x entries=0x%x checksum=0x%x.\n", + le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries), + le16_to_cpu(hdr.checksum))); + return; + } + + data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL); + if (!data) { + DEBUG2(qla_printk(KERN_INFO, ha, "NPIV-Config: Unable to " + "allocate memory.\n")); + return; + } + + ha->isp_ops->read_optrom(ha, (uint8_t *)data, + ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE); + + cnt = (sizeof(struct qla_npiv_header) + le16_to_cpu(hdr.entries) * + sizeof(struct qla_npiv_entry)) >> 1; + for (wptr = data, chksum = 0; cnt; cnt--) + chksum += le16_to_cpu(*wptr++); + if (chksum) { + DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent NPIV-Config " + "detected: version=0x%x entries=0x%x checksum=0x%x.\n", + le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries), + chksum)); + goto done; + } + + entry = data + sizeof(struct qla_npiv_header); + cnt = le16_to_cpu(hdr.entries); + for ( ; cnt; cnt--, entry++) { + uint16_t flags; + struct fc_vport_identifiers vid; + struct fc_vport *vport; + + flags = le16_to_cpu(entry->flags); + if (flags == 0xffff) + continue; + if ((flags & BIT_0) == 0) + continue; + + memset(&vid, 0, sizeof(vid)); + vid.roles = FC_PORT_ROLE_FCP_INITIATOR; + vid.vport_type = FC_PORTTYPE_NPIV; + vid.disable = false; + vid.port_name = wwn_to_u64(entry->port_name); + vid.node_name = wwn_to_u64(entry->node_name); + + DEBUG2(qla_printk(KERN_DEBUG, ha, "NPIV[%02x]: wwpn=%llx " + "wwnn=%llx vf_id=0x%x qos=0x%x.\n", cnt, + (unsigned long long)vid.port_name, + (unsigned long long)vid.node_name, + le16_to_cpu(entry->vf_id), le16_to_cpu(entry->qos))); + + vport = fc_vport_create(ha->host, 0, &vid); + if (!vport) + qla_printk(KERN_INFO, ha, "NPIV-Config: Failed to " + "create vport [%02x]: wwpn=%llx wwnn=%llx.\n", cnt, + (unsigned long long)vid.port_name, + (unsigned long long)vid.node_name); + } +done: + kfree(data); +} + static void qla24xx_unprotect_flash(scsi_qla_host_t *ha) { @@ -920,7 +1197,8 @@ qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, dwptr = (uint32_t *)buf; for (i = 0; i < bytes >> 2; i++, naddr++) dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, - flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr))); + flash_data_to_access_addr(ha->flt_region_vpd_nvram | + naddr))); return buf; } @@ -935,10 +1213,10 @@ qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, dbuf = vmalloc(RMW_BUFFER_SIZE); if (!dbuf) return QLA_MEMORY_ALLOC_FAILED; - ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, + ha->isp_ops->read_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, RMW_BUFFER_SIZE); memcpy(dbuf + (naddr << 2), buf, bytes); - ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, + ha->isp_ops->write_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, RMW_BUFFER_SIZE); vfree(dbuf); @@ -2166,7 +2444,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) memset(dbyte, 0, 8); dcode = (uint16_t *)dbyte; - qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, + qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10, 8); DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", __func__, ha->host_no)); @@ -2177,7 +2455,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && dcode[3] == 0)) { DEBUG2(printk("%s(): Unrecognized fw revision at " - "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); + "%x.\n", __func__, ha->flt_region_fw * 4)); } else { /* values are in big endian */ ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; @@ -2212,7 +2490,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) dcode = mbuf; /* Begin with first PCI expansion ROM header. */ - pcihdr = 0; + pcihdr = ha->flt_region_boot; last_image = 1; do { /* Verify PCI expansion ROM header. */ @@ -2282,7 +2560,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dcode = mbuf; - qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); + qla24xx_read_flash_data(ha, dcode, ha->flt_region_fw + 4, 4); for (i = 0; i < 4; i++) dcode[i] = be32_to_cpu(dcode[i]); @@ -2291,7 +2569,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && dcode[3] == 0)) { DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", - __func__, FA_RISC_CODE_ADDR)); + __func__, ha->flt_region_fw)); } else { ha->fw_revision[0] = dcode[0]; ha->fw_revision[1] = dcode[1]; @@ -2355,7 +2633,7 @@ qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata) /* Locate first empty entry. */ for (;;) { if (ha->hw_event_ptr >= - ha->hw_event_start + FA_HW_EVENT_SIZE) { + ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { DEBUG2(qla_printk(KERN_WARNING, ha, "HW event -- Log Full!\n")); return QLA_MEMORY_ALLOC_FAILED; @@ -2391,7 +2669,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, int rval; uint32_t marker[2], fdata[4]; - if (ha->hw_event_start == 0) + if (ha->flt_region_hw_event == 0) return QLA_FUNCTION_FAILED; DEBUG2(qla_printk(KERN_WARNING, ha, @@ -2406,7 +2684,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER); /* Locate marker. */ - ha->hw_event_ptr = ha->hw_event_start; + ha->hw_event_ptr = ha->flt_region_hw_event; for (;;) { qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr, 4); @@ -2415,7 +2693,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, break; ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE; if (ha->hw_event_ptr >= - ha->hw_event_start + FA_HW_EVENT_SIZE) { + ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { DEBUG2(qla_printk(KERN_WARNING, ha, "HW event -- Log Full!\n")); return QLA_MEMORY_ALLOC_FAILED; diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 4160e4caa7b9..be5e299df528 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.01-k7" +#define QLA2XXX_VERSION "8.02.01-k8" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 88bebb13bc52..de8279ad7d89 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1542,7 +1542,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) DEBUG2(printk(KERN_INFO "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x," "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no, - cmd, jiffies, cmd->timeout_per_command / HZ, + cmd, jiffies, cmd->request->timeout / HZ, ha->dpc_flags, cmd->result, cmd->allowed)); /* FIXME: wait for hba to go online */ @@ -1598,7 +1598,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) DEBUG2(printk(KERN_INFO "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, " "to=%x,dpc_flags=%lx, status=%x allowed=%d\n", - ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ, + ha->host_no, cmd, jiffies, cmd->request->timeout / HZ, ha->dpc_flags, cmd->result, cmd->allowed)); stat = qla4xxx_reset_target(ha, ddb_entry); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ee6be596503d..2ac3cb2b9081 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -291,7 +291,6 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) unsigned long flags; cmd->device = dev; - init_timer(&cmd->eh_timeout); INIT_LIST_HEAD(&cmd->list); spin_lock_irqsave(&dev->list_lock, flags); list_add_tail(&cmd->list, &dev->cmd_list); @@ -652,26 +651,33 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) unsigned long timeout; int rtn = 0; + /* + * We will use a queued command if possible, otherwise we will + * emulate the queuing and calling of completion function ourselves. + */ + atomic_inc(&cmd->device->iorequest_cnt); + /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { /* in SDEV_DEL we error all commands. DID_NO_CONNECT * returns an immediate error upwards, and signals * that the device is no longer present */ cmd->result = DID_NO_CONNECT << 16; - atomic_inc(&cmd->device->iorequest_cnt); - __scsi_done(cmd); + scsi_done(cmd); /* return 0 (because the command has been processed) */ goto out; } - /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */ - if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) { + /* Check to see if the scsi lld made this device blocked. */ + if (unlikely(scsi_device_blocked(cmd->device))) { /* - * in SDEV_BLOCK, the command is just put back on the device - * queue. The suspend state has already blocked the queue so - * future requests should not occur until the device - * transitions out of the suspend state. + * in blocked state, the command is just put back on + * the device queue. The suspend state has already + * blocked the queue so future requests should not + * occur until the device transitions out of the + * suspend state. */ + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n")); @@ -714,21 +720,9 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) host->resetting = 0; } - /* - * AK: unlikely race here: for some reason the timer could - * expire before the serial number is set up below. - */ - scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out); - scsi_log_send(cmd); /* - * We will use a queued command if possible, otherwise we will - * emulate the queuing and calling of completion function ourselves. - */ - atomic_inc(&cmd->device->iorequest_cnt); - - /* * Before we queue this command, check if the command * length exceeds what the host adapter can handle. */ @@ -744,6 +738,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) } spin_lock_irqsave(host->host_lock, flags); + /* + * AK: unlikely race here: for some reason the timer could + * expire before the serial number is set up below. + * + * TODO: kill serial or move to blk layer + */ scsi_cmd_get_serial(host, cmd); if (unlikely(host->shost_state == SHOST_DEL)) { @@ -754,12 +754,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) } spin_unlock_irqrestore(host->host_lock, flags); if (rtn) { - if (scsi_delete_timer(cmd)) { - atomic_inc(&cmd->device->iodone_cnt); - scsi_queue_insert(cmd, - (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ? - rtn : SCSI_MLQUEUE_HOST_BUSY); - } + scsi_queue_insert(cmd, (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ? + rtn : SCSI_MLQUEUE_HOST_BUSY); SCSI_LOG_MLQUEUE(3, printk("queuecommand : request rejected\n")); } @@ -770,24 +766,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) } /** - * scsi_req_abort_cmd -- Request command recovery for the specified command - * @cmd: pointer to the SCSI command of interest - * - * This function requests that SCSI Core start recovery for the - * command by deleting the timer and adding the command to the eh - * queue. It can be called by either LLDDs or SCSI Core. LLDDs who - * implement their own error recovery MAY ignore the timeout event if - * they generated scsi_req_abort_cmd. - */ -void scsi_req_abort_cmd(struct scsi_cmnd *cmd) -{ - if (!scsi_delete_timer(cmd)) - return; - scsi_times_out(cmd); -} -EXPORT_SYMBOL(scsi_req_abort_cmd); - -/** * scsi_done - Enqueue the finished SCSI command into the done queue. * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives * ownership back to SCSI Core -- i.e. the LLDD has finished with it. @@ -802,42 +780,7 @@ EXPORT_SYMBOL(scsi_req_abort_cmd); */ static void scsi_done(struct scsi_cmnd *cmd) { - /* - * We don't have to worry about this one timing out anymore. - * If we are unable to remove the timer, then the command - * has already timed out. In which case, we have no choice but to - * let the timeout function run, as we have no idea where in fact - * that function could really be. It might be on another processor, - * etc, etc. - */ - if (!scsi_delete_timer(cmd)) - return; - __scsi_done(cmd); -} - -/* Private entry to scsi_done() to complete a command when the timer - * isn't running --- used by scsi_times_out */ -void __scsi_done(struct scsi_cmnd *cmd) -{ - struct request *rq = cmd->request; - - /* - * Set the serial numbers back to zero - */ - cmd->serial_number = 0; - - atomic_inc(&cmd->device->iodone_cnt); - if (cmd->result) - atomic_inc(&cmd->device->ioerr_cnt); - - BUG_ON(!rq); - - /* - * The uptodate/nbytes values don't matter, as we allow partial - * completes and thus will check this in the softirq callback - */ - rq->completion_data = cmd; - blk_complete_request(rq); + blk_complete_request(cmd->request); } /* Move this to a header if it becomes more generally useful */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 39ce3aba1dac..fecefa05cb62 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -112,69 +112,8 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) } /** - * scsi_add_timer - Start timeout timer for a single scsi command. - * @scmd: scsi command that is about to start running. - * @timeout: amount of time to allow this command to run. - * @complete: timeout function to call if timer isn't canceled. - * - * Notes: - * This should be turned into an inline function. Each scsi command - * has its own timer, and as it is added to the queue, we set up the - * timer. When the command completes, we cancel the timer. - */ -void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, - void (*complete)(struct scsi_cmnd *)) -{ - - /* - * If the clock was already running for this command, then - * first delete the timer. The timer handling code gets rather - * confused if we don't do this. - */ - if (scmd->eh_timeout.function) - del_timer(&scmd->eh_timeout); - - scmd->eh_timeout.data = (unsigned long)scmd; - scmd->eh_timeout.expires = jiffies + timeout; - scmd->eh_timeout.function = (void (*)(unsigned long)) complete; - - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:" - " %d, (%p)\n", __func__, - scmd, timeout, complete)); - - add_timer(&scmd->eh_timeout); -} - -/** - * scsi_delete_timer - Delete/cancel timer for a given function. - * @scmd: Cmd that we are canceling timer for - * - * Notes: - * This should be turned into an inline function. - * - * Return value: - * 1 if we were able to detach the timer. 0 if we blew it, and the - * timer function has already started to run. - */ -int scsi_delete_timer(struct scsi_cmnd *scmd) -{ - int rtn; - - rtn = del_timer(&scmd->eh_timeout); - - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p," - " rtn: %d\n", __func__, - scmd, rtn)); - - scmd->eh_timeout.data = (unsigned long)NULL; - scmd->eh_timeout.function = NULL; - - return rtn; -} - -/** * scsi_times_out - Timeout function for normal scsi commands. - * @scmd: Cmd that is timing out. + * @req: request that is timing out. * * Notes: * We do not need to lock this. There is the potential for a race @@ -182,9 +121,11 @@ int scsi_delete_timer(struct scsi_cmnd *scmd) * normal completion function determines that the timer has already * fired, then it mustn't do anything. */ -void scsi_times_out(struct scsi_cmnd *scmd) +enum blk_eh_timer_return scsi_times_out(struct request *req) { - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + struct scsi_cmnd *scmd = req->special; + enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); + enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED; scsi_log_completion(scmd, TIMEOUT_ERROR); @@ -196,22 +137,20 @@ void scsi_times_out(struct scsi_cmnd *scmd) eh_timed_out = NULL; if (eh_timed_out) - switch (eh_timed_out(scmd)) { - case EH_HANDLED: - __scsi_done(scmd); - return; - case EH_RESET_TIMER: - scsi_add_timer(scmd, scmd->timeout_per_command, - scsi_times_out); - return; - case EH_NOT_HANDLED: + rtn = eh_timed_out(scmd); + switch (rtn) { + case BLK_EH_NOT_HANDLED: break; + default: + return rtn; } if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { scmd->result |= DID_TIME_OUT << 16; - __scsi_done(scmd); + return BLK_EH_HANDLED; } + + return BLK_EH_NOT_HANDLED; } /** @@ -1793,7 +1732,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) blk_rq_init(NULL, &req); scmd->request = &req; - memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); scmd->cmnd = req.cmd; @@ -1804,8 +1742,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scmd->sc_data_direction = DMA_BIDIRECTIONAL; - init_timer(&scmd->eh_timeout); - spin_lock_irqsave(shost->host_lock, flags); shost->tmf_in_progress = 1; spin_unlock_irqrestore(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 62307bd794a9..98ee55ced592 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1181,7 +1181,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) cmd->transfersize = req->data_len; cmd->allowed = req->retries; - cmd->timeout_per_command = req->timeout; return BLKPREP_OK; } EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); @@ -1251,6 +1250,7 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) break; case SDEV_QUIESCE: case SDEV_BLOCK: + case SDEV_CREATED_BLOCK: /* * If the devices is blocked we defer normal commands. */ @@ -1416,17 +1416,26 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) spin_unlock(shost->host_lock); spin_lock(sdev->request_queue->queue_lock); - __scsi_done(cmd); + blk_complete_request(req); } static void scsi_softirq_done(struct request *rq) { - struct scsi_cmnd *cmd = rq->completion_data; - unsigned long wait_for = (cmd->allowed + 1) * cmd->timeout_per_command; + struct scsi_cmnd *cmd = rq->special; + unsigned long wait_for = (cmd->allowed + 1) * rq->timeout; int disposition; INIT_LIST_HEAD(&cmd->eh_entry); + /* + * Set the serial numbers back to zero + */ + cmd->serial_number = 0; + + atomic_inc(&cmd->device->iodone_cnt); + if (cmd->result) + atomic_inc(&cmd->device->ioerr_cnt); + disposition = scsi_decide_disposition(cmd); if (disposition != SUCCESS && time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { @@ -1675,6 +1684,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_prep_rq(q, scsi_prep_fn); blk_queue_softirq_done(q, scsi_softirq_done); + blk_queue_rq_timed_out(q, scsi_times_out); return q; } @@ -2064,10 +2074,13 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) switch (state) { case SDEV_CREATED: - /* There are no legal states that come back to - * created. This is the manually initialised start - * state */ - goto illegal; + switch (oldstate) { + case SDEV_CREATED_BLOCK: + break; + default: + goto illegal; + } + break; case SDEV_RUNNING: switch (oldstate) { @@ -2105,8 +2118,17 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) case SDEV_BLOCK: switch (oldstate) { - case SDEV_CREATED: case SDEV_RUNNING: + case SDEV_CREATED_BLOCK: + break; + default: + goto illegal; + } + break; + + case SDEV_CREATED_BLOCK: + switch (oldstate) { + case SDEV_CREATED: break; default: goto illegal; @@ -2394,8 +2416,12 @@ scsi_internal_device_block(struct scsi_device *sdev) int err = 0; err = scsi_device_set_state(sdev, SDEV_BLOCK); - if (err) - return err; + if (err) { + err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK); + + if (err) + return err; + } /* * The device has transitioned to SDEV_BLOCK. Stop the @@ -2438,8 +2464,12 @@ scsi_internal_device_unblock(struct scsi_device *sdev) * and goose the device queue if successful. */ err = scsi_device_set_state(sdev, SDEV_RUNNING); - if (err) - return err; + if (err) { + err = scsi_device_set_state(sdev, SDEV_CREATED); + + if (err) + return err; + } spin_lock_irqsave(q->queue_lock, flags); blk_start_queue(q); diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index ae7ed9a22662..b37e133de805 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -21,6 +21,7 @@ #include <linux/time.h> #include <linux/jiffies.h> #include <linux/security.h> +#include <linux/delay.h> #include <net/sock.h> #include <net/netlink.h> @@ -30,6 +31,39 @@ struct sock *scsi_nl_sock = NULL; EXPORT_SYMBOL_GPL(scsi_nl_sock); +static DEFINE_SPINLOCK(scsi_nl_lock); +static struct list_head scsi_nl_drivers; + +static u32 scsi_nl_state; +#define STATE_EHANDLER_BSY 0x00000001 + +struct scsi_nl_transport { + int (*msg_handler)(struct sk_buff *); + void (*event_handler)(struct notifier_block *, unsigned long, void *); + unsigned int refcnt; + int flags; +}; + +/* flags values (bit flags) */ +#define HANDLER_DELETING 0x1 + +static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] = + { {NULL, }, }; + + +struct scsi_nl_drvr { + struct list_head next; + int (*dmsg_handler)(struct Scsi_Host *shost, void *payload, + u32 len, u32 pid); + void (*devt_handler)(struct notifier_block *nb, + unsigned long event, void *notify_ptr); + struct scsi_host_template *hostt; + u64 vendor_id; + unsigned int refcnt; + int flags; +}; + + /** * scsi_nl_rcv_msg - Receive message handler. @@ -45,8 +79,9 @@ scsi_nl_rcv_msg(struct sk_buff *skb) { struct nlmsghdr *nlh; struct scsi_nl_hdr *hdr; - uint32_t rlen; - int err; + unsigned long flags; + u32 rlen; + int err, tport; while (skb->len >= NLMSG_SPACE(0)) { err = 0; @@ -65,7 +100,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { err = -EBADMSG; - return; + goto next_msg; } hdr = NLMSG_DATA(nlh); @@ -83,12 +118,27 @@ scsi_nl_rcv_msg(struct sk_buff *skb) if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { printk(KERN_WARNING "%s: discarding partial message\n", __func__); - return; + goto next_msg; } /* - * We currently don't support anyone sending us a message + * Deliver message to the appropriate transport */ + spin_lock_irqsave(&scsi_nl_lock, flags); + + tport = hdr->transport; + if ((tport < SCSI_NL_MAX_TRANSPORTS) && + !(transports[tport].flags & HANDLER_DELETING) && + (transports[tport].msg_handler)) { + transports[tport].refcnt++; + spin_unlock_irqrestore(&scsi_nl_lock, flags); + err = transports[tport].msg_handler(skb); + spin_lock_irqsave(&scsi_nl_lock, flags); + transports[tport].refcnt--; + } else + err = -ENOENT; + + spin_unlock_irqrestore(&scsi_nl_lock, flags); next_msg: if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) @@ -110,14 +160,42 @@ static int scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netlink_notify *n = ptr; + struct scsi_nl_drvr *driver; + unsigned long flags; + int tport; if (n->protocol != NETLINK_SCSITRANSPORT) return NOTIFY_DONE; + spin_lock_irqsave(&scsi_nl_lock, flags); + scsi_nl_state |= STATE_EHANDLER_BSY; + /* - * Currently, we are not tracking PID's, etc. There is nothing - * to handle. + * Pass event on to any transports that may be listening */ + for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) { + if (!(transports[tport].flags & HANDLER_DELETING) && + (transports[tport].event_handler)) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + transports[tport].event_handler(this, event, ptr); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + } + + /* + * Pass event on to any drivers that may be listening + */ + list_for_each_entry(driver, &scsi_nl_drivers, next) { + if (!(driver->flags & HANDLER_DELETING) && + (driver->devt_handler)) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + driver->devt_handler(this, event, ptr); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + } + + scsi_nl_state &= ~STATE_EHANDLER_BSY; + spin_unlock_irqrestore(&scsi_nl_lock, flags); return NOTIFY_DONE; } @@ -128,7 +206,281 @@ static struct notifier_block scsi_netlink_notifier = { /** - * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface + * GENERIC SCSI transport receive and event handlers + **/ + +/** + * scsi_generic_msg_handler - receive message handler for GENERIC transport + * messages + * + * @skb: socket receive buffer + * + **/ +static int +scsi_generic_msg_handler(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = nlmsg_hdr(skb); + struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh); + struct scsi_nl_drvr *driver; + struct Scsi_Host *shost; + unsigned long flags; + int err = 0, match, pid; + + pid = NETLINK_CREDS(skb)->pid; + + switch (snlh->msgtype) { + case SCSI_NL_SHOST_VENDOR: + { + struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh); + + /* Locate the driver that corresponds to the message */ + spin_lock_irqsave(&scsi_nl_lock, flags); + match = 0; + list_for_each_entry(driver, &scsi_nl_drivers, next) { + if (driver->vendor_id == msg->vendor_id) { + match = 1; + break; + } + } + + if ((!match) || (!driver->dmsg_handler)) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + err = -ESRCH; + goto rcv_exit; + } + + if (driver->flags & HANDLER_DELETING) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + err = -ESHUTDOWN; + goto rcv_exit; + } + + driver->refcnt++; + spin_unlock_irqrestore(&scsi_nl_lock, flags); + + + /* if successful, scsi_host_lookup takes a shost reference */ + shost = scsi_host_lookup(msg->host_no); + if (!shost) { + err = -ENODEV; + goto driver_exit; + } + + /* is this host owned by the vendor ? */ + if (shost->hostt != driver->hostt) { + err = -EINVAL; + goto vendormsg_put; + } + + /* pass message on to the driver */ + err = driver->dmsg_handler(shost, (void *)&msg[1], + msg->vmsg_datalen, pid); + +vendormsg_put: + /* release reference by scsi_host_lookup */ + scsi_host_put(shost); + +driver_exit: + /* release our own reference on the registration object */ + spin_lock_irqsave(&scsi_nl_lock, flags); + driver->refcnt--; + spin_unlock_irqrestore(&scsi_nl_lock, flags); + break; + } + + default: + err = -EBADR; + break; + } + +rcv_exit: + if (err) + printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", + __func__, snlh->msgtype, err); + return err; +} + + +/** + * scsi_nl_add_transport - + * Registers message and event handlers for a transport. Enables + * receipt of netlink messages and events to a transport. + * + * @tport: transport registering handlers + * @msg_handler: receive message handler callback + * @event_handler: receive event handler callback + **/ +int +scsi_nl_add_transport(u8 tport, + int (*msg_handler)(struct sk_buff *), + void (*event_handler)(struct notifier_block *, unsigned long, void *)) +{ + unsigned long flags; + int err = 0; + + if (tport >= SCSI_NL_MAX_TRANSPORTS) + return -EINVAL; + + spin_lock_irqsave(&scsi_nl_lock, flags); + + if (scsi_nl_state & STATE_EHANDLER_BSY) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + msleep(1); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + + if (transports[tport].msg_handler || transports[tport].event_handler) { + err = -EALREADY; + goto register_out; + } + + transports[tport].msg_handler = msg_handler; + transports[tport].event_handler = event_handler; + transports[tport].flags = 0; + transports[tport].refcnt = 0; + +register_out: + spin_unlock_irqrestore(&scsi_nl_lock, flags); + + return err; +} +EXPORT_SYMBOL_GPL(scsi_nl_add_transport); + + +/** + * scsi_nl_remove_transport - + * Disable transport receiption of messages and events + * + * @tport: transport deregistering handlers + * + **/ +void +scsi_nl_remove_transport(u8 tport) +{ + unsigned long flags; + + spin_lock_irqsave(&scsi_nl_lock, flags); + if (scsi_nl_state & STATE_EHANDLER_BSY) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + msleep(1); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + + if (tport < SCSI_NL_MAX_TRANSPORTS) { + transports[tport].flags |= HANDLER_DELETING; + + while (transports[tport].refcnt != 0) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + schedule_timeout_uninterruptible(HZ/4); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + transports[tport].msg_handler = NULL; + transports[tport].event_handler = NULL; + transports[tport].flags = 0; + } + + spin_unlock_irqrestore(&scsi_nl_lock, flags); + + return; +} +EXPORT_SYMBOL_GPL(scsi_nl_remove_transport); + + +/** + * scsi_nl_add_driver - + * A driver is registering its interfaces for SCSI netlink messages + * + * @vendor_id: A unique identification value for the driver. + * @hostt: address of the driver's host template. Used + * to verify an shost is bound to the driver + * @nlmsg_handler: receive message handler callback + * @nlevt_handler: receive event handler callback + * + * Returns: + * 0 on Success + * error result otherwise + **/ +int +scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, + int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, + u32 len, u32 pid), + void (*nlevt_handler)(struct notifier_block *nb, + unsigned long event, void *notify_ptr)) +{ + struct scsi_nl_drvr *driver; + unsigned long flags; + + driver = kzalloc(sizeof(*driver), GFP_KERNEL); + if (unlikely(!driver)) { + printk(KERN_ERR "%s: allocation failure\n", __func__); + return -ENOMEM; + } + + driver->dmsg_handler = nlmsg_handler; + driver->devt_handler = nlevt_handler; + driver->hostt = hostt; + driver->vendor_id = vendor_id; + + spin_lock_irqsave(&scsi_nl_lock, flags); + if (scsi_nl_state & STATE_EHANDLER_BSY) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + msleep(1); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + list_add_tail(&driver->next, &scsi_nl_drivers); + spin_unlock_irqrestore(&scsi_nl_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(scsi_nl_add_driver); + + +/** + * scsi_nl_remove_driver - + * An driver is unregistering with the SCSI netlink messages + * + * @vendor_id: The unique identification value for the driver. + **/ +void +scsi_nl_remove_driver(u64 vendor_id) +{ + struct scsi_nl_drvr *driver; + unsigned long flags; + + spin_lock_irqsave(&scsi_nl_lock, flags); + if (scsi_nl_state & STATE_EHANDLER_BSY) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + msleep(1); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + + list_for_each_entry(driver, &scsi_nl_drivers, next) { + if (driver->vendor_id == vendor_id) { + driver->flags |= HANDLER_DELETING; + while (driver->refcnt != 0) { + spin_unlock_irqrestore(&scsi_nl_lock, flags); + schedule_timeout_uninterruptible(HZ/4); + spin_lock_irqsave(&scsi_nl_lock, flags); + } + list_del(&driver->next); + kfree(driver); + spin_unlock_irqrestore(&scsi_nl_lock, flags); + return; + } + } + + spin_unlock_irqrestore(&scsi_nl_lock, flags); + + printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n", + __func__, (unsigned long long)vendor_id); + return; +} +EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); + + +/** + * scsi_netlink_init - Called by SCSI subsystem to intialize + * the SCSI transport netlink interface * **/ void @@ -136,6 +488,8 @@ scsi_netlink_init(void) { int error; + INIT_LIST_HEAD(&scsi_nl_drivers); + error = netlink_register_notifier(&scsi_netlink_notifier); if (error) { printk(KERN_ERR "%s: register of event handler failed - %d\n", @@ -150,8 +504,15 @@ scsi_netlink_init(void) printk(KERN_ERR "%s: register of recieve handler failed\n", __func__); netlink_unregister_notifier(&scsi_netlink_notifier); + return; } + /* Register the entry points for the generic SCSI transport */ + error = scsi_nl_add_transport(SCSI_NL_TRANSPORT, + scsi_generic_msg_handler, NULL); + if (error) + printk(KERN_ERR "%s: register of GENERIC transport handler" + " failed - %d\n", __func__, error); return; } @@ -163,6 +524,8 @@ scsi_netlink_init(void) void scsi_netlink_exit(void) { + scsi_nl_remove_transport(SCSI_NL_TRANSPORT); + if (scsi_nl_sock) { netlink_kernel_release(scsi_nl_sock); netlink_unregister_notifier(&scsi_netlink_notifier); @@ -172,3 +535,147 @@ scsi_netlink_exit(void) } +/* + * Exported Interfaces + */ + +/** + * scsi_nl_send_transport_msg - + * Generic function to send a single message from a SCSI transport to + * a single process + * + * @pid: receiving pid + * @hdr: message payload + * + **/ +void +scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + const char *fn; + char *datab; + u32 len, skblen; + int err; + + if (!scsi_nl_sock) { + err = -ENOENT; + fn = "netlink socket"; + goto msg_fail; + } + + len = NLMSG_SPACE(hdr->msglen); + skblen = NLMSG_SPACE(len); + + skb = alloc_skb(skblen, GFP_KERNEL); + if (!skb) { + err = -ENOBUFS; + fn = "alloc_skb"; + goto msg_fail; + } + + nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0); + if (!nlh) { + err = -ENOBUFS; + fn = "nlmsg_put"; + goto msg_fail_skb; + } + datab = NLMSG_DATA(nlh); + memcpy(datab, hdr, hdr->msglen); + + err = nlmsg_unicast(scsi_nl_sock, skb, pid); + if (err < 0) { + fn = "nlmsg_unicast"; + /* nlmsg_unicast already kfree_skb'd */ + goto msg_fail; + } + + return; + +msg_fail_skb: + kfree_skb(skb); +msg_fail: + printk(KERN_WARNING + "%s: Dropped Message : pid %d Transport %d, msgtype x%x, " + "msglen %d: %s : err %d\n", + __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen, + fn, err); + return; +} +EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg); + + +/** + * scsi_nl_send_vendor_msg - called to send a shost vendor unique message + * to a specific process id. + * + * @pid: process id of the receiver + * @host_no: host # sending the message + * @vendor_id: unique identifier for the driver's vendor + * @data_len: amount, in bytes, of vendor unique payload data + * @data_buf: pointer to vendor unique data buffer + * + * Returns: + * 0 on succesful return + * otherwise, failing error code + * + * Notes: + * This routine assumes no locks are held on entry. + */ +int +scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, + char *data_buf, u32 data_len) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + struct scsi_nl_host_vendor_msg *msg; + u32 len, skblen; + int err; + + if (!scsi_nl_sock) { + err = -ENOENT; + goto send_vendor_fail; + } + + len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len); + skblen = NLMSG_SPACE(len); + + skb = alloc_skb(skblen, GFP_KERNEL); + if (!skb) { + err = -ENOBUFS; + goto send_vendor_fail; + } + + nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, + skblen - sizeof(*nlh), 0); + if (!nlh) { + err = -ENOBUFS; + goto send_vendor_fail_skb; + } + msg = NLMSG_DATA(nlh); + + INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT, + SCSI_NL_SHOST_VENDOR, len); + msg->vendor_id = vendor_id; + msg->host_no = host_no; + msg->vmsg_datalen = data_len; /* bytes */ + memcpy(&msg[1], data_buf, data_len); + + err = nlmsg_unicast(scsi_nl_sock, skb, pid); + if (err) + /* nlmsg_multicast already kfree_skb'd */ + goto send_vendor_fail; + + return 0; + +send_vendor_fail_skb: + kfree_skb(skb); +send_vendor_fail: + printk(KERN_WARNING + "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n", + __func__, host_no, err); + return err; +} +EXPORT_SYMBOL(scsi_nl_send_vendor_msg); + + diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 79f0f7511204..6cddd5dd323c 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -4,6 +4,7 @@ #include <linux/device.h> struct request_queue; +struct request; struct scsi_cmnd; struct scsi_device; struct scsi_host_template; @@ -27,7 +28,6 @@ extern void scsi_exit_hosts(void); extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); -extern void __scsi_done(struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING void scsi_log_send(struct scsi_cmnd *cmd); void scsi_log_completion(struct scsi_cmnd *cmd, int disposition); @@ -49,10 +49,7 @@ extern int __init scsi_init_devinfo(void); extern void scsi_exit_devinfo(void); /* scsi_error.c */ -extern void scsi_add_timer(struct scsi_cmnd *, int, - void (*)(struct scsi_cmnd *)); -extern int scsi_delete_timer(struct scsi_cmnd *); -extern void scsi_times_out(struct scsi_cmnd *cmd); +extern enum blk_eh_timer_return scsi_times_out(struct request *req); extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); extern void scsi_eh_wakeup(struct Scsi_Host *shost); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index c6a904a45bf9..82f7b2dd08a2 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -259,8 +259,8 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) int error = -ENXIO; shost = scsi_host_lookup(host); - if (IS_ERR(shost)) - return PTR_ERR(shost); + if (!shost) + return error; if (shost->transportt->user_scan) error = shost->transportt->user_scan(shost, channel, id, lun); @@ -287,8 +287,8 @@ static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) int error = -ENXIO; shost = scsi_host_lookup(host); - if (IS_ERR(shost)) - return PTR_ERR(shost); + if (!shost) + return error; sdev = scsi_device_lookup(shost, channel, id, lun); if (sdev) { scsi_remove_device(sdev); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 34d0de6cd511..334862e26a1b 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -730,6 +730,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, int *bflags, int async) { + int ret; + /* * XXX do not save the inquiry, since it can change underneath us, * save just vendor/model/rev. @@ -885,7 +887,17 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, /* set the device running here so that slave configure * may do I/O */ - scsi_device_set_state(sdev, SDEV_RUNNING); + ret = scsi_device_set_state(sdev, SDEV_RUNNING); + if (ret) { + ret = scsi_device_set_state(sdev, SDEV_BLOCK); + + if (ret) { + sdev_printk(KERN_ERR, sdev, + "in wrong state %s to complete scan\n", + scsi_device_state_name(sdev->sdev_state)); + return SCSI_SCAN_NO_RESPONSE; + } + } if (*bflags & BLIST_MS_192_BYTES_FOR_3F) sdev->use_192_bytes_for_3f = 1; @@ -899,7 +911,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, transport_configure_device(&sdev->sdev_gendev); if (sdev->host->hostt->slave_configure) { - int ret = sdev->host->hostt->slave_configure(sdev); + ret = sdev->host->hostt->slave_configure(sdev); if (ret) { /* * if LLDD reports slave not present, don't clutter @@ -994,7 +1006,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, */ sdev = scsi_device_lookup_by_target(starget, lun); if (sdev) { - if (rescan || sdev->sdev_state != SDEV_CREATED) { + if (rescan || !scsi_device_created(sdev)) { SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: device exists on %s\n", sdev->sdev_gendev.bus_id)); @@ -1467,7 +1479,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, kfree(lun_data); out: scsi_device_put(sdev); - if (sdev->sdev_state == SDEV_CREATED) + if (scsi_device_created(sdev)) /* * the sdev we used didn't appear in the report luns scan */ diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ab3c71869be5..93c28f30bbd7 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -34,6 +34,7 @@ static const struct { { SDEV_QUIESCE, "quiesce" }, { SDEV_OFFLINE, "offline" }, { SDEV_BLOCK, "blocked" }, + { SDEV_CREATED_BLOCK, "created-blocked" }, }; const char *scsi_device_state_name(enum scsi_device_state state) @@ -560,12 +561,15 @@ sdev_rd_attr (vendor, "%.8s\n"); sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); +/* + * TODO: can we make these symlinks to the block layer ones? + */ static ssize_t sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf) { struct scsi_device *sdev; sdev = to_scsi_device(dev); - return snprintf (buf, 20, "%d\n", sdev->timeout / HZ); + return snprintf(buf, 20, "%d\n", sdev->request_queue->rq_timeout / HZ); } static ssize_t @@ -576,7 +580,7 @@ sdev_store_timeout (struct device *dev, struct device_attribute *attr, int timeout; sdev = to_scsi_device(dev); sscanf (buf, "%d\n", &timeout); - sdev->timeout = timeout * HZ; + blk_queue_rq_timeout(sdev->request_queue, timeout * HZ); return count; } static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout); diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 257e097c39af..48ba413f7f6a 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -362,7 +362,7 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, int err; dprintk("%lx %u\n", uaddr, len); - err = blk_rq_map_user(q, rq, (void *)uaddr, len); + err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL); if (err) { /* * TODO: need to fixup sg_tablesize, max_segment_size, @@ -460,7 +460,7 @@ int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, /* TODO: replace with a O(1) alg */ shost = scsi_host_lookup(host_no); - if (IS_ERR(shost)) { + if (!shost) { printk(KERN_ERR "Could not find host no %d\n", host_no); return -EINVAL; } @@ -550,7 +550,7 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); shost = scsi_host_lookup(host_no); - if (IS_ERR(shost)) { + if (!shost) { printk(KERN_ERR "Could not find host no %d\n", host_no); return err; } @@ -603,7 +603,7 @@ int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id); shost = scsi_host_lookup(host_no); - if (IS_ERR(shost)) { + if (!shost) { printk(KERN_ERR "Could not find host no %d\n", host_no); return err; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 56823fd1fb84..d5f7653bb94b 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -40,31 +40,7 @@ static int fc_queue_work(struct Scsi_Host *, struct work_struct *); static void fc_vport_sched_delete(struct work_struct *work); - -/* - * This is a temporary carrier for creating a vport. It will eventually - * be replaced by a real message definition for sgio or netlink. - * - * fc_vport_identifiers: This set of data contains all elements - * to uniquely identify and instantiate a FC virtual port. - * - * Notes: - * symbolic_name: The driver is to append the symbolic_name string data - * to the symbolic_node_name data that it generates by default. - * the resulting combination should then be registered with the switch. - * It is expected that things like Xen may stuff a VM title into - * this field. - */ -struct fc_vport_identifiers { - u64 node_name; - u64 port_name; - u32 roles; - bool disable; - enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */ - char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN]; -}; - -static int fc_vport_create(struct Scsi_Host *shost, int channel, +static int fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev, struct fc_vport_identifiers *ids, struct fc_vport **vport); @@ -1760,7 +1736,7 @@ store_fc_host_vport_create(struct device *dev, struct device_attribute *attr, vid.disable = false; /* always enabled */ /* we only allow support on Channel 0 !!! */ - stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport); + stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport); return stat ? stat : count; } static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL, @@ -1950,15 +1926,15 @@ static int fc_vport_match(struct attribute_container *cont, * Notes: * This routine assumes no locks are held on entry. */ -static enum scsi_eh_timer_return +static enum blk_eh_timer_return fc_timed_out(struct scsi_cmnd *scmd) { struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device)); if (rport->port_state == FC_PORTSTATE_BLOCKED) - return EH_RESET_TIMER; + return BLK_EH_RESET_TIMER; - return EH_NOT_HANDLED; + return BLK_EH_NOT_HANDLED; } /* @@ -3103,7 +3079,7 @@ fc_scsi_scan_rport(struct work_struct *work) /** - * fc_vport_create - allocates and creates a FC virtual port. + * fc_vport_setup - allocates and creates a FC virtual port. * @shost: scsi host the virtual port is connected to. * @channel: Channel on shost port connected to. * @pdev: parent device for vport @@ -3118,7 +3094,7 @@ fc_scsi_scan_rport(struct work_struct *work) * This routine assumes no locks are held on entry. */ static int -fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev, +fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev, struct fc_vport_identifiers *ids, struct fc_vport **ret_vport) { struct fc_host_attrs *fc_host = shost_to_fc_host(shost); @@ -3231,6 +3207,28 @@ delete_vport: return error; } +/** + * fc_vport_create - Admin App or LLDD requests creation of a vport + * @shost: scsi host the virtual port is connected to. + * @channel: channel on shost port connected to. + * @ids: The world wide names, FC4 port roles, etc for + * the virtual port. + * + * Notes: + * This routine assumes no locks are held on entry. + */ +struct fc_vport * +fc_vport_create(struct Scsi_Host *shost, int channel, + struct fc_vport_identifiers *ids) +{ + int stat; + struct fc_vport *vport; + + stat = fc_vport_setup(shost, channel, &shost->shost_gendev, + ids, &vport); + return stat ? NULL : vport; +} +EXPORT_SYMBOL(fc_vport_create); /** * fc_vport_terminate - Admin App or LLDD requests termination of a vport diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 043c3921164f..0ce5f7cdfe2a 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1361,7 +1361,7 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport, return -EINVAL; shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); - if (IS_ERR(shost)) { + if (!shost) { printk(KERN_ERR "target discovery could not find host no %u\n", ev->u.tgt_dscvr.host_no); return -ENODEV; @@ -1387,7 +1387,7 @@ iscsi_set_host_param(struct iscsi_transport *transport, return -ENOSYS; shost = scsi_host_lookup(ev->u.set_host_param.host_no); - if (IS_ERR(shost)) { + if (!shost) { printk(KERN_ERR "set_host_param could not find host no %u\n", ev->u.set_host_param.host_no); return -ENODEV; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e5e7d7856454..a7b53be63367 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -47,6 +47,7 @@ #include <linux/blkpg.h> #include <linux/delay.h> #include <linux/mutex.h> +#include <linux/string_helpers.h> #include <asm/uaccess.h> #include <scsi/scsi.h> @@ -86,6 +87,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); +#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) +#define SD_MINORS 16 +#else +#define SD_MINORS 0 +#endif + static int sd_revalidate_disk(struct gendisk *); static int sd_probe(struct device *); static int sd_remove(struct device *); @@ -159,7 +166,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, sd_print_sense_hdr(sdkp, &sshdr); return -EINVAL; } - sd_revalidate_disk(sdkp->disk); + revalidate_disk(sdkp->disk); return count; } @@ -377,7 +384,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) sector_t block = rq->sector; sector_t threshold; unsigned int this_count = rq->nr_sectors; - unsigned int timeout = sdp->timeout; int ret; if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { @@ -578,7 +584,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->transfersize = sdp->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = SD_MAX_RETRIES; - SCpnt->timeout_per_command = timeout; /* * This indicates that the command is ready from our end to be @@ -910,7 +915,7 @@ static void sd_rescan(struct device *dev) struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); if (sdkp) { - sd_revalidate_disk(sdkp->disk); + revalidate_disk(sdkp->disk); scsi_disk_put(sdkp); } } @@ -1429,27 +1434,21 @@ got_data: */ sector_size = 512; } + blk_queue_hardsect_size(sdp->request_queue, sector_size); + { - /* - * The msdos fs needs to know the hardware sector size - * So I have created this table. See ll_rw_blk.c - * Jacques Gelinas (Jacques@solucorp.qc.ca) - */ - int hard_sector = sector_size; - sector_t sz = (sdkp->capacity/2) * (hard_sector/256); - struct request_queue *queue = sdp->request_queue; - sector_t mb = sz; + char cap_str_2[10], cap_str_10[10]; + u64 sz = sdkp->capacity << ffz(~sector_size); - blk_queue_hardsect_size(queue, hard_sector); - /* avoid 64-bit division on 32-bit platforms */ - sector_div(sz, 625); - mb -= sz - 974; - sector_div(mb, 1950); + string_get_size(sz, STRING_UNITS_2, cap_str_2, + sizeof(cap_str_2)); + string_get_size(sz, STRING_UNITS_10, cap_str_10, + sizeof(cap_str_10)); sd_printk(KERN_NOTICE, sdkp, - "%llu %d-byte hardware sectors (%llu MB)\n", + "%llu %d-byte hardware sectors: (%s/%s)\n", (unsigned long long)sdkp->capacity, - hard_sector, (unsigned long long)mb); + sector_size, cap_str_10, cap_str_2); } /* Rescale capacity to 512-byte units */ @@ -1764,6 +1763,52 @@ static int sd_revalidate_disk(struct gendisk *disk) } /** + * sd_format_disk_name - format disk name + * @prefix: name prefix - ie. "sd" for SCSI disks + * @index: index of the disk to format name for + * @buf: output buffer + * @buflen: length of the output buffer + * + * SCSI disk names starts at sda. The 26th device is sdz and the + * 27th is sdaa. The last one for two lettered suffix is sdzz + * which is followed by sdaaa. + * + * This is basically 26 base counting with one extra 'nil' entry + * at the beggining from the second digit on and can be + * determined using similar method as 26 base conversion with the + * index shifted -1 after each digit is computed. + * + * CONTEXT: + * Don't care. + * + * RETURNS: + * 0 on success, -errno on failure. + */ +static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen) +{ + const int base = 'z' - 'a' + 1; + char *begin = buf + strlen(prefix); + char *end = buf + buflen; + char *p; + int unit; + + p = end - 1; + *p = '\0'; + unit = base; + do { + if (p == begin) + return -EINVAL; + *--p = 'a' + (index % unit); + index = (index / unit) - 1; + } while (index >= 0); + + memmove(begin, p, end - p); + memcpy(buf, prefix, strlen(prefix)); + + return 0; +} + +/** * sd_probe - called during driver initialization and whenever a * new scsi device is attached to the system. It is called once * for each scsi device (not just disks) present. @@ -1801,7 +1846,7 @@ static int sd_probe(struct device *dev) if (!sdkp) goto out; - gd = alloc_disk(16); + gd = alloc_disk(SD_MINORS); if (!gd) goto out_free; @@ -1815,8 +1860,8 @@ static int sd_probe(struct device *dev) if (error) goto out_put; - error = -EBUSY; - if (index >= SD_MAX_DISKS) + error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN); + if (error) goto out_free_index; sdkp->device = sdp; @@ -1826,11 +1871,12 @@ static int sd_probe(struct device *dev) sdkp->openers = 0; sdkp->previous_state = 1; - if (!sdp->timeout) { + if (!sdp->request_queue->rq_timeout) { if (sdp->type != TYPE_MOD) - sdp->timeout = SD_TIMEOUT; + blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); else - sdp->timeout = SD_MOD_TIMEOUT; + blk_queue_rq_timeout(sdp->request_queue, + SD_MOD_TIMEOUT); } device_initialize(&sdkp->dev); @@ -1843,24 +1889,12 @@ static int sd_probe(struct device *dev) get_device(&sdp->sdev_gendev); - gd->major = sd_major((index & 0xf0) >> 4); - gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); - gd->minors = 16; - gd->fops = &sd_fops; - - if (index < 26) { - sprintf(gd->disk_name, "sd%c", 'a' + index % 26); - } else if (index < (26 + 1) * 26) { - sprintf(gd->disk_name, "sd%c%c", - 'a' + index / 26 - 1,'a' + index % 26); - } else { - const unsigned int m1 = (index / 26 - 1) / 26 - 1; - const unsigned int m2 = (index / 26 - 1) % 26; - const unsigned int m3 = index % 26; - sprintf(gd->disk_name, "sd%c%c%c", - 'a' + m1, 'a' + m2, 'a' + m3); + if (index < SD_MAX_DISKS) { + gd->major = sd_major((index & 0xf0) >> 4); + gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); + gd->minors = SD_MINORS; } - + gd->fops = &sd_fops; gd->private_data = &sdkp->driver; gd->queue = sdkp->device->request_queue; @@ -1869,7 +1903,7 @@ static int sd_probe(struct device *dev) blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); gd->driverfs_dev = &sdp->sdev_gendev; - gd->flags = GENHD_FL_DRIVERFS; + gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS; if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 661f9f21650a..ba9b9bbd4e73 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -47,7 +47,6 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include <linux/seq_file.h> #include <linux/blkdev.h> #include <linux/delay.h> -#include <linux/scatterlist.h> #include <linux/blktrace_api.h> #include <linux/smp_lock.h> @@ -69,7 +68,6 @@ static void sg_proc_cleanup(void); #endif #define SG_ALLOW_DIO_DEF 0 -#define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ #define SG_MAX_DEVS 32768 @@ -118,8 +116,8 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */ unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */ unsigned bufflen; /* Size of (aggregate) data buffer */ - unsigned b_malloc_len; /* actual len malloc'ed in buffer */ - struct scatterlist *buffer;/* scatter list */ + struct page **pages; + int page_order; char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */ unsigned char cmd_opcode; /* first byte of command */ } Sg_scatter_hold; @@ -137,6 +135,8 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ char orphan; /* 1 -> drop on sight, 0 -> normal */ char sg_io_owned; /* 1 -> packet belongs to SG_IO */ volatile char done; /* 0->before bh, 1->before read, 2->read */ + struct request *rq; + struct bio *bio; } Sg_request; typedef struct sg_fd { /* holds the state of a file descriptor */ @@ -175,8 +175,8 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ static int sg_fasync(int fd, struct file *filp, int mode); /* tasklet or soft irq callback */ -static void sg_cmd_done(void *data, char *sense, int result, int resid); -static int sg_start_req(Sg_request * srp); +static void sg_rq_end_io(struct request *rq, int uptodate); +static int sg_start_req(Sg_request *srp, unsigned char *cmd); static void sg_finish_rem_req(Sg_request * srp); static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size); static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, @@ -188,17 +188,11 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, int read_only, Sg_request **o_srp); static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); -static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, - int wr_xf, int *countp, unsigned char __user **up); -static int sg_write_xfer(Sg_request * srp); -static int sg_read_xfer(Sg_request * srp); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); static void sg_remove_scat(Sg_scatter_hold * schp); static void sg_build_reserve(Sg_fd * sfp, int req_size); static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size); static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp); -static struct page *sg_page_malloc(int rqSz, int lowDma, int *retSzp); -static void sg_page_free(struct page *page, int size); static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev); static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); @@ -206,7 +200,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); -static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); static Sg_device *sg_get_dev(int dev); #ifdef CONFIG_SCSI_PROC_FS static int sg_last_dev(void); @@ -529,8 +522,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) err = -EFAULT; goto err_out; } - err = sg_read_xfer(srp); - err_out: +err_out: sg_finish_rem_req(srp); return (0 == err) ? count : err; } @@ -612,7 +604,10 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) else hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE; hp->dxfer_len = mxsize; - hp->dxferp = (char __user *)buf + cmd_size; + if (hp->dxfer_direction == SG_DXFER_TO_DEV) + hp->dxferp = (char __user *)buf + cmd_size; + else + hp->dxferp = NULL; hp->sbp = NULL; hp->timeout = old_hdr.reply_len; /* structure abuse ... */ hp->flags = input_size; /* structure abuse ... */ @@ -732,16 +727,12 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, SCSI_LOG_TIMEOUT(4, printk("sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", (int) cmnd[0], (int) hp->cmd_len)); - if ((k = sg_start_req(srp))) { + k = sg_start_req(srp, cmnd); + if (k) { SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k)); sg_finish_rem_req(srp); return k; /* probably out of space --> ENOMEM */ } - if ((k = sg_write_xfer(srp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_common_write: write_xfer, bad address\n")); - sg_finish_rem_req(srp); - return k; - } if (sdp->detached) { sg_finish_rem_req(srp); return -ENODEV; @@ -763,20 +754,11 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, break; } hp->duration = jiffies_to_msecs(jiffies); -/* Now send everything of to mid-level. The next time we hear about this - packet is when sg_cmd_done() is called (i.e. a callback). */ - if (scsi_execute_async(sdp->device, cmnd, hp->cmd_len, data_dir, srp->data.buffer, - hp->dxfer_len, srp->data.k_use_sg, timeout, - SG_DEFAULT_RETRIES, srp, sg_cmd_done, - GFP_ATOMIC)) { - SCSI_LOG_TIMEOUT(1, printk("sg_common_write: scsi_execute_async failed\n")); - /* - * most likely out of mem, but could also be a bad map - */ - sg_finish_rem_req(srp); - return -ENOMEM; - } else - return 0; + + srp->rq->timeout = timeout; + blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk, + srp->rq, 1, sg_rq_end_io); + return 0; } static int @@ -1192,8 +1174,7 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) Sg_fd *sfp; unsigned long offset, len, sa; Sg_scatter_hold *rsv_schp; - struct scatterlist *sg; - int k; + int k, length; if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data))) return VM_FAULT_SIGBUS; @@ -1203,15 +1184,14 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_SIGBUS; SCSI_LOG_TIMEOUT(3, printk("sg_vma_fault: offset=%lu, scatg=%d\n", offset, rsv_schp->k_use_sg)); - sg = rsv_schp->buffer; sa = vma->vm_start; - for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, sg = sg_next(sg)) { + length = 1 << (PAGE_SHIFT + rsv_schp->page_order); + for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) { len = vma->vm_end - sa; - len = (len < sg->length) ? len : sg->length; + len = (len < length) ? len : length; if (offset < len) { - struct page *page; - page = virt_to_page(page_address(sg_page(sg)) + offset); + struct page *page = nth_page(rsv_schp->pages[k], + offset >> PAGE_SHIFT); get_page(page); /* increment page count */ vmf->page = page; return 0; /* success */ @@ -1233,8 +1213,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) Sg_fd *sfp; unsigned long req_sz, len, sa; Sg_scatter_hold *rsv_schp; - int k; - struct scatterlist *sg; + int k, length; if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data))) return -ENXIO; @@ -1248,11 +1227,10 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) return -ENOMEM; /* cannot map more than reserved buffer */ sa = vma->vm_start; - sg = rsv_schp->buffer; - for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, sg = sg_next(sg)) { + length = 1 << (PAGE_SHIFT + rsv_schp->page_order); + for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) { len = vma->vm_end - sa; - len = (len < sg->length) ? len : sg->length; + len = (len < length) ? len : length; sa += len; } @@ -1263,16 +1241,19 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) return 0; } -/* This function is a "bottom half" handler that is called by the - * mid level when a command is completed (or has failed). */ -static void -sg_cmd_done(void *data, char *sense, int result, int resid) +/* + * This function is a "bottom half" handler that is called by the mid + * level when a command is completed (or has failed). + */ +static void sg_rq_end_io(struct request *rq, int uptodate) { - Sg_request *srp = data; + struct sg_request *srp = rq->end_io_data; Sg_device *sdp = NULL; Sg_fd *sfp; unsigned long iflags; unsigned int ms; + char *sense; + int result, resid; if (NULL == srp) { printk(KERN_ERR "sg_cmd_done: NULL request\n"); @@ -1286,6 +1267,9 @@ sg_cmd_done(void *data, char *sense, int result, int resid) return; } + sense = rq->sense; + result = rq->errors; + resid = rq->data_len; SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", sdp->disk->disk_name, srp->header.pack_id, result)); @@ -1296,7 +1280,6 @@ sg_cmd_done(void *data, char *sense, int result, int resid) if (0 != result) { struct scsi_sense_hdr sshdr; - memcpy(srp->sense_b, sense, sizeof (srp->sense_b)); srp->header.status = 0xff & result; srp->header.masked_status = status_byte(result); srp->header.msg_status = msg_byte(result); @@ -1634,37 +1617,79 @@ exit_sg(void) idr_destroy(&sg_index_idr); } -static int -sg_start_req(Sg_request * srp) +static int sg_start_req(Sg_request *srp, unsigned char *cmd) { int res; + struct request *rq; Sg_fd *sfp = srp->parentfp; sg_io_hdr_t *hp = &srp->header; int dxfer_len = (int) hp->dxfer_len; int dxfer_dir = hp->dxfer_direction; + unsigned int iov_count = hp->iovec_count; Sg_scatter_hold *req_schp = &srp->data; Sg_scatter_hold *rsv_schp = &sfp->reserve; + struct request_queue *q = sfp->parentdp->device->request_queue; + struct rq_map_data *md, map_data; + int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; + + SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", + dxfer_len)); + + rq = blk_get_request(q, rw, GFP_ATOMIC); + if (!rq) + return -ENOMEM; + + memcpy(rq->cmd, cmd, hp->cmd_len); + + rq->cmd_len = hp->cmd_len; + rq->cmd_type = REQ_TYPE_BLOCK_PC; + + srp->rq = rq; + rq->end_io_data = srp; + rq->sense = srp->sense_b; + rq->retries = SG_DEFAULT_RETRIES; - SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) return 0; - if (sg_allow_dio && (hp->flags & SG_FLAG_DIRECT_IO) && - (dxfer_dir != SG_DXFER_UNKNOWN) && (0 == hp->iovec_count) && - (!sfp->parentdp->device->host->unchecked_isa_dma)) { - res = sg_build_direct(srp, sfp, dxfer_len); - if (res <= 0) /* -ve -> error, 0 -> done, 1 -> try indirect */ - return res; - } - if ((!sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) - sg_link_reserve(sfp, srp, dxfer_len); - else { - res = sg_build_indirect(req_schp, sfp, dxfer_len); - if (res) { - sg_remove_scat(req_schp); - return res; + + if (sg_allow_dio && hp->flags & SG_FLAG_DIRECT_IO && + dxfer_dir != SG_DXFER_UNKNOWN && !iov_count && + !sfp->parentdp->device->host->unchecked_isa_dma && + blk_rq_aligned(q, hp->dxferp, dxfer_len)) + md = NULL; + else + md = &map_data; + + if (md) { + if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen) + sg_link_reserve(sfp, srp, dxfer_len); + else { + res = sg_build_indirect(req_schp, sfp, dxfer_len); + if (res) + return res; } + + md->pages = req_schp->pages; + md->page_order = req_schp->page_order; + md->nr_entries = req_schp->k_use_sg; } - return 0; + + if (iov_count) + res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count, + hp->dxfer_len, GFP_ATOMIC); + else + res = blk_rq_map_user(q, rq, md, hp->dxferp, + hp->dxfer_len, GFP_ATOMIC); + + if (!res) { + srp->bio = rq->bio; + + if (!md) { + req_schp->dio_in_use = 1; + hp->info |= SG_INFO_DIRECT_IO; + } + } + return res; } static void @@ -1678,186 +1703,37 @@ sg_finish_rem_req(Sg_request * srp) sg_unlink_reserve(sfp, srp); else sg_remove_scat(req_schp); + + if (srp->rq) { + if (srp->bio) + blk_rq_unmap_user(srp->bio); + + blk_put_request(srp->rq); + } + sg_remove_request(sfp, srp); } static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize) { - int sg_bufflen = tablesize * sizeof(struct scatterlist); + int sg_bufflen = tablesize * sizeof(struct page *); gfp_t gfp_flags = GFP_ATOMIC | __GFP_NOWARN; - /* - * TODO: test without low_dma, we should not need it since - * the block layer will bounce the buffer for us - * - * XXX(hch): we shouldn't need GFP_DMA for the actual S/G list. - */ - if (sfp->low_dma) - gfp_flags |= GFP_DMA; - schp->buffer = kzalloc(sg_bufflen, gfp_flags); - if (!schp->buffer) + schp->pages = kzalloc(sg_bufflen, gfp_flags); + if (!schp->pages) return -ENOMEM; - sg_init_table(schp->buffer, tablesize); schp->sglist_len = sg_bufflen; return tablesize; /* number of scat_gath elements allocated */ } -#ifdef SG_ALLOW_DIO_CODE -/* vvvvvvvv following code borrowed from st driver's direct IO vvvvvvvvv */ - /* TODO: hopefully we can use the generic block layer code */ - -/* Pin down user pages and put them into a scatter gather list. Returns <= 0 if - - mapping of all pages not successful - (i.e., either completely successful or fails) -*/ -static int -st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, - unsigned long uaddr, size_t count, int rw) -{ - unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned long start = uaddr >> PAGE_SHIFT; - const int nr_pages = end - start; - int res, i, j; - struct page **pages; - - /* User attempted Overflow! */ - if ((uaddr + count) < uaddr) - return -EINVAL; - - /* Too big */ - if (nr_pages > max_pages) - return -ENOMEM; - - /* Hmm? */ - if (count == 0) - return 0; - - if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_ATOMIC)) == NULL) - return -ENOMEM; - - /* Try to fault in all of the necessary pages */ - down_read(¤t->mm->mmap_sem); - /* rw==READ means read from drive, write into memory area */ - res = get_user_pages( - current, - current->mm, - uaddr, - nr_pages, - rw == READ, - 0, /* don't force */ - pages, - NULL); - up_read(¤t->mm->mmap_sem); - - /* Errors and no page mapped should return here */ - if (res < nr_pages) - goto out_unmap; - - for (i=0; i < nr_pages; i++) { - /* FIXME: flush superflous for rw==READ, - * probably wrong function for rw==WRITE - */ - flush_dcache_page(pages[i]); - /* ?? Is locking needed? I don't think so */ - /* if (!trylock_page(pages[i])) - goto out_unlock; */ - } - - sg_set_page(sgl, pages[0], 0, uaddr & ~PAGE_MASK); - if (nr_pages > 1) { - sgl[0].length = PAGE_SIZE - sgl[0].offset; - count -= sgl[0].length; - for (i=1; i < nr_pages ; i++) - sg_set_page(&sgl[i], pages[i], count < PAGE_SIZE ? count : PAGE_SIZE, 0); - } - else { - sgl[0].length = count; - } - - kfree(pages); - return nr_pages; - - out_unmap: - if (res > 0) { - for (j=0; j < res; j++) - page_cache_release(pages[j]); - res = 0; - } - kfree(pages); - return res; -} - - -/* And unmap them... */ -static int -st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages, - int dirtied) -{ - int i; - - for (i=0; i < nr_pages; i++) { - struct page *page = sg_page(&sgl[i]); - - if (dirtied) - SetPageDirty(page); - /* unlock_page(page); */ - /* FIXME: cache flush missing for rw==READ - * FIXME: call the correct reference counting function - */ - page_cache_release(page); - } - - return 0; -} - -/* ^^^^^^^^ above code borrowed from st driver's direct IO ^^^^^^^^^ */ -#endif - - -/* Returns: -ve -> error, 0 -> done, 1 -> try indirect */ -static int -sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len) -{ -#ifdef SG_ALLOW_DIO_CODE - sg_io_hdr_t *hp = &srp->header; - Sg_scatter_hold *schp = &srp->data; - int sg_tablesize = sfp->parentdp->sg_tablesize; - int mx_sc_elems, res; - struct scsi_device *sdev = sfp->parentdp->device; - - if (((unsigned long)hp->dxferp & - queue_dma_alignment(sdev->request_queue)) != 0) - return 1; - - mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize); - if (mx_sc_elems <= 0) { - return 1; - } - res = st_map_user_pages(schp->buffer, mx_sc_elems, - (unsigned long)hp->dxferp, dxfer_len, - (SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0); - if (res <= 0) { - sg_remove_scat(schp); - return 1; - } - schp->k_use_sg = res; - schp->dio_in_use = 1; - hp->info |= SG_INFO_DIRECT_IO; - return 0; -#else - return 1; -#endif -} - static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) { - struct scatterlist *sg; - int ret_sz = 0, k, rem_sz, num, mx_sc_elems; + int ret_sz = 0, i, k, rem_sz, num, mx_sc_elems; int sg_tablesize = sfp->parentdp->sg_tablesize; - int blk_size = buff_size; - struct page *p = NULL; + int blk_size = buff_size, order; + gfp_t gfp_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; if (blk_size < 0) return -EFAULT; @@ -1881,15 +1757,26 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) } else scatter_elem_sz_prev = num; } - for (k = 0, sg = schp->buffer, rem_sz = blk_size; - (rem_sz > 0) && (k < mx_sc_elems); - ++k, rem_sz -= ret_sz, sg = sg_next(sg)) { - + + if (sfp->low_dma) + gfp_mask |= GFP_DMA; + + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + gfp_mask |= __GFP_ZERO; + + order = get_order(num); +retry: + ret_sz = 1 << (PAGE_SHIFT + order); + + for (k = 0, rem_sz = blk_size; rem_sz > 0 && k < mx_sc_elems; + k++, rem_sz -= ret_sz) { + num = (rem_sz > scatter_elem_sz_prev) ? - scatter_elem_sz_prev : rem_sz; - p = sg_page_malloc(num, sfp->low_dma, &ret_sz); - if (!p) - return -ENOMEM; + scatter_elem_sz_prev : rem_sz; + + schp->pages[k] = alloc_pages(gfp_mask, order); + if (!schp->pages[k]) + goto out; if (num == scatter_elem_sz_prev) { if (unlikely(ret_sz > scatter_elem_sz_prev)) { @@ -1897,12 +1784,12 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) scatter_elem_sz_prev = ret_sz; } } - sg_set_page(sg, p, (ret_sz > num) ? num : ret_sz, 0); SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " "ret_sz=%d\n", k, num, ret_sz)); } /* end of for loop */ + schp->page_order = order; schp->k_use_sg = k; SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, " "rem_sz=%d\n", k, rem_sz)); @@ -1910,223 +1797,42 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) schp->bufflen = blk_size; if (rem_sz > 0) /* must have failed */ return -ENOMEM; - return 0; -} - -static int -sg_write_xfer(Sg_request * srp) -{ - sg_io_hdr_t *hp = &srp->header; - Sg_scatter_hold *schp = &srp->data; - struct scatterlist *sg = schp->buffer; - int num_xfer = 0; - int j, k, onum, usglen, ksglen, res; - int iovec_count = (int) hp->iovec_count; - int dxfer_dir = hp->dxfer_direction; - unsigned char *p; - unsigned char __user *up; - int new_interface = ('\0' == hp->interface_id) ? 0 : 1; - - if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_TO_DEV == dxfer_dir) || - (SG_DXFER_TO_FROM_DEV == dxfer_dir)) { - num_xfer = (int) (new_interface ? hp->dxfer_len : hp->flags); - if (schp->bufflen < num_xfer) - num_xfer = schp->bufflen; - } - if ((num_xfer <= 0) || (schp->dio_in_use) || - (new_interface - && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags))) - return 0; - - SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n", - num_xfer, iovec_count, schp->k_use_sg)); - if (iovec_count) { - onum = iovec_count; - if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum)) - return -EFAULT; - } else - onum = 1; - - ksglen = sg->length; - p = page_address(sg_page(sg)); - for (j = 0, k = 0; j < onum; ++j) { - res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up); - if (res) - return res; - - for (; p; sg = sg_next(sg), ksglen = sg->length, - p = page_address(sg_page(sg))) { - if (usglen <= 0) - break; - if (ksglen > usglen) { - if (usglen >= num_xfer) { - if (__copy_from_user(p, up, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_from_user(p, up, usglen)) - return -EFAULT; - p += usglen; - ksglen -= usglen; - break; - } else { - if (ksglen >= num_xfer) { - if (__copy_from_user(p, up, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_from_user(p, up, ksglen)) - return -EFAULT; - up += ksglen; - usglen -= ksglen; - } - ++k; - if (k >= schp->k_use_sg) - return 0; - } - } - - return 0; -} +out: + for (i = 0; i < k; i++) + __free_pages(schp->pages[k], order); -static int -sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, - int wr_xf, int *countp, unsigned char __user **up) -{ - int num_xfer = (int) hp->dxfer_len; - unsigned char __user *p = hp->dxferp; - int count; + if (--order >= 0) + goto retry; - if (0 == sg_num) { - if (wr_xf && ('\0' == hp->interface_id)) - count = (int) hp->flags; /* holds "old" input_size */ - else - count = num_xfer; - } else { - sg_iovec_t iovec; - if (__copy_from_user(&iovec, p + ind*SZ_SG_IOVEC, SZ_SG_IOVEC)) - return -EFAULT; - p = iovec.iov_base; - count = (int) iovec.iov_len; - } - if (!access_ok(wr_xf ? VERIFY_READ : VERIFY_WRITE, p, count)) - return -EFAULT; - if (up) - *up = p; - if (countp) - *countp = count; - return 0; + return -ENOMEM; } static void sg_remove_scat(Sg_scatter_hold * schp) { SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg)); - if (schp->buffer && (schp->sglist_len > 0)) { - struct scatterlist *sg = schp->buffer; - - if (schp->dio_in_use) { -#ifdef SG_ALLOW_DIO_CODE - st_unmap_user_pages(sg, schp->k_use_sg, TRUE); -#endif - } else { + if (schp->pages && schp->sglist_len > 0) { + if (!schp->dio_in_use) { int k; - for (k = 0; (k < schp->k_use_sg) && sg_page(sg); - ++k, sg = sg_next(sg)) { + for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) { SCSI_LOG_TIMEOUT(5, printk( - "sg_remove_scat: k=%d, pg=0x%p, len=%d\n", - k, sg_page(sg), sg->length)); - sg_page_free(sg_page(sg), sg->length); + "sg_remove_scat: k=%d, pg=0x%p\n", + k, schp->pages[k])); + __free_pages(schp->pages[k], schp->page_order); } - } - kfree(schp->buffer); - } - memset(schp, 0, sizeof (*schp)); -} -static int -sg_read_xfer(Sg_request * srp) -{ - sg_io_hdr_t *hp = &srp->header; - Sg_scatter_hold *schp = &srp->data; - struct scatterlist *sg = schp->buffer; - int num_xfer = 0; - int j, k, onum, usglen, ksglen, res; - int iovec_count = (int) hp->iovec_count; - int dxfer_dir = hp->dxfer_direction; - unsigned char *p; - unsigned char __user *up; - int new_interface = ('\0' == hp->interface_id) ? 0 : 1; - - if ((SG_DXFER_UNKNOWN == dxfer_dir) || (SG_DXFER_FROM_DEV == dxfer_dir) - || (SG_DXFER_TO_FROM_DEV == dxfer_dir)) { - num_xfer = hp->dxfer_len; - if (schp->bufflen < num_xfer) - num_xfer = schp->bufflen; - } - if ((num_xfer <= 0) || (schp->dio_in_use) || - (new_interface - && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags))) - return 0; - - SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n", - num_xfer, iovec_count, schp->k_use_sg)); - if (iovec_count) { - onum = iovec_count; - if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum)) - return -EFAULT; - } else - onum = 1; - - p = page_address(sg_page(sg)); - ksglen = sg->length; - for (j = 0, k = 0; j < onum; ++j) { - res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up); - if (res) - return res; - - for (; p; sg = sg_next(sg), ksglen = sg->length, - p = page_address(sg_page(sg))) { - if (usglen <= 0) - break; - if (ksglen > usglen) { - if (usglen >= num_xfer) { - if (__copy_to_user(up, p, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_to_user(up, p, usglen)) - return -EFAULT; - p += usglen; - ksglen -= usglen; - break; - } else { - if (ksglen >= num_xfer) { - if (__copy_to_user(up, p, num_xfer)) - return -EFAULT; - return 0; - } - if (__copy_to_user(up, p, ksglen)) - return -EFAULT; - up += ksglen; - usglen -= ksglen; - } - ++k; - if (k >= schp->k_use_sg) - return 0; + kfree(schp->pages); } } - - return 0; + memset(schp, 0, sizeof (*schp)); } static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) { Sg_scatter_hold *schp = &srp->data; - struct scatterlist *sg = schp->buffer; int k, num; SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n", @@ -2134,15 +1840,15 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) if ((!outp) || (num_read_xfer <= 0)) return 0; - for (k = 0; (k < schp->k_use_sg) && sg_page(sg); ++k, sg = sg_next(sg)) { - num = sg->length; + num = 1 << (PAGE_SHIFT + schp->page_order); + for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) { if (num > num_read_xfer) { - if (__copy_to_user(outp, page_address(sg_page(sg)), + if (__copy_to_user(outp, page_address(schp->pages[k]), num_read_xfer)) return -EFAULT; break; } else { - if (__copy_to_user(outp, page_address(sg_page(sg)), + if (__copy_to_user(outp, page_address(schp->pages[k]), num)) return -EFAULT; num_read_xfer -= num; @@ -2177,24 +1883,21 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) { Sg_scatter_hold *req_schp = &srp->data; Sg_scatter_hold *rsv_schp = &sfp->reserve; - struct scatterlist *sg = rsv_schp->buffer; int k, num, rem; srp->res_used = 1; SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); rem = size; - for (k = 0; k < rsv_schp->k_use_sg; ++k, sg = sg_next(sg)) { - num = sg->length; + num = 1 << (PAGE_SHIFT + rsv_schp->page_order); + for (k = 0; k < rsv_schp->k_use_sg; k++) { if (rem <= num) { - sfp->save_scat_len = num; - sg->length = rem; req_schp->k_use_sg = k + 1; req_schp->sglist_len = rsv_schp->sglist_len; - req_schp->buffer = rsv_schp->buffer; + req_schp->pages = rsv_schp->pages; req_schp->bufflen = size; - req_schp->b_malloc_len = rsv_schp->b_malloc_len; + req_schp->page_order = rsv_schp->page_order; break; } else rem -= num; @@ -2208,22 +1911,13 @@ static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) { Sg_scatter_hold *req_schp = &srp->data; - Sg_scatter_hold *rsv_schp = &sfp->reserve; SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n", (int) req_schp->k_use_sg)); - if ((rsv_schp->k_use_sg > 0) && (req_schp->k_use_sg > 0)) { - struct scatterlist *sg = rsv_schp->buffer; - - if (sfp->save_scat_len > 0) - (sg + (req_schp->k_use_sg - 1))->length = - (unsigned) sfp->save_scat_len; - else - SCSI_LOG_TIMEOUT(1, printk ("sg_unlink_reserve: BAD save_scat_len\n")); - } req_schp->k_use_sg = 0; req_schp->bufflen = 0; - req_schp->buffer = NULL; + req_schp->pages = NULL; + req_schp->page_order = 0; req_schp->sglist_len = 0; sfp->save_scat_len = 0; srp->res_used = 0; @@ -2481,53 +2175,6 @@ sg_res_in_use(Sg_fd * sfp) return srp ? 1 : 0; } -/* The size fetched (value output via retSzp) set when non-NULL return */ -static struct page * -sg_page_malloc(int rqSz, int lowDma, int *retSzp) -{ - struct page *resp = NULL; - gfp_t page_mask; - int order, a_size; - int resSz; - - if ((rqSz <= 0) || (NULL == retSzp)) - return resp; - - if (lowDma) - page_mask = GFP_ATOMIC | GFP_DMA | __GFP_COMP | __GFP_NOWARN; - else - page_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN; - - for (order = 0, a_size = PAGE_SIZE; a_size < rqSz; - order++, a_size <<= 1) ; - resSz = a_size; /* rounded up if necessary */ - resp = alloc_pages(page_mask, order); - while ((!resp) && order) { - --order; - a_size >>= 1; /* divide by 2, until PAGE_SIZE */ - resp = alloc_pages(page_mask, order); /* try half */ - resSz = a_size; - } - if (resp) { - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - memset(page_address(resp), 0, resSz); - *retSzp = resSz; - } - return resp; -} - -static void -sg_page_free(struct page *page, int size) -{ - int order, a_size; - - if (!page) - return; - for (order = 0, a_size = PAGE_SIZE; a_size < size; - order++, a_size <<= 1) ; - __free_pages(page, order); -} - #ifdef CONFIG_SCSI_PROC_FS static int sg_idr_max_id(int id, void *p, void *data) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 27f5bfd1def3..0f17009c99d2 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -331,7 +331,7 @@ static int sr_done(struct scsi_cmnd *SCpnt) static int sr_prep_fn(struct request_queue *q, struct request *rq) { - int block=0, this_count, s_size, timeout = SR_TIMEOUT; + int block = 0, this_count, s_size; struct scsi_cd *cd; struct scsi_cmnd *SCpnt; struct scsi_device *sdp = q->queuedata; @@ -461,7 +461,6 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) SCpnt->transfersize = cd->device->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = MAX_RETRIES; - SCpnt->timeout_per_command = timeout; /* * This indicates that the command is ready from our end to be @@ -620,6 +619,8 @@ static int sr_probe(struct device *dev) disk->fops = &sr_bdops; disk->flags = GENHD_FL_CD; + blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); + cd->device = sdev; cd->disk = disk; cd->driver = &sr_template; @@ -878,7 +879,7 @@ static void sr_kref_release(struct kref *kref) struct gendisk *disk = cd->disk; spin_lock(&sr_index_lock); - clear_bit(disk->first_minor, sr_index_bits); + clear_bit(MINOR(disk_devt(disk)), sr_index_bits); spin_unlock(&sr_index_lock); unregister_cdrom(&cd->cdi); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index d39107b7669b..f4e6cde1fd0d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -519,8 +519,8 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, * Shorten our settle_time if needed for * this command not to time out. */ - if (np->s.settle_time_valid && cmd->timeout_per_command) { - unsigned long tlimit = jiffies + cmd->timeout_per_command; + if (np->s.settle_time_valid && cmd->request->timeout) { + unsigned long tlimit = jiffies + cmd->request->timeout; tlimit -= SYM_CONF_TIMER_INTERVAL*2; if (time_after(np->s.settle_time, tlimit)) { np->s.settle_time = tlimit; diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 1723d71cbf3f..69ac6e590f1d 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -2573,8 +2573,8 @@ static struct pci_driver dc390_driver = { static int __init dc390_module_init(void) { if (!disable_clustering) - printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n" - "\twith \"disable_clustering=1\" and report to maintainers\n"); + printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n"); + printk(KERN_INFO " with \"disable_clustering=1\" and report to maintainers\n"); if (tmscsim[0] == -1 || tmscsim[0] > 15) { tmscsim[0] = 7; diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index c3e174b35fe6..19caf7c962ac 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -107,7 +107,8 @@ void bio_integrity_free(struct bio *bio, struct bio_set *bs) BUG_ON(bip == NULL); /* A cloned bio doesn't own the integrity metadata */ - if (!bio_flagged(bio, BIO_CLONED) && bip->bip_buf != NULL) + if (!bio_flagged(bio, BIO_CLONED) && !bio_flagged(bio, BIO_FS_INTEGRITY) + && bip->bip_buf != NULL) kfree(bip->bip_buf); mempool_free(bip->bip_vec, bs->bvec_pools[bip->bip_pool]); @@ -150,6 +151,24 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, } EXPORT_SYMBOL(bio_integrity_add_page); +static int bdev_integrity_enabled(struct block_device *bdev, int rw) +{ + struct blk_integrity *bi = bdev_get_integrity(bdev); + + if (bi == NULL) + return 0; + + if (rw == READ && bi->verify_fn != NULL && + (bi->flags & INTEGRITY_FLAG_READ)) + return 1; + + if (rw == WRITE && bi->generate_fn != NULL && + (bi->flags & INTEGRITY_FLAG_WRITE)) + return 1; + + return 0; +} + /** * bio_integrity_enabled - Check whether integrity can be passed * @bio: bio to check @@ -313,6 +332,14 @@ static void bio_integrity_generate(struct bio *bio) } } +static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi) +{ + if (bi) + return bi->tuple_size; + + return 0; +} + /** * bio_integrity_prep - Prepare bio for integrity I/O * @bio: bio to prepare @@ -30,7 +30,7 @@ static struct kmem_cache *bio_slab __read_mostly; -mempool_t *bio_split_pool __read_mostly; +static mempool_t *bio_split_pool __read_mostly; /* * if you change this list, also change bvec_alloc or things will @@ -60,25 +60,46 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct struct bio_vec *bvl; /* - * see comment near bvec_array define! + * If 'bs' is given, lookup the pool and do the mempool alloc. + * If not, this is a bio_kmalloc() allocation and just do a + * kzalloc() for the exact number of vecs right away. */ - switch (nr) { - case 1 : *idx = 0; break; - case 2 ... 4: *idx = 1; break; - case 5 ... 16: *idx = 2; break; - case 17 ... 64: *idx = 3; break; - case 65 ... 128: *idx = 4; break; - case 129 ... BIO_MAX_PAGES: *idx = 5; break; + if (bs) { + /* + * see comment near bvec_array define! + */ + switch (nr) { + case 1: + *idx = 0; + break; + case 2 ... 4: + *idx = 1; + break; + case 5 ... 16: + *idx = 2; + break; + case 17 ... 64: + *idx = 3; + break; + case 65 ... 128: + *idx = 4; + break; + case 129 ... BIO_MAX_PAGES: + *idx = 5; + break; default: return NULL; - } - /* - * idx now points to the pool we want to allocate from - */ + } - bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask); - if (bvl) - memset(bvl, 0, bvec_nr_vecs(*idx) * sizeof(struct bio_vec)); + /* + * idx now points to the pool we want to allocate from + */ + bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask); + if (bvl) + memset(bvl, 0, + bvec_nr_vecs(*idx) * sizeof(struct bio_vec)); + } else + bvl = kzalloc(nr * sizeof(struct bio_vec), gfp_mask); return bvl; } @@ -107,10 +128,17 @@ static void bio_fs_destructor(struct bio *bio) bio_free(bio, fs_bio_set); } +static void bio_kmalloc_destructor(struct bio *bio) +{ + kfree(bio->bi_io_vec); + kfree(bio); +} + void bio_init(struct bio *bio) { memset(bio, 0, sizeof(*bio)); bio->bi_flags = 1 << BIO_UPTODATE; + bio->bi_comp_cpu = -1; atomic_set(&bio->bi_cnt, 1); } @@ -118,19 +146,25 @@ void bio_init(struct bio *bio) * bio_alloc_bioset - allocate a bio for I/O * @gfp_mask: the GFP_ mask given to the slab allocator * @nr_iovecs: number of iovecs to pre-allocate - * @bs: the bio_set to allocate from + * @bs: the bio_set to allocate from. If %NULL, just use kmalloc * * Description: - * bio_alloc_bioset will first try it's on mempool to satisfy the allocation. + * bio_alloc_bioset will first try its own mempool to satisfy the allocation. * If %__GFP_WAIT is set then we will block on the internal pool waiting - * for a &struct bio to become free. + * for a &struct bio to become free. If a %NULL @bs is passed in, we will + * fall back to just using @kmalloc to allocate the required memory. * * allocate bio and iovecs from the memory pools specified by the - * bio_set structure. + * bio_set structure, or @kmalloc if none given. **/ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) { - struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask); + struct bio *bio; + + if (bs) + bio = mempool_alloc(bs->bio_pool, gfp_mask); + else + bio = kmalloc(sizeof(*bio), gfp_mask); if (likely(bio)) { struct bio_vec *bvl = NULL; @@ -141,7 +175,10 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); if (unlikely(!bvl)) { - mempool_free(bio, bs->bio_pool); + if (bs) + mempool_free(bio, bs->bio_pool); + else + kfree(bio); bio = NULL; goto out; } @@ -164,6 +201,23 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) return bio; } +/* + * Like bio_alloc(), but doesn't use a mempool backing. This means that + * it CAN fail, but while bio_alloc() can only be used for allocations + * that have a short (finite) life span, bio_kmalloc() should be used + * for more permanent bio allocations (like allocating some bio's for + * initalization or setup purposes). + */ +struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs) +{ + struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, NULL); + + if (bio) + bio->bi_destructor = bio_kmalloc_destructor; + + return bio; +} + void zero_fill_bio(struct bio *bio) { unsigned long flags; @@ -208,14 +262,6 @@ inline int bio_phys_segments(struct request_queue *q, struct bio *bio) return bio->bi_phys_segments; } -inline int bio_hw_segments(struct request_queue *q, struct bio *bio) -{ - if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) - blk_recount_segments(q, bio); - - return bio->bi_hw_segments; -} - /** * __bio_clone - clone a bio * @bio: destination bio @@ -350,8 +396,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page */ while (bio->bi_phys_segments >= q->max_phys_segments - || bio->bi_hw_segments >= q->max_hw_segments - || BIOVEC_VIRT_OVERSIZE(bio->bi_size)) { + || bio->bi_phys_segments >= q->max_hw_segments) { if (retried_segments) return 0; @@ -395,13 +440,11 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page } /* If we may be able to merge these biovecs, force a recount */ - if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec) || - BIOVEC_VIRT_MERGEABLE(bvec-1, bvec))) + if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec))) bio->bi_flags &= ~(1 << BIO_SEG_VALID); bio->bi_vcnt++; bio->bi_phys_segments++; - bio->bi_hw_segments++; done: bio->bi_size += len; return len; @@ -449,16 +492,19 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, struct bio_map_data { struct bio_vec *iovecs; - int nr_sgvecs; struct sg_iovec *sgvecs; + int nr_sgvecs; + int is_our_pages; }; static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio, - struct sg_iovec *iov, int iov_count) + struct sg_iovec *iov, int iov_count, + int is_our_pages) { memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt); memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count); bmd->nr_sgvecs = iov_count; + bmd->is_our_pages = is_our_pages; bio->bi_private = bmd; } @@ -493,7 +539,8 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, } static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, - struct sg_iovec *iov, int iov_count, int uncopy) + struct sg_iovec *iov, int iov_count, int uncopy, + int do_free_page) { int ret = 0, i; struct bio_vec *bvec; @@ -536,7 +583,7 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, } } - if (uncopy) + if (do_free_page) __free_page(bvec->bv_page); } @@ -553,10 +600,11 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, int bio_uncopy_user(struct bio *bio) { struct bio_map_data *bmd = bio->bi_private; - int ret; - - ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, bmd->nr_sgvecs, 1); + int ret = 0; + if (!bio_flagged(bio, BIO_NULL_MAPPED)) + ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, + bmd->nr_sgvecs, 1, bmd->is_our_pages); bio_free_map_data(bmd); bio_put(bio); return ret; @@ -565,16 +613,20 @@ int bio_uncopy_user(struct bio *bio) /** * bio_copy_user_iov - copy user data to bio * @q: destination block queue + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @iov: the iovec. * @iov_count: number of elements in the iovec * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Prepares and returns a bio for indirect user io, bouncing data * to/from kernel pages as necessary. Must be paired with * call bio_uncopy_user() on io completion. */ -struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, - int iov_count, int write_to_vm) +struct bio *bio_copy_user_iov(struct request_queue *q, + struct rq_map_data *map_data, + struct sg_iovec *iov, int iov_count, + int write_to_vm, gfp_t gfp_mask) { struct bio_map_data *bmd; struct bio_vec *bvec; @@ -597,25 +649,38 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, len += iov[i].iov_len; } - bmd = bio_alloc_map_data(nr_pages, iov_count, GFP_KERNEL); + bmd = bio_alloc_map_data(nr_pages, iov_count, gfp_mask); if (!bmd) return ERR_PTR(-ENOMEM); ret = -ENOMEM; - bio = bio_alloc(GFP_KERNEL, nr_pages); + bio = bio_alloc(gfp_mask, nr_pages); if (!bio) goto out_bmd; bio->bi_rw |= (!write_to_vm << BIO_RW); ret = 0; + i = 0; while (len) { - unsigned int bytes = PAGE_SIZE; + unsigned int bytes; + + if (map_data) + bytes = 1U << (PAGE_SHIFT + map_data->page_order); + else + bytes = PAGE_SIZE; if (bytes > len) bytes = len; - page = alloc_page(q->bounce_gfp | GFP_KERNEL); + if (map_data) { + if (i == map_data->nr_entries) { + ret = -ENOMEM; + break; + } + page = map_data->pages[i++]; + } else + page = alloc_page(q->bounce_gfp | gfp_mask); if (!page) { ret = -ENOMEM; break; @@ -634,16 +699,17 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, * success */ if (!write_to_vm) { - ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0); + ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); if (ret) goto cleanup; } - bio_set_map_data(bmd, bio, iov, iov_count); + bio_set_map_data(bmd, bio, iov, iov_count, map_data ? 0 : 1); return bio; cleanup: - bio_for_each_segment(bvec, bio, i) - __free_page(bvec->bv_page); + if (!map_data) + bio_for_each_segment(bvec, bio, i) + __free_page(bvec->bv_page); bio_put(bio); out_bmd: @@ -654,29 +720,32 @@ out_bmd: /** * bio_copy_user - copy user data to bio * @q: destination block queue + * @map_data: pointer to the rq_map_data holding pages (if necessary) * @uaddr: start of user address * @len: length in bytes * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Prepares and returns a bio for indirect user io, bouncing data * to/from kernel pages as necessary. Must be paired with * call bio_uncopy_user() on io completion. */ -struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr, - unsigned int len, int write_to_vm) +struct bio *bio_copy_user(struct request_queue *q, struct rq_map_data *map_data, + unsigned long uaddr, unsigned int len, + int write_to_vm, gfp_t gfp_mask) { struct sg_iovec iov; iov.iov_base = (void __user *)uaddr; iov.iov_len = len; - return bio_copy_user_iov(q, &iov, 1, write_to_vm); + return bio_copy_user_iov(q, map_data, &iov, 1, write_to_vm, gfp_mask); } static struct bio *__bio_map_user_iov(struct request_queue *q, struct block_device *bdev, struct sg_iovec *iov, int iov_count, - int write_to_vm) + int write_to_vm, gfp_t gfp_mask) { int i, j; int nr_pages = 0; @@ -702,12 +771,12 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, if (!nr_pages) return ERR_PTR(-EINVAL); - bio = bio_alloc(GFP_KERNEL, nr_pages); + bio = bio_alloc(gfp_mask, nr_pages); if (!bio) return ERR_PTR(-ENOMEM); ret = -ENOMEM; - pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL); + pages = kcalloc(nr_pages, sizeof(struct page *), gfp_mask); if (!pages) goto out; @@ -786,19 +855,21 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, * @uaddr: start of user address * @len: length in bytes * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Map the user space address into a bio suitable for io to a block * device. Returns an error pointer in case of error. */ struct bio *bio_map_user(struct request_queue *q, struct block_device *bdev, - unsigned long uaddr, unsigned int len, int write_to_vm) + unsigned long uaddr, unsigned int len, int write_to_vm, + gfp_t gfp_mask) { struct sg_iovec iov; iov.iov_base = (void __user *)uaddr; iov.iov_len = len; - return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm); + return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm, gfp_mask); } /** @@ -808,18 +879,19 @@ struct bio *bio_map_user(struct request_queue *q, struct block_device *bdev, * @iov: the iovec. * @iov_count: number of elements in the iovec * @write_to_vm: bool indicating writing to pages or not + * @gfp_mask: memory allocation flags * * Map the user space address into a bio suitable for io to a block * device. Returns an error pointer in case of error. */ struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev, struct sg_iovec *iov, int iov_count, - int write_to_vm) + int write_to_vm, gfp_t gfp_mask) { struct bio *bio; - bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm); - + bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm, + gfp_mask); if (IS_ERR(bio)) return bio; @@ -976,48 +1048,13 @@ static void bio_copy_kern_endio(struct bio *bio, int err) struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, gfp_t gfp_mask, int reading) { - unsigned long kaddr = (unsigned long)data; - unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned long start = kaddr >> PAGE_SHIFT; - const int nr_pages = end - start; struct bio *bio; struct bio_vec *bvec; - struct bio_map_data *bmd; - int i, ret; - struct sg_iovec iov; - - iov.iov_base = data; - iov.iov_len = len; - - bmd = bio_alloc_map_data(nr_pages, 1, gfp_mask); - if (!bmd) - return ERR_PTR(-ENOMEM); - - ret = -ENOMEM; - bio = bio_alloc(gfp_mask, nr_pages); - if (!bio) - goto out_bmd; - - while (len) { - struct page *page; - unsigned int bytes = PAGE_SIZE; - - if (bytes > len) - bytes = len; - - page = alloc_page(q->bounce_gfp | gfp_mask); - if (!page) { - ret = -ENOMEM; - goto cleanup; - } - - if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) { - ret = -EINVAL; - goto cleanup; - } + int i; - len -= bytes; - } + bio = bio_copy_user(q, NULL, (unsigned long)data, len, 1, gfp_mask); + if (IS_ERR(bio)) + return bio; if (!reading) { void *p = data; @@ -1030,20 +1067,9 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, } } - bio->bi_private = bmd; bio->bi_end_io = bio_copy_kern_endio; - bio_set_map_data(bmd, bio, &iov, 1); return bio; -cleanup: - bio_for_each_segment(bvec, bio, i) - __free_page(bvec->bv_page); - - bio_put(bio); -out_bmd: - bio_free_map_data(bmd); - - return ERR_PTR(ret); } /* @@ -1230,9 +1256,9 @@ static void bio_pair_end_2(struct bio *bi, int err) * split a bio - only worry about a bio with a single page * in it's iovec */ -struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) +struct bio_pair *bio_split(struct bio *bi, int first_sectors) { - struct bio_pair *bp = mempool_alloc(pool, GFP_NOIO); + struct bio_pair *bp = mempool_alloc(bio_split_pool, GFP_NOIO); if (!bp) return bp; @@ -1266,7 +1292,7 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) bp->bio2.bi_end_io = bio_pair_end_2; bp->bio1.bi_private = bi; - bp->bio2.bi_private = pool; + bp->bio2.bi_private = bio_split_pool; if (bio_integrity(bi)) bio_integrity_split(bi, bp, first_sectors); @@ -1274,6 +1300,42 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) return bp; } +/** + * bio_sector_offset - Find hardware sector offset in bio + * @bio: bio to inspect + * @index: bio_vec index + * @offset: offset in bv_page + * + * Return the number of hardware sectors between beginning of bio + * and an end point indicated by a bio_vec index and an offset + * within that vector's page. + */ +sector_t bio_sector_offset(struct bio *bio, unsigned short index, + unsigned int offset) +{ + unsigned int sector_sz = queue_hardsect_size(bio->bi_bdev->bd_disk->queue); + struct bio_vec *bv; + sector_t sectors; + int i; + + sectors = 0; + + if (index >= bio->bi_idx) + index = bio->bi_vcnt - 1; + + __bio_for_each_segment(bv, bio, i, 0) { + if (i == index) { + if (offset > bv->bv_offset) + sectors += (offset - bv->bv_offset) / sector_sz; + break; + } + + sectors += bv->bv_len / sector_sz; + } + + return sectors; +} +EXPORT_SYMBOL(bio_sector_offset); /* * create memory pools for biovec's in a bio_set. @@ -1376,6 +1438,7 @@ static int __init init_bio(void) subsys_initcall(init_bio); EXPORT_SYMBOL(bio_alloc); +EXPORT_SYMBOL(bio_kmalloc); EXPORT_SYMBOL(bio_put); EXPORT_SYMBOL(bio_free); EXPORT_SYMBOL(bio_endio); @@ -1383,7 +1446,6 @@ EXPORT_SYMBOL(bio_init); EXPORT_SYMBOL(__bio_clone); EXPORT_SYMBOL(bio_clone); EXPORT_SYMBOL(bio_phys_segments); -EXPORT_SYMBOL(bio_hw_segments); EXPORT_SYMBOL(bio_add_page); EXPORT_SYMBOL(bio_add_pc_page); EXPORT_SYMBOL(bio_get_nr_vecs); @@ -1393,7 +1455,6 @@ EXPORT_SYMBOL(bio_map_kern); EXPORT_SYMBOL(bio_copy_kern); EXPORT_SYMBOL(bio_pair_release); EXPORT_SYMBOL(bio_split); -EXPORT_SYMBOL(bio_split_pool); EXPORT_SYMBOL(bio_copy_user); EXPORT_SYMBOL(bio_uncopy_user); EXPORT_SYMBOL(bioset_create); diff --git a/fs/block_dev.c b/fs/block_dev.c index aff54219e049..d84f0469a016 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -540,22 +540,6 @@ EXPORT_SYMBOL(bd_release); * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 */ -static struct kobject *bdev_get_kobj(struct block_device *bdev) -{ - if (bdev->bd_contains != bdev) - return kobject_get(&bdev->bd_part->dev.kobj); - else - return kobject_get(&bdev->bd_disk->dev.kobj); -} - -static struct kobject *bdev_get_holder(struct block_device *bdev) -{ - if (bdev->bd_contains != bdev) - return kobject_get(bdev->bd_part->holder_dir); - else - return kobject_get(bdev->bd_disk->holder_dir); -} - static int add_symlink(struct kobject *from, struct kobject *to) { if (!from || !to) @@ -604,11 +588,11 @@ static int bd_holder_grab_dirs(struct block_device *bdev, if (!bo->hdev) goto fail_put_sdir; - bo->sdev = bdev_get_kobj(bdev); + bo->sdev = kobject_get(&part_to_dev(bdev->bd_part)->kobj); if (!bo->sdev) goto fail_put_hdev; - bo->hdir = bdev_get_holder(bdev); + bo->hdir = kobject_get(bdev->bd_part->holder_dir); if (!bo->hdir) goto fail_put_sdev; @@ -868,6 +852,87 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) EXPORT_SYMBOL(open_by_devnum); +/** + * flush_disk - invalidates all buffer-cache entries on a disk + * + * @bdev: struct block device to be flushed + * + * Invalidates all buffer-cache entries on a disk. It should be called + * when a disk has been changed -- either by a media change or online + * resize. + */ +static void flush_disk(struct block_device *bdev) +{ + if (__invalidate_device(bdev)) { + char name[BDEVNAME_SIZE] = ""; + + if (bdev->bd_disk) + disk_name(bdev->bd_disk, 0, name); + printk(KERN_WARNING "VFS: busy inodes on changed media or " + "resized disk %s\n", name); + } + + if (!bdev->bd_disk) + return; + if (disk_partitionable(bdev->bd_disk)) + bdev->bd_invalidated = 1; +} + +/** + * check_disk_size_change - checks for disk size change and adjusts bdev size. + * @disk: struct gendisk to check + * @bdev: struct bdev to adjust. + * + * This routine checks to see if the bdev size does not match the disk size + * and adjusts it if it differs. + */ +void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) +{ + loff_t disk_size, bdev_size; + + disk_size = (loff_t)get_capacity(disk) << 9; + bdev_size = i_size_read(bdev->bd_inode); + if (disk_size != bdev_size) { + char name[BDEVNAME_SIZE]; + + disk_name(disk, 0, name); + printk(KERN_INFO + "%s: detected capacity change from %lld to %lld\n", + name, bdev_size, disk_size); + i_size_write(bdev->bd_inode, disk_size); + flush_disk(bdev); + } +} +EXPORT_SYMBOL(check_disk_size_change); + +/** + * revalidate_disk - wrapper for lower-level driver's revalidate_disk call-back + * @disk: struct gendisk to be revalidated + * + * This routine is a wrapper for lower-level driver's revalidate_disk + * call-backs. It is used to do common pre and post operations needed + * for all revalidate_disk operations. + */ +int revalidate_disk(struct gendisk *disk) +{ + struct block_device *bdev; + int ret = 0; + + if (disk->fops->revalidate_disk) + ret = disk->fops->revalidate_disk(disk); + + bdev = bdget_disk(disk, 0); + if (!bdev) + return ret; + + mutex_lock(&bdev->bd_mutex); + check_disk_size_change(disk, bdev); + mutex_unlock(&bdev->bd_mutex); + bdput(bdev); + return ret; +} +EXPORT_SYMBOL(revalidate_disk); + /* * This routine checks whether a removable media has been changed, * and invalidates all buffer-cache-entries in that case. This @@ -887,13 +952,9 @@ int check_disk_change(struct block_device *bdev) if (!bdops->media_changed(bdev->bd_disk)) return 0; - if (__invalidate_device(bdev)) - printk("VFS: busy inodes on changed media.\n"); - + flush_disk(bdev); if (bdops->revalidate_disk) bdops->revalidate_disk(bdev->bd_disk); - if (bdev->bd_disk->minors > 1) - bdev->bd_invalidated = 1; return 1; } @@ -927,10 +988,10 @@ static int __blkdev_put(struct block_device *bdev, int for_part); static int do_open(struct block_device *bdev, struct file *file, int for_part) { - struct module *owner = NULL; struct gendisk *disk; + struct hd_struct *part = NULL; int ret; - int part; + int partno; int perm = 0; if (file->f_mode & FMODE_READ) @@ -948,25 +1009,27 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) ret = -ENXIO; file->f_mapping = bdev->bd_inode->i_mapping; + lock_kernel(); - disk = get_gendisk(bdev->bd_dev, &part); - if (!disk) { - unlock_kernel(); - bdput(bdev); - return ret; - } - owner = disk->fops->owner; + + disk = get_gendisk(bdev->bd_dev, &partno); + if (!disk) + goto out_unlock_kernel; + part = disk_get_part(disk, partno); + if (!part) + goto out_unlock_kernel; mutex_lock_nested(&bdev->bd_mutex, for_part); if (!bdev->bd_openers) { bdev->bd_disk = disk; + bdev->bd_part = part; bdev->bd_contains = bdev; - if (!part) { + if (!partno) { struct backing_dev_info *bdi; if (disk->fops->open) { ret = disk->fops->open(bdev->bd_inode, file); if (ret) - goto out_first; + goto out_clear; } if (!bdev->bd_openers) { bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); @@ -978,36 +1041,36 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) if (bdev->bd_invalidated) rescan_partitions(disk, bdev); } else { - struct hd_struct *p; struct block_device *whole; whole = bdget_disk(disk, 0); ret = -ENOMEM; if (!whole) - goto out_first; + goto out_clear; BUG_ON(for_part); ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1); if (ret) - goto out_first; + goto out_clear; bdev->bd_contains = whole; - p = disk->part[part - 1]; bdev->bd_inode->i_data.backing_dev_info = whole->bd_inode->i_data.backing_dev_info; - if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { + if (!(disk->flags & GENHD_FL_UP) || + !part || !part->nr_sects) { ret = -ENXIO; - goto out_first; + goto out_clear; } - kobject_get(&p->dev.kobj); - bdev->bd_part = p; - bd_set_size(bdev, (loff_t) p->nr_sects << 9); + bd_set_size(bdev, (loff_t)part->nr_sects << 9); } } else { + disk_put_part(part); put_disk(disk); - module_put(owner); + module_put(disk->fops->owner); + part = NULL; + disk = NULL; if (bdev->bd_contains == bdev) { if (bdev->bd_disk->fops->open) { ret = bdev->bd_disk->fops->open(bdev->bd_inode, file); if (ret) - goto out; + goto out_unlock_bdev; } if (bdev->bd_invalidated) rescan_partitions(bdev->bd_disk, bdev); @@ -1020,19 +1083,24 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) unlock_kernel(); return 0; -out_first: + out_clear: bdev->bd_disk = NULL; + bdev->bd_part = NULL; bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; if (bdev != bdev->bd_contains) __blkdev_put(bdev->bd_contains, 1); bdev->bd_contains = NULL; - put_disk(disk); - module_put(owner); -out: + out_unlock_bdev: mutex_unlock(&bdev->bd_mutex); + out_unlock_kernel: unlock_kernel(); - if (ret) - bdput(bdev); + + disk_put_part(part); + if (disk) + module_put(disk->fops->owner); + put_disk(disk); + bdput(bdev); + return ret; } @@ -1117,11 +1185,8 @@ static int __blkdev_put(struct block_device *bdev, int for_part) put_disk(disk); module_put(owner); - - if (bdev->bd_contains != bdev) { - kobject_put(&bdev->bd_part->dev.kobj); - bdev->bd_part = NULL; - } + disk_put_part(bdev->bd_part); + bdev->bd_part = NULL; bdev->bd_disk = NULL; bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; if (bdev != bdev->bd_contains) @@ -1197,10 +1262,9 @@ EXPORT_SYMBOL(ioctl_by_bdev); /** * lookup_bdev - lookup a struct block_device by name + * @pathname: special file representing the block device * - * @path: special file representing the block device - * - * Get a reference to the blockdevice at @path in the current + * Get a reference to the blockdevice at @pathname in the current * namespace if possible and return it. Return ERR_PTR(error) * otherwise. */ diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 89d2fb7b991a..fd9859f92fad 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -14,6 +14,9 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/configfs.h> +#include <linux/in.h> +#include <linux/in6.h> +#include <net/ipv6.h> #include <net/sock.h> #include "config.h" @@ -377,24 +380,24 @@ static struct config_item_type node_type = { .ct_owner = THIS_MODULE, }; -static struct dlm_cluster *to_cluster(struct config_item *i) +static struct dlm_cluster *config_item_to_cluster(struct config_item *i) { return i ? container_of(to_config_group(i), struct dlm_cluster, group) : NULL; } -static struct dlm_space *to_space(struct config_item *i) +static struct dlm_space *config_item_to_space(struct config_item *i) { return i ? container_of(to_config_group(i), struct dlm_space, group) : NULL; } -static struct dlm_comm *to_comm(struct config_item *i) +static struct dlm_comm *config_item_to_comm(struct config_item *i) { return i ? container_of(i, struct dlm_comm, item) : NULL; } -static struct dlm_node *to_node(struct config_item *i) +static struct dlm_node *config_item_to_node(struct config_item *i) { return i ? container_of(i, struct dlm_node, item) : NULL; } @@ -450,7 +453,7 @@ static struct config_group *make_cluster(struct config_group *g, static void drop_cluster(struct config_group *g, struct config_item *i) { - struct dlm_cluster *cl = to_cluster(i); + struct dlm_cluster *cl = config_item_to_cluster(i); struct config_item *tmp; int j; @@ -468,7 +471,7 @@ static void drop_cluster(struct config_group *g, struct config_item *i) static void release_cluster(struct config_item *i) { - struct dlm_cluster *cl = to_cluster(i); + struct dlm_cluster *cl = config_item_to_cluster(i); kfree(cl->group.default_groups); kfree(cl); } @@ -507,7 +510,7 @@ static struct config_group *make_space(struct config_group *g, const char *name) static void drop_space(struct config_group *g, struct config_item *i) { - struct dlm_space *sp = to_space(i); + struct dlm_space *sp = config_item_to_space(i); struct config_item *tmp; int j; @@ -524,7 +527,7 @@ static void drop_space(struct config_group *g, struct config_item *i) static void release_space(struct config_item *i) { - struct dlm_space *sp = to_space(i); + struct dlm_space *sp = config_item_to_space(i); kfree(sp->group.default_groups); kfree(sp); } @@ -546,7 +549,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name) static void drop_comm(struct config_group *g, struct config_item *i) { - struct dlm_comm *cm = to_comm(i); + struct dlm_comm *cm = config_item_to_comm(i); if (local_comm == cm) local_comm = NULL; dlm_lowcomms_close(cm->nodeid); @@ -557,13 +560,13 @@ static void drop_comm(struct config_group *g, struct config_item *i) static void release_comm(struct config_item *i) { - struct dlm_comm *cm = to_comm(i); + struct dlm_comm *cm = config_item_to_comm(i); kfree(cm); } static struct config_item *make_node(struct config_group *g, const char *name) { - struct dlm_space *sp = to_space(g->cg_item.ci_parent); + struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent); struct dlm_node *nd; nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL); @@ -585,8 +588,8 @@ static struct config_item *make_node(struct config_group *g, const char *name) static void drop_node(struct config_group *g, struct config_item *i) { - struct dlm_space *sp = to_space(g->cg_item.ci_parent); - struct dlm_node *nd = to_node(i); + struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent); + struct dlm_node *nd = config_item_to_node(i); mutex_lock(&sp->members_lock); list_del(&nd->list); @@ -598,7 +601,7 @@ static void drop_node(struct config_group *g, struct config_item *i) static void release_node(struct config_item *i) { - struct dlm_node *nd = to_node(i); + struct dlm_node *nd = config_item_to_node(i); kfree(nd); } @@ -632,7 +635,7 @@ void dlm_config_exit(void) static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct dlm_cluster *cl = to_cluster(i); + struct dlm_cluster *cl = config_item_to_cluster(i); struct cluster_attribute *cla = container_of(a, struct cluster_attribute, attr); return cla->show ? cla->show(cl, buf) : 0; @@ -642,7 +645,7 @@ static ssize_t store_cluster(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct dlm_cluster *cl = to_cluster(i); + struct dlm_cluster *cl = config_item_to_cluster(i); struct cluster_attribute *cla = container_of(a, struct cluster_attribute, attr); return cla->store ? cla->store(cl, buf, len) : -EINVAL; @@ -651,7 +654,7 @@ static ssize_t store_cluster(struct config_item *i, static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct dlm_comm *cm = to_comm(i); + struct dlm_comm *cm = config_item_to_comm(i); struct comm_attribute *cma = container_of(a, struct comm_attribute, attr); return cma->show ? cma->show(cm, buf) : 0; @@ -660,7 +663,7 @@ static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct dlm_comm *cm = to_comm(i); + struct dlm_comm *cm = config_item_to_comm(i); struct comm_attribute *cma = container_of(a, struct comm_attribute, attr); return cma->store ? cma->store(cm, buf, len) : -EINVAL; @@ -714,7 +717,7 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct dlm_node *nd = to_node(i); + struct dlm_node *nd = config_item_to_node(i); struct node_attribute *nda = container_of(a, struct node_attribute, attr); return nda->show ? nda->show(nd, buf) : 0; @@ -723,7 +726,7 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct dlm_node *nd = to_node(i); + struct dlm_node *nd = config_item_to_node(i); struct node_attribute *nda = container_of(a, struct node_attribute, attr); return nda->store ? nda->store(nd, buf, len) : -EINVAL; @@ -768,7 +771,7 @@ static struct dlm_space *get_space(char *name) i = config_group_find_item(space_list, name); mutex_unlock(&space_list->cg_subsys->su_mutex); - return to_space(i); + return config_item_to_space(i); } static void put_space(struct dlm_space *sp) @@ -776,6 +779,33 @@ static void put_space(struct dlm_space *sp) config_item_put(&sp->group.cg_item); } +static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y) +{ + switch (x->ss_family) { + case AF_INET: { + struct sockaddr_in *sinx = (struct sockaddr_in *)x; + struct sockaddr_in *siny = (struct sockaddr_in *)y; + if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr) + return 0; + if (sinx->sin_port != siny->sin_port) + return 0; + break; + } + case AF_INET6: { + struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x; + struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y; + if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr)) + return 0; + if (sinx->sin6_port != siny->sin6_port) + return 0; + break; + } + default: + return 0; + } + return 1; +} + static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) { struct config_item *i; @@ -788,7 +818,7 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) mutex_lock(&clusters_root.subsys.su_mutex); list_for_each_entry(i, &comm_list->cg_children, ci_entry) { - cm = to_comm(i); + cm = config_item_to_comm(i); if (nodeid) { if (cm->nodeid != nodeid) @@ -797,8 +827,7 @@ static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) config_item_get(i); break; } else { - if (!cm->addr_count || - memcmp(cm->addr[0], addr, sizeof(*addr))) + if (!cm->addr_count || !addr_compare(cm->addr[0], addr)) continue; found = 1; config_item_get(i); diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 5a7ac33b629c..868e4c9ef127 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions @@ -441,8 +441,11 @@ struct dlm_ls { uint32_t ls_global_id; /* global unique lockspace ID */ uint32_t ls_exflags; int ls_lvblen; - int ls_count; /* reference count */ + int ls_count; /* refcount of processes in + the dlm using this ls */ + int ls_create_count; /* create/release refcount */ unsigned long ls_flags; /* LSFL_ */ + unsigned long ls_scan_time; struct kobject ls_kobj; struct dlm_rsbtable *ls_rsbtbl; diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 499e16759e96..d910501de6d2 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions @@ -23,6 +23,7 @@ #include "lock.h" #include "recover.h" #include "requestqueue.h" +#include "user.h" static int ls_count; static struct mutex ls_lock; @@ -211,19 +212,41 @@ void dlm_lockspace_exit(void) kset_unregister(dlm_kset); } +static struct dlm_ls *find_ls_to_scan(void) +{ + struct dlm_ls *ls; + + spin_lock(&lslist_lock); + list_for_each_entry(ls, &lslist, ls_list) { + if (time_after_eq(jiffies, ls->ls_scan_time + + dlm_config.ci_scan_secs * HZ)) { + spin_unlock(&lslist_lock); + return ls; + } + } + spin_unlock(&lslist_lock); + return NULL; +} + static int dlm_scand(void *data) { struct dlm_ls *ls; + int timeout_jiffies = dlm_config.ci_scan_secs * HZ; while (!kthread_should_stop()) { - list_for_each_entry(ls, &lslist, ls_list) { + ls = find_ls_to_scan(); + if (ls) { if (dlm_lock_recovery_try(ls)) { + ls->ls_scan_time = jiffies; dlm_scan_rsbs(ls); dlm_scan_timeout(ls); dlm_unlock_recovery(ls); + } else { + ls->ls_scan_time += HZ; } + } else { + schedule_timeout_interruptible(timeout_jiffies); } - schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ); } return 0; } @@ -246,23 +269,6 @@ static void dlm_scand_stop(void) kthread_stop(scand_task); } -static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen) -{ - struct dlm_ls *ls; - - spin_lock(&lslist_lock); - - list_for_each_entry(ls, &lslist, ls_list) { - if (ls->ls_namelen == namelen && - memcmp(ls->ls_name, name, namelen) == 0) - goto out; - } - ls = NULL; - out: - spin_unlock(&lslist_lock); - return ls; -} - struct dlm_ls *dlm_find_lockspace_global(uint32_t id) { struct dlm_ls *ls; @@ -327,6 +333,7 @@ static void remove_lockspace(struct dlm_ls *ls) for (;;) { spin_lock(&lslist_lock); if (ls->ls_count == 0) { + WARN_ON(ls->ls_create_count != 0); list_del(&ls->ls_list); spin_unlock(&lslist_lock); return; @@ -381,7 +388,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, uint32_t flags, int lvblen) { struct dlm_ls *ls; - int i, size, error = -ENOMEM; + int i, size, error; int do_unreg = 0; if (namelen > DLM_LOCKSPACE_LEN) @@ -393,12 +400,37 @@ static int new_lockspace(char *name, int namelen, void **lockspace, if (!try_module_get(THIS_MODULE)) return -EINVAL; - ls = dlm_find_lockspace_name(name, namelen); - if (ls) { - *lockspace = ls; + if (!dlm_user_daemon_available()) { + module_put(THIS_MODULE); + return -EUNATCH; + } + + error = 0; + + spin_lock(&lslist_lock); + list_for_each_entry(ls, &lslist, ls_list) { + WARN_ON(ls->ls_create_count <= 0); + if (ls->ls_namelen != namelen) + continue; + if (memcmp(ls->ls_name, name, namelen)) + continue; + if (flags & DLM_LSFL_NEWEXCL) { + error = -EEXIST; + break; + } + ls->ls_create_count++; module_put(THIS_MODULE); - return -EEXIST; + error = 1; /* not an error, return 0 */ + break; } + spin_unlock(&lslist_lock); + + if (error < 0) + goto out; + if (error) + goto ret_zero; + + error = -ENOMEM; ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL); if (!ls) @@ -408,6 +440,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, ls->ls_lvblen = lvblen; ls->ls_count = 0; ls->ls_flags = 0; + ls->ls_scan_time = jiffies; if (flags & DLM_LSFL_TIMEWARN) set_bit(LSFL_TIMEWARN, &ls->ls_flags); @@ -418,8 +451,9 @@ static int new_lockspace(char *name, int namelen, void **lockspace, ls->ls_allocation = GFP_KERNEL; /* ls_exflags are forced to match among nodes, and we don't - need to require all nodes to have TIMEWARN or FS set */ - ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS)); + need to require all nodes to have some flags set */ + ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS | + DLM_LSFL_NEWEXCL)); size = dlm_config.ci_rsbtbl_size; ls->ls_rsbtbl_size = size; @@ -510,6 +544,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, down_write(&ls->ls_in_recovery); spin_lock(&lslist_lock); + ls->ls_create_count = 1; list_add(&ls->ls_list, &lslist); spin_unlock(&lslist_lock); @@ -548,7 +583,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, dlm_create_debug_file(ls); log_debug(ls, "join complete"); - + ret_zero: *lockspace = ls; return 0; @@ -635,13 +670,34 @@ static int release_lockspace(struct dlm_ls *ls, int force) struct dlm_lkb *lkb; struct dlm_rsb *rsb; struct list_head *head; - int i; - int busy = lockspace_busy(ls); + int i, busy, rv; + + busy = lockspace_busy(ls); + + spin_lock(&lslist_lock); + if (ls->ls_create_count == 1) { + if (busy > force) + rv = -EBUSY; + else { + /* remove_lockspace takes ls off lslist */ + ls->ls_create_count = 0; + rv = 0; + } + } else if (ls->ls_create_count > 1) { + rv = --ls->ls_create_count; + } else { + rv = -EINVAL; + } + spin_unlock(&lslist_lock); - if (busy > force) - return -EBUSY; + if (rv) { + log_debug(ls, "release_lockspace no remove %d", rv); + return rv; + } + + dlm_device_deregister(ls); - if (force < 3) + if (force < 3 && dlm_user_daemon_available()) do_uevent(ls, 0); dlm_recoverd_stop(ls); @@ -720,15 +776,10 @@ static int release_lockspace(struct dlm_ls *ls, int force) dlm_clear_members(ls); dlm_clear_members_gone(ls); kfree(ls->ls_node_array); + log_debug(ls, "release_lockspace final free"); kobject_put(&ls->ls_kobj); /* The ls structure will be freed when the kobject is done with */ - mutex_lock(&ls_lock); - ls_count--; - if (!ls_count) - threads_stop(); - mutex_unlock(&ls_lock); - module_put(THIS_MODULE); return 0; } @@ -750,11 +801,38 @@ static int release_lockspace(struct dlm_ls *ls, int force) int dlm_release_lockspace(void *lockspace, int force) { struct dlm_ls *ls; + int error; ls = dlm_find_lockspace_local(lockspace); if (!ls) return -EINVAL; dlm_put_lockspace(ls); - return release_lockspace(ls, force); + + mutex_lock(&ls_lock); + error = release_lockspace(ls, force); + if (!error) + ls_count--; + else if (!ls_count) + threads_stop(); + mutex_unlock(&ls_lock); + + return error; +} + +void dlm_stop_lockspaces(void) +{ + struct dlm_ls *ls; + + restart: + spin_lock(&lslist_lock); + list_for_each_entry(ls, &lslist, ls_list) { + if (!test_bit(LSFL_RUNNING, &ls->ls_flags)) + continue; + spin_unlock(&lslist_lock); + log_error(ls, "no userland control daemon, stopping lockspace"); + dlm_ls_stop(ls); + goto restart; + } + spin_unlock(&lslist_lock); } diff --git a/fs/dlm/lockspace.h b/fs/dlm/lockspace.h index 891eabbdd021..f879f87901f8 100644 --- a/fs/dlm/lockspace.h +++ b/fs/dlm/lockspace.h @@ -20,6 +20,7 @@ struct dlm_ls *dlm_find_lockspace_global(uint32_t id); struct dlm_ls *dlm_find_lockspace_local(void *id); struct dlm_ls *dlm_find_lockspace_device(int minor); void dlm_put_lockspace(struct dlm_ls *ls); +void dlm_stop_lockspaces(void); #endif /* __LOCKSPACE_DOT_H__ */ diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 34f14a14fb4e..b3832c67194a 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions @@ -15,7 +15,6 @@ #include <linux/poll.h> #include <linux/signal.h> #include <linux/spinlock.h> -#include <linux/smp_lock.h> #include <linux/dlm.h> #include <linux/dlm_device.h> @@ -27,6 +26,8 @@ static const char name_prefix[] = "dlm"; static const struct file_operations device_fops; +static atomic_t dlm_monitor_opened; +static int dlm_monitor_unused = 1; #ifdef CONFIG_COMPAT @@ -340,10 +341,15 @@ static int device_user_deadlock(struct dlm_user_proc *proc, return error; } -static int create_misc_device(struct dlm_ls *ls, char *name) +static int dlm_device_register(struct dlm_ls *ls, char *name) { int error, len; + /* The device is already registered. This happens when the + lockspace is created multiple times from userspace. */ + if (ls->ls_device.name) + return 0; + error = -ENOMEM; len = strlen(name) + strlen(name_prefix) + 2; ls->ls_device.name = kzalloc(len, GFP_KERNEL); @@ -363,6 +369,22 @@ fail: return error; } +int dlm_device_deregister(struct dlm_ls *ls) +{ + int error; + + /* The device is not registered. This happens when the lockspace + was never used from userspace, or when device_create_lockspace() + calls dlm_release_lockspace() after the register fails. */ + if (!ls->ls_device.name) + return 0; + + error = misc_deregister(&ls->ls_device); + if (!error) + kfree(ls->ls_device.name); + return error; +} + static int device_user_purge(struct dlm_user_proc *proc, struct dlm_purge_params *params) { @@ -397,7 +419,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params) if (!ls) return -ENOENT; - error = create_misc_device(ls, params->name); + error = dlm_device_register(ls, params->name); dlm_put_lockspace(ls); if (error) @@ -421,31 +443,22 @@ static int device_remove_lockspace(struct dlm_lspace_params *params) if (!ls) return -ENOENT; - /* Deregister the misc device first, so we don't have - * a device that's not attached to a lockspace. If - * dlm_release_lockspace fails then we can recreate it - */ - error = misc_deregister(&ls->ls_device); - if (error) { - dlm_put_lockspace(ls); - goto out; - } - kfree(ls->ls_device.name); - if (params->flags & DLM_USER_LSFLG_FORCEFREE) force = 2; lockspace = ls->ls_local_handle; + dlm_put_lockspace(ls); - /* dlm_release_lockspace waits for references to go to zero, - so all processes will need to close their device for the ls - before the release will procede */ + /* The final dlm_release_lockspace waits for references to go to + zero, so all processes will need to close their device for the + ls before the release will proceed. release also calls the + device_deregister above. Converting a positive return value + from release to zero means that userspace won't know when its + release was the final one, but it shouldn't need to know. */ - dlm_put_lockspace(ls); error = dlm_release_lockspace(lockspace, force); - if (error) - create_misc_device(ls, ls->ls_name); - out: + if (error > 0) + error = 0; return error; } @@ -623,17 +636,13 @@ static int device_open(struct inode *inode, struct file *file) struct dlm_user_proc *proc; struct dlm_ls *ls; - lock_kernel(); ls = dlm_find_lockspace_device(iminor(inode)); - if (!ls) { - unlock_kernel(); + if (!ls) return -ENOENT; - } proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL); if (!proc) { dlm_put_lockspace(ls); - unlock_kernel(); return -ENOMEM; } @@ -645,7 +654,6 @@ static int device_open(struct inode *inode, struct file *file) spin_lock_init(&proc->locks_spin); init_waitqueue_head(&proc->wait); file->private_data = proc; - unlock_kernel(); return 0; } @@ -878,9 +886,28 @@ static unsigned int device_poll(struct file *file, poll_table *wait) return 0; } +int dlm_user_daemon_available(void) +{ + /* dlm_controld hasn't started (or, has started, but not + properly populated configfs) */ + + if (!dlm_our_nodeid()) + return 0; + + /* This is to deal with versions of dlm_controld that don't + know about the monitor device. We assume that if the + dlm_controld was started (above), but the monitor device + was never opened, that it's an old version. dlm_controld + should open the monitor device before populating configfs. */ + + if (dlm_monitor_unused) + return 1; + + return atomic_read(&dlm_monitor_opened) ? 1 : 0; +} + static int ctl_device_open(struct inode *inode, struct file *file) { - cycle_kernel_lock(); file->private_data = NULL; return 0; } @@ -890,6 +917,20 @@ static int ctl_device_close(struct inode *inode, struct file *file) return 0; } +static int monitor_device_open(struct inode *inode, struct file *file) +{ + atomic_inc(&dlm_monitor_opened); + dlm_monitor_unused = 0; + return 0; +} + +static int monitor_device_close(struct inode *inode, struct file *file) +{ + if (atomic_dec_and_test(&dlm_monitor_opened)) + dlm_stop_lockspaces(); + return 0; +} + static const struct file_operations device_fops = { .open = device_open, .release = device_close, @@ -913,19 +954,42 @@ static struct miscdevice ctl_device = { .minor = MISC_DYNAMIC_MINOR, }; +static const struct file_operations monitor_device_fops = { + .open = monitor_device_open, + .release = monitor_device_close, + .owner = THIS_MODULE, +}; + +static struct miscdevice monitor_device = { + .name = "dlm-monitor", + .fops = &monitor_device_fops, + .minor = MISC_DYNAMIC_MINOR, +}; + int __init dlm_user_init(void) { int error; + atomic_set(&dlm_monitor_opened, 0); + error = misc_register(&ctl_device); - if (error) + if (error) { log_print("misc_register failed for control device"); + goto out; + } + error = misc_register(&monitor_device); + if (error) { + log_print("misc_register failed for monitor device"); + misc_deregister(&ctl_device); + } + out: return error; } void dlm_user_exit(void) { misc_deregister(&ctl_device); + misc_deregister(&monitor_device); } diff --git a/fs/dlm/user.h b/fs/dlm/user.h index d38e9f3e4151..35eb6a13d616 100644 --- a/fs/dlm/user.h +++ b/fs/dlm/user.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions @@ -12,5 +12,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type); int dlm_user_init(void); void dlm_user_exit(void); +int dlm_device_deregister(struct dlm_ls *ls); +int dlm_user_daemon_available(void); #endif diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index 302e95c4af7e..fb98b3d847ed 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -6,6 +6,7 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/msdos_fs.h> +#include <linux/blkdev.h> struct fatent_operations { void (*ent_blocknr)(struct super_block *, int, int *, sector_t *); @@ -535,6 +536,7 @@ int fat_free_clusters(struct inode *inode, int cluster) struct fat_entry fatent; struct buffer_head *bhs[MAX_BUF_PER_PAGE]; int i, err, nr_bhs; + int first_cl = cluster; nr_bhs = 0; fatent_init(&fatent); @@ -551,6 +553,18 @@ int fat_free_clusters(struct inode *inode, int cluster) goto error; } + /* + * Issue discard for the sectors we no longer care about, + * batching contiguous clusters into one request + */ + if (cluster != fatent.entry + 1) { + int nr_clus = fatent.entry - first_cl + 1; + + sb_issue_discard(sb, fat_clus_to_blknr(sbi, first_cl), + nr_clus * sbi->sec_per_clus); + first_cl = cluster; + } + ops->ent_put(&fatent, FAT_ENT_FREE); if (sbi->free_clusters != -1) { sbi->free_clusters++; diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 13391e546616..c962283d4e7f 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1265,6 +1265,8 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; if (time_before(now, holdtime)) delay = holdtime - now; + if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) + delay = gl->gl_ops->go_min_hold_time; spin_lock(&gl->gl_spin); handle_callback(gl, state, 1, delay); @@ -1578,8 +1580,6 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags) *p++ = 'a'; if (flags & GL_EXACT) *p++ = 'E'; - if (flags & GL_ATIME) - *p++ = 'a'; if (flags & GL_NOCACHE) *p++ = 'c'; if (test_bit(HIF_HOLDER, &iflags)) @@ -1816,15 +1816,17 @@ restart: if (gl) { gi->gl = hlist_entry(gl->gl_list.next, struct gfs2_glock, gl_list); - if (gi->gl) - gfs2_glock_hold(gi->gl); + } else { + gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first, + struct gfs2_glock, gl_list); } + if (gi->gl) + gfs2_glock_hold(gi->gl); read_unlock(gl_lock_addr(gi->hash)); if (gl) gfs2_glock_put(gl); - if (gl && gi->gl == NULL) - gi->hash++; while (gi->gl == NULL) { + gi->hash++; if (gi->hash >= GFS2_GL_HASH_SIZE) return 1; read_lock(gl_lock_addr(gi->hash)); @@ -1833,7 +1835,6 @@ restart: if (gi->gl) gfs2_glock_hold(gi->gl); read_unlock(gl_lock_addr(gi->hash)); - gi->hash++; } if (gi->sdp != gi->gl->gl_sbd) diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 971d92af70fc..695c6b193611 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -24,7 +24,6 @@ #define GL_ASYNC 0x00000040 #define GL_EXACT 0x00000080 #define GL_SKIP 0x00000100 -#define GL_ATIME 0x00000200 #define GL_NOCACHE 0x00000400 #define GLR_TRYFAILED 13 diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 448697a5c462..f566ec1b4e8e 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -386,20 +386,21 @@ struct gfs2_statfs_change_host { #define GFS2_DATA_ORDERED 2 struct gfs2_args { - char ar_lockproto[GFS2_LOCKNAME_LEN]; /* Name of the Lock Protocol */ - char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */ - char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */ - int ar_spectator; /* Don't get a journal because we're always RO */ - int ar_ignore_local_fs; /* Don't optimize even if local_fs is 1 */ - int ar_localflocks; /* Let the VFS do flock|fcntl locks for us */ - int ar_localcaching; /* Local-style caching (dangerous on multihost) */ - int ar_debug; /* Oops on errors instead of trying to be graceful */ - int ar_upgrade; /* Upgrade ondisk/multihost format */ - unsigned int ar_num_glockd; /* Number of glockd threads */ - int ar_posix_acl; /* Enable posix acls */ - int ar_quota; /* off/account/on */ - int ar_suiddir; /* suiddir support */ - int ar_data; /* ordered/writeback */ + char ar_lockproto[GFS2_LOCKNAME_LEN]; /* Name of the Lock Protocol */ + char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */ + char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */ + unsigned int ar_spectator:1; /* Don't get a journal */ + unsigned int ar_ignore_local_fs:1; /* Ignore optimisations */ + unsigned int ar_localflocks:1; /* Let the VFS do flock|fcntl */ + unsigned int ar_localcaching:1; /* Local caching */ + unsigned int ar_debug:1; /* Oops on errors */ + unsigned int ar_upgrade:1; /* Upgrade ondisk format */ + unsigned int ar_posix_acl:1; /* Enable posix acls */ + unsigned int ar_quota:2; /* off/account/on */ + unsigned int ar_suiddir:1; /* suiddir support */ + unsigned int ar_data:2; /* ordered/writeback */ + unsigned int ar_meta:1; /* mount metafs */ + unsigned int ar_num_glockd; /* Number of glockd threads */ }; struct gfs2_tune { @@ -419,7 +420,6 @@ struct gfs2_tune { unsigned int gt_quota_scale_den; /* Denominator */ unsigned int gt_quota_cache_secs; unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ - unsigned int gt_atime_quantum; /* Min secs between atime updates */ unsigned int gt_new_files_jdata; unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ unsigned int gt_stall_secs; /* Detects trouble! */ @@ -432,7 +432,7 @@ enum { SDF_JOURNAL_CHECKED = 0, SDF_JOURNAL_LIVE = 1, SDF_SHUTDOWN = 2, - SDF_NOATIME = 3, + SDF_NOBARRIERS = 3, }; #define GFS2_FSNAME_LEN 256 @@ -461,7 +461,6 @@ struct gfs2_sb_host { struct gfs2_sbd { struct super_block *sd_vfs; - struct super_block *sd_vfs_meta; struct kobject sd_kobj; unsigned long sd_flags; /* SDF_... */ struct gfs2_sb_host sd_sb; @@ -499,7 +498,9 @@ struct gfs2_sbd { /* Inode Stuff */ - struct inode *sd_master_dir; + struct dentry *sd_master_dir; + struct dentry *sd_root_dir; + struct inode *sd_jindex; struct inode *sd_inum_inode; struct inode *sd_statfs_inode; @@ -634,7 +635,6 @@ struct gfs2_sbd { /* Debugging crud */ unsigned long sd_last_warning; - struct vfsmount *sd_gfs2mnt; struct dentry *debugfs_dir; /* debugfs directory */ struct dentry *debugfs_dentry_glocks; /* for debugfs */ }; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 8b0806a32948..7cee695fa441 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -18,6 +18,7 @@ #include <linux/crc32.h> #include <linux/lm_interface.h> #include <linux/security.h> +#include <linux/time.h> #include "gfs2.h" #include "incore.h" @@ -249,6 +250,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) { struct gfs2_dinode_host *di = &ip->i_di; const struct gfs2_dinode *str = buf; + struct timespec atime; u16 height, depth; if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) @@ -275,8 +277,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) di->di_size = be64_to_cpu(str->di_size); i_size_write(&ip->i_inode, di->di_size); gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); - ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); - ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); + atime.tv_sec = be64_to_cpu(str->di_atime); + atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); + if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0) + ip->i_inode.i_atime = atime; ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); @@ -1033,13 +1037,11 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, if (bh) brelse(bh); - if (!inode) - return ERR_PTR(-ENOMEM); return inode; fail_gunlock2: gfs2_glock_dq_uninit(ghs + 1); - if (inode) + if (inode && !IS_ERR(inode)) iput(inode); fail_gunlock: gfs2_glock_dq(ghs); @@ -1140,54 +1142,6 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, return 0; } -/* - * gfs2_ok_to_move - check if it's ok to move a directory to another directory - * @this: move this - * @to: to here - * - * Follow @to back to the root and make sure we don't encounter @this - * Assumes we already hold the rename lock. - * - * Returns: errno - */ - -int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) -{ - struct inode *dir = &to->i_inode; - struct super_block *sb = dir->i_sb; - struct inode *tmp; - struct qstr dotdot; - int error = 0; - - gfs2_str2qstr(&dotdot, ".."); - - igrab(dir); - - for (;;) { - if (dir == &this->i_inode) { - error = -EINVAL; - break; - } - if (dir == sb->s_root->d_inode) { - error = 0; - break; - } - - tmp = gfs2_lookupi(dir, &dotdot, 1); - if (IS_ERR(tmp)) { - error = PTR_ERR(tmp); - break; - } - - iput(dir); - dir = tmp; - } - - iput(dir); - - return error; -} - /** * gfs2_readlinki - return the contents of a symlink * @ip: the symlink's inode @@ -1207,8 +1161,8 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len) unsigned int x; int error; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh); - error = gfs2_glock_nq_atime(&i_gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + error = gfs2_glock_nq(&i_gh); if (error) { gfs2_holder_uninit(&i_gh); return error; @@ -1243,101 +1197,6 @@ out: return error; } -/** - * gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and - * conditionally update the inode's atime - * @gh: the holder to acquire - * - * Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap - * Update if the difference between the current time and the inode's current - * atime is greater than an interval specified at mount. - * - * Returns: errno - */ - -int gfs2_glock_nq_atime(struct gfs2_holder *gh) -{ - struct gfs2_glock *gl = gh->gh_gl; - struct gfs2_sbd *sdp = gl->gl_sbd; - struct gfs2_inode *ip = gl->gl_object; - s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum); - unsigned int state; - int flags; - int error; - struct timespec tv = CURRENT_TIME; - - if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) || - gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) || - gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops)) - return -EINVAL; - - state = gh->gh_state; - flags = gh->gh_flags; - - error = gfs2_glock_nq(gh); - if (error) - return error; - - if (test_bit(SDF_NOATIME, &sdp->sd_flags) || - (sdp->sd_vfs->s_flags & MS_RDONLY)) - return 0; - - if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { - gfs2_glock_dq(gh); - gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY, - gh); - error = gfs2_glock_nq(gh); - if (error) - return error; - - /* Verify that atime hasn't been updated while we were - trying to get exclusive lock. */ - - tv = CURRENT_TIME; - if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { - struct buffer_head *dibh; - struct gfs2_dinode *di; - - error = gfs2_trans_begin(sdp, RES_DINODE, 0); - if (error == -EROFS) - return 0; - if (error) - goto fail; - - error = gfs2_meta_inode_buffer(ip, &dibh); - if (error) - goto fail_end_trans; - - ip->i_inode.i_atime = tv; - - gfs2_trans_add_bh(ip->i_gl, dibh, 1); - di = (struct gfs2_dinode *)dibh->b_data; - di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); - di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); - brelse(dibh); - - gfs2_trans_end(sdp); - } - - /* If someone else has asked for the glock, - unlock and let them have it. Then reacquire - in the original state. */ - if (gfs2_glock_is_blocking(gl)) { - gfs2_glock_dq(gh); - gfs2_holder_reinit(state, flags, gh); - return gfs2_glock_nq(gh); - } - } - - return 0; - -fail_end_trans: - gfs2_trans_end(sdp); -fail: - gfs2_glock_dq(gh); - return error; -} - static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) { diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 58f9607d6a86..2d43f69610a0 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -91,9 +91,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, const struct gfs2_inode *ip); int gfs2_permission(struct inode *inode, int mask); -int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to); int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len); -int gfs2_glock_nq_atime(struct gfs2_holder *gh); int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c index 09d78c216f48..0c4cbe6c8285 100644 --- a/fs/gfs2/locking/dlm/mount.c +++ b/fs/gfs2/locking/dlm/mount.c @@ -144,7 +144,8 @@ static int gdlm_mount(char *table_name, char *host_data, error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), &ls->dlm_lockspace, - DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0), + DLM_LSFL_FS | DLM_LSFL_NEWEXCL | + (nodir ? DLM_LSFL_NODIR : 0), GDLM_LVB_SIZE); if (error) { log_error("dlm_new_lockspace error %d", error); diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 6c6af9f5e3ab..ad305854bdc6 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/kthread.h> #include <linux/freezer.h> +#include <linux/bio.h> #include "gfs2.h" #include "incore.h" @@ -584,7 +585,6 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) memset(bh->b_data, 0, bh->b_size); set_buffer_uptodate(bh); clear_buffer_dirty(bh); - unlock_buffer(bh); gfs2_ail1_empty(sdp, 0); tail = current_tail(sdp); @@ -601,8 +601,23 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) hash = gfs2_disk_hash(bh->b_data, sizeof(struct gfs2_log_header)); lh->lh_hash = cpu_to_be32(hash); - set_buffer_dirty(bh); - if (sync_dirty_buffer(bh)) + bh->b_end_io = end_buffer_write_sync; + if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) + goto skip_barrier; + get_bh(bh); + submit_bh(WRITE_BARRIER | (1 << BIO_RW_META), bh); + wait_on_buffer(bh); + if (buffer_eopnotsupp(bh)) { + clear_buffer_eopnotsupp(bh); + set_buffer_uptodate(bh); + set_bit(SDF_NOBARRIERS, &sdp->sd_flags); + lock_buffer(bh); +skip_barrier: + get_bh(bh); + submit_bh(WRITE_SYNC | (1 << BIO_RW_META), bh); + wait_on_buffer(bh); + } + if (!buffer_uptodate(bh)) gfs2_io_error_bh(sdp, bh); brelse(bh); diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index b941f9f9f958..df48333e6f01 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c @@ -42,6 +42,7 @@ enum { Opt_nosuiddir, Opt_data_writeback, Opt_data_ordered, + Opt_meta, Opt_err, }; @@ -66,6 +67,7 @@ static match_table_t tokens = { {Opt_nosuiddir, "nosuiddir"}, {Opt_data_writeback, "data=writeback"}, {Opt_data_ordered, "data=ordered"}, + {Opt_meta, "meta"}, {Opt_err, NULL} }; @@ -239,6 +241,11 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) case Opt_data_ordered: args->ar_data = GFS2_DATA_ORDERED; break; + case Opt_meta: + if (remount && args->ar_meta != 1) + goto cant_remount; + args->ar_meta = 1; + break; case Opt_err: default: fs_info(sdp, "unknown option: %s\n", o); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index e64a1b04117a..27563816e1c5 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -512,8 +512,8 @@ static int gfs2_readpage(struct file *file, struct page *page) int error; unlock_page(page); - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - error = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + error = gfs2_glock_nq(&gh); if (unlikely(error)) goto out; error = AOP_TRUNCATED_PAGE; @@ -594,8 +594,8 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping, struct gfs2_holder gh; int ret; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - ret = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + ret = gfs2_glock_nq(&gh); if (unlikely(ret)) goto out_uninit; if (!gfs2_is_stuffed(ip)) @@ -636,8 +636,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, unsigned to = from + len; struct page *page; - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &ip->i_gh); - error = gfs2_glock_nq_atime(&ip->i_gh); + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); + error = gfs2_glock_nq(&ip->i_gh); if (unlikely(error)) goto out_uninit; @@ -975,7 +975,7 @@ static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset) if (gfs2_is_stuffed(ip)) return 0; - if (offset > i_size_read(&ip->i_inode)) + if (offset >= i_size_read(&ip->i_inode)) return 0; return 1; } @@ -1000,8 +1000,8 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, * unfortunately have the option of only flushing a range like * the VFS does. */ - gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, GL_ATIME, &gh); - rv = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh); + rv = gfs2_glock_nq(&gh); if (rv) return rv; rv = gfs2_ok_for_dio(ip, rw, offset); diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index e9a366d4411c..3a747f8e2188 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -89,8 +89,8 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) u64 offset = file->f_pos; int error; - gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh); - error = gfs2_glock_nq_atime(&d_gh); + gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + error = gfs2_glock_nq(&d_gh); if (error) { gfs2_holder_uninit(&d_gh); return error; @@ -153,8 +153,8 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) int error; u32 fsflags; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); - error = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + error = gfs2_glock_nq(&gh); if (error) return error; @@ -351,8 +351,8 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) struct gfs2_alloc *al; int ret; - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &gh); - ret = gfs2_glock_nq_atime(&gh); + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + ret = gfs2_glock_nq(&gh); if (ret) goto out; @@ -434,8 +434,8 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) struct gfs2_holder i_gh; int error; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh); - error = gfs2_glock_nq_atime(&i_gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + error = gfs2_glock_nq(&i_gh); if (error) { gfs2_holder_uninit(&i_gh); return error; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index b4d1d6490633..b117fcf2c4f5 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -40,6 +40,44 @@ #define DO 0 #define UNDO 1 +static const u32 gfs2_old_fs_formats[] = { + 0 +}; + +static const u32 gfs2_old_multihost_formats[] = { + 0 +}; + +/** + * gfs2_tune_init - Fill a gfs2_tune structure with default values + * @gt: tune + * + */ + +static void gfs2_tune_init(struct gfs2_tune *gt) +{ + spin_lock_init(>->gt_spin); + + gt->gt_demote_secs = 300; + gt->gt_incore_log_blocks = 1024; + gt->gt_log_flush_secs = 60; + gt->gt_recoverd_secs = 60; + gt->gt_logd_secs = 1; + gt->gt_quotad_secs = 5; + gt->gt_quota_simul_sync = 64; + gt->gt_quota_warn_period = 10; + gt->gt_quota_scale_num = 1; + gt->gt_quota_scale_den = 1; + gt->gt_quota_cache_secs = 300; + gt->gt_quota_quantum = 60; + gt->gt_new_files_jdata = 0; + gt->gt_max_readahead = 1 << 18; + gt->gt_stall_secs = 600; + gt->gt_complain_secs = 10; + gt->gt_statfs_quantum = 30; + gt->gt_statfs_slow = 0; +} + static struct gfs2_sbd *init_sbd(struct super_block *sb) { struct gfs2_sbd *sdp; @@ -96,21 +134,271 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) return sdp; } -static void init_vfs(struct super_block *sb, unsigned noatime) + +/** + * gfs2_check_sb - Check superblock + * @sdp: the filesystem + * @sb: The superblock + * @silent: Don't print a message if the check fails + * + * Checks the version code of the FS is one that we understand how to + * read and that the sizes of the various on-disk structures have not + * changed. + */ + +static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) { - struct gfs2_sbd *sdp = sb->s_fs_info; + unsigned int x; - sb->s_magic = GFS2_MAGIC; - sb->s_op = &gfs2_super_ops; - sb->s_export_op = &gfs2_export_ops; - sb->s_time_gran = 1; - sb->s_maxbytes = MAX_LFS_FILESIZE; + if (sb->sb_magic != GFS2_MAGIC || + sb->sb_type != GFS2_METATYPE_SB) { + if (!silent) + printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); + return -EINVAL; + } + + /* If format numbers match exactly, we're done. */ + + if (sb->sb_fs_format == GFS2_FORMAT_FS && + sb->sb_multihost_format == GFS2_FORMAT_MULTI) + return 0; + + if (sb->sb_fs_format != GFS2_FORMAT_FS) { + for (x = 0; gfs2_old_fs_formats[x]; x++) + if (gfs2_old_fs_formats[x] == sb->sb_fs_format) + break; + + if (!gfs2_old_fs_formats[x]) { + printk(KERN_WARNING + "GFS2: code version (%u, %u) is incompatible " + "with ondisk format (%u, %u)\n", + GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk(KERN_WARNING + "GFS2: I don't know how to upgrade this FS\n"); + return -EINVAL; + } + } + + if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) { + for (x = 0; gfs2_old_multihost_formats[x]; x++) + if (gfs2_old_multihost_formats[x] == + sb->sb_multihost_format) + break; + + if (!gfs2_old_multihost_formats[x]) { + printk(KERN_WARNING + "GFS2: code version (%u, %u) is incompatible " + "with ondisk format (%u, %u)\n", + GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk(KERN_WARNING + "GFS2: I don't know how to upgrade this FS\n"); + return -EINVAL; + } + } + + if (!sdp->sd_args.ar_upgrade) { + printk(KERN_WARNING + "GFS2: code version (%u, %u) is incompatible " + "with ondisk format (%u, %u)\n", + GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, + sb->sb_fs_format, sb->sb_multihost_format); + printk(KERN_INFO + "GFS2: Use the \"upgrade\" mount option to upgrade " + "the FS\n"); + printk(KERN_INFO "GFS2: See the manual for more details\n"); + return -EINVAL; + } + + return 0; +} + +static void end_bio_io_page(struct bio *bio, int error) +{ + struct page *page = bio->bi_private; - if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME)) - set_bit(noatime, &sdp->sd_flags); + if (!error) + SetPageUptodate(page); + else + printk(KERN_WARNING "gfs2: error %d reading superblock\n", error); + unlock_page(page); +} + +static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) +{ + const struct gfs2_sb *str = buf; + + sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); + sb->sb_type = be32_to_cpu(str->sb_header.mh_type); + sb->sb_format = be32_to_cpu(str->sb_header.mh_format); + sb->sb_fs_format = be32_to_cpu(str->sb_fs_format); + sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format); + sb->sb_bsize = be32_to_cpu(str->sb_bsize); + sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift); + sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr); + sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino); + sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr); + sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino); + + memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); + memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); +} + +/** + * gfs2_read_super - Read the gfs2 super block from disk + * @sdp: The GFS2 super block + * @sector: The location of the super block + * @error: The error code to return + * + * This uses the bio functions to read the super block from disk + * because we want to be 100% sure that we never read cached data. + * A super block is read twice only during each GFS2 mount and is + * never written to by the filesystem. The first time its read no + * locks are held, and the only details which are looked at are those + * relating to the locking protocol. Once locking is up and working, + * the sb is read again under the lock to establish the location of + * the master directory (contains pointers to journals etc) and the + * root directory. + * + * Returns: 0 on success or error + */ + +static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) +{ + struct super_block *sb = sdp->sd_vfs; + struct gfs2_sb *p; + struct page *page; + struct bio *bio; + + page = alloc_page(GFP_NOFS); + if (unlikely(!page)) + return -ENOBUFS; + + ClearPageUptodate(page); + ClearPageDirty(page); + lock_page(page); + + bio = bio_alloc(GFP_NOFS, 1); + if (unlikely(!bio)) { + __free_page(page); + return -ENOBUFS; + } - /* Don't let the VFS update atimes. GFS2 handles this itself. */ - sb->s_flags |= MS_NOATIME | MS_NODIRATIME; + bio->bi_sector = sector * (sb->s_blocksize >> 9); + bio->bi_bdev = sb->s_bdev; + bio_add_page(bio, page, PAGE_SIZE, 0); + + bio->bi_end_io = end_bio_io_page; + bio->bi_private = page; + submit_bio(READ_SYNC | (1 << BIO_RW_META), bio); + wait_on_page_locked(page); + bio_put(bio); + if (!PageUptodate(page)) { + __free_page(page); + return -EIO; + } + p = kmap(page); + gfs2_sb_in(&sdp->sd_sb, p); + kunmap(page); + __free_page(page); + return 0; +} +/** + * gfs2_read_sb - Read super block + * @sdp: The GFS2 superblock + * @gl: the glock for the superblock (assumed to be held) + * @silent: Don't print message if mount fails + * + */ + +static int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) +{ + u32 hash_blocks, ind_blocks, leaf_blocks; + u32 tmp_blocks; + unsigned int x; + int error; + + error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); + if (error) { + if (!silent) + fs_err(sdp, "can't read superblock\n"); + return error; + } + + error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); + if (error) + return error; + + sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - + GFS2_BASIC_BLOCK_SHIFT; + sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; + sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_dinode)) / sizeof(u64); + sdp->sd_inptrs = (sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_meta_header)) / sizeof(u64); + sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header); + sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2; + sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1; + sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(u64); + sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_meta_header)) / + sizeof(struct gfs2_quota_change); + + /* Compute maximum reservation required to add a entry to a directory */ + + hash_blocks = DIV_ROUND_UP(sizeof(u64) * (1 << GFS2_DIR_MAX_DEPTH), + sdp->sd_jbsize); + + ind_blocks = 0; + for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) { + tmp_blocks = DIV_ROUND_UP(tmp_blocks, sdp->sd_inptrs); + ind_blocks += tmp_blocks; + } + + leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH; + + sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks; + + sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_dinode); + sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs; + for (x = 2;; x++) { + u64 space, d; + u32 m; + + space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs; + d = space; + m = do_div(d, sdp->sd_inptrs); + + if (d != sdp->sd_heightsize[x - 1] || m) + break; + sdp->sd_heightsize[x] = space; + } + sdp->sd_max_height = x; + sdp->sd_heightsize[x] = ~0; + gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); + + sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - + sizeof(struct gfs2_dinode); + sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs; + for (x = 2;; x++) { + u64 space, d; + u32 m; + + space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs; + d = space; + m = do_div(d, sdp->sd_inptrs); + + if (d != sdp->sd_jheightsize[x - 1] || m) + break; + sdp->sd_jheightsize[x] = space; + } + sdp->sd_max_jheight = x; + sdp->sd_jheightsize[x] = ~0; + gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); + + return 0; } static int init_names(struct gfs2_sbd *sdp, int silent) @@ -224,51 +512,59 @@ fail: return error; } -static inline struct inode *gfs2_lookup_root(struct super_block *sb, - u64 no_addr) +static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr, + u64 no_addr, const char *name) { - return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); + struct gfs2_sbd *sdp = sb->s_fs_info; + struct dentry *dentry; + struct inode *inode; + + inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); + if (IS_ERR(inode)) { + fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode)); + return PTR_ERR(inode); + } + dentry = d_alloc_root(inode); + if (!dentry) { + fs_err(sdp, "can't alloc %s dentry\n", name); + iput(inode); + return -ENOMEM; + } + dentry->d_op = &gfs2_dops; + *dptr = dentry; + return 0; } -static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) +static int init_sb(struct gfs2_sbd *sdp, int silent) { struct super_block *sb = sdp->sd_vfs; struct gfs2_holder sb_gh; u64 no_addr; - struct inode *inode; - int error = 0; + int ret; - if (undo) { - if (sb->s_root) { - dput(sb->s_root); - sb->s_root = NULL; - } - return 0; + ret = gfs2_glock_nq_num(sdp, GFS2_SB_LOCK, &gfs2_meta_glops, + LM_ST_SHARED, 0, &sb_gh); + if (ret) { + fs_err(sdp, "can't acquire superblock glock: %d\n", ret); + return ret; } - error = gfs2_glock_nq_num(sdp, GFS2_SB_LOCK, &gfs2_meta_glops, - LM_ST_SHARED, 0, &sb_gh); - if (error) { - fs_err(sdp, "can't acquire superblock glock: %d\n", error); - return error; - } - - error = gfs2_read_sb(sdp, sb_gh.gh_gl, silent); - if (error) { - fs_err(sdp, "can't read superblock: %d\n", error); + ret = gfs2_read_sb(sdp, sb_gh.gh_gl, silent); + if (ret) { + fs_err(sdp, "can't read superblock: %d\n", ret); goto out; } /* Set up the buffer cache and SB for real */ if (sdp->sd_sb.sb_bsize < bdev_hardsect_size(sb->s_bdev)) { - error = -EINVAL; + ret = -EINVAL; fs_err(sdp, "FS block size (%u) is too small for device " "block size (%u)\n", sdp->sd_sb.sb_bsize, bdev_hardsect_size(sb->s_bdev)); goto out; } if (sdp->sd_sb.sb_bsize > PAGE_SIZE) { - error = -EINVAL; + ret = -EINVAL; fs_err(sdp, "FS block size (%u) is too big for machine " "page size (%u)\n", sdp->sd_sb.sb_bsize, (unsigned int)PAGE_SIZE); @@ -278,26 +574,21 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) /* Get the root inode */ no_addr = sdp->sd_sb.sb_root_dir.no_addr; - if (sb->s_type == &gfs2meta_fs_type) - no_addr = sdp->sd_sb.sb_master_dir.no_addr; - inode = gfs2_lookup_root(sb, no_addr); - if (IS_ERR(inode)) { - error = PTR_ERR(inode); - fs_err(sdp, "can't read in root inode: %d\n", error); + ret = gfs2_lookup_root(sb, &sdp->sd_root_dir, no_addr, "root"); + if (ret) goto out; - } - sb->s_root = d_alloc_root(inode); - if (!sb->s_root) { - fs_err(sdp, "can't get root dentry\n"); - error = -ENOMEM; - iput(inode); - } else - sb->s_root->d_op = &gfs2_dops; - + /* Get the master inode */ + no_addr = sdp->sd_sb.sb_master_dir.no_addr; + ret = gfs2_lookup_root(sb, &sdp->sd_master_dir, no_addr, "master"); + if (ret) { + dput(sdp->sd_root_dir); + goto out; + } + sb->s_root = dget(sdp->sd_args.ar_meta ? sdp->sd_master_dir : sdp->sd_root_dir); out: gfs2_glock_dq_uninit(&sb_gh); - return error; + return ret; } /** @@ -372,6 +663,7 @@ static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp) static int init_journal(struct gfs2_sbd *sdp, int undo) { + struct inode *master = sdp->sd_master_dir->d_inode; struct gfs2_holder ji_gh; struct task_struct *p; struct gfs2_inode *ip; @@ -383,7 +675,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) goto fail_recoverd; } - sdp->sd_jindex = gfs2_lookup_simple(sdp->sd_master_dir, "jindex"); + sdp->sd_jindex = gfs2_lookup_simple(master, "jindex"); if (IS_ERR(sdp->sd_jindex)) { fs_err(sdp, "can't lookup journal index: %d\n", error); return PTR_ERR(sdp->sd_jindex); @@ -506,25 +798,17 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) { int error = 0; struct gfs2_inode *ip; - struct inode *inode; + struct inode *master = sdp->sd_master_dir->d_inode; if (undo) goto fail_qinode; - inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr); - if (IS_ERR(inode)) { - error = PTR_ERR(inode); - fs_err(sdp, "can't read in master directory: %d\n", error); - goto fail; - } - sdp->sd_master_dir = inode; - error = init_journal(sdp, undo); if (error) - goto fail_master; + goto fail; /* Read in the master inode number inode */ - sdp->sd_inum_inode = gfs2_lookup_simple(sdp->sd_master_dir, "inum"); + sdp->sd_inum_inode = gfs2_lookup_simple(master, "inum"); if (IS_ERR(sdp->sd_inum_inode)) { error = PTR_ERR(sdp->sd_inum_inode); fs_err(sdp, "can't read in inum inode: %d\n", error); @@ -533,7 +817,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) /* Read in the master statfs inode */ - sdp->sd_statfs_inode = gfs2_lookup_simple(sdp->sd_master_dir, "statfs"); + sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs"); if (IS_ERR(sdp->sd_statfs_inode)) { error = PTR_ERR(sdp->sd_statfs_inode); fs_err(sdp, "can't read in statfs inode: %d\n", error); @@ -541,7 +825,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) } /* Read in the resource index inode */ - sdp->sd_rindex = gfs2_lookup_simple(sdp->sd_master_dir, "rindex"); + sdp->sd_rindex = gfs2_lookup_simple(master, "rindex"); if (IS_ERR(sdp->sd_rindex)) { error = PTR_ERR(sdp->sd_rindex); fs_err(sdp, "can't get resource index inode: %d\n", error); @@ -552,7 +836,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) sdp->sd_rindex_uptodate = 0; /* Read in the quota inode */ - sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota"); + sdp->sd_quota_inode = gfs2_lookup_simple(master, "quota"); if (IS_ERR(sdp->sd_quota_inode)) { error = PTR_ERR(sdp->sd_quota_inode); fs_err(sdp, "can't get quota file inode: %d\n", error); @@ -571,8 +855,6 @@ fail_inum: iput(sdp->sd_inum_inode); fail_journal: init_journal(sdp, UNDO); -fail_master: - iput(sdp->sd_master_dir); fail: return error; } @@ -583,6 +865,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo) char buf[30]; int error = 0; struct gfs2_inode *ip; + struct inode *master = sdp->sd_master_dir->d_inode; if (sdp->sd_args.ar_spectator) return 0; @@ -590,7 +873,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo) if (undo) goto fail_qc_gh; - pn = gfs2_lookup_simple(sdp->sd_master_dir, "per_node"); + pn = gfs2_lookup_simple(master, "per_node"); if (IS_ERR(pn)) { error = PTR_ERR(pn); fs_err(sdp, "can't find per_node directory: %d\n", error); @@ -800,7 +1083,11 @@ static int fill_super(struct super_block *sb, void *data, int silent) goto fail; } - init_vfs(sb, SDF_NOATIME); + sb->s_magic = GFS2_MAGIC; + sb->s_op = &gfs2_super_ops; + sb->s_export_op = &gfs2_export_ops; + sb->s_time_gran = 1; + sb->s_maxbytes = MAX_LFS_FILESIZE; /* Set up the buffer cache and fill in some fake block size values to allow us to read-in the on-disk superblock. */ @@ -828,7 +1115,7 @@ static int fill_super(struct super_block *sb, void *data, int silent) if (error) goto fail_lm; - error = init_sb(sdp, silent, DO); + error = init_sb(sdp, silent); if (error) goto fail_locking; @@ -869,7 +1156,11 @@ fail_per_node: fail_inodes: init_inodes(sdp, UNDO); fail_sb: - init_sb(sdp, 0, UNDO); + if (sdp->sd_root_dir) + dput(sdp->sd_root_dir); + if (sdp->sd_master_dir) + dput(sdp->sd_master_dir); + sb->s_root = NULL; fail_locking: init_locking(sdp, &mount_gh, UNDO); fail_lm: @@ -887,151 +1178,63 @@ fail: } static int gfs2_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data, struct vfsmount *mnt) + const char *dev_name, void *data, struct vfsmount *mnt) { - struct super_block *sb; - struct gfs2_sbd *sdp; - int error = get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); - if (error) - goto out; - sb = mnt->mnt_sb; - sdp = sb->s_fs_info; - sdp->sd_gfs2mnt = mnt; -out: - return error; + return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); } -static int fill_super_meta(struct super_block *sb, struct super_block *new, - void *data, int silent) +static struct super_block *get_gfs2_sb(const char *dev_name) { - struct gfs2_sbd *sdp = sb->s_fs_info; - struct inode *inode; - int error = 0; - - new->s_fs_info = sdp; - sdp->sd_vfs_meta = sb; - - init_vfs(new, SDF_NOATIME); - - /* Get the master inode */ - inode = igrab(sdp->sd_master_dir); - - new->s_root = d_alloc_root(inode); - if (!new->s_root) { - fs_err(sdp, "can't get root dentry\n"); - error = -ENOMEM; - iput(inode); - } else - new->s_root->d_op = &gfs2_dops; - - return error; -} - -static int set_bdev_super(struct super_block *s, void *data) -{ - s->s_bdev = data; - s->s_dev = s->s_bdev->bd_dev; - return 0; -} - -static int test_bdev_super(struct super_block *s, void *data) -{ - return s->s_bdev == data; -} - -static struct super_block* get_gfs2_sb(const char *dev_name) -{ - struct kstat stat; + struct super_block *sb; struct nameidata nd; - struct super_block *sb = NULL, *s; int error; error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); if (error) { - printk(KERN_WARNING "GFS2: path_lookup on %s returned error\n", - dev_name); - goto out; - } - error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat); - - list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) { - if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || - (S_ISDIR(stat.mode) && - s == nd.path.dentry->d_inode->i_sb)) { - sb = s; - goto free_nd; - } + printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", + dev_name, error); + return NULL; } - - printk(KERN_WARNING "GFS2: Unrecognized block device or " - "mount point %s\n", dev_name); - -free_nd: + sb = nd.path.dentry->d_inode->i_sb; + if (sb && (sb->s_type == &gfs2_fs_type)) + atomic_inc(&sb->s_active); + else + sb = NULL; path_put(&nd.path); -out: return sb; } static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - int error = 0; - struct super_block *sb = NULL, *new; + struct super_block *sb = NULL; struct gfs2_sbd *sdp; sb = get_gfs2_sb(dev_name); if (!sb) { printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); - error = -ENOENT; - goto error; + return -ENOENT; } sdp = sb->s_fs_info; - if (sdp->sd_vfs_meta) { - printk(KERN_WARNING "GFS2: gfs2meta mount already exists\n"); - error = -EBUSY; - goto error; - } - down(&sb->s_bdev->bd_mount_sem); - new = sget(fs_type, test_bdev_super, set_bdev_super, sb->s_bdev); - up(&sb->s_bdev->bd_mount_sem); - if (IS_ERR(new)) { - error = PTR_ERR(new); - goto error; - } - new->s_flags = flags; - strlcpy(new->s_id, sb->s_id, sizeof(new->s_id)); - sb_set_blocksize(new, sb->s_blocksize); - error = fill_super_meta(sb, new, data, flags & MS_SILENT ? 1 : 0); - if (error) { - up_write(&new->s_umount); - deactivate_super(new); - goto error; - } - - new->s_flags |= MS_ACTIVE; - - /* Grab a reference to the gfs2 mount point */ - atomic_inc(&sdp->sd_gfs2mnt->mnt_count); - return simple_set_mnt(mnt, new); -error: - return error; + mnt->mnt_sb = sb; + mnt->mnt_root = dget(sdp->sd_master_dir); + return 0; } static void gfs2_kill_sb(struct super_block *sb) { - if (sb->s_fs_info) { - gfs2_delete_debugfs_file(sb->s_fs_info); - gfs2_meta_syncfs(sb->s_fs_info); + struct gfs2_sbd *sdp = sb->s_fs_info; + if (sdp) { + gfs2_meta_syncfs(sdp); + dput(sdp->sd_root_dir); + dput(sdp->sd_master_dir); + sdp->sd_root_dir = NULL; + sdp->sd_master_dir = NULL; } + shrink_dcache_sb(sb); kill_block_super(sb); -} - -static void gfs2_kill_sb_meta(struct super_block *sb) -{ - struct gfs2_sbd *sdp = sb->s_fs_info; - generic_shutdown_super(sb); - sdp->sd_vfs_meta = NULL; - atomic_dec(&sdp->sd_gfs2mnt->mnt_count); + if (sdp) + gfs2_delete_debugfs_file(sdp); } struct file_system_type gfs2_fs_type = { @@ -1046,7 +1249,6 @@ struct file_system_type gfs2meta_fs_type = { .name = "gfs2meta", .fs_flags = FS_REQUIRES_DEV, .get_sb = gfs2_get_sb_meta, - .kill_sb = gfs2_kill_sb_meta, .owner = THIS_MODULE, }; diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index e2c62f73a778..534e1e2c65ca 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c @@ -159,9 +159,13 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); - error = gfs2_glock_nq_m(2, ghs); + error = gfs2_glock_nq(ghs); /* parent */ if (error) - goto out; + goto out_parent; + + error = gfs2_glock_nq(ghs + 1); /* child */ + if (error) + goto out_child; error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC); if (error) @@ -245,8 +249,10 @@ out_alloc: if (alloc_required) gfs2_alloc_put(dip); out_gunlock: - gfs2_glock_dq_m(2, ghs); -out: + gfs2_glock_dq(ghs + 1); +out_child: + gfs2_glock_dq(ghs); +out_parent: gfs2_holder_uninit(ghs); gfs2_holder_uninit(ghs + 1); if (!error) { @@ -302,7 +308,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) error = gfs2_unlink_ok(dip, &dentry->d_name, ip); if (error) - goto out_rgrp; + goto out_gunlock; error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0); if (error) @@ -316,6 +322,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) out_end_trans: gfs2_trans_end(sdp); +out_gunlock: gfs2_glock_dq(ghs + 2); out_rgrp: gfs2_holder_uninit(ghs + 2); @@ -485,7 +492,6 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) struct gfs2_holder ri_gh; int error; - error = gfs2_rindex_hold(sdp, &ri_gh); if (error) return error; @@ -495,9 +501,17 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); - error = gfs2_glock_nq_m(3, ghs); + error = gfs2_glock_nq(ghs); /* parent */ if (error) - goto out; + goto out_parent; + + error = gfs2_glock_nq(ghs + 1); /* child */ + if (error) + goto out_child; + + error = gfs2_glock_nq(ghs + 2); /* rgrp */ + if (error) + goto out_rgrp; error = gfs2_unlink_ok(dip, &dentry->d_name, ip); if (error) @@ -523,11 +537,15 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) gfs2_trans_end(sdp); out_gunlock: - gfs2_glock_dq_m(3, ghs); -out: - gfs2_holder_uninit(ghs); - gfs2_holder_uninit(ghs + 1); + gfs2_glock_dq(ghs + 2); +out_rgrp: gfs2_holder_uninit(ghs + 2); + gfs2_glock_dq(ghs + 1); +out_child: + gfs2_holder_uninit(ghs + 1); + gfs2_glock_dq(ghs); +out_parent: + gfs2_holder_uninit(ghs); gfs2_glock_dq_uninit(&ri_gh); return error; } @@ -571,6 +589,54 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode, return 0; } +/* + * gfs2_ok_to_move - check if it's ok to move a directory to another directory + * @this: move this + * @to: to here + * + * Follow @to back to the root and make sure we don't encounter @this + * Assumes we already hold the rename lock. + * + * Returns: errno + */ + +static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) +{ + struct inode *dir = &to->i_inode; + struct super_block *sb = dir->i_sb; + struct inode *tmp; + struct qstr dotdot; + int error = 0; + + gfs2_str2qstr(&dotdot, ".."); + + igrab(dir); + + for (;;) { + if (dir == &this->i_inode) { + error = -EINVAL; + break; + } + if (dir == sb->s_root->d_inode) { + error = 0; + break; + } + + tmp = gfs2_lookupi(dir, &dotdot, 1); + if (IS_ERR(tmp)) { + error = PTR_ERR(tmp); + break; + } + + iput(dir); + dir = tmp; + } + + iput(dir); + + return error; +} + /** * gfs2_rename - Rename a file * @odir: Parent directory of old file name @@ -589,7 +655,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, struct gfs2_inode *ip = GFS2_I(odentry->d_inode); struct gfs2_inode *nip = NULL; struct gfs2_sbd *sdp = GFS2_SB(odir); - struct gfs2_holder ghs[5], r_gh; + struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }; struct gfs2_rgrpd *nrgd; unsigned int num_gh; int dir_rename = 0; @@ -603,19 +669,20 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, return 0; } - /* Make sure we aren't trying to move a dirctory into it's subdir */ - - if (S_ISDIR(ip->i_inode.i_mode) && odip != ndip) { - dir_rename = 1; - error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0, - &r_gh); + if (odip != ndip) { + error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, + 0, &r_gh); if (error) goto out; - error = gfs2_ok_to_move(ip, ndip); - if (error) - goto out_gunlock_r; + if (S_ISDIR(ip->i_inode.i_mode)) { + dir_rename = 1; + /* don't move a dirctory into it's subdir */ + error = gfs2_ok_to_move(ip, ndip); + if (error) + goto out_gunlock_r; + } } num_gh = 1; @@ -639,9 +706,11 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); } - error = gfs2_glock_nq_m(num_gh, ghs); - if (error) - goto out_uninit; + for (x = 0; x < num_gh; x++) { + error = gfs2_glock_nq(ghs + x); + if (error) + goto out_gunlock; + } /* Check out the old directory */ @@ -804,12 +873,12 @@ out_alloc: if (alloc_required) gfs2_alloc_put(ndip); out_gunlock: - gfs2_glock_dq_m(num_gh, ghs); -out_uninit: - for (x = 0; x < num_gh; x++) + while (x--) { + gfs2_glock_dq(ghs + x); gfs2_holder_uninit(ghs + x); + } out_gunlock_r: - if (dir_rename) + if (r_gh.gh_gl) gfs2_glock_dq_uninit(&r_gh); out: return error; diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index f66ea0f7a356..d5355d9b5926 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c @@ -20,6 +20,7 @@ #include <linux/gfs2_ondisk.h> #include <linux/crc32.h> #include <linux/lm_interface.h> +#include <linux/time.h> #include "gfs2.h" #include "incore.h" @@ -38,6 +39,7 @@ #include "dir.h" #include "eattr.h" #include "bmap.h" +#include "meta_io.h" /** * gfs2_write_inode - Make sure the inode is stable on the disk @@ -50,16 +52,74 @@ static int gfs2_write_inode(struct inode *inode, int sync) { struct gfs2_inode *ip = GFS2_I(inode); - - /* Check this is a "normal" inode */ - if (test_bit(GIF_USER, &ip->i_flags)) { - if (current->flags & PF_MEMALLOC) - return 0; - if (sync) - gfs2_log_flush(GFS2_SB(inode), ip->i_gl); + struct gfs2_sbd *sdp = GFS2_SB(inode); + struct gfs2_holder gh; + struct buffer_head *bh; + struct timespec atime; + struct gfs2_dinode *di; + int ret = 0; + + /* Check this is a "normal" inode, etc */ + if (!test_bit(GIF_USER, &ip->i_flags) || + (current->flags & PF_MEMALLOC)) + return 0; + ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (ret) + goto do_flush; + ret = gfs2_trans_begin(sdp, RES_DINODE, 0); + if (ret) + goto do_unlock; + ret = gfs2_meta_inode_buffer(ip, &bh); + if (ret == 0) { + di = (struct gfs2_dinode *)bh->b_data; + atime.tv_sec = be64_to_cpu(di->di_atime); + atime.tv_nsec = be32_to_cpu(di->di_atime_nsec); + if (timespec_compare(&inode->i_atime, &atime) > 0) { + gfs2_trans_add_bh(ip->i_gl, bh, 1); + gfs2_dinode_out(ip, bh->b_data); + } + brelse(bh); } + gfs2_trans_end(sdp); +do_unlock: + gfs2_glock_dq_uninit(&gh); +do_flush: + if (sync != 0) + gfs2_log_flush(GFS2_SB(inode), ip->i_gl); + return ret; +} - return 0; +/** + * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one + * @sdp: the filesystem + * + * Returns: errno + */ + +static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) +{ + struct gfs2_holder t_gh; + int error; + + gfs2_quota_sync(sdp); + gfs2_statfs_sync(sdp); + + error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, + &t_gh); + if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + return error; + + gfs2_meta_syncfs(sdp); + gfs2_log_shutdown(sdp); + + clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); + + if (t_gh.gh_gl) + gfs2_glock_dq_uninit(&t_gh); + + gfs2_quota_cleanup(sdp); + + return error; } /** @@ -73,12 +133,6 @@ static void gfs2_put_super(struct super_block *sb) struct gfs2_sbd *sdp = sb->s_fs_info; int error; - if (!sdp) - return; - - if (!strncmp(sb->s_type->name, "gfs2meta", 8)) - return; /* Nothing to do */ - /* Unfreeze the filesystem, if we need to */ mutex_lock(&sdp->sd_freeze_lock); @@ -101,7 +155,6 @@ static void gfs2_put_super(struct super_block *sb) /* Release stuff */ - iput(sdp->sd_master_dir); iput(sdp->sd_jindex); iput(sdp->sd_inum_inode); iput(sdp->sd_statfs_inode); @@ -152,6 +205,7 @@ static void gfs2_write_super(struct super_block *sb) * * Flushes the log to disk. */ + static int gfs2_sync_fs(struct super_block *sb, int wait) { sb->s_dirt = 0; @@ -270,14 +324,6 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) } } - if (*flags & (MS_NOATIME | MS_NODIRATIME)) - set_bit(SDF_NOATIME, &sdp->sd_flags); - else - clear_bit(SDF_NOATIME, &sdp->sd_flags); - - /* Don't let the VFS update atimes. GFS2 handles this itself. */ - *flags |= MS_NOATIME | MS_NODIRATIME; - return error; } @@ -295,6 +341,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) * inode's blocks, or alternatively pass the baton on to another * node for later deallocation. */ + static void gfs2_drop_inode(struct inode *inode) { struct gfs2_inode *ip = GFS2_I(inode); @@ -333,6 +380,16 @@ static void gfs2_clear_inode(struct inode *inode) } } +static int is_ancestor(const struct dentry *d1, const struct dentry *d2) +{ + do { + if (d1 == d2) + return 1; + d1 = d1->d_parent; + } while (!IS_ROOT(d1)); + return 0; +} + /** * gfs2_show_options - Show mount options for /proc/mounts * @s: seq_file structure @@ -346,6 +403,8 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info; struct gfs2_args *args = &sdp->sd_args; + if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir)) + seq_printf(s, ",meta"); if (args->ar_lockproto[0]) seq_printf(s, ",lockproto=%s", args->ar_lockproto); if (args->ar_locktable[0]) @@ -414,6 +473,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) * conversion on the iopen lock, but we can change that later. This * is safe, just less efficient. */ + static void gfs2_delete_inode(struct inode *inode) { struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; @@ -478,8 +538,6 @@ out: clear_inode(inode); } - - static struct inode *gfs2_alloc_inode(struct super_block *sb) { struct gfs2_inode *ip; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index ca831991cbc2..c3ba3d9d0aac 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -33,313 +33,6 @@ #include "trans.h" #include "util.h" -static const u32 gfs2_old_fs_formats[] = { - 0 -}; - -static const u32 gfs2_old_multihost_formats[] = { - 0 -}; - -/** - * gfs2_tune_init - Fill a gfs2_tune structure with default values - * @gt: tune - * - */ - -void gfs2_tune_init(struct gfs2_tune *gt) -{ - spin_lock_init(>->gt_spin); - - gt->gt_demote_secs = 300; - gt->gt_incore_log_blocks = 1024; - gt->gt_log_flush_secs = 60; - gt->gt_recoverd_secs = 60; - gt->gt_logd_secs = 1; - gt->gt_quotad_secs = 5; - gt->gt_quota_simul_sync = 64; - gt->gt_quota_warn_period = 10; - gt->gt_quota_scale_num = 1; - gt->gt_quota_scale_den = 1; - gt->gt_quota_cache_secs = 300; - gt->gt_quota_quantum = 60; - gt->gt_atime_quantum = 3600; - gt->gt_new_files_jdata = 0; - gt->gt_max_readahead = 1 << 18; - gt->gt_stall_secs = 600; - gt->gt_complain_secs = 10; - gt->gt_statfs_quantum = 30; - gt->gt_statfs_slow = 0; -} - -/** - * gfs2_check_sb - Check superblock - * @sdp: the filesystem - * @sb: The superblock - * @silent: Don't print a message if the check fails - * - * Checks the version code of the FS is one that we understand how to - * read and that the sizes of the various on-disk structures have not - * changed. - */ - -int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) -{ - unsigned int x; - - if (sb->sb_magic != GFS2_MAGIC || - sb->sb_type != GFS2_METATYPE_SB) { - if (!silent) - printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); - return -EINVAL; - } - - /* If format numbers match exactly, we're done. */ - - if (sb->sb_fs_format == GFS2_FORMAT_FS && - sb->sb_multihost_format == GFS2_FORMAT_MULTI) - return 0; - - if (sb->sb_fs_format != GFS2_FORMAT_FS) { - for (x = 0; gfs2_old_fs_formats[x]; x++) - if (gfs2_old_fs_formats[x] == sb->sb_fs_format) - break; - - if (!gfs2_old_fs_formats[x]) { - printk(KERN_WARNING - "GFS2: code version (%u, %u) is incompatible " - "with ondisk format (%u, %u)\n", - GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, - sb->sb_fs_format, sb->sb_multihost_format); - printk(KERN_WARNING - "GFS2: I don't know how to upgrade this FS\n"); - return -EINVAL; - } - } - - if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) { - for (x = 0; gfs2_old_multihost_formats[x]; x++) - if (gfs2_old_multihost_formats[x] == - sb->sb_multihost_format) - break; - - if (!gfs2_old_multihost_formats[x]) { - printk(KERN_WARNING - "GFS2: code version (%u, %u) is incompatible " - "with ondisk format (%u, %u)\n", - GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, - sb->sb_fs_format, sb->sb_multihost_format); - printk(KERN_WARNING - "GFS2: I don't know how to upgrade this FS\n"); - return -EINVAL; - } - } - - if (!sdp->sd_args.ar_upgrade) { - printk(KERN_WARNING - "GFS2: code version (%u, %u) is incompatible " - "with ondisk format (%u, %u)\n", - GFS2_FORMAT_FS, GFS2_FORMAT_MULTI, - sb->sb_fs_format, sb->sb_multihost_format); - printk(KERN_INFO - "GFS2: Use the \"upgrade\" mount option to upgrade " - "the FS\n"); - printk(KERN_INFO "GFS2: See the manual for more details\n"); - return -EINVAL; - } - - return 0; -} - - -static void end_bio_io_page(struct bio *bio, int error) -{ - struct page *page = bio->bi_private; - - if (!error) - SetPageUptodate(page); - else - printk(KERN_WARNING "gfs2: error %d reading superblock\n", error); - unlock_page(page); -} - -static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) -{ - const struct gfs2_sb *str = buf; - - sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); - sb->sb_type = be32_to_cpu(str->sb_header.mh_type); - sb->sb_format = be32_to_cpu(str->sb_header.mh_format); - sb->sb_fs_format = be32_to_cpu(str->sb_fs_format); - sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format); - sb->sb_bsize = be32_to_cpu(str->sb_bsize); - sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift); - sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr); - sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino); - sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr); - sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino); - - memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); - memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); -} - -/** - * gfs2_read_super - Read the gfs2 super block from disk - * @sdp: The GFS2 super block - * @sector: The location of the super block - * @error: The error code to return - * - * This uses the bio functions to read the super block from disk - * because we want to be 100% sure that we never read cached data. - * A super block is read twice only during each GFS2 mount and is - * never written to by the filesystem. The first time its read no - * locks are held, and the only details which are looked at are those - * relating to the locking protocol. Once locking is up and working, - * the sb is read again under the lock to establish the location of - * the master directory (contains pointers to journals etc) and the - * root directory. - * - * Returns: 0 on success or error - */ - -int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) -{ - struct super_block *sb = sdp->sd_vfs; - struct gfs2_sb *p; - struct page *page; - struct bio *bio; - - page = alloc_page(GFP_NOFS); - if (unlikely(!page)) - return -ENOBUFS; - - ClearPageUptodate(page); - ClearPageDirty(page); - lock_page(page); - - bio = bio_alloc(GFP_NOFS, 1); - if (unlikely(!bio)) { - __free_page(page); - return -ENOBUFS; - } - - bio->bi_sector = sector * (sb->s_blocksize >> 9); - bio->bi_bdev = sb->s_bdev; - bio_add_page(bio, page, PAGE_SIZE, 0); - - bio->bi_end_io = end_bio_io_page; - bio->bi_private = page; - submit_bio(READ_SYNC | (1 << BIO_RW_META), bio); - wait_on_page_locked(page); - bio_put(bio); - if (!PageUptodate(page)) { - __free_page(page); - return -EIO; - } - p = kmap(page); - gfs2_sb_in(&sdp->sd_sb, p); - kunmap(page); - __free_page(page); - return 0; -} - -/** - * gfs2_read_sb - Read super block - * @sdp: The GFS2 superblock - * @gl: the glock for the superblock (assumed to be held) - * @silent: Don't print message if mount fails - * - */ - -int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) -{ - u32 hash_blocks, ind_blocks, leaf_blocks; - u32 tmp_blocks; - unsigned int x; - int error; - - error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); - if (error) { - if (!silent) - fs_err(sdp, "can't read superblock\n"); - return error; - } - - error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); - if (error) - return error; - - sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - - GFS2_BASIC_BLOCK_SHIFT; - sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; - sdp->sd_diptrs = (sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_dinode)) / sizeof(u64); - sdp->sd_inptrs = (sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_meta_header)) / sizeof(u64); - sdp->sd_jbsize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header); - sdp->sd_hash_bsize = sdp->sd_sb.sb_bsize / 2; - sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1; - sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(u64); - sdp->sd_qc_per_block = (sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_meta_header)) / - sizeof(struct gfs2_quota_change); - - /* Compute maximum reservation required to add a entry to a directory */ - - hash_blocks = DIV_ROUND_UP(sizeof(u64) * (1 << GFS2_DIR_MAX_DEPTH), - sdp->sd_jbsize); - - ind_blocks = 0; - for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) { - tmp_blocks = DIV_ROUND_UP(tmp_blocks, sdp->sd_inptrs); - ind_blocks += tmp_blocks; - } - - leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH; - - sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks; - - sdp->sd_heightsize[0] = sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_dinode); - sdp->sd_heightsize[1] = sdp->sd_sb.sb_bsize * sdp->sd_diptrs; - for (x = 2;; x++) { - u64 space, d; - u32 m; - - space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs; - d = space; - m = do_div(d, sdp->sd_inptrs); - - if (d != sdp->sd_heightsize[x - 1] || m) - break; - sdp->sd_heightsize[x] = space; - } - sdp->sd_max_height = x; - sdp->sd_heightsize[x] = ~0; - gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); - - sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_dinode); - sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs; - for (x = 2;; x++) { - u64 space, d; - u32 m; - - space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs; - d = space; - m = do_div(d, sdp->sd_inptrs); - - if (d != sdp->sd_jheightsize[x - 1] || m) - break; - sdp->sd_jheightsize[x] = space; - } - sdp->sd_max_jheight = x; - sdp->sd_jheightsize[x] = ~0; - gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); - - return 0; -} - /** * gfs2_jindex_hold - Grab a lock on the jindex * @sdp: The GFS2 superblock @@ -581,39 +274,6 @@ fail: return error; } -/** - * gfs2_make_fs_ro - Turn a Read-Write FS into a Read-Only one - * @sdp: the filesystem - * - * Returns: errno - */ - -int gfs2_make_fs_ro(struct gfs2_sbd *sdp) -{ - struct gfs2_holder t_gh; - int error; - - gfs2_quota_sync(sdp); - gfs2_statfs_sync(sdp); - - error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, - &t_gh); - if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) - return error; - - gfs2_meta_syncfs(sdp); - gfs2_log_shutdown(sdp); - - clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); - - if (t_gh.gh_gl) - gfs2_glock_dq_uninit(&t_gh); - - gfs2_quota_cleanup(sdp); - - return error; -} - static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) { const struct gfs2_statfs_change *str = buf; diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 44361ecc44f7..50a4c9b1215e 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h @@ -12,11 +12,6 @@ #include "incore.h" -void gfs2_tune_init(struct gfs2_tune *gt); - -int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); -int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); -int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector); void gfs2_lm_unmount(struct gfs2_sbd *sdp); static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) @@ -40,7 +35,6 @@ int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename, struct gfs2_inode **ipp); int gfs2_make_fs_rw(struct gfs2_sbd *sdp); -int gfs2_make_fs_ro(struct gfs2_sbd *sdp); int gfs2_statfs_init(struct gfs2_sbd *sdp); void gfs2_statfs_change(struct gfs2_sbd *sdp, diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 74846559fc3f..7e1879f1a02c 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -269,14 +269,6 @@ ARGS_ATTR(quota, "%u\n"); ARGS_ATTR(suiddir, "%d\n"); ARGS_ATTR(data, "%d\n"); -/* one oddball doesn't fit the macro mold */ -static ssize_t noatime_show(struct gfs2_sbd *sdp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - !!test_bit(SDF_NOATIME, &sdp->sd_flags)); -} -static struct args_attr args_attr_noatime = __ATTR_RO(noatime); - static struct attribute *args_attrs[] = { &args_attr_lockproto.attr, &args_attr_locktable.attr, @@ -292,7 +284,6 @@ static struct attribute *args_attrs[] = { &args_attr_quota.attr, &args_attr_suiddir.attr, &args_attr_data.attr, - &args_attr_noatime.attr, NULL, }; @@ -407,7 +398,6 @@ TUNE_ATTR(incore_log_blocks, 0); TUNE_ATTR(log_flush_secs, 0); TUNE_ATTR(quota_warn_period, 0); TUNE_ATTR(quota_quantum, 0); -TUNE_ATTR(atime_quantum, 0); TUNE_ATTR(max_readahead, 0); TUNE_ATTR(complain_secs, 0); TUNE_ATTR(statfs_slow, 0); @@ -427,7 +417,6 @@ static struct attribute *tune_attrs[] = { &tune_attr_log_flush_secs.attr, &tune_attr_quota_warn_period.attr, &tune_attr_quota_quantum.attr, - &tune_attr_atime_quantum.attr, &tune_attr_max_readahead.attr, &tune_attr_complain_secs.attr, &tune_attr_statfs_slow.attr, diff --git a/fs/partitions/check.c b/fs/partitions/check.c index ecc3330972e5..7408227c49c9 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -120,22 +120,21 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = * a pointer to that same buffer (for convenience). */ -char *disk_name(struct gendisk *hd, int part, char *buf) +char *disk_name(struct gendisk *hd, int partno, char *buf) { - if (!part) + if (!partno) snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name); else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) - snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, part); + snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, partno); else - snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, part); + snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, partno); return buf; } const char *bdevname(struct block_device *bdev, char *buf) { - int part = MINOR(bdev->bd_dev) - bdev->bd_disk->first_minor; - return disk_name(bdev->bd_disk, part, buf); + return disk_name(bdev->bd_disk, bdev->bd_part->partno, buf); } EXPORT_SYMBOL(bdevname); @@ -169,7 +168,7 @@ check_partition(struct gendisk *hd, struct block_device *bdev) if (isdigit(state->name[strlen(state->name)-1])) sprintf(state->name, "p"); - state->limit = hd->minors; + state->limit = disk_max_parts(hd); i = res = err = 0; while (!res && check_part[i]) { memset(&state->parts, 0, sizeof(state->parts)); @@ -204,21 +203,22 @@ static ssize_t part_start_show(struct device *dev, return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect); } -static ssize_t part_size_show(struct device *dev, - struct device_attribute *attr, char *buf) +ssize_t part_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); } -static ssize_t part_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) +ssize_t part_stat_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); + int cpu; - preempt_disable(); - part_round_stats(p); - preempt_enable(); + cpu = part_stat_lock(); + part_round_stats(cpu, p); + part_stat_unlock(); return sprintf(buf, "%8lu %8lu %8llu %8u " "%8lu %8lu %8llu %8u " @@ -238,17 +238,17 @@ static ssize_t part_stat_show(struct device *dev, } #ifdef CONFIG_FAIL_MAKE_REQUEST -static ssize_t part_fail_show(struct device *dev, - struct device_attribute *attr, char *buf) +ssize_t part_fail_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct hd_struct *p = dev_to_part(dev); return sprintf(buf, "%d\n", p->make_it_fail); } -static ssize_t part_fail_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +ssize_t part_fail_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct hd_struct *p = dev_to_part(dev); int i; @@ -300,40 +300,34 @@ struct device_type part_type = { .release = part_release, }; -static inline void partition_sysfs_add_subdir(struct hd_struct *p) -{ - struct kobject *k; - - k = kobject_get(&p->dev.kobj); - p->holder_dir = kobject_create_and_add("holders", k); - kobject_put(k); -} - -static inline void disk_sysfs_add_subdirs(struct gendisk *disk) +static void delete_partition_rcu_cb(struct rcu_head *head) { - struct kobject *k; + struct hd_struct *part = container_of(head, struct hd_struct, rcu_head); - k = kobject_get(&disk->dev.kobj); - disk->holder_dir = kobject_create_and_add("holders", k); - disk->slave_dir = kobject_create_and_add("slaves", k); - kobject_put(k); + part->start_sect = 0; + part->nr_sects = 0; + part_stat_set_all(part, 0); + put_device(part_to_dev(part)); } -void delete_partition(struct gendisk *disk, int part) +void delete_partition(struct gendisk *disk, int partno) { - struct hd_struct *p = disk->part[part-1]; + struct disk_part_tbl *ptbl = disk->part_tbl; + struct hd_struct *part; - if (!p) + if (partno >= ptbl->len) return; - if (!p->nr_sects) + + part = ptbl->part[partno]; + if (!part) return; - disk->part[part-1] = NULL; - p->start_sect = 0; - p->nr_sects = 0; - part_stat_set_all(p, 0); - kobject_put(p->holder_dir); - device_del(&p->dev); - put_device(&p->dev); + + blk_free_devt(part_devt(part)); + rcu_assign_pointer(ptbl->part[partno], NULL); + kobject_put(part->holder_dir); + device_del(part_to_dev(part)); + + call_rcu(&part->rcu_head, delete_partition_rcu_cb); } static ssize_t whole_disk_show(struct device *dev, @@ -344,102 +338,132 @@ static ssize_t whole_disk_show(struct device *dev, static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, whole_disk_show, NULL); -int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) +int add_partition(struct gendisk *disk, int partno, + sector_t start, sector_t len, int flags) { struct hd_struct *p; + dev_t devt = MKDEV(0, 0); + struct device *ddev = disk_to_dev(disk); + struct device *pdev; + struct disk_part_tbl *ptbl; + const char *dname; int err; + err = disk_expand_part_tbl(disk, partno); + if (err) + return err; + ptbl = disk->part_tbl; + + if (ptbl->part[partno]) + return -EBUSY; + p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; if (!init_part_stats(p)) { err = -ENOMEM; - goto out0; + goto out_free; } + pdev = part_to_dev(p); + p->start_sect = start; p->nr_sects = len; - p->partno = part; - p->policy = disk->policy; + p->partno = partno; + p->policy = get_disk_ro(disk); - if (isdigit(disk->dev.bus_id[strlen(disk->dev.bus_id)-1])) - snprintf(p->dev.bus_id, BUS_ID_SIZE, - "%sp%d", disk->dev.bus_id, part); + dname = dev_name(ddev); + if (isdigit(dname[strlen(dname) - 1])) + snprintf(pdev->bus_id, BUS_ID_SIZE, "%sp%d", dname, partno); else - snprintf(p->dev.bus_id, BUS_ID_SIZE, - "%s%d", disk->dev.bus_id, part); + snprintf(pdev->bus_id, BUS_ID_SIZE, "%s%d", dname, partno); - device_initialize(&p->dev); - p->dev.devt = MKDEV(disk->major, disk->first_minor + part); - p->dev.class = &block_class; - p->dev.type = &part_type; - p->dev.parent = &disk->dev; - disk->part[part-1] = p; + device_initialize(pdev); + pdev->class = &block_class; + pdev->type = &part_type; + pdev->parent = ddev; + + err = blk_alloc_devt(p, &devt); + if (err) + goto out_free; + pdev->devt = devt; /* delay uevent until 'holders' subdir is created */ - p->dev.uevent_suppress = 1; - err = device_add(&p->dev); + pdev->uevent_suppress = 1; + err = device_add(pdev); if (err) - goto out1; - partition_sysfs_add_subdir(p); - p->dev.uevent_suppress = 0; + goto out_put; + + err = -ENOMEM; + p->holder_dir = kobject_create_and_add("holders", &pdev->kobj); + if (!p->holder_dir) + goto out_del; + + pdev->uevent_suppress = 0; if (flags & ADDPART_FLAG_WHOLEDISK) { - err = device_create_file(&p->dev, &dev_attr_whole_disk); + err = device_create_file(pdev, &dev_attr_whole_disk); if (err) - goto out2; + goto out_del; } + /* everything is up and running, commence */ + INIT_RCU_HEAD(&p->rcu_head); + rcu_assign_pointer(ptbl->part[partno], p); + /* suppress uevent if the disk supresses it */ - if (!disk->dev.uevent_suppress) - kobject_uevent(&p->dev.kobj, KOBJ_ADD); + if (!ddev->uevent_suppress) + kobject_uevent(&pdev->kobj, KOBJ_ADD); return 0; -out2: - device_del(&p->dev); -out1: - put_device(&p->dev); - free_part_stats(p); -out0: +out_free: kfree(p); return err; +out_del: + kobject_put(p->holder_dir); + device_del(pdev); +out_put: + put_device(pdev); + blk_free_devt(devt); + return err; } /* Not exported, helper to add_disk(). */ void register_disk(struct gendisk *disk) { + struct device *ddev = disk_to_dev(disk); struct block_device *bdev; + struct disk_part_iter piter; + struct hd_struct *part; char *s; - int i; - struct hd_struct *p; int err; - disk->dev.parent = disk->driverfs_dev; - disk->dev.devt = MKDEV(disk->major, disk->first_minor); + ddev->parent = disk->driverfs_dev; - strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE); + strlcpy(ddev->bus_id, disk->disk_name, BUS_ID_SIZE); /* ewww... some of these buggers have / in the name... */ - s = strchr(disk->dev.bus_id, '/'); + s = strchr(ddev->bus_id, '/'); if (s) *s = '!'; /* delay uevents, until we scanned partition table */ - disk->dev.uevent_suppress = 1; + ddev->uevent_suppress = 1; - if (device_add(&disk->dev)) + if (device_add(ddev)) return; #ifndef CONFIG_SYSFS_DEPRECATED - err = sysfs_create_link(block_depr, &disk->dev.kobj, - kobject_name(&disk->dev.kobj)); + err = sysfs_create_link(block_depr, &ddev->kobj, + kobject_name(&ddev->kobj)); if (err) { - device_del(&disk->dev); + device_del(ddev); return; } #endif - disk_sysfs_add_subdirs(disk); + disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); + disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); /* No minors to use for partitions */ - if (disk->minors == 1) + if (!disk_partitionable(disk)) goto exit; /* No such device (e.g., media were just removed) */ @@ -458,41 +482,57 @@ void register_disk(struct gendisk *disk) exit: /* announce disk after possible partitions are created */ - disk->dev.uevent_suppress = 0; - kobject_uevent(&disk->dev.kobj, KOBJ_ADD); + ddev->uevent_suppress = 0; + kobject_uevent(&ddev->kobj, KOBJ_ADD); /* announce possible partitions */ - for (i = 1; i < disk->minors; i++) { - p = disk->part[i-1]; - if (!p || !p->nr_sects) - continue; - kobject_uevent(&p->dev.kobj, KOBJ_ADD); - } + disk_part_iter_init(&piter, disk, 0); + while ((part = disk_part_iter_next(&piter))) + kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD); + disk_part_iter_exit(&piter); } int rescan_partitions(struct gendisk *disk, struct block_device *bdev) { + struct disk_part_iter piter; + struct hd_struct *part; struct parsed_partitions *state; - int p, res; + int p, highest, res; if (bdev->bd_part_count) return -EBUSY; res = invalidate_partition(disk, 0); if (res) return res; - bdev->bd_invalidated = 0; - for (p = 1; p < disk->minors; p++) - delete_partition(disk, p); + + disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY); + while ((part = disk_part_iter_next(&piter))) + delete_partition(disk, part->partno); + disk_part_iter_exit(&piter); + if (disk->fops->revalidate_disk) disk->fops->revalidate_disk(disk); + check_disk_size_change(disk, bdev); + bdev->bd_invalidated = 0; if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) return 0; if (IS_ERR(state)) /* I/O error reading the partition table */ return -EIO; /* tell userspace that the media / partition table may have changed */ - kobject_uevent(&disk->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); + /* Detect the highest partition number and preallocate + * disk->part_tbl. This is an optimization and not strictly + * necessary. + */ + for (p = 1, highest = 0; p < state->limit; p++) + if (state->parts[p].size) + highest = p; + + disk_expand_part_tbl(disk, highest); + + /* add partitions */ for (p = 1; p < state->limit; p++) { sector_t size = state->parts[p].size; sector_t from = state->parts[p].from; @@ -541,25 +581,31 @@ EXPORT_SYMBOL(read_dev_sector); void del_gendisk(struct gendisk *disk) { - int p; + struct disk_part_iter piter; + struct hd_struct *part; /* invalidate stuff */ - for (p = disk->minors - 1; p > 0; p--) { - invalidate_partition(disk, p); - delete_partition(disk, p); + disk_part_iter_init(&piter, disk, + DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE); + while ((part = disk_part_iter_next(&piter))) { + invalidate_partition(disk, part->partno); + delete_partition(disk, part->partno); } + disk_part_iter_exit(&piter); + invalidate_partition(disk, 0); - disk->capacity = 0; + blk_free_devt(disk_to_dev(disk)->devt); + set_capacity(disk, 0); disk->flags &= ~GENHD_FL_UP; unlink_gendisk(disk); - disk_stat_set_all(disk, 0); - disk->stamp = 0; + part_stat_set_all(&disk->part0, 0); + disk->part0.stamp = 0; - kobject_put(disk->holder_dir); + kobject_put(disk->part0.holder_dir); kobject_put(disk->slave_dir); disk->driverfs_dev = NULL; #ifndef CONFIG_SYSFS_DEPRECATED - sysfs_remove_link(block_depr, disk->dev.bus_id); + sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); #endif - device_del(&disk->dev); + device_del(disk_to_dev(disk)); } diff --git a/fs/partitions/check.h b/fs/partitions/check.h index 17ae8ecd9e8b..98dbe1a84528 100644 --- a/fs/partitions/check.h +++ b/fs/partitions/check.h @@ -5,15 +5,13 @@ * add_gd_partition adds a partitions details to the devices partition * description. */ -enum { MAX_PART = 256 }; - struct parsed_partitions { char name[BDEVNAME_SIZE]; struct { sector_t from; sector_t size; int flags; - } parts[MAX_PART]; + } parts[DISK_MAX_PARTS]; int next; int limit; }; diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 986061ae1b9b..36d5fcd3f593 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1001,12 +1001,13 @@ xfs_buf_iodone_work( * We can get an EOPNOTSUPP to ordered writes. Here we clear the * ordered flag and reissue them. Because we can't tell the higher * layers directly that they should not issue ordered I/O anymore, they - * need to check if the ordered flag was cleared during I/O completion. + * need to check if the _XFS_BARRIER_FAILED flag was set during I/O completion. */ if ((bp->b_error == EOPNOTSUPP) && (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) { XB_TRACE(bp, "ordered_retry", bp->b_iodone); bp->b_flags &= ~XBF_ORDERED; + bp->b_flags |= _XFS_BARRIER_FAILED; xfs_buf_iorequest(bp); } else if (bp->b_iodone) (*(bp->b_iodone))(bp); diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index fe0109956656..456519a088c7 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -85,6 +85,14 @@ typedef enum { * modifications being lost. */ _XBF_PAGE_LOCKED = (1 << 22), + + /* + * If we try a barrier write, but it fails we have to communicate + * this to the upper layers. Unfortunately b_error gets overwritten + * when the buffer is re-issued so we have to add another flag to + * keep this information. + */ + _XFS_BARRIER_FAILED = (1 << 23), } xfs_buf_flags_t; typedef enum { diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 503ea89e8b9a..0b02c6443551 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1033,11 +1033,12 @@ xlog_iodone(xfs_buf_t *bp) l = iclog->ic_log; /* - * If the ordered flag has been removed by a lower - * layer, it means the underlyin device no longer supports + * If the _XFS_BARRIER_FAILED flag was set by a lower + * layer, it means the underlying device no longer supports * barrier I/O. Warn loudly and turn off barriers. */ - if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ISORDERED(bp)) { + if (bp->b_flags & _XFS_BARRIER_FAILED) { + bp->b_flags &= ~_XFS_BARRIER_FAILED; l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; xfs_fs_cmn_err(CE_WARN, l->l_mp, "xlog_iodone: Barriers are no longer supported" diff --git a/include/asm-x86/a.out-core.h b/include/asm-x86/a.out-core.h index 714207a1c387..f5705761a37b 100644 --- a/include/asm-x86/a.out-core.h +++ b/include/asm-x86/a.out-core.h @@ -9,8 +9,8 @@ * 2 of the Licence, or (at your option) any later version. */ -#ifndef _ASM_A_OUT_CORE_H -#define _ASM_A_OUT_CORE_H +#ifndef ASM_X86__A_OUT_CORE_H +#define ASM_X86__A_OUT_CORE_H #ifdef __KERNEL__ #ifdef CONFIG_X86_32 @@ -70,4 +70,4 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) #endif /* CONFIG_X86_32 */ #endif /* __KERNEL__ */ -#endif /* _ASM_A_OUT_CORE_H */ +#endif /* ASM_X86__A_OUT_CORE_H */ diff --git a/include/asm-x86/a.out.h b/include/asm-x86/a.out.h index 4684f97a5bbd..0948748bc69c 100644 --- a/include/asm-x86/a.out.h +++ b/include/asm-x86/a.out.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_A_OUT_H -#define _ASM_X86_A_OUT_H +#ifndef ASM_X86__A_OUT_H +#define ASM_X86__A_OUT_H struct exec { @@ -17,4 +17,4 @@ struct exec #define N_DRSIZE(a) ((a).a_drsize) #define N_SYMSIZE(a) ((a).a_syms) -#endif /* _ASM_X86_A_OUT_H */ +#endif /* ASM_X86__A_OUT_H */ diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h index 35d1743b57ac..392e17336be1 100644 --- a/include/asm-x86/acpi.h +++ b/include/asm-x86/acpi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ACPI_H -#define _ASM_X86_ACPI_H +#ifndef ASM_X86__ACPI_H +#define ASM_X86__ACPI_H /* * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -175,4 +175,4 @@ static inline void acpi_fake_nodes(const struct bootnode *fake_nodes, #define acpi_unlazy_tlb(x) leave_mm(x) -#endif /*__X86_ASM_ACPI_H*/ +#endif /* ASM_X86__ACPI_H */ diff --git a/include/asm-x86/agp.h b/include/asm-x86/agp.h index e4004a9f6a9a..3617fd4fcdf9 100644 --- a/include/asm-x86/agp.h +++ b/include/asm-x86/agp.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_AGP_H -#define _ASM_X86_AGP_H +#ifndef ASM_X86__AGP_H +#define ASM_X86__AGP_H #include <asm/pgtable.h> #include <asm/cacheflush.h> @@ -32,4 +32,4 @@ #define free_gatt_pages(table, order) \ free_pages((unsigned long)(table), (order)) -#endif +#endif /* ASM_X86__AGP_H */ diff --git a/include/asm-x86/alternative.h b/include/asm-x86/alternative.h index f6aa18eadf71..22d3c9862bf3 100644 --- a/include/asm-x86/alternative.h +++ b/include/asm-x86/alternative.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ALTERNATIVE_H -#define _ASM_X86_ALTERNATIVE_H +#ifndef ASM_X86__ALTERNATIVE_H +#define ASM_X86__ALTERNATIVE_H #include <linux/types.h> #include <linux/stddef.h> @@ -180,4 +180,4 @@ extern void add_nops(void *insns, unsigned int len); extern void *text_poke(void *addr, const void *opcode, size_t len); extern void *text_poke_early(void *addr, const void *opcode, size_t len); -#endif /* _ASM_X86_ALTERNATIVE_H */ +#endif /* ASM_X86__ALTERNATIVE_H */ diff --git a/include/asm-x86/amd_iommu.h b/include/asm-x86/amd_iommu.h index 30a12049353b..783f43e58052 100644 --- a/include/asm-x86/amd_iommu.h +++ b/include/asm-x86/amd_iommu.h @@ -17,8 +17,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ASM_X86_AMD_IOMMU_H -#define _ASM_X86_AMD_IOMMU_H +#ifndef ASM_X86__AMD_IOMMU_H +#define ASM_X86__AMD_IOMMU_H #ifdef CONFIG_AMD_IOMMU extern int amd_iommu_init(void); @@ -29,4 +29,4 @@ static inline int amd_iommu_init(void) { return -ENODEV; } static inline void amd_iommu_detect(void) { } #endif -#endif +#endif /* ASM_X86__AMD_IOMMU_H */ diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index dcc812067394..1ffa4e53c989 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h @@ -17,8 +17,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __AMD_IOMMU_TYPES_H__ -#define __AMD_IOMMU_TYPES_H__ +#ifndef ASM_X86__AMD_IOMMU_TYPES_H +#define ASM_X86__AMD_IOMMU_TYPES_H #include <linux/types.h> #include <linux/list.h> @@ -341,4 +341,4 @@ static inline u16 calc_devid(u8 bus, u8 devfn) return (((u16)bus) << 8) | devfn; } -#endif +#endif /* ASM_X86__AMD_IOMMU_TYPES_H */ diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h index 133c998161ca..65590c9aecd4 100644 --- a/include/asm-x86/apic.h +++ b/include/asm-x86/apic.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_APIC_H -#define _ASM_X86_APIC_H +#ifndef ASM_X86__APIC_H +#define ASM_X86__APIC_H #include <linux/pm.h> #include <linux/delay.h> @@ -54,6 +54,11 @@ extern int disable_apic; #endif extern int is_vsmp_box(void); +extern void xapic_wait_icr_idle(void); +extern u32 safe_xapic_wait_icr_idle(void); +extern u64 xapic_icr_read(void); +extern void xapic_icr_write(u32, u32); +extern int setup_profiling_timer(unsigned int); static inline void native_apic_write(unsigned long reg, u32 v) { @@ -76,9 +81,7 @@ extern int get_physical_broadcast(void); static inline void ack_APIC_irq(void) { /* - * ack_APIC_irq() actually gets compiled as a single instruction: - * - a single rmw on Pentium/82489DX - * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC) + * ack_APIC_irq() actually gets compiled as a single instruction * ... yummie. */ @@ -128,4 +131,4 @@ static inline void init_apic_mappings(void) { } #endif /* !CONFIG_X86_LOCAL_APIC */ -#endif /* __ASM_APIC_H */ +#endif /* ASM_X86__APIC_H */ diff --git a/include/asm-x86/apicdef.h b/include/asm-x86/apicdef.h index 6b9008c78731..c40687da20fc 100644 --- a/include/asm-x86/apicdef.h +++ b/include/asm-x86/apicdef.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_APICDEF_H -#define _ASM_X86_APICDEF_H +#ifndef ASM_X86__APICDEF_H +#define ASM_X86__APICDEF_H /* * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) @@ -411,4 +411,4 @@ struct local_apic { #else #define BAD_APICID 0xFFFFu #endif -#endif +#endif /* ASM_X86__APICDEF_H */ diff --git a/include/asm-x86/arch_hooks.h b/include/asm-x86/arch_hooks.h index 8411750ceb63..72adc3a109cc 100644 --- a/include/asm-x86/arch_hooks.h +++ b/include/asm-x86/arch_hooks.h @@ -1,5 +1,5 @@ -#ifndef _ASM_ARCH_HOOKS_H -#define _ASM_ARCH_HOOKS_H +#ifndef ASM_X86__ARCH_HOOKS_H +#define ASM_X86__ARCH_HOOKS_H #include <linux/interrupt.h> @@ -25,4 +25,4 @@ extern void pre_time_init_hook(void); extern void time_init_hook(void); extern void mca_nmi_hook(void); -#endif +#endif /* ASM_X86__ARCH_HOOKS_H */ diff --git a/include/asm-x86/asm.h b/include/asm-x86/asm.h index 97220321f39d..e1355f44d7c3 100644 --- a/include/asm-x86/asm.h +++ b/include/asm-x86/asm.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ASM_H -#define _ASM_X86_ASM_H +#ifndef ASM_X86__ASM_H +#define ASM_X86__ASM_H #ifdef __ASSEMBLY__ # define __ASM_FORM(x) x @@ -20,17 +20,22 @@ #define _ASM_PTR __ASM_SEL(.long, .quad) #define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8) -#define _ASM_MOV_UL __ASM_SIZE(mov) +#define _ASM_MOV __ASM_SIZE(mov) #define _ASM_INC __ASM_SIZE(inc) #define _ASM_DEC __ASM_SIZE(dec) #define _ASM_ADD __ASM_SIZE(add) #define _ASM_SUB __ASM_SIZE(sub) #define _ASM_XADD __ASM_SIZE(xadd) + #define _ASM_AX __ASM_REG(ax) #define _ASM_BX __ASM_REG(bx) #define _ASM_CX __ASM_REG(cx) #define _ASM_DX __ASM_REG(dx) +#define _ASM_SP __ASM_REG(sp) +#define _ASM_BP __ASM_REG(bp) +#define _ASM_SI __ASM_REG(si) +#define _ASM_DI __ASM_REG(di) /* Exception table entry */ # define _ASM_EXTABLE(from,to) \ @@ -39,4 +44,4 @@ _ASM_PTR #from "," #to "\n" \ " .previous\n" -#endif /* _ASM_X86_ASM_H */ +#endif /* ASM_X86__ASM_H */ diff --git a/include/asm-x86/atomic_32.h b/include/asm-x86/atomic_32.h index 21a4825148c0..14d3f0beb889 100644 --- a/include/asm-x86/atomic_32.h +++ b/include/asm-x86/atomic_32.h @@ -1,5 +1,5 @@ -#ifndef __ARCH_I386_ATOMIC__ -#define __ARCH_I386_ATOMIC__ +#ifndef ASM_X86__ATOMIC_32_H +#define ASM_X86__ATOMIC_32_H #include <linux/compiler.h> #include <asm/processor.h> @@ -256,4 +256,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #define smp_mb__after_atomic_inc() barrier() #include <asm-generic/atomic.h> -#endif +#endif /* ASM_X86__ATOMIC_32_H */ diff --git a/include/asm-x86/atomic_64.h b/include/asm-x86/atomic_64.h index 91c7d03e65bc..2cb218c4a356 100644 --- a/include/asm-x86/atomic_64.h +++ b/include/asm-x86/atomic_64.h @@ -1,5 +1,5 @@ -#ifndef __ARCH_X86_64_ATOMIC__ -#define __ARCH_X86_64_ATOMIC__ +#ifndef ASM_X86__ATOMIC_64_H +#define ASM_X86__ATOMIC_64_H #include <asm/alternative.h> #include <asm/cmpxchg.h> @@ -470,4 +470,4 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2) #define smp_mb__after_atomic_inc() barrier() #include <asm-generic/atomic.h> -#endif +#endif /* ASM_X86__ATOMIC_64_H */ diff --git a/include/asm-x86/auxvec.h b/include/asm-x86/auxvec.h index 87f5e6d5a020..12c7cac74202 100644 --- a/include/asm-x86/auxvec.h +++ b/include/asm-x86/auxvec.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_AUXVEC_H -#define _ASM_X86_AUXVEC_H +#ifndef ASM_X86__AUXVEC_H +#define ASM_X86__AUXVEC_H /* * Architecture-neutral AT_ values in 0-17, leave some room * for more of them, start the x86-specific ones at 32. @@ -9,4 +9,4 @@ #endif #define AT_SYSINFO_EHDR 33 -#endif +#endif /* ASM_X86__AUXVEC_H */ diff --git a/include/asm-x86/bios_ebda.h b/include/asm-x86/bios_ebda.h index 0033e50c13b2..ec42ed874591 100644 --- a/include/asm-x86/bios_ebda.h +++ b/include/asm-x86/bios_ebda.h @@ -1,5 +1,5 @@ -#ifndef _MACH_BIOS_EBDA_H -#define _MACH_BIOS_EBDA_H +#ifndef ASM_X86__BIOS_EBDA_H +#define ASM_X86__BIOS_EBDA_H #include <asm/io.h> @@ -16,4 +16,4 @@ static inline unsigned int get_bios_ebda(void) void reserve_ebda_region(void); -#endif /* _MACH_BIOS_EBDA_H */ +#endif /* ASM_X86__BIOS_EBDA_H */ diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h index cfb2b64f76e7..61989b93b475 100644 --- a/include/asm-x86/bitops.h +++ b/include/asm-x86/bitops.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BITOPS_H -#define _ASM_X86_BITOPS_H +#ifndef ASM_X86__BITOPS_H +#define ASM_X86__BITOPS_H /* * Copyright 1992, Linus Torvalds. @@ -458,4 +458,4 @@ static inline void set_bit_string(unsigned long *bitmap, #include <asm-generic/bitops/minix.h> #endif /* __KERNEL__ */ -#endif /* _ASM_X86_BITOPS_H */ +#endif /* ASM_X86__BITOPS_H */ diff --git a/include/asm-x86/boot.h b/include/asm-x86/boot.h index 2faed7ecb092..825de5dc867c 100644 --- a/include/asm-x86/boot.h +++ b/include/asm-x86/boot.h @@ -1,5 +1,5 @@ -#ifndef _ASM_BOOT_H -#define _ASM_BOOT_H +#ifndef ASM_X86__BOOT_H +#define ASM_X86__BOOT_H /* Don't touch these, unless you really know what you're doing. */ #define DEF_INITSEG 0x9000 @@ -25,4 +25,4 @@ #define BOOT_STACK_SIZE 0x1000 #endif -#endif /* _ASM_BOOT_H */ +#endif /* ASM_X86__BOOT_H */ diff --git a/include/asm-x86/bootparam.h b/include/asm-x86/bootparam.h index ae22bdf0ab14..ccf027e2d97d 100644 --- a/include/asm-x86/bootparam.h +++ b/include/asm-x86/bootparam.h @@ -1,5 +1,5 @@ -#ifndef _ASM_BOOTPARAM_H -#define _ASM_BOOTPARAM_H +#ifndef ASM_X86__BOOTPARAM_H +#define ASM_X86__BOOTPARAM_H #include <linux/types.h> #include <linux/screen_info.h> @@ -108,4 +108,4 @@ struct boot_params { __u8 _pad9[276]; /* 0xeec */ } __attribute__((packed)); -#endif /* _ASM_BOOTPARAM_H */ +#endif /* ASM_X86__BOOTPARAM_H */ diff --git a/include/asm-x86/bug.h b/include/asm-x86/bug.h index b69aa64b82a4..91ad43a54c47 100644 --- a/include/asm-x86/bug.h +++ b/include/asm-x86/bug.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BUG_H -#define _ASM_X86_BUG_H +#ifndef ASM_X86__BUG_H +#define ASM_X86__BUG_H #ifdef CONFIG_BUG #define HAVE_ARCH_BUG @@ -36,4 +36,4 @@ do { \ #endif /* !CONFIG_BUG */ #include <asm-generic/bug.h> -#endif +#endif /* ASM_X86__BUG_H */ diff --git a/include/asm-x86/bugs.h b/include/asm-x86/bugs.h index 021cbdd5f258..4761c461d23a 100644 --- a/include/asm-x86/bugs.h +++ b/include/asm-x86/bugs.h @@ -1,7 +1,7 @@ -#ifndef _ASM_X86_BUGS_H -#define _ASM_X86_BUGS_H +#ifndef ASM_X86__BUGS_H +#define ASM_X86__BUGS_H extern void check_bugs(void); int ppro_with_ram_bug(void); -#endif /* _ASM_X86_BUGS_H */ +#endif /* ASM_X86__BUGS_H */ diff --git a/include/asm-x86/byteorder.h b/include/asm-x86/byteorder.h index e02ae2d89acf..722f27d68105 100644 --- a/include/asm-x86/byteorder.h +++ b/include/asm-x86/byteorder.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BYTEORDER_H -#define _ASM_X86_BYTEORDER_H +#ifndef ASM_X86__BYTEORDER_H +#define ASM_X86__BYTEORDER_H #include <asm/types.h> #include <linux/compiler.h> @@ -78,4 +78,4 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) #include <linux/byteorder/little_endian.h> -#endif /* _ASM_X86_BYTEORDER_H */ +#endif /* ASM_X86__BYTEORDER_H */ diff --git a/include/asm-x86/cache.h b/include/asm-x86/cache.h index 1e0bac86f38f..ea3f1cc06a97 100644 --- a/include/asm-x86/cache.h +++ b/include/asm-x86/cache.h @@ -1,5 +1,5 @@ -#ifndef _ARCH_X86_CACHE_H -#define _ARCH_X86_CACHE_H +#ifndef ASM_X86__CACHE_H +#define ASM_X86__CACHE_H /* L1 cache line size */ #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) @@ -17,4 +17,4 @@ #endif #endif -#endif +#endif /* ASM_X86__CACHE_H */ diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index f4c0ab50d2c2..59859cb28a36 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_CACHEFLUSH_H -#define _ASM_X86_CACHEFLUSH_H +#ifndef ASM_X86__CACHEFLUSH_H +#define ASM_X86__CACHEFLUSH_H /* Keep includes the same across arches. */ #include <linux/mm.h> @@ -112,4 +112,4 @@ static inline int rodata_test(void) } #endif -#endif +#endif /* ASM_X86__CACHEFLUSH_H */ diff --git a/include/asm-x86/calgary.h b/include/asm-x86/calgary.h index 67f60406e2d8..933fd272f826 100644 --- a/include/asm-x86/calgary.h +++ b/include/asm-x86/calgary.h @@ -21,8 +21,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ASM_X86_64_CALGARY_H -#define _ASM_X86_64_CALGARY_H +#ifndef ASM_X86__CALGARY_H +#define ASM_X86__CALGARY_H #include <linux/spinlock.h> #include <linux/device.h> @@ -69,4 +69,4 @@ static inline int calgary_iommu_init(void) { return 1; } static inline void detect_calgary(void) { return; } #endif -#endif /* _ASM_X86_64_CALGARY_H */ +#endif /* ASM_X86__CALGARY_H */ diff --git a/include/asm-x86/checksum_32.h b/include/asm-x86/checksum_32.h index 52bbb0d8c4c1..d041e8cda227 100644 --- a/include/asm-x86/checksum_32.h +++ b/include/asm-x86/checksum_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_CHECKSUM_H -#define _I386_CHECKSUM_H +#ifndef ASM_X86__CHECKSUM_32_H +#define ASM_X86__CHECKSUM_32_H #include <linux/in6.h> @@ -186,4 +186,4 @@ static inline __wsum csum_and_copy_to_user(const void *src, return (__force __wsum)-1; /* invalid checksum */ } -#endif +#endif /* ASM_X86__CHECKSUM_32_H */ diff --git a/include/asm-x86/checksum_64.h b/include/asm-x86/checksum_64.h index 8bd861cc5267..110f403beb89 100644 --- a/include/asm-x86/checksum_64.h +++ b/include/asm-x86/checksum_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_CHECKSUM_H -#define _X86_64_CHECKSUM_H +#ifndef ASM_X86__CHECKSUM_64_H +#define ASM_X86__CHECKSUM_64_H /* * Checksums for x86-64 @@ -188,4 +188,4 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b) return a; } -#endif +#endif /* ASM_X86__CHECKSUM_64_H */ diff --git a/include/asm-x86/cmpxchg_32.h b/include/asm-x86/cmpxchg_32.h index bf5a69d1329e..0622e45cdf7c 100644 --- a/include/asm-x86/cmpxchg_32.h +++ b/include/asm-x86/cmpxchg_32.h @@ -1,5 +1,5 @@ -#ifndef __ASM_CMPXCHG_H -#define __ASM_CMPXCHG_H +#ifndef ASM_X86__CMPXCHG_32_H +#define ASM_X86__CMPXCHG_32_H #include <linux/bitops.h> /* for LOCK_PREFIX */ @@ -341,4 +341,4 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64); #endif -#endif +#endif /* ASM_X86__CMPXCHG_32_H */ diff --git a/include/asm-x86/cmpxchg_64.h b/include/asm-x86/cmpxchg_64.h index 17463ccf8166..63c1a5e61b99 100644 --- a/include/asm-x86/cmpxchg_64.h +++ b/include/asm-x86/cmpxchg_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_CMPXCHG_H -#define __ASM_CMPXCHG_H +#ifndef ASM_X86__CMPXCHG_64_H +#define ASM_X86__CMPXCHG_64_H #include <asm/alternative.h> /* Provides LOCK_PREFIX */ @@ -182,4 +182,4 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, cmpxchg_local((ptr), (o), (n)); \ }) -#endif +#endif /* ASM_X86__CMPXCHG_64_H */ diff --git a/include/asm-x86/compat.h b/include/asm-x86/compat.h index 1793ac317a30..6732b150949e 100644 --- a/include/asm-x86/compat.h +++ b/include/asm-x86/compat.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_COMPAT_H -#define _ASM_X86_64_COMPAT_H +#ifndef ASM_X86__COMPAT_H +#define ASM_X86__COMPAT_H /* * Architecture specific compatibility types @@ -215,4 +215,4 @@ static inline int is_compat_task(void) return current_thread_info()->status & TS_COMPAT; } -#endif /* _ASM_X86_64_COMPAT_H */ +#endif /* ASM_X86__COMPAT_H */ diff --git a/include/asm-x86/cpu.h b/include/asm-x86/cpu.h index 73f2ea84fd74..83a115083f0d 100644 --- a/include/asm-x86/cpu.h +++ b/include/asm-x86/cpu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_I386_CPU_H_ -#define _ASM_I386_CPU_H_ +#ifndef ASM_X86__CPU_H +#define ASM_X86__CPU_H #include <linux/device.h> #include <linux/cpu.h> @@ -17,4 +17,4 @@ extern void arch_unregister_cpu(int); #endif DECLARE_PER_CPU(int, cpu_state); -#endif /* _ASM_I386_CPU_H_ */ +#endif /* ASM_X86__CPU_H */ diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index cfcfb0a806ba..250fa0cb144b 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -1,8 +1,8 @@ /* * Defines x86 CPU feature bits */ -#ifndef _ASM_X86_CPUFEATURE_H -#define _ASM_X86_CPUFEATURE_H +#ifndef ASM_X86__CPUFEATURE_H +#define ASM_X86__CPUFEATURE_H #include <asm/required-features.h> @@ -224,4 +224,4 @@ extern const char * const x86_power_flags[32]; #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ -#endif /* _ASM_X86_CPUFEATURE_H */ +#endif /* ASM_X86__CPUFEATURE_H */ diff --git a/include/asm-x86/current.h b/include/asm-x86/current.h index 7515c19d4988..a863ead856f3 100644 --- a/include/asm-x86/current.h +++ b/include/asm-x86/current.h @@ -1,5 +1,5 @@ -#ifndef _X86_CURRENT_H -#define _X86_CURRENT_H +#ifndef ASM_X86__CURRENT_H +#define ASM_X86__CURRENT_H #ifdef CONFIG_X86_32 #include <linux/compiler.h> @@ -36,4 +36,4 @@ static __always_inline struct task_struct *get_current(void) #define current get_current() -#endif /* X86_CURRENT_H */ +#endif /* ASM_X86__CURRENT_H */ diff --git a/include/asm-x86/debugreg.h b/include/asm-x86/debugreg.h index c6344d572b03..ecb6907c3ea4 100644 --- a/include/asm-x86/debugreg.h +++ b/include/asm-x86/debugreg.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DEBUGREG_H -#define _ASM_X86_DEBUGREG_H +#ifndef ASM_X86__DEBUGREG_H +#define ASM_X86__DEBUGREG_H /* Indicate the register numbers for a number of the specific @@ -67,4 +67,4 @@ #define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ #define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ -#endif +#endif /* ASM_X86__DEBUGREG_H */ diff --git a/include/asm-x86/delay.h b/include/asm-x86/delay.h index 409a649204aa..8a0da95b4fc5 100644 --- a/include/asm-x86/delay.h +++ b/include/asm-x86/delay.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DELAY_H -#define _ASM_X86_DELAY_H +#ifndef ASM_X86__DELAY_H +#define ASM_X86__DELAY_H /* * Copyright (C) 1993 Linus Torvalds @@ -28,4 +28,4 @@ extern void __delay(unsigned long loops); void use_tsc_delay(void); -#endif /* _ASM_X86_DELAY_H */ +#endif /* ASM_X86__DELAY_H */ diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h index a44c4dc70590..b73fea54def2 100644 --- a/include/asm-x86/desc.h +++ b/include/asm-x86/desc.h @@ -1,5 +1,5 @@ -#ifndef _ASM_DESC_H_ -#define _ASM_DESC_H_ +#ifndef ASM_X86__DESC_H +#define ASM_X86__DESC_H #ifndef __ASSEMBLY__ #include <asm/desc_defs.h> @@ -397,4 +397,4 @@ static inline void set_system_gate_ist(int n, void *addr, unsigned ist) #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__DESC_H */ diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h index f7bacf357dac..b881db664b46 100644 --- a/include/asm-x86/desc_defs.h +++ b/include/asm-x86/desc_defs.h @@ -1,6 +1,6 @@ /* Written 2000 by Andi Kleen */ -#ifndef __ARCH_DESC_DEFS_H -#define __ARCH_DESC_DEFS_H +#ifndef ASM_X86__DESC_DEFS_H +#define ASM_X86__DESC_DEFS_H /* * Segment descriptor structure definitions, usable from both x86_64 and i386 @@ -92,4 +92,4 @@ struct desc_ptr { #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__DESC_DEFS_H */ diff --git a/include/asm-x86/device.h b/include/asm-x86/device.h index 3c034f48fdb0..1bece04c7d9d 100644 --- a/include/asm-x86/device.h +++ b/include/asm-x86/device.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DEVICE_H -#define _ASM_X86_DEVICE_H +#ifndef ASM_X86__DEVICE_H +#define ASM_X86__DEVICE_H struct dev_archdata { #ifdef CONFIG_ACPI @@ -13,4 +13,4 @@ struct dma_mapping_ops *dma_ops; #endif }; -#endif /* _ASM_X86_DEVICE_H */ +#endif /* ASM_X86__DEVICE_H */ diff --git a/include/asm-x86/div64.h b/include/asm-x86/div64.h index 9a2d644c08ef..f9530f23f1d6 100644 --- a/include/asm-x86/div64.h +++ b/include/asm-x86/div64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DIV64_H -#define _ASM_X86_DIV64_H +#ifndef ASM_X86__DIV64_H +#define ASM_X86__DIV64_H #ifdef CONFIG_X86_32 @@ -57,4 +57,4 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) # include <asm-generic/div64.h> #endif /* CONFIG_X86_32 */ -#endif /* _ASM_X86_DIV64_H */ +#endif /* ASM_X86__DIV64_H */ diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h index ad9cd6d49bfc..5d200e78bd81 100644 --- a/include/asm-x86/dma-mapping.h +++ b/include/asm-x86/dma-mapping.h @@ -1,5 +1,5 @@ -#ifndef _ASM_DMA_MAPPING_H_ -#define _ASM_DMA_MAPPING_H_ +#ifndef ASM_X86__DMA_MAPPING_H +#define ASM_X86__DMA_MAPPING_H /* * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for @@ -250,4 +250,4 @@ static inline int dma_get_cache_alignment(void) #define dma_is_consistent(d, h) (1) #include <asm-generic/dma-coherent.h> -#endif +#endif /* ASM_X86__DMA_MAPPING_H */ diff --git a/include/asm-x86/dma.h b/include/asm-x86/dma.h index ca1098a7e580..c9f7a4eec555 100644 --- a/include/asm-x86/dma.h +++ b/include/asm-x86/dma.h @@ -5,8 +5,8 @@ * and John Boyd, Nov. 1992. */ -#ifndef _ASM_X86_DMA_H -#define _ASM_X86_DMA_H +#ifndef ASM_X86__DMA_H +#define ASM_X86__DMA_H #include <linux/spinlock.h> /* And spinlocks */ #include <asm/io.h> /* need byte IO */ @@ -315,4 +315,4 @@ extern int isa_dma_bridge_buggy; #define isa_dma_bridge_buggy (0) #endif -#endif /* _ASM_X86_DMA_H */ +#endif /* ASM_X86__DMA_H */ diff --git a/include/asm-x86/dmi.h b/include/asm-x86/dmi.h index 58a86571fe0f..1cff6fe81fa5 100644 --- a/include/asm-x86/dmi.h +++ b/include/asm-x86/dmi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_DMI_H -#define _ASM_X86_DMI_H +#ifndef ASM_X86__DMI_H +#define ASM_X86__DMI_H #include <asm/io.h> @@ -23,4 +23,4 @@ static inline void *dmi_alloc(unsigned len) #define dmi_ioremap early_ioremap #define dmi_iounmap early_iounmap -#endif +#endif /* ASM_X86__DMI_H */ diff --git a/include/asm-x86/ds.h b/include/asm-x86/ds.h index 7881368142fa..c3c953a45b21 100644 --- a/include/asm-x86/ds.h +++ b/include/asm-x86/ds.h @@ -2,71 +2,237 @@ * Debug Store (DS) support * * This provides a low-level interface to the hardware's Debug Store - * feature that is used for last branch recording (LBR) and + * feature that is used for branch trace store (BTS) and * precise-event based sampling (PEBS). * - * Different architectures use a different DS layout/pointer size. - * The below functions therefore work on a void*. + * It manages: + * - per-thread and per-cpu allocation of BTS and PEBS + * - buffer memory allocation (optional) + * - buffer overflow handling + * - buffer access * + * It assumes: + * - get_task_struct on all parameter tasks + * - current is allowed to trace parameter tasks * - * Since there is no user for PEBS, yet, only LBR (or branch - * trace store, BTS) is supported. * - * - * Copyright (C) 2007 Intel Corporation. - * Markus Metzger <markus.t.metzger@intel.com>, Dec 2007 + * Copyright (C) 2007-2008 Intel Corporation. + * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008 */ -#ifndef _ASM_X86_DS_H -#define _ASM_X86_DS_H +#ifndef ASM_X86__DS_H +#define ASM_X86__DS_H + +#ifdef CONFIG_X86_DS #include <linux/types.h> #include <linux/init.h> -struct cpuinfo_x86; +struct task_struct; -/* a branch trace record entry +/* + * Request BTS or PEBS + * + * Due to alignement constraints, the actual buffer may be slightly + * smaller than the requested or provided buffer. * - * In order to unify the interface between various processor versions, - * we use the below data structure for all processors. + * Returns 0 on success; -Eerrno otherwise + * + * task: the task to request recording for; + * NULL for per-cpu recording on the current cpu + * base: the base pointer for the (non-pageable) buffer; + * NULL if buffer allocation requested + * size: the size of the requested or provided buffer + * ovfl: pointer to a function to be called on buffer overflow; + * NULL if cyclic buffer requested */ -enum bts_qualifier { - BTS_INVALID = 0, - BTS_BRANCH, - BTS_TASK_ARRIVES, - BTS_TASK_DEPARTS -}; +typedef void (*ds_ovfl_callback_t)(struct task_struct *); +extern int ds_request_bts(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl); +extern int ds_request_pebs(struct task_struct *task, void *base, size_t size, + ds_ovfl_callback_t ovfl); -struct bts_struct { - u64 qualifier; - union { - /* BTS_BRANCH */ - struct { - u64 from_ip; - u64 to_ip; - } lbr; - /* BTS_TASK_ARRIVES or - BTS_TASK_DEPARTS */ - u64 jiffies; - } variant; +/* + * Release BTS or PEBS resources + * + * Frees buffers allocated on ds_request. + * + * Returns 0 on success; -Eerrno otherwise + * + * task: the task to release resources for; + * NULL to release resources for the current cpu + */ +extern int ds_release_bts(struct task_struct *task); +extern int ds_release_pebs(struct task_struct *task); + +/* + * Return the (array) index of the write pointer. + * (assuming an array of BTS/PEBS records) + * + * Returns -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * pos (out): if not NULL, will hold the result + */ +extern int ds_get_bts_index(struct task_struct *task, size_t *pos); +extern int ds_get_pebs_index(struct task_struct *task, size_t *pos); + +/* + * Return the (array) index one record beyond the end of the array. + * (assuming an array of BTS/PEBS records) + * + * Returns -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * pos (out): if not NULL, will hold the result + */ +extern int ds_get_bts_end(struct task_struct *task, size_t *pos); +extern int ds_get_pebs_end(struct task_struct *task, size_t *pos); + +/* + * Provide a pointer to the BTS/PEBS record at parameter index. + * (assuming an array of BTS/PEBS records) + * + * The pointer points directly into the buffer. The user is + * responsible for copying the record. + * + * Returns the size of a single record on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * index: the index of the requested record + * record (out): pointer to the requested record + */ +extern int ds_access_bts(struct task_struct *task, + size_t index, const void **record); +extern int ds_access_pebs(struct task_struct *task, + size_t index, const void **record); + +/* + * Write one or more BTS/PEBS records at the write pointer index and + * advance the write pointer. + * + * If size is not a multiple of the record size, trailing bytes are + * zeroed out. + * + * May result in one or more overflow notifications. + * + * If called during overflow handling, that is, with index >= + * interrupt threshold, the write will wrap around. + * + * An overflow notification is given if and when the interrupt + * threshold is reached during or after the write. + * + * Returns the number of bytes written or -Eerrno. + * + * task: the task to access; + * NULL to access the current cpu + * buffer: the buffer to write + * size: the size of the buffer + */ +extern int ds_write_bts(struct task_struct *task, + const void *buffer, size_t size); +extern int ds_write_pebs(struct task_struct *task, + const void *buffer, size_t size); + +/* + * Same as ds_write_bts/pebs, but omit ownership checks. + * + * This is needed to have some other task than the owner of the + * BTS/PEBS buffer or the parameter task itself write into the + * respective buffer. + */ +extern int ds_unchecked_write_bts(struct task_struct *task, + const void *buffer, size_t size); +extern int ds_unchecked_write_pebs(struct task_struct *task, + const void *buffer, size_t size); + +/* + * Reset the write pointer of the BTS/PEBS buffer. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + */ +extern int ds_reset_bts(struct task_struct *task); +extern int ds_reset_pebs(struct task_struct *task); + +/* + * Clear the BTS/PEBS buffer and reset the write pointer. + * The entire buffer will be zeroed out. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + */ +extern int ds_clear_bts(struct task_struct *task); +extern int ds_clear_pebs(struct task_struct *task); + +/* + * Provide the PEBS counter reset value. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * value (out): the counter reset value + */ +extern int ds_get_pebs_reset(struct task_struct *task, u64 *value); + +/* + * Set the PEBS counter reset value. + * + * Returns 0 on success; -Eerrno on error + * + * task: the task to access; + * NULL to access the current cpu + * value: the new counter reset value + */ +extern int ds_set_pebs_reset(struct task_struct *task, u64 value); + +/* + * Initialization + */ +struct cpuinfo_x86; +extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); + + + +/* + * The DS context - part of struct thread_struct. + */ +struct ds_context { + /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */ + unsigned char *ds; + /* the owner of the BTS and PEBS configuration, respectively */ + struct task_struct *owner[2]; + /* buffer overflow notification function for BTS and PEBS */ + ds_ovfl_callback_t callback[2]; + /* the original buffer address */ + void *buffer[2]; + /* the number of allocated pages for on-request allocated buffers */ + unsigned int pages[2]; + /* use count */ + unsigned long count; + /* a pointer to the context location inside the thread_struct + * or the per_cpu context array */ + struct ds_context **this; + /* a pointer to the task owning this context, or NULL, if the + * context is owned by a cpu */ + struct task_struct *task; }; -/* Overflow handling mechanisms */ -#define DS_O_SIGNAL 1 /* send overflow signal */ -#define DS_O_WRAP 2 /* wrap around */ - -extern int ds_allocate(void **, size_t); -extern int ds_free(void **); -extern int ds_get_bts_size(void *); -extern int ds_get_bts_end(void *); -extern int ds_get_bts_index(void *); -extern int ds_set_overflow(void *, int); -extern int ds_get_overflow(void *); -extern int ds_clear(void *); -extern int ds_read_bts(void *, int, struct bts_struct *); -extern int ds_write_bts(void *, const struct bts_struct *); -extern unsigned long ds_debugctl_mask(void); -extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *c); - -#endif /* _ASM_X86_DS_H */ +/* called by exit_thread() to free leftover contexts */ +extern void ds_free(struct ds_context *context); + +#else /* CONFIG_X86_DS */ + +#define ds_init_intel(config) do {} while (0) + +#endif /* CONFIG_X86_DS */ +#endif /* ASM_X86__DS_H */ diff --git a/include/asm-x86/dwarf2.h b/include/asm-x86/dwarf2.h index 738bb9fb3e53..21d1bc32ad7c 100644 --- a/include/asm-x86/dwarf2.h +++ b/include/asm-x86/dwarf2.h @@ -1,5 +1,5 @@ -#ifndef _DWARF2_H -#define _DWARF2_H +#ifndef ASM_X86__DWARF2_H +#define ASM_X86__DWARF2_H #ifndef __ASSEMBLY__ #warning "asm/dwarf2.h should be only included in pure assembly files" @@ -58,4 +58,4 @@ #endif -#endif +#endif /* ASM_X86__DWARF2_H */ diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h index 16a31e2c7c57..f52daf176bcb 100644 --- a/include/asm-x86/e820.h +++ b/include/asm-x86/e820.h @@ -1,5 +1,5 @@ -#ifndef __ASM_E820_H -#define __ASM_E820_H +#ifndef ASM_X86__E820_H +#define ASM_X86__E820_H #define E820MAP 0x2d0 /* our map */ #define E820MAX 128 /* number of entries in E820MAP */ @@ -64,6 +64,7 @@ struct e820map { extern struct e820map e820; extern struct e820map e820_saved; +extern unsigned long pci_mem_start; extern int e820_any_mapped(u64 start, u64 end, unsigned type); extern int e820_all_mapped(u64 start, u64 end, unsigned type); extern void e820_add_region(u64 start, u64 size, int type); @@ -140,4 +141,4 @@ extern char *memory_setup(void); #define HIGH_MEMORY (1024*1024) #endif /* __KERNEL__ */ -#endif /* __ASM_E820_H */ +#endif /* ASM_X86__E820_H */ diff --git a/include/asm-x86/edac.h b/include/asm-x86/edac.h index a8088f63a30e..9493c5b27bbd 100644 --- a/include/asm-x86/edac.h +++ b/include/asm-x86/edac.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_EDAC_H -#define _ASM_X86_EDAC_H +#ifndef ASM_X86__EDAC_H +#define ASM_X86__EDAC_H /* ECC atomic, DMA, SMP and interrupt safe scrub function */ @@ -15,4 +15,4 @@ static inline void atomic_scrub(void *va, u32 size) asm volatile("lock; addl $0, %0"::"m" (*virt_addr)); } -#endif +#endif /* ASM_X86__EDAC_H */ diff --git a/include/asm-x86/efi.h b/include/asm-x86/efi.h index d4f2b0abe929..ed2de22e8705 100644 --- a/include/asm-x86/efi.h +++ b/include/asm-x86/efi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_EFI_H -#define _ASM_X86_EFI_H +#ifndef ASM_X86__EFI_H +#define ASM_X86__EFI_H #ifdef CONFIG_X86_32 @@ -94,4 +94,4 @@ extern void efi_reserve_early(void); extern void efi_call_phys_prelog(void); extern void efi_call_phys_epilog(void); -#endif +#endif /* ASM_X86__EFI_H */ diff --git a/include/asm-x86/elf.h b/include/asm-x86/elf.h index 7be4733c793e..5c4745bec906 100644 --- a/include/asm-x86/elf.h +++ b/include/asm-x86/elf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_ELF_H -#define _ASM_X86_ELF_H +#ifndef ASM_X86__ELF_H +#define ASM_X86__ELF_H /* * ELF register definitions.. @@ -148,8 +148,9 @@ do { \ static inline void start_ia32_thread(struct pt_regs *regs, u32 ip, u32 sp) { - asm volatile("movl %0,%%fs" :: "r" (0)); - asm volatile("movl %0,%%es; movl %0,%%ds" : : "r" (__USER32_DS)); + loadsegment(fs, 0); + loadsegment(ds, __USER32_DS); + loadsegment(es, __USER32_DS); load_gs_index(0); regs->ip = ip; regs->sp = sp; @@ -332,4 +333,4 @@ extern int syscall32_setup_pages(struct linux_binprm *, int exstack); extern unsigned long arch_randomize_brk(struct mm_struct *mm); #define arch_randomize_brk arch_randomize_brk -#endif +#endif /* ASM_X86__ELF_H */ diff --git a/include/asm-x86/emergency-restart.h b/include/asm-x86/emergency-restart.h index 8e6aef19f8f0..190d0d8b71e3 100644 --- a/include/asm-x86/emergency-restart.h +++ b/include/asm-x86/emergency-restart.h @@ -1,5 +1,5 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H +#ifndef ASM_X86__EMERGENCY_RESTART_H +#define ASM_X86__EMERGENCY_RESTART_H enum reboot_type { BOOT_TRIPLE = 't', @@ -15,4 +15,4 @@ extern enum reboot_type reboot_type; extern void machine_emergency_restart(void); -#endif /* _ASM_EMERGENCY_RESTART_H */ +#endif /* ASM_X86__EMERGENCY_RESTART_H */ diff --git a/include/asm-x86/fb.h b/include/asm-x86/fb.h index 53018464aea6..aca38dbd9a64 100644 --- a/include/asm-x86/fb.h +++ b/include/asm-x86/fb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_FB_H -#define _ASM_X86_FB_H +#ifndef ASM_X86__FB_H +#define ASM_X86__FB_H #include <linux/fb.h> #include <linux/fs.h> @@ -18,4 +18,4 @@ extern int fb_is_primary_device(struct fb_info *info); static inline int fb_is_primary_device(struct fb_info *info) { return 0; } #endif -#endif /* _ASM_X86_FB_H */ +#endif /* ASM_X86__FB_H */ diff --git a/include/asm-x86/fixmap.h b/include/asm-x86/fixmap.h index 44d4f8217349..78e33a1bc591 100644 --- a/include/asm-x86/fixmap.h +++ b/include/asm-x86/fixmap.h @@ -1,5 +1,5 @@ -#ifndef _ASM_FIXMAP_H -#define _ASM_FIXMAP_H +#ifndef ASM_X86__FIXMAP_H +#define ASM_X86__FIXMAP_H #ifdef CONFIG_X86_32 # include "fixmap_32.h" @@ -65,4 +65,4 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr) BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); return __virt_to_fix(vaddr); } -#endif +#endif /* ASM_X86__FIXMAP_H */ diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h index f1ac2b2167d7..784e3e759866 100644 --- a/include/asm-x86/fixmap_32.h +++ b/include/asm-x86/fixmap_32.h @@ -10,8 +10,8 @@ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 */ -#ifndef _ASM_FIXMAP_32_H -#define _ASM_FIXMAP_32_H +#ifndef ASM_X86__FIXMAP_32_H +#define ASM_X86__FIXMAP_32_H /* used by vmalloc.c, vsyscall.lds.S. @@ -120,4 +120,4 @@ extern void reserve_top_address(unsigned long reserve); #define FIXADDR_BOOT_START (FIXADDR_TOP - __FIXADDR_BOOT_SIZE) #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__FIXMAP_32_H */ diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h index 00f3d74a0524..dafb24bc0424 100644 --- a/include/asm-x86/fixmap_64.h +++ b/include/asm-x86/fixmap_64.h @@ -8,8 +8,8 @@ * Copyright (C) 1998 Ingo Molnar */ -#ifndef _ASM_FIXMAP_64_H -#define _ASM_FIXMAP_64_H +#ifndef ASM_X86__FIXMAP_64_H +#define ASM_X86__FIXMAP_64_H #include <linux/kernel.h> #include <asm/acpi.h> @@ -80,4 +80,4 @@ enum fixed_addresses { #define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL) #define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) -#endif +#endif /* ASM_X86__FIXMAP_64_H */ diff --git a/include/asm-x86/floppy.h b/include/asm-x86/floppy.h index dbe82a5c5eac..7d83a3a83e37 100644 --- a/include/asm-x86/floppy.h +++ b/include/asm-x86/floppy.h @@ -7,8 +7,8 @@ * * Copyright (C) 1995 */ -#ifndef _ASM_X86_FLOPPY_H -#define _ASM_X86_FLOPPY_H +#ifndef ASM_X86__FLOPPY_H +#define ASM_X86__FLOPPY_H #include <linux/vmalloc.h> @@ -278,4 +278,4 @@ static int FDC2 = -1; #define EXTRA_FLOPPY_PARAMS -#endif /* _ASM_X86_FLOPPY_H */ +#endif /* ASM_X86__FLOPPY_H */ diff --git a/include/asm-x86/ftrace.h b/include/asm-x86/ftrace.h index 5c68b32ee1c8..be0e004ad148 100644 --- a/include/asm-x86/ftrace.h +++ b/include/asm-x86/ftrace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_FTRACE -#define _ASM_X86_FTRACE +#ifndef ASM_X86__FTRACE_H +#define ASM_X86__FTRACE_H #ifdef CONFIG_FTRACE #define MCOUNT_ADDR ((long)(mcount)) @@ -11,4 +11,4 @@ extern void mcount(void); #endif /* CONFIG_FTRACE */ -#endif /* _ASM_X86_FTRACE */ +#endif /* ASM_X86__FTRACE_H */ diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h index e7a76b37b333..06b924ef6fa5 100644 --- a/include/asm-x86/futex.h +++ b/include/asm-x86/futex.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_FUTEX_H -#define _ASM_X86_FUTEX_H +#ifndef ASM_X86__FUTEX_H +#define ASM_X86__FUTEX_H #ifdef __KERNEL__ @@ -25,7 +25,7 @@ asm volatile("1:\tmovl %2, %0\n" \ "\tmovl\t%0, %3\n" \ "\t" insn "\n" \ - "2:\tlock; cmpxchgl %3, %2\n" \ + "2:\t" LOCK_PREFIX "cmpxchgl %3, %2\n" \ "\tjnz\t1b\n" \ "3:\t.section .fixup,\"ax\"\n" \ "4:\tmov\t%5, %1\n" \ @@ -64,7 +64,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_ADD: - __futex_atomic_op1("lock; xaddl %0, %2", ret, oldval, + __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_OR: @@ -122,7 +122,7 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - asm volatile("1:\tlock; cmpxchgl %3, %1\n" + asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n" "2:\t.section .fixup, \"ax\"\n" "3:\tmov %2, %0\n" "\tjmp 2b\n" @@ -137,4 +137,4 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, } #endif -#endif +#endif /* ASM_X86__FUTEX_H */ diff --git a/include/asm-x86/gart.h b/include/asm-x86/gart.h index 3f62a83887f3..baa54faba892 100644 --- a/include/asm-x86/gart.h +++ b/include/asm-x86/gart.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_GART_H -#define _ASM_X8664_GART_H 1 +#ifndef ASM_X86__GART_H +#define ASM_X86__GART_H #include <asm/e820.h> @@ -52,15 +52,15 @@ static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size) return 0; if (aper_base + aper_size > 0x100000000ULL) { - printk(KERN_ERR "Aperture beyond 4GB. Ignoring.\n"); + printk(KERN_INFO "Aperture beyond 4GB. Ignoring.\n"); return 0; } if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { - printk(KERN_ERR "Aperture pointing to e820 RAM. Ignoring.\n"); + printk(KERN_INFO "Aperture pointing to e820 RAM. Ignoring.\n"); return 0; } if (aper_size < min_size) { - printk(KERN_ERR "Aperture too small (%d MB) than (%d MB)\n", + printk(KERN_INFO "Aperture too small (%d MB) than (%d MB)\n", aper_size>>20, min_size>>20); return 0; } @@ -68,4 +68,4 @@ static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size) return 1; } -#endif +#endif /* ASM_X86__GART_H */ diff --git a/include/asm-x86/genapic_32.h b/include/asm-x86/genapic_32.h index 754d635f90ff..34280f027664 100644 --- a/include/asm-x86/genapic_32.h +++ b/include/asm-x86/genapic_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_GENAPIC_H -#define _ASM_GENAPIC_H 1 +#ifndef ASM_X86__GENAPIC_32_H +#define ASM_X86__GENAPIC_32_H #include <asm/mpspec.h> @@ -121,4 +121,4 @@ enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; #define uv_system_init() do {} while (0) -#endif +#endif /* ASM_X86__GENAPIC_32_H */ diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index a47d63129135..25097a8cc5ef 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_GENAPIC_H -#define _ASM_GENAPIC_H 1 +#ifndef ASM_X86__GENAPIC_64_H +#define ASM_X86__GENAPIC_64_H /* * Copyright 2004 James Cleverdon, IBM. @@ -47,4 +47,4 @@ extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); extern void setup_apic_routing(void); -#endif +#endif /* ASM_X86__GENAPIC_64_H */ diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h index 2c1cda0b8a86..3f3444be2638 100644 --- a/include/asm-x86/geode.h +++ b/include/asm-x86/geode.h @@ -7,8 +7,8 @@ * as published by the Free Software Foundation. */ -#ifndef _ASM_GEODE_H_ -#define _ASM_GEODE_H_ +#ifndef ASM_X86__GEODE_H +#define ASM_X86__GEODE_H #include <asm/processor.h> #include <linux/io.h> @@ -250,4 +250,4 @@ extern int __init mfgpt_timer_setup(void); static inline int mfgpt_timer_setup(void) { return 0; } #endif -#endif +#endif /* ASM_X86__GEODE_H */ diff --git a/include/asm-x86/gpio.h b/include/asm-x86/gpio.h index c4c91b37c104..497fb980d962 100644 --- a/include/asm-x86/gpio.h +++ b/include/asm-x86/gpio.h @@ -53,4 +53,4 @@ static inline int irq_to_gpio(unsigned int irq) #endif /* CONFIG_GPIOLIB */ -#endif /* _ASM_I386_GPIO_H */ +#endif /* ASM_X86__GPIO_H */ diff --git a/include/asm-x86/hardirq_32.h b/include/asm-x86/hardirq_32.h index 4f85f0f4b563..700fe230d919 100644 --- a/include/asm-x86/hardirq_32.h +++ b/include/asm-x86/hardirq_32.h @@ -1,5 +1,5 @@ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H +#ifndef ASM_X86__HARDIRQ_32_H +#define ASM_X86__HARDIRQ_32_H #include <linux/threads.h> #include <linux/irq.h> @@ -25,4 +25,4 @@ DECLARE_PER_CPU(irq_cpustat_t, irq_stat); void ack_bad_irq(unsigned int irq); #include <linux/irq_cpustat.h> -#endif /* __ASM_HARDIRQ_H */ +#endif /* ASM_X86__HARDIRQ_32_H */ diff --git a/include/asm-x86/hardirq_64.h b/include/asm-x86/hardirq_64.h index 95d5e090ed89..f8bd2919a8ce 100644 --- a/include/asm-x86/hardirq_64.h +++ b/include/asm-x86/hardirq_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_HARDIRQ_H -#define __ASM_HARDIRQ_H +#ifndef ASM_X86__HARDIRQ_64_H +#define ASM_X86__HARDIRQ_64_H #include <linux/threads.h> #include <linux/irq.h> @@ -20,4 +20,4 @@ extern void ack_bad_irq(unsigned int irq); -#endif /* __ASM_HARDIRQ_H */ +#endif /* ASM_X86__HARDIRQ_64_H */ diff --git a/include/asm-x86/highmem.h b/include/asm-x86/highmem.h index 4514b16cc723..bc3f6a280316 100644 --- a/include/asm-x86/highmem.h +++ b/include/asm-x86/highmem.h @@ -15,8 +15,8 @@ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> */ -#ifndef _ASM_HIGHMEM_H -#define _ASM_HIGHMEM_H +#ifndef ASM_X86__HIGHMEM_H +#define ASM_X86__HIGHMEM_H #ifdef __KERNEL__ @@ -79,4 +79,4 @@ extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn, #endif /* __KERNEL__ */ -#endif /* _ASM_HIGHMEM_H */ +#endif /* ASM_X86__HIGHMEM_H */ diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h index 82f1ac641bd7..cbbbb6d4dd32 100644 --- a/include/asm-x86/hpet.h +++ b/include/asm-x86/hpet.h @@ -1,5 +1,5 @@ -#ifndef ASM_X86_HPET_H -#define ASM_X86_HPET_H +#ifndef ASM_X86__HPET_H +#define ASM_X86__HPET_H #ifdef CONFIG_HPET_TIMER @@ -90,4 +90,4 @@ static inline int is_hpet_enabled(void) { return 0; } #define hpet_readl(a) 0 #endif -#endif /* ASM_X86_HPET_H */ +#endif /* ASM_X86__HPET_H */ diff --git a/include/asm-x86/hugetlb.h b/include/asm-x86/hugetlb.h index 439a9acc132d..0b7ec5dc0884 100644 --- a/include/asm-x86/hugetlb.h +++ b/include/asm-x86/hugetlb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_HUGETLB_H -#define _ASM_X86_HUGETLB_H +#ifndef ASM_X86__HUGETLB_H +#define ASM_X86__HUGETLB_H #include <asm/page.h> @@ -90,4 +90,4 @@ static inline void arch_release_hugepage(struct page *page) { } -#endif /* _ASM_X86_HUGETLB_H */ +#endif /* ASM_X86__HUGETLB_H */ diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h index edd0b95f14d0..65997b15d56a 100644 --- a/include/asm-x86/hw_irq.h +++ b/include/asm-x86/hw_irq.h @@ -1,5 +1,5 @@ -#ifndef _ASM_HW_IRQ_H -#define _ASM_HW_IRQ_H +#ifndef ASM_X86__HW_IRQ_H +#define ASM_X86__HW_IRQ_H /* * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar @@ -93,6 +93,26 @@ extern asmlinkage void qic_reschedule_interrupt(void); extern asmlinkage void qic_enable_irq_interrupt(void); extern asmlinkage void qic_call_function_interrupt(void); +/* SMP */ +extern void smp_apic_timer_interrupt(struct pt_regs *); +#ifdef CONFIG_X86_32 +extern void smp_spurious_interrupt(struct pt_regs *); +extern void smp_error_interrupt(struct pt_regs *); +#else +extern asmlinkage void smp_spurious_interrupt(void); +extern asmlinkage void smp_error_interrupt(void); +#endif +#ifdef CONFIG_X86_SMP +extern void smp_reschedule_interrupt(struct pt_regs *); +extern void smp_call_function_interrupt(struct pt_regs *); +extern void smp_call_function_single_interrupt(struct pt_regs *); +#ifdef CONFIG_X86_32 +extern void smp_invalidate_interrupt(struct pt_regs *); +#else +extern asmlinkage void smp_invalidate_interrupt(struct pt_regs *); +#endif +#endif + #ifdef CONFIG_X86_32 extern void (*const interrupt[NR_IRQS])(void); #else @@ -112,4 +132,4 @@ static inline void __setup_vector_irq(int cpu) {} #endif /* !ASSEMBLY_ */ -#endif +#endif /* ASM_X86__HW_IRQ_H */ diff --git a/include/asm-x86/hypertransport.h b/include/asm-x86/hypertransport.h index d2bbd238b3e1..cc011a3bc1c2 100644 --- a/include/asm-x86/hypertransport.h +++ b/include/asm-x86/hypertransport.h @@ -1,5 +1,5 @@ -#ifndef ASM_HYPERTRANSPORT_H -#define ASM_HYPERTRANSPORT_H +#ifndef ASM_X86__HYPERTRANSPORT_H +#define ASM_X86__HYPERTRANSPORT_H /* * Constants for x86 Hypertransport Interrupts. @@ -42,4 +42,4 @@ #define HT_IRQ_HIGH_DEST_ID(v) \ ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK) -#endif /* ASM_HYPERTRANSPORT_H */ +#endif /* ASM_X86__HYPERTRANSPORT_H */ diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index 56d00e31aec0..1ecdc3ed96e4 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -7,8 +7,8 @@ * x86-64 work by Andi Kleen 2002 */ -#ifndef _ASM_X86_I387_H -#define _ASM_X86_I387_H +#ifndef ASM_X86__I387_H +#define ASM_X86__I387_H #include <linux/sched.h> #include <linux/kernel_stat.h> @@ -25,6 +25,7 @@ extern void mxcsr_feature_mask_init(void); extern int init_fpu(struct task_struct *child); extern asmlinkage void math_state_restore(void); extern void init_thread_xstate(void); +extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); extern user_regset_active_fn fpregs_active, xfpregs_active; extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get; @@ -336,4 +337,4 @@ static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk) } } -#endif /* _ASM_X86_I387_H */ +#endif /* ASM_X86__I387_H */ diff --git a/include/asm-x86/i8253.h b/include/asm-x86/i8253.h index b51c0487fc41..15a5b530044e 100644 --- a/include/asm-x86/i8253.h +++ b/include/asm-x86/i8253.h @@ -1,5 +1,5 @@ -#ifndef __ASM_I8253_H__ -#define __ASM_I8253_H__ +#ifndef ASM_X86__I8253_H +#define ASM_X86__I8253_H /* i8253A PIT registers */ #define PIT_MODE 0x43 @@ -15,4 +15,4 @@ extern void setup_pit_timer(void); #define inb_pit inb_p #define outb_pit outb_p -#endif /* __ASM_I8253_H__ */ +#endif /* ASM_X86__I8253_H */ diff --git a/include/asm-x86/i8259.h b/include/asm-x86/i8259.h index 2f98df91f1f2..c586559a6957 100644 --- a/include/asm-x86/i8259.h +++ b/include/asm-x86/i8259.h @@ -1,5 +1,5 @@ -#ifndef __ASM_I8259_H__ -#define __ASM_I8259_H__ +#ifndef ASM_X86__I8259_H +#define ASM_X86__I8259_H #include <linux/delay.h> @@ -57,4 +57,4 @@ static inline void outb_pic(unsigned char value, unsigned int port) extern struct irq_chip i8259A_chip; -#endif /* __ASM_I8259_H__ */ +#endif /* ASM_X86__I8259_H */ diff --git a/include/asm-x86/ia32.h b/include/asm-x86/ia32.h index 55d3abe5276f..f932f7ad51dd 100644 --- a/include/asm-x86/ia32.h +++ b/include/asm-x86/ia32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_IA32_H -#define _ASM_X86_64_IA32_H +#ifndef ASM_X86__IA32_H +#define ASM_X86__IA32_H #ifdef CONFIG_IA32_EMULATION @@ -167,4 +167,4 @@ extern void ia32_pick_mmap_layout(struct mm_struct *mm); #endif /* !CONFIG_IA32_SUPPORT */ -#endif +#endif /* ASM_X86__IA32_H */ diff --git a/include/asm-x86/ia32_unistd.h b/include/asm-x86/ia32_unistd.h index 61cea9e7c5c1..dbd887d8a5a5 100644 --- a/include/asm-x86/ia32_unistd.h +++ b/include/asm-x86/ia32_unistd.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_IA32_UNISTD_H_ -#define _ASM_X86_64_IA32_UNISTD_H_ +#ifndef ASM_X86__IA32_UNISTD_H +#define ASM_X86__IA32_UNISTD_H /* * This file contains the system call numbers of the ia32 port, @@ -15,4 +15,4 @@ #define __NR_ia32_sigreturn 119 #define __NR_ia32_rt_sigreturn 173 -#endif /* _ASM_X86_64_IA32_UNISTD_H_ */ +#endif /* ASM_X86__IA32_UNISTD_H */ diff --git a/include/asm-x86/idle.h b/include/asm-x86/idle.h index cbb649123612..baa3f783d27d 100644 --- a/include/asm-x86/idle.h +++ b/include/asm-x86/idle.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_IDLE_H -#define _ASM_X86_64_IDLE_H 1 +#ifndef ASM_X86__IDLE_H +#define ASM_X86__IDLE_H #define IDLE_START 1 #define IDLE_END 2 @@ -12,4 +12,4 @@ void exit_idle(void); void c1e_remove_cpu(int cpu); -#endif +#endif /* ASM_X86__IDLE_H */ diff --git a/include/asm-x86/intel_arch_perfmon.h b/include/asm-x86/intel_arch_perfmon.h index fa0fd068bc2e..07c03c6c9a16 100644 --- a/include/asm-x86/intel_arch_perfmon.h +++ b/include/asm-x86/intel_arch_perfmon.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_INTEL_ARCH_PERFMON_H -#define _ASM_X86_INTEL_ARCH_PERFMON_H +#ifndef ASM_X86__INTEL_ARCH_PERFMON_H +#define ASM_X86__INTEL_ARCH_PERFMON_H #define MSR_ARCH_PERFMON_PERFCTR0 0xc1 #define MSR_ARCH_PERFMON_PERFCTR1 0xc2 @@ -28,4 +28,4 @@ union cpuid10_eax { unsigned int full; }; -#endif /* _ASM_X86_INTEL_ARCH_PERFMON_H */ +#endif /* ASM_X86__INTEL_ARCH_PERFMON_H */ diff --git a/include/asm-x86/io.h b/include/asm-x86/io.h index 0f954dc89cb3..72b7719523bf 100644 --- a/include/asm-x86/io.h +++ b/include/asm-x86/io.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_IO_H -#define _ASM_X86_IO_H +#ifndef ASM_X86__IO_H +#define ASM_X86__IO_H #define ARCH_HAS_IOREMAP_WC @@ -73,6 +73,8 @@ build_mmio_write(__writeq, "q", unsigned long, "r", ) #define writeq writeq #endif +extern int iommu_bio_merge; + #ifdef CONFIG_X86_32 # include "io_32.h" #else @@ -99,4 +101,4 @@ extern void early_iounmap(void *addr, unsigned long size); extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); -#endif /* _ASM_X86_IO_H */ +#endif /* ASM_X86__IO_H */ diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h index e876d89ac156..4f7d878bda18 100644 --- a/include/asm-x86/io_32.h +++ b/include/asm-x86/io_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IO_H -#define _ASM_IO_H +#ifndef ASM_X86__IO_32_H +#define ASM_X86__IO_32_H #include <linux/string.h> #include <linux/compiler.h> @@ -281,4 +281,4 @@ BUILDIO(b, b, char) BUILDIO(w, w, short) BUILDIO(l, , int) -#endif +#endif /* ASM_X86__IO_32_H */ diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h index 22995c5c5adc..64429e9431a8 100644 --- a/include/asm-x86/io_64.h +++ b/include/asm-x86/io_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IO_H -#define _ASM_IO_H +#ifndef ASM_X86__IO_64_H +#define ASM_X86__IO_64_H /* @@ -235,7 +235,6 @@ void memset_io(volatile void __iomem *a, int b, size_t c); #define flush_write_buffers() -extern int iommu_bio_merge; #define BIO_VMERGE_BOUNDARY iommu_bio_merge /* @@ -245,4 +244,4 @@ extern int iommu_bio_merge; #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__IO_64_H */ diff --git a/include/asm-x86/io_apic.h b/include/asm-x86/io_apic.h index 14f82bbcb5fd..be62847ab07e 100644 --- a/include/asm-x86/io_apic.h +++ b/include/asm-x86/io_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_IO_APIC_H -#define __ASM_IO_APIC_H +#ifndef ASM_X86__IO_APIC_H +#define ASM_X86__IO_APIC_H #include <linux/types.h> #include <asm/mpspec.h> @@ -189,4 +189,4 @@ static const int timer_through_8259 = 0; static inline void ioapic_init_mappings(void) { } #endif -#endif +#endif /* ASM_X86__IO_APIC_H */ diff --git a/include/asm-x86/ioctls.h b/include/asm-x86/ioctls.h index c0c338bd4068..336603512399 100644 --- a/include/asm-x86/ioctls.h +++ b/include/asm-x86/ioctls.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_IOCTLS_H -#define _ASM_X86_IOCTLS_H +#ifndef ASM_X86__IOCTLS_H +#define ASM_X86__IOCTLS_H #include <asm/ioctl.h> @@ -85,4 +85,4 @@ #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ -#endif +#endif /* ASM_X86__IOCTLS_H */ diff --git a/include/asm-x86/iommu.h b/include/asm-x86/iommu.h index 5f888cc5be49..e86f44148c66 100644 --- a/include/asm-x86/iommu.h +++ b/include/asm-x86/iommu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_IOMMU_H -#define _ASM_X8664_IOMMU_H 1 +#ifndef ASM_X86__IOMMU_H +#define ASM_X86__IOMMU_H extern void pci_iommu_shutdown(void); extern void no_iommu_init(void); @@ -42,4 +42,4 @@ static inline void gart_iommu_hole_init(void) } #endif -#endif +#endif /* ASM_X86__IOMMU_H */ diff --git a/include/asm-x86/ipcbuf.h b/include/asm-x86/ipcbuf.h index ee678fd51594..910304fbdc8f 100644 --- a/include/asm-x86/ipcbuf.h +++ b/include/asm-x86/ipcbuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_IPCBUF_H -#define _ASM_X86_IPCBUF_H +#ifndef ASM_X86__IPCBUF_H +#define ASM_X86__IPCBUF_H /* * The ipc64_perm structure for x86 architecture. @@ -25,4 +25,4 @@ struct ipc64_perm { unsigned long __unused2; }; -#endif /* _ASM_X86_IPCBUF_H */ +#endif /* ASM_X86__IPCBUF_H */ diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h index bb1c09f7a76c..c1b226797518 100644 --- a/include/asm-x86/ipi.h +++ b/include/asm-x86/ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_IPI_H -#define __ASM_IPI_H +#ifndef ASM_X86__IPI_H +#define ASM_X86__IPI_H /* * Copyright 2004 James Cleverdon, IBM. @@ -129,4 +129,4 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) local_irq_restore(flags); } -#endif /* __ASM_IPI_H */ +#endif /* ASM_X86__IPI_H */ diff --git a/include/asm-x86/irq.h b/include/asm-x86/irq.h index 1a2925757317..1e5f2909c1db 100644 --- a/include/asm-x86/irq.h +++ b/include/asm-x86/irq.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_H -#define _ASM_IRQ_H +#ifndef ASM_X86__IRQ_H +#define ASM_X86__IRQ_H /* * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar * @@ -47,4 +47,4 @@ extern void native_init_IRQ(void); /* Interrupt vector management */ extern DECLARE_BITMAP(used_vectors, NR_VECTORS); -#endif /* _ASM_IRQ_H */ +#endif /* ASM_X86__IRQ_H */ diff --git a/include/asm-x86/irq_regs_32.h b/include/asm-x86/irq_regs_32.h index 3368b20c0b48..316a3b258871 100644 --- a/include/asm-x86/irq_regs_32.h +++ b/include/asm-x86/irq_regs_32.h @@ -4,8 +4,8 @@ * * Jeremy Fitzhardinge <jeremy@goop.org> */ -#ifndef _ASM_I386_IRQ_REGS_H -#define _ASM_I386_IRQ_REGS_H +#ifndef ASM_X86__IRQ_REGS_32_H +#define ASM_X86__IRQ_REGS_32_H #include <asm/percpu.h> @@ -26,4 +26,4 @@ static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs) return old_regs; } -#endif /* _ASM_I386_IRQ_REGS_H */ +#endif /* ASM_X86__IRQ_REGS_32_H */ diff --git a/include/asm-x86/irq_vectors.h b/include/asm-x86/irq_vectors.h index a48c7f2dbdc0..c5d2d767a1f3 100644 --- a/include/asm-x86/irq_vectors.h +++ b/include/asm-x86/irq_vectors.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_VECTORS_H -#define _ASM_IRQ_VECTORS_H +#ifndef ASM_X86__IRQ_VECTORS_H +#define ASM_X86__IRQ_VECTORS_H #include <linux/threads.h> @@ -179,4 +179,4 @@ #define VIC_CPU_BOOT_ERRATA_CPI (VIC_CPI_LEVEL0 + 8) -#endif /* _ASM_IRQ_VECTORS_H */ +#endif /* ASM_X86__IRQ_VECTORS_H */ diff --git a/include/asm-x86/ist.h b/include/asm-x86/ist.h index 6ec6ceed95a7..35a2fe9bc921 100644 --- a/include/asm-x86/ist.h +++ b/include/asm-x86/ist.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IST_H -#define _ASM_IST_H +#ifndef ASM_X86__IST_H +#define ASM_X86__IST_H /* * Include file for the interface to IST BIOS @@ -31,4 +31,4 @@ struct ist_info { extern struct ist_info ist_info; #endif /* __KERNEL__ */ -#endif /* _ASM_IST_H */ +#endif /* ASM_X86__IST_H */ diff --git a/include/asm-x86/k8.h b/include/asm-x86/k8.h index 452e2b696ff4..2bbaf4370a55 100644 --- a/include/asm-x86/k8.h +++ b/include/asm-x86/k8.h @@ -1,5 +1,5 @@ -#ifndef _ASM_K8_H -#define _ASM_K8_H 1 +#ifndef ASM_X86__K8_H +#define ASM_X86__K8_H #include <linux/pci.h> @@ -12,4 +12,4 @@ extern int cache_k8_northbridges(void); extern void k8_flush_garts(void); extern int k8_scan_nodes(unsigned long start, unsigned long end); -#endif +#endif /* ASM_X86__K8_H */ diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h index 96651bb59ba1..5ec3ad3e825c 100644 --- a/include/asm-x86/kdebug.h +++ b/include/asm-x86/kdebug.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_KDEBUG_H -#define _ASM_X86_KDEBUG_H +#ifndef ASM_X86__KDEBUG_H +#define ASM_X86__KDEBUG_H #include <linux/notifier.h> @@ -35,4 +35,4 @@ extern void show_regs(struct pt_regs *regs); extern unsigned long oops_begin(void); extern void oops_end(unsigned long, struct pt_regs *, int signr); -#endif +#endif /* ASM_X86__KDEBUG_H */ diff --git a/include/asm-x86/kexec.h b/include/asm-x86/kexec.h index 4246ab7dc988..ea09600d6129 100644 --- a/include/asm-x86/kexec.h +++ b/include/asm-x86/kexec.h @@ -1,5 +1,5 @@ -#ifndef _KEXEC_H -#define _KEXEC_H +#ifndef ASM_X86__KEXEC_H +#define ASM_X86__KEXEC_H #ifdef CONFIG_X86_32 # define PA_CONTROL_PAGE 0 @@ -172,4 +172,4 @@ relocate_kernel(unsigned long indirection_page, #endif /* __ASSEMBLY__ */ -#endif /* _KEXEC_H */ +#endif /* ASM_X86__KEXEC_H */ diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h index 94d63db10365..d283863354de 100644 --- a/include/asm-x86/kgdb.h +++ b/include/asm-x86/kgdb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_KGDB_H_ -#define _ASM_KGDB_H_ +#ifndef ASM_X86__KGDB_H +#define ASM_X86__KGDB_H /* * Copyright (C) 2001-2004 Amit S. Kale @@ -76,4 +76,4 @@ static inline void arch_kgdb_breakpoint(void) #define BREAK_INSTR_SIZE 1 #define CACHE_FLUSH_IS_SAFE 1 -#endif /* _ASM_KGDB_H_ */ +#endif /* ASM_X86__KGDB_H */ diff --git a/include/asm-x86/kmap_types.h b/include/asm-x86/kmap_types.h index 5f4174132a22..89f44493e643 100644 --- a/include/asm-x86/kmap_types.h +++ b/include/asm-x86/kmap_types.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_KMAP_TYPES_H -#define _ASM_X86_KMAP_TYPES_H +#ifndef ASM_X86__KMAP_TYPES_H +#define ASM_X86__KMAP_TYPES_H #if defined(CONFIG_X86_32) && defined(CONFIG_DEBUG_HIGHMEM) # define D(n) __KM_FENCE_##n , @@ -26,4 +26,4 @@ D(13) KM_TYPE_NR #undef D -#endif +#endif /* ASM_X86__KMAP_TYPES_H */ diff --git a/include/asm-x86/kprobes.h b/include/asm-x86/kprobes.h index 54980b0b3892..bd8407863c13 100644 --- a/include/asm-x86/kprobes.h +++ b/include/asm-x86/kprobes.h @@ -1,5 +1,5 @@ -#ifndef _ASM_KPROBES_H -#define _ASM_KPROBES_H +#ifndef ASM_X86__KPROBES_H +#define ASM_X86__KPROBES_H /* * Kernel Probes (KProbes) * @@ -94,4 +94,4 @@ static inline void restore_interrupts(struct pt_regs *regs) extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); -#endif /* _ASM_KPROBES_H */ +#endif /* ASM_X86__KPROBES_H */ diff --git a/include/asm-x86/kvm.h b/include/asm-x86/kvm.h index 6f1840812e59..78e954db1e7f 100644 --- a/include/asm-x86/kvm.h +++ b/include/asm-x86/kvm.h @@ -1,5 +1,5 @@ -#ifndef __LINUX_KVM_X86_H -#define __LINUX_KVM_X86_H +#ifndef ASM_X86__KVM_H +#define ASM_X86__KVM_H /* * KVM x86 specific structures and definitions @@ -230,4 +230,4 @@ struct kvm_pit_state { #define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14) #define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15) -#endif +#endif /* ASM_X86__KVM_H */ diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index c2e34c275900..69794547f514 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -1,4 +1,4 @@ -#/* +/* * Kernel-based Virtual Machine driver for Linux * * This header defines architecture specific interfaces, x86 version @@ -8,8 +8,8 @@ * */ -#ifndef ASM_KVM_HOST_H -#define ASM_KVM_HOST_H +#ifndef ASM_X86__KVM_HOST_H +#define ASM_X86__KVM_HOST_H #include <linux/types.h> #include <linux/mm.h> @@ -735,4 +735,4 @@ asmlinkage void kvm_handle_fault_on_reboot(void); int kvm_unmap_hva(struct kvm *kvm, unsigned long hva); int kvm_age_hva(struct kvm *kvm, unsigned long hva); -#endif +#endif /* ASM_X86__KVM_HOST_H */ diff --git a/include/asm-x86/kvm_para.h b/include/asm-x86/kvm_para.h index 76f392146daa..30054fded4fb 100644 --- a/include/asm-x86/kvm_para.h +++ b/include/asm-x86/kvm_para.h @@ -1,5 +1,5 @@ -#ifndef __X86_KVM_PARA_H -#define __X86_KVM_PARA_H +#ifndef ASM_X86__KVM_PARA_H +#define ASM_X86__KVM_PARA_H /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It * should be used to determine that a VM is running under KVM. @@ -144,4 +144,4 @@ static inline unsigned int kvm_arch_para_features(void) #endif -#endif +#endif /* ASM_X86__KVM_PARA_H */ diff --git a/include/asm-x86/kvm_x86_emulate.h b/include/asm-x86/kvm_x86_emulate.h index 4e8c1e48d91d..e2d9b030c1ac 100644 --- a/include/asm-x86/kvm_x86_emulate.h +++ b/include/asm-x86/kvm_x86_emulate.h @@ -8,8 +8,8 @@ * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 */ -#ifndef __X86_EMULATE_H__ -#define __X86_EMULATE_H__ +#ifndef ASM_X86__KVM_X86_EMULATE_H +#define ASM_X86__KVM_X86_EMULATE_H struct x86_emulate_ctxt; @@ -181,4 +181,4 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops); -#endif /* __X86_EMULATE_H__ */ +#endif /* ASM_X86__KVM_X86_EMULATE_H */ diff --git a/include/asm-x86/ldt.h b/include/asm-x86/ldt.h index 20c597242b53..a5228504d867 100644 --- a/include/asm-x86/ldt.h +++ b/include/asm-x86/ldt.h @@ -3,8 +3,8 @@ * * Definitions of structures used with the modify_ldt system call. */ -#ifndef _ASM_X86_LDT_H -#define _ASM_X86_LDT_H +#ifndef ASM_X86__LDT_H +#define ASM_X86__LDT_H /* Maximum number of LDT entries supported. */ #define LDT_ENTRIES 8192 @@ -37,4 +37,4 @@ struct user_desc { #define MODIFY_LDT_CONTENTS_CODE 2 #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__LDT_H */ diff --git a/include/asm-x86/lguest.h b/include/asm-x86/lguest.h index be4a7247fa2b..7505e947ed27 100644 --- a/include/asm-x86/lguest.h +++ b/include/asm-x86/lguest.h @@ -1,5 +1,5 @@ -#ifndef _X86_LGUEST_H -#define _X86_LGUEST_H +#ifndef ASM_X86__LGUEST_H +#define ASM_X86__LGUEST_H #define GDT_ENTRY_LGUEST_CS 10 #define GDT_ENTRY_LGUEST_DS 11 @@ -91,4 +91,4 @@ static inline void lguest_set_ts(void) #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__LGUEST_H */ diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h index a3241f28e34a..8f034ba4b53e 100644 --- a/include/asm-x86/lguest_hcall.h +++ b/include/asm-x86/lguest_hcall.h @@ -1,6 +1,6 @@ /* Architecture specific portion of the lguest hypercalls */ -#ifndef _X86_LGUEST_HCALL_H -#define _X86_LGUEST_HCALL_H +#ifndef ASM_X86__LGUEST_HCALL_H +#define ASM_X86__LGUEST_HCALL_H #define LHCALL_FLUSH_ASYNC 0 #define LHCALL_LGUEST_INIT 1 @@ -68,4 +68,4 @@ struct hcall_args { }; #endif /* !__ASSEMBLY__ */ -#endif /* _I386_LGUEST_HCALL_H */ +#endif /* ASM_X86__LGUEST_HCALL_H */ diff --git a/include/asm-x86/linkage.h b/include/asm-x86/linkage.h index 64e444f8e85b..42d8b62ee8ab 100644 --- a/include/asm-x86/linkage.h +++ b/include/asm-x86/linkage.h @@ -1,5 +1,5 @@ -#ifndef __ASM_LINKAGE_H -#define __ASM_LINKAGE_H +#ifndef ASM_X86__LINKAGE_H +#define ASM_X86__LINKAGE_H #undef notrace #define notrace __attribute__((no_instrument_function)) @@ -57,5 +57,5 @@ #define __ALIGN_STR ".align 16,0x90" #endif -#endif +#endif /* ASM_X86__LINKAGE_H */ diff --git a/include/asm-x86/local.h b/include/asm-x86/local.h index 330a72496abd..ae91994fd6c9 100644 --- a/include/asm-x86/local.h +++ b/include/asm-x86/local.h @@ -1,5 +1,5 @@ -#ifndef _ARCH_LOCAL_H -#define _ARCH_LOCAL_H +#ifndef ASM_X86__LOCAL_H +#define ASM_X86__LOCAL_H #include <linux/percpu.h> @@ -232,4 +232,4 @@ static inline long local_sub_return(long i, local_t *l) #define __cpu_local_add(i, l) cpu_local_add((i), (l)) #define __cpu_local_sub(i, l) cpu_local_sub((i), (l)) -#endif /* _ARCH_LOCAL_H */ +#endif /* ASM_X86__LOCAL_H */ diff --git a/include/asm-x86/mach-bigsmp/mach_apic.h b/include/asm-x86/mach-bigsmp/mach_apic.h index c3b9dc6970c9..05362d44a3ee 100644 --- a/include/asm-x86/mach-bigsmp/mach_apic.h +++ b/include/asm-x86/mach-bigsmp/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_BIGSMP__MACH_APIC_H +#define ASM_X86__MACH_BIGSMP__MACH_APIC_H #define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu)) #define esr_disable (1) @@ -141,4 +141,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_BIGSMP__MACH_APIC_H */ diff --git a/include/asm-x86/mach-bigsmp/mach_apicdef.h b/include/asm-x86/mach-bigsmp/mach_apicdef.h index a58ab5a75c8c..811935d9d49b 100644 --- a/include/asm-x86/mach-bigsmp/mach_apicdef.h +++ b/include/asm-x86/mach-bigsmp/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_BIGSMP__MACH_APICDEF_H +#define ASM_X86__MACH_BIGSMP__MACH_APICDEF_H #define APIC_ID_MASK (0xFF<<24) @@ -10,4 +10,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_BIGSMP__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-bigsmp/mach_ipi.h b/include/asm-x86/mach-bigsmp/mach_ipi.h index 9404c535b7ec..b1b0f966a009 100644 --- a/include/asm-x86/mach-bigsmp/mach_ipi.h +++ b/include/asm-x86/mach-bigsmp/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_BIGSMP__MACH_IPI_H +#define ASM_X86__MACH_BIGSMP__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_BIGSMP__MACH_IPI_H */ diff --git a/include/asm-x86/mach-default/apm.h b/include/asm-x86/mach-default/apm.h index 989f34c37d32..2aa61b54fbd5 100644 --- a/include/asm-x86/mach-default/apm.h +++ b/include/asm-x86/mach-default/apm.h @@ -3,8 +3,8 @@ * Split out from apm.c by Osamu Tomita <tomita@cinet.co.jp> */ -#ifndef _ASM_APM_H -#define _ASM_APM_H +#ifndef ASM_X86__MACH_DEFAULT__APM_H +#define ASM_X86__MACH_DEFAULT__APM_H #ifdef APM_ZERO_SEGS # define APM_DO_ZERO_SEGS \ @@ -70,4 +70,4 @@ static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in, return error; } -#endif /* _ASM_APM_H */ +#endif /* ASM_X86__MACH_DEFAULT__APM_H */ diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h index f3226b9a6b82..b615f40736be 100644 --- a/include/asm-x86/mach-default/mach_apic.h +++ b/include/asm-x86/mach-default/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_APIC_H +#define ASM_X86__MACH_DEFAULT__MACH_APIC_H #ifdef CONFIG_X86_LOCAL_APIC @@ -138,4 +138,4 @@ static inline void enable_apic_mode(void) } #endif /* CONFIG_X86_LOCAL_APIC */ -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_APIC_H */ diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h index e4b29ba37de6..936704f816d6 100644 --- a/include/asm-x86/mach-default/mach_apicdef.h +++ b/include/asm-x86/mach-default/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_APICDEF_H +#define ASM_X86__MACH_DEFAULT__MACH_APICDEF_H #include <asm/apic.h> @@ -21,4 +21,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) #endif -#endif +#endif /* ASM_X86__MACH_DEFAULT__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-default/mach_ipi.h b/include/asm-x86/mach-default/mach_ipi.h index be323364e68f..674bc7e50c35 100644 --- a/include/asm-x86/mach-default/mach_ipi.h +++ b/include/asm-x86/mach-default/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_IPI_H +#define ASM_X86__MACH_DEFAULT__MACH_IPI_H /* Avoid include hell */ #define NMI_VECTOR 0x02 @@ -61,4 +61,4 @@ static inline void send_IPI_all(int vector) } #endif -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_IPI_H */ diff --git a/include/asm-x86/mach-default/mach_mpparse.h b/include/asm-x86/mach-default/mach_mpparse.h index d14108505bb8..9c381f2815ac 100644 --- a/include/asm-x86/mach-default/mach_mpparse.h +++ b/include/asm-x86/mach-default/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H +#define ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) @@ -14,4 +14,4 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) } -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-default/mach_mpspec.h b/include/asm-x86/mach-default/mach_mpspec.h index 51c9a9775932..d77646f011f1 100644 --- a/include/asm-x86/mach-default/mach_mpspec.h +++ b/include/asm-x86/mach-default/mach_mpspec.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPSPEC_H -#define __ASM_MACH_MPSPEC_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H +#define ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H #define MAX_IRQ_SOURCES 256 @@ -9,4 +9,4 @@ #define MAX_MP_BUSSES 32 #endif -#endif /* __ASM_MACH_MPSPEC_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_MPSPEC_H */ diff --git a/include/asm-x86/mach-default/mach_timer.h b/include/asm-x86/mach-default/mach_timer.h index 4b76e536cd98..990b15833834 100644 --- a/include/asm-x86/mach-default/mach_timer.h +++ b/include/asm-x86/mach-default/mach_timer.h @@ -10,8 +10,8 @@ * directly because of the awkward 8-bit access mechanism of the 82C54 * device. */ -#ifndef _MACH_TIMER_H -#define _MACH_TIMER_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_TIMER_H +#define ASM_X86__MACH_DEFAULT__MACH_TIMER_H #define CALIBRATE_TIME_MSEC 30 /* 30 msecs */ #define CALIBRATE_LATCH \ @@ -45,4 +45,4 @@ static inline void mach_countup(unsigned long *count_p) *count_p = count; } -#endif /* !_MACH_TIMER_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_TIMER_H */ diff --git a/include/asm-x86/mach-default/mach_traps.h b/include/asm-x86/mach-default/mach_traps.h index 2fe7705c0484..de9ac3f5c4ce 100644 --- a/include/asm-x86/mach-default/mach_traps.h +++ b/include/asm-x86/mach-default/mach_traps.h @@ -2,8 +2,8 @@ * Machine specific NMI handling for generic. * Split out from traps.c by Osamu Tomita <tomita@cinet.co.jp> */ -#ifndef _MACH_TRAPS_H -#define _MACH_TRAPS_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_TRAPS_H +#define ASM_X86__MACH_DEFAULT__MACH_TRAPS_H #include <asm/mc146818rtc.h> @@ -36,4 +36,4 @@ static inline void reassert_nmi(void) unlock_cmos(); } -#endif /* !_MACH_TRAPS_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_TRAPS_H */ diff --git a/include/asm-x86/mach-default/mach_wakecpu.h b/include/asm-x86/mach-default/mach_wakecpu.h index 3ebb17893aa5..361b810f5160 100644 --- a/include/asm-x86/mach-default/mach_wakecpu.h +++ b/include/asm-x86/mach-default/mach_wakecpu.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_WAKECPU_H -#define __ASM_MACH_WAKECPU_H +#ifndef ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H +#define ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H /* * This file copes with machines that wakeup secondary CPUs by the @@ -39,4 +39,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} #endif -#endif /* __ASM_MACH_WAKECPU_H */ +#endif /* ASM_X86__MACH_DEFAULT__MACH_WAKECPU_H */ diff --git a/include/asm-x86/mach-es7000/mach_apic.h b/include/asm-x86/mach-es7000/mach_apic.h index 0a3fdf930672..c1f6f682d619 100644 --- a/include/asm-x86/mach-es7000/mach_apic.h +++ b/include/asm-x86/mach-es7000/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_ES7000__MACH_APIC_H +#define ASM_X86__MACH_ES7000__MACH_APIC_H #define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu) #define esr_disable (1) @@ -191,4 +191,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_APIC_H */ diff --git a/include/asm-x86/mach-es7000/mach_apicdef.h b/include/asm-x86/mach-es7000/mach_apicdef.h index a58ab5a75c8c..a07e56744028 100644 --- a/include/asm-x86/mach-es7000/mach_apicdef.h +++ b/include/asm-x86/mach-es7000/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_ES7000__MACH_APICDEF_H +#define ASM_X86__MACH_ES7000__MACH_APICDEF_H #define APIC_ID_MASK (0xFF<<24) @@ -10,4 +10,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_ES7000__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-es7000/mach_ipi.h b/include/asm-x86/mach-es7000/mach_ipi.h index 5e61bd220b06..3a21240e03dc 100644 --- a/include/asm-x86/mach-es7000/mach_ipi.h +++ b/include/asm-x86/mach-es7000/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_ES7000__MACH_IPI_H +#define ASM_X86__MACH_ES7000__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -21,4 +21,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_IPI_H */ diff --git a/include/asm-x86/mach-es7000/mach_mpparse.h b/include/asm-x86/mach-es7000/mach_mpparse.h index ef26d3523625..befde24705b7 100644 --- a/include/asm-x86/mach-es7000/mach_mpparse.h +++ b/include/asm-x86/mach-es7000/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_ES7000__MACH_MPPARSE_H +#define ASM_X86__MACH_ES7000__MACH_MPPARSE_H #include <linux/acpi.h> @@ -26,4 +26,4 @@ static inline int es7000_check_dsdt(void) } #endif -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-es7000/mach_wakecpu.h b/include/asm-x86/mach-es7000/mach_wakecpu.h index 84ff58314501..97c776ce13f2 100644 --- a/include/asm-x86/mach-es7000/mach_wakecpu.h +++ b/include/asm-x86/mach-es7000/mach_wakecpu.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_WAKECPU_H -#define __ASM_MACH_WAKECPU_H +#ifndef ASM_X86__MACH_ES7000__MACH_WAKECPU_H +#define ASM_X86__MACH_ES7000__MACH_WAKECPU_H /* * This file copes with machines that wakeup secondary CPUs by the @@ -56,4 +56,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} #endif -#endif /* __ASM_MACH_WAKECPU_H */ +#endif /* ASM_X86__MACH_ES7000__MACH_WAKECPU_H */ diff --git a/include/asm-x86/mach-generic/gpio.h b/include/asm-x86/mach-generic/gpio.h index 5305dcb96df2..6ce0f7786ef8 100644 --- a/include/asm-x86/mach-generic/gpio.h +++ b/include/asm-x86/mach-generic/gpio.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_GENERIC_GPIO_H -#define __ASM_MACH_GENERIC_GPIO_H +#ifndef ASM_X86__MACH_GENERIC__GPIO_H +#define ASM_X86__MACH_GENERIC__GPIO_H int gpio_request(unsigned gpio, const char *label); void gpio_free(unsigned gpio); @@ -12,4 +12,4 @@ int irq_to_gpio(unsigned irq); #include <asm-generic/gpio.h> /* cansleep wrappers */ -#endif /* __ASM_MACH_GENERIC_GPIO_H */ +#endif /* ASM_X86__MACH_GENERIC__GPIO_H */ diff --git a/include/asm-x86/mach-generic/irq_vectors_limits.h b/include/asm-x86/mach-generic/irq_vectors_limits.h index 890ce3f5e09a..f7870e1a220d 100644 --- a/include/asm-x86/mach-generic/irq_vectors_limits.h +++ b/include/asm-x86/mach-generic/irq_vectors_limits.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_VECTORS_LIMITS_H -#define _ASM_IRQ_VECTORS_LIMITS_H +#ifndef ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H +#define ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H /* * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs, @@ -11,4 +11,4 @@ #define NR_IRQS 224 #define NR_IRQ_VECTORS 1024 -#endif /* _ASM_IRQ_VECTORS_LIMITS_H */ +#endif /* ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H */ diff --git a/include/asm-x86/mach-generic/mach_apic.h b/include/asm-x86/mach-generic/mach_apic.h index 6eff343e1233..5d010c6881dd 100644 --- a/include/asm-x86/mach-generic/mach_apic.h +++ b/include/asm-x86/mach-generic/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_GENERIC__MACH_APIC_H +#define ASM_X86__MACH_GENERIC__MACH_APIC_H #include <asm/genapic.h> @@ -29,4 +29,4 @@ extern void generic_bigsmp_probe(void); -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_GENERIC__MACH_APIC_H */ diff --git a/include/asm-x86/mach-generic/mach_apicdef.h b/include/asm-x86/mach-generic/mach_apicdef.h index 28ed98972ca8..1657f38b8f27 100644 --- a/include/asm-x86/mach-generic/mach_apicdef.h +++ b/include/asm-x86/mach-generic/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef _GENAPIC_MACH_APICDEF_H -#define _GENAPIC_MACH_APICDEF_H 1 +#ifndef ASM_X86__MACH_GENERIC__MACH_APICDEF_H +#define ASM_X86__MACH_GENERIC__MACH_APICDEF_H #ifndef APIC_DEFINITION #include <asm/genapic.h> @@ -8,4 +8,4 @@ #define APIC_ID_MASK (genapic->apic_id_mask) #endif -#endif +#endif /* ASM_X86__MACH_GENERIC__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-generic/mach_ipi.h b/include/asm-x86/mach-generic/mach_ipi.h index 441b0fe3ed1d..f67433dbd65f 100644 --- a/include/asm-x86/mach-generic/mach_ipi.h +++ b/include/asm-x86/mach-generic/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef _MACH_IPI_H -#define _MACH_IPI_H 1 +#ifndef ASM_X86__MACH_GENERIC__MACH_IPI_H +#define ASM_X86__MACH_GENERIC__MACH_IPI_H #include <asm/genapic.h> @@ -7,4 +7,4 @@ #define send_IPI_allbutself (genapic->send_IPI_allbutself) #define send_IPI_all (genapic->send_IPI_all) -#endif +#endif /* ASM_X86__MACH_GENERIC__MACH_IPI_H */ diff --git a/include/asm-x86/mach-generic/mach_mpparse.h b/include/asm-x86/mach-generic/mach_mpparse.h index 586cadbf3787..3115564e557c 100644 --- a/include/asm-x86/mach-generic/mach_mpparse.h +++ b/include/asm-x86/mach-generic/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef _MACH_MPPARSE_H -#define _MACH_MPPARSE_H 1 +#ifndef ASM_X86__MACH_GENERIC__MACH_MPPARSE_H +#define ASM_X86__MACH_GENERIC__MACH_MPPARSE_H extern int mps_oem_check(struct mp_config_table *mpc, char *oem, @@ -7,4 +7,4 @@ extern int mps_oem_check(struct mp_config_table *mpc, char *oem, extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id); -#endif +#endif /* ASM_X86__MACH_GENERIC__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-generic/mach_mpspec.h b/include/asm-x86/mach-generic/mach_mpspec.h index c83c120be538..6061b153613e 100644 --- a/include/asm-x86/mach-generic/mach_mpspec.h +++ b/include/asm-x86/mach-generic/mach_mpspec.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPSPEC_H -#define __ASM_MACH_MPSPEC_H +#ifndef ASM_X86__MACH_GENERIC__MACH_MPSPEC_H +#define ASM_X86__MACH_GENERIC__MACH_MPSPEC_H #define MAX_IRQ_SOURCES 256 @@ -9,4 +9,4 @@ extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid); -#endif /* __ASM_MACH_MPSPEC_H */ +#endif /* ASM_X86__MACH_GENERIC__MACH_MPSPEC_H */ diff --git a/include/asm-x86/mach-numaq/mach_apic.h b/include/asm-x86/mach-numaq/mach_apic.h index d802465e026a..7a0d39edfcfa 100644 --- a/include/asm-x86/mach-numaq/mach_apic.h +++ b/include/asm-x86/mach-numaq/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_APIC_H +#define ASM_X86__MACH_NUMAQ__MACH_APIC_H #include <asm/io.h> #include <linux/mmzone.h> @@ -135,4 +135,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return cpuid_apic >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_APIC_H */ diff --git a/include/asm-x86/mach-numaq/mach_apicdef.h b/include/asm-x86/mach-numaq/mach_apicdef.h index bf439d0690f5..f870ec5f7782 100644 --- a/include/asm-x86/mach-numaq/mach_apicdef.h +++ b/include/asm-x86/mach-numaq/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_APICDEF_H +#define ASM_X86__MACH_NUMAQ__MACH_APICDEF_H #define APIC_ID_MASK (0xF<<24) @@ -11,4 +11,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_NUMAQ__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-numaq/mach_ipi.h b/include/asm-x86/mach-numaq/mach_ipi.h index c6044488e9e6..1e835823f4bc 100644 --- a/include/asm-x86/mach-numaq/mach_ipi.h +++ b/include/asm-x86/mach-numaq/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_IPI_H +#define ASM_X86__MACH_NUMAQ__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_IPI_H */ diff --git a/include/asm-x86/mach-numaq/mach_mpparse.h b/include/asm-x86/mach-numaq/mach_mpparse.h index 626aef6b155f..74ade184920b 100644 --- a/include/asm-x86/mach-numaq/mach_mpparse.h +++ b/include/asm-x86/mach-numaq/mach_mpparse.h @@ -1,7 +1,7 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H +#define ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid); -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_MPPARSE_H */ diff --git a/include/asm-x86/mach-numaq/mach_wakecpu.h b/include/asm-x86/mach-numaq/mach_wakecpu.h index 00530041a991..0db8cea643c0 100644 --- a/include/asm-x86/mach-numaq/mach_wakecpu.h +++ b/include/asm-x86/mach-numaq/mach_wakecpu.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_WAKECPU_H -#define __ASM_MACH_WAKECPU_H +#ifndef ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H +#define ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H /* This file copes with machines that wakeup secondary CPUs by NMIs */ @@ -40,4 +40,4 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) #define inquire_remote_apic(apicid) {} -#endif /* __ASM_MACH_WAKECPU_H */ +#endif /* ASM_X86__MACH_NUMAQ__MACH_WAKECPU_H */ diff --git a/include/asm-x86/mach-rdc321x/gpio.h b/include/asm-x86/mach-rdc321x/gpio.h index acce0b7d397b..94b6cdf532e2 100644 --- a/include/asm-x86/mach-rdc321x/gpio.h +++ b/include/asm-x86/mach-rdc321x/gpio.h @@ -1,5 +1,7 @@ -#ifndef _RDC321X_GPIO_H -#define _RDC321X_GPIO_H +#ifndef ASM_X86__MACH_RDC321X__GPIO_H +#define ASM_X86__MACH_RDC321X__GPIO_H + +#include <linux/kernel.h> extern int rdc_gpio_get_value(unsigned gpio); extern void rdc_gpio_set_value(unsigned gpio, int value); @@ -18,6 +20,7 @@ static inline int gpio_request(unsigned gpio, const char *label) static inline void gpio_free(unsigned gpio) { + might_sleep(); rdc_gpio_free(gpio); } @@ -54,4 +57,4 @@ static inline int irq_to_gpio(unsigned irq) /* For cansleep */ #include <asm-generic/gpio.h> -#endif /* _RDC321X_GPIO_H_ */ +#endif /* ASM_X86__MACH_RDC321X__GPIO_H */ diff --git a/include/asm-x86/mach-summit/irq_vectors_limits.h b/include/asm-x86/mach-summit/irq_vectors_limits.h index 890ce3f5e09a..22f376ad68e1 100644 --- a/include/asm-x86/mach-summit/irq_vectors_limits.h +++ b/include/asm-x86/mach-summit/irq_vectors_limits.h @@ -1,5 +1,5 @@ -#ifndef _ASM_IRQ_VECTORS_LIMITS_H -#define _ASM_IRQ_VECTORS_LIMITS_H +#ifndef ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H +#define ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H /* * For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs, @@ -11,4 +11,4 @@ #define NR_IRQS 224 #define NR_IRQ_VECTORS 1024 -#endif /* _ASM_IRQ_VECTORS_LIMITS_H */ +#endif /* ASM_X86__MACH_SUMMIT__IRQ_VECTORS_LIMITS_H */ diff --git a/include/asm-x86/mach-summit/mach_apic.h b/include/asm-x86/mach-summit/mach_apic.h index c47e2ab5c5ca..7a66758d701d 100644 --- a/include/asm-x86/mach-summit/mach_apic.h +++ b/include/asm-x86/mach-summit/mach_apic.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_APIC_H +#define ASM_X86__MACH_SUMMIT__MACH_APIC_H #include <asm/smp.h> @@ -182,4 +182,4 @@ static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) return hard_smp_processor_id() >> index_msb; } -#endif /* __ASM_MACH_APIC_H */ +#endif /* ASM_X86__MACH_SUMMIT__MACH_APIC_H */ diff --git a/include/asm-x86/mach-summit/mach_apicdef.h b/include/asm-x86/mach-summit/mach_apicdef.h index a58ab5a75c8c..d4bc8590c4f6 100644 --- a/include/asm-x86/mach-summit/mach_apicdef.h +++ b/include/asm-x86/mach-summit/mach_apicdef.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_APICDEF_H +#define ASM_X86__MACH_SUMMIT__MACH_APICDEF_H #define APIC_ID_MASK (0xFF<<24) @@ -10,4 +10,4 @@ static inline unsigned get_apic_id(unsigned long x) #define GET_APIC_ID(x) get_apic_id(x) -#endif +#endif /* ASM_X86__MACH_SUMMIT__MACH_APICDEF_H */ diff --git a/include/asm-x86/mach-summit/mach_ipi.h b/include/asm-x86/mach-summit/mach_ipi.h index 9404c535b7ec..a3b31c528d90 100644 --- a/include/asm-x86/mach-summit/mach_ipi.h +++ b/include/asm-x86/mach-summit/mach_ipi.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_IPI_H +#define ASM_X86__MACH_SUMMIT__MACH_IPI_H void send_IPI_mask_sequence(cpumask_t mask, int vector); @@ -22,4 +22,4 @@ static inline void send_IPI_all(int vector) send_IPI_mask(cpu_online_map, vector); } -#endif /* __ASM_MACH_IPI_H */ +#endif /* ASM_X86__MACH_SUMMIT__MACH_IPI_H */ diff --git a/include/asm-x86/mach-summit/mach_mpparse.h b/include/asm-x86/mach-summit/mach_mpparse.h index fdf591701339..92396f28772b 100644 --- a/include/asm-x86/mach-summit/mach_mpparse.h +++ b/include/asm-x86/mach-summit/mach_mpparse.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MACH_MPPARSE_H -#define __ASM_MACH_MPPARSE_H +#ifndef ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H +#define ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H #include <mach_apic.h> #include <asm/tsc.h> @@ -107,4 +107,4 @@ static inline int is_WPEG(struct rio_detail *rio){ rio->type == LookOutAWPEG || rio->type == LookOutBWPEG); } -#endif /* __ASM_MACH_MPPARSE_H */ +#endif /* ASM_X86__MACH_SUMMIT__MACH_MPPARSE_H */ diff --git a/include/asm-x86/math_emu.h b/include/asm-x86/math_emu.h index 9bf4ae93ab10..5768d8e95c8c 100644 --- a/include/asm-x86/math_emu.h +++ b/include/asm-x86/math_emu.h @@ -1,5 +1,5 @@ -#ifndef _I386_MATH_EMU_H -#define _I386_MATH_EMU_H +#ifndef ASM_X86__MATH_EMU_H +#define ASM_X86__MATH_EMU_H /* This structure matches the layout of the data saved to the stack following a device-not-present interrupt, part of it saved @@ -28,4 +28,4 @@ struct info { long ___vm86_fs; long ___vm86_gs; }; -#endif +#endif /* ASM_X86__MATH_EMU_H */ diff --git a/include/asm-x86/mc146818rtc.h b/include/asm-x86/mc146818rtc.h index daf1ccde77af..a995f33176cd 100644 --- a/include/asm-x86/mc146818rtc.h +++ b/include/asm-x86/mc146818rtc.h @@ -1,8 +1,8 @@ /* * Machine dependent access functions for RTC registers. */ -#ifndef _ASM_MC146818RTC_H -#define _ASM_MC146818RTC_H +#ifndef ASM_X86__MC146818RTC_H +#define ASM_X86__MC146818RTC_H #include <asm/io.h> #include <asm/system.h> @@ -101,4 +101,4 @@ extern unsigned long mach_get_cmos_time(void); #define RTC_IRQ 8 -#endif /* _ASM_MC146818RTC_H */ +#endif /* ASM_X86__MC146818RTC_H */ diff --git a/include/asm-x86/mca.h b/include/asm-x86/mca.h index 09adf2eac4dc..60d1ed287b13 100644 --- a/include/asm-x86/mca.h +++ b/include/asm-x86/mca.h @@ -1,8 +1,8 @@ /* -*- mode: c; c-basic-offset: 8 -*- */ /* Platform specific MCA defines */ -#ifndef _ASM_MCA_H -#define _ASM_MCA_H +#ifndef ASM_X86__MCA_H +#define ASM_X86__MCA_H /* Maximal number of MCA slots - actually, some machines have less, but * they all have sufficient number of POS registers to cover 8. @@ -40,4 +40,4 @@ */ #define MCA_NUMADAPTERS (MCA_MAX_SLOT_NR+3) -#endif +#endif /* ASM_X86__MCA_H */ diff --git a/include/asm-x86/mca_dma.h b/include/asm-x86/mca_dma.h index c3dca6edc6b1..49f22be237d2 100644 --- a/include/asm-x86/mca_dma.h +++ b/include/asm-x86/mca_dma.h @@ -1,5 +1,5 @@ -#ifndef MCA_DMA_H -#define MCA_DMA_H +#ifndef ASM_X86__MCA_DMA_H +#define ASM_X86__MCA_DMA_H #include <asm/io.h> #include <linux/ioport.h> @@ -198,4 +198,4 @@ static inline void mca_set_dma_mode(unsigned int dmanr, unsigned int mode) outb(mode, MCA_DMA_REG_EXE); } -#endif /* MCA_DMA_H */ +#endif /* ASM_X86__MCA_DMA_H */ diff --git a/include/asm-x86/mce.h b/include/asm-x86/mce.h index 531eaa587455..036133eaf744 100644 --- a/include/asm-x86/mce.h +++ b/include/asm-x86/mce.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MCE_H -#define _ASM_X86_MCE_H +#ifndef ASM_X86__MCE_H +#define ASM_X86__MCE_H #ifdef __x86_64__ @@ -127,4 +127,4 @@ extern void restart_mce(void); #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__MCE_H */ diff --git a/include/asm-x86/mman.h b/include/asm-x86/mman.h index 90bc4108a4fd..4ef28e6de383 100644 --- a/include/asm-x86/mman.h +++ b/include/asm-x86/mman.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MMAN_H -#define _ASM_X86_MMAN_H +#ifndef ASM_X86__MMAN_H +#define ASM_X86__MMAN_H #include <asm-generic/mman.h> @@ -17,4 +17,4 @@ #define MCL_CURRENT 1 /* lock all current mappings */ #define MCL_FUTURE 2 /* lock all future mappings */ -#endif /* _ASM_X86_MMAN_H */ +#endif /* ASM_X86__MMAN_H */ diff --git a/include/asm-x86/mmconfig.h b/include/asm-x86/mmconfig.h index e293ab81e850..fb79b1cf5d07 100644 --- a/include/asm-x86/mmconfig.h +++ b/include/asm-x86/mmconfig.h @@ -1,5 +1,5 @@ -#ifndef _ASM_MMCONFIG_H -#define _ASM_MMCONFIG_H +#ifndef ASM_X86__MMCONFIG_H +#define ASM_X86__MMCONFIG_H #ifdef CONFIG_PCI_MMCONFIG extern void __cpuinit fam10h_check_enable_mmcfg(void); @@ -9,4 +9,4 @@ static inline void fam10h_check_enable_mmcfg(void) { } static inline void check_enable_amd_mmconf_dmi(void) { } #endif -#endif +#endif /* ASM_X86__MMCONFIG_H */ diff --git a/include/asm-x86/mmu.h b/include/asm-x86/mmu.h index 00e88679e11f..9d5aff14334a 100644 --- a/include/asm-x86/mmu.h +++ b/include/asm-x86/mmu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MMU_H -#define _ASM_X86_MMU_H +#ifndef ASM_X86__MMU_H +#define ASM_X86__MMU_H #include <linux/spinlock.h> #include <linux/mutex.h> @@ -7,14 +7,9 @@ /* * The x86 doesn't have a mmu context, but * we put the segment information here. - * - * cpu_vm_mask is used to optimize ldt flushing. */ typedef struct { void *ldt; -#ifdef CONFIG_X86_64 - rwlock_t ldtlock; -#endif int size; struct mutex lock; void *vdso; @@ -28,4 +23,4 @@ static inline void leave_mm(int cpu) } #endif -#endif /* _ASM_X86_MMU_H */ +#endif /* ASM_X86__MMU_H */ diff --git a/include/asm-x86/mmu_context.h b/include/asm-x86/mmu_context.h index fac57014e7c6..8ec940bfd079 100644 --- a/include/asm-x86/mmu_context.h +++ b/include/asm-x86/mmu_context.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_MMU_CONTEXT_H -#define __ASM_X86_MMU_CONTEXT_H +#ifndef ASM_X86__MMU_CONTEXT_H +#define ASM_X86__MMU_CONTEXT_H #include <asm/desc.h> #include <asm/atomic.h> @@ -34,4 +34,4 @@ do { \ } while (0); -#endif /* __ASM_X86_MMU_CONTEXT_H */ +#endif /* ASM_X86__MMU_CONTEXT_H */ diff --git a/include/asm-x86/mmu_context_32.h b/include/asm-x86/mmu_context_32.h index 824fc575c6d8..cce6f6e4afd6 100644 --- a/include/asm-x86/mmu_context_32.h +++ b/include/asm-x86/mmu_context_32.h @@ -1,5 +1,5 @@ -#ifndef __I386_SCHED_H -#define __I386_SCHED_H +#ifndef ASM_X86__MMU_CONTEXT_32_H +#define ASM_X86__MMU_CONTEXT_32_H static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { @@ -53,4 +53,4 @@ static inline void switch_mm(struct mm_struct *prev, #define deactivate_mm(tsk, mm) \ asm("movl %0,%%gs": :"r" (0)); -#endif +#endif /* ASM_X86__MMU_CONTEXT_32_H */ diff --git a/include/asm-x86/mmu_context_64.h b/include/asm-x86/mmu_context_64.h index c7000634ccae..26758673c828 100644 --- a/include/asm-x86/mmu_context_64.h +++ b/include/asm-x86/mmu_context_64.h @@ -1,5 +1,5 @@ -#ifndef __X86_64_MMU_CONTEXT_H -#define __X86_64_MMU_CONTEXT_H +#ifndef ASM_X86__MMU_CONTEXT_64_H +#define ASM_X86__MMU_CONTEXT_64_H #include <asm/pda.h> @@ -51,4 +51,4 @@ do { \ asm volatile("movl %0,%%fs"::"r"(0)); \ } while (0) -#endif +#endif /* ASM_X86__MMU_CONTEXT_64_H */ diff --git a/include/asm-x86/mmx.h b/include/asm-x86/mmx.h index 940881218ff8..2e7299bb3653 100644 --- a/include/asm-x86/mmx.h +++ b/include/asm-x86/mmx.h @@ -1,5 +1,5 @@ -#ifndef _ASM_MMX_H -#define _ASM_MMX_H +#ifndef ASM_X86__MMX_H +#define ASM_X86__MMX_H /* * MMX 3Dnow! helper operations @@ -11,4 +11,4 @@ extern void *_mmx_memcpy(void *to, const void *from, size_t size); extern void mmx_clear_page(void *page); extern void mmx_copy_page(void *to, void *from); -#endif +#endif /* ASM_X86__MMX_H */ diff --git a/include/asm-x86/mmzone_32.h b/include/asm-x86/mmzone_32.h index 5862e6460658..121b65d61d86 100644 --- a/include/asm-x86/mmzone_32.h +++ b/include/asm-x86/mmzone_32.h @@ -3,8 +3,8 @@ * */ -#ifndef _ASM_MMZONE_H_ -#define _ASM_MMZONE_H_ +#ifndef ASM_X86__MMZONE_32_H +#define ASM_X86__MMZONE_32_H #include <asm/smp.h> @@ -131,4 +131,4 @@ static inline int pfn_valid(int pfn) }) #endif /* CONFIG_NEED_MULTIPLE_NODES */ -#endif /* _ASM_MMZONE_H_ */ +#endif /* ASM_X86__MMZONE_32_H */ diff --git a/include/asm-x86/mmzone_64.h b/include/asm-x86/mmzone_64.h index 594bd0dc1d08..626b03a14875 100644 --- a/include/asm-x86/mmzone_64.h +++ b/include/asm-x86/mmzone_64.h @@ -1,8 +1,8 @@ /* K8 NUMA support */ /* Copyright 2002,2003 by Andi Kleen, SuSE Labs */ /* 2.5 Version loosely based on the NUMAQ Code by Pat Gaughen. */ -#ifndef _ASM_X86_64_MMZONE_H -#define _ASM_X86_64_MMZONE_H 1 +#ifndef ASM_X86__MMZONE_64_H +#define ASM_X86__MMZONE_64_H #ifdef CONFIG_NUMA @@ -49,4 +49,4 @@ extern int early_pfn_to_nid(unsigned long pfn); #endif #endif -#endif +#endif /* ASM_X86__MMZONE_64_H */ diff --git a/include/asm-x86/module.h b/include/asm-x86/module.h index bfedb247871c..48dc3e0c07d9 100644 --- a/include/asm-x86/module.h +++ b/include/asm-x86/module.h @@ -1,5 +1,5 @@ -#ifndef _ASM_MODULE_H -#define _ASM_MODULE_H +#ifndef ASM_X86__MODULE_H +#define ASM_X86__MODULE_H /* x86_32/64 are simple */ struct mod_arch_specific {}; @@ -79,4 +79,4 @@ struct mod_arch_specific {}; # define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE #endif -#endif /* _ASM_MODULE_H */ +#endif /* ASM_X86__MODULE_H */ diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h index b6995e567fcc..118da365e371 100644 --- a/include/asm-x86/mpspec.h +++ b/include/asm-x86/mpspec.h @@ -1,5 +1,5 @@ -#ifndef _AM_X86_MPSPEC_H -#define _AM_X86_MPSPEC_H +#ifndef ASM_X86__MPSPEC_H +#define ASM_X86__MPSPEC_H #include <linux/init.h> @@ -141,4 +141,4 @@ static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map) extern physid_mask_t phys_cpu_present_map; -#endif +#endif /* ASM_X86__MPSPEC_H */ diff --git a/include/asm-x86/mpspec_def.h b/include/asm-x86/mpspec_def.h index 38d1e73b49e4..79166b048012 100644 --- a/include/asm-x86/mpspec_def.h +++ b/include/asm-x86/mpspec_def.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MPSPEC_DEF_H -#define __ASM_MPSPEC_DEF_H +#ifndef ASM_X86__MPSPEC_DEF_H +#define ASM_X86__MPSPEC_DEF_H /* * Structure definitions for SMP machines following the @@ -177,4 +177,4 @@ enum mp_bustype { MP_BUS_PCI, MP_BUS_MCA, }; -#endif +#endif /* ASM_X86__MPSPEC_DEF_H */ diff --git a/include/asm-x86/msgbuf.h b/include/asm-x86/msgbuf.h index 7e4e9481f51c..1b538c907a3d 100644 --- a/include/asm-x86/msgbuf.h +++ b/include/asm-x86/msgbuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_MSGBUF_H -#define _ASM_X86_MSGBUF_H +#ifndef ASM_X86__MSGBUF_H +#define ASM_X86__MSGBUF_H /* * The msqid64_ds structure for i386 architecture. @@ -36,4 +36,4 @@ struct msqid64_ds { unsigned long __unused5; }; -#endif /* _ASM_X86_MSGBUF_H */ +#endif /* ASM_X86__MSGBUF_H */ diff --git a/include/asm-x86/msidef.h b/include/asm-x86/msidef.h index 296f29ce426d..3139666a94fa 100644 --- a/include/asm-x86/msidef.h +++ b/include/asm-x86/msidef.h @@ -1,5 +1,5 @@ -#ifndef ASM_MSIDEF_H -#define ASM_MSIDEF_H +#ifndef ASM_X86__MSIDEF_H +#define ASM_X86__MSIDEF_H /* * Constants for Intel APIC based MSI messages. @@ -48,4 +48,4 @@ #define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \ MSI_ADDR_DEST_ID_MASK) -#endif /* ASM_MSIDEF_H */ +#endif /* ASM_X86__MSIDEF_H */ diff --git a/include/asm-x86/msr-index.h b/include/asm-x86/msr-index.h index 44bce773012e..3052f058ab06 100644 --- a/include/asm-x86/msr-index.h +++ b/include/asm-x86/msr-index.h @@ -1,5 +1,5 @@ -#ifndef __ASM_MSR_INDEX_H -#define __ASM_MSR_INDEX_H +#ifndef ASM_X86__MSR_INDEX_H +#define ASM_X86__MSR_INDEX_H /* CPU model specific register (MSR) numbers */ @@ -310,4 +310,4 @@ /* Geode defined MSRs */ #define MSR_GEODE_BUSCONT_CONF0 0x00001900 -#endif /* __ASM_MSR_INDEX_H */ +#endif /* ASM_X86__MSR_INDEX_H */ diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index 2362cfda1fbc..530af1f6389e 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_MSR_H_ -#define __ASM_X86_MSR_H_ +#ifndef ASM_X86__MSR_H +#define ASM_X86__MSR_H #include <asm/msr-index.h> @@ -63,6 +63,22 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, return EAX_EDX_VAL(val, low, high); } +static inline unsigned long long native_read_msr_amd_safe(unsigned int msr, + int *err) +{ + DECLARE_ARGS(val, low, high); + + asm volatile("2: rdmsr ; xor %0,%0\n" + "1:\n\t" + ".section .fixup,\"ax\"\n\t" + "3: mov %3,%0 ; jmp 1b\n\t" + ".previous\n\t" + _ASM_EXTABLE(2b, 3b) + : "=r" (*err), EAX_EDX_RET(val, low, high) + : "c" (msr), "D" (0x9c5a203a), "i" (-EFAULT)); + return EAX_EDX_VAL(val, low, high); +} + static inline void native_write_msr(unsigned int msr, unsigned low, unsigned high) { @@ -158,6 +174,13 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p) *p = native_read_msr_safe(msr, &err); return err; } +static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) +{ + int err; + + *p = native_read_msr_amd_safe(msr, &err); + return err; +} #define rdtscl(low) \ ((low) = (u32)native_read_tsc()) @@ -221,4 +244,4 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__MSR_H */ diff --git a/include/asm-x86/mtrr.h b/include/asm-x86/mtrr.h index a69a01a51729..23a7f83da953 100644 --- a/include/asm-x86/mtrr.h +++ b/include/asm-x86/mtrr.h @@ -20,8 +20,8 @@ The postal address is: Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. */ -#ifndef _ASM_X86_MTRR_H -#define _ASM_X86_MTRR_H +#ifndef ASM_X86__MTRR_H +#define ASM_X86__MTRR_H #include <linux/ioctl.h> #include <linux/errno.h> @@ -170,4 +170,4 @@ struct mtrr_gentry32 { #endif /* __KERNEL__ */ -#endif /* _ASM_X86_MTRR_H */ +#endif /* ASM_X86__MTRR_H */ diff --git a/include/asm-x86/mutex_32.h b/include/asm-x86/mutex_32.h index 73e928ef5f03..25c16d8ba3c7 100644 --- a/include/asm-x86/mutex_32.h +++ b/include/asm-x86/mutex_32.h @@ -6,8 +6,8 @@ * * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> */ -#ifndef _ASM_MUTEX_H -#define _ASM_MUTEX_H +#ifndef ASM_X86__MUTEX_32_H +#define ASM_X86__MUTEX_32_H #include <asm/alternative.h> @@ -122,4 +122,4 @@ static inline int __mutex_fastpath_trylock(atomic_t *count, #endif } -#endif +#endif /* ASM_X86__MUTEX_32_H */ diff --git a/include/asm-x86/mutex_64.h b/include/asm-x86/mutex_64.h index f3fae9becb38..918ba21ab9d9 100644 --- a/include/asm-x86/mutex_64.h +++ b/include/asm-x86/mutex_64.h @@ -6,8 +6,8 @@ * * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> */ -#ifndef _ASM_MUTEX_H -#define _ASM_MUTEX_H +#ifndef ASM_X86__MUTEX_64_H +#define ASM_X86__MUTEX_64_H /** * __mutex_fastpath_lock - decrement and call function if negative @@ -97,4 +97,4 @@ static inline int __mutex_fastpath_trylock(atomic_t *count, return 0; } -#endif +#endif /* ASM_X86__MUTEX_64_H */ diff --git a/include/asm-x86/nmi.h b/include/asm-x86/nmi.h index 21f8d0202a82..d5e715f024dc 100644 --- a/include/asm-x86/nmi.h +++ b/include/asm-x86/nmi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_NMI_H_ -#define _ASM_X86_NMI_H_ +#ifndef ASM_X86__NMI_H +#define ASM_X86__NMI_H #include <linux/pm.h> #include <asm/irq.h> @@ -34,6 +34,7 @@ extern void stop_apic_nmi_watchdog(void *); extern void disable_timer_nmi_watchdog(void); extern void enable_timer_nmi_watchdog(void); extern int nmi_watchdog_tick(struct pt_regs *regs, unsigned reason); +extern void cpu_nmi_set_wd_enabled(void); extern atomic_t nmi_active; extern unsigned int nmi_watchdog; @@ -81,4 +82,4 @@ void enable_lapic_nmi_watchdog(void); void stop_nmi(void); void restart_nmi(void); -#endif +#endif /* ASM_X86__NMI_H */ diff --git a/include/asm-x86/nops.h b/include/asm-x86/nops.h index ad0bedd10b89..ae742721ae73 100644 --- a/include/asm-x86/nops.h +++ b/include/asm-x86/nops.h @@ -1,5 +1,5 @@ -#ifndef _ASM_NOPS_H -#define _ASM_NOPS_H 1 +#ifndef ASM_X86__NOPS_H +#define ASM_X86__NOPS_H /* Define nops for use with alternative() */ @@ -115,4 +115,4 @@ #define ASM_NOP_MAX 8 -#endif +#endif /* ASM_X86__NOPS_H */ diff --git a/include/asm-x86/numa_32.h b/include/asm-x86/numa_32.h index 220d7b7707a0..44cb07855c5b 100644 --- a/include/asm-x86/numa_32.h +++ b/include/asm-x86/numa_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_32_NUMA_H -#define _ASM_X86_32_NUMA_H 1 +#ifndef ASM_X86__NUMA_32_H +#define ASM_X86__NUMA_32_H extern int pxm_to_nid(int pxm); extern void numa_remove_cpu(int cpu); @@ -8,4 +8,4 @@ extern void numa_remove_cpu(int cpu); extern void set_highmem_pages_init(void); #endif -#endif /* _ASM_X86_32_NUMA_H */ +#endif /* ASM_X86__NUMA_32_H */ diff --git a/include/asm-x86/numa_64.h b/include/asm-x86/numa_64.h index 3830094434a9..15c990395b02 100644 --- a/include/asm-x86/numa_64.h +++ b/include/asm-x86/numa_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_NUMA_H -#define _ASM_X8664_NUMA_H 1 +#ifndef ASM_X86__NUMA_64_H +#define ASM_X86__NUMA_64_H #include <linux/nodemask.h> #include <asm/apicdef.h> @@ -40,4 +40,4 @@ static inline void numa_add_cpu(int cpu, int node) { } static inline void numa_remove_cpu(int cpu) { } #endif -#endif +#endif /* ASM_X86__NUMA_64_H */ diff --git a/include/asm-x86/numaq.h b/include/asm-x86/numaq.h index 34b92d581fa3..124bf7d4b70a 100644 --- a/include/asm-x86/numaq.h +++ b/include/asm-x86/numaq.h @@ -23,8 +23,8 @@ * Send feedback to <gone@us.ibm.com> */ -#ifndef NUMAQ_H -#define NUMAQ_H +#ifndef ASM_X86__NUMAQ_H +#define ASM_X86__NUMAQ_H #ifdef CONFIG_X86_NUMAQ @@ -165,5 +165,5 @@ static inline int get_memcfg_numaq(void) return 0; } #endif /* CONFIG_X86_NUMAQ */ -#endif /* NUMAQ_H */ +#endif /* ASM_X86__NUMAQ_H */ diff --git a/include/asm-x86/olpc.h b/include/asm-x86/olpc.h index 97d47133486f..d7328b1a05c1 100644 --- a/include/asm-x86/olpc.h +++ b/include/asm-x86/olpc.h @@ -1,7 +1,7 @@ /* OLPC machine specific definitions */ -#ifndef ASM_OLPC_H_ -#define ASM_OLPC_H_ +#ifndef ASM_X86__OLPC_H +#define ASM_X86__OLPC_H #include <asm/geode.h> @@ -129,4 +129,4 @@ extern int olpc_ec_mask_unset(uint8_t bits); #define OLPC_GPIO_LID geode_gpio(26) #define OLPC_GPIO_ECSCI geode_gpio(27) -#endif +#endif /* ASM_X86__OLPC_H */ diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h index 49982110e4d9..79544e6ffb8b 100644 --- a/include/asm-x86/page.h +++ b/include/asm-x86/page.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PAGE_H -#define _ASM_X86_PAGE_H +#ifndef ASM_X86__PAGE_H +#define ASM_X86__PAGE_H #include <linux/const.h> @@ -199,4 +199,4 @@ static inline pteval_t native_pte_flags(pte_t pte) #define __HAVE_ARCH_GATE_AREA 1 #endif /* __KERNEL__ */ -#endif /* _ASM_X86_PAGE_H */ +#endif /* ASM_X86__PAGE_H */ diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h index ab8528793f08..72f7305682c6 100644 --- a/include/asm-x86/page_32.h +++ b/include/asm-x86/page_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PAGE_32_H -#define _ASM_X86_PAGE_32_H +#ifndef ASM_X86__PAGE_32_H +#define ASM_X86__PAGE_32_H /* * This handles the memory map. @@ -89,13 +89,11 @@ extern int nx_enabled; extern unsigned int __VMALLOC_RESERVE; extern int sysctl_legacy_va_layout; -#define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE) -#define MAXMEM (-__PAGE_OFFSET - __VMALLOC_RESERVE) - extern void find_low_pfn_range(void); extern unsigned long init_memory_mapping(unsigned long start, unsigned long end); extern void initmem_init(unsigned long, unsigned long); +extern void free_initmem(void); extern void setup_bootmem_allocator(void); @@ -126,4 +124,4 @@ static inline void copy_page(void *to, void *from) #endif /* CONFIG_X86_3DNOW */ #endif /* !__ASSEMBLY__ */ -#endif /* _ASM_X86_PAGE_32_H */ +#endif /* ASM_X86__PAGE_32_H */ diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h index c6916c83e6b1..5e64acfed0a4 100644 --- a/include/asm-x86/page_64.h +++ b/include/asm-x86/page_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_PAGE_H -#define _X86_64_PAGE_H +#ifndef ASM_X86__PAGE_64_H +#define ASM_X86__PAGE_64_H #define PAGETABLE_LEVELS 4 @@ -91,6 +91,7 @@ extern unsigned long init_memory_mapping(unsigned long start, unsigned long end); extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn); +extern void free_initmem(void); extern void init_extra_mapping_uc(unsigned long phys, unsigned long size); extern void init_extra_mapping_wb(unsigned long phys, unsigned long size); @@ -102,4 +103,4 @@ extern void init_extra_mapping_wb(unsigned long phys, unsigned long size); #endif -#endif /* _X86_64_PAGE_H */ +#endif /* ASM_X86__PAGE_64_H */ diff --git a/include/asm-x86/param.h b/include/asm-x86/param.h index 6f0d0422f4ca..0009cfb11a5f 100644 --- a/include/asm-x86/param.h +++ b/include/asm-x86/param.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PARAM_H -#define _ASM_X86_PARAM_H +#ifndef ASM_X86__PARAM_H +#define ASM_X86__PARAM_H #ifdef __KERNEL__ # define HZ CONFIG_HZ /* Internal kernel timer frequency */ @@ -19,4 +19,4 @@ #define MAXHOSTNAMELEN 64 /* max length of hostname */ -#endif /* _ASM_X86_PARAM_H */ +#endif /* ASM_X86__PARAM_H */ diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index fbbde93f12d6..891971f57d35 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h @@ -1,5 +1,5 @@ -#ifndef __ASM_PARAVIRT_H -#define __ASM_PARAVIRT_H +#ifndef ASM_X86__PARAVIRT_H +#define ASM_X86__PARAVIRT_H /* Various instructions on x86 need to be replaced for * para-virtualization: those hooks are defined here. */ @@ -137,6 +137,7 @@ struct pv_cpu_ops { /* MSR, PMC and TSR operations. err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */ + u64 (*read_msr_amd)(unsigned int msr, int *err); u64 (*read_msr)(unsigned int msr, int *err); int (*write_msr)(unsigned int msr, unsigned low, unsigned high); @@ -257,13 +258,13 @@ struct pv_mmu_ops { * Hooks for allocating/releasing pagetable pages when they're * attached to a pagetable */ - void (*alloc_pte)(struct mm_struct *mm, u32 pfn); - void (*alloc_pmd)(struct mm_struct *mm, u32 pfn); - void (*alloc_pmd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count); - void (*alloc_pud)(struct mm_struct *mm, u32 pfn); - void (*release_pte)(u32 pfn); - void (*release_pmd)(u32 pfn); - void (*release_pud)(u32 pfn); + void (*alloc_pte)(struct mm_struct *mm, unsigned long pfn); + void (*alloc_pmd)(struct mm_struct *mm, unsigned long pfn); + void (*alloc_pmd_clone)(unsigned long pfn, unsigned long clonepfn, unsigned long start, unsigned long count); + void (*alloc_pud)(struct mm_struct *mm, unsigned long pfn); + void (*release_pte)(unsigned long pfn); + void (*release_pmd)(unsigned long pfn); + void (*release_pud)(unsigned long pfn); /* Pagetable manipulation functions */ void (*set_pte)(pte_t *ptep, pte_t pteval); @@ -726,6 +727,10 @@ static inline u64 paravirt_read_msr(unsigned msr, int *err) { return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err); } +static inline u64 paravirt_read_msr_amd(unsigned msr, int *err) +{ + return PVOP_CALL2(u64, pv_cpu_ops.read_msr_amd, msr, err); +} static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high) { return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high); @@ -771,6 +776,13 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p) *p = paravirt_read_msr(msr, &err); return err; } +static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) +{ + int err; + + *p = paravirt_read_msr_amd(msr, &err); + return err; +} static inline u64 paravirt_read_tsc(void) { @@ -993,35 +1005,35 @@ static inline void paravirt_pgd_free(struct mm_struct *mm, pgd_t *pgd) PVOP_VCALL2(pv_mmu_ops.pgd_free, mm, pgd); } -static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned pfn) +static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned long pfn) { PVOP_VCALL2(pv_mmu_ops.alloc_pte, mm, pfn); } -static inline void paravirt_release_pte(unsigned pfn) +static inline void paravirt_release_pte(unsigned long pfn) { PVOP_VCALL1(pv_mmu_ops.release_pte, pfn); } -static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned pfn) +static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn) { PVOP_VCALL2(pv_mmu_ops.alloc_pmd, mm, pfn); } -static inline void paravirt_alloc_pmd_clone(unsigned pfn, unsigned clonepfn, - unsigned start, unsigned count) +static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn, + unsigned long start, unsigned long count) { PVOP_VCALL4(pv_mmu_ops.alloc_pmd_clone, pfn, clonepfn, start, count); } -static inline void paravirt_release_pmd(unsigned pfn) +static inline void paravirt_release_pmd(unsigned long pfn) { PVOP_VCALL1(pv_mmu_ops.release_pmd, pfn); } -static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned pfn) +static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned long pfn) { PVOP_VCALL2(pv_mmu_ops.alloc_pud, mm, pfn); } -static inline void paravirt_release_pud(unsigned pfn) +static inline void paravirt_release_pud(unsigned long pfn) { PVOP_VCALL1(pv_mmu_ops.release_pud, pfn); } @@ -1634,4 +1646,4 @@ static inline unsigned long __raw_local_irq_save(void) #endif /* __ASSEMBLY__ */ #endif /* CONFIG_PARAVIRT */ -#endif /* __ASM_PARAVIRT_H */ +#endif /* ASM_X86__PARAVIRT_H */ diff --git a/include/asm-x86/parport.h b/include/asm-x86/parport.h index 3c4ffeb467e9..2e3dda4dc3d9 100644 --- a/include/asm-x86/parport.h +++ b/include/asm-x86/parport.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PARPORT_H -#define _ASM_X86_PARPORT_H +#ifndef ASM_X86__PARPORT_H +#define ASM_X86__PARPORT_H static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma); static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma) @@ -7,4 +7,4 @@ static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma) return parport_pc_find_isa_ports(autoirq, autodma); } -#endif /* _ASM_X86_PARPORT_H */ +#endif /* ASM_X86__PARPORT_H */ diff --git a/include/asm-x86/pat.h b/include/asm-x86/pat.h index 7edc47307217..482c3e3f9879 100644 --- a/include/asm-x86/pat.h +++ b/include/asm-x86/pat.h @@ -1,5 +1,5 @@ -#ifndef _ASM_PAT_H -#define _ASM_PAT_H +#ifndef ASM_X86__PAT_H +#define ASM_X86__PAT_H #include <linux/types.h> @@ -19,4 +19,4 @@ extern int free_memtype(u64 start, u64 end); extern void pat_disable(char *reason); -#endif +#endif /* ASM_X86__PAT_H */ diff --git a/include/asm-x86/pci-direct.h b/include/asm-x86/pci-direct.h index 80c775d9fe20..da42be07b690 100644 --- a/include/asm-x86/pci-direct.h +++ b/include/asm-x86/pci-direct.h @@ -1,5 +1,5 @@ -#ifndef ASM_PCI_DIRECT_H -#define ASM_PCI_DIRECT_H 1 +#ifndef ASM_X86__PCI_DIRECT_H +#define ASM_X86__PCI_DIRECT_H #include <linux/types.h> @@ -18,4 +18,4 @@ extern int early_pci_allowed(void); extern unsigned int pci_early_dump_regs; extern void early_dump_pci_device(u8 bus, u8 slot, u8 func); extern void early_dump_pci_devices(void); -#endif +#endif /* ASM_X86__PCI_DIRECT_H */ diff --git a/include/asm-x86/pci.h b/include/asm-x86/pci.h index 2db14cf17db8..602583192991 100644 --- a/include/asm-x86/pci.h +++ b/include/asm-x86/pci.h @@ -1,5 +1,5 @@ -#ifndef __x86_PCI_H -#define __x86_PCI_H +#ifndef ASM_X86__PCI_H +#define ASM_X86__PCI_H #include <linux/mm.h> /* for struct page */ #include <linux/types.h> @@ -111,4 +111,4 @@ static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus) } #endif -#endif +#endif /* ASM_X86__PCI_H */ diff --git a/include/asm-x86/pci_32.h b/include/asm-x86/pci_32.h index a50d46851285..3f2288207c0c 100644 --- a/include/asm-x86/pci_32.h +++ b/include/asm-x86/pci_32.h @@ -1,5 +1,5 @@ -#ifndef __i386_PCI_H -#define __i386_PCI_H +#ifndef ASM_X86__PCI_32_H +#define ASM_X86__PCI_32_H #ifdef __KERNEL__ @@ -31,4 +31,4 @@ struct pci_dev; #endif /* __KERNEL__ */ -#endif /* __i386_PCI_H */ +#endif /* ASM_X86__PCI_32_H */ diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h index f330234ffa5c..f72e12d5770e 100644 --- a/include/asm-x86/pci_64.h +++ b/include/asm-x86/pci_64.h @@ -1,5 +1,5 @@ -#ifndef __x8664_PCI_H -#define __x8664_PCI_H +#ifndef ASM_X86__PCI_64_H +#define ASM_X86__PCI_64_H #ifdef __KERNEL__ @@ -63,4 +63,4 @@ extern void pci_iommu_alloc(void); #endif /* __KERNEL__ */ -#endif /* __x8664_PCI_H */ +#endif /* ASM_X86__PCI_64_H */ diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h index b34e9a7cc80b..80860afffbdb 100644 --- a/include/asm-x86/pda.h +++ b/include/asm-x86/pda.h @@ -1,5 +1,5 @@ -#ifndef X86_64_PDA_H -#define X86_64_PDA_H +#ifndef ASM_X86__PDA_H +#define ASM_X86__PDA_H #ifndef __ASSEMBLY__ #include <linux/stddef.h> @@ -134,4 +134,4 @@ do { \ #define PDA_STACKOFFSET (5*8) -#endif +#endif /* ASM_X86__PDA_H */ diff --git a/include/asm-x86/percpu.h b/include/asm-x86/percpu.h index f643a3a92da0..e10a1d0678cf 100644 --- a/include/asm-x86/percpu.h +++ b/include/asm-x86/percpu.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PERCPU_H_ -#define _ASM_X86_PERCPU_H_ +#ifndef ASM_X86__PERCPU_H +#define ASM_X86__PERCPU_H #ifdef CONFIG_X86_64 #include <linux/compiler.h> @@ -215,4 +215,4 @@ do { \ #endif /* !CONFIG_SMP */ -#endif /* _ASM_X86_PERCPU_H_ */ +#endif /* ASM_X86__PERCPU_H */ diff --git a/include/asm-x86/pgalloc.h b/include/asm-x86/pgalloc.h index d63ea431cb3b..3cd23adedae8 100644 --- a/include/asm-x86/pgalloc.h +++ b/include/asm-x86/pgalloc.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PGALLOC_H -#define _ASM_X86_PGALLOC_H +#ifndef ASM_X86__PGALLOC_H +#define ASM_X86__PGALLOC_H #include <linux/threads.h> #include <linux/mm.h> /* for struct page */ @@ -111,4 +111,4 @@ extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud); #endif /* PAGETABLE_LEVELS > 3 */ #endif /* PAGETABLE_LEVELS > 2 */ -#endif /* _ASM_X86_PGALLOC_H */ +#endif /* ASM_X86__PGALLOC_H */ diff --git a/include/asm-x86/pgtable-2level-defs.h b/include/asm-x86/pgtable-2level-defs.h index 0f71c9f13da4..7ec48f4e5347 100644 --- a/include/asm-x86/pgtable-2level-defs.h +++ b/include/asm-x86/pgtable-2level-defs.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_2LEVEL_DEFS_H -#define _I386_PGTABLE_2LEVEL_DEFS_H +#ifndef ASM_X86__PGTABLE_2LEVEL_DEFS_H +#define ASM_X86__PGTABLE_2LEVEL_DEFS_H #define SHARED_KERNEL_PMD 0 @@ -17,4 +17,4 @@ #define PTRS_PER_PTE 1024 -#endif /* _I386_PGTABLE_2LEVEL_DEFS_H */ +#endif /* ASM_X86__PGTABLE_2LEVEL_DEFS_H */ diff --git a/include/asm-x86/pgtable-2level.h b/include/asm-x86/pgtable-2level.h index 46bc52c0eae1..81762081dcd8 100644 --- a/include/asm-x86/pgtable-2level.h +++ b/include/asm-x86/pgtable-2level.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_2LEVEL_H -#define _I386_PGTABLE_2LEVEL_H +#ifndef ASM_X86__PGTABLE_2LEVEL_H +#define ASM_X86__PGTABLE_2LEVEL_H #define pte_ERROR(e) \ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low) @@ -53,9 +53,7 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp) #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp) #endif -#define pte_page(x) pfn_to_page(pte_pfn(x)) #define pte_none(x) (!(x).pte_low) -#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT) /* * Bits 0, 6 and 7 are taken, split up the 29 bits of offset @@ -78,4 +76,4 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp) #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) -#endif /* _I386_PGTABLE_2LEVEL_H */ +#endif /* ASM_X86__PGTABLE_2LEVEL_H */ diff --git a/include/asm-x86/pgtable-3level-defs.h b/include/asm-x86/pgtable-3level-defs.h index 448ac9516314..c05fe6ff3720 100644 --- a/include/asm-x86/pgtable-3level-defs.h +++ b/include/asm-x86/pgtable-3level-defs.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_3LEVEL_DEFS_H -#define _I386_PGTABLE_3LEVEL_DEFS_H +#ifndef ASM_X86__PGTABLE_3LEVEL_DEFS_H +#define ASM_X86__PGTABLE_3LEVEL_DEFS_H #ifdef CONFIG_PARAVIRT #define SHARED_KERNEL_PMD (pv_info.shared_kernel_pmd) @@ -25,4 +25,4 @@ */ #define PTRS_PER_PTE 512 -#endif /* _I386_PGTABLE_3LEVEL_DEFS_H */ +#endif /* ASM_X86__PGTABLE_3LEVEL_DEFS_H */ diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h index 105057f34032..75f4276b5ddb 100644 --- a/include/asm-x86/pgtable-3level.h +++ b/include/asm-x86/pgtable-3level.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_3LEVEL_H -#define _I386_PGTABLE_3LEVEL_H +#ifndef ASM_X86__PGTABLE_3LEVEL_H +#define ASM_X86__PGTABLE_3LEVEL_H /* * Intel Physical Address Extension (PAE) Mode - three-level page @@ -151,18 +151,11 @@ static inline int pte_same(pte_t a, pte_t b) return a.pte_low == b.pte_low && a.pte_high == b.pte_high; } -#define pte_page(x) pfn_to_page(pte_pfn(x)) - static inline int pte_none(pte_t pte) { return !pte.pte_low && !pte.pte_high; } -static inline unsigned long pte_pfn(pte_t pte) -{ - return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT; -} - /* * Bits 0, 6 and 7 are taken in the low part of the pte, * put the 32 bits of offset into the high part. @@ -179,4 +172,4 @@ static inline unsigned long pte_pfn(pte_t pte) #define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high }) #define __swp_entry_to_pte(x) ((pte_t){ { .pte_high = (x).val } }) -#endif /* _I386_PGTABLE_3LEVEL_H */ +#endif /* ASM_X86__PGTABLE_3LEVEL_H */ diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 04caa2f544df..888add7b0882 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PGTABLE_H -#define _ASM_X86_PGTABLE_H +#ifndef ASM_X86__PGTABLE_H +#define ASM_X86__PGTABLE_H #define FIRST_USER_ADDRESS 0 @@ -186,6 +186,13 @@ static inline int pte_special(pte_t pte) return pte_val(pte) & _PAGE_SPECIAL; } +static inline unsigned long pte_pfn(pte_t pte) +{ + return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT; +} + +#define pte_page(pte) pfn_to_page(pte_pfn(pte)) + static inline int pmd_large(pmd_t pte) { return (pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == @@ -313,6 +320,8 @@ static inline void native_pagetable_setup_start(pgd_t *base) {} static inline void native_pagetable_setup_done(pgd_t *base) {} #endif +extern int arch_report_meminfo(char *page); + #ifdef CONFIG_PARAVIRT #include <asm/paravirt.h> #else /* !CONFIG_PARAVIRT */ @@ -521,4 +530,4 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) #include <asm-generic/pgtable.h> #endif /* __ASSEMBLY__ */ -#endif /* _ASM_X86_PGTABLE_H */ +#endif /* ASM_X86__PGTABLE_H */ diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h index 5c3b26567a95..8de702dc7d62 100644 --- a/include/asm-x86/pgtable_32.h +++ b/include/asm-x86/pgtable_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_PGTABLE_H -#define _I386_PGTABLE_H +#ifndef ASM_X86__PGTABLE_32_H +#define ASM_X86__PGTABLE_32_H /* @@ -31,6 +31,7 @@ static inline void pgtable_cache_init(void) { } static inline void check_pgt_cache(void) { } void paging_init(void); +extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); /* * The Linux x86 paging architecture is 'compile-time dual-mode', it @@ -56,8 +57,7 @@ void paging_init(void); * area for the same reason. ;) */ #define VMALLOC_OFFSET (8 * 1024 * 1024) -#define VMALLOC_START (((unsigned long)high_memory + 2 * VMALLOC_OFFSET - 1) \ - & ~(VMALLOC_OFFSET - 1)) +#define VMALLOC_START ((unsigned long)high_memory + VMALLOC_OFFSET) #ifdef CONFIG_X86_PAE #define LAST_PKMAP 512 #else @@ -73,6 +73,8 @@ void paging_init(void); # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE) #endif +#define MAXMEM (VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE) + /* * Define this if things work differently on an i386 and an i486: * it will (on an i486) warn about kernel memory accesses that are @@ -186,4 +188,4 @@ do { \ #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ remap_pfn_range(vma, vaddr, pfn, size, prot) -#endif /* _I386_PGTABLE_H */ +#endif /* ASM_X86__PGTABLE_32_H */ diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h index 549144d03d99..fde9770e53d1 100644 --- a/include/asm-x86/pgtable_64.h +++ b/include/asm-x86/pgtable_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_PGTABLE_H -#define _X86_64_PGTABLE_H +#ifndef ASM_X86__PGTABLE_64_H +#define ASM_X86__PGTABLE_64_H #include <linux/const.h> #ifndef __ASSEMBLY__ @@ -175,8 +175,6 @@ static inline int pmd_bad(pmd_t pmd) #define pte_present(x) (pte_val((x)) & (_PAGE_PRESENT | _PAGE_PROTNONE)) #define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) /* FIXME: is this right? */ -#define pte_page(x) pfn_to_page(pte_pfn((x))) -#define pte_pfn(x) ((pte_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT) /* * Macro to mark a page protection value as "uncacheable". @@ -284,4 +282,4 @@ extern void cleanup_highmap(void); #define __HAVE_ARCH_PTE_SAME #endif /* !__ASSEMBLY__ */ -#endif /* _X86_64_PGTABLE_H */ +#endif /* ASM_X86__PGTABLE_64_H */ diff --git a/include/asm-x86/posix_types_32.h b/include/asm-x86/posix_types_32.h index b031efda37ec..70cf2bb05939 100644 --- a/include/asm-x86/posix_types_32.h +++ b/include/asm-x86/posix_types_32.h @@ -1,5 +1,5 @@ -#ifndef __ARCH_I386_POSIX_TYPES_H -#define __ARCH_I386_POSIX_TYPES_H +#ifndef ASM_X86__POSIX_TYPES_32_H +#define ASM_X86__POSIX_TYPES_32_H /* * This file is generally used by user-level software, so you need to @@ -82,4 +82,4 @@ do { \ #endif /* defined(__KERNEL__) */ -#endif +#endif /* ASM_X86__POSIX_TYPES_32_H */ diff --git a/include/asm-x86/posix_types_64.h b/include/asm-x86/posix_types_64.h index d6624c95854a..388b4e7f4a44 100644 --- a/include/asm-x86/posix_types_64.h +++ b/include/asm-x86/posix_types_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_POSIX_TYPES_H -#define _ASM_X86_64_POSIX_TYPES_H +#ifndef ASM_X86__POSIX_TYPES_64_H +#define ASM_X86__POSIX_TYPES_64_H /* * This file is generally used by user-level software, so you need to @@ -116,4 +116,4 @@ static inline void __FD_ZERO(__kernel_fd_set *p) #endif /* defined(__KERNEL__) */ -#endif +#endif /* ASM_X86__POSIX_TYPES_64_H */ diff --git a/include/asm-x86/prctl.h b/include/asm-x86/prctl.h index 52952adef1ca..e7ae34eb4103 100644 --- a/include/asm-x86/prctl.h +++ b/include/asm-x86/prctl.h @@ -1,5 +1,5 @@ -#ifndef X86_64_PRCTL_H -#define X86_64_PRCTL_H 1 +#ifndef ASM_X86__PRCTL_H +#define ASM_X86__PRCTL_H #define ARCH_SET_GS 0x1001 #define ARCH_SET_FS 0x1002 @@ -7,4 +7,4 @@ #define ARCH_GET_GS 0x1004 -#endif +#endif /* ASM_X86__PRCTL_H */ diff --git a/include/asm-x86/processor-flags.h b/include/asm-x86/processor-flags.h index eff2ecd7fff0..5dd79774f693 100644 --- a/include/asm-x86/processor-flags.h +++ b/include/asm-x86/processor-flags.h @@ -1,5 +1,5 @@ -#ifndef __ASM_I386_PROCESSOR_FLAGS_H -#define __ASM_I386_PROCESSOR_FLAGS_H +#ifndef ASM_X86__PROCESSOR_FLAGS_H +#define ASM_X86__PROCESSOR_FLAGS_H /* Various flags defined: can be included from assembler. */ /* @@ -96,4 +96,4 @@ #endif #endif -#endif /* __ASM_I386_PROCESSOR_FLAGS_H */ +#endif /* ASM_X86__PROCESSOR_FLAGS_H */ diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 4df3e2f6fb56..5eaf9bf0a623 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_PROCESSOR_H -#define __ASM_X86_PROCESSOR_H +#ifndef ASM_X86__PROCESSOR_H +#define ASM_X86__PROCESSOR_H #include <asm/processor-flags.h> @@ -20,6 +20,7 @@ struct mm_struct; #include <asm/msr.h> #include <asm/desc_defs.h> #include <asm/nops.h> +#include <asm/ds.h> #include <linux/personality.h> #include <linux/cpumask.h> @@ -140,6 +141,8 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info); #define current_cpu_data boot_cpu_data #endif +extern const struct seq_operations cpuinfo_op; + static inline int hlt_works(int cpu) { #ifdef CONFIG_X86_32 @@ -153,6 +156,8 @@ static inline int hlt_works(int cpu) extern void cpu_detect(struct cpuinfo_x86 *c); +extern struct pt_regs *idle_regs(struct pt_regs *); + extern void early_cpu_init(void); extern void identify_boot_cpu(void); extern void identify_secondary_cpu(struct cpuinfo_x86 *); @@ -411,9 +416,14 @@ struct thread_struct { unsigned io_bitmap_max; /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set. */ unsigned long debugctlmsr; -/* Debug Store - if not 0 points to a DS Save Area configuration; - * goes into MSR_IA32_DS_AREA */ - unsigned long ds_area_msr; +#ifdef CONFIG_X86_DS +/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */ + struct ds_context *ds_ctx; +#endif /* CONFIG_X86_DS */ +#ifdef CONFIG_X86_PTRACE_BTS +/* the signal to send on a bts buffer overflow */ + unsigned int bts_ovfl_signal; +#endif /* CONFIG_X86_PTRACE_BTS */ }; static inline unsigned long native_get_debugreg(int regno) @@ -943,4 +953,4 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, extern int get_tsc_mode(unsigned long adr); extern int set_tsc_mode(unsigned int val); -#endif +#endif /* ASM_X86__PROCESSOR_H */ diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h index 3dd458c385c0..6e89e8b4de0e 100644 --- a/include/asm-x86/proto.h +++ b/include/asm-x86/proto.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X8664_PROTO_H -#define _ASM_X8664_PROTO_H 1 +#ifndef ASM_X86__PROTO_H +#define ASM_X86__PROTO_H #include <asm/ldt.h> @@ -29,4 +29,4 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); #define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1)) #define round_down(x, y) ((x) & ~((y) - 1)) -#endif +#endif /* ASM_X86__PROTO_H */ diff --git a/include/asm-x86/ptrace-abi.h b/include/asm-x86/ptrace-abi.h index 72e7b9db29bb..4298b8882a78 100644 --- a/include/asm-x86/ptrace-abi.h +++ b/include/asm-x86/ptrace-abi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PTRACE_ABI_H -#define _ASM_X86_PTRACE_ABI_H +#ifndef ASM_X86__PTRACE_ABI_H +#define ASM_X86__PTRACE_ABI_H #ifdef __i386__ @@ -80,8 +80,9 @@ #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ -#ifndef __ASSEMBLY__ +#ifdef CONFIG_X86_PTRACE_BTS +#ifndef __ASSEMBLY__ #include <asm/types.h> /* configuration/status structure used in PTRACE_BTS_CONFIG and @@ -97,20 +98,20 @@ struct ptrace_bts_config { /* actual size of bts_struct in bytes */ __u32 bts_size; }; -#endif +#endif /* __ASSEMBLY__ */ #define PTRACE_BTS_O_TRACE 0x1 /* branch trace */ #define PTRACE_BTS_O_SCHED 0x2 /* scheduling events w/ jiffies */ #define PTRACE_BTS_O_SIGNAL 0x4 /* send SIG<signal> on buffer overflow instead of wrapping around */ -#define PTRACE_BTS_O_CUT_SIZE 0x8 /* cut requested size to max available - instead of failing */ +#define PTRACE_BTS_O_ALLOC 0x8 /* (re)allocate buffer */ #define PTRACE_BTS_CONFIG 40 /* Configure branch trace recording. ADDR points to a struct ptrace_bts_config. DATA gives the size of that buffer. - A new buffer is allocated, iff the size changes. + A new buffer is allocated, if requested in the flags. + An overflow signal may only be requested for new buffers. Returns the number of bytes read. */ #define PTRACE_BTS_STATUS 41 @@ -119,7 +120,7 @@ struct ptrace_bts_config { Returns the number of bytes written. */ #define PTRACE_BTS_SIZE 42 -/* Return the number of available BTS records. +/* Return the number of available BTS records for draining. DATA and ADDR are ignored. */ #define PTRACE_BTS_GET 43 @@ -139,5 +140,6 @@ struct ptrace_bts_config { BTS records are read from oldest to newest. Returns number of BTS records drained. */ +#endif /* CONFIG_X86_PTRACE_BTS */ -#endif +#endif /* ASM_X86__PTRACE_ABI_H */ diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index 8a71db803da6..d64a61097165 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PTRACE_H -#define _ASM_X86_PTRACE_H +#ifndef ASM_X86__PTRACE_H +#define ASM_X86__PTRACE_H #include <linux/compiler.h> /* For __user */ #include <asm/ptrace-abi.h> @@ -127,14 +127,48 @@ struct pt_regs { #endif /* __KERNEL__ */ #endif /* !__i386__ */ + +#ifdef CONFIG_X86_PTRACE_BTS +/* a branch trace record entry + * + * In order to unify the interface between various processor versions, + * we use the below data structure for all processors. + */ +enum bts_qualifier { + BTS_INVALID = 0, + BTS_BRANCH, + BTS_TASK_ARRIVES, + BTS_TASK_DEPARTS +}; + +struct bts_struct { + __u64 qualifier; + union { + /* BTS_BRANCH */ + struct { + __u64 from_ip; + __u64 to_ip; + } lbr; + /* BTS_TASK_ARRIVES or + BTS_TASK_DEPARTS */ + __u64 jiffies; + } variant; +}; +#endif /* CONFIG_X86_PTRACE_BTS */ + #ifdef __KERNEL__ -/* the DS BTS struct is used for ptrace as well */ -#include <asm/ds.h> +#include <linux/init.h> +struct cpuinfo_x86; struct task_struct; +#ifdef CONFIG_X86_PTRACE_BTS +extern void __cpuinit ptrace_bts_init_intel(struct cpuinfo_x86 *); extern void ptrace_bts_take_timestamp(struct task_struct *, enum bts_qualifier); +#else +#define ptrace_bts_init_intel(config) do {} while (0) +#endif /* CONFIG_X86_PTRACE_BTS */ extern unsigned long profile_pc(struct pt_regs *regs); @@ -148,6 +182,9 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, void signal_fault(struct pt_regs *regs, void __user *frame, char *where); #endif +extern long syscall_trace_enter(struct pt_regs *); +extern void syscall_trace_leave(struct pt_regs *); + static inline unsigned long regs_return_value(struct pt_regs *regs) { return regs->ax; @@ -213,6 +250,11 @@ static inline unsigned long frame_pointer(struct pt_regs *regs) return regs->bp; } +static inline unsigned long user_stack_pointer(struct pt_regs *regs) +{ + return regs->sp; +} + /* * These are defined as per linux/ptrace.h, which see. */ @@ -239,4 +281,4 @@ extern int do_set_thread_area(struct task_struct *p, int idx, #endif /* !__ASSEMBLY__ */ -#endif +#endif /* ASM_X86__PTRACE_H */ diff --git a/include/asm-x86/pvclock-abi.h b/include/asm-x86/pvclock-abi.h index 6857f840b243..edb3b4ecfc81 100644 --- a/include/asm-x86/pvclock-abi.h +++ b/include/asm-x86/pvclock-abi.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PVCLOCK_ABI_H_ -#define _ASM_X86_PVCLOCK_ABI_H_ +#ifndef ASM_X86__PVCLOCK_ABI_H +#define ASM_X86__PVCLOCK_ABI_H #ifndef __ASSEMBLY__ /* @@ -39,4 +39,4 @@ struct pvclock_wall_clock { } __attribute__((__packed__)); #endif /* __ASSEMBLY__ */ -#endif /* _ASM_X86_PVCLOCK_ABI_H_ */ +#endif /* ASM_X86__PVCLOCK_ABI_H */ diff --git a/include/asm-x86/pvclock.h b/include/asm-x86/pvclock.h index 85b1bba8e0a3..1a38f6834800 100644 --- a/include/asm-x86/pvclock.h +++ b/include/asm-x86/pvclock.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_PVCLOCK_H_ -#define _ASM_X86_PVCLOCK_H_ +#ifndef ASM_X86__PVCLOCK_H +#define ASM_X86__PVCLOCK_H #include <linux/clocksource.h> #include <asm/pvclock-abi.h> @@ -10,4 +10,4 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall, struct pvclock_vcpu_time_info *vcpu, struct timespec *ts); -#endif /* _ASM_X86_PVCLOCK_H_ */ +#endif /* ASM_X86__PVCLOCK_H */ diff --git a/include/asm-x86/reboot.h b/include/asm-x86/reboot.h index 206f355786dc..1c2f0ce9e31e 100644 --- a/include/asm-x86/reboot.h +++ b/include/asm-x86/reboot.h @@ -1,5 +1,5 @@ -#ifndef _ASM_REBOOT_H -#define _ASM_REBOOT_H +#ifndef ASM_X86__REBOOT_H +#define ASM_X86__REBOOT_H struct pt_regs; @@ -18,4 +18,4 @@ void native_machine_crash_shutdown(struct pt_regs *regs); void native_machine_shutdown(void); void machine_real_restart(const unsigned char *code, int length); -#endif /* _ASM_REBOOT_H */ +#endif /* ASM_X86__REBOOT_H */ diff --git a/include/asm-x86/reboot_fixups.h b/include/asm-x86/reboot_fixups.h index 0cb7d87c2b68..2c2987d97570 100644 --- a/include/asm-x86/reboot_fixups.h +++ b/include/asm-x86/reboot_fixups.h @@ -1,6 +1,6 @@ -#ifndef _LINUX_REBOOT_FIXUPS_H -#define _LINUX_REBOOT_FIXUPS_H +#ifndef ASM_X86__REBOOT_FIXUPS_H +#define ASM_X86__REBOOT_FIXUPS_H extern void mach_reboot_fixups(void); -#endif /* _LINUX_REBOOT_FIXUPS_H */ +#endif /* ASM_X86__REBOOT_FIXUPS_H */ diff --git a/include/asm-x86/required-features.h b/include/asm-x86/required-features.h index 5c2ff4bc2980..a01c4e376331 100644 --- a/include/asm-x86/required-features.h +++ b/include/asm-x86/required-features.h @@ -1,5 +1,5 @@ -#ifndef _ASM_REQUIRED_FEATURES_H -#define _ASM_REQUIRED_FEATURES_H 1 +#ifndef ASM_X86__REQUIRED_FEATURES_H +#define ASM_X86__REQUIRED_FEATURES_H /* Define minimum CPUID feature set for kernel These bits are checked really early to actually display a visible error message before the @@ -79,4 +79,4 @@ #define REQUIRED_MASK6 0 #define REQUIRED_MASK7 0 -#endif +#endif /* ASM_X86__REQUIRED_FEATURES_H */ diff --git a/include/asm-x86/resume-trace.h b/include/asm-x86/resume-trace.h index 8d9f0b41ee86..e39376d7de50 100644 --- a/include/asm-x86/resume-trace.h +++ b/include/asm-x86/resume-trace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_RESUME_TRACE_H -#define _ASM_X86_RESUME_TRACE_H +#ifndef ASM_X86__RESUME_TRACE_H +#define ASM_X86__RESUME_TRACE_H #include <asm/asm.h> @@ -7,7 +7,7 @@ do { \ if (pm_trace_enabled) { \ const void *tracedata; \ - asm volatile(_ASM_MOV_UL " $1f,%0\n" \ + asm volatile(_ASM_MOV " $1f,%0\n" \ ".section .tracedata,\"a\"\n" \ "1:\t.word %c1\n\t" \ _ASM_PTR " %c2\n" \ @@ -18,4 +18,4 @@ do { \ } \ } while (0) -#endif +#endif /* ASM_X86__RESUME_TRACE_H */ diff --git a/include/asm-x86/rio.h b/include/asm-x86/rio.h index c9448bd8968f..5e1256bdee83 100644 --- a/include/asm-x86/rio.h +++ b/include/asm-x86/rio.h @@ -5,8 +5,8 @@ * Author: Laurent Vivier <Laurent.Vivier@bull.net> */ -#ifndef __ASM_RIO_H -#define __ASM_RIO_H +#ifndef ASM_X86__RIO_H +#define ASM_X86__RIO_H #define RIO_TABLE_VERSION 3 @@ -60,4 +60,4 @@ enum { ALT_CALGARY = 5, /* Second Planar Calgary */ }; -#endif /* __ASM_RIO_H */ +#endif /* ASM_X86__RIO_H */ diff --git a/include/asm-x86/rwlock.h b/include/asm-x86/rwlock.h index 6a8c0d645108..48a3109e1a7d 100644 --- a/include/asm-x86/rwlock.h +++ b/include/asm-x86/rwlock.h @@ -1,8 +1,8 @@ -#ifndef _ASM_X86_RWLOCK_H -#define _ASM_X86_RWLOCK_H +#ifndef ASM_X86__RWLOCK_H +#define ASM_X86__RWLOCK_H #define RW_LOCK_BIAS 0x01000000 /* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */ -#endif /* _ASM_X86_RWLOCK_H */ +#endif /* ASM_X86__RWLOCK_H */ diff --git a/include/asm-x86/rwsem.h b/include/asm-x86/rwsem.h index 750f2a3542b3..3ff3015b71a8 100644 --- a/include/asm-x86/rwsem.h +++ b/include/asm-x86/rwsem.h @@ -29,8 +29,8 @@ * front, then they'll all be woken up, but no other readers will be. */ -#ifndef _I386_RWSEM_H -#define _I386_RWSEM_H +#ifndef ASM_X86__RWSEM_H +#define ASM_X86__RWSEM_H #ifndef _LINUX_RWSEM_H #error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead" @@ -262,4 +262,4 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) } #endif /* __KERNEL__ */ -#endif /* _I386_RWSEM_H */ +#endif /* ASM_X86__RWSEM_H */ diff --git a/include/asm-x86/scatterlist.h b/include/asm-x86/scatterlist.h index c0432061f81a..ee48f880005d 100644 --- a/include/asm-x86/scatterlist.h +++ b/include/asm-x86/scatterlist.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SCATTERLIST_H -#define _ASM_X86_SCATTERLIST_H +#ifndef ASM_X86__SCATTERLIST_H +#define ASM_X86__SCATTERLIST_H #include <asm/types.h> @@ -30,4 +30,4 @@ struct scatterlist { # define sg_dma_len(sg) ((sg)->dma_length) #endif -#endif +#endif /* ASM_X86__SCATTERLIST_H */ diff --git a/include/asm-x86/seccomp_32.h b/include/asm-x86/seccomp_32.h index 36e71c5f306f..cf9ab2dbcef1 100644 --- a/include/asm-x86/seccomp_32.h +++ b/include/asm-x86/seccomp_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SECCOMP_H -#define _ASM_SECCOMP_H +#ifndef ASM_X86__SECCOMP_32_H +#define ASM_X86__SECCOMP_32_H #include <linux/thread_info.h> @@ -14,4 +14,4 @@ #define __NR_seccomp_exit __NR_exit #define __NR_seccomp_sigreturn __NR_sigreturn -#endif /* _ASM_SECCOMP_H */ +#endif /* ASM_X86__SECCOMP_32_H */ diff --git a/include/asm-x86/seccomp_64.h b/include/asm-x86/seccomp_64.h index 76cfe69aa63c..03274cea751f 100644 --- a/include/asm-x86/seccomp_64.h +++ b/include/asm-x86/seccomp_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SECCOMP_H -#define _ASM_SECCOMP_H +#ifndef ASM_X86__SECCOMP_64_H +#define ASM_X86__SECCOMP_64_H #include <linux/thread_info.h> @@ -22,4 +22,4 @@ #define __NR_seccomp_exit_32 __NR_ia32_exit #define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn -#endif /* _ASM_SECCOMP_H */ +#endif /* ASM_X86__SECCOMP_64_H */ diff --git a/include/asm-x86/segment.h b/include/asm-x86/segment.h index 646452ea9ea3..ea5f0a8686f7 100644 --- a/include/asm-x86/segment.h +++ b/include/asm-x86/segment.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SEGMENT_H_ -#define _ASM_X86_SEGMENT_H_ +#ifndef ASM_X86__SEGMENT_H +#define ASM_X86__SEGMENT_H /* Constructor for a conventional segment GDT (or LDT) entry */ /* This is a macro so it can be used in initializers */ @@ -212,4 +212,4 @@ extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10]; #endif #endif -#endif +#endif /* ASM_X86__SEGMENT_H */ diff --git a/include/asm-x86/sembuf.h b/include/asm-x86/sembuf.h index ee50c801f7b7..81f06b7e5a3f 100644 --- a/include/asm-x86/sembuf.h +++ b/include/asm-x86/sembuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SEMBUF_H -#define _ASM_X86_SEMBUF_H +#ifndef ASM_X86__SEMBUF_H +#define ASM_X86__SEMBUF_H /* * The semid64_ds structure for x86 architecture. @@ -21,4 +21,4 @@ struct semid64_ds { unsigned long __unused4; }; -#endif /* _ASM_X86_SEMBUF_H */ +#endif /* ASM_X86__SEMBUF_H */ diff --git a/include/asm-x86/serial.h b/include/asm-x86/serial.h index 628c801535ea..303660b671e5 100644 --- a/include/asm-x86/serial.h +++ b/include/asm-x86/serial.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SERIAL_H -#define _ASM_X86_SERIAL_H +#ifndef ASM_X86__SERIAL_H +#define ASM_X86__SERIAL_H /* * This assumes you have a 1.8432 MHz clock for your UART. @@ -26,4 +26,4 @@ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ -#endif /* _ASM_X86_SERIAL_H */ +#endif /* ASM_X86__SERIAL_H */ diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h index a07c6f1c01e1..9030cb73c4d7 100644 --- a/include/asm-x86/setup.h +++ b/include/asm-x86/setup.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SETUP_H -#define _ASM_X86_SETUP_H +#ifndef ASM_X86__SETUP_H +#define ASM_X86__SETUP_H #define COMMAND_LINE_SIZE 2048 @@ -41,6 +41,7 @@ struct x86_quirks { }; extern struct x86_quirks *x86_quirks; +extern unsigned long saved_video_mode; #ifndef CONFIG_PARAVIRT #define paravirt_post_allocator_init() do {} while (0) @@ -100,4 +101,4 @@ void __init x86_64_start_reservations(char *real_mode_data); #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ -#endif /* _ASM_X86_SETUP_H */ +#endif /* ASM_X86__SETUP_H */ diff --git a/include/asm-x86/shmbuf.h b/include/asm-x86/shmbuf.h index b51413b74971..f51aec2298e9 100644 --- a/include/asm-x86/shmbuf.h +++ b/include/asm-x86/shmbuf.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SHMBUF_H -#define _ASM_X86_SHMBUF_H +#ifndef ASM_X86__SHMBUF_H +#define ASM_X86__SHMBUF_H /* * The shmid64_ds structure for x86 architecture. @@ -48,4 +48,4 @@ struct shminfo64 { unsigned long __unused4; }; -#endif /* _ASM_X86_SHMBUF_H */ +#endif /* ASM_X86__SHMBUF_H */ diff --git a/include/asm-x86/shmparam.h b/include/asm-x86/shmparam.h index 0880cf0917b9..a83a1fd96a0e 100644 --- a/include/asm-x86/shmparam.h +++ b/include/asm-x86/shmparam.h @@ -1,6 +1,6 @@ -#ifndef _ASM_X86_SHMPARAM_H -#define _ASM_X86_SHMPARAM_H +#ifndef ASM_X86__SHMPARAM_H +#define ASM_X86__SHMPARAM_H #define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ -#endif /* _ASM_X86_SHMPARAM_H */ +#endif /* ASM_X86__SHMPARAM_H */ diff --git a/include/asm-x86/sigcontext.h b/include/asm-x86/sigcontext.h index 2f9c884d2c0f..24879c85b291 100644 --- a/include/asm-x86/sigcontext.h +++ b/include/asm-x86/sigcontext.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SIGCONTEXT_H -#define _ASM_X86_SIGCONTEXT_H +#ifndef ASM_X86__SIGCONTEXT_H +#define ASM_X86__SIGCONTEXT_H #include <linux/compiler.h> #include <asm/types.h> @@ -202,4 +202,4 @@ struct sigcontext { #endif /* !__i386__ */ -#endif +#endif /* ASM_X86__SIGCONTEXT_H */ diff --git a/include/asm-x86/sigcontext32.h b/include/asm-x86/sigcontext32.h index 57a9686fb491..4e2ec732dd01 100644 --- a/include/asm-x86/sigcontext32.h +++ b/include/asm-x86/sigcontext32.h @@ -1,5 +1,5 @@ -#ifndef _SIGCONTEXT32_H -#define _SIGCONTEXT32_H 1 +#ifndef ASM_X86__SIGCONTEXT32_H +#define ASM_X86__SIGCONTEXT32_H /* signal context for 32bit programs. */ @@ -68,4 +68,4 @@ struct sigcontext_ia32 { unsigned int cr2; }; -#endif +#endif /* ASM_X86__SIGCONTEXT32_H */ diff --git a/include/asm-x86/siginfo.h b/include/asm-x86/siginfo.h index a477bea0c2a1..808bdfb2958c 100644 --- a/include/asm-x86/siginfo.h +++ b/include/asm-x86/siginfo.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SIGINFO_H -#define _ASM_X86_SIGINFO_H +#ifndef ASM_X86__SIGINFO_H +#define ASM_X86__SIGINFO_H #ifdef __x86_64__ # define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) @@ -7,4 +7,4 @@ #include <asm-generic/siginfo.h> -#endif +#endif /* ASM_X86__SIGINFO_H */ diff --git a/include/asm-x86/signal.h b/include/asm-x86/signal.h index 6dac49364e95..65acc82d267a 100644 --- a/include/asm-x86/signal.h +++ b/include/asm-x86/signal.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SIGNAL_H -#define _ASM_X86_SIGNAL_H +#ifndef ASM_X86__SIGNAL_H +#define ASM_X86__SIGNAL_H #ifndef __ASSEMBLY__ #include <linux/types.h> @@ -140,6 +140,9 @@ struct sigaction { struct k_sigaction { struct sigaction sa; }; + +extern void do_notify_resume(struct pt_regs *, void *, __u32); + # else /* __KERNEL__ */ /* Here we must cater to libcs that poke about in kernel headers. */ @@ -256,4 +259,4 @@ struct pt_regs; #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__SIGNAL_H */ diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h index 3c877f74f279..04f84f4e2c8b 100644 --- a/include/asm-x86/smp.h +++ b/include/asm-x86/smp.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SMP_H_ -#define _ASM_X86_SMP_H_ +#ifndef ASM_X86__SMP_H +#define ASM_X86__SMP_H #ifndef __ASSEMBLY__ #include <linux/cpumask.h> #include <linux/init.h> @@ -34,6 +34,9 @@ extern cpumask_t cpu_initialized; DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); DECLARE_PER_CPU(cpumask_t, cpu_core_map); DECLARE_PER_CPU(u16, cpu_llc_id); +#ifdef CONFIG_X86_32 +DECLARE_PER_CPU(int, cpu_number); +#endif DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid); DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); @@ -142,7 +145,6 @@ extern unsigned disabled_cpus __cpuinitdata; * from the initial startup. We map APIC_BASE very early in page_setup(), * so this is correct in the x86 case. */ -DECLARE_PER_CPU(int, cpu_number); #define raw_smp_processor_id() (x86_read_percpu(cpu_number)) extern int safe_smp_processor_id(void); @@ -205,4 +207,4 @@ extern void cpu_uninit(void); #endif #endif /* __ASSEMBLY__ */ -#endif +#endif /* ASM_X86__SMP_H */ diff --git a/include/asm-x86/socket.h b/include/asm-x86/socket.h index 80af9c4ccad7..db73274c83c3 100644 --- a/include/asm-x86/socket.h +++ b/include/asm-x86/socket.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SOCKET_H -#define _ASM_SOCKET_H +#ifndef ASM_X86__SOCKET_H +#define ASM_X86__SOCKET_H #include <asm/sockios.h> @@ -54,4 +54,4 @@ #define SO_MARK 36 -#endif /* _ASM_SOCKET_H */ +#endif /* ASM_X86__SOCKET_H */ diff --git a/include/asm-x86/sockios.h b/include/asm-x86/sockios.h index 49cc72b5d3c9..a006704fdc84 100644 --- a/include/asm-x86/sockios.h +++ b/include/asm-x86/sockios.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SOCKIOS_H -#define _ASM_X86_SOCKIOS_H +#ifndef ASM_X86__SOCKIOS_H +#define ASM_X86__SOCKIOS_H /* Socket-level I/O control calls. */ #define FIOSETOWN 0x8901 @@ -10,4 +10,4 @@ #define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ #define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ -#endif /* _ASM_X86_SOCKIOS_H */ +#endif /* ASM_X86__SOCKIOS_H */ diff --git a/include/asm-x86/sparsemem.h b/include/asm-x86/sparsemem.h index 9bd48b0a534b..38f8e6bc3186 100644 --- a/include/asm-x86/sparsemem.h +++ b/include/asm-x86/sparsemem.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SPARSEMEM_H -#define _ASM_X86_SPARSEMEM_H +#ifndef ASM_X86__SPARSEMEM_H +#define ASM_X86__SPARSEMEM_H #ifdef CONFIG_SPARSEMEM /* @@ -31,4 +31,4 @@ #endif #endif /* CONFIG_SPARSEMEM */ -#endif +#endif /* ASM_X86__SPARSEMEM_H */ diff --git a/include/asm-x86/spinlock.h b/include/asm-x86/spinlock.h index e39c790dbfd2..93adae338ac6 100644 --- a/include/asm-x86/spinlock.h +++ b/include/asm-x86/spinlock.h @@ -1,5 +1,5 @@ -#ifndef _X86_SPINLOCK_H_ -#define _X86_SPINLOCK_H_ +#ifndef ASM_X86__SPINLOCK_H +#define ASM_X86__SPINLOCK_H #include <asm/atomic.h> #include <asm/rwlock.h> @@ -97,7 +97,7 @@ static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock) "jne 1f\n\t" "movw %w0,%w1\n\t" "incb %h1\n\t" - "lock ; cmpxchgw %w1,%2\n\t" + LOCK_PREFIX "cmpxchgw %w1,%2\n\t" "1:" "sete %b1\n\t" "movzbl %b1,%0\n\t" @@ -135,7 +135,7 @@ static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock) int inc = 0x00010000; int tmp; - asm volatile("lock ; xaddl %0, %1\n" + asm volatile(LOCK_PREFIX "xaddl %0, %1\n" "movzwl %w0, %2\n\t" "shrl $16, %0\n\t" "1:\t" @@ -162,7 +162,7 @@ static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock) "cmpl %0,%1\n\t" "jne 1f\n\t" "addl $0x00010000, %1\n\t" - "lock ; cmpxchgl %1,%2\n\t" + LOCK_PREFIX "cmpxchgl %1,%2\n\t" "1:" "sete %b1\n\t" "movzbl %b1,%0\n\t" @@ -366,4 +366,4 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) #define _raw_read_relax(lock) cpu_relax() #define _raw_write_relax(lock) cpu_relax() -#endif +#endif /* ASM_X86__SPINLOCK_H */ diff --git a/include/asm-x86/spinlock_types.h b/include/asm-x86/spinlock_types.h index 06c071c9eee9..6aa9b562c508 100644 --- a/include/asm-x86/spinlock_types.h +++ b/include/asm-x86/spinlock_types.h @@ -1,5 +1,5 @@ -#ifndef __ASM_SPINLOCK_TYPES_H -#define __ASM_SPINLOCK_TYPES_H +#ifndef ASM_X86__SPINLOCK_TYPES_H +#define ASM_X86__SPINLOCK_TYPES_H #ifndef __LINUX_SPINLOCK_TYPES_H # error "please don't include this file directly" @@ -17,4 +17,4 @@ typedef struct { #define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } -#endif +#endif /* ASM_X86__SPINLOCK_TYPES_H */ diff --git a/include/asm-x86/srat.h b/include/asm-x86/srat.h index 774c919dc232..5363e4f7e1cd 100644 --- a/include/asm-x86/srat.h +++ b/include/asm-x86/srat.h @@ -24,8 +24,8 @@ * Send feedback to Pat Gaughen <gone@us.ibm.com> */ -#ifndef _ASM_SRAT_H_ -#define _ASM_SRAT_H_ +#ifndef ASM_X86__SRAT_H +#define ASM_X86__SRAT_H #ifdef CONFIG_ACPI_NUMA extern int get_memcfg_from_srat(void); @@ -36,4 +36,4 @@ static inline int get_memcfg_from_srat(void) } #endif -#endif /* _ASM_SRAT_H_ */ +#endif /* ASM_X86__SRAT_H */ diff --git a/include/asm-x86/stacktrace.h b/include/asm-x86/stacktrace.h index 30f82526a8e2..f43517e28532 100644 --- a/include/asm-x86/stacktrace.h +++ b/include/asm-x86/stacktrace.h @@ -1,5 +1,5 @@ -#ifndef _ASM_STACKTRACE_H -#define _ASM_STACKTRACE_H 1 +#ifndef ASM_X86__STACKTRACE_H +#define ASM_X86__STACKTRACE_H extern int kstack_depth_to_print; @@ -18,4 +18,4 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack, unsigned long bp, const struct stacktrace_ops *ops, void *data); -#endif +#endif /* ASM_X86__STACKTRACE_H */ diff --git a/include/asm-x86/stat.h b/include/asm-x86/stat.h index 5c22dcb5d17e..1e120f628905 100644 --- a/include/asm-x86/stat.h +++ b/include/asm-x86/stat.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_STAT_H -#define _ASM_X86_STAT_H +#ifndef ASM_X86__STAT_H +#define ASM_X86__STAT_H #define STAT_HAVE_NSEC 1 @@ -111,4 +111,4 @@ struct __old_kernel_stat { #endif }; -#endif +#endif /* ASM_X86__STAT_H */ diff --git a/include/asm-x86/statfs.h b/include/asm-x86/statfs.h index 7c651aa97252..3f005bc3aa5b 100644 --- a/include/asm-x86/statfs.h +++ b/include/asm-x86/statfs.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_STATFS_H -#define _ASM_X86_STATFS_H +#ifndef ASM_X86__STATFS_H +#define ASM_X86__STATFS_H #ifdef __i386__ #include <asm-generic/statfs.h> @@ -60,4 +60,4 @@ struct compat_statfs64 { } __attribute__((packed)); #endif /* !__i386__ */ -#endif +#endif /* ASM_X86__STATFS_H */ diff --git a/include/asm-x86/string_32.h b/include/asm-x86/string_32.h index 193578cd1fd9..487843ed245a 100644 --- a/include/asm-x86/string_32.h +++ b/include/asm-x86/string_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_STRING_H_ -#define _I386_STRING_H_ +#ifndef ASM_X86__STRING_32_H +#define ASM_X86__STRING_32_H #ifdef __KERNEL__ @@ -323,4 +323,4 @@ extern void *memscan(void *addr, int c, size_t size); #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__STRING_32_H */ diff --git a/include/asm-x86/string_64.h b/include/asm-x86/string_64.h index 52b5ab383395..a2add11d3b66 100644 --- a/include/asm-x86/string_64.h +++ b/include/asm-x86/string_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_STRING_H_ -#define _X86_64_STRING_H_ +#ifndef ASM_X86__STRING_64_H +#define ASM_X86__STRING_64_H #ifdef __KERNEL__ @@ -57,4 +57,4 @@ int strcmp(const char *cs, const char *ct); #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__STRING_64_H */ diff --git a/include/asm-x86/suspend_32.h b/include/asm-x86/suspend_32.h index 8675c6782a7d..acb6d4d491f4 100644 --- a/include/asm-x86/suspend_32.h +++ b/include/asm-x86/suspend_32.h @@ -3,8 +3,8 @@ * Based on code * Copyright 2001 Patrick Mochel <mochel@osdl.org> */ -#ifndef __ASM_X86_32_SUSPEND_H -#define __ASM_X86_32_SUSPEND_H +#ifndef ASM_X86__SUSPEND_32_H +#define ASM_X86__SUSPEND_32_H #include <asm/desc.h> #include <asm/i387.h> @@ -48,4 +48,4 @@ static inline void acpi_save_register_state(unsigned long return_point) extern int acpi_save_state_mem(void); #endif -#endif /* __ASM_X86_32_SUSPEND_H */ +#endif /* ASM_X86__SUSPEND_32_H */ diff --git a/include/asm-x86/suspend_64.h b/include/asm-x86/suspend_64.h index dc3262b43072..cf821dd310e8 100644 --- a/include/asm-x86/suspend_64.h +++ b/include/asm-x86/suspend_64.h @@ -3,8 +3,8 @@ * Based on code * Copyright 2001 Patrick Mochel <mochel@osdl.org> */ -#ifndef __ASM_X86_64_SUSPEND_H -#define __ASM_X86_64_SUSPEND_H +#ifndef ASM_X86__SUSPEND_64_H +#define ASM_X86__SUSPEND_64_H #include <asm/desc.h> #include <asm/i387.h> @@ -49,4 +49,4 @@ extern int acpi_save_state_mem(void); extern char core_restore_code; extern char restore_registers; -#endif /* __ASM_X86_64_SUSPEND_H */ +#endif /* ASM_X86__SUSPEND_64_H */ diff --git a/include/asm-x86/swiotlb.h b/include/asm-x86/swiotlb.h index 2730b351afcf..1e20adbcad4b 100644 --- a/include/asm-x86/swiotlb.h +++ b/include/asm-x86/swiotlb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_SWIOTLB_H -#define _ASM_SWIOTLB_H 1 +#ifndef ASM_X86__SWIOTLB_H +#define ASM_X86__SWIOTLB_H #include <asm/dma-mapping.h> @@ -55,4 +55,4 @@ static inline void pci_swiotlb_init(void) static inline void dma_mark_clean(void *addr, size_t size) {} -#endif /* _ASM_SWIOTLB_H */ +#endif /* ASM_X86__SWIOTLB_H */ diff --git a/include/asm-x86/sync_bitops.h b/include/asm-x86/sync_bitops.h index b47a1d0b8a83..b689bee71104 100644 --- a/include/asm-x86/sync_bitops.h +++ b/include/asm-x86/sync_bitops.h @@ -1,5 +1,5 @@ -#ifndef _I386_SYNC_BITOPS_H -#define _I386_SYNC_BITOPS_H +#ifndef ASM_X86__SYNC_BITOPS_H +#define ASM_X86__SYNC_BITOPS_H /* * Copyright 1992, Linus Torvalds. @@ -127,4 +127,4 @@ static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr) #undef ADDR -#endif /* _I386_SYNC_BITOPS_H */ +#endif /* ASM_X86__SYNC_BITOPS_H */ diff --git a/include/asm-x86/syscall.h b/include/asm-x86/syscall.h new file mode 100644 index 000000000000..04c47dc5597c --- /dev/null +++ b/include/asm-x86/syscall.h @@ -0,0 +1,211 @@ +/* + * Access to user system call parameters and results + * + * Copyright (C) 2008 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * See asm-generic/syscall.h for descriptions of what we must do here. + */ + +#ifndef _ASM_SYSCALL_H +#define _ASM_SYSCALL_H 1 + +#include <linux/sched.h> +#include <linux/err.h> + +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + /* + * We always sign-extend a -1 value being set here, + * so this is always either -1L or a syscall number. + */ + return regs->orig_ax; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->ax = regs->orig_ax; +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + unsigned long error = regs->ax; +#ifdef CONFIG_IA32_EMULATION + /* + * TS_COMPAT is set for 32-bit syscall entries and then + * remains set until we return to user mode. + */ + if (task_thread_info(task)->status & TS_COMPAT) + /* + * Sign-extend the value so (int)-EFOO becomes (long)-EFOO + * and will match correctly in comparisons. + */ + error = (long) (int) error; +#endif + return IS_ERR_VALUE(error) ? error : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->ax; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->ax = (long) error ?: val; +} + +#ifdef CONFIG_X86_32 + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); + memcpy(args, ®s->bx + i, n * sizeof(args[0])); +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + BUG_ON(i + n > 6); + memcpy(®s->bx + i, args, n * sizeof(args[0])); +} + +#else /* CONFIG_X86_64 */ + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ +# ifdef CONFIG_IA32_EMULATION + if (task_thread_info(task)->status & TS_COMPAT) + switch (i + n) { + case 6: + if (!n--) break; + *args++ = regs->bp; + case 5: + if (!n--) break; + *args++ = regs->di; + case 4: + if (!n--) break; + *args++ = regs->si; + case 3: + if (!n--) break; + *args++ = regs->dx; + case 2: + if (!n--) break; + *args++ = regs->cx; + case 1: + if (!n--) break; + *args++ = regs->bx; + case 0: + if (!n--) break; + default: + BUG(); + break; + } + else +# endif + switch (i + n) { + case 6: + if (!n--) break; + *args++ = regs->r9; + case 5: + if (!n--) break; + *args++ = regs->r8; + case 4: + if (!n--) break; + *args++ = regs->r10; + case 3: + if (!n--) break; + *args++ = regs->dx; + case 2: + if (!n--) break; + *args++ = regs->si; + case 1: + if (!n--) break; + *args++ = regs->di; + case 0: + if (!n--) break; + default: + BUG(); + break; + } +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ +# ifdef CONFIG_IA32_EMULATION + if (task_thread_info(task)->status & TS_COMPAT) + switch (i + n) { + case 6: + if (!n--) break; + regs->bp = *args++; + case 5: + if (!n--) break; + regs->di = *args++; + case 4: + if (!n--) break; + regs->si = *args++; + case 3: + if (!n--) break; + regs->dx = *args++; + case 2: + if (!n--) break; + regs->cx = *args++; + case 1: + if (!n--) break; + regs->bx = *args++; + case 0: + if (!n--) break; + default: + BUG(); + } + else +# endif + switch (i + n) { + case 6: + if (!n--) break; + regs->r9 = *args++; + case 5: + if (!n--) break; + regs->r8 = *args++; + case 4: + if (!n--) break; + regs->r10 = *args++; + case 3: + if (!n--) break; + regs->dx = *args++; + case 2: + if (!n--) break; + regs->si = *args++; + case 1: + if (!n--) break; + regs->di = *args++; + case 0: + if (!n--) break; + default: + BUG(); + } +} + +#endif /* CONFIG_X86_32 */ + +#endif /* _ASM_SYSCALL_H */ diff --git a/include/asm-x86/syscalls.h b/include/asm-x86/syscalls.h new file mode 100644 index 000000000000..87803da44010 --- /dev/null +++ b/include/asm-x86/syscalls.h @@ -0,0 +1,93 @@ +/* + * syscalls.h - Linux syscall interfaces (arch-specific) + * + * Copyright (c) 2008 Jaswinder Singh + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#ifndef _ASM_X86_SYSCALLS_H +#define _ASM_X86_SYSCALLS_H + +#include <linux/compiler.h> +#include <linux/linkage.h> +#include <linux/types.h> +#include <linux/signal.h> + +/* Common in X86_32 and X86_64 */ +/* kernel/ioport.c */ +asmlinkage long sys_ioperm(unsigned long, unsigned long, int); + +/* X86_32 only */ +#ifdef CONFIG_X86_32 +/* kernel/process_32.c */ +asmlinkage int sys_fork(struct pt_regs); +asmlinkage int sys_clone(struct pt_regs); +asmlinkage int sys_vfork(struct pt_regs); +asmlinkage int sys_execve(struct pt_regs); + +/* kernel/signal_32.c */ +asmlinkage int sys_sigsuspend(int, int, old_sigset_t); +asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, + struct old_sigaction __user *); +asmlinkage int sys_sigaltstack(unsigned long); +asmlinkage unsigned long sys_sigreturn(unsigned long); +asmlinkage int sys_rt_sigreturn(unsigned long); + +/* kernel/ioport.c */ +asmlinkage long sys_iopl(unsigned long); + +/* kernel/ldt.c */ +asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); + +/* kernel/sys_i386_32.c */ +asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long, unsigned long); +struct mmap_arg_struct; +asmlinkage int old_mmap(struct mmap_arg_struct __user *); +struct sel_arg_struct; +asmlinkage int old_select(struct sel_arg_struct __user *); +asmlinkage int sys_ipc(uint, int, int, int, void __user *, long); +struct old_utsname; +asmlinkage int sys_uname(struct old_utsname __user *); +struct oldold_utsname; +asmlinkage int sys_olduname(struct oldold_utsname __user *); + +/* kernel/tls.c */ +asmlinkage int sys_set_thread_area(struct user_desc __user *); +asmlinkage int sys_get_thread_area(struct user_desc __user *); + +/* kernel/vm86_32.c */ +asmlinkage int sys_vm86old(struct pt_regs); +asmlinkage int sys_vm86(struct pt_regs); + +#else /* CONFIG_X86_32 */ + +/* X86_64 only */ +/* kernel/process_64.c */ +asmlinkage long sys_fork(struct pt_regs *); +asmlinkage long sys_clone(unsigned long, unsigned long, + void __user *, void __user *, + struct pt_regs *); +asmlinkage long sys_vfork(struct pt_regs *); +asmlinkage long sys_execve(char __user *, char __user * __user *, + char __user * __user *, + struct pt_regs *); + +/* kernel/ioport.c */ +asmlinkage long sys_iopl(unsigned int, struct pt_regs *); + +/* kernel/signal_64.c */ +asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *, + struct pt_regs *); +asmlinkage long sys_rt_sigreturn(struct pt_regs *); + +/* kernel/sys_x86_64.c */ +asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long, unsigned long); +struct new_utsname; +asmlinkage long sys_uname(struct new_utsname __user *); + +#endif /* CONFIG_X86_32 */ +#endif /* _ASM_X86_SYSCALLS_H */ diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h index 983ce37c491f..34505dd7b24d 100644 --- a/include/asm-x86/system.h +++ b/include/asm-x86/system.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_SYSTEM_H_ -#define _ASM_X86_SYSTEM_H_ +#ifndef ASM_X86__SYSTEM_H +#define ASM_X86__SYSTEM_H #include <asm/asm.h> #include <asm/segment.h> @@ -419,4 +419,4 @@ static inline void rdtsc_barrier(void) alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC); } -#endif +#endif /* ASM_X86__SYSTEM_H */ diff --git a/include/asm-x86/system_64.h b/include/asm-x86/system_64.h index 97fa251ccb2b..5aedb8bffc5a 100644 --- a/include/asm-x86/system_64.h +++ b/include/asm-x86/system_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_SYSTEM_H -#define __ASM_SYSTEM_H +#ifndef ASM_X86__SYSTEM_64_H +#define ASM_X86__SYSTEM_64_H #include <asm/segment.h> #include <asm/cmpxchg.h> @@ -19,4 +19,4 @@ static inline void write_cr8(unsigned long val) #include <linux/irqflags.h> -#endif +#endif /* ASM_X86__SYSTEM_64_H */ diff --git a/include/asm-x86/tce.h b/include/asm-x86/tce.h index b1a4ea00df78..e7932d7fbbab 100644 --- a/include/asm-x86/tce.h +++ b/include/asm-x86/tce.h @@ -21,8 +21,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _ASM_X86_64_TCE_H -#define _ASM_X86_64_TCE_H +#ifndef ASM_X86__TCE_H +#define ASM_X86__TCE_H extern unsigned int specified_table_size; struct iommu_table; @@ -45,4 +45,4 @@ extern void * __init alloc_tce_table(void); extern void __init free_tce_table(void *tbl); extern int __init build_tce_table(struct pci_dev *dev, void __iomem *bbar); -#endif /* _ASM_X86_64_TCE_H */ +#endif /* ASM_X86__TCE_H */ diff --git a/include/asm-x86/termbits.h b/include/asm-x86/termbits.h index af1b70ea440f..3d00dc5e0c71 100644 --- a/include/asm-x86/termbits.h +++ b/include/asm-x86/termbits.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TERMBITS_H -#define _ASM_X86_TERMBITS_H +#ifndef ASM_X86__TERMBITS_H +#define ASM_X86__TERMBITS_H #include <linux/posix_types.h> @@ -195,4 +195,4 @@ struct ktermios { #define TCSADRAIN 1 #define TCSAFLUSH 2 -#endif /* _ASM_X86_TERMBITS_H */ +#endif /* ASM_X86__TERMBITS_H */ diff --git a/include/asm-x86/termios.h b/include/asm-x86/termios.h index f72956331c49..e235db248071 100644 --- a/include/asm-x86/termios.h +++ b/include/asm-x86/termios.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TERMIOS_H -#define _ASM_X86_TERMIOS_H +#ifndef ASM_X86__TERMIOS_H +#define ASM_X86__TERMIOS_H #include <asm/termbits.h> #include <asm/ioctls.h> @@ -110,4 +110,4 @@ static inline int kernel_termios_to_user_termios_1(struct termios __user *u, #endif /* __KERNEL__ */ -#endif /* _ASM_X86_TERMIOS_H */ +#endif /* ASM_X86__TERMIOS_H */ diff --git a/include/asm-x86/therm_throt.h b/include/asm-x86/therm_throt.h index 399bf6026b16..1c7f57b6b66e 100644 --- a/include/asm-x86/therm_throt.h +++ b/include/asm-x86/therm_throt.h @@ -1,9 +1,9 @@ -#ifndef __ASM_I386_THERM_THROT_H__ -#define __ASM_I386_THERM_THROT_H__ 1 +#ifndef ASM_X86__THERM_THROT_H +#define ASM_X86__THERM_THROT_H #include <asm/atomic.h> extern atomic_t therm_throt_en; int therm_throt_process(int curr); -#endif /* __ASM_I386_THERM_THROT_H__ */ +#endif /* ASM_X86__THERM_THROT_H */ diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h index da0a675adf94..4db0066a3a35 100644 --- a/include/asm-x86/thread_info.h +++ b/include/asm-x86/thread_info.h @@ -4,8 +4,8 @@ * - Incorporating suggestions made by Linus Torvalds and Dave Miller */ -#ifndef _ASM_X86_THREAD_INFO_H -#define _ASM_X86_THREAD_INFO_H +#ifndef ASM_X86__THREAD_INFO_H +#define ASM_X86__THREAD_INFO_H #include <linux/compiler.h> #include <asm/page.h> @@ -71,6 +71,7 @@ struct thread_info { * Warning: layout of LSW is hardcoded in entry.S */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ @@ -93,6 +94,7 @@ struct thread_info { #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) @@ -133,7 +135,7 @@ struct thread_info { /* Only used for 64 bit */ #define _TIF_DO_NOTIFY_MASK \ - (_TIF_SIGPENDING|_TIF_MCE_NOTIFY) + (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME) /* flags to check in __switch_to() */ #define _TIF_WORK_CTXSW \ @@ -258,4 +260,4 @@ extern void free_thread_info(struct thread_info *ti); extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); #define arch_task_cache_init arch_task_cache_init #endif -#endif /* _ASM_X86_THREAD_INFO_H */ +#endif /* ASM_X86__THREAD_INFO_H */ diff --git a/include/asm-x86/time.h b/include/asm-x86/time.h index a17fa473e91d..3e724eef7ac4 100644 --- a/include/asm-x86/time.h +++ b/include/asm-x86/time.h @@ -1,5 +1,5 @@ -#ifndef _ASMX86_TIME_H -#define _ASMX86_TIME_H +#ifndef ASM_X86__TIME_H +#define ASM_X86__TIME_H extern void hpet_time_init(void); @@ -46,6 +46,8 @@ static inline int native_set_wallclock(unsigned long nowtime) #endif +extern void time_init(void); + #ifdef CONFIG_PARAVIRT #include <asm/paravirt.h> #else /* !CONFIG_PARAVIRT */ @@ -58,4 +60,4 @@ static inline int native_set_wallclock(unsigned long nowtime) extern unsigned long __init calibrate_cpu(void); -#endif +#endif /* ASM_X86__TIME_H */ diff --git a/include/asm-x86/timer.h b/include/asm-x86/timer.h index fb2a4ddddf3d..d0babce4b47a 100644 --- a/include/asm-x86/timer.h +++ b/include/asm-x86/timer.h @@ -1,5 +1,5 @@ -#ifndef _ASMi386_TIMER_H -#define _ASMi386_TIMER_H +#ifndef ASM_X86__TIMER_H +#define ASM_X86__TIMER_H #include <linux/init.h> #include <linux/pm.h> #include <linux/percpu.h> @@ -9,9 +9,12 @@ unsigned long long native_sched_clock(void); unsigned long native_calibrate_tsc(void); +#ifdef CONFIG_X86_32 extern int timer_ack; -extern int no_timer_check; extern int recalibrate_cpu_khz(void); +#endif /* CONFIG_X86_32 */ + +extern int no_timer_check; #ifndef CONFIG_PARAVIRT #define calibrate_tsc() native_calibrate_tsc() @@ -60,4 +63,4 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) return ns; } -#endif +#endif /* ASM_X86__TIMER_H */ diff --git a/include/asm-x86/timex.h b/include/asm-x86/timex.h index 43e5a78500c5..d1ce2416a5da 100644 --- a/include/asm-x86/timex.h +++ b/include/asm-x86/timex.h @@ -1,6 +1,6 @@ /* x86 architecture timex specifications */ -#ifndef _ASM_X86_TIMEX_H -#define _ASM_X86_TIMEX_H +#ifndef ASM_X86__TIMEX_H +#define ASM_X86__TIMEX_H #include <asm/processor.h> #include <asm/tsc.h> @@ -16,4 +16,4 @@ #define ARCH_HAS_READ_CURRENT_TIMER -#endif +#endif /* ASM_X86__TIMEX_H */ diff --git a/include/asm-x86/tlb.h b/include/asm-x86/tlb.h index e4e9e2d07a93..db36e9e89e87 100644 --- a/include/asm-x86/tlb.h +++ b/include/asm-x86/tlb.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TLB_H -#define _ASM_X86_TLB_H +#ifndef ASM_X86__TLB_H +#define ASM_X86__TLB_H #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) @@ -8,4 +8,4 @@ #include <asm-generic/tlb.h> -#endif +#endif /* ASM_X86__TLB_H */ diff --git a/include/asm-x86/tlbflush.h b/include/asm-x86/tlbflush.h index 35c76ceb9f40..ef68b76dc3c5 100644 --- a/include/asm-x86/tlbflush.h +++ b/include/asm-x86/tlbflush.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TLBFLUSH_H -#define _ASM_X86_TLBFLUSH_H +#ifndef ASM_X86__TLBFLUSH_H +#define ASM_X86__TLBFLUSH_H #include <linux/mm.h> #include <linux/sched.h> @@ -165,4 +165,4 @@ static inline void flush_tlb_kernel_range(unsigned long start, flush_tlb_all(); } -#endif /* _ASM_X86_TLBFLUSH_H */ +#endif /* ASM_X86__TLBFLUSH_H */ diff --git a/include/asm-x86/topology.h b/include/asm-x86/topology.h index 90ac7718469a..7eca9bc022b2 100644 --- a/include/asm-x86/topology.h +++ b/include/asm-x86/topology.h @@ -22,8 +22,8 @@ * * Send feedback to <colpatch@us.ibm.com> */ -#ifndef _ASM_X86_TOPOLOGY_H -#define _ASM_X86_TOPOLOGY_H +#ifndef ASM_X86__TOPOLOGY_H +#define ASM_X86__TOPOLOGY_H #ifdef CONFIG_X86_32 # ifdef CONFIG_X86_HT @@ -255,4 +255,4 @@ static inline void set_mp_bus_to_node(int busnum, int node) } #endif -#endif /* _ASM_X86_TOPOLOGY_H */ +#endif /* ASM_X86__TOPOLOGY_H */ diff --git a/include/asm-x86/trampoline.h b/include/asm-x86/trampoline.h index b156b08d0131..0406bbd898a9 100644 --- a/include/asm-x86/trampoline.h +++ b/include/asm-x86/trampoline.h @@ -1,5 +1,5 @@ -#ifndef __TRAMPOLINE_HEADER -#define __TRAMPOLINE_HEADER +#ifndef ASM_X86__TRAMPOLINE_H +#define ASM_X86__TRAMPOLINE_H #ifndef __ASSEMBLY__ @@ -18,4 +18,4 @@ extern unsigned long setup_trampoline(void); #endif /* __ASSEMBLY__ */ -#endif /* __TRAMPOLINE_HEADER */ +#endif /* ASM_X86__TRAMPOLINE_H */ diff --git a/include/asm-x86/traps.h b/include/asm-x86/traps.h index a4b65a71bd66..2ccebc6fb0b0 100644 --- a/include/asm-x86/traps.h +++ b/include/asm-x86/traps.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TRAPS_H -#define _ASM_X86_TRAPS_H +#ifndef ASM_X86__TRAPS_H +#define ASM_X86__TRAPS_H /* Common in X86_32 and X86_64 */ asmlinkage void divide_error(void); @@ -51,6 +51,8 @@ void do_spurious_interrupt_bug(struct pt_regs *, long); unsigned long patch_espfix_desc(unsigned long, unsigned long); asmlinkage void math_emulate(long); +void do_page_fault(struct pt_regs *regs, unsigned long error_code); + #else /* CONFIG_X86_32 */ asmlinkage void double_fault(void); @@ -62,5 +64,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *); asmlinkage void do_simd_coprocessor_error(struct pt_regs *); asmlinkage void do_spurious_interrupt_bug(struct pt_regs *); +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code); + #endif /* CONFIG_X86_32 */ -#endif /* _ASM_X86_TRAPS_H */ +#endif /* ASM_X86__TRAPS_H */ diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h index cb6f6ee45b8f..ad0f5c41e78c 100644 --- a/include/asm-x86/tsc.h +++ b/include/asm-x86/tsc.h @@ -1,8 +1,8 @@ /* * x86 TSC related functions */ -#ifndef _ASM_X86_TSC_H -#define _ASM_X86_TSC_H +#ifndef ASM_X86__TSC_H +#define ASM_X86__TSC_H #include <asm/processor.h> @@ -59,4 +59,4 @@ extern void check_tsc_sync_target(void); extern int notsc_setup(char *); -#endif +#endif /* ASM_X86__TSC_H */ diff --git a/include/asm-x86/types.h b/include/asm-x86/types.h index 1ac80cd9acf8..e78b52e17444 100644 --- a/include/asm-x86/types.h +++ b/include/asm-x86/types.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_TYPES_H -#define _ASM_X86_TYPES_H +#ifndef ASM_X86__TYPES_H +#define ASM_X86__TYPES_H #include <asm-generic/int-ll64.h> @@ -33,4 +33,4 @@ typedef u32 dma_addr_t; #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__TYPES_H */ diff --git a/include/asm-x86/uaccess.h b/include/asm-x86/uaccess.h index 5f702d1d5218..48ebc0ad40ec 100644 --- a/include/asm-x86/uaccess.h +++ b/include/asm-x86/uaccess.h @@ -1,5 +1,5 @@ -#ifndef _ASM_UACCES_H_ -#define _ASM_UACCES_H_ +#ifndef ASM_X86__UACCESS_H +#define ASM_X86__UACCESS_H /* * User space memory access functions */ @@ -450,5 +450,5 @@ extern struct movsl_mask { # include "uaccess_64.h" #endif -#endif +#endif /* ASM_X86__UACCESS_H */ diff --git a/include/asm-x86/uaccess_32.h b/include/asm-x86/uaccess_32.h index 6fdef39a0bcb..6b5b57d9c6d1 100644 --- a/include/asm-x86/uaccess_32.h +++ b/include/asm-x86/uaccess_32.h @@ -1,5 +1,5 @@ -#ifndef __i386_UACCESS_H -#define __i386_UACCESS_H +#ifndef ASM_X86__UACCESS_32_H +#define ASM_X86__UACCESS_32_H /* * User space memory access functions @@ -215,4 +215,4 @@ long strnlen_user(const char __user *str, long n); unsigned long __must_check clear_user(void __user *mem, unsigned long len); unsigned long __must_check __clear_user(void __user *mem, unsigned long len); -#endif /* __i386_UACCESS_H */ +#endif /* ASM_X86__UACCESS_32_H */ diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h index 45806d60bcbe..c96c1f5d07a2 100644 --- a/include/asm-x86/uaccess_64.h +++ b/include/asm-x86/uaccess_64.h @@ -1,5 +1,5 @@ -#ifndef __X86_64_UACCESS_H -#define __X86_64_UACCESS_H +#ifndef ASM_X86__UACCESS_64_H +#define ASM_X86__UACCESS_64_H /* * User space memory access functions @@ -199,4 +199,4 @@ static inline int __copy_from_user_inatomic_nocache(void *dst, unsigned long copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest); -#endif /* __X86_64_UACCESS_H */ +#endif /* ASM_X86__UACCESS_64_H */ diff --git a/include/asm-x86/ucontext.h b/include/asm-x86/ucontext.h index 50a79f7fcde9..9948dd328084 100644 --- a/include/asm-x86/ucontext.h +++ b/include/asm-x86/ucontext.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UCONTEXT_H -#define _ASM_X86_UCONTEXT_H +#ifndef ASM_X86__UCONTEXT_H +#define ASM_X86__UCONTEXT_H struct ucontext { unsigned long uc_flags; @@ -9,4 +9,4 @@ struct ucontext { sigset_t uc_sigmask; /* mask last for extensibility */ }; -#endif /* _ASM_X86_UCONTEXT_H */ +#endif /* ASM_X86__UCONTEXT_H */ diff --git a/include/asm-x86/unaligned.h b/include/asm-x86/unaligned.h index a7bd416b4763..59dcdec37160 100644 --- a/include/asm-x86/unaligned.h +++ b/include/asm-x86/unaligned.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UNALIGNED_H -#define _ASM_X86_UNALIGNED_H +#ifndef ASM_X86__UNALIGNED_H +#define ASM_X86__UNALIGNED_H /* * The x86 can do unaligned accesses itself. @@ -11,4 +11,4 @@ #define get_unaligned __get_unaligned_le #define put_unaligned __put_unaligned_le -#endif /* _ASM_X86_UNALIGNED_H */ +#endif /* ASM_X86__UNALIGNED_H */ diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h index d7394673b772..017f4a87c913 100644 --- a/include/asm-x86/unistd_32.h +++ b/include/asm-x86/unistd_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_I386_UNISTD_H_ -#define _ASM_I386_UNISTD_H_ +#ifndef ASM_X86__UNISTD_32_H +#define ASM_X86__UNISTD_32_H /* * This file contains the system call numbers. @@ -376,4 +376,4 @@ #endif #endif /* __KERNEL__ */ -#endif /* _ASM_I386_UNISTD_H_ */ +#endif /* ASM_X86__UNISTD_32_H */ diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h index 3a341d791792..ace83f1f6787 100644 --- a/include/asm-x86/unistd_64.h +++ b/include/asm-x86/unistd_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_UNISTD_H_ -#define _ASM_X86_64_UNISTD_H_ +#ifndef ASM_X86__UNISTD_64_H +#define ASM_X86__UNISTD_64_H #ifndef __SYSCALL #define __SYSCALL(a, b) @@ -690,4 +690,4 @@ __SYSCALL(__NR_inotify_init1, sys_inotify_init1) #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") #endif /* __KERNEL__ */ -#endif /* _ASM_X86_64_UNISTD_H_ */ +#endif /* ASM_X86__UNISTD_64_H */ diff --git a/include/asm-x86/unwind.h b/include/asm-x86/unwind.h index 8b064bd9c553..a2151567db44 100644 --- a/include/asm-x86/unwind.h +++ b/include/asm-x86/unwind.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UNWIND_H -#define _ASM_X86_UNWIND_H +#ifndef ASM_X86__UNWIND_H +#define ASM_X86__UNWIND_H #define UNW_PC(frame) ((void)(frame), 0UL) #define UNW_SP(frame) ((void)(frame), 0UL) @@ -10,4 +10,4 @@ static inline int arch_unw_user_mode(const void *info) return 0; } -#endif /* _ASM_X86_UNWIND_H */ +#endif /* ASM_X86__UNWIND_H */ diff --git a/include/asm-x86/user32.h b/include/asm-x86/user32.h index a3d910047879..aa66c1857f06 100644 --- a/include/asm-x86/user32.h +++ b/include/asm-x86/user32.h @@ -1,5 +1,5 @@ -#ifndef USER32_H -#define USER32_H 1 +#ifndef ASM_X86__USER32_H +#define ASM_X86__USER32_H /* IA32 compatible user structures for ptrace. * These should be used for 32bit coredumps too. */ @@ -67,4 +67,4 @@ struct user32 { }; -#endif +#endif /* ASM_X86__USER32_H */ diff --git a/include/asm-x86/user_32.h b/include/asm-x86/user_32.h index d6e51edc259d..e0fe2f55f1a6 100644 --- a/include/asm-x86/user_32.h +++ b/include/asm-x86/user_32.h @@ -1,5 +1,5 @@ -#ifndef _I386_USER_H -#define _I386_USER_H +#ifndef ASM_X86__USER_32_H +#define ASM_X86__USER_32_H #include <asm/page.h> /* Core file format: The core file is written in such a way that gdb @@ -128,4 +128,4 @@ struct user{ #define HOST_TEXT_START_ADDR (u.start_code) #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) -#endif /* _I386_USER_H */ +#endif /* ASM_X86__USER_32_H */ diff --git a/include/asm-x86/user_64.h b/include/asm-x86/user_64.h index 6037b634c77f..38b5799863b4 100644 --- a/include/asm-x86/user_64.h +++ b/include/asm-x86/user_64.h @@ -1,5 +1,5 @@ -#ifndef _X86_64_USER_H -#define _X86_64_USER_H +#ifndef ASM_X86__USER_64_H +#define ASM_X86__USER_64_H #include <asm/types.h> #include <asm/page.h> @@ -134,4 +134,4 @@ struct user { #define HOST_TEXT_START_ADDR (u.start_code) #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) -#endif /* _X86_64_USER_H */ +#endif /* ASM_X86__USER_64_H */ diff --git a/include/asm-x86/uv/bios.h b/include/asm-x86/uv/bios.h index aa73362ff5df..7cd6d7ec1308 100644 --- a/include/asm-x86/uv/bios.h +++ b/include/asm-x86/uv/bios.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_BIOS_H -#define _ASM_X86_BIOS_H +#ifndef ASM_X86__UV__BIOS_H +#define ASM_X86__UV__BIOS_H /* * BIOS layer definitions. @@ -65,4 +65,4 @@ x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second, unsigned long *drift_info); extern const char *x86_bios_strerror(long status); -#endif /* _ASM_X86_BIOS_H */ +#endif /* ASM_X86__UV__BIOS_H */ diff --git a/include/asm-x86/uv/uv_bau.h b/include/asm-x86/uv/uv_bau.h index 610b6b308e93..77153fb18f5e 100644 --- a/include/asm-x86/uv/uv_bau.h +++ b/include/asm-x86/uv/uv_bau.h @@ -8,8 +8,8 @@ * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved. */ -#ifndef __ASM_X86_UV_BAU__ -#define __ASM_X86_UV_BAU__ +#ifndef ASM_X86__UV__UV_BAU_H +#define ASM_X86__UV__UV_BAU_H #include <linux/bitmap.h> #define BITSPERBYTE 8 @@ -329,4 +329,4 @@ extern int uv_flush_tlb_others(cpumask_t *, struct mm_struct *, unsigned long); extern void uv_bau_message_intr1(void); extern void uv_bau_timeout_intr1(void); -#endif /* __ASM_X86_UV_BAU__ */ +#endif /* ASM_X86__UV__UV_BAU_H */ diff --git a/include/asm-x86/uv/uv_hub.h b/include/asm-x86/uv/uv_hub.h index a4ef26e5850b..bdb5b01afbf5 100644 --- a/include/asm-x86/uv/uv_hub.h +++ b/include/asm-x86/uv/uv_hub.h @@ -8,8 +8,8 @@ * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. */ -#ifndef __ASM_X86_UV_HUB_H__ -#define __ASM_X86_UV_HUB_H__ +#ifndef ASM_X86__UV__UV_HUB_H +#define ASM_X86__UV__UV_HUB_H #include <linux/numa.h> #include <linux/percpu.h> @@ -350,5 +350,5 @@ static inline int uv_num_possible_blades(void) return uv_possible_blades; } -#endif /* __ASM_X86_UV_HUB__ */ +#endif /* ASM_X86__UV__UV_HUB_H */ diff --git a/include/asm-x86/uv/uv_mmrs.h b/include/asm-x86/uv/uv_mmrs.h index 151fd7fcb809..8b03d89d2459 100644 --- a/include/asm-x86/uv/uv_mmrs.h +++ b/include/asm-x86/uv/uv_mmrs.h @@ -8,8 +8,8 @@ * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. */ -#ifndef __ASM_X86_UV_MMRS__ -#define __ASM_X86_UV_MMRS__ +#ifndef ASM_X86__UV__UV_MMRS_H +#define ASM_X86__UV__UV_MMRS_H #define UV_MMR_ENABLE (1UL << 63) @@ -1292,4 +1292,4 @@ union uvh_si_alias2_overlay_config_u { }; -#endif /* __ASM_X86_UV_MMRS__ */ +#endif /* ASM_X86__UV__UV_MMRS_H */ diff --git a/include/asm-x86/vdso.h b/include/asm-x86/vdso.h index 8e18fb80f5e6..4ab320913ea3 100644 --- a/include/asm-x86/vdso.h +++ b/include/asm-x86/vdso.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_VDSO_H -#define _ASM_X86_VDSO_H 1 +#ifndef ASM_X86__VDSO_H +#define ASM_X86__VDSO_H #ifdef CONFIG_X86_64 extern const char VDSO64_PRELINK[]; @@ -44,4 +44,4 @@ extern const char vdso32_int80_start, vdso32_int80_end; extern const char vdso32_syscall_start, vdso32_syscall_end; extern const char vdso32_sysenter_start, vdso32_sysenter_end; -#endif /* asm-x86/vdso.h */ +#endif /* ASM_X86__VDSO_H */ diff --git a/include/asm-x86/vga.h b/include/asm-x86/vga.h index 0ccf804377e6..b9e493d07d07 100644 --- a/include/asm-x86/vga.h +++ b/include/asm-x86/vga.h @@ -4,8 +4,8 @@ * (c) 1998 Martin Mares <mj@ucw.cz> */ -#ifndef _LINUX_ASM_VGA_H_ -#define _LINUX_ASM_VGA_H_ +#ifndef ASM_X86__VGA_H +#define ASM_X86__VGA_H /* * On the PC, we can just recalculate addresses and then @@ -17,4 +17,4 @@ #define vga_readb(x) (*(x)) #define vga_writeb(x, y) (*(y) = (x)) -#endif +#endif /* ASM_X86__VGA_H */ diff --git a/include/asm-x86/vgtod.h b/include/asm-x86/vgtod.h index 3301f0929342..38fd13364021 100644 --- a/include/asm-x86/vgtod.h +++ b/include/asm-x86/vgtod.h @@ -1,5 +1,5 @@ -#ifndef _ASM_VGTOD_H -#define _ASM_VGTOD_H 1 +#ifndef ASM_X86__VGTOD_H +#define ASM_X86__VGTOD_H #include <asm/vsyscall.h> #include <linux/clocksource.h> @@ -26,4 +26,4 @@ extern struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data; extern struct vsyscall_gtod_data vsyscall_gtod_data; -#endif +#endif /* ASM_X86__VGTOD_H */ diff --git a/include/asm-x86/visws/cobalt.h b/include/asm-x86/visws/cobalt.h index 995258831b7f..9627a8fe84e9 100644 --- a/include/asm-x86/visws/cobalt.h +++ b/include/asm-x86/visws/cobalt.h @@ -1,5 +1,5 @@ -#ifndef __I386_SGI_COBALT_H -#define __I386_SGI_COBALT_H +#ifndef ASM_X86__VISWS__COBALT_H +#define ASM_X86__VISWS__COBALT_H #include <asm/fixmap.h> @@ -122,4 +122,4 @@ extern char visws_board_type; extern char visws_board_rev; -#endif /* __I386_SGI_COBALT_H */ +#endif /* ASM_X86__VISWS__COBALT_H */ diff --git a/include/asm-x86/visws/lithium.h b/include/asm-x86/visws/lithium.h index dfcd4f07ab85..b36d3b378c63 100644 --- a/include/asm-x86/visws/lithium.h +++ b/include/asm-x86/visws/lithium.h @@ -1,5 +1,5 @@ -#ifndef __I386_SGI_LITHIUM_H -#define __I386_SGI_LITHIUM_H +#ifndef ASM_X86__VISWS__LITHIUM_H +#define ASM_X86__VISWS__LITHIUM_H #include <asm/fixmap.h> @@ -49,5 +49,5 @@ static inline unsigned short li_pcib_read16(unsigned long reg) return *((volatile unsigned short *)(LI_PCIB_VADDR+reg)); } -#endif +#endif /* ASM_X86__VISWS__LITHIUM_H */ diff --git a/include/asm-x86/visws/piix4.h b/include/asm-x86/visws/piix4.h index 83ea4f46e419..61c938045ec9 100644 --- a/include/asm-x86/visws/piix4.h +++ b/include/asm-x86/visws/piix4.h @@ -1,5 +1,5 @@ -#ifndef __I386_SGI_PIIX_H -#define __I386_SGI_PIIX_H +#ifndef ASM_X86__VISWS__PIIX4_H +#define ASM_X86__VISWS__PIIX4_H /* * PIIX4 as used on SGI Visual Workstations @@ -104,4 +104,4 @@ */ #define PIIX_GPI_STPCLK 0x4 // STPCLK signal routed back in -#endif +#endif /* ASM_X86__VISWS__PIIX4_H */ diff --git a/include/asm-x86/vm86.h b/include/asm-x86/vm86.h index 5ce351325e01..998bd18eb737 100644 --- a/include/asm-x86/vm86.h +++ b/include/asm-x86/vm86.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_VM86_H -#define _LINUX_VM86_H +#ifndef ASM_X86__VM86_H +#define ASM_X86__VM86_H /* * I'm guessing at the VIF/VIP flag usage, but hope that this is how @@ -205,4 +205,4 @@ static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c) #endif /* __KERNEL__ */ -#endif +#endif /* ASM_X86__VM86_H */ diff --git a/include/asm-x86/vmi_time.h b/include/asm-x86/vmi_time.h index c3118c385156..b2d39e6a08b7 100644 --- a/include/asm-x86/vmi_time.h +++ b/include/asm-x86/vmi_time.h @@ -22,8 +22,8 @@ * */ -#ifndef __VMI_TIME_H -#define __VMI_TIME_H +#ifndef ASM_X86__VMI_TIME_H +#define ASM_X86__VMI_TIME_H /* * Raw VMI call indices for timer functions @@ -95,4 +95,4 @@ extern void __devinit vmi_time_ap_init(void); #define CONFIG_VMI_ALARM_HZ 100 -#endif +#endif /* ASM_X86__VMI_TIME_H */ diff --git a/include/asm-x86/vsyscall.h b/include/asm-x86/vsyscall.h index 6b66ff905af0..dcd4682413de 100644 --- a/include/asm-x86/vsyscall.h +++ b/include/asm-x86/vsyscall.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_64_VSYSCALL_H_ -#define _ASM_X86_64_VSYSCALL_H_ +#ifndef ASM_X86__VSYSCALL_H +#define ASM_X86__VSYSCALL_H enum vsyscall_num { __NR_vgettimeofday, @@ -41,4 +41,4 @@ extern void map_vsyscall(void); #endif /* __KERNEL__ */ -#endif /* _ASM_X86_64_VSYSCALL_H_ */ +#endif /* ASM_X86__VSYSCALL_H */ diff --git a/include/asm-x86/xen/events.h b/include/asm-x86/xen/events.h index 8ded74720024..8151f5b8b6cb 100644 --- a/include/asm-x86/xen/events.h +++ b/include/asm-x86/xen/events.h @@ -1,5 +1,5 @@ -#ifndef __XEN_EVENTS_H -#define __XEN_EVENTS_H +#ifndef ASM_X86__XEN__EVENTS_H +#define ASM_X86__XEN__EVENTS_H enum ipi_vector { XEN_RESCHEDULE_VECTOR, @@ -21,4 +21,4 @@ static inline void xen_do_IRQ(int irq, struct pt_regs *regs) do_IRQ(regs); } -#endif /* __XEN_EVENTS_H */ +#endif /* ASM_X86__XEN__EVENTS_H */ diff --git a/include/asm-x86/xen/grant_table.h b/include/asm-x86/xen/grant_table.h index 2444d4593a3b..c4baab4d2b68 100644 --- a/include/asm-x86/xen/grant_table.h +++ b/include/asm-x86/xen/grant_table.h @@ -1,7 +1,7 @@ -#ifndef __XEN_GRANT_TABLE_H -#define __XEN_GRANT_TABLE_H +#ifndef ASM_X86__XEN__GRANT_TABLE_H +#define ASM_X86__XEN__GRANT_TABLE_H #define xen_alloc_vm_area(size) alloc_vm_area(size) #define xen_free_vm_area(area) free_vm_area(area) -#endif /* __XEN_GRANT_TABLE_H */ +#endif /* ASM_X86__XEN__GRANT_TABLE_H */ diff --git a/include/asm-x86/xen/hypercall.h b/include/asm-x86/xen/hypercall.h index 91cb7fd5c123..44f4259bee3f 100644 --- a/include/asm-x86/xen/hypercall.h +++ b/include/asm-x86/xen/hypercall.h @@ -30,8 +30,8 @@ * IN THE SOFTWARE. */ -#ifndef __HYPERCALL_H__ -#define __HYPERCALL_H__ +#ifndef ASM_X86__XEN__HYPERCALL_H +#define ASM_X86__XEN__HYPERCALL_H #include <linux/errno.h> #include <linux/string.h> @@ -524,4 +524,4 @@ MULTI_stack_switch(struct multicall_entry *mcl, mcl->args[1] = esp; } -#endif /* __HYPERCALL_H__ */ +#endif /* ASM_X86__XEN__HYPERCALL_H */ diff --git a/include/asm-x86/xen/hypervisor.h b/include/asm-x86/xen/hypervisor.h index 04ee0610014a..0ef3a88b869d 100644 --- a/include/asm-x86/xen/hypervisor.h +++ b/include/asm-x86/xen/hypervisor.h @@ -30,8 +30,8 @@ * IN THE SOFTWARE. */ -#ifndef __HYPERVISOR_H__ -#define __HYPERVISOR_H__ +#ifndef ASM_X86__XEN__HYPERVISOR_H +#define ASM_X86__XEN__HYPERVISOR_H #include <linux/types.h> #include <linux/kernel.h> @@ -69,4 +69,4 @@ u64 jiffies_to_st(unsigned long jiffies); #define is_running_on_xen() (xen_start_info ? 1 : 0) -#endif /* __HYPERVISOR_H__ */ +#endif /* ASM_X86__XEN__HYPERVISOR_H */ diff --git a/include/asm-x86/xen/interface.h b/include/asm-x86/xen/interface.h index 9d810f2538a2..d077bba96da9 100644 --- a/include/asm-x86/xen/interface.h +++ b/include/asm-x86/xen/interface.h @@ -6,8 +6,8 @@ * Copyright (c) 2004, K A Fraser */ -#ifndef __ASM_X86_XEN_INTERFACE_H -#define __ASM_X86_XEN_INTERFACE_H +#ifndef ASM_X86__XEN__INTERFACE_H +#define ASM_X86__XEN__INTERFACE_H #ifdef __XEN__ #define __DEFINE_GUEST_HANDLE(name, type) \ @@ -172,4 +172,4 @@ DEFINE_GUEST_HANDLE_STRUCT(vcpu_guest_context); #define XEN_CPUID XEN_EMULATE_PREFIX "cpuid" #endif -#endif /* __ASM_X86_XEN_INTERFACE_H */ +#endif /* ASM_X86__XEN__INTERFACE_H */ diff --git a/include/asm-x86/xen/interface_32.h b/include/asm-x86/xen/interface_32.h index d8ac41d5db86..08167e19fc66 100644 --- a/include/asm-x86/xen/interface_32.h +++ b/include/asm-x86/xen/interface_32.h @@ -6,8 +6,8 @@ * Copyright (c) 2004, K A Fraser */ -#ifndef __ASM_X86_XEN_INTERFACE_32_H -#define __ASM_X86_XEN_INTERFACE_32_H +#ifndef ASM_X86__XEN__INTERFACE_32_H +#define ASM_X86__XEN__INTERFACE_32_H /* @@ -94,4 +94,4 @@ typedef struct xen_callback xen_callback_t; #define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20)) #define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20)) -#endif /* __ASM_X86_XEN_INTERFACE_32_H */ +#endif /* ASM_X86__XEN__INTERFACE_32_H */ diff --git a/include/asm-x86/xen/interface_64.h b/include/asm-x86/xen/interface_64.h index 842266ce96e6..046c0f1e01d4 100644 --- a/include/asm-x86/xen/interface_64.h +++ b/include/asm-x86/xen/interface_64.h @@ -1,5 +1,5 @@ -#ifndef __ASM_X86_XEN_INTERFACE_64_H -#define __ASM_X86_XEN_INTERFACE_64_H +#ifndef ASM_X86__XEN__INTERFACE_64_H +#define ASM_X86__XEN__INTERFACE_64_H /* * 64-bit segment selectors @@ -156,4 +156,4 @@ typedef unsigned long xen_callback_t; #endif /* !__ASSEMBLY__ */ -#endif /* __ASM_X86_XEN_INTERFACE_64_H */ +#endif /* ASM_X86__XEN__INTERFACE_64_H */ diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h index 7b3835d3b77d..c50185dccec1 100644 --- a/include/asm-x86/xen/page.h +++ b/include/asm-x86/xen/page.h @@ -1,5 +1,5 @@ -#ifndef __XEN_PAGE_H -#define __XEN_PAGE_H +#ifndef ASM_X86__XEN__PAGE_H +#define ASM_X86__XEN__PAGE_H #include <linux/pfn.h> @@ -162,4 +162,4 @@ xmaddr_t arbitrary_virt_to_machine(void *address); void make_lowmem_page_readonly(void *vaddr); void make_lowmem_page_readwrite(void *vaddr); -#endif /* __XEN_PAGE_H */ +#endif /* ASM_X86__XEN__PAGE_H */ diff --git a/include/crypto/internal/rng.h b/include/crypto/internal/rng.h new file mode 100644 index 000000000000..896973369573 --- /dev/null +++ b/include/crypto/internal/rng.h @@ -0,0 +1,26 @@ +/* + * RNG: Random Number Generator algorithms under the crypto API + * + * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#ifndef _CRYPTO_INTERNAL_RNG_H +#define _CRYPTO_INTERNAL_RNG_H + +#include <crypto/algapi.h> +#include <crypto/rng.h> + +extern const struct crypto_type crypto_rng_type; + +static inline void *crypto_rng_ctx(struct crypto_rng *tfm) +{ + return crypto_tfm_ctx(&tfm->base); +} + +#endif diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index ccc32bad9a89..2ba42cd7d6aa 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -15,7 +15,6 @@ #include <crypto/algapi.h> #include <crypto/skcipher.h> -#include <linux/init.h> #include <linux/types.h> struct rtattr; @@ -65,11 +64,6 @@ void skcipher_geniv_free(struct crypto_instance *inst); int skcipher_geniv_init(struct crypto_tfm *tfm); void skcipher_geniv_exit(struct crypto_tfm *tfm); -int __init eseqiv_module_init(void); -void __exit eseqiv_module_exit(void); -int __init chainiv_module_init(void); -void chainiv_module_exit(void); - static inline struct crypto_ablkcipher *skcipher_geniv_cipher( struct crypto_ablkcipher *geniv) { diff --git a/include/crypto/rng.h b/include/crypto/rng.h new file mode 100644 index 000000000000..c93f9b917925 --- /dev/null +++ b/include/crypto/rng.h @@ -0,0 +1,75 @@ +/* + * RNG: Random Number Generator algorithms under the crypto API + * + * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#ifndef _CRYPTO_RNG_H +#define _CRYPTO_RNG_H + +#include <linux/crypto.h> + +extern struct crypto_rng *crypto_default_rng; + +int crypto_get_default_rng(void); +void crypto_put_default_rng(void); + +static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm) +{ + return (struct crypto_rng *)tfm; +} + +static inline struct crypto_rng *crypto_alloc_rng(const char *alg_name, + u32 type, u32 mask) +{ + type &= ~CRYPTO_ALG_TYPE_MASK; + type |= CRYPTO_ALG_TYPE_RNG; + mask |= CRYPTO_ALG_TYPE_MASK; + + return __crypto_rng_cast(crypto_alloc_base(alg_name, type, mask)); +} + +static inline struct crypto_tfm *crypto_rng_tfm(struct crypto_rng *tfm) +{ + return &tfm->base; +} + +static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm) +{ + return &crypto_rng_tfm(tfm)->__crt_alg->cra_rng; +} + +static inline struct rng_tfm *crypto_rng_crt(struct crypto_rng *tfm) +{ + return &crypto_rng_tfm(tfm)->crt_rng; +} + +static inline void crypto_free_rng(struct crypto_rng *tfm) +{ + crypto_free_tfm(crypto_rng_tfm(tfm)); +} + +static inline int crypto_rng_get_bytes(struct crypto_rng *tfm, + u8 *rdata, unsigned int dlen) +{ + return crypto_rng_crt(tfm)->rng_gen_random(tfm, rdata, dlen); +} + +static inline int crypto_rng_reset(struct crypto_rng *tfm, + u8 *seed, unsigned int slen) +{ + return crypto_rng_crt(tfm)->rng_reset(tfm, seed, slen); +} + +static inline int crypto_rng_seedsize(struct crypto_rng *tfm) +{ + return crypto_rng_alg(tfm)->seedsize; +} + +#endif diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b68ec09399be..31474e89c59a 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -180,6 +180,7 @@ unifdef-y += audit.h unifdef-y += auto_fs.h unifdef-y += auxvec.h unifdef-y += binfmts.h +unifdef-y += blktrace_api.h unifdef-y += capability.h unifdef-y += capi.h unifdef-y += cciss_ioctl.h diff --git a/include/linux/ata.h b/include/linux/ata.h index 8a12d718c169..be00973d1a8c 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -88,6 +88,7 @@ enum { ATA_ID_DLF = 128, ATA_ID_CSFO = 129, ATA_ID_CFA_POWER = 160, + ATA_ID_ROT_SPEED = 217, ATA_ID_PIO4 = (1 << 1), ATA_ID_SERNO_LEN = 20, @@ -667,6 +668,15 @@ static inline int ata_id_has_dword_io(const u16 *id) return 0; } +static inline int ata_id_has_unload(const u16 *id) +{ + if (ata_id_major_version(id) >= 7 && + (id[ATA_ID_CFSSE] & 0xC000) == 0x4000 && + id[ATA_ID_CFSSE] & (1 << 13)) + return 1; + return 0; +} + static inline int ata_id_current_chs_valid(const u16 *id) { /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command @@ -691,6 +701,11 @@ static inline int ata_id_is_cfa(const u16 *id) return 0; } +static inline int ata_id_is_ssd(const u16 *id) +{ + return id[ATA_ID_ROT_SPEED] == 0x01; +} + static inline int ata_drive_40wire(const u16 *dev_id) { if (ata_id_is_sata(dev_id)) diff --git a/include/linux/bio.h b/include/linux/bio.h index 0933a14e6414..ff5b4cf9e2da 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -26,21 +26,8 @@ #ifdef CONFIG_BLOCK -/* Platforms may set this to teach the BIO layer about IOMMU hardware. */ #include <asm/io.h> -#if defined(BIO_VMERGE_MAX_SIZE) && defined(BIO_VMERGE_BOUNDARY) -#define BIOVEC_VIRT_START_SIZE(x) (bvec_to_phys(x) & (BIO_VMERGE_BOUNDARY - 1)) -#define BIOVEC_VIRT_OVERSIZE(x) ((x) > BIO_VMERGE_MAX_SIZE) -#else -#define BIOVEC_VIRT_START_SIZE(x) 0 -#define BIOVEC_VIRT_OVERSIZE(x) 0 -#endif - -#ifndef BIO_VMERGE_BOUNDARY -#define BIO_VMERGE_BOUNDARY 0 -#endif - #define BIO_DEBUG #ifdef BIO_DEBUG @@ -88,25 +75,14 @@ struct bio { /* Number of segments in this BIO after * physical address coalescing is performed. */ - unsigned short bi_phys_segments; - - /* Number of segments after physical and DMA remapping - * hardware coalescing is performed. - */ - unsigned short bi_hw_segments; + unsigned int bi_phys_segments; unsigned int bi_size; /* residual I/O count */ - /* - * To keep track of the max hw size, we account for the - * sizes of the first and last virtually mergeable segments - * in this bio - */ - unsigned int bi_hw_front_size; - unsigned int bi_hw_back_size; - unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ + unsigned int bi_comp_cpu; /* completion CPU */ + struct bio_vec *bi_io_vec; /* the actual vec list */ bio_end_io_t *bi_end_io; @@ -126,11 +102,14 @@ struct bio { #define BIO_UPTODATE 0 /* ok after I/O completion */ #define BIO_RW_BLOCK 1 /* RW_AHEAD set, and read/write would block */ #define BIO_EOF 2 /* out-out-bounds error */ -#define BIO_SEG_VALID 3 /* nr_hw_seg valid */ +#define BIO_SEG_VALID 3 /* bi_phys_segments valid */ #define BIO_CLONED 4 /* doesn't own data */ #define BIO_BOUNCED 5 /* bio is a bounce bio */ #define BIO_USER_MAPPED 6 /* contains user pages */ #define BIO_EOPNOTSUPP 7 /* not supported */ +#define BIO_CPU_AFFINE 8 /* complete bio on same CPU as submitted */ +#define BIO_NULL_MAPPED 9 /* contains invalid user pages */ +#define BIO_FS_INTEGRITY 10 /* fs owns integrity data, not block layer */ #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) /* @@ -144,18 +123,31 @@ struct bio { /* * bio bi_rw flags * - * bit 0 -- read (not set) or write (set) + * bit 0 -- data direction + * If not set, bio is a read from device. If set, it's a write to device. * bit 1 -- rw-ahead when set * bit 2 -- barrier + * Insert a serialization point in the IO queue, forcing previously + * submitted IO to be completed before this oen is issued. * bit 3 -- fail fast, don't want low level driver retries * bit 4 -- synchronous I/O hint: the block layer will unplug immediately + * Note that this does NOT indicate that the IO itself is sync, just + * that the block layer will not postpone issue of this IO by plugging. + * bit 5 -- metadata request + * Used for tracing to differentiate metadata and data IO. May also + * get some preferential treatment in the IO scheduler + * bit 6 -- discard sectors + * Informs the lower level device that this range of sectors is no longer + * used by the file system and may thus be freed by the device. Used + * for flash based storage. */ -#define BIO_RW 0 -#define BIO_RW_AHEAD 1 +#define BIO_RW 0 /* Must match RW in req flags (blkdev.h) */ +#define BIO_RW_AHEAD 1 /* Must match FAILFAST in req flags */ #define BIO_RW_BARRIER 2 #define BIO_RW_FAILFAST 3 #define BIO_RW_SYNC 4 #define BIO_RW_META 5 +#define BIO_RW_DISCARD 6 /* * upper 16 bits of bi_rw define the io priority of this bio @@ -185,14 +177,15 @@ struct bio { #define bio_failfast(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST)) #define bio_rw_ahead(bio) ((bio)->bi_rw & (1 << BIO_RW_AHEAD)) #define bio_rw_meta(bio) ((bio)->bi_rw & (1 << BIO_RW_META)) -#define bio_empty_barrier(bio) (bio_barrier(bio) && !(bio)->bi_size) +#define bio_discard(bio) ((bio)->bi_rw & (1 << BIO_RW_DISCARD)) +#define bio_empty_barrier(bio) (bio_barrier(bio) && !bio_has_data(bio) && !bio_discard(bio)) static inline unsigned int bio_cur_sectors(struct bio *bio) { if (bio->bi_vcnt) return bio_iovec(bio)->bv_len >> 9; - - return 0; + else /* dataless requests such as discard */ + return bio->bi_size >> 9; } static inline void *bio_data(struct bio *bio) @@ -236,8 +229,6 @@ static inline void *bio_data(struct bio *bio) ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) #endif -#define BIOVEC_VIRT_MERGEABLE(vec1, vec2) \ - ((((bvec_to_phys((vec1)) + (vec1)->bv_len) | bvec_to_phys((vec2))) & (BIO_VMERGE_BOUNDARY - 1)) == 0) #define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \ (((addr1) | (mask)) == (((addr2) - 1) | (mask))) #define BIOVEC_SEG_BOUNDARY(q, b1, b2) \ @@ -319,15 +310,14 @@ struct bio_pair { atomic_t cnt; int error; }; -extern struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, - int first_sectors); -extern mempool_t *bio_split_pool; +extern struct bio_pair *bio_split(struct bio *bi, int first_sectors); extern void bio_pair_release(struct bio_pair *dbio); extern struct bio_set *bioset_create(int, int); extern void bioset_free(struct bio_set *); extern struct bio *bio_alloc(gfp_t, int); +extern struct bio *bio_kmalloc(gfp_t, int); extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); extern void bio_put(struct bio *); extern void bio_free(struct bio *, struct bio_set *); @@ -335,7 +325,6 @@ extern void bio_free(struct bio *, struct bio_set *); extern void bio_endio(struct bio *, int); struct request_queue; extern int bio_phys_segments(struct request_queue *, struct bio *); -extern int bio_hw_segments(struct request_queue *, struct bio *); extern void __bio_clone(struct bio *, struct bio *); extern struct bio *bio_clone(struct bio *, gfp_t); @@ -346,12 +335,14 @@ extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, unsigned int, unsigned int); extern int bio_get_nr_vecs(struct block_device *); +extern sector_t bio_sector_offset(struct bio *, unsigned short, unsigned int); extern struct bio *bio_map_user(struct request_queue *, struct block_device *, - unsigned long, unsigned int, int); + unsigned long, unsigned int, int, gfp_t); struct sg_iovec; +struct rq_map_data; extern struct bio *bio_map_user_iov(struct request_queue *, struct block_device *, - struct sg_iovec *, int, int); + struct sg_iovec *, int, int, gfp_t); extern void bio_unmap_user(struct bio *); extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int, gfp_t); @@ -359,15 +350,25 @@ extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int, gfp_t, int); extern void bio_set_pages_dirty(struct bio *bio); extern void bio_check_pages_dirty(struct bio *bio); -extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int); -extern struct bio *bio_copy_user_iov(struct request_queue *, struct sg_iovec *, - int, int); +extern struct bio *bio_copy_user(struct request_queue *, struct rq_map_data *, + unsigned long, unsigned int, int, gfp_t); +extern struct bio *bio_copy_user_iov(struct request_queue *, + struct rq_map_data *, struct sg_iovec *, + int, int, gfp_t); extern int bio_uncopy_user(struct bio *); void zero_fill_bio(struct bio *bio); extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set *); extern unsigned int bvec_nr_vecs(unsigned short idx); /* + * Allow queuer to specify a completion CPU for this bio + */ +static inline void bio_set_completion_cpu(struct bio *bio, unsigned int cpu) +{ + bio->bi_comp_cpu = cpu; +} + +/* * bio_set is used to allow other portions of the IO system to * allocate their own private memory pools for bio and iovec structures. * These memory pools in turn all allocate from the bio_slab @@ -445,6 +446,14 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx, __bio_kmap_irq((bio), (bio)->bi_idx, (flags)) #define bio_kunmap_irq(buf,flags) __bio_kunmap_irq(buf, flags) +/* + * Check whether this bio carries any data or not. A NULL bio is allowed. + */ +static inline int bio_has_data(struct bio *bio) +{ + return bio && bio->bi_io_vec != NULL; +} + #if defined(CONFIG_BLK_DEV_INTEGRITY) #define bip_vec_idx(bip, idx) (&(bip->bip_vec[(idx)])) @@ -458,14 +467,7 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx, #define bip_for_each_vec(bvl, bip, i) \ __bip_for_each_vec(bvl, bip, i, (bip)->bip_idx) -static inline int bio_integrity(struct bio *bio) -{ -#if defined(CONFIG_BLK_DEV_INTEGRITY) - return bio->bi_integrity != NULL; -#else - return 0; -#endif -} +#define bio_integrity(bio) (bio->bi_integrity != NULL) extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *); extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 53ea933cf60b..a92d9e4ea96e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -16,7 +16,9 @@ #include <linux/bio.h> #include <linux/module.h> #include <linux/stringify.h> +#include <linux/gfp.h> #include <linux/bsg.h> +#include <linux/smp.h> #include <asm/scatterlist.h> @@ -54,7 +56,6 @@ enum rq_cmd_type_bits { REQ_TYPE_PM_SUSPEND, /* suspend request */ REQ_TYPE_PM_RESUME, /* resume request */ REQ_TYPE_PM_SHUTDOWN, /* shutdown request */ - REQ_TYPE_FLUSH, /* flush request */ REQ_TYPE_SPECIAL, /* driver defined type */ REQ_TYPE_LINUX_BLOCK, /* generic block layer message */ /* @@ -76,19 +77,18 @@ enum rq_cmd_type_bits { * */ enum { - /* - * just examples for now - */ REQ_LB_OP_EJECT = 0x40, /* eject request */ - REQ_LB_OP_FLUSH = 0x41, /* flush device */ + REQ_LB_OP_FLUSH = 0x41, /* flush request */ + REQ_LB_OP_DISCARD = 0x42, /* discard sectors */ }; /* - * request type modified bits. first three bits match BIO_RW* bits, important + * request type modified bits. first two bits match BIO_RW* bits, important */ enum rq_flag_bits { __REQ_RW, /* not set, read. set, write */ __REQ_FAILFAST, /* no low level driver retries */ + __REQ_DISCARD, /* request to discard sectors */ __REQ_SORTED, /* elevator knows about this request */ __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ __REQ_HARDBARRIER, /* may not be passed by drive either */ @@ -111,6 +111,7 @@ enum rq_flag_bits { }; #define REQ_RW (1 << __REQ_RW) +#define REQ_DISCARD (1 << __REQ_DISCARD) #define REQ_FAILFAST (1 << __REQ_FAILFAST) #define REQ_SORTED (1 << __REQ_SORTED) #define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER) @@ -140,12 +141,14 @@ enum rq_flag_bits { */ struct request { struct list_head queuelist; - struct list_head donelist; + struct call_single_data csd; + int cpu; struct request_queue *q; unsigned int cmd_flags; enum rq_cmd_type_bits cmd_type; + unsigned long atomic_flags; /* Maintain bio traversal state for part by part I/O submission. * hard_* are block layer internals, no driver should touch them! @@ -190,13 +193,6 @@ struct request { */ unsigned short nr_phys_segments; - /* Number of scatter-gather addr+len pairs after - * physical and DMA remapping hardware coalescing is performed. - * This is the number of scatter-gather entries the driver - * will actually have to deal with after DMA mapping is done. - */ - unsigned short nr_hw_segments; - unsigned short ioprio; void *special; @@ -220,6 +216,8 @@ struct request { void *data; void *sense; + unsigned long deadline; + struct list_head timeout_list; unsigned int timeout; int retries; @@ -233,6 +231,11 @@ struct request { struct request *next_rq; }; +static inline unsigned short req_get_ioprio(struct request *req) +{ + return req->ioprio; +} + /* * State information carried for REQ_TYPE_PM_SUSPEND and REQ_TYPE_PM_RESUME * requests. Some step values could eventually be made generic. @@ -252,6 +255,7 @@ typedef void (request_fn_proc) (struct request_queue *q); typedef int (make_request_fn) (struct request_queue *q, struct bio *bio); typedef int (prep_rq_fn) (struct request_queue *, struct request *); typedef void (unplug_fn) (struct request_queue *); +typedef int (prepare_discard_fn) (struct request_queue *, struct request *); struct bio_vec; struct bvec_merge_data { @@ -265,6 +269,15 @@ typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *, typedef void (prepare_flush_fn) (struct request_queue *, struct request *); typedef void (softirq_done_fn)(struct request *); typedef int (dma_drain_needed_fn)(struct request *); +typedef int (lld_busy_fn) (struct request_queue *q); + +enum blk_eh_timer_return { + BLK_EH_NOT_HANDLED, + BLK_EH_HANDLED, + BLK_EH_RESET_TIMER, +}; + +typedef enum blk_eh_timer_return (rq_timed_out_fn)(struct request *); enum blk_queue_state { Queue_down, @@ -307,10 +320,13 @@ struct request_queue make_request_fn *make_request_fn; prep_rq_fn *prep_rq_fn; unplug_fn *unplug_fn; + prepare_discard_fn *prepare_discard_fn; merge_bvec_fn *merge_bvec_fn; prepare_flush_fn *prepare_flush_fn; softirq_done_fn *softirq_done_fn; + rq_timed_out_fn *rq_timed_out_fn; dma_drain_needed_fn *dma_drain_needed; + lld_busy_fn *lld_busy_fn; /* * Dispatch queue sorting @@ -385,6 +401,10 @@ struct request_queue unsigned int nr_sorted; unsigned int in_flight; + unsigned int rq_timeout; + struct timer_list timeout; + struct list_head timeout_list; + /* * sg stuff */ @@ -421,6 +441,10 @@ struct request_queue #define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */ #define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */ #define QUEUE_FLAG_NOMERGES 10 /* disable merge attempts */ +#define QUEUE_FLAG_SAME_COMP 11 /* force complete on same CPU */ +#define QUEUE_FLAG_FAIL_IO 12 /* fake timeout */ +#define QUEUE_FLAG_STACKABLE 13 /* supports request stacking */ +#define QUEUE_FLAG_NONROT 14 /* non-rotational device (SSD) */ static inline int queue_is_locked(struct request_queue *q) { @@ -526,7 +550,10 @@ enum { #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) #define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags) +#define blk_queue_nonrot(q) test_bit(QUEUE_FLAG_NONROT, &(q)->queue_flags) #define blk_queue_flushing(q) ((q)->ordseq) +#define blk_queue_stackable(q) \ + test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags) #define blk_fs_request(rq) ((rq)->cmd_type == REQ_TYPE_FS) #define blk_pc_request(rq) ((rq)->cmd_type == REQ_TYPE_BLOCK_PC) @@ -536,16 +563,18 @@ enum { #define blk_noretry_request(rq) ((rq)->cmd_flags & REQ_FAILFAST) #define blk_rq_started(rq) ((rq)->cmd_flags & REQ_STARTED) -#define blk_account_rq(rq) (blk_rq_started(rq) && blk_fs_request(rq)) +#define blk_account_rq(rq) (blk_rq_started(rq) && (blk_fs_request(rq) || blk_discard_rq(rq))) #define blk_pm_suspend_request(rq) ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND) #define blk_pm_resume_request(rq) ((rq)->cmd_type == REQ_TYPE_PM_RESUME) #define blk_pm_request(rq) \ (blk_pm_suspend_request(rq) || blk_pm_resume_request(rq)) +#define blk_rq_cpu_valid(rq) ((rq)->cpu != -1) #define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED) #define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER) #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) +#define blk_discard_rq(rq) ((rq)->cmd_flags & REQ_DISCARD) #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) #define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors) /* rq->queuelist of dequeued request must be list_empty() */ @@ -592,7 +621,8 @@ static inline void blk_clear_queue_full(struct request_queue *q, int rw) #define RQ_NOMERGE_FLAGS \ (REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER) #define rq_mergeable(rq) \ - (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && blk_fs_request((rq))) + (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \ + (blk_discard_rq(rq) || blk_fs_request((rq)))) /* * q->prep_rq_fn return values @@ -637,6 +667,12 @@ static inline void blk_queue_bounce(struct request_queue *q, struct bio **bio) } #endif /* CONFIG_MMU */ +struct rq_map_data { + struct page **pages; + int page_order; + int nr_entries; +}; + struct req_iterator { int i; struct bio *bio; @@ -664,6 +700,10 @@ extern void __blk_put_request(struct request_queue *, struct request *); extern struct request *blk_get_request(struct request_queue *, int, gfp_t); extern void blk_insert_request(struct request_queue *, struct request *, int, void *); extern void blk_requeue_request(struct request_queue *, struct request *); +extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); +extern int blk_lld_busy(struct request_queue *q); +extern int blk_insert_cloned_request(struct request_queue *q, + struct request *rq); extern void blk_plug_device(struct request_queue *); extern void blk_plug_device_unlocked(struct request_queue *); extern int blk_remove_plug(struct request_queue *); @@ -705,11 +745,14 @@ extern void __blk_stop_queue(struct request_queue *q); extern void __blk_run_queue(struct request_queue *); extern void blk_run_queue(struct request_queue *); extern void blk_start_queueing(struct request_queue *); -extern int blk_rq_map_user(struct request_queue *, struct request *, void __user *, unsigned long); +extern int blk_rq_map_user(struct request_queue *, struct request *, + struct rq_map_data *, void __user *, unsigned long, + gfp_t); extern int blk_rq_unmap_user(struct bio *); extern int blk_rq_map_kern(struct request_queue *, struct request *, void *, unsigned int, gfp_t); extern int blk_rq_map_user_iov(struct request_queue *, struct request *, - struct sg_iovec *, int, unsigned int); + struct rq_map_data *, struct sg_iovec *, int, + unsigned int, gfp_t); extern int blk_execute_rq(struct request_queue *, struct gendisk *, struct request *, int); extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, @@ -750,12 +793,15 @@ extern int __blk_end_request(struct request *rq, int error, extern int blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes, unsigned int bidi_bytes); extern void end_request(struct request *, int); -extern void end_queued_request(struct request *, int); -extern void end_dequeued_request(struct request *, int); extern int blk_end_request_callback(struct request *rq, int error, unsigned int nr_bytes, int (drv_callback)(struct request *)); extern void blk_complete_request(struct request *); +extern void __blk_complete_request(struct request *); +extern void blk_abort_request(struct request *); +extern void blk_abort_queue(struct request_queue *); +extern void blk_update_request(struct request *rq, int error, + unsigned int nr_bytes); /* * blk_end_request() takes bytes instead of sectors as a complete size. @@ -790,12 +836,16 @@ extern void blk_queue_update_dma_pad(struct request_queue *, unsigned int); extern int blk_queue_dma_drain(struct request_queue *q, dma_drain_needed_fn *dma_drain_needed, void *buf, unsigned int size); +extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn); extern void blk_queue_segment_boundary(struct request_queue *, unsigned long); extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn); extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *); extern void blk_queue_dma_alignment(struct request_queue *, int); extern void blk_queue_update_dma_alignment(struct request_queue *, int); extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); +extern void blk_queue_set_discard(struct request_queue *, prepare_discard_fn *); +extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); +extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); extern int blk_queue_ordered(struct request_queue *, unsigned, prepare_flush_fn *); extern int blk_do_ordered(struct request_queue *, struct request **); @@ -837,6 +887,16 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, } extern int blkdev_issue_flush(struct block_device *, sector_t *); +extern int blkdev_issue_discard(struct block_device *, + sector_t sector, sector_t nr_sects, gfp_t); + +static inline int sb_issue_discard(struct super_block *sb, + sector_t block, sector_t nr_blocks) +{ + block <<= (sb->s_blocksize_bits - 9); + nr_blocks <<= (sb->s_blocksize_bits - 9); + return blkdev_issue_discard(sb->s_bdev, block, nr_blocks, GFP_KERNEL); +} /* * command filter functions @@ -874,6 +934,13 @@ static inline int queue_dma_alignment(struct request_queue *q) return q ? q->dma_alignment : 511; } +static inline int blk_rq_aligned(struct request_queue *q, void *addr, + unsigned int len) +{ + unsigned int alignment = queue_dma_alignment(q) | q->dma_pad_mask; + return !((unsigned long)addr & alignment) && !(len & alignment); +} + /* assumes size > 256 */ static inline unsigned int blksize_bits(unsigned int size) { @@ -900,7 +967,7 @@ static inline void put_dev_sector(Sector p) } struct work_struct; -int kblockd_schedule_work(struct work_struct *work); +int kblockd_schedule_work(struct request_queue *q, struct work_struct *work); void kblockd_flush_work(struct work_struct *work); #define MODULE_ALIAS_BLOCKDEV(major,minor) \ @@ -945,49 +1012,19 @@ struct blk_integrity { extern int blk_integrity_register(struct gendisk *, struct blk_integrity *); extern void blk_integrity_unregister(struct gendisk *); -extern int blk_integrity_compare(struct block_device *, struct block_device *); +extern int blk_integrity_compare(struct gendisk *, struct gendisk *); extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *); extern int blk_rq_count_integrity_sg(struct request *); -static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi) -{ - if (bi) - return bi->tuple_size; - - return 0; -} - -static inline struct blk_integrity *bdev_get_integrity(struct block_device *bdev) +static inline +struct blk_integrity *bdev_get_integrity(struct block_device *bdev) { return bdev->bd_disk->integrity; } -static inline unsigned int bdev_get_tag_size(struct block_device *bdev) +static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk) { - struct blk_integrity *bi = bdev_get_integrity(bdev); - - if (bi) - return bi->tag_size; - - return 0; -} - -static inline int bdev_integrity_enabled(struct block_device *bdev, int rw) -{ - struct blk_integrity *bi = bdev_get_integrity(bdev); - - if (bi == NULL) - return 0; - - if (rw == READ && bi->verify_fn != NULL && - (bi->flags & INTEGRITY_FLAG_READ)) - return 1; - - if (rw == WRITE && bi->generate_fn != NULL && - (bi->flags & INTEGRITY_FLAG_WRITE)) - return 1; - - return 0; + return disk->integrity; } static inline int blk_integrity_rq(struct request *rq) @@ -1004,7 +1041,7 @@ static inline int blk_integrity_rq(struct request *rq) #define blk_rq_count_integrity_sg(a) (0) #define blk_rq_map_integrity_sg(a, b) (0) #define bdev_get_integrity(a) (0) -#define bdev_get_tag_size(a) (0) +#define blk_get_integrity(a) (0) #define blk_integrity_compare(a, b) (0) #define blk_integrity_register(a, b) (0) #define blk_integrity_unregister(a) do { } while (0); diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index d084b8d227a5..3a31eb506164 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -1,8 +1,10 @@ #ifndef BLKTRACE_H #define BLKTRACE_H +#ifdef __KERNEL__ #include <linux/blkdev.h> #include <linux/relay.h> +#endif /* * Trace categories @@ -21,6 +23,7 @@ enum blktrace_cat { BLK_TC_NOTIFY = 1 << 10, /* special message */ BLK_TC_AHEAD = 1 << 11, /* readahead */ BLK_TC_META = 1 << 12, /* metadata */ + BLK_TC_DISCARD = 1 << 13, /* discard requests */ BLK_TC_END = 1 << 15, /* only 16-bits, reminder */ }; @@ -47,6 +50,7 @@ enum blktrace_act { __BLK_TA_SPLIT, /* bio was split */ __BLK_TA_BOUNCE, /* bio was bounced */ __BLK_TA_REMAP, /* bio was remapped */ + __BLK_TA_ABORT, /* request aborted */ }; /* @@ -77,6 +81,7 @@ enum blktrace_notify { #define BLK_TA_SPLIT (__BLK_TA_SPLIT) #define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) #define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) +#define BLK_TA_ABORT (__BLK_TA_ABORT | BLK_TC_ACT(BLK_TC_QUEUE)) #define BLK_TN_PROCESS (__BLK_TN_PROCESS | BLK_TC_ACT(BLK_TC_NOTIFY)) #define BLK_TN_TIMESTAMP (__BLK_TN_TIMESTAMP | BLK_TC_ACT(BLK_TC_NOTIFY)) @@ -89,17 +94,17 @@ enum blktrace_notify { * The trace itself */ struct blk_io_trace { - u32 magic; /* MAGIC << 8 | version */ - u32 sequence; /* event number */ - u64 time; /* in microseconds */ - u64 sector; /* disk offset */ - u32 bytes; /* transfer length */ - u32 action; /* what happened */ - u32 pid; /* who did it */ - u32 device; /* device number */ - u32 cpu; /* on what cpu did it happen */ - u16 error; /* completion error */ - u16 pdu_len; /* length of data after this trace */ + __u32 magic; /* MAGIC << 8 | version */ + __u32 sequence; /* event number */ + __u64 time; /* in microseconds */ + __u64 sector; /* disk offset */ + __u32 bytes; /* transfer length */ + __u32 action; /* what happened */ + __u32 pid; /* who did it */ + __u32 device; /* device number */ + __u32 cpu; /* on what cpu did it happen */ + __u16 error; /* completion error */ + __u16 pdu_len; /* length of data after this trace */ }; /* @@ -117,6 +122,23 @@ enum { Blktrace_stopped, }; +#define BLKTRACE_BDEV_SIZE 32 + +/* + * User setup structure passed with BLKTRACESTART + */ +struct blk_user_trace_setup { + char name[BLKTRACE_BDEV_SIZE]; /* output */ + __u16 act_mask; /* input */ + __u32 buf_size; /* input */ + __u32 buf_nr; /* input */ + __u64 start_lba; + __u64 end_lba; + __u32 pid; +}; + +#ifdef __KERNEL__ +#if defined(CONFIG_BLK_DEV_IO_TRACE) struct blk_trace { int trace_state; struct rchan *rchan; @@ -133,21 +155,6 @@ struct blk_trace { atomic_t dropped; }; -/* - * User setup structure passed with BLKTRACESTART - */ -struct blk_user_trace_setup { - char name[BDEVNAME_SIZE]; /* output */ - u16 act_mask; /* input */ - u32 buf_size; /* input */ - u32 buf_nr; /* input */ - u64 start_lba; - u64 end_lba; - u32 pid; -}; - -#ifdef __KERNEL__ -#if defined(CONFIG_BLK_DEV_IO_TRACE) extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); extern void blk_trace_shutdown(struct request_queue *); extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); @@ -195,6 +202,9 @@ static inline void blk_add_trace_rq(struct request_queue *q, struct request *rq, if (likely(!bt)) return; + if (blk_discard_rq(rq)) + rw |= (1 << BIO_RW_DISCARD); + if (blk_pc_request(rq)) { what |= BLK_TC_ACT(BLK_TC_PC); __blk_add_trace(bt, 0, rq->data_len, rw, what, rq->errors, sizeof(rq->cmd), rq->cmd); diff --git a/include/linux/compiler.h b/include/linux/compiler.h index c8bd2daf95ec..8322141ee480 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -190,7 +190,9 @@ extern void __chk_io_ptr(const volatile void __iomem *); * ACCESS_ONCE() in different C statements. * * This macro does absolutely -nothing- to prevent the CPU from reordering, - * merging, or refetching absolutely anything at any time. + * merging, or refetching absolutely anything at any time. Its main intended + * use is to mediate communication between process-level code and irq/NMI + * handlers, all running on the same CPU. */ #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) diff --git a/include/linux/completion.h b/include/linux/completion.h index 02ef8835999c..4a6b604ef7e4 100644 --- a/include/linux/completion.h +++ b/include/linux/completion.h @@ -10,6 +10,18 @@ #include <linux/wait.h> +/** + * struct completion - structure used to maintain state for a "completion" + * + * This is the opaque structure used to maintain the state for a "completion". + * Completions currently use a FIFO to queue threads that have to wait for + * the "completion" event. + * + * See also: complete(), wait_for_completion() (and friends _timeout, + * _interruptible, _interruptible_timeout, and _killable), init_completion(), + * and macros DECLARE_COMPLETION(), DECLARE_COMPLETION_ONSTACK(), and + * INIT_COMPLETION(). + */ struct completion { unsigned int done; wait_queue_head_t wait; @@ -21,6 +33,14 @@ struct completion { #define COMPLETION_INITIALIZER_ONSTACK(work) \ ({ init_completion(&work); work; }) +/** + * DECLARE_COMPLETION: - declare and initialize a completion structure + * @work: identifier for the completion structure + * + * This macro declares and initializes a completion structure. Generally used + * for static declarations. You should use the _ONSTACK variant for automatic + * variables. + */ #define DECLARE_COMPLETION(work) \ struct completion work = COMPLETION_INITIALIZER(work) @@ -29,6 +49,13 @@ struct completion { * completions - so we use the _ONSTACK() variant for those that * are on the kernel stack: */ +/** + * DECLARE_COMPLETION_ONSTACK: - declare and initialize a completion structure + * @work: identifier for the completion structure + * + * This macro declares and initializes a completion structure on the kernel + * stack. + */ #ifdef CONFIG_LOCKDEP # define DECLARE_COMPLETION_ONSTACK(work) \ struct completion work = COMPLETION_INITIALIZER_ONSTACK(work) @@ -36,6 +63,13 @@ struct completion { # define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work) #endif +/** + * init_completion: - Initialize a dynamically allocated completion + * @x: completion structure that is to be initialized + * + * This inline function will initialize a dynamically created completion + * structure. + */ static inline void init_completion(struct completion *x) { x->done = 0; @@ -55,6 +89,13 @@ extern bool completion_done(struct completion *x); extern void complete(struct completion *); extern void complete_all(struct completion *); +/** + * INIT_COMPLETION: - reinitialize a completion structure + * @x: completion structure to be reinitialized + * + * This macro should be used to reinitialize a completion structure so it can + * be reused. This is especially important after complete_all() is used. + */ #define INIT_COMPLETION(x) ((x).done = 0) diff --git a/include/linux/cpu.h b/include/linux/cpu.h index d7faf8808497..c2747ac2ae43 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -69,6 +69,7 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb) #endif int cpu_up(unsigned int cpu); +void notify_cpu_starting(unsigned int cpu); extern void cpu_hotplug_init(void); extern void cpu_maps_update_begin(void); extern void cpu_maps_update_done(void); diff --git a/include/linux/crypto.h b/include/linux/crypto.h index c43dc47fdf75..3d2317e4af2e 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -38,6 +38,7 @@ #define CRYPTO_ALG_TYPE_DIGEST 0x00000008 #define CRYPTO_ALG_TYPE_HASH 0x00000009 #define CRYPTO_ALG_TYPE_AHASH 0x0000000a +#define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c @@ -61,6 +62,14 @@ #define CRYPTO_ALG_GENIV 0x00000200 /* + * Set if the algorithm has passed automated run-time testing. Note that + * if there is no run-time testing for a given algorithm it is considered + * to have passed. + */ + +#define CRYPTO_ALG_TESTED 0x00000400 + +/* * Transform masks and values (for crt_flags). */ #define CRYPTO_TFM_REQ_MASK 0x000fff00 @@ -105,6 +114,7 @@ struct crypto_aead; struct crypto_blkcipher; struct crypto_hash; struct crypto_ahash; +struct crypto_rng; struct crypto_tfm; struct crypto_type; struct aead_givcrypt_request; @@ -290,6 +300,15 @@ struct compress_alg { unsigned int slen, u8 *dst, unsigned int *dlen); }; +struct rng_alg { + int (*rng_make_random)(struct crypto_rng *tfm, u8 *rdata, + unsigned int dlen); + int (*rng_reset)(struct crypto_rng *tfm, u8 *seed, unsigned int slen); + + unsigned int seedsize; +}; + + #define cra_ablkcipher cra_u.ablkcipher #define cra_aead cra_u.aead #define cra_blkcipher cra_u.blkcipher @@ -298,6 +317,7 @@ struct compress_alg { #define cra_hash cra_u.hash #define cra_ahash cra_u.ahash #define cra_compress cra_u.compress +#define cra_rng cra_u.rng struct crypto_alg { struct list_head cra_list; @@ -325,6 +345,7 @@ struct crypto_alg { struct hash_alg hash; struct ahash_alg ahash; struct compress_alg compress; + struct rng_alg rng; } cra_u; int (*cra_init)(struct crypto_tfm *tfm); @@ -430,6 +451,12 @@ struct compress_tfm { u8 *dst, unsigned int *dlen); }; +struct rng_tfm { + int (*rng_gen_random)(struct crypto_rng *tfm, u8 *rdata, + unsigned int dlen); + int (*rng_reset)(struct crypto_rng *tfm, u8 *seed, unsigned int slen); +}; + #define crt_ablkcipher crt_u.ablkcipher #define crt_aead crt_u.aead #define crt_blkcipher crt_u.blkcipher @@ -437,6 +464,7 @@ struct compress_tfm { #define crt_hash crt_u.hash #define crt_ahash crt_u.ahash #define crt_compress crt_u.compress +#define crt_rng crt_u.rng struct crypto_tfm { @@ -450,6 +478,7 @@ struct crypto_tfm { struct hash_tfm hash; struct ahash_tfm ahash; struct compress_tfm compress; + struct rng_tfm rng; } crt_u; struct crypto_alg *__crt_alg; @@ -481,6 +510,10 @@ struct crypto_hash { struct crypto_tfm base; }; +struct crypto_rng { + struct crypto_tfm base; +}; + enum { CRYPTOA_UNSPEC, CRYPTOA_ALG, @@ -515,6 +548,8 @@ struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask); void crypto_free_tfm(struct crypto_tfm *tfm); +int alg_test(const char *driver, const char *alg, u32 type, u32 mask); + /* * Transform helpers which query the underlying algorithm. */ diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index a90222e3297d..08d783592b73 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -13,7 +13,6 @@ struct dm_target; struct dm_table; -struct dm_dev; struct mapped_device; struct bio_vec; @@ -84,6 +83,12 @@ void dm_error(const char *message); */ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev); +struct dm_dev { + struct block_device *bdev; + int mode; + char name[16]; +}; + /* * Constructors should call these functions to ensure destination devices * are opened/closed correctly. @@ -202,6 +207,7 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid); struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct mapped_device *md); int dm_noflush_suspending(struct dm_target *ti); +union map_info *dm_get_mapinfo(struct bio *bio); /* * Geometry functions. @@ -232,6 +238,11 @@ int dm_table_add_target(struct dm_table *t, const char *type, int dm_table_complete(struct dm_table *t); /* + * Unplug all devices in a table. + */ +void dm_table_unplug_all(struct dm_table *t); + +/* * Table reference counting. */ struct dm_table *dm_get_table(struct mapped_device *md); @@ -256,6 +267,11 @@ void dm_table_event(struct dm_table *t); */ int dm_swap_table(struct mapped_device *md, struct dm_table *t); +/* + * A wrapper around vmalloc. + */ +void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); + /*----------------------------------------------------------------- * Macros. *---------------------------------------------------------------*/ diff --git a/include/linux/device.h b/include/linux/device.h index 4d8372d135df..246937c9cbc7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -199,6 +199,11 @@ struct class { struct class_private *p; }; +struct class_dev_iter { + struct klist_iter ki; + const struct device_type *type; +}; + extern struct kobject *sysfs_dev_block_kobj; extern struct kobject *sysfs_dev_char_kobj; extern int __must_check __class_register(struct class *class, @@ -213,6 +218,13 @@ extern void class_unregister(struct class *class); __class_register(class, &__key); \ }) +extern void class_dev_iter_init(struct class_dev_iter *iter, + struct class *class, + struct device *start, + const struct device_type *type); +extern struct device *class_dev_iter_next(struct class_dev_iter *iter); +extern void class_dev_iter_exit(struct class_dev_iter *iter); + extern int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); @@ -396,7 +408,7 @@ struct device { spinlock_t devres_lock; struct list_head devres_head; - struct list_head node; + struct klist_node knode_class; struct class *class; dev_t devt; /* dev_t, creates the sysfs "dev" */ struct attribute_group **groups; /* optional groups */ diff --git a/include/linux/dlm.h b/include/linux/dlm.h index 203a025e30e5..b9cd38603fd8 100644 --- a/include/linux/dlm.h +++ b/include/linux/dlm.h @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions @@ -65,9 +65,12 @@ struct dlm_lksb { char * sb_lvbptr; }; +/* dlm_new_lockspace() flags */ + #define DLM_LSFL_NODIR 0x00000001 #define DLM_LSFL_TIMEWARN 0x00000002 #define DLM_LSFL_FS 0x00000004 +#define DLM_LSFL_NEWEXCL 0x00000008 #ifdef __KERNEL__ diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h index c6034508fed9..3060783c4191 100644 --- a/include/linux/dlm_device.h +++ b/include/linux/dlm_device.h @@ -26,7 +26,7 @@ /* Version of the device interface */ #define DLM_DEVICE_VERSION_MAJOR 6 #define DLM_DEVICE_VERSION_MINOR 0 -#define DLM_DEVICE_VERSION_PATCH 0 +#define DLM_DEVICE_VERSION_PATCH 1 /* struct passed to the lock write */ struct dlm_lock_params { diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 639624b55fbe..92f6f634e3e6 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -112,6 +112,7 @@ extern struct request *elv_latter_request(struct request_queue *, struct request extern int elv_register_queue(struct request_queue *q); extern void elv_unregister_queue(struct request_queue *q); extern int elv_may_queue(struct request_queue *, int); +extern void elv_abort_queue(struct request_queue *); extern void elv_completed_request(struct request_queue *, struct request *); extern int elv_set_request(struct request_queue *, struct request *, gfp_t); extern void elv_put_request(struct request_queue *, struct request *); @@ -173,15 +174,15 @@ enum { #define rb_entry_rq(node) rb_entry((node), struct request, rb_node) /* - * Hack to reuse the donelist list_head as the fifo time holder while + * Hack to reuse the csd.list list_head as the fifo time holder while * the request is in the io scheduler. Saves an unsigned long in rq. */ -#define rq_fifo_time(rq) ((unsigned long) (rq)->donelist.next) -#define rq_set_fifo_time(rq,exp) ((rq)->donelist.next = (void *) (exp)) +#define rq_fifo_time(rq) ((unsigned long) (rq)->csd.list.next) +#define rq_set_fifo_time(rq,exp) ((rq)->csd.list.next = (void *) (exp)) #define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) #define rq_fifo_clear(rq) do { \ list_del_init(&(rq)->queuelist); \ - INIT_LIST_HEAD(&(rq)->donelist); \ + INIT_LIST_HEAD(&(rq)->csd.list); \ } while (0) /* diff --git a/include/linux/fd.h b/include/linux/fd.h index b6bd41d2b460..f5d194af07a8 100644 --- a/include/linux/fd.h +++ b/include/linux/fd.h @@ -15,10 +15,16 @@ struct floppy_struct { sect, /* sectors per track */ head, /* nr of heads */ track, /* nr of tracks */ - stretch; /* !=0 means double track steps */ + stretch; /* bit 0 !=0 means double track steps */ + /* bit 1 != 0 means swap sides */ + /* bits 2..9 give the first sector */ + /* number (the LSB is flipped) */ #define FD_STRETCH 1 #define FD_SWAPSIDES 2 #define FD_ZEROBASED 4 +#define FD_SECTBASEMASK 0x3FC +#define FD_MKSECTBASE(s) (((s) ^ 1) << 2) +#define FD_SECTBASE(floppy) ((((floppy)->stretch & FD_SECTBASEMASK) >> 2) ^ 1) unsigned char gap, /* gap1 size */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 580b513668fe..32477e8872d5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -86,7 +86,9 @@ extern int dir_notify_enable; #define READ_META (READ | (1 << BIO_RW_META)) #define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC)) #define SWRITE_SYNC (SWRITE | (1 << BIO_RW_SYNC)) -#define WRITE_BARRIER ((1 << BIO_RW) | (1 << BIO_RW_BARRIER)) +#define WRITE_BARRIER (WRITE | (1 << BIO_RW_BARRIER)) +#define DISCARD_NOBARRIER (1 << BIO_RW_DISCARD) +#define DISCARD_BARRIER ((1 << BIO_RW_DISCARD) | (1 << BIO_RW_BARRIER)) #define SEL_IN 1 #define SEL_OUT 2 @@ -222,6 +224,7 @@ extern int dir_notify_enable; #define BLKTRACESTART _IO(0x12,116) #define BLKTRACESTOP _IO(0x12,117) #define BLKTRACETEARDOWN _IO(0x12,118) +#define BLKDISCARD _IO(0x12,119) #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ #define FIBMAP _IO(0x00,1) /* bmap access */ @@ -1682,6 +1685,7 @@ extern void chrdev_show(struct seq_file *,off_t); /* fs/block_dev.c */ #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ +#define BDEVT_SIZE 10 /* Largest string for MAJ:MIN for blkdev */ #ifdef CONFIG_BLOCK #define BLKDEV_MAJOR_HASH_SIZE 255 @@ -1718,6 +1722,9 @@ extern int fs_may_remount_ro(struct super_block *); */ #define bio_data_dir(bio) ((bio)->bi_rw & 1) +extern void check_disk_size_change(struct gendisk *disk, + struct block_device *bdev); +extern int revalidate_disk(struct gendisk *); extern int check_disk_change(struct block_device *); extern int __invalidate_device(struct block_device *); extern int invalidate_partition(struct gendisk *, int); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index be4f5e5bfe06..206cdf96c3a7 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -11,12 +11,15 @@ #include <linux/types.h> #include <linux/kdev_t.h> +#include <linux/rcupdate.h> #ifdef CONFIG_BLOCK -#define kobj_to_dev(k) container_of(k, struct device, kobj) -#define dev_to_disk(device) container_of(device, struct gendisk, dev) -#define dev_to_part(device) container_of(device, struct hd_struct, dev) +#define kobj_to_dev(k) container_of((k), struct device, kobj) +#define dev_to_disk(device) container_of((device), struct gendisk, part0.__dev) +#define dev_to_part(device) container_of((device), struct hd_struct, __dev) +#define disk_to_dev(disk) (&(disk)->part0.__dev) +#define part_to_dev(part) (&((part)->__dev)) extern struct device_type part_type; extern struct kobject *block_depr; @@ -55,6 +58,9 @@ enum { UNIXWARE_PARTITION = 0x63, /* Same as GNU_HURD and SCO Unix */ }; +#define DISK_MAX_PARTS 256 +#define DISK_NAME_LEN 32 + #include <linux/major.h> #include <linux/device.h> #include <linux/smp.h> @@ -87,7 +93,7 @@ struct disk_stats { struct hd_struct { sector_t start_sect; sector_t nr_sects; - struct device dev; + struct device __dev; struct kobject *holder_dir; int policy, partno; #ifdef CONFIG_FAIL_MAKE_REQUEST @@ -100,6 +106,7 @@ struct hd_struct { #else struct disk_stats dkstats; #endif + struct rcu_head rcu_head; }; #define GENHD_FL_REMOVABLE 1 @@ -108,100 +115,148 @@ struct hd_struct { #define GENHD_FL_CD 8 #define GENHD_FL_UP 16 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 -#define GENHD_FL_FAIL 64 +#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ + +#define BLK_SCSI_MAX_CMDS (256) +#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) + +struct blk_scsi_cmd_filter { + unsigned long read_ok[BLK_SCSI_CMD_PER_LONG]; + unsigned long write_ok[BLK_SCSI_CMD_PER_LONG]; + struct kobject kobj; +}; + +struct disk_part_tbl { + struct rcu_head rcu_head; + int len; + struct hd_struct *part[]; +}; struct gendisk { + /* major, first_minor and minors are input parameters only, + * don't use directly. Use disk_devt() and disk_max_parts(). + */ int major; /* major number of driver */ int first_minor; int minors; /* maximum number of minors, =1 for * disks that can't be partitioned. */ - char disk_name[32]; /* name of major driver */ - struct hd_struct **part; /* [indexed by minor] */ + + char disk_name[DISK_NAME_LEN]; /* name of major driver */ + + /* Array of pointers to partitions indexed by partno. + * Protected with matching bdev lock but stat and other + * non-critical accesses use RCU. Always access through + * helpers. + */ + struct disk_part_tbl *part_tbl; + struct hd_struct part0; + struct block_device_operations *fops; struct request_queue *queue; void *private_data; - sector_t capacity; int flags; struct device *driverfs_dev; // FIXME: remove - struct device dev; - struct kobject *holder_dir; struct kobject *slave_dir; struct timer_rand_state *random; - int policy; atomic_t sync_io; /* RAID */ - unsigned long stamp; - int in_flight; -#ifdef CONFIG_SMP - struct disk_stats *dkstats; -#else - struct disk_stats dkstats; -#endif struct work_struct async_notify; #ifdef CONFIG_BLK_DEV_INTEGRITY struct blk_integrity *integrity; #endif + int node_id; }; -/* - * Macros to operate on percpu disk statistics: - * - * The __ variants should only be called in critical sections. The full - * variants disable/enable preemption. - */ -static inline struct hd_struct *get_part(struct gendisk *gendiskp, - sector_t sector) +static inline struct gendisk *part_to_disk(struct hd_struct *part) { - struct hd_struct *part; - int i; - for (i = 0; i < gendiskp->minors - 1; i++) { - part = gendiskp->part[i]; - if (part && part->start_sect <= sector - && sector < part->start_sect + part->nr_sects) - return part; + if (likely(part)) { + if (part->partno) + return dev_to_disk(part_to_dev(part)->parent); + else + return dev_to_disk(part_to_dev(part)); } return NULL; } -#ifdef CONFIG_SMP -#define __disk_stat_add(gendiskp, field, addnd) \ - (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) +static inline int disk_max_parts(struct gendisk *disk) +{ + if (disk->flags & GENHD_FL_EXT_DEVT) + return DISK_MAX_PARTS; + return disk->minors; +} -#define disk_stat_read(gendiskp, field) \ -({ \ - typeof(gendiskp->dkstats->field) res = 0; \ - int i; \ - for_each_possible_cpu(i) \ - res += per_cpu_ptr(gendiskp->dkstats, i)->field; \ - res; \ -}) +static inline bool disk_partitionable(struct gendisk *disk) +{ + return disk_max_parts(disk) > 1; +} -static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { - int i; +static inline dev_t disk_devt(struct gendisk *disk) +{ + return disk_to_dev(disk)->devt; +} - for_each_possible_cpu(i) - memset(per_cpu_ptr(gendiskp->dkstats, i), value, - sizeof(struct disk_stats)); -} +static inline dev_t part_devt(struct hd_struct *part) +{ + return part_to_dev(part)->devt; +} -#define __part_stat_add(part, field, addnd) \ - (per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd) +extern struct hd_struct *disk_get_part(struct gendisk *disk, int partno); -#define __all_stat_add(gendiskp, part, field, addnd, sector) \ -({ \ - if (part) \ - __part_stat_add(part, field, addnd); \ - __disk_stat_add(gendiskp, field, addnd); \ -}) +static inline void disk_put_part(struct hd_struct *part) +{ + if (likely(part)) + put_device(part_to_dev(part)); +} + +/* + * Smarter partition iterator without context limits. + */ +#define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */ +#define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */ +#define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */ + +struct disk_part_iter { + struct gendisk *disk; + struct hd_struct *part; + int idx; + unsigned int flags; +}; + +extern void disk_part_iter_init(struct disk_part_iter *piter, + struct gendisk *disk, unsigned int flags); +extern struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter); +extern void disk_part_iter_exit(struct disk_part_iter *piter); + +extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, + sector_t sector); + +/* + * Macros to operate on percpu disk statistics: + * + * {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters + * and should be called between disk_stat_lock() and + * disk_stat_unlock(). + * + * part_stat_read() can be called at any time. + * + * part_stat_{add|set_all}() and {init|free}_part_stats are for + * internal use only. + */ +#ifdef CONFIG_SMP +#define part_stat_lock() ({ rcu_read_lock(); get_cpu(); }) +#define part_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0) + +#define __part_stat_add(cpu, part, field, addnd) \ + (per_cpu_ptr((part)->dkstats, (cpu))->field += (addnd)) #define part_stat_read(part, field) \ ({ \ - typeof(part->dkstats->field) res = 0; \ + typeof((part)->dkstats->field) res = 0; \ int i; \ for_each_possible_cpu(i) \ - res += per_cpu_ptr(part->dkstats, i)->field; \ + res += per_cpu_ptr((part)->dkstats, i)->field; \ res; \ }) @@ -213,171 +268,107 @@ static inline void part_stat_set_all(struct hd_struct *part, int value) memset(per_cpu_ptr(part->dkstats, i), value, sizeof(struct disk_stats)); } - -#else /* !CONFIG_SMP */ -#define __disk_stat_add(gendiskp, field, addnd) \ - (gendiskp->dkstats.field += addnd) -#define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) -static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) +static inline int init_part_stats(struct hd_struct *part) { - memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); + part->dkstats = alloc_percpu(struct disk_stats); + if (!part->dkstats) + return 0; + return 1; } -#define __part_stat_add(part, field, addnd) \ - (part->dkstats.field += addnd) - -#define __all_stat_add(gendiskp, part, field, addnd, sector) \ -({ \ - if (part) \ - part->dkstats.field += addnd; \ - __disk_stat_add(gendiskp, field, addnd); \ -}) - -#define part_stat_read(part, field) (part->dkstats.field) - -static inline void part_stat_set_all(struct hd_struct *part, int value) +static inline void free_part_stats(struct hd_struct *part) { - memset(&part->dkstats, value, sizeof(struct disk_stats)); + free_percpu(part->dkstats); } -#endif /* CONFIG_SMP */ +#else /* !CONFIG_SMP */ +#define part_stat_lock() ({ rcu_read_lock(); 0; }) +#define part_stat_unlock() rcu_read_unlock() -#define disk_stat_add(gendiskp, field, addnd) \ - do { \ - preempt_disable(); \ - __disk_stat_add(gendiskp, field, addnd); \ - preempt_enable(); \ - } while (0) - -#define __disk_stat_dec(gendiskp, field) __disk_stat_add(gendiskp, field, -1) -#define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1) - -#define __disk_stat_inc(gendiskp, field) __disk_stat_add(gendiskp, field, 1) -#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1) - -#define __disk_stat_sub(gendiskp, field, subnd) \ - __disk_stat_add(gendiskp, field, -subnd) -#define disk_stat_sub(gendiskp, field, subnd) \ - disk_stat_add(gendiskp, field, -subnd) - -#define part_stat_add(gendiskp, field, addnd) \ - do { \ - preempt_disable(); \ - __part_stat_add(gendiskp, field, addnd);\ - preempt_enable(); \ - } while (0) - -#define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1) -#define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1) - -#define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1) -#define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1) - -#define __part_stat_sub(gendiskp, field, subnd) \ - __part_stat_add(gendiskp, field, -subnd) -#define part_stat_sub(gendiskp, field, subnd) \ - part_stat_add(gendiskp, field, -subnd) - -#define all_stat_add(gendiskp, part, field, addnd, sector) \ - do { \ - preempt_disable(); \ - __all_stat_add(gendiskp, part, field, addnd, sector); \ - preempt_enable(); \ - } while (0) - -#define __all_stat_dec(gendiskp, field, sector) \ - __all_stat_add(gendiskp, field, -1, sector) -#define all_stat_dec(gendiskp, field, sector) \ - all_stat_add(gendiskp, field, -1, sector) - -#define __all_stat_inc(gendiskp, part, field, sector) \ - __all_stat_add(gendiskp, part, field, 1, sector) -#define all_stat_inc(gendiskp, part, field, sector) \ - all_stat_add(gendiskp, part, field, 1, sector) - -#define __all_stat_sub(gendiskp, part, field, subnd, sector) \ - __all_stat_add(gendiskp, part, field, -subnd, sector) -#define all_stat_sub(gendiskp, part, field, subnd, sector) \ - all_stat_add(gendiskp, part, field, -subnd, sector) - -/* Inlines to alloc and free disk stats in struct gendisk */ -#ifdef CONFIG_SMP -static inline int init_disk_stats(struct gendisk *disk) -{ - disk->dkstats = alloc_percpu(struct disk_stats); - if (!disk->dkstats) - return 0; - return 1; -} +#define __part_stat_add(cpu, part, field, addnd) \ + ((part)->dkstats.field += addnd) + +#define part_stat_read(part, field) ((part)->dkstats.field) -static inline void free_disk_stats(struct gendisk *disk) +static inline void part_stat_set_all(struct hd_struct *part, int value) { - free_percpu(disk->dkstats); + memset(&part->dkstats, value, sizeof(struct disk_stats)); } static inline int init_part_stats(struct hd_struct *part) { - part->dkstats = alloc_percpu(struct disk_stats); - if (!part->dkstats) - return 0; return 1; } static inline void free_part_stats(struct hd_struct *part) { - free_percpu(part->dkstats); -} - -#else /* CONFIG_SMP */ -static inline int init_disk_stats(struct gendisk *disk) -{ - return 1; } -static inline void free_disk_stats(struct gendisk *disk) -{ -} +#endif /* CONFIG_SMP */ -static inline int init_part_stats(struct hd_struct *part) +#define part_stat_add(cpu, part, field, addnd) do { \ + __part_stat_add((cpu), (part), field, addnd); \ + if ((part)->partno) \ + __part_stat_add((cpu), &part_to_disk((part))->part0, \ + field, addnd); \ +} while (0) + +#define part_stat_dec(cpu, gendiskp, field) \ + part_stat_add(cpu, gendiskp, field, -1) +#define part_stat_inc(cpu, gendiskp, field) \ + part_stat_add(cpu, gendiskp, field, 1) +#define part_stat_sub(cpu, gendiskp, field, subnd) \ + part_stat_add(cpu, gendiskp, field, -subnd) + +static inline void part_inc_in_flight(struct hd_struct *part) { - return 1; + part->in_flight++; + if (part->partno) + part_to_disk(part)->part0.in_flight++; } -static inline void free_part_stats(struct hd_struct *part) +static inline void part_dec_in_flight(struct hd_struct *part) { + part->in_flight--; + if (part->partno) + part_to_disk(part)->part0.in_flight--; } -#endif /* CONFIG_SMP */ /* drivers/block/ll_rw_blk.c */ -extern void disk_round_stats(struct gendisk *disk); -extern void part_round_stats(struct hd_struct *part); +extern void part_round_stats(int cpu, struct hd_struct *part); /* drivers/block/genhd.c */ extern int get_blkdev_list(char *, int); extern void add_disk(struct gendisk *disk); extern void del_gendisk(struct gendisk *gp); extern void unlink_gendisk(struct gendisk *gp); -extern struct gendisk *get_gendisk(dev_t dev, int *part); +extern struct gendisk *get_gendisk(dev_t dev, int *partno); +extern struct block_device *bdget_disk(struct gendisk *disk, int partno); extern void set_device_ro(struct block_device *bdev, int flag); extern void set_disk_ro(struct gendisk *disk, int flag); +static inline int get_disk_ro(struct gendisk *disk) +{ + return disk->part0.policy; +} + /* drivers/char/random.c */ extern void add_disk_randomness(struct gendisk *disk); extern void rand_initialize_disk(struct gendisk *disk); static inline sector_t get_start_sect(struct block_device *bdev) { - return bdev->bd_contains == bdev ? 0 : bdev->bd_part->start_sect; + return bdev->bd_part->start_sect; } static inline sector_t get_capacity(struct gendisk *disk) { - return disk->capacity; + return disk->part0.nr_sects; } static inline void set_capacity(struct gendisk *disk, sector_t size) { - disk->capacity = size; + disk->part0.nr_sects = size; } #ifdef CONFIG_SOLARIS_X86_PARTITION @@ -527,9 +518,12 @@ struct unixware_disklabel { #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 -extern dev_t blk_lookup_devt(const char *name, int part); -extern char *disk_name (struct gendisk *hd, int part, char *buf); +extern int blk_alloc_devt(struct hd_struct *part, dev_t *devt); +extern void blk_free_devt(dev_t devt); +extern dev_t blk_lookup_devt(const char *name, int partno); +extern char *disk_name (struct gendisk *hd, int partno, char *buf); +extern int disk_expand_part_tbl(struct gendisk *disk, int target); extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int); extern void delete_partition(struct gendisk *, int); @@ -546,16 +540,23 @@ extern void blk_register_region(dev_t devt, unsigned long range, void *data); extern void blk_unregister_region(dev_t devt, unsigned long range); -static inline struct block_device *bdget_disk(struct gendisk *disk, int index) -{ - return bdget(MKDEV(disk->major, disk->first_minor) + index); -} +extern ssize_t part_size_show(struct device *dev, + struct device_attribute *attr, char *buf); +extern ssize_t part_stat_show(struct device *dev, + struct device_attribute *attr, char *buf); +#ifdef CONFIG_FAIL_MAKE_REQUEST +extern ssize_t part_fail_show(struct device *dev, + struct device_attribute *attr, char *buf); +extern ssize_t part_fail_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +#endif /* CONFIG_FAIL_MAKE_REQUEST */ #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } -static inline dev_t blk_lookup_devt(const char *name, int part) +static inline dev_t blk_lookup_devt(const char *name, int partno) { dev_t devt = MKDEV(0, 0); return devt; diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index c3c19f926e6f..14d0df0b5749 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -118,7 +118,11 @@ struct gfs2_sb { char sb_lockproto[GFS2_LOCKNAME_LEN]; char sb_locktable[GFS2_LOCKNAME_LEN]; - /* In gfs1, quota and license dinodes followed */ + + struct gfs2_inum __pad3; /* Was quota inode in gfs1 */ + struct gfs2_inum __pad4; /* Was licence inode in gfs1 */ +#define GFS2_HAS_UUID 1 + __u8 sb_uuid[16]; /* The UUID, maybe 0 for backwards compat */ }; /* diff --git a/include/linux/klist.h b/include/linux/klist.h index 06c338ef7f1b..8ea98db223e5 100644 --- a/include/linux/klist.h +++ b/include/linux/klist.h @@ -38,7 +38,7 @@ extern void klist_init(struct klist *k, void (*get)(struct klist_node *), void (*put)(struct klist_node *)); struct klist_node { - struct klist *n_klist; + void *n_klist; /* never access directly */ struct list_head n_node; struct kref n_ref; struct completion n_removed; @@ -57,7 +57,6 @@ extern int klist_node_attached(struct klist_node *n); struct klist_iter { struct klist *i_klist; - struct list_head *i_head; struct klist_node *i_cur; }; diff --git a/include/linux/libata.h b/include/linux/libata.h index 225bfc5bd9ec..947cf84e555d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -146,6 +146,7 @@ enum { ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */ ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */ + ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */ ATA_DFLAG_INIT_MASK = (1 << 24) - 1, ATA_DFLAG_DETACH = (1 << 24), @@ -244,6 +245,7 @@ enum { ATA_TMOUT_BOOT = 30000, /* heuristic */ ATA_TMOUT_BOOT_QUICK = 7000, /* heuristic */ ATA_TMOUT_INTERNAL_QUICK = 5000, + ATA_TMOUT_MAX_PARK = 30000, /* FIXME: GoVault needs 2s but we can't afford that without * parallel probing. 800ms is enough for iVDR disk @@ -319,8 +321,11 @@ enum { ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, ATA_EH_ENABLE_LINK = (1 << 3), ATA_EH_LPM = (1 << 4), /* link power management action */ + ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */ - ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, + ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK, + ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET | + ATA_EH_ENABLE_LINK | ATA_EH_LPM, /* ata_eh_info->flags */ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ @@ -452,6 +457,7 @@ enum link_pm { MEDIUM_POWER, }; extern struct device_attribute dev_attr_link_power_management_policy; +extern struct device_attribute dev_attr_unload_heads; extern struct device_attribute dev_attr_em_message_type; extern struct device_attribute dev_attr_em_message; extern struct device_attribute dev_attr_sw_activity; @@ -554,8 +560,8 @@ struct ata_ering { struct ata_device { struct ata_link *link; unsigned int devno; /* 0 or 1 */ - unsigned long flags; /* ATA_DFLAG_xxx */ unsigned int horkage; /* List of broken features */ + unsigned long flags; /* ATA_DFLAG_xxx */ struct scsi_device *sdev; /* attached SCSI device */ #ifdef CONFIG_ATA_ACPI acpi_handle acpi_handle; @@ -564,6 +570,7 @@ struct ata_device { /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ u64 n_sectors; /* size of device, if ATA */ unsigned int class; /* ATA_DEV_xxx */ + unsigned long unpark_deadline; u8 pio_mode; u8 dma_mode; @@ -621,6 +628,7 @@ struct ata_eh_context { [ATA_EH_CMD_TIMEOUT_TABLE_SIZE]; unsigned int classes[ATA_MAX_DEVICES]; unsigned int did_probe_mask; + unsigned int unloaded_mask; unsigned int saved_ncq_enabled; u8 saved_xfer_mode[ATA_MAX_DEVICES]; /* timestamp for the last reset attempt or success */ @@ -688,7 +696,8 @@ struct ata_port { unsigned int qc_active; int nr_active_links; /* #links with active qcs */ - struct ata_link link; /* host default link */ + struct ata_link link; /* host default link */ + struct ata_link *slave_link; /* see ata_slave_link_init() */ int nr_pmp_links; /* nr of available PMP links */ struct ata_link *pmp_link; /* array of PMP links */ @@ -709,6 +718,7 @@ struct ata_port { struct list_head eh_done_q; wait_queue_head_t eh_wait_q; int eh_tries; + struct completion park_req_pending; pm_message_t pm_mesg; int *pm_result; @@ -772,8 +782,8 @@ struct ata_port_operations { /* * Optional features */ - int (*scr_read)(struct ata_port *ap, unsigned int sc_reg, u32 *val); - int (*scr_write)(struct ata_port *ap, unsigned int sc_reg, u32 val); + int (*scr_read)(struct ata_link *link, unsigned int sc_reg, u32 *val); + int (*scr_write)(struct ata_link *link, unsigned int sc_reg, u32 val); void (*pmp_attach)(struct ata_port *ap); void (*pmp_detach)(struct ata_port *ap); int (*enable_pm)(struct ata_port *ap, enum link_pm policy); @@ -895,6 +905,7 @@ extern void ata_port_disable(struct ata_port *); extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports); extern struct ata_host *ata_host_alloc_pinfo(struct device *dev, const struct ata_port_info * const * ppi, int n_ports); +extern int ata_slave_link_init(struct ata_port *ap); extern int ata_host_start(struct ata_host *host); extern int ata_host_register(struct ata_host *host, struct scsi_host_template *sht); @@ -920,8 +931,8 @@ extern int sata_scr_valid(struct ata_link *link); extern int sata_scr_read(struct ata_link *link, int reg, u32 *val); extern int sata_scr_write(struct ata_link *link, int reg, u32 val); extern int sata_scr_write_flush(struct ata_link *link, int reg, u32 val); -extern int ata_link_online(struct ata_link *link); -extern int ata_link_offline(struct ata_link *link); +extern bool ata_link_online(struct ata_link *link); +extern bool ata_link_offline(struct ata_link *link); #ifdef CONFIG_PM extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); extern void ata_host_resume(struct ata_host *host); @@ -1098,6 +1109,7 @@ extern void ata_std_error_handler(struct ata_port *ap); */ extern const struct ata_port_operations ata_base_port_ops; extern const struct ata_port_operations sata_port_ops; +extern struct device_attribute *ata_common_sdev_attrs[]; #define ATA_BASE_SHT(drv_name) \ .module = THIS_MODULE, \ @@ -1112,7 +1124,8 @@ extern const struct ata_port_operations sata_port_ops; .proc_name = drv_name, \ .slave_configure = ata_scsi_slave_config, \ .slave_destroy = ata_scsi_slave_destroy, \ - .bios_param = ata_std_bios_param + .bios_param = ata_std_bios_param, \ + .sdev_attrs = ata_common_sdev_attrs #define ATA_NCQ_SHT(drv_name) \ ATA_BASE_SHT(drv_name), \ @@ -1134,7 +1147,7 @@ static inline bool sata_pmp_attached(struct ata_port *ap) static inline int ata_is_host_link(const struct ata_link *link) { - return link == &link->ap->link; + return link == &link->ap->link || link == link->ap->slave_link; } #else /* CONFIG_SATA_PMP */ static inline bool sata_pmp_supported(struct ata_port *ap) @@ -1167,7 +1180,7 @@ static inline int sata_srst_pmp(struct ata_link *link) printk("%sata%u: "fmt, lv, (ap)->print_id , ##args) #define ata_link_printk(link, lv, fmt, args...) do { \ - if (sata_pmp_attached((link)->ap)) \ + if (sata_pmp_attached((link)->ap) || (link)->ap->slave_link) \ printk("%sata%u.%02u: "fmt, lv, (link)->ap->print_id, \ (link)->pmp , ##args); \ else \ @@ -1265,34 +1278,17 @@ static inline int ata_link_active(struct ata_link *link) return ata_tag_valid(link->active_tag) || link->sactive; } -static inline struct ata_link *ata_port_first_link(struct ata_port *ap) -{ - if (sata_pmp_attached(ap)) - return ap->pmp_link; - return &ap->link; -} - -static inline struct ata_link *ata_port_next_link(struct ata_link *link) -{ - struct ata_port *ap = link->ap; - - if (ata_is_host_link(link)) { - if (!sata_pmp_attached(ap)) - return NULL; - return ap->pmp_link; - } - - if (++link < ap->nr_pmp_links + ap->pmp_link) - return link; - return NULL; -} +extern struct ata_link *__ata_port_next_link(struct ata_port *ap, + struct ata_link *link, + bool dev_only); -#define __ata_port_for_each_link(lk, ap) \ - for ((lk) = &(ap)->link; (lk); (lk) = ata_port_next_link(lk)) +#define __ata_port_for_each_link(link, ap) \ + for ((link) = __ata_port_next_link((ap), NULL, false); (link); \ + (link) = __ata_port_next_link((ap), (link), false)) #define ata_port_for_each_link(link, ap) \ - for ((link) = ata_port_first_link(ap); (link); \ - (link) = ata_port_next_link(link)) + for ((link) = __ata_port_next_link((ap), NULL, true); (link); \ + (link) = __ata_port_next_link((ap), (link), true)) #define ata_link_for_each_dev(dev, link) \ for ((dev) = (link)->device; \ diff --git a/include/linux/major.h b/include/linux/major.h index 53d5fafd85c3..88249452b935 100644 --- a/include/linux/major.h +++ b/include/linux/major.h @@ -170,4 +170,6 @@ #define VIOTAPE_MAJOR 230 +#define BLOCK_EXT_MAJOR 259 + #endif diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index 310e61606415..8b4aa0523db7 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -41,6 +41,8 @@ struct mtd_blktrans_ops { unsigned long block, char *buffer); int (*writesect)(struct mtd_blktrans_dev *dev, unsigned long block, char *buffer); + int (*discard)(struct mtd_blktrans_dev *dev, + unsigned long block, unsigned nr_blocks); /* Block layer ioctls */ int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo); diff --git a/include/linux/notifier.h b/include/linux/notifier.h index da2698b0fdd1..b86fa2ffca0c 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -213,9 +213,16 @@ static inline int notifier_to_errno(int ret) #define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */ #define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ #define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task, - * not handling interrupts, soon dead */ + * not handling interrupts, soon dead. + * Called on the dying cpu, interrupts + * are already disabled. Must not + * sleep, must not fail */ #define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug * lock is dropped */ +#define CPU_STARTING 0x000A /* CPU (unsigned)v soon running. + * Called on the new cpu, just before + * enabling interrupts. Must not sleep, + * must not fail */ /* Used for CPU hotplug events occuring while tasks are frozen due to a suspend * operation in progress @@ -229,6 +236,7 @@ static inline int notifier_to_errno(int ret) #define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN) #define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN) #define CPU_DYING_FROZEN (CPU_DYING | CPU_TASKS_FROZEN) +#define CPU_STARTING_FROZEN (CPU_STARTING | CPU_TASKS_FROZEN) /* Hibernation and suspend events */ #define PM_HIBERNATION_PREPARE 0x0001 /* Going to hibernate */ diff --git a/include/linux/proportions.h b/include/linux/proportions.h index 5afc1b23346d..cf793bbbd05e 100644 --- a/include/linux/proportions.h +++ b/include/linux/proportions.h @@ -104,8 +104,8 @@ struct prop_local_single { * snapshot of the last seen global state * and a lock protecting this state */ - int shift; unsigned long period; + int shift; spinlock_t lock; /* protect the snapshot state */ }; diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h index 4ab843622727..5f89b62e6983 100644 --- a/include/linux/rcuclassic.h +++ b/include/linux/rcuclassic.h @@ -40,12 +40,21 @@ #include <linux/cpumask.h> #include <linux/seqlock.h> +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR +#define RCU_SECONDS_TILL_STALL_CHECK ( 3 * HZ) /* for rcp->jiffies_stall */ +#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ) /* for rcp->jiffies_stall */ +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ /* Global control variables for rcupdate callback mechanism. */ struct rcu_ctrlblk { long cur; /* Current batch number. */ long completed; /* Number of the last completed batch */ - int next_pending; /* Is the next batch already waiting? */ + long pending; /* Number of the last pending batch */ +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR + unsigned long gp_start; /* Time at which GP started in jiffies. */ + unsigned long jiffies_stall; + /* Time at which to check for CPU stalls. */ +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ int signaled; @@ -66,11 +75,7 @@ static inline int rcu_batch_after(long a, long b) return (a - b) > 0; } -/* - * Per-CPU data for Read-Copy UPdate. - * nxtlist - new callbacks are added here - * curlist - current batch for which quiescent cycle started if any - */ +/* Per-CPU data for Read-Copy UPdate. */ struct rcu_data { /* 1) quiescent state handling : */ long quiescbatch; /* Batch # for grace period */ @@ -78,12 +83,24 @@ struct rcu_data { int qs_pending; /* core waits for quiesc state */ /* 2) batch handling */ - long batch; /* Batch # for current RCU batch */ + /* + * if nxtlist is not NULL, then: + * batch: + * The batch # for the last entry of nxtlist + * [*nxttail[1], NULL = *nxttail[2]): + * Entries that batch # <= batch + * [*nxttail[0], *nxttail[1]): + * Entries that batch # <= batch - 1 + * [nxtlist, *nxttail[0]): + * Entries that batch # <= batch - 2 + * The grace period for these entries has completed, and + * the other grace-period-completed entries may be moved + * here temporarily in rcu_process_callbacks(). + */ + long batch; struct rcu_head *nxtlist; - struct rcu_head **nxttail; + struct rcu_head **nxttail[3]; long qlen; /* # of queued callbacks */ - struct rcu_head *curlist; - struct rcu_head **curtail; struct rcu_head *donelist; struct rcu_head **donetail; long blimit; /* Upper limit on a processed batch */ diff --git a/include/linux/rculist.h b/include/linux/rculist.h index eb4443c7e05b..e649bd3f2c97 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -198,20 +198,6 @@ static inline void list_splice_init_rcu(struct list_head *list, at->prev = last; } -/** - * list_for_each_rcu - iterate over an rcu-protected list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_rcu(pos, head) \ - for (pos = rcu_dereference((head)->next); \ - prefetch(pos->next), pos != (head); \ - pos = rcu_dereference(pos->next)) - #define __list_for_each_rcu(pos, head) \ for (pos = rcu_dereference((head)->next); \ pos != (head); \ diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index e8b4039cfb2f..86f1f5e43e33 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -133,6 +133,26 @@ struct rcu_head { #define rcu_read_unlock_bh() __rcu_read_unlock_bh() /** + * rcu_read_lock_sched - mark the beginning of a RCU-classic critical section + * + * Should be used with either + * - synchronize_sched() + * or + * - call_rcu_sched() and rcu_barrier_sched() + * on the write-side to insure proper synchronization. + */ +#define rcu_read_lock_sched() preempt_disable() + +/* + * rcu_read_unlock_sched - marks the end of a RCU-classic critical section + * + * See rcu_read_lock_sched for more information. + */ +#define rcu_read_unlock_sched() preempt_enable() + + + +/** * rcu_dereference - fetch an RCU-protected pointer in an * RCU read-side critical section. This pointer may later * be safely dereferenced. diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h index 0967f03b0705..3e05c09b54a2 100644 --- a/include/linux/rcupreempt.h +++ b/include/linux/rcupreempt.h @@ -57,7 +57,13 @@ static inline void rcu_qsctr_inc(int cpu) rdssp->sched_qs++; } #define rcu_bh_qsctr_inc(cpu) -#define call_rcu_bh(head, rcu) call_rcu(head, rcu) + +/* + * Someone might want to pass call_rcu_bh as a function pointer. + * So this needs to just be a rename and not a macro function. + * (no parentheses) + */ +#define call_rcu_bh call_rcu /** * call_rcu_sched - Queue RCU callback for invocation after sched grace period. @@ -111,7 +117,6 @@ extern struct rcupreempt_trace *rcupreempt_trace_cpu(int cpu); struct softirq_action; #ifdef CONFIG_NO_HZ -DECLARE_PER_CPU(struct rcu_dyntick_sched, rcu_dyntick_sched); static inline void rcu_enter_nohz(void) { @@ -126,8 +131,8 @@ static inline void rcu_exit_nohz(void) { static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1); - smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ __get_cpu_var(rcu_dyntick_sched).dynticks++; + smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */ WARN_ON_RATELIMIT(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1), &rs); } diff --git a/include/linux/sched.h b/include/linux/sched.h index 3d9120c5ad15..5d0819ee442a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -451,8 +451,8 @@ struct signal_struct { * - everyone except group_exit_task is stopped during signal delivery * of fatal signals, group_exit_task processes the signal. */ - struct task_struct *group_exit_task; int notify_count; + struct task_struct *group_exit_task; /* thread group stop support, overloads group_exit_code too */ int group_stop_count; @@ -824,6 +824,9 @@ struct sched_domain { unsigned int ttwu_move_affine; unsigned int ttwu_move_balance; #endif +#ifdef CONFIG_SCHED_DEBUG + char *name; +#endif }; extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new, @@ -897,7 +900,7 @@ struct sched_class { void (*yield_task) (struct rq *rq); int (*select_task_rq)(struct task_struct *p, int sync); - void (*check_preempt_curr) (struct rq *rq, struct task_struct *p); + void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int sync); struct task_struct * (*pick_next_task) (struct rq *rq); void (*put_prev_task) (struct rq *rq, struct task_struct *p); @@ -1010,8 +1013,8 @@ struct sched_entity { struct sched_rt_entity { struct list_head run_list; - unsigned int time_slice; unsigned long timeout; + unsigned int time_slice; int nr_cpus_allowed; struct sched_rt_entity *back; diff --git a/include/linux/security.h b/include/linux/security.h index 80c4d002864c..f5c4a51eb42e 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1560,11 +1560,6 @@ struct security_operations { extern int security_init(void); extern int security_module_enable(struct security_operations *ops); extern int register_security(struct security_operations *ops); -extern struct dentry *securityfs_create_file(const char *name, mode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops); -extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent); -extern void securityfs_remove(struct dentry *dentry); /* Security operations */ int security_ptrace_may_access(struct task_struct *child, unsigned int mode); @@ -2424,25 +2419,6 @@ static inline int security_netlink_recv(struct sk_buff *skb, int cap) return cap_netlink_recv(skb, cap); } -static inline struct dentry *securityfs_create_dir(const char *name, - struct dentry *parent) -{ - return ERR_PTR(-ENODEV); -} - -static inline struct dentry *securityfs_create_file(const char *name, - mode_t mode, - struct dentry *parent, - void *data, - const struct file_operations *fops) -{ - return ERR_PTR(-ENODEV); -} - -static inline void securityfs_remove(struct dentry *dentry) -{ -} - static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { return -EOPNOTSUPP; @@ -2806,5 +2782,35 @@ static inline void security_audit_rule_free(void *lsmrule) #endif /* CONFIG_SECURITY */ #endif /* CONFIG_AUDIT */ +#ifdef CONFIG_SECURITYFS + +extern struct dentry *securityfs_create_file(const char *name, mode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops); +extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent); +extern void securityfs_remove(struct dentry *dentry); + +#else /* CONFIG_SECURITYFS */ + +static inline struct dentry *securityfs_create_dir(const char *name, + struct dentry *parent) +{ + return ERR_PTR(-ENODEV); +} + +static inline struct dentry *securityfs_create_file(const char *name, + mode_t mode, + struct dentry *parent, + void *data, + const struct file_operations *fops) +{ + return ERR_PTR(-ENODEV); +} + +static inline void securityfs_remove(struct dentry *dentry) +{} + +#endif + #endif /* ! __LINUX_SECURITY_H */ diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h new file mode 100644 index 000000000000..a3eb2f65b656 --- /dev/null +++ b/include/linux/string_helpers.h @@ -0,0 +1,16 @@ +#ifndef _LINUX_STRING_HELPERS_H_ +#define _LINUX_STRING_HELPERS_H_ + +#include <linux/types.h> + +/* Descriptions of the types of units to + * print in */ +enum string_size_units { + STRING_UNITS_10, /* use powers of 10^3 (standard SI) */ + STRING_UNITS_2, /* use binary powers of 2^10 */ +}; + +int string_get_size(u64 size, enum string_size_units units, + char *buf, int len); + +#endif diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index f9f6e793575c..855bf95963e7 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -75,7 +75,6 @@ struct scsi_cmnd { int retries; int allowed; - int timeout_per_command; unsigned char prot_op; unsigned char prot_type; @@ -86,7 +85,6 @@ struct scsi_cmnd { /* These elements define the operation we are about to perform */ unsigned char *cmnd; - struct timer_list eh_timeout; /* Used to time out the command. */ /* These elements define the operation we ultimately want to perform */ struct scsi_data_buffer sdb; @@ -139,7 +137,6 @@ extern void scsi_put_command(struct scsi_cmnd *); extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, struct device *); extern void scsi_finish_command(struct scsi_cmnd *cmd); -extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t *offset, size_t *len); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 80b2e93c2936..b49e725be039 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -42,9 +42,11 @@ enum scsi_device_state { * originate in the mid-layer) */ SDEV_OFFLINE, /* Device offlined (by error handling or * user request */ - SDEV_BLOCK, /* Device blocked by scsi lld. No scsi - * commands from user or midlayer should be issued - * to the scsi lld. */ + SDEV_BLOCK, /* Device blocked by scsi lld. No + * scsi commands from user or midlayer + * should be issued to the scsi + * lld. */ + SDEV_CREATED_BLOCK, /* same as above but for created devices */ }; enum scsi_device_event { @@ -384,10 +386,23 @@ static inline unsigned int sdev_id(struct scsi_device *sdev) #define scmd_id(scmd) sdev_id((scmd)->device) #define scmd_channel(scmd) sdev_channel((scmd)->device) +/* + * checks for positions of the SCSI state machine + */ static inline int scsi_device_online(struct scsi_device *sdev) { return sdev->sdev_state != SDEV_OFFLINE; } +static inline int scsi_device_blocked(struct scsi_device *sdev) +{ + return sdev->sdev_state == SDEV_BLOCK || + sdev->sdev_state == SDEV_CREATED_BLOCK; +} +static inline int scsi_device_created(struct scsi_device *sdev) +{ + return sdev->sdev_state == SDEV_CREATED || + sdev->sdev_state == SDEV_CREATED_BLOCK; +} /* accessor functions for the SCSI parameters */ static inline int scsi_device_sync(struct scsi_device *sdev) diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 44a55d1bf530..d123ca84e732 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -43,13 +43,6 @@ struct blk_queue_tags; #define DISABLE_CLUSTERING 0 #define ENABLE_CLUSTERING 1 -enum scsi_eh_timer_return { - EH_NOT_HANDLED, - EH_HANDLED, - EH_RESET_TIMER, -}; - - struct scsi_host_template { struct module *module; const char *name; @@ -347,7 +340,7 @@ struct scsi_host_template { * * Status: OPTIONAL */ - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); /* * Name of proc directory diff --git a/include/scsi/scsi_netlink.h b/include/scsi/scsi_netlink.h index 8c1470cc8209..536752c40d41 100644 --- a/include/scsi/scsi_netlink.h +++ b/include/scsi/scsi_netlink.h @@ -22,6 +22,9 @@ #ifndef SCSI_NETLINK_H #define SCSI_NETLINK_H +#include <linux/netlink.h> + + /* * This file intended to be included by both kernel and user space */ @@ -55,7 +58,41 @@ struct scsi_nl_hdr { #define SCSI_NL_TRANSPORT_FC 1 #define SCSI_NL_MAX_TRANSPORTS 2 -/* scsi_nl_hdr->msgtype values are defined in each transport */ +/* Transport-based scsi_nl_hdr->msgtype values are defined in each transport */ + +/* + * GENERIC SCSI scsi_nl_hdr->msgtype Values + */ + /* kernel -> user */ +#define SCSI_NL_SHOST_VENDOR 0x0001 + /* user -> kernel */ +/* SCSI_NL_SHOST_VENDOR msgtype is kernel->user and user->kernel */ + + +/* + * Message Structures : + */ + +/* macro to round up message lengths to 8byte boundary */ +#define SCSI_NL_MSGALIGN(len) (((len) + 7) & ~7) + + +/* + * SCSI HOST Vendor Unique messages : + * SCSI_NL_SHOST_VENDOR + * + * Note: The Vendor Unique message payload will begin directly after + * this structure, with the length of the payload per vmsg_datalen. + * + * Note: When specifying vendor_id, be sure to read the Vendor Type and ID + * formatting requirements specified below + */ +struct scsi_nl_host_vendor_msg { + struct scsi_nl_hdr snlh; /* must be 1st element ! */ + uint64_t vendor_id; + uint16_t host_no; + uint16_t vmsg_datalen; +} __attribute__((aligned(sizeof(uint64_t)))); /* @@ -83,5 +120,28 @@ struct scsi_nl_hdr { } +#ifdef __KERNEL__ + +#include <scsi/scsi_host.h> + +/* Exported Kernel Interfaces */ +int scsi_nl_add_transport(u8 tport, + int (*msg_handler)(struct sk_buff *), + void (*event_handler)(struct notifier_block *, unsigned long, void *)); +void scsi_nl_remove_transport(u8 tport); + +int scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, + int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, + u32 len, u32 pid), + void (*nlevt_handler)(struct notifier_block *nb, + unsigned long event, void *notify_ptr)); +void scsi_nl_remove_driver(u64 vendor_id); + +void scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr); +int scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, + char *data_buf, u32 data_len); + +#endif /* __KERNEL__ */ + #endif /* SCSI_NETLINK_H */ diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index 490bd13a634c..0de32cd4e8a7 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -21,6 +21,7 @@ #define SCSI_TRANSPORT_H #include <linux/transport_class.h> +#include <linux/blkdev.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> @@ -64,7 +65,7 @@ struct scsi_transport_template { * begin counting again * EH_NOT_HANDLED Begin normal error recovery */ - enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); /* * Used as callback for the completion of i_t_nexus request diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 878373c32ef7..21018a4df452 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -167,6 +167,26 @@ enum fc_tgtid_binding_type { struct device_attribute dev_attr_vport_##_name = \ __ATTR(_name,_mode,_show,_store) +/* + * fc_vport_identifiers: This set of data contains all elements + * to uniquely identify and instantiate a FC virtual port. + * + * Notes: + * symbolic_name: The driver is to append the symbolic_name string data + * to the symbolic_node_name data that it generates by default. + * the resulting combination should then be registered with the switch. + * It is expected that things like Xen may stuff a VM title into + * this field. + */ +#define FC_VPORT_SYMBOLIC_NAMELEN 64 +struct fc_vport_identifiers { + u64 node_name; + u64 port_name; + u32 roles; + bool disable; + enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */ + char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN]; +}; /* * FC Virtual Port Attributes @@ -197,7 +217,6 @@ struct device_attribute dev_attr_vport_##_name = \ * managed by the transport w/o driver interaction. */ -#define FC_VPORT_SYMBOLIC_NAMELEN 64 struct fc_vport { /* Fixed Attributes */ @@ -732,6 +751,8 @@ void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, * be sure to read the Vendor Type and ID formatting requirements * specified in scsi_netlink.h */ +struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, + struct fc_vport_identifiers *); int fc_vport_terminate(struct fc_vport *vport); #endif /* SCSI_TRANSPORT_FC_H */ diff --git a/init/do_mounts.c b/init/do_mounts.c index 3715feb8446d..d055b1914c3d 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -263,6 +263,10 @@ retry: printk("Please append a correct \"root=\" boot option; here are the available partitions:\n"); printk_all_partitions(); +#ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT + printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify " + "explicit textual name for \"root=\" boot option.\n"); +#endif panic("VFS: Unable to mount root fs on %s", b); } diff --git a/kernel/cpu.c b/kernel/cpu.c index f17e9854c246..86d49045daed 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -199,13 +199,14 @@ static int __ref take_cpu_down(void *_param) struct take_cpu_down_param *param = _param; int err; - raw_notifier_call_chain(&cpu_chain, CPU_DYING | param->mod, - param->hcpu); /* Ensure this CPU doesn't handle any more interrupts. */ err = __cpu_disable(); if (err < 0) return err; + raw_notifier_call_chain(&cpu_chain, CPU_DYING | param->mod, + param->hcpu); + /* Force idle task to run as soon as we yield: it should immediately notice cpu is offline and die quickly. */ sched_idle_next(); @@ -453,6 +454,25 @@ out: } #endif /* CONFIG_PM_SLEEP_SMP */ +/** + * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers + * @cpu: cpu that just started + * + * This function calls the cpu_chain notifiers with CPU_STARTING. + * It must be called by the arch code on the new cpu, before the new cpu + * enables interrupts and before the "boot" cpu returns from __cpu_up(). + */ +void notify_cpu_starting(unsigned int cpu) +{ + unsigned long val = CPU_STARTING; + +#ifdef CONFIG_PM_SLEEP_SMP + if (cpu_isset(cpu, frozen_cpus)) + val = CPU_STARTING_FROZEN; +#endif /* CONFIG_PM_SLEEP_SMP */ + raw_notifier_call_chain(&cpu_chain, val, (void *)(long)cpu); +} + #endif /* CONFIG_SMP */ /* diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 827cd9adccb2..eab7bd6628e0 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1921,7 +1921,7 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs) * that has tasks along with an empty 'mems'. But if we did see such * a cpuset, we'd handle it just like we do if its 'cpus' was empty. */ -static void scan_for_empty_cpusets(const struct cpuset *root) +static void scan_for_empty_cpusets(struct cpuset *root) { LIST_HEAD(queue); struct cpuset *cp; /* scans cpusets being updated */ diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index aad93cdc9f68..37f72e551542 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -47,6 +47,7 @@ #include <linux/notifier.h> #include <linux/cpu.h> #include <linux/mutex.h> +#include <linux/time.h> #ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key rcu_lock_key; @@ -60,12 +61,14 @@ EXPORT_SYMBOL_GPL(rcu_lock_map); static struct rcu_ctrlblk rcu_ctrlblk = { .cur = -300, .completed = -300, + .pending = -300, .lock = __SPIN_LOCK_UNLOCKED(&rcu_ctrlblk.lock), .cpumask = CPU_MASK_NONE, }; static struct rcu_ctrlblk rcu_bh_ctrlblk = { .cur = -300, .completed = -300, + .pending = -300, .lock = __SPIN_LOCK_UNLOCKED(&rcu_bh_ctrlblk.lock), .cpumask = CPU_MASK_NONE, }; @@ -83,7 +86,10 @@ static void force_quiescent_state(struct rcu_data *rdp, { int cpu; cpumask_t cpumask; + unsigned long flags; + set_need_resched(); + spin_lock_irqsave(&rcp->lock, flags); if (unlikely(!rcp->signaled)) { rcp->signaled = 1; /* @@ -109,6 +115,7 @@ static void force_quiescent_state(struct rcu_data *rdp, for_each_cpu_mask_nr(cpu, cpumask) smp_send_reschedule(cpu); } + spin_unlock_irqrestore(&rcp->lock, flags); } #else static inline void force_quiescent_state(struct rcu_data *rdp, @@ -118,6 +125,126 @@ static inline void force_quiescent_state(struct rcu_data *rdp, } #endif +static void __call_rcu(struct rcu_head *head, struct rcu_ctrlblk *rcp, + struct rcu_data *rdp) +{ + long batch; + + head->next = NULL; + smp_mb(); /* Read of rcu->cur must happen after any change by caller. */ + + /* + * Determine the batch number of this callback. + * + * Using ACCESS_ONCE to avoid the following error when gcc eliminates + * local variable "batch" and emits codes like this: + * 1) rdp->batch = rcp->cur + 1 # gets old value + * ...... + * 2)rcu_batch_after(rcp->cur + 1, rdp->batch) # gets new value + * then [*nxttail[0], *nxttail[1]) may contain callbacks + * that batch# = rdp->batch, see the comment of struct rcu_data. + */ + batch = ACCESS_ONCE(rcp->cur) + 1; + + if (rdp->nxtlist && rcu_batch_after(batch, rdp->batch)) { + /* process callbacks */ + rdp->nxttail[0] = rdp->nxttail[1]; + rdp->nxttail[1] = rdp->nxttail[2]; + if (rcu_batch_after(batch - 1, rdp->batch)) + rdp->nxttail[0] = rdp->nxttail[2]; + } + + rdp->batch = batch; + *rdp->nxttail[2] = head; + rdp->nxttail[2] = &head->next; + + if (unlikely(++rdp->qlen > qhimark)) { + rdp->blimit = INT_MAX; + force_quiescent_state(rdp, &rcu_ctrlblk); + } +} + +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR + +static void record_gp_stall_check_time(struct rcu_ctrlblk *rcp) +{ + rcp->gp_start = jiffies; + rcp->jiffies_stall = jiffies + RCU_SECONDS_TILL_STALL_CHECK; +} + +static void print_other_cpu_stall(struct rcu_ctrlblk *rcp) +{ + int cpu; + long delta; + unsigned long flags; + + /* Only let one CPU complain about others per time interval. */ + + spin_lock_irqsave(&rcp->lock, flags); + delta = jiffies - rcp->jiffies_stall; + if (delta < 2 || rcp->cur != rcp->completed) { + spin_unlock_irqrestore(&rcp->lock, flags); + return; + } + rcp->jiffies_stall = jiffies + RCU_SECONDS_TILL_STALL_RECHECK; + spin_unlock_irqrestore(&rcp->lock, flags); + + /* OK, time to rat on our buddy... */ + + printk(KERN_ERR "RCU detected CPU stalls:"); + for_each_possible_cpu(cpu) { + if (cpu_isset(cpu, rcp->cpumask)) + printk(" %d", cpu); + } + printk(" (detected by %d, t=%ld jiffies)\n", + smp_processor_id(), (long)(jiffies - rcp->gp_start)); +} + +static void print_cpu_stall(struct rcu_ctrlblk *rcp) +{ + unsigned long flags; + + printk(KERN_ERR "RCU detected CPU %d stall (t=%lu/%lu jiffies)\n", + smp_processor_id(), jiffies, + jiffies - rcp->gp_start); + dump_stack(); + spin_lock_irqsave(&rcp->lock, flags); + if ((long)(jiffies - rcp->jiffies_stall) >= 0) + rcp->jiffies_stall = + jiffies + RCU_SECONDS_TILL_STALL_RECHECK; + spin_unlock_irqrestore(&rcp->lock, flags); + set_need_resched(); /* kick ourselves to get things going. */ +} + +static void check_cpu_stall(struct rcu_ctrlblk *rcp) +{ + long delta; + + delta = jiffies - rcp->jiffies_stall; + if (cpu_isset(smp_processor_id(), rcp->cpumask) && delta >= 0) { + + /* We haven't checked in, so go dump stack. */ + print_cpu_stall(rcp); + + } else if (rcp->cur != rcp->completed && delta >= 2) { + + /* They had two seconds to dump stack, so complain. */ + print_other_cpu_stall(rcp); + } +} + +#else /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ + +static void record_gp_stall_check_time(struct rcu_ctrlblk *rcp) +{ +} + +static inline void check_cpu_stall(struct rcu_ctrlblk *rcp) +{ +} + +#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ + /** * call_rcu - Queue an RCU callback for invocation after a grace period. * @head: structure to be used for queueing the RCU updates. @@ -133,18 +260,10 @@ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) { unsigned long flags; - struct rcu_data *rdp; head->func = func; - head->next = NULL; local_irq_save(flags); - rdp = &__get_cpu_var(rcu_data); - *rdp->nxttail = head; - rdp->nxttail = &head->next; - if (unlikely(++rdp->qlen > qhimark)) { - rdp->blimit = INT_MAX; - force_quiescent_state(rdp, &rcu_ctrlblk); - } + __call_rcu(head, &rcu_ctrlblk, &__get_cpu_var(rcu_data)); local_irq_restore(flags); } EXPORT_SYMBOL_GPL(call_rcu); @@ -169,20 +288,10 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) { unsigned long flags; - struct rcu_data *rdp; head->func = func; - head->next = NULL; local_irq_save(flags); - rdp = &__get_cpu_var(rcu_bh_data); - *rdp->nxttail = head; - rdp->nxttail = &head->next; - - if (unlikely(++rdp->qlen > qhimark)) { - rdp->blimit = INT_MAX; - force_quiescent_state(rdp, &rcu_bh_ctrlblk); - } - + __call_rcu(head, &rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data)); local_irq_restore(flags); } EXPORT_SYMBOL_GPL(call_rcu_bh); @@ -211,12 +320,6 @@ EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); static inline void raise_rcu_softirq(void) { raise_softirq(RCU_SOFTIRQ); - /* - * The smp_mb() here is required to ensure that this cpu's - * __rcu_process_callbacks() reads the most recently updated - * value of rcu->cur. - */ - smp_mb(); } /* @@ -225,6 +328,7 @@ static inline void raise_rcu_softirq(void) */ static void rcu_do_batch(struct rcu_data *rdp) { + unsigned long flags; struct rcu_head *next, *list; int count = 0; @@ -239,9 +343,9 @@ static void rcu_do_batch(struct rcu_data *rdp) } rdp->donelist = list; - local_irq_disable(); + local_irq_save(flags); rdp->qlen -= count; - local_irq_enable(); + local_irq_restore(flags); if (rdp->blimit == INT_MAX && rdp->qlen <= qlowmark) rdp->blimit = blimit; @@ -269,6 +373,7 @@ static void rcu_do_batch(struct rcu_data *rdp) * rcu_check_quiescent_state calls rcu_start_batch(0) to start the next grace * period (if necessary). */ + /* * Register a new batch of callbacks, and start it up if there is currently no * active batch and the batch to be registered has not already occurred. @@ -276,15 +381,10 @@ static void rcu_do_batch(struct rcu_data *rdp) */ static void rcu_start_batch(struct rcu_ctrlblk *rcp) { - if (rcp->next_pending && + if (rcp->cur != rcp->pending && rcp->completed == rcp->cur) { - rcp->next_pending = 0; - /* - * next_pending == 0 must be visible in - * __rcu_process_callbacks() before it can see new value of cur. - */ - smp_wmb(); rcp->cur++; + record_gp_stall_check_time(rcp); /* * Accessing nohz_cpu_mask before incrementing rcp->cur needs a @@ -322,6 +422,8 @@ static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp) static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { + unsigned long flags; + if (rdp->quiescbatch != rcp->cur) { /* start new grace period: */ rdp->qs_pending = 1; @@ -345,7 +447,7 @@ static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, return; rdp->qs_pending = 0; - spin_lock(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); /* * rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync * during cpu startup. Ignore the quiescent state. @@ -353,7 +455,7 @@ static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, if (likely(rdp->quiescbatch == rcp->cur)) cpu_quiet(rdp->cpu, rcp); - spin_unlock(&rcp->lock); + spin_unlock_irqrestore(&rcp->lock, flags); } @@ -364,33 +466,38 @@ static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp, * which is dead and hence not processing interrupts. */ static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list, - struct rcu_head **tail) + struct rcu_head **tail, long batch) { - local_irq_disable(); - *this_rdp->nxttail = list; - if (list) - this_rdp->nxttail = tail; - local_irq_enable(); + unsigned long flags; + + if (list) { + local_irq_save(flags); + this_rdp->batch = batch; + *this_rdp->nxttail[2] = list; + this_rdp->nxttail[2] = tail; + local_irq_restore(flags); + } } static void __rcu_offline_cpu(struct rcu_data *this_rdp, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { - /* if the cpu going offline owns the grace period + unsigned long flags; + + /* + * if the cpu going offline owns the grace period * we can block indefinitely waiting for it, so flush * it here */ - spin_lock_bh(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags); if (rcp->cur != rcp->completed) cpu_quiet(rdp->cpu, rcp); - spin_unlock_bh(&rcp->lock); - rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail); - rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail); - rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail); + rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail, rcp->cur + 1); + rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail[2], rcp->cur + 1); + spin_unlock(&rcp->lock); - local_irq_disable(); this_rdp->qlen += rdp->qlen; - local_irq_enable(); + local_irq_restore(flags); } static void rcu_offline_cpu(int cpu) @@ -420,38 +527,52 @@ static void rcu_offline_cpu(int cpu) static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { - if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) { - *rdp->donetail = rdp->curlist; - rdp->donetail = rdp->curtail; - rdp->curlist = NULL; - rdp->curtail = &rdp->curlist; - } + unsigned long flags; + long completed_snap; - if (rdp->nxtlist && !rdp->curlist) { - local_irq_disable(); - rdp->curlist = rdp->nxtlist; - rdp->curtail = rdp->nxttail; - rdp->nxtlist = NULL; - rdp->nxttail = &rdp->nxtlist; - local_irq_enable(); + if (rdp->nxtlist) { + local_irq_save(flags); + completed_snap = ACCESS_ONCE(rcp->completed); /* - * start the next batch of callbacks + * move the other grace-period-completed entries to + * [rdp->nxtlist, *rdp->nxttail[0]) temporarily */ + if (!rcu_batch_before(completed_snap, rdp->batch)) + rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2]; + else if (!rcu_batch_before(completed_snap, rdp->batch - 1)) + rdp->nxttail[0] = rdp->nxttail[1]; - /* determine batch number */ - rdp->batch = rcp->cur + 1; - /* see the comment and corresponding wmb() in - * the rcu_start_batch() + /* + * the grace period for entries in + * [rdp->nxtlist, *rdp->nxttail[0]) has completed and + * move these entries to donelist */ - smp_rmb(); + if (rdp->nxttail[0] != &rdp->nxtlist) { + *rdp->donetail = rdp->nxtlist; + rdp->donetail = rdp->nxttail[0]; + rdp->nxtlist = *rdp->nxttail[0]; + *rdp->donetail = NULL; + + if (rdp->nxttail[1] == rdp->nxttail[0]) + rdp->nxttail[1] = &rdp->nxtlist; + if (rdp->nxttail[2] == rdp->nxttail[0]) + rdp->nxttail[2] = &rdp->nxtlist; + rdp->nxttail[0] = &rdp->nxtlist; + } + + local_irq_restore(flags); + + if (rcu_batch_after(rdp->batch, rcp->pending)) { + unsigned long flags2; - if (!rcp->next_pending) { /* and start it/schedule start if it's a new batch */ - spin_lock(&rcp->lock); - rcp->next_pending = 1; - rcu_start_batch(rcp); - spin_unlock(&rcp->lock); + spin_lock_irqsave(&rcp->lock, flags2); + if (rcu_batch_after(rdp->batch, rcp->pending)) { + rcp->pending = rdp->batch; + rcu_start_batch(rcp); + } + spin_unlock_irqrestore(&rcp->lock, flags2); } } @@ -462,21 +583,53 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp, static void rcu_process_callbacks(struct softirq_action *unused) { + /* + * Memory references from any prior RCU read-side critical sections + * executed by the interrupted code must be see before any RCU + * grace-period manupulations below. + */ + + smp_mb(); /* See above block comment. */ + __rcu_process_callbacks(&rcu_ctrlblk, &__get_cpu_var(rcu_data)); __rcu_process_callbacks(&rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data)); + + /* + * Memory references from any later RCU read-side critical sections + * executed by the interrupted code must be see after any RCU + * grace-period manupulations above. + */ + + smp_mb(); /* See above block comment. */ } static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { - /* This cpu has pending rcu entries and the grace period - * for them has completed. - */ - if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) - return 1; + /* Check for CPU stalls, if enabled. */ + check_cpu_stall(rcp); - /* This cpu has no pending entries, but there are new entries */ - if (!rdp->curlist && rdp->nxtlist) - return 1; + if (rdp->nxtlist) { + long completed_snap = ACCESS_ONCE(rcp->completed); + + /* + * This cpu has pending rcu entries and the grace period + * for them has completed. + */ + if (!rcu_batch_before(completed_snap, rdp->batch)) + return 1; + if (!rcu_batch_before(completed_snap, rdp->batch - 1) && + rdp->nxttail[0] != rdp->nxttail[1]) + return 1; + if (rdp->nxttail[0] != &rdp->nxtlist) + return 1; + + /* + * This cpu has pending rcu entries and the new batch + * for then hasn't been started nor scheduled start + */ + if (rcu_batch_after(rdp->batch, rcp->pending)) + return 1; + } /* This cpu has finished callbacks to invoke */ if (rdp->donelist) @@ -512,9 +665,15 @@ int rcu_needs_cpu(int cpu) struct rcu_data *rdp = &per_cpu(rcu_data, cpu); struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu); - return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu)); + return !!rdp->nxtlist || !!rdp_bh->nxtlist || rcu_pending(cpu); } +/* + * Top-level function driving RCU grace-period detection, normally + * invoked from the scheduler-clock interrupt. This function simply + * increments counters that are read only from softirq by this same + * CPU, so there are no memory barriers required. + */ void rcu_check_callbacks(int cpu, int user) { if (user || @@ -558,14 +717,17 @@ void rcu_check_callbacks(int cpu, int user) static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) { + unsigned long flags; + + spin_lock_irqsave(&rcp->lock, flags); memset(rdp, 0, sizeof(*rdp)); - rdp->curtail = &rdp->curlist; - rdp->nxttail = &rdp->nxtlist; + rdp->nxttail[0] = rdp->nxttail[1] = rdp->nxttail[2] = &rdp->nxtlist; rdp->donetail = &rdp->donelist; rdp->quiescbatch = rcp->completed; rdp->qs_pending = 0; rdp->cpu = cpu; rdp->blimit = blimit; + spin_unlock_irqrestore(&rcp->lock, flags); } static void __cpuinit rcu_online_cpu(int cpu) @@ -610,6 +772,9 @@ static struct notifier_block __cpuinitdata rcu_nb = { */ void __init __rcu_init(void) { +#ifdef CONFIG_RCU_CPU_STALL_DETECTOR + printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n"); +#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)smp_processor_id()); /* Register notifier for non-boot CPUs */ diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c index 27827931ca0d..ca4bbbe04aa4 100644 --- a/kernel/rcupreempt.c +++ b/kernel/rcupreempt.c @@ -59,14 +59,6 @@ #include <linux/rcupreempt_trace.h> /* - * Macro that prevents the compiler from reordering accesses, but does - * absolutely -nothing- to prevent CPUs from reordering. This is used - * only to mediate communication between mainline code and hardware - * interrupt and NMI handlers. - */ -#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) - -/* * PREEMPT_RCU data structures. */ diff --git a/kernel/rcupreempt_trace.c b/kernel/rcupreempt_trace.c index 5edf82c34bbc..35c2d3360ecf 100644 --- a/kernel/rcupreempt_trace.c +++ b/kernel/rcupreempt_trace.c @@ -308,11 +308,16 @@ out: static int __init rcupreempt_trace_init(void) { + int ret; + mutex_init(&rcupreempt_trace_mutex); rcupreempt_trace_buf = kmalloc(RCUPREEMPT_TRACE_BUF_SIZE, GFP_KERNEL); if (!rcupreempt_trace_buf) return 1; - return rcupreempt_debugfs_init(); + ret = rcupreempt_debugfs_init(); + if (ret) + kfree(rcupreempt_trace_buf); + return ret; } static void __exit rcupreempt_trace_cleanup(void) diff --git a/kernel/sched.c b/kernel/sched.c index ad1962dc0aa2..6f230596bd0c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -204,11 +204,16 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime) rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED; } +static inline int rt_bandwidth_enabled(void) +{ + return sysctl_sched_rt_runtime >= 0; +} + static void start_rt_bandwidth(struct rt_bandwidth *rt_b) { ktime_t now; - if (rt_b->rt_runtime == RUNTIME_INF) + if (rt_bandwidth_enabled() && rt_b->rt_runtime == RUNTIME_INF) return; if (hrtimer_active(&rt_b->rt_period_timer)) @@ -298,9 +303,9 @@ static DEFINE_PER_CPU(struct cfs_rq, init_cfs_rq) ____cacheline_aligned_in_smp; static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity); static DEFINE_PER_CPU(struct rt_rq, init_rt_rq) ____cacheline_aligned_in_smp; #endif /* CONFIG_RT_GROUP_SCHED */ -#else /* !CONFIG_FAIR_GROUP_SCHED */ +#else /* !CONFIG_USER_SCHED */ #define root_task_group init_task_group -#endif /* CONFIG_FAIR_GROUP_SCHED */ +#endif /* CONFIG_USER_SCHED */ /* task_group_lock serializes add/remove of task groups and also changes to * a task group's cpu shares. @@ -604,9 +609,9 @@ struct rq { static DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); -static inline void check_preempt_curr(struct rq *rq, struct task_struct *p) +static inline void check_preempt_curr(struct rq *rq, struct task_struct *p, int sync) { - rq->curr->sched_class->check_preempt_curr(rq, p); + rq->curr->sched_class->check_preempt_curr(rq, p, sync); } static inline int cpu_of(struct rq *rq) @@ -1102,7 +1107,7 @@ static void hrtick_start(struct rq *rq, u64 delay) hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), HRTIMER_MODE_REL); } -static void init_hrtick(void) +static inline void init_hrtick(void) { } #endif /* CONFIG_SMP */ @@ -1121,7 +1126,7 @@ static void init_rq_hrtick(struct rq *rq) rq->hrtick_timer.function = hrtick; rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU; } -#else +#else /* CONFIG_SCHED_HRTICK */ static inline void hrtick_clear(struct rq *rq) { } @@ -1133,7 +1138,7 @@ static inline void init_rq_hrtick(struct rq *rq) static inline void init_hrtick(void) { } -#endif +#endif /* CONFIG_SCHED_HRTICK */ /* * resched_task - mark a task 'to be rescheduled now'. @@ -1380,38 +1385,24 @@ static inline void dec_cpu_load(struct rq *rq, unsigned long load) update_load_sub(&rq->load, load); } -#ifdef CONFIG_SMP -static unsigned long source_load(int cpu, int type); -static unsigned long target_load(int cpu, int type); -static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd); - -static unsigned long cpu_avg_load_per_task(int cpu) -{ - struct rq *rq = cpu_rq(cpu); - - if (rq->nr_running) - rq->avg_load_per_task = rq->load.weight / rq->nr_running; - - return rq->avg_load_per_task; -} - -#ifdef CONFIG_FAIR_GROUP_SCHED - -typedef void (*tg_visitor)(struct task_group *, int, struct sched_domain *); +#if (defined(CONFIG_SMP) && defined(CONFIG_FAIR_GROUP_SCHED)) || defined(CONFIG_RT_GROUP_SCHED) +typedef int (*tg_visitor)(struct task_group *, void *); /* * Iterate the full tree, calling @down when first entering a node and @up when * leaving it for the final time. */ -static void -walk_tg_tree(tg_visitor down, tg_visitor up, int cpu, struct sched_domain *sd) +static int walk_tg_tree(tg_visitor down, tg_visitor up, void *data) { struct task_group *parent, *child; + int ret; rcu_read_lock(); parent = &root_task_group; down: - (*down)(parent, cpu, sd); + ret = (*down)(parent, data); + if (ret) + goto out_unlock; list_for_each_entry_rcu(child, &parent->children, siblings) { parent = child; goto down; @@ -1419,15 +1410,43 @@ down: up: continue; } - (*up)(parent, cpu, sd); + ret = (*up)(parent, data); + if (ret) + goto out_unlock; child = parent; parent = parent->parent; if (parent) goto up; +out_unlock: rcu_read_unlock(); + + return ret; } +static int tg_nop(struct task_group *tg, void *data) +{ + return 0; +} +#endif + +#ifdef CONFIG_SMP +static unsigned long source_load(int cpu, int type); +static unsigned long target_load(int cpu, int type); +static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd); + +static unsigned long cpu_avg_load_per_task(int cpu) +{ + struct rq *rq = cpu_rq(cpu); + + if (rq->nr_running) + rq->avg_load_per_task = rq->load.weight / rq->nr_running; + + return rq->avg_load_per_task; +} + +#ifdef CONFIG_FAIR_GROUP_SCHED + static void __set_se_shares(struct sched_entity *se, unsigned long shares); /* @@ -1486,11 +1505,11 @@ __update_group_shares_cpu(struct task_group *tg, int cpu, * This needs to be done in a bottom-up fashion because the rq weight of a * parent group depends on the shares of its child groups. */ -static void -tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) +static int tg_shares_up(struct task_group *tg, void *data) { unsigned long rq_weight = 0; unsigned long shares = 0; + struct sched_domain *sd = data; int i; for_each_cpu_mask(i, sd->span) { @@ -1515,6 +1534,8 @@ tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) __update_group_shares_cpu(tg, i, shares, rq_weight); spin_unlock_irqrestore(&rq->lock, flags); } + + return 0; } /* @@ -1522,10 +1543,10 @@ tg_shares_up(struct task_group *tg, int cpu, struct sched_domain *sd) * This needs to be done in a top-down fashion because the load of a child * group is a fraction of its parents load. */ -static void -tg_load_down(struct task_group *tg, int cpu, struct sched_domain *sd) +static int tg_load_down(struct task_group *tg, void *data) { unsigned long load; + long cpu = (long)data; if (!tg->parent) { load = cpu_rq(cpu)->load.weight; @@ -1536,11 +1557,8 @@ tg_load_down(struct task_group *tg, int cpu, struct sched_domain *sd) } tg->cfs_rq[cpu]->h_load = load; -} -static void -tg_nop(struct task_group *tg, int cpu, struct sched_domain *sd) -{ + return 0; } static void update_shares(struct sched_domain *sd) @@ -1550,7 +1568,7 @@ static void update_shares(struct sched_domain *sd) if (elapsed >= (s64)(u64)sysctl_sched_shares_ratelimit) { sd->last_update = now; - walk_tg_tree(tg_nop, tg_shares_up, 0, sd); + walk_tg_tree(tg_nop, tg_shares_up, sd); } } @@ -1561,9 +1579,9 @@ static void update_shares_locked(struct rq *rq, struct sched_domain *sd) spin_lock(&rq->lock); } -static void update_h_load(int cpu) +static void update_h_load(long cpu) { - walk_tg_tree(tg_load_down, tg_nop, cpu, NULL); + walk_tg_tree(tg_load_down, tg_nop, (void *)cpu); } #else @@ -1921,11 +1939,8 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) running = task_running(rq, p); on_rq = p->se.on_rq; ncsw = 0; - if (!match_state || p->state == match_state) { - ncsw = p->nivcsw + p->nvcsw; - if (unlikely(!ncsw)) - ncsw = 1; - } + if (!match_state || p->state == match_state) + ncsw = p->nvcsw | LONG_MIN; /* sets MSB */ task_rq_unlock(rq, &flags); /* @@ -2285,7 +2300,7 @@ out_running: trace_mark(kernel_sched_wakeup, "pid %d state %ld ## rq %p task %p rq->curr %p", p->pid, p->state, rq, p, rq->curr); - check_preempt_curr(rq, p); + check_preempt_curr(rq, p, sync); p->state = TASK_RUNNING; #ifdef CONFIG_SMP @@ -2420,7 +2435,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags) trace_mark(kernel_sched_wakeup_new, "pid %d state %ld ## rq %p task %p rq->curr %p", p->pid, p->state, rq, p, rq->curr); - check_preempt_curr(rq, p); + check_preempt_curr(rq, p, 0); #ifdef CONFIG_SMP if (p->sched_class->task_wake_up) p->sched_class->task_wake_up(rq, p); @@ -2880,7 +2895,7 @@ static void pull_task(struct rq *src_rq, struct task_struct *p, * Note that idle threads have a prio of MAX_PRIO, for this test * to be always true for them. */ - check_preempt_curr(this_rq, p); + check_preempt_curr(this_rq, p, 0); } /* @@ -4627,6 +4642,15 @@ __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) } EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ +/** + * complete: - signals a single thread waiting on this completion + * @x: holds the state of this particular completion + * + * This will wake up a single thread waiting on this completion. Threads will be + * awakened in the same order in which they were queued. + * + * See also complete_all(), wait_for_completion() and related routines. + */ void complete(struct completion *x) { unsigned long flags; @@ -4638,6 +4662,12 @@ void complete(struct completion *x) } EXPORT_SYMBOL(complete); +/** + * complete_all: - signals all threads waiting on this completion + * @x: holds the state of this particular completion + * + * This will wake up all threads waiting on this particular completion event. + */ void complete_all(struct completion *x) { unsigned long flags; @@ -4658,10 +4688,7 @@ do_wait_for_common(struct completion *x, long timeout, int state) wait.flags |= WQ_FLAG_EXCLUSIVE; __add_wait_queue_tail(&x->wait, &wait); do { - if ((state == TASK_INTERRUPTIBLE && - signal_pending(current)) || - (state == TASK_KILLABLE && - fatal_signal_pending(current))) { + if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; } @@ -4689,12 +4716,31 @@ wait_for_common(struct completion *x, long timeout, int state) return timeout; } +/** + * wait_for_completion: - waits for completion of a task + * @x: holds the state of this particular completion + * + * This waits to be signaled for completion of a specific task. It is NOT + * interruptible and there is no timeout. + * + * See also similar routines (i.e. wait_for_completion_timeout()) with timeout + * and interrupt capability. Also see complete(). + */ void __sched wait_for_completion(struct completion *x) { wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(wait_for_completion); +/** + * wait_for_completion_timeout: - waits for completion of a task (w/timeout) + * @x: holds the state of this particular completion + * @timeout: timeout value in jiffies + * + * This waits for either a completion of a specific task to be signaled or for a + * specified timeout to expire. The timeout is in jiffies. It is not + * interruptible. + */ unsigned long __sched wait_for_completion_timeout(struct completion *x, unsigned long timeout) { @@ -4702,6 +4748,13 @@ wait_for_completion_timeout(struct completion *x, unsigned long timeout) } EXPORT_SYMBOL(wait_for_completion_timeout); +/** + * wait_for_completion_interruptible: - waits for completion of a task (w/intr) + * @x: holds the state of this particular completion + * + * This waits for completion of a specific task to be signaled. It is + * interruptible. + */ int __sched wait_for_completion_interruptible(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE); @@ -4711,6 +4764,14 @@ int __sched wait_for_completion_interruptible(struct completion *x) } EXPORT_SYMBOL(wait_for_completion_interruptible); +/** + * wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr)) + * @x: holds the state of this particular completion + * @timeout: timeout value in jiffies + * + * This waits for either a completion of a specific task to be signaled or for a + * specified timeout to expire. It is interruptible. The timeout is in jiffies. + */ unsigned long __sched wait_for_completion_interruptible_timeout(struct completion *x, unsigned long timeout) @@ -4719,6 +4780,13 @@ wait_for_completion_interruptible_timeout(struct completion *x, } EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); +/** + * wait_for_completion_killable: - waits for completion of a task (killable) + * @x: holds the state of this particular completion + * + * This waits to be signaled for completion of a specific task. It can be + * interrupted by a kill signal. + */ int __sched wait_for_completion_killable(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE); @@ -5121,7 +5189,8 @@ recheck: * Do not allow realtime tasks into groups that have no runtime * assigned. */ - if (rt_policy(policy) && task_group(p)->rt_bandwidth.rt_runtime == 0) + if (rt_bandwidth_enabled() && rt_policy(policy) && + task_group(p)->rt_bandwidth.rt_runtime == 0) return -EPERM; #endif @@ -5957,7 +6026,7 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) set_task_cpu(p, dest_cpu); if (on_rq) { activate_task(rq_dest, p, 0); - check_preempt_curr(rq_dest, p); + check_preempt_curr(rq_dest, p, 0); } done: ret = 1; @@ -6282,7 +6351,7 @@ set_table_entry(struct ctl_table *entry, static struct ctl_table * sd_alloc_ctl_domain_table(struct sched_domain *sd) { - struct ctl_table *table = sd_alloc_ctl_entry(12); + struct ctl_table *table = sd_alloc_ctl_entry(13); if (table == NULL) return NULL; @@ -6310,7 +6379,9 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd) sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[10], "flags", &sd->flags, sizeof(int), 0644, proc_dointvec_minmax); - /* &table[11] is terminator */ + set_table_entry(&table[11], "name", sd->name, + CORENAME_MAX_SIZE, 0444, proc_dostring); + /* &table[12] is terminator */ return table; } @@ -7194,13 +7265,21 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd) * Non-inlined to reduce accumulated stack pressure in build_sched_domains() */ +#ifdef CONFIG_SCHED_DEBUG +# define SD_INIT_NAME(sd, type) sd->name = #type +#else +# define SD_INIT_NAME(sd, type) do { } while (0) +#endif + #define SD_INIT(sd, type) sd_init_##type(sd) + #define SD_INIT_FUNC(type) \ static noinline void sd_init_##type(struct sched_domain *sd) \ { \ memset(sd, 0, sizeof(*sd)); \ *sd = SD_##type##_INIT; \ sd->level = SD_LV_##type; \ + SD_INIT_NAME(sd, type); \ } SD_INIT_FUNC(CPU) @@ -8242,20 +8321,25 @@ void __might_sleep(char *file, int line) #ifdef in_atomic static unsigned long prev_jiffy; /* ratelimiting */ - if ((in_atomic() || irqs_disabled()) && - system_state == SYSTEM_RUNNING && !oops_in_progress) { - if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) - return; - prev_jiffy = jiffies; - printk(KERN_ERR "BUG: sleeping function called from invalid" - " context at %s:%d\n", file, line); - printk("in_atomic():%d, irqs_disabled():%d\n", - in_atomic(), irqs_disabled()); - debug_show_held_locks(current); - if (irqs_disabled()) - print_irqtrace_events(current); - dump_stack(); - } + if ((!in_atomic() && !irqs_disabled()) || + system_state != SYSTEM_RUNNING || oops_in_progress) + return; + if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) + return; + prev_jiffy = jiffies; + + printk(KERN_ERR + "BUG: sleeping function called from invalid context at %s:%d\n", + file, line); + printk(KERN_ERR + "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n", + in_atomic(), irqs_disabled(), + current->pid, current->comm); + + debug_show_held_locks(current); + if (irqs_disabled()) + print_irqtrace_events(current); + dump_stack(); #endif } EXPORT_SYMBOL(__might_sleep); @@ -8753,73 +8837,95 @@ static DEFINE_MUTEX(rt_constraints_mutex); static unsigned long to_ratio(u64 period, u64 runtime) { if (runtime == RUNTIME_INF) - return 1ULL << 16; + return 1ULL << 20; - return div64_u64(runtime << 16, period); + return div64_u64(runtime << 20, period); } -#ifdef CONFIG_CGROUP_SCHED -static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime) +/* Must be called with tasklist_lock held */ +static inline int tg_has_rt_tasks(struct task_group *tg) { - struct task_group *tgi, *parent = tg->parent; - unsigned long total = 0; + struct task_struct *g, *p; - if (!parent) { - if (global_rt_period() < period) - return 0; + do_each_thread(g, p) { + if (rt_task(p) && rt_rq_of_se(&p->rt)->tg == tg) + return 1; + } while_each_thread(g, p); - return to_ratio(period, runtime) < - to_ratio(global_rt_period(), global_rt_runtime()); - } + return 0; +} - if (ktime_to_ns(parent->rt_bandwidth.rt_period) < period) - return 0; +struct rt_schedulable_data { + struct task_group *tg; + u64 rt_period; + u64 rt_runtime; +}; - rcu_read_lock(); - list_for_each_entry_rcu(tgi, &parent->children, siblings) { - if (tgi == tg) - continue; +static int tg_schedulable(struct task_group *tg, void *data) +{ + struct rt_schedulable_data *d = data; + struct task_group *child; + unsigned long total, sum = 0; + u64 period, runtime; - total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period), - tgi->rt_bandwidth.rt_runtime); + period = ktime_to_ns(tg->rt_bandwidth.rt_period); + runtime = tg->rt_bandwidth.rt_runtime; + + if (tg == d->tg) { + period = d->rt_period; + runtime = d->rt_runtime; } - rcu_read_unlock(); - return total + to_ratio(period, runtime) <= - to_ratio(ktime_to_ns(parent->rt_bandwidth.rt_period), - parent->rt_bandwidth.rt_runtime); -} -#elif defined CONFIG_USER_SCHED -static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime) -{ - struct task_group *tgi; - unsigned long total = 0; - unsigned long global_ratio = - to_ratio(global_rt_period(), global_rt_runtime()); + /* + * Cannot have more runtime than the period. + */ + if (runtime > period && runtime != RUNTIME_INF) + return -EINVAL; - rcu_read_lock(); - list_for_each_entry_rcu(tgi, &task_groups, list) { - if (tgi == tg) - continue; + /* + * Ensure we don't starve existing RT tasks. + */ + if (rt_bandwidth_enabled() && !runtime && tg_has_rt_tasks(tg)) + return -EBUSY; + + total = to_ratio(period, runtime); + + /* + * Nobody can have more than the global setting allows. + */ + if (total > to_ratio(global_rt_period(), global_rt_runtime())) + return -EINVAL; + + /* + * The sum of our children's runtime should not exceed our own. + */ + list_for_each_entry_rcu(child, &tg->children, siblings) { + period = ktime_to_ns(child->rt_bandwidth.rt_period); + runtime = child->rt_bandwidth.rt_runtime; + + if (child == d->tg) { + period = d->rt_period; + runtime = d->rt_runtime; + } - total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period), - tgi->rt_bandwidth.rt_runtime); + sum += to_ratio(period, runtime); } - rcu_read_unlock(); - return total + to_ratio(period, runtime) < global_ratio; + if (sum > total) + return -EINVAL; + + return 0; } -#endif -/* Must be called with tasklist_lock held */ -static inline int tg_has_rt_tasks(struct task_group *tg) +static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime) { - struct task_struct *g, *p; - do_each_thread(g, p) { - if (rt_task(p) && rt_rq_of_se(&p->rt)->tg == tg) - return 1; - } while_each_thread(g, p); - return 0; + struct rt_schedulable_data data = { + .tg = tg, + .rt_period = period, + .rt_runtime = runtime, + }; + + return walk_tg_tree(tg_schedulable, tg_nop, &data); } static int tg_set_bandwidth(struct task_group *tg, @@ -8829,14 +8935,9 @@ static int tg_set_bandwidth(struct task_group *tg, mutex_lock(&rt_constraints_mutex); read_lock(&tasklist_lock); - if (rt_runtime == 0 && tg_has_rt_tasks(tg)) { - err = -EBUSY; + err = __rt_schedulable(tg, rt_period, rt_runtime); + if (err) goto unlock; - } - if (!__rt_schedulable(tg, rt_period, rt_runtime)) { - err = -EINVAL; - goto unlock; - } spin_lock_irq(&tg->rt_bandwidth.rt_runtime_lock); tg->rt_bandwidth.rt_period = ns_to_ktime(rt_period); @@ -8905,19 +9006,25 @@ long sched_group_rt_period(struct task_group *tg) static int sched_rt_global_constraints(void) { - struct task_group *tg = &root_task_group; - u64 rt_runtime, rt_period; + u64 runtime, period; int ret = 0; if (sysctl_sched_rt_period <= 0) return -EINVAL; - rt_period = ktime_to_ns(tg->rt_bandwidth.rt_period); - rt_runtime = tg->rt_bandwidth.rt_runtime; + runtime = global_rt_runtime(); + period = global_rt_period(); + + /* + * Sanity check on the sysctl variables. + */ + if (runtime > period && runtime != RUNTIME_INF) + return -EINVAL; mutex_lock(&rt_constraints_mutex); - if (!__rt_schedulable(tg, rt_period, rt_runtime)) - ret = -EINVAL; + read_lock(&tasklist_lock); + ret = __rt_schedulable(NULL, 0, 0); + read_unlock(&tasklist_lock); mutex_unlock(&rt_constraints_mutex); return ret; @@ -8991,7 +9098,6 @@ cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp) if (!cgrp->parent) { /* This is early initialization for the top cgroup */ - init_task_group.css.cgroup = cgrp; return &init_task_group.css; } @@ -9000,9 +9106,6 @@ cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp) if (IS_ERR(tg)) return ERR_PTR(-ENOMEM); - /* Bind the cgroup to task_group object we just created */ - tg->css.cgroup = cgrp; - return &tg->css; } diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index fb8994c6d4bb..18fd17172eb6 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -409,64 +409,6 @@ static u64 sched_vslice_add(struct cfs_rq *cfs_rq, struct sched_entity *se) } /* - * The goal of calc_delta_asym() is to be asymmetrically around NICE_0_LOAD, in - * that it favours >=0 over <0. - * - * -20 | - * | - * 0 --------+------- - * .' - * 19 .' - * - */ -static unsigned long -calc_delta_asym(unsigned long delta, struct sched_entity *se) -{ - struct load_weight lw = { - .weight = NICE_0_LOAD, - .inv_weight = 1UL << (WMULT_SHIFT-NICE_0_SHIFT) - }; - - for_each_sched_entity(se) { - struct load_weight *se_lw = &se->load; - unsigned long rw = cfs_rq_of(se)->load.weight; - -#ifdef CONFIG_FAIR_SCHED_GROUP - struct cfs_rq *cfs_rq = se->my_q; - struct task_group *tg = NULL - - if (cfs_rq) - tg = cfs_rq->tg; - - if (tg && tg->shares < NICE_0_LOAD) { - /* - * scale shares to what it would have been had - * tg->weight been NICE_0_LOAD: - * - * weight = 1024 * shares / tg->weight - */ - lw.weight *= se->load.weight; - lw.weight /= tg->shares; - - lw.inv_weight = 0; - - se_lw = &lw; - rw += lw.weight - se->load.weight; - } else -#endif - - if (se->load.weight < NICE_0_LOAD) { - se_lw = &lw; - rw += NICE_0_LOAD - se->load.weight; - } - - delta = calc_delta_mine(delta, rw, se_lw); - } - - return delta; -} - -/* * Update the current task's runtime statistics. Skip current tasks that * are not in our scheduling class. */ @@ -586,11 +528,12 @@ account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se) update_load_add(&cfs_rq->load, se->load.weight); if (!parent_entity(se)) inc_cpu_load(rq_of(cfs_rq), se->load.weight); - if (entity_is_task(se)) + if (entity_is_task(se)) { add_cfs_task_weight(cfs_rq, se->load.weight); + list_add(&se->group_node, &cfs_rq->tasks); + } cfs_rq->nr_running++; se->on_rq = 1; - list_add(&se->group_node, &cfs_rq->tasks); } static void @@ -599,11 +542,12 @@ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se) update_load_sub(&cfs_rq->load, se->load.weight); if (!parent_entity(se)) dec_cpu_load(rq_of(cfs_rq), se->load.weight); - if (entity_is_task(se)) + if (entity_is_task(se)) { add_cfs_task_weight(cfs_rq, -se->load.weight); + list_del_init(&se->group_node); + } cfs_rq->nr_running--; se->on_rq = 0; - list_del_init(&se->group_node); } static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) @@ -1085,7 +1029,6 @@ static long effective_load(struct task_group *tg, int cpu, long wl, long wg) { struct sched_entity *se = tg->se[cpu]; - long more_w; if (!tg->parent) return wl; @@ -1097,18 +1040,17 @@ static long effective_load(struct task_group *tg, int cpu, if (!wl && sched_feat(ASYM_EFF_LOAD)) return wl; - /* - * Instead of using this increment, also add the difference - * between when the shares were last updated and now. - */ - more_w = se->my_q->load.weight - se->my_q->rq_weight; - wl += more_w; - wg += more_w; - for_each_sched_entity(se) { -#define D(n) (likely(n) ? (n) : 1) - long S, rw, s, a, b; + long more_w; + + /* + * Instead of using this increment, also add the difference + * between when the shares were last updated and now. + */ + more_w = se->my_q->load.weight - se->my_q->rq_weight; + wl += more_w; + wg += more_w; S = se->my_q->tg->shares; s = se->my_q->shares; @@ -1117,7 +1059,11 @@ static long effective_load(struct task_group *tg, int cpu, a = S*(rw + wl); b = S*rw + s*wg; - wl = s*(a-b)/D(b); + wl = s*(a-b); + + if (likely(b)) + wl /= b; + /* * Assume the group is already running and will * thus already be accounted for in the weight. @@ -1126,7 +1072,6 @@ static long effective_load(struct task_group *tg, int cpu, * alter the group weight. */ wg = 0; -#undef D } return wl; @@ -1143,7 +1088,7 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu, #endif static int -wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq, +wake_affine(struct sched_domain *this_sd, struct rq *this_rq, struct task_struct *p, int prev_cpu, int this_cpu, int sync, int idx, unsigned long load, unsigned long this_load, unsigned int imbalance) @@ -1158,6 +1103,11 @@ wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq, if (!(this_sd->flags & SD_WAKE_AFFINE) || !sched_feat(AFFINE_WAKEUPS)) return 0; + if (!sync && sched_feat(SYNC_WAKEUPS) && + curr->se.avg_overlap < sysctl_sched_migration_cost && + p->se.avg_overlap < sysctl_sched_migration_cost) + sync = 1; + /* * If sync wakeup then subtract the (maximum possible) * effect of the currently running task from the load @@ -1182,17 +1132,14 @@ wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq, * a reasonable amount of time then attract this newly * woken task: */ - if (sync && balanced) { - if (curr->se.avg_overlap < sysctl_sched_migration_cost && - p->se.avg_overlap < sysctl_sched_migration_cost) - return 1; - } + if (sync && balanced) + return 1; schedstat_inc(p, se.nr_wakeups_affine_attempts); tl_per_task = cpu_avg_load_per_task(this_cpu); - if ((tl <= load && tl + target_load(prev_cpu, idx) <= tl_per_task) || - balanced) { + if (balanced || (tl <= load && tl + target_load(prev_cpu, idx) <= + tl_per_task)) { /* * This domain has SD_WAKE_AFFINE and * p is cache cold in this domain, and @@ -1211,16 +1158,17 @@ static int select_task_rq_fair(struct task_struct *p, int sync) struct sched_domain *sd, *this_sd = NULL; int prev_cpu, this_cpu, new_cpu; unsigned long load, this_load; - struct rq *rq, *this_rq; + struct rq *this_rq; unsigned int imbalance; int idx; prev_cpu = task_cpu(p); - rq = task_rq(p); this_cpu = smp_processor_id(); this_rq = cpu_rq(this_cpu); new_cpu = prev_cpu; + if (prev_cpu == this_cpu) + goto out; /* * 'this_sd' is the first domain that both * this_cpu and prev_cpu are present in: @@ -1248,13 +1196,10 @@ static int select_task_rq_fair(struct task_struct *p, int sync) load = source_load(prev_cpu, idx); this_load = target_load(this_cpu, idx); - if (wake_affine(rq, this_sd, this_rq, p, prev_cpu, this_cpu, sync, idx, + if (wake_affine(this_sd, this_rq, p, prev_cpu, this_cpu, sync, idx, load, this_load, imbalance)) return this_cpu; - if (prev_cpu == this_cpu) - goto out; - /* * Start passive balancing when half the imbalance_pct * limit is reached. @@ -1281,62 +1226,20 @@ static unsigned long wakeup_gran(struct sched_entity *se) * + nice tasks. */ if (sched_feat(ASYM_GRAN)) - gran = calc_delta_asym(sysctl_sched_wakeup_granularity, se); - else - gran = calc_delta_fair(sysctl_sched_wakeup_granularity, se); + gran = calc_delta_mine(gran, NICE_0_LOAD, &se->load); return gran; } /* - * Should 'se' preempt 'curr'. - * - * |s1 - * |s2 - * |s3 - * g - * |<--->|c - * - * w(c, s1) = -1 - * w(c, s2) = 0 - * w(c, s3) = 1 - * - */ -static int -wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se) -{ - s64 gran, vdiff = curr->vruntime - se->vruntime; - - if (vdiff < 0) - return -1; - - gran = wakeup_gran(curr); - if (vdiff > gran) - return 1; - - return 0; -} - -/* return depth at which a sched entity is present in the hierarchy */ -static inline int depth_se(struct sched_entity *se) -{ - int depth = 0; - - for_each_sched_entity(se) - depth++; - - return depth; -} - -/* * Preempt the current task with a newly woken task if needed: */ -static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) +static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync) { struct task_struct *curr = rq->curr; struct cfs_rq *cfs_rq = task_cfs_rq(curr); struct sched_entity *se = &curr->se, *pse = &p->se; - int se_depth, pse_depth; + s64 delta_exec; if (unlikely(rt_prio(p->prio))) { update_rq_clock(rq); @@ -1351,6 +1254,13 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) cfs_rq_of(pse)->next = pse; /* + * We can come here with TIF_NEED_RESCHED already set from new task + * wake up path. + */ + if (test_tsk_need_resched(curr)) + return; + + /* * Batch tasks do not preempt (their preemption is driven by * the tick): */ @@ -1360,33 +1270,15 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) if (!sched_feat(WAKEUP_PREEMPT)) return; - /* - * preemption test can be made between sibling entities who are in the - * same cfs_rq i.e who have a common parent. Walk up the hierarchy of - * both tasks until we find their ancestors who are siblings of common - * parent. - */ - - /* First walk up until both entities are at same depth */ - se_depth = depth_se(se); - pse_depth = depth_se(pse); - - while (se_depth > pse_depth) { - se_depth--; - se = parent_entity(se); - } - - while (pse_depth > se_depth) { - pse_depth--; - pse = parent_entity(pse); - } - - while (!is_same_group(se, pse)) { - se = parent_entity(se); - pse = parent_entity(pse); + if (sched_feat(WAKEUP_OVERLAP) && (sync || + (se->avg_overlap < sysctl_sched_migration_cost && + pse->avg_overlap < sysctl_sched_migration_cost))) { + resched_task(curr); + return; } - if (wakeup_preempt_entity(se, pse) == 1) + delta_exec = se->sum_exec_runtime - se->prev_sum_exec_runtime; + if (delta_exec > wakeup_gran(pse)) resched_task(curr); } @@ -1445,19 +1337,9 @@ __load_balance_iterator(struct cfs_rq *cfs_rq, struct list_head *next) if (next == &cfs_rq->tasks) return NULL; - /* Skip over entities that are not tasks */ - do { - se = list_entry(next, struct sched_entity, group_node); - next = next->next; - } while (next != &cfs_rq->tasks && !entity_is_task(se)); - - if (next == &cfs_rq->tasks) - return NULL; - - cfs_rq->balance_iterator = next; - - if (entity_is_task(se)) - p = task_of(se); + se = list_entry(next, struct sched_entity, group_node); + p = task_of(se); + cfs_rq->balance_iterator = next->next; return p; } @@ -1507,7 +1389,7 @@ load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest, rcu_read_lock(); update_h_load(busiest_cpu); - list_for_each_entry(tg, &task_groups, list) { + list_for_each_entry_rcu(tg, &task_groups, list) { struct cfs_rq *busiest_cfs_rq = tg->cfs_rq[busiest_cpu]; unsigned long busiest_h_load = busiest_cfs_rq->h_load; unsigned long busiest_weight = busiest_cfs_rq->load.weight; @@ -1620,10 +1502,10 @@ static void task_new_fair(struct rq *rq, struct task_struct *p) * 'current' within the tree based on its new key value. */ swap(curr->vruntime, se->vruntime); + resched_task(rq->curr); } enqueue_task_fair(rq, p, 0); - resched_task(rq->curr); } /* @@ -1642,7 +1524,7 @@ static void prio_changed_fair(struct rq *rq, struct task_struct *p, if (p->prio > oldprio) resched_task(rq->curr); } else - check_preempt_curr(rq, p); + check_preempt_curr(rq, p, 0); } /* @@ -1659,7 +1541,7 @@ static void switched_to_fair(struct rq *rq, struct task_struct *p, if (running) resched_task(rq->curr); else - check_preempt_curr(rq, p); + check_preempt_curr(rq, p, 0); } /* Account for a task changing its policy or group. diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 9353ca78154e..7c9e8f4a049f 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -11,3 +11,4 @@ SCHED_FEAT(ASYM_GRAN, 1) SCHED_FEAT(LB_BIAS, 1) SCHED_FEAT(LB_WAKEUP_UPDATE, 1) SCHED_FEAT(ASYM_EFF_LOAD, 1) +SCHED_FEAT(WAKEUP_OVERLAP, 0) diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c index 3a4f92dbbe66..dec4ccabe2f5 100644 --- a/kernel/sched_idletask.c +++ b/kernel/sched_idletask.c @@ -14,7 +14,7 @@ static int select_task_rq_idle(struct task_struct *p, int sync) /* * Idle tasks are unconditionally rescheduled: */ -static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p) +static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int sync) { resched_task(rq->idle); } @@ -76,7 +76,7 @@ static void switched_to_idle(struct rq *rq, struct task_struct *p, if (running) resched_task(rq->curr); else - check_preempt_curr(rq, p); + check_preempt_curr(rq, p, 0); } static void prio_changed_idle(struct rq *rq, struct task_struct *p, @@ -93,7 +93,7 @@ static void prio_changed_idle(struct rq *rq, struct task_struct *p, if (p->prio > oldprio) resched_task(rq->curr); } else - check_preempt_curr(rq, p); + check_preempt_curr(rq, p, 0); } /* diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 1113157b2058..cdf5740ab03e 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -102,12 +102,12 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se); static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) { + struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; struct sched_rt_entity *rt_se = rt_rq->rt_se; - if (rt_se && !on_rt_rq(rt_se) && rt_rq->rt_nr_running) { - struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; - - enqueue_rt_entity(rt_se); + if (rt_rq->rt_nr_running) { + if (rt_se && !on_rt_rq(rt_se)) + enqueue_rt_entity(rt_se); if (rt_rq->highest_prio < curr->prio) resched_task(curr); } @@ -231,6 +231,9 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq) #endif /* CONFIG_RT_GROUP_SCHED */ #ifdef CONFIG_SMP +/* + * We ran out of runtime, see if we can borrow some from our neighbours. + */ static int do_balance_runtime(struct rt_rq *rt_rq) { struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); @@ -250,9 +253,18 @@ static int do_balance_runtime(struct rt_rq *rt_rq) continue; spin_lock(&iter->rt_runtime_lock); + /* + * Either all rqs have inf runtime and there's nothing to steal + * or __disable_runtime() below sets a specific rq to inf to + * indicate its been disabled and disalow stealing. + */ if (iter->rt_runtime == RUNTIME_INF) goto next; + /* + * From runqueues with spare time, take 1/n part of their + * spare time, but no more than our period. + */ diff = iter->rt_runtime - iter->rt_time; if (diff > 0) { diff = div_u64((u64)diff, weight); @@ -274,6 +286,9 @@ next: return more; } +/* + * Ensure this RQ takes back all the runtime it lend to its neighbours. + */ static void __disable_runtime(struct rq *rq) { struct root_domain *rd = rq->rd; @@ -289,17 +304,33 @@ static void __disable_runtime(struct rq *rq) spin_lock(&rt_b->rt_runtime_lock); spin_lock(&rt_rq->rt_runtime_lock); + /* + * Either we're all inf and nobody needs to borrow, or we're + * already disabled and thus have nothing to do, or we have + * exactly the right amount of runtime to take out. + */ if (rt_rq->rt_runtime == RUNTIME_INF || rt_rq->rt_runtime == rt_b->rt_runtime) goto balanced; spin_unlock(&rt_rq->rt_runtime_lock); + /* + * Calculate the difference between what we started out with + * and what we current have, that's the amount of runtime + * we lend and now have to reclaim. + */ want = rt_b->rt_runtime - rt_rq->rt_runtime; + /* + * Greedy reclaim, take back as much as we can. + */ for_each_cpu_mask(i, rd->span) { struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i); s64 diff; + /* + * Can't reclaim from ourselves or disabled runqueues. + */ if (iter == rt_rq || iter->rt_runtime == RUNTIME_INF) continue; @@ -319,8 +350,16 @@ static void __disable_runtime(struct rq *rq) } spin_lock(&rt_rq->rt_runtime_lock); + /* + * We cannot be left wanting - that would mean some runtime + * leaked out of the system. + */ BUG_ON(want); balanced: + /* + * Disable all the borrow logic by pretending we have inf + * runtime - in which case borrowing doesn't make sense. + */ rt_rq->rt_runtime = RUNTIME_INF; spin_unlock(&rt_rq->rt_runtime_lock); spin_unlock(&rt_b->rt_runtime_lock); @@ -343,6 +382,9 @@ static void __enable_runtime(struct rq *rq) if (unlikely(!scheduler_running)) return; + /* + * Reset each runqueue's bandwidth settings + */ for_each_leaf_rt_rq(rt_rq, rq) { struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); @@ -389,7 +431,7 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) int i, idle = 1; cpumask_t span; - if (rt_b->rt_runtime == RUNTIME_INF) + if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF) return 1; span = sched_rt_period_mask(); @@ -487,6 +529,9 @@ static void update_curr_rt(struct rq *rq) curr->se.exec_start = rq->clock; cpuacct_charge(curr, delta_exec); + if (!rt_bandwidth_enabled()) + return; + for_each_sched_rt_entity(rt_se) { rt_rq = rt_rq_of_se(rt_se); @@ -784,7 +829,7 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p) /* * Preempt the current task with a newly woken task if needed: */ -static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p) +static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int sync) { if (p->prio < rq->curr->prio) { resched_task(rq->curr); diff --git a/kernel/user.c b/kernel/user.c index 865ecf57a096..39d6159fae43 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -169,7 +169,7 @@ static ssize_t cpu_rt_runtime_show(struct kobject *kobj, { struct user_struct *up = container_of(kobj, struct user_struct, kobj); - return sprintf(buf, "%lu\n", sched_group_rt_runtime(up->tg)); + return sprintf(buf, "%ld\n", sched_group_rt_runtime(up->tg)); } static ssize_t cpu_rt_runtime_store(struct kobject *kobj, @@ -180,7 +180,7 @@ static ssize_t cpu_rt_runtime_store(struct kobject *kobj, unsigned long rt_runtime; int rc; - sscanf(buf, "%lu", &rt_runtime); + sscanf(buf, "%ld", &rt_runtime); rc = sched_group_set_rt_runtime(up->tg, rt_runtime); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0b504814e378..ce697e0b319e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -597,6 +597,19 @@ config RCU_TORTURE_TEST_RUNNABLE Say N here if you want the RCU torture tests to start only after being manually enabled via /proc. +config RCU_CPU_STALL_DETECTOR + bool "Check for stalled CPUs delaying RCU grace periods" + depends on CLASSIC_RCU + default n + help + This option causes RCU to printk information on which + CPUs are delaying the current grace period, but only when + the grace period extends for excessive time periods. + + Say Y if you want RCU to perform such checks. + + Say N if you are unsure. + config KPROBES_SANITY_TEST bool "Kprobes sanity tests" depends on DEBUG_KERNEL @@ -624,6 +637,28 @@ config BACKTRACE_SELF_TEST Say N if you are unsure. +config DEBUG_BLOCK_EXT_DEVT + bool "Force extended block device numbers and spread them" + depends on DEBUG_KERNEL + depends on BLOCK + default n + help + Conventionally, block device numbers are allocated from + predetermined contiguous area. However, extended block area + may introduce non-contiguous block device numbers. This + option forces most block device numbers to be allocated from + the extended space and spreads them to discover kernel or + userland code paths which assume predetermined contiguous + device number allocation. + + Note that turning on this debug option shuffles all the + device numbers for all IDE and SCSI devices including libata + ones, so root partition specified using device number + directly (via rdev or root=MAJ:MIN) won't work anymore. + Textual device names (root=/dev/sdXn) will continue to work. + + Say N if you are unsure. + config LKDTM tristate "Linux Kernel Dump Test Tool Module" depends on DEBUG_KERNEL @@ -661,10 +696,21 @@ config FAIL_PAGE_ALLOC config FAIL_MAKE_REQUEST bool "Fault-injection capability for disk IO" - depends on FAULT_INJECTION + depends on FAULT_INJECTION && BLOCK help Provide fault-injection capability for disk IO. +config FAIL_IO_TIMEOUT + bool "Faul-injection capability for faking disk interrupts" + depends on FAULT_INJECTION && BLOCK + help + Provide fault-injection capability on end IO handling. This + will make the block layer "forget" an interrupt as configured, + thus exercising the error handling. + + Only works with drivers that use the generic timeout handling, + for others it wont do anything. + config FAULT_INJECTION_DEBUG_FS bool "Debugfs entries for fault-injection capabilities" depends on FAULT_INJECTION && SYSFS && DEBUG_FS diff --git a/lib/Makefile b/lib/Makefile index 3b1f94bbe9de..44001af76a7d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -19,7 +19,8 @@ lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o klist.o obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ - bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o + bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ + string_helpers.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/klist.c b/lib/klist.c index cca37f96faa2..bbdd3015c2c7 100644 --- a/lib/klist.c +++ b/lib/klist.c @@ -37,6 +37,37 @@ #include <linux/klist.h> #include <linux/module.h> +/* + * Use the lowest bit of n_klist to mark deleted nodes and exclude + * dead ones from iteration. + */ +#define KNODE_DEAD 1LU +#define KNODE_KLIST_MASK ~KNODE_DEAD + +static struct klist *knode_klist(struct klist_node *knode) +{ + return (struct klist *) + ((unsigned long)knode->n_klist & KNODE_KLIST_MASK); +} + +static bool knode_dead(struct klist_node *knode) +{ + return (unsigned long)knode->n_klist & KNODE_DEAD; +} + +static void knode_set_klist(struct klist_node *knode, struct klist *klist) +{ + knode->n_klist = klist; + /* no knode deserves to start its life dead */ + WARN_ON(knode_dead(knode)); +} + +static void knode_kill(struct klist_node *knode) +{ + /* and no knode should die twice ever either, see we're very humane */ + WARN_ON(knode_dead(knode)); + *(unsigned long *)&knode->n_klist |= KNODE_DEAD; +} /** * klist_init - Initialize a klist structure. @@ -79,7 +110,7 @@ static void klist_node_init(struct klist *k, struct klist_node *n) INIT_LIST_HEAD(&n->n_node); init_completion(&n->n_removed); kref_init(&n->n_ref); - n->n_klist = k; + knode_set_klist(n, k); if (k->get) k->get(n); } @@ -115,7 +146,7 @@ EXPORT_SYMBOL_GPL(klist_add_tail); */ void klist_add_after(struct klist_node *n, struct klist_node *pos) { - struct klist *k = pos->n_klist; + struct klist *k = knode_klist(pos); klist_node_init(k, n); spin_lock(&k->k_lock); @@ -131,7 +162,7 @@ EXPORT_SYMBOL_GPL(klist_add_after); */ void klist_add_before(struct klist_node *n, struct klist_node *pos) { - struct klist *k = pos->n_klist; + struct klist *k = knode_klist(pos); klist_node_init(k, n); spin_lock(&k->k_lock); @@ -144,9 +175,10 @@ static void klist_release(struct kref *kref) { struct klist_node *n = container_of(kref, struct klist_node, n_ref); + WARN_ON(!knode_dead(n)); list_del(&n->n_node); complete(&n->n_removed); - n->n_klist = NULL; + knode_set_klist(n, NULL); } static int klist_dec_and_del(struct klist_node *n) @@ -154,22 +186,29 @@ static int klist_dec_and_del(struct klist_node *n) return kref_put(&n->n_ref, klist_release); } -/** - * klist_del - Decrement the reference count of node and try to remove. - * @n: node we're deleting. - */ -void klist_del(struct klist_node *n) +static void klist_put(struct klist_node *n, bool kill) { - struct klist *k = n->n_klist; + struct klist *k = knode_klist(n); void (*put)(struct klist_node *) = k->put; spin_lock(&k->k_lock); + if (kill) + knode_kill(n); if (!klist_dec_and_del(n)) put = NULL; spin_unlock(&k->k_lock); if (put) put(n); } + +/** + * klist_del - Decrement the reference count of node and try to remove. + * @n: node we're deleting. + */ +void klist_del(struct klist_node *n) +{ + klist_put(n, true); +} EXPORT_SYMBOL_GPL(klist_del); /** @@ -206,7 +245,6 @@ void klist_iter_init_node(struct klist *k, struct klist_iter *i, struct klist_node *n) { i->i_klist = k; - i->i_head = &k->k_list; i->i_cur = n; if (n) kref_get(&n->n_ref); @@ -237,7 +275,7 @@ EXPORT_SYMBOL_GPL(klist_iter_init); void klist_iter_exit(struct klist_iter *i) { if (i->i_cur) { - klist_del(i->i_cur); + klist_put(i->i_cur, false); i->i_cur = NULL; } } @@ -258,27 +296,33 @@ static struct klist_node *to_klist_node(struct list_head *n) */ struct klist_node *klist_next(struct klist_iter *i) { - struct list_head *next; - struct klist_node *lnode = i->i_cur; - struct klist_node *knode = NULL; void (*put)(struct klist_node *) = i->i_klist->put; + struct klist_node *last = i->i_cur; + struct klist_node *next; spin_lock(&i->i_klist->k_lock); - if (lnode) { - next = lnode->n_node.next; - if (!klist_dec_and_del(lnode)) + + if (last) { + next = to_klist_node(last->n_node.next); + if (!klist_dec_and_del(last)) put = NULL; } else - next = i->i_head->next; + next = to_klist_node(i->i_klist->k_list.next); - if (next != i->i_head) { - knode = to_klist_node(next); - kref_get(&knode->n_ref); + i->i_cur = NULL; + while (next != to_klist_node(&i->i_klist->k_list)) { + if (likely(!knode_dead(next))) { + kref_get(&next->n_ref); + i->i_cur = next; + break; + } + next = to_klist_node(next->n_node.next); } - i->i_cur = knode; + spin_unlock(&i->i_klist->k_lock); - if (put && lnode) - put(lnode); - return knode; + + if (put && last) + put(last); + return i->i_cur; } EXPORT_SYMBOL_GPL(klist_next); diff --git a/lib/string_helpers.c b/lib/string_helpers.c new file mode 100644 index 000000000000..8347925030ff --- /dev/null +++ b/lib/string_helpers.c @@ -0,0 +1,64 @@ +/* + * Helpers for formatting and printing strings + * + * Copyright 31 August 2008 James Bottomley + */ +#include <linux/kernel.h> +#include <linux/math64.h> +#include <linux/module.h> +#include <linux/string_helpers.h> + +/** + * string_get_size - get the size in the specified units + * @size: The size to be converted + * @units: units to use (powers of 1000 or 1024) + * @buf: buffer to format to + * @len: length of buffer + * + * This function returns a string formatted to 3 significant figures + * giving the size in the required units. Returns 0 on success or + * error on failure. @buf is always zero terminated. + * + */ +int string_get_size(u64 size, const enum string_size_units units, + char *buf, int len) +{ + const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB", + "EB", "ZB", "YB", NULL}; + const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", + "EiB", "ZiB", "YiB", NULL }; + const char **units_str[] = { + [STRING_UNITS_10] = units_10, + [STRING_UNITS_2] = units_2, + }; + const int divisor[] = { + [STRING_UNITS_10] = 1000, + [STRING_UNITS_2] = 1024, + }; + int i, j; + u64 remainder = 0, sf_cap; + char tmp[8]; + + tmp[0] = '\0'; + + for (i = 0; size > divisor[units] && units_str[units][i]; i++) + remainder = do_div(size, divisor[units]); + + sf_cap = size; + for (j = 0; sf_cap*10 < 1000; j++) + sf_cap *= 10; + + if (j) { + remainder *= 1000; + do_div(remainder, divisor[units]); + snprintf(tmp, sizeof(tmp), ".%03lld", + (unsigned long long)remainder); + tmp[j+1] = '\0'; + } + + snprintf(buf, len, "%lld%s%s", (unsigned long long)size, + tmp, units_str[units][i]); + + return 0; +} +EXPORT_SYMBOL(string_get_size); diff --git a/mm/bounce.c b/mm/bounce.c index b6d2d0f1019b..06722c403058 100644 --- a/mm/bounce.c +++ b/mm/bounce.c @@ -267,7 +267,7 @@ void blk_queue_bounce(struct request_queue *q, struct bio **bio_orig) /* * Data-less bio, nothing to bounce */ - if (bio_empty_barrier(*bio_orig)) + if (!bio_has_data(*bio_orig)) return; /* diff --git a/scripts/Makefile b/scripts/Makefile index 1c73c5aea66b..aafdf064feef 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -20,6 +20,7 @@ hostprogs-y += unifdef subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-y += mod +subdir-$(CONFIG_SECURITY_SELINUX) += selinux # Let clean descend into subdirs -subdir- += basic kconfig package +subdir- += basic kconfig package selinux diff --git a/scripts/selinux/Makefile b/scripts/selinux/Makefile new file mode 100644 index 000000000000..ca4b1ec01822 --- /dev/null +++ b/scripts/selinux/Makefile @@ -0,0 +1,2 @@ +subdir-y := mdp +subdir- += mdp diff --git a/scripts/selinux/README b/scripts/selinux/README new file mode 100644 index 000000000000..a936315ba2c8 --- /dev/null +++ b/scripts/selinux/README @@ -0,0 +1,2 @@ +Please see Documentation/SELinux.txt for information on +installing a dummy SELinux policy. diff --git a/scripts/selinux/install_policy.sh b/scripts/selinux/install_policy.sh new file mode 100644 index 000000000000..7b9ccf61f8f9 --- /dev/null +++ b/scripts/selinux/install_policy.sh @@ -0,0 +1,69 @@ +#!/bin/sh +if [ `id -u` -ne 0 ]; then + echo "$0: must be root to install the selinux policy" + exit 1 +fi +SF=`which setfiles` +if [ $? -eq 1 ]; then + if [ -f /sbin/setfiles ]; then + SF="/usr/setfiles" + else + echo "no selinux tools installed: setfiles" + exit 1 + fi +fi + +cd mdp + +CP=`which checkpolicy` +VERS=`$CP -V | awk '{print $1}'` + +./mdp policy.conf file_contexts +$CP -o policy.$VERS policy.conf + +mkdir -p /etc/selinux/dummy/policy +mkdir -p /etc/selinux/dummy/contexts/files + +cp file_contexts /etc/selinux/dummy/contexts/files +cp dbus_contexts /etc/selinux/dummy/contexts +cp policy.$VERS /etc/selinux/dummy/policy +FC_FILE=/etc/selinux/dummy/contexts/files/file_contexts + +if [ ! -d /etc/selinux ]; then + mkdir -p /etc/selinux +fi +if [ ! -f /etc/selinux/config ]; then + cat > /etc/selinux/config << EOF +SELINUX=enforcing +SELINUXTYPE=dummy +EOF +else + TYPE=`cat /etc/selinux/config | grep "^SELINUXTYPE" | tail -1 | awk -F= '{ print $2 '}` + if [ "eq$TYPE" != "eqdummy" ]; then + selinuxenabled + if [ $? -eq 0 ]; then + echo "SELinux already enabled with a non-dummy policy." + echo "Exiting. Please install policy by hand if that" + echo "is what you REALLY want." + exit 1 + fi + mv /etc/selinux/config /etc/selinux/config.mdpbak + grep -v "^SELINUXTYPE" /etc/selinux/config.mdpbak >> /etc/selinux/config + echo "SELINUXTYPE=dummy" >> /etc/selinux/config + fi +fi + +cd /etc/selinux/dummy/contexts/files +$SF file_contexts / + +mounts=`cat /proc/$$/mounts | egrep "ext2|ext3|xfs|jfs|ext4|ext4dev|gfs2" | awk '{ print $2 '}` +$SF file_contexts $mounts + + +dodev=`cat /proc/$$/mounts | grep "/dev "` +if [ "eq$dodev" != "eq" ]; then + mount --move /dev /mnt + $SF file_contexts /dev + mount --move /mnt /dev +fi + diff --git a/scripts/selinux/mdp/.gitignore b/scripts/selinux/mdp/.gitignore new file mode 100644 index 000000000000..654546d8dffd --- /dev/null +++ b/scripts/selinux/mdp/.gitignore @@ -0,0 +1,2 @@ +# Generated file +mdp diff --git a/scripts/selinux/mdp/Makefile b/scripts/selinux/mdp/Makefile new file mode 100644 index 000000000000..eb365b333441 --- /dev/null +++ b/scripts/selinux/mdp/Makefile @@ -0,0 +1,5 @@ +hostprogs-y := mdp +HOST_EXTRACFLAGS += -Isecurity/selinux/include + +always := $(hostprogs-y) +clean-files := $(hostprogs-y) policy.* file_contexts diff --git a/scripts/selinux/mdp/dbus_contexts b/scripts/selinux/mdp/dbus_contexts new file mode 100644 index 000000000000..116e684f9fc1 --- /dev/null +++ b/scripts/selinux/mdp/dbus_contexts @@ -0,0 +1,6 @@ +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> + <selinux> + </selinux> +</busconfig> diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c new file mode 100644 index 000000000000..ca757d486187 --- /dev/null +++ b/scripts/selinux/mdp/mdp.c @@ -0,0 +1,242 @@ +/* + * + * mdp - make dummy policy + * + * When pointed at a kernel tree, builds a dummy policy for that kernel + * with exactly one type with full rights to itself. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2006 + * + * Authors: Serge E. Hallyn <serue@us.ibm.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "flask.h" + +void usage(char *name) +{ + printf("usage: %s [-m] policy_file context_file\n", name); + exit(1); +} + +void find_common_name(char *cname, char *dest, int len) +{ + char *start, *end; + + start = strchr(cname, '_')+1; + end = strchr(start, '_'); + if (!start || !end || start-cname > len || end-start > len) { + printf("Error with commons defines\n"); + exit(1); + } + strncpy(dest, start, end-start); + dest[end-start] = '\0'; +} + +#define S_(x) x, +static char *classlist[] = { +#include "class_to_string.h" + NULL +}; +#undef S_ + +#include "initial_sid_to_string.h" + +#define TB_(x) char *x[] = { +#define TE_(x) NULL }; +#define S_(x) x, +#include "common_perm_to_string.h" +#undef TB_ +#undef TE_ +#undef S_ + +struct common { + char *cname; + char **perms; +}; +struct common common[] = { +#define TB_(x) { #x, x }, +#define S_(x) +#define TE_(x) +#include "common_perm_to_string.h" +#undef TB_ +#undef TE_ +#undef S_ +}; + +#define S_(x, y, z) {x, #y}, +struct av_inherit { + int class; + char *common; +}; +struct av_inherit av_inherit[] = { +#include "av_inherit.h" +}; +#undef S_ + +#include "av_permissions.h" +#define S_(x, y, z) {x, y, z}, +struct av_perms { + int class; + int perm_i; + char *perm_s; +}; +struct av_perms av_perms[] = { +#include "av_perm_to_string.h" +}; +#undef S_ + +int main(int argc, char *argv[]) +{ + int i, j, mls = 0; + char **arg, *polout, *ctxout; + int classlist_len, initial_sid_to_string_len; + FILE *fout; + + if (argc < 3) + usage(argv[0]); + arg = argv+1; + if (argc==4 && strcmp(argv[1], "-m") == 0) { + mls = 1; + arg++; + } + polout = *arg++; + ctxout = *arg; + + fout = fopen(polout, "w"); + if (!fout) { + printf("Could not open %s for writing\n", polout); + usage(argv[0]); + } + + classlist_len = sizeof(classlist) / sizeof(char *); + /* print out the classes */ + for (i=1; i < classlist_len; i++) { + if(classlist[i]) + fprintf(fout, "class %s\n", classlist[i]); + else + fprintf(fout, "class user%d\n", i); + } + fprintf(fout, "\n"); + + initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *); + /* print out the sids */ + for (i=1; i < initial_sid_to_string_len; i++) + fprintf(fout, "sid %s\n", initial_sid_to_string[i]); + fprintf(fout, "\n"); + + /* print out the commons */ + for (i=0; i< sizeof(common)/sizeof(struct common); i++) { + char cname[101]; + find_common_name(common[i].cname, cname, 100); + cname[100] = '\0'; + fprintf(fout, "common %s\n{\n", cname); + for (j=0; common[i].perms[j]; j++) + fprintf(fout, "\t%s\n", common[i].perms[j]); + fprintf(fout, "}\n\n"); + } + fprintf(fout, "\n"); + + /* print out the class permissions */ + for (i=1; i < classlist_len; i++) { + if (classlist[i]) { + int firstperm = -1, numperms = 0; + + fprintf(fout, "class %s\n", classlist[i]); + /* does it inherit from a common? */ + for (j=0; j < sizeof(av_inherit)/sizeof(struct av_inherit); j++) + if (av_inherit[j].class == i) + fprintf(fout, "inherits %s\n", av_inherit[j].common); + + for (j=0; j < sizeof(av_perms)/sizeof(struct av_perms); j++) { + if (av_perms[j].class == i) { + if (firstperm == -1) + firstperm = j; + numperms++; + } + } + if (!numperms) { + fprintf(fout, "\n"); + continue; + } + + fprintf(fout, "{\n"); + /* print out the av_perms */ + for (j=0; j < numperms; j++) { + fprintf(fout, "\t%s\n", av_perms[firstperm+j].perm_s); + } + fprintf(fout, "}\n\n"); + } + } + fprintf(fout, "\n"); + + /* NOW PRINT OUT MLS STUFF */ + if (mls) { + printf("MLS not yet implemented\n"); + exit(1); + } + + /* types, roles, and allows */ + fprintf(fout, "type base_t;\n"); + fprintf(fout, "role base_r types { base_t };\n"); + for (i=1; i < classlist_len; i++) { + if (classlist[i]) + fprintf(fout, "allow base_t base_t:%s *;\n", classlist[i]); + else + fprintf(fout, "allow base_t base_t:user%d *;\n", i); + } + fprintf(fout, "user user_u roles { base_r };\n"); + fprintf(fout, "\n"); + + /* default sids */ + for (i=1; i < initial_sid_to_string_len; i++) + fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]); + fprintf(fout, "\n"); + + + fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n"); + fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n"); + fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n"); + fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n"); + fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n"); + + fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n"); + fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n"); + + fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n"); + fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n"); + fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n"); + + fprintf(fout, "genfscon proc / user_u:base_r:base_t\n"); + + fclose(fout); + + fout = fopen(ctxout, "w"); + if (!fout) { + printf("Wrote policy, but cannot open %s for writing\n", ctxout); + usage(argv[0]); + } + fprintf(fout, "/ user_u:base_r:base_t\n"); + fprintf(fout, "/.* user_u:base_r:base_t\n"); + fclose(fout); + + return 0; +} diff --git a/security/Kconfig b/security/Kconfig index 559293922a47..d9f47ce7e207 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -51,6 +51,14 @@ config SECURITY If you are unsure how to answer this question, answer N. +config SECURITYFS + bool "Enable the securityfs filesystem" + help + This will build the securityfs filesystem. It is currently used by + the TPM bios character driver. It is not used by SELinux or SMACK. + + If you are unsure how to answer this question, answer N. + config SECURITY_NETWORK bool "Socket and Networking Security Hooks" depends on SECURITY diff --git a/security/Makefile b/security/Makefile index f65426099aa6..c05c127fff9a 100644 --- a/security/Makefile +++ b/security/Makefile @@ -10,7 +10,8 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack obj-y += commoncap.o # Object file lists -obj-$(CONFIG_SECURITY) += security.o capability.o inode.o +obj-$(CONFIG_SECURITY) += security.o capability.o +obj-$(CONFIG_SECURITYFS) += inode.o # Must precede capability.o in order to stack properly. obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o diff --git a/security/commoncap.c b/security/commoncap.c index e4c4b3fc0c04..399bfdb9e2da 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -541,7 +541,7 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, * yet with increased caps. * So we check for increased caps on the target process. */ -static inline int cap_safe_nice(struct task_struct *p) +static int cap_safe_nice(struct task_struct *p) { if (!cap_issubset(p->cap_permitted, current->cap_permitted) && !capable(CAP_SYS_NICE)) diff --git a/security/inode.c b/security/inode.c index acc6cf0d7900..ca4958ebad8d 100644 --- a/security/inode.c +++ b/security/inode.c @@ -190,7 +190,7 @@ static int create_by_name(const char *name, mode_t mode, * @name: a pointer to a string containing the name of the file to create. * @mode: the permission that the file should have * @parent: a pointer to the parent dentry for this file. This should be a - * directory dentry if set. If this paramater is NULL, then the + * directory dentry if set. If this parameter is %NULL, then the * file will be created in the root of the securityfs filesystem. * @data: a pointer to something that the caller will want to get to later * on. The inode.i_private pointer will point to this value on @@ -199,18 +199,18 @@ static int create_by_name(const char *name, mode_t mode, * this file. * * This is the basic "create a file" function for securityfs. It allows for a - * wide range of flexibility in createing a file, or a directory (if you + * wide range of flexibility in creating a file, or a directory (if you * want to create a directory, the securityfs_create_dir() function is - * recommended to be used instead.) + * recommended to be used instead). * - * This function will return a pointer to a dentry if it succeeds. This + * This function returns a pointer to a dentry if it succeeds. This * pointer must be passed to the securityfs_remove() function when the file is * to be removed (no automatic cleanup happens if your module is unloaded, - * you are responsible here.) If an error occurs, NULL will be returned. + * you are responsible here). If an error occurs, %NULL is returned. * - * If securityfs is not enabled in the kernel, the value -ENODEV will be + * If securityfs is not enabled in the kernel, the value %-ENODEV is * returned. It is not wise to check for this value, but rather, check for - * NULL or !NULL instead as to eliminate the need for #ifdef in the calling + * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling * code. */ struct dentry *securityfs_create_file(const char *name, mode_t mode, @@ -252,19 +252,19 @@ EXPORT_SYMBOL_GPL(securityfs_create_file); * @name: a pointer to a string containing the name of the directory to * create. * @parent: a pointer to the parent dentry for this file. This should be a - * directory dentry if set. If this paramater is NULL, then the + * directory dentry if set. If this parameter is %NULL, then the * directory will be created in the root of the securityfs filesystem. * - * This function creates a directory in securityfs with the given name. + * This function creates a directory in securityfs with the given @name. * - * This function will return a pointer to a dentry if it succeeds. This + * This function returns a pointer to a dentry if it succeeds. This * pointer must be passed to the securityfs_remove() function when the file is * to be removed (no automatic cleanup happens if your module is unloaded, - * you are responsible here.) If an error occurs, NULL will be returned. + * you are responsible here). If an error occurs, %NULL will be returned. * - * If securityfs is not enabled in the kernel, the value -ENODEV will be + * If securityfs is not enabled in the kernel, the value %-ENODEV is * returned. It is not wise to check for this value, but rather, check for - * NULL or !NULL instead as to eliminate the need for #ifdef in the calling + * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling * code. */ struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) @@ -278,16 +278,15 @@ EXPORT_SYMBOL_GPL(securityfs_create_dir); /** * securityfs_remove - removes a file or directory from the securityfs filesystem * - * @dentry: a pointer to a the dentry of the file or directory to be - * removed. + * @dentry: a pointer to a the dentry of the file or directory to be removed. * * This function removes a file or directory in securityfs that was previously * created with a call to another securityfs function (like * securityfs_create_file() or variants thereof.) * * This function is required to be called in order for the file to be - * removed, no automatic cleanup of files will happen when a module is - * removed, you are responsible here. + * removed. No automatic cleanup of files will happen when a module is + * removed; you are responsible here. */ void securityfs_remove(struct dentry *dentry) { diff --git a/security/security.c b/security/security.c index 3a4b4f55b33f..255b08559b2b 100644 --- a/security/security.c +++ b/security/security.c @@ -82,8 +82,8 @@ __setup("security=", choose_lsm); * * Return true if: * -The passed LSM is the one chosen by user at boot time, - * -or user didsn't specify a specific LSM and we're the first to ask - * for registeration permissoin, + * -or user didn't specify a specific LSM and we're the first to ask + * for registration permission, * -or the passed LSM is currently loaded. * Otherwise, return false. */ @@ -101,13 +101,13 @@ int __init security_module_enable(struct security_operations *ops) * register_security - registers a security framework with the kernel * @ops: a pointer to the struct security_options that is to be registered * - * This function is to allow a security module to register itself with the + * This function allows a security module to register itself with the * kernel security subsystem. Some rudimentary checking is done on the @ops * value passed to this function. You'll need to check first if your LSM * is allowed to register its @ops by calling security_module_enable(@ops). * * If there is already a security module registered with the kernel, - * an error will be returned. Otherwise 0 is returned on success. + * an error will be returned. Otherwise %0 is returned on success. */ int register_security(struct security_operations *ops) { diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index a436d1cfa88b..26301dd651d3 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -6,9 +6,6 @@ config SECURITY_SELINUX help This selects NSA Security-Enhanced Linux (SELinux). You will also need a policy configuration and a labeled filesystem. - You can obtain the policy compiler (checkpolicy), the utility for - labeling filesystems (setfiles), and an example policy configuration - from <http://www.nsa.gov/selinux/>. If you are unsure how to answer this question, answer N. config SECURITY_SELINUX_BOOTPARAM diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 114b4b4c97b2..cb30c7e350b3 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -136,7 +136,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) * @tclass: target security class * @av: access vector */ -static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) +void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) { const char **common_pts = NULL; u32 common_base = 0; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3aa811eba25b..c679ba653e1d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -958,7 +958,8 @@ out_err: return rc; } -void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) +static void selinux_write_opts(struct seq_file *m, + struct security_mnt_opts *opts) { int i; char *prefix; @@ -1291,7 +1292,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent /* Default to the fs superblock SID. */ isec->sid = sbsec->sid; - if (sbsec->proc) { + if (sbsec->proc && !S_ISLNK(inode->i_mode)) { struct proc_inode *proci = PROC_I(inode); if (proci->pde) { isec->sclass = inode_mode_to_security_class(inode->i_mode); @@ -3549,38 +3550,44 @@ out: #endif /* IPV6 */ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, - char **addrp, int src, u8 *proto) + char **_addrp, int src, u8 *proto) { - int ret = 0; + char *addrp; + int ret; switch (ad->u.net.family) { case PF_INET: ret = selinux_parse_skb_ipv4(skb, ad, proto); - if (ret || !addrp) - break; - *addrp = (char *)(src ? &ad->u.net.v4info.saddr : - &ad->u.net.v4info.daddr); - break; + if (ret) + goto parse_error; + addrp = (char *)(src ? &ad->u.net.v4info.saddr : + &ad->u.net.v4info.daddr); + goto okay; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case PF_INET6: ret = selinux_parse_skb_ipv6(skb, ad, proto); - if (ret || !addrp) - break; - *addrp = (char *)(src ? &ad->u.net.v6info.saddr : - &ad->u.net.v6info.daddr); - break; + if (ret) + goto parse_error; + addrp = (char *)(src ? &ad->u.net.v6info.saddr : + &ad->u.net.v6info.daddr); + goto okay; #endif /* IPV6 */ default: - break; + addrp = NULL; + goto okay; } - if (unlikely(ret)) - printk(KERN_WARNING - "SELinux: failure in selinux_parse_skb()," - " unable to parse packet\n"); - +parse_error: + printk(KERN_WARNING + "SELinux: failure in selinux_parse_skb()," + " unable to parse packet\n"); return ret; + +okay: + if (_addrp) + *_addrp = addrp; + return 0; } /** @@ -5321,8 +5328,12 @@ static int selinux_setprocattr(struct task_struct *p, if (sid == 0) return -EINVAL; - - /* Only allow single threaded processes to change context */ + /* + * SELinux allows to change context in the following case only. + * - Single threaded processes. + * - Multi threaded processes intend to change its context into + * more restricted domain (defined by TYPEBOUNDS statement). + */ if (atomic_read(&p->mm->mm_users) != 1) { struct task_struct *g, *t; struct mm_struct *mm = p->mm; @@ -5330,11 +5341,16 @@ static int selinux_setprocattr(struct task_struct *p, do_each_thread(g, t) { if (t->mm == mm && t != p) { read_unlock(&tasklist_lock); - return -EPERM; + error = security_bounded_transition(tsec->sid, sid); + if (!error) + goto boundary_ok; + + return error; } } while_each_thread(g, t); read_unlock(&tasklist_lock); } +boundary_ok: /* Check permissions for the transition. */ error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 7b9769f5e775..d12ff1a9c0aa 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -12,6 +12,7 @@ #include <linux/kdev_t.h> #include <linux/spinlock.h> #include <linux/init.h> +#include <linux/audit.h> #include <linux/in6.h> #include <linux/path.h> #include <asm/system.h> @@ -126,6 +127,9 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, u32 events, u32 ssid, u32 tsid, u16 tclass, u32 perms); +/* Shows permission in human readable form */ +void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av); + /* Exported to selinuxfs */ int avc_get_hash_stats(char *page); extern unsigned int avc_cache_threshold; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 7c543003d653..72447370bc95 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -27,13 +27,14 @@ #define POLICYDB_VERSION_RANGETRANS 21 #define POLICYDB_VERSION_POLCAP 22 #define POLICYDB_VERSION_PERMISSIVE 23 +#define POLICYDB_VERSION_BOUNDARY 24 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #else -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY #endif #define CONTEXT_MNT 0x01 @@ -62,6 +63,16 @@ enum { extern int selinux_policycap_netpeer; extern int selinux_policycap_openperm; +/* + * type_datum properties + * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY + */ +#define TYPEDATUM_PROPERTY_PRIMARY 0x0001 +#define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002 + +/* limitation of boundary depth */ +#define POLICYDB_BOUNDS_MAXDEPTH 4 + int security_load_policy(void *data, size_t len); int security_policycap_supported(unsigned int req_cap); @@ -117,6 +128,8 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen, int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, u16 tclass); +int security_bounded_transition(u32 oldsid, u32 newsid); + int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index a1be97f8beea..1215b8e47dba 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -98,7 +98,7 @@ struct avtab_node * avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) { int hvalue; - struct avtab_node *prev, *cur, *newnode; + struct avtab_node *prev, *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); if (!h || !h->htable) @@ -122,9 +122,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu key->target_class < cur->key.target_class) break; } - newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); - - return newnode; + return avtab_insert_node(h, hvalue, prev, cur, key, datum); } struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) @@ -231,7 +229,7 @@ void avtab_destroy(struct avtab *h) for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; - while (cur != NULL) { + while (cur) { temp = cur; cur = cur->next; kmem_cache_free(avtab_node_cachep, temp); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index fb4efe4f4bc8..4a4e35cac22b 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -29,7 +29,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr) int s[COND_EXPR_MAXDEPTH]; int sp = -1; - for (cur = expr; cur != NULL; cur = cur->next) { + for (cur = expr; cur; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: if (sp == (COND_EXPR_MAXDEPTH - 1)) @@ -97,14 +97,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) if (new_state == -1) printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); /* turn the rules on or off */ - for (cur = node->true_list; cur != NULL; cur = cur->next) { + for (cur = node->true_list; cur; cur = cur->next) { if (new_state <= 0) cur->node->key.specified &= ~AVTAB_ENABLED; else cur->node->key.specified |= AVTAB_ENABLED; } - for (cur = node->false_list; cur != NULL; cur = cur->next) { + for (cur = node->false_list; cur; cur = cur->next) { /* -1 or 1 */ if (new_state) cur->node->key.specified &= ~AVTAB_ENABLED; @@ -128,7 +128,7 @@ int cond_policydb_init(struct policydb *p) static void cond_av_list_destroy(struct cond_av_list *list) { struct cond_av_list *cur, *next; - for (cur = list; cur != NULL; cur = next) { + for (cur = list; cur; cur = next) { next = cur->next; /* the avtab_ptr_t node is destroy by the avtab */ kfree(cur); @@ -139,7 +139,7 @@ static void cond_node_destroy(struct cond_node *node) { struct cond_expr *cur_expr, *next_expr; - for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) { + for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) { next_expr = cur_expr->next; kfree(cur_expr); } @@ -155,7 +155,7 @@ static void cond_list_destroy(struct cond_node *list) if (list == NULL) return; - for (cur = list; cur != NULL; cur = next) { + for (cur = list; cur; cur = next) { next = cur->next; cond_node_destroy(cur); } @@ -239,7 +239,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto err; - key[len] = 0; + key[len] = '\0'; if (hashtab_insert(h, key, booldatum)) goto err; @@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum goto err; } found = 0; - for (cur = other; cur != NULL; cur = cur->next) { + for (cur = other; cur; cur = cur->next) { if (cur->node == node_ptr) { found = 1; break; @@ -485,7 +485,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi if (!ctab || !key || !avd) return; - for (node = avtab_search_node(ctab, key); node != NULL; + for (node = avtab_search_node(ctab, key); node; node = avtab_search_node_next(node, key->specified)) { if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h index 65b9f8366e9c..53ddb013ae57 100644 --- a/security/selinux/ss/conditional.h +++ b/security/selinux/ss/conditional.h @@ -28,7 +28,7 @@ struct cond_expr { #define COND_XOR 5 /* bool ^ bool */ #define COND_EQ 6 /* bool == bool */ #define COND_NEQ 7 /* bool != bool */ -#define COND_LAST 8 +#define COND_LAST COND_NEQ __u32 expr_type; __u32 bool; struct cond_expr *next; diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index ddc275490af8..68c7348d1acc 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -109,7 +109,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, *catmap = c_iter; c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); - while (e_iter != NULL) { + while (e_iter) { for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { unsigned int delta, e_startbit, c_endbit; @@ -197,7 +197,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, } } c_iter = c_iter->next; - } while (c_iter != NULL); + } while (c_iter); if (e_iter != NULL) ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; else diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 2e7788e13213..933e735bb185 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -81,7 +81,7 @@ void *hashtab_search(struct hashtab *h, const void *key) hvalue = h->hash_value(h, key); cur = h->htable[hvalue]; - while (cur != NULL && h->keycmp(h, key, cur->key) > 0) + while (cur && h->keycmp(h, key, cur->key) > 0) cur = cur->next; if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) @@ -100,7 +100,7 @@ void hashtab_destroy(struct hashtab *h) for (i = 0; i < h->size; i++) { cur = h->htable[i]; - while (cur != NULL) { + while (cur) { temp = cur; cur = cur->next; kfree(temp); @@ -127,7 +127,7 @@ int hashtab_map(struct hashtab *h, for (i = 0; i < h->size; i++) { cur = h->htable[i]; - while (cur != NULL) { + while (cur) { ret = apply(cur->key, cur->datum, args); if (ret) return ret; diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 77d745da48bb..b5407f16c2a4 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -283,8 +283,8 @@ int mls_context_to_sid(struct policydb *pol, p++; delim = *p; - if (delim != 0) - *p++ = 0; + if (delim != '\0') + *p++ = '\0'; for (l = 0; l < 2; l++) { levdatum = hashtab_search(pol->p_levels.table, scontextp); @@ -302,14 +302,14 @@ int mls_context_to_sid(struct policydb *pol, while (*p && *p != ',' && *p != '-') p++; delim = *p; - if (delim != 0) - *p++ = 0; + if (delim != '\0') + *p++ = '\0'; /* Separate into range if exists */ rngptr = strchr(scontextp, '.'); if (rngptr != NULL) { /* Remove '.' */ - *rngptr++ = 0; + *rngptr++ = '\0'; } catdatum = hashtab_search(pol->p_cats.table, @@ -357,8 +357,8 @@ int mls_context_to_sid(struct policydb *pol, p++; delim = *p; - if (delim != 0) - *p++ = 0; + if (delim != '\0') + *p++ = '\0'; } else break; } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 2391761ae422..72e4a54973aa 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -30,6 +30,7 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/errno.h> +#include <linux/audit.h> #include "security.h" #include "policydb.h" @@ -116,7 +117,12 @@ static struct policydb_compat_info policydb_compat[] = { .version = POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, .ocon_num = OCON_NUM, - } + }, + { + .version = POLICYDB_VERSION_BOUNDARY, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM, + }, }; static struct policydb_compat_info *policydb_lookup_compat(int version) @@ -254,7 +260,9 @@ static int role_index(void *key, void *datum, void *datap) role = datum; p = datap; - if (!role->value || role->value > p->p_roles.nprim) + if (!role->value + || role->value > p->p_roles.nprim + || role->bounds > p->p_roles.nprim) return -EINVAL; p->p_role_val_to_name[role->value - 1] = key; p->role_val_to_struct[role->value - 1] = role; @@ -270,9 +278,12 @@ static int type_index(void *key, void *datum, void *datap) p = datap; if (typdatum->primary) { - if (!typdatum->value || typdatum->value > p->p_types.nprim) + if (!typdatum->value + || typdatum->value > p->p_types.nprim + || typdatum->bounds > p->p_types.nprim) return -EINVAL; p->p_type_val_to_name[typdatum->value - 1] = key; + p->type_val_to_struct[typdatum->value - 1] = typdatum; } return 0; @@ -285,7 +296,9 @@ static int user_index(void *key, void *datum, void *datap) usrdatum = datum; p = datap; - if (!usrdatum->value || usrdatum->value > p->p_users.nprim) + if (!usrdatum->value + || usrdatum->value > p->p_users.nprim + || usrdatum->bounds > p->p_users.nprim) return -EINVAL; p->p_user_val_to_name[usrdatum->value - 1] = key; p->user_val_to_struct[usrdatum->value - 1] = usrdatum; @@ -438,6 +451,14 @@ static int policydb_index_others(struct policydb *p) goto out; } + p->type_val_to_struct = + kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)), + GFP_KERNEL); + if (!p->type_val_to_struct) { + rc = -ENOMEM; + goto out; + } + if (cond_init_bool_indexes(p)) { rc = -ENOMEM; goto out; @@ -625,6 +646,7 @@ void policydb_destroy(struct policydb *p) kfree(p->class_val_to_struct); kfree(p->role_val_to_struct); kfree(p->user_val_to_struct); + kfree(p->type_val_to_struct); avtab_destroy(&p->te_avtab); @@ -932,7 +954,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = hashtab_insert(h, key, perdatum); if (rc) @@ -979,7 +1001,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; for (i = 0; i < nel; i++) { rc = perm_read(p, comdatum->permissions.table, fp); @@ -1117,7 +1139,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; if (len2) { cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); @@ -1128,7 +1150,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(cladatum->comkey, fp, len2); if (rc < 0) goto bad; - cladatum->comkey[len2] = 0; + cladatum->comkey[len2] = '\0'; cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); @@ -1176,8 +1198,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct role_datum *role; - int rc; - __le32 buf[2]; + int rc, to_read = 2; + __le32 buf[3]; u32 len; role = kzalloc(sizeof(*role), GFP_KERNEL); @@ -1186,12 +1208,17 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) goto out; } - rc = next_entry(buf, fp, sizeof buf); + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) + to_read = 3; + + rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); role->value = le32_to_cpu(buf[1]); + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) + role->bounds = le32_to_cpu(buf[2]); key = kmalloc(len + 1, GFP_KERNEL); if (!key) { @@ -1201,7 +1228,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = ebitmap_read(&role->dominates, fp); if (rc) @@ -1236,8 +1263,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct type_datum *typdatum; - int rc; - __le32 buf[3]; + int rc, to_read = 3; + __le32 buf[4]; u32 len; typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); @@ -1246,13 +1273,27 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) return rc; } - rc = next_entry(buf, fp, sizeof buf); + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) + to_read = 4; + + rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); typdatum->value = le32_to_cpu(buf[1]); - typdatum->primary = le32_to_cpu(buf[2]); + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) { + u32 prop = le32_to_cpu(buf[2]); + + if (prop & TYPEDATUM_PROPERTY_PRIMARY) + typdatum->primary = 1; + if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE) + typdatum->attribute = 1; + + typdatum->bounds = le32_to_cpu(buf[3]); + } else { + typdatum->primary = le32_to_cpu(buf[2]); + } key = kmalloc(len + 1, GFP_KERNEL); if (!key) { @@ -1262,7 +1303,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = hashtab_insert(h, key, typdatum); if (rc) @@ -1309,8 +1350,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct user_datum *usrdatum; - int rc; - __le32 buf[2]; + int rc, to_read = 2; + __le32 buf[3]; u32 len; usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); @@ -1319,12 +1360,17 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) goto out; } - rc = next_entry(buf, fp, sizeof buf); + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) + to_read = 3; + + rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); usrdatum->value = le32_to_cpu(buf[1]); + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) + usrdatum->bounds = le32_to_cpu(buf[2]); key = kmalloc(len + 1, GFP_KERNEL); if (!key) { @@ -1334,7 +1380,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = ebitmap_read(&usrdatum->roles, fp); if (rc) @@ -1388,7 +1434,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); if (!levdatum->level) { @@ -1440,7 +1486,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) rc = next_entry(key, fp, len); if (rc < 0) goto bad; - key[len] = 0; + key[len] = '\0'; rc = hashtab_insert(h, key, catdatum); if (rc) @@ -1465,6 +1511,133 @@ static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) cat_read, }; +static int user_bounds_sanity_check(void *key, void *datum, void *datap) +{ + struct user_datum *upper, *user; + struct policydb *p = datap; + int depth = 0; + + upper = user = datum; + while (upper->bounds) { + struct ebitmap_node *node; + unsigned long bit; + + if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { + printk(KERN_ERR "SELinux: user %s: " + "too deep or looped boundary", + (char *) key); + return -EINVAL; + } + + upper = p->user_val_to_struct[upper->bounds - 1]; + ebitmap_for_each_positive_bit(&user->roles, node, bit) { + if (ebitmap_get_bit(&upper->roles, bit)) + continue; + + printk(KERN_ERR + "SELinux: boundary violated policy: " + "user=%s role=%s bounds=%s\n", + p->p_user_val_to_name[user->value - 1], + p->p_role_val_to_name[bit], + p->p_user_val_to_name[upper->value - 1]); + + return -EINVAL; + } + } + + return 0; +} + +static int role_bounds_sanity_check(void *key, void *datum, void *datap) +{ + struct role_datum *upper, *role; + struct policydb *p = datap; + int depth = 0; + + upper = role = datum; + while (upper->bounds) { + struct ebitmap_node *node; + unsigned long bit; + + if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { + printk(KERN_ERR "SELinux: role %s: " + "too deep or looped bounds\n", + (char *) key); + return -EINVAL; + } + + upper = p->role_val_to_struct[upper->bounds - 1]; + ebitmap_for_each_positive_bit(&role->types, node, bit) { + if (ebitmap_get_bit(&upper->types, bit)) + continue; + + printk(KERN_ERR + "SELinux: boundary violated policy: " + "role=%s type=%s bounds=%s\n", + p->p_role_val_to_name[role->value - 1], + p->p_type_val_to_name[bit], + p->p_role_val_to_name[upper->value - 1]); + + return -EINVAL; + } + } + + return 0; +} + +static int type_bounds_sanity_check(void *key, void *datum, void *datap) +{ + struct type_datum *upper, *type; + struct policydb *p = datap; + int depth = 0; + + upper = type = datum; + while (upper->bounds) { + if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { + printk(KERN_ERR "SELinux: type %s: " + "too deep or looped boundary\n", + (char *) key); + return -EINVAL; + } + + upper = p->type_val_to_struct[upper->bounds - 1]; + if (upper->attribute) { + printk(KERN_ERR "SELinux: type %s: " + "bounded by attribute %s", + (char *) key, + p->p_type_val_to_name[upper->value - 1]); + return -EINVAL; + } + } + + return 0; +} + +static int policydb_bounds_sanity_check(struct policydb *p) +{ + int rc; + + if (p->policyvers < POLICYDB_VERSION_BOUNDARY) + return 0; + + rc = hashtab_map(p->p_users.table, + user_bounds_sanity_check, p); + if (rc) + return rc; + + rc = hashtab_map(p->p_roles.table, + role_bounds_sanity_check, p); + if (rc) + return rc; + + rc = hashtab_map(p->p_types.table, + type_bounds_sanity_check, p); + if (rc) + return rc; + + return 0; +} + extern int ss_initialized; /* @@ -1523,7 +1696,7 @@ int policydb_read(struct policydb *p, void *fp) kfree(policydb_str); goto bad; } - policydb_str[len] = 0; + policydb_str[len] = '\0'; if (strcmp(policydb_str, POLICYDB_STRING)) { printk(KERN_ERR "SELinux: policydb string %s does not match " "my string %s\n", policydb_str, POLICYDB_STRING); @@ -1961,6 +2134,10 @@ int policydb_read(struct policydb *p, void *fp) goto bad; } + rc = policydb_bounds_sanity_check(p); + if (rc) + goto bad; + rc = 0; out: return rc; diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 4253370fda6a..55152d498b53 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -61,6 +61,7 @@ struct class_datum { /* Role attributes */ struct role_datum { u32 value; /* internal role value */ + u32 bounds; /* boundary of role */ struct ebitmap dominates; /* set of roles dominated by this role */ struct ebitmap types; /* set of authorized types for role */ }; @@ -81,12 +82,15 @@ struct role_allow { /* Type attributes */ struct type_datum { u32 value; /* internal type value */ + u32 bounds; /* boundary of type */ unsigned char primary; /* primary name? */ + unsigned char attribute;/* attribute ?*/ }; /* User attributes */ struct user_datum { u32 value; /* internal user value */ + u32 bounds; /* bounds of user */ struct ebitmap roles; /* set of authorized roles for user */ struct mls_range range; /* MLS range (min - max) for user */ struct mls_level dfltlevel; /* default login MLS level for user */ @@ -209,6 +213,7 @@ struct policydb { struct class_datum **class_val_to_struct; struct role_datum **role_val_to_struct; struct user_datum **user_val_to_struct; + struct type_datum **type_val_to_struct; /* type enforcement access vectors and transitions */ struct avtab te_avtab; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ed0ca649d7db..343c8ab14af0 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -88,6 +88,11 @@ static u32 latest_granting; static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len); +static int context_struct_compute_av(struct context *scontext, + struct context *tcontext, + u16 tclass, + u32 requested, + struct av_decision *avd); /* * Return the boolean value of a constraint expression * when it is applied to the specified source and target @@ -274,6 +279,100 @@ mls_ops: } /* + * security_boundary_permission - drops violated permissions + * on boundary constraint. + */ +static void type_attribute_bounds_av(struct context *scontext, + struct context *tcontext, + u16 tclass, + u32 requested, + struct av_decision *avd) +{ + struct context lo_scontext; + struct context lo_tcontext; + struct av_decision lo_avd; + struct type_datum *source + = policydb.type_val_to_struct[scontext->type - 1]; + struct type_datum *target + = policydb.type_val_to_struct[tcontext->type - 1]; + u32 masked = 0; + + if (source->bounds) { + memset(&lo_avd, 0, sizeof(lo_avd)); + + memcpy(&lo_scontext, scontext, sizeof(lo_scontext)); + lo_scontext.type = source->bounds; + + context_struct_compute_av(&lo_scontext, + tcontext, + tclass, + requested, + &lo_avd); + if ((lo_avd.allowed & avd->allowed) == avd->allowed) + return; /* no masked permission */ + masked = ~lo_avd.allowed & avd->allowed; + } + + if (target->bounds) { + memset(&lo_avd, 0, sizeof(lo_avd)); + + memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext)); + lo_tcontext.type = target->bounds; + + context_struct_compute_av(scontext, + &lo_tcontext, + tclass, + requested, + &lo_avd); + if ((lo_avd.allowed & avd->allowed) == avd->allowed) + return; /* no masked permission */ + masked = ~lo_avd.allowed & avd->allowed; + } + + if (source->bounds && target->bounds) { + memset(&lo_avd, 0, sizeof(lo_avd)); + /* + * lo_scontext and lo_tcontext are already + * set up. + */ + + context_struct_compute_av(&lo_scontext, + &lo_tcontext, + tclass, + requested, + &lo_avd); + if ((lo_avd.allowed & avd->allowed) == avd->allowed) + return; /* no masked permission */ + masked = ~lo_avd.allowed & avd->allowed; + } + + if (masked) { + struct audit_buffer *ab; + char *stype_name + = policydb.p_type_val_to_name[source->value - 1]; + char *ttype_name + = policydb.p_type_val_to_name[target->value - 1]; + char *tclass_name + = policydb.p_class_val_to_name[tclass - 1]; + + /* mask violated permissions */ + avd->allowed &= ~masked; + + /* notice to userspace via audit message */ + ab = audit_log_start(current->audit_context, + GFP_ATOMIC, AUDIT_SELINUX_ERR); + if (!ab) + return; + + audit_log_format(ab, "av boundary violation: " + "source=%s target=%s tclass=%s", + stype_name, ttype_name, tclass_name); + avc_dump_av(ab, tclass, masked); + audit_log_end(ab); + } +} + +/* * Compute access vectors based on a context structure pair for * the permissions in a particular class. */ @@ -356,7 +455,7 @@ static int context_struct_compute_av(struct context *scontext, avkey.source_type = i + 1; avkey.target_type = j + 1; for (node = avtab_search_node(&policydb.te_avtab, &avkey); - node != NULL; + node; node = avtab_search_node_next(node, avkey.specified)) { if (node->key.specified == AVTAB_ALLOWED) avd->allowed |= node->datum.data; @@ -404,6 +503,14 @@ static int context_struct_compute_av(struct context *scontext, PROCESS__DYNTRANSITION); } + /* + * If the given source and target types have boundary + * constraint, lazy checks have to mask any violated + * permission and notice it to userspace via audit. + */ + type_attribute_bounds_av(scontext, tcontext, + tclass, requested, avd); + return 0; inval_class: @@ -549,6 +656,69 @@ out: return rc; } +/* + * security_bounded_transition - check whether the given + * transition is directed to bounded, or not. + * It returns 0, if @newsid is bounded by @oldsid. + * Otherwise, it returns error code. + * + * @oldsid : current security identifier + * @newsid : destinated security identifier + */ +int security_bounded_transition(u32 old_sid, u32 new_sid) +{ + struct context *old_context, *new_context; + struct type_datum *type; + int index; + int rc = -EINVAL; + + read_lock(&policy_rwlock); + + old_context = sidtab_search(&sidtab, old_sid); + if (!old_context) { + printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", + __func__, old_sid); + goto out; + } + + new_context = sidtab_search(&sidtab, new_sid); + if (!new_context) { + printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", + __func__, new_sid); + goto out; + } + + /* type/domain unchaned */ + if (old_context->type == new_context->type) { + rc = 0; + goto out; + } + + index = new_context->type; + while (true) { + type = policydb.type_val_to_struct[index - 1]; + BUG_ON(!type); + + /* not bounded anymore */ + if (!type->bounds) { + rc = -EPERM; + break; + } + + /* @newsid is bounded by @oldsid */ + if (type->bounds == old_context->type) { + rc = 0; + break; + } + index = type->bounds; + } +out: + read_unlock(&policy_rwlock); + + return rc; +} + + /** * security_compute_av - Compute access vector decisions. * @ssid: source security identifier @@ -794,7 +964,7 @@ static int string_to_context_struct(struct policydb *pol, *p++ = 0; typdatum = hashtab_search(pol->p_types.table, scontextp); - if (!typdatum) + if (!typdatum || typdatum->attribute) goto out; ctx->type = typdatum->value; @@ -1037,7 +1207,7 @@ static int security_compute_sid(u32 ssid, /* If no permanent rule, also check for enabled conditional rules */ if (!avdatum) { node = avtab_search_node(&policydb.te_cond_avtab, &avkey); - for (; node != NULL; node = avtab_search_node_next(node, specified)) { + for (; node; node = avtab_search_node_next(node, specified)) { if (node->key.specified & AVTAB_ENABLED) { avdatum = &node->datum; break; @@ -2050,7 +2220,7 @@ int security_set_bools(int len, int *values) policydb.bool_val_to_struct[i]->state = 0; } - for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { + for (cur = policydb.cond_list; cur; cur = cur->next) { rc = evaluate_cond_node(&policydb, cur); if (rc) goto out; @@ -2102,7 +2272,7 @@ static int security_preserve_bools(struct policydb *p) if (booldatum) booldatum->state = bvalues[i]; } - for (cur = p->cond_list; cur != NULL; cur = cur->next) { + for (cur = p->cond_list; cur; cur = cur->next) { rc = evaluate_cond_node(p, cur); if (rc) goto out; diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index a81ded104129..e817989764cd 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -43,7 +43,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context) hvalue = SIDTAB_HASH(sid); prev = NULL; cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) { + while (cur && sid > cur->sid) { prev = cur; cur = cur->next; } @@ -92,7 +92,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) + while (cur && sid > cur->sid) cur = cur->next; if (force && cur && sid == cur->sid && cur->context.len) @@ -103,7 +103,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) sid = SECINITSID_UNLABELED; hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) + while (cur && sid > cur->sid) cur = cur->next; if (!cur || sid != cur->sid) return NULL; @@ -136,7 +136,7 @@ int sidtab_map(struct sidtab *s, for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; - while (cur != NULL) { + while (cur) { rc = apply(cur->sid, &cur->context, args); if (rc) goto out; @@ -155,7 +155,7 @@ static inline u32 sidtab_search_context(struct sidtab *s, for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; - while (cur != NULL) { + while (cur) { if (context_cmp(&cur->context, context)) return cur->sid; cur = cur->next; @@ -242,7 +242,7 @@ void sidtab_destroy(struct sidtab *s) for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; - while (cur != NULL) { + while (cur) { temp = cur; cur = cur->next; context_destroy(&temp->context); diff --git a/security/smack/smack.h b/security/smack/smack.h index 4a4477f5afdc..31dce559595a 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -178,6 +178,7 @@ u32 smack_to_secid(const char *); extern int smack_cipso_direct; extern int smack_net_nltype; extern char *smack_net_ambient; +extern char *smack_onlycap; extern struct smack_known *smack_known; extern struct smack_known smack_known_floor; diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f6b5f6eed6dd..79ff21ed4c3b 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -157,7 +157,7 @@ int smk_access(char *subject_label, char *object_label, int request) * * This function checks the current subject label/object label pair * in the access rule list and returns 0 if the access is permitted, - * non zero otherwise. It allows that current my have the capability + * non zero otherwise. It allows that current may have the capability * to override the rules. */ int smk_curacc(char *obj_label, u32 mode) @@ -168,6 +168,14 @@ int smk_curacc(char *obj_label, u32 mode) if (rc == 0) return 0; + /* + * Return if a specific label has been designated as the + * only one that gets privilege and current does not + * have that label. + */ + if (smack_onlycap != NULL && smack_onlycap != current->security) + return rc; + if (capable(CAP_MAC_OVERRIDE)) return 0; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 9733f8eb1a2a..c21d8c8bf0c7 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -39,6 +39,7 @@ enum smk_inos { SMK_DIRECT = 6, /* CIPSO level indicating direct label */ SMK_AMBIENT = 7, /* internet ambient label */ SMK_NLTYPE = 8, /* label scheme to use by default */ + SMK_ONLYCAP = 9, /* the only "capable" label */ }; /* @@ -68,6 +69,16 @@ int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4; */ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; +/* + * Unless a process is running with this label even + * having CAP_MAC_OVERRIDE isn't enough to grant + * privilege to violate MAC policy. If no label is + * designated (the NULL case) capabilities apply to + * everyone. It is expected that the hat (^) label + * will be used if any label is used. + */ +char *smack_onlycap; + static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; struct smk_list_entry *smack_list; @@ -789,6 +800,85 @@ static const struct file_operations smk_ambient_ops = { .write = smk_write_ambient, }; +/** + * smk_read_onlycap - read() for /smack/onlycap + * @filp: file pointer, not actually used + * @buf: where to put the result + * @cn: maximum to send along + * @ppos: where to start + * + * Returns number of bytes read or error code, as appropriate + */ +static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, + size_t cn, loff_t *ppos) +{ + char *smack = ""; + ssize_t rc = -EINVAL; + int asize; + + if (*ppos != 0) + return 0; + + if (smack_onlycap != NULL) + smack = smack_onlycap; + + asize = strlen(smack) + 1; + + if (cn >= asize) + rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); + + return rc; +} + +/** + * smk_write_onlycap - write() for /smack/onlycap + * @filp: file pointer, not actually used + * @buf: where to get the data from + * @count: bytes sent + * @ppos: where to start + * + * Returns number of bytes written or error code, as appropriate + */ +static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + char in[SMK_LABELLEN]; + char *sp = current->security; + + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + + /* + * This can be done using smk_access() but is done + * explicitly for clarity. The smk_access() implementation + * would use smk_access(smack_onlycap, MAY_WRITE) + */ + if (smack_onlycap != NULL && smack_onlycap != sp) + return -EPERM; + + if (count >= SMK_LABELLEN) + return -EINVAL; + + if (copy_from_user(in, buf, count) != 0) + return -EFAULT; + + /* + * Should the null string be passed in unset the onlycap value. + * This seems like something to be careful with as usually + * smk_import only expects to return NULL for errors. It + * is usually the case that a nullstring or "\n" would be + * bad to pass to smk_import but in fact this is useful here. + */ + smack_onlycap = smk_import(in, count); + + return count; +} + +static const struct file_operations smk_onlycap_ops = { + .read = smk_read_onlycap, + .write = smk_write_onlycap, +}; + struct option_names { int o_number; char *o_name; @@ -921,6 +1011,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, [SMK_NLTYPE] = {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, + [SMK_ONLYCAP] = + {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, /* last one */ {""} }; |