diff --git a/[refs] b/[refs] index 2f43f4e8b807..caa18e7defd1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 44637a12f80b80157d9c1bc5b7d6ef09c9e05713 +refs/heads/master: afcc2472d80569059b5fe71fcb67e618b9d83fa8 diff --git a/trunk/CREDITS b/trunk/CREDITS index 8e577ce4abeb..521f00d1b549 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -3203,7 +3203,7 @@ N: Eugene Surovegin E: ebs@ebshome.net W: http://kernel.ebshome.net/ P: 1024D/AE5467F1 FF22 39F1 6728 89F6 6E6C 2365 7602 F33D AE54 67F1 -D: Embedded PowerPC 4xx: EMAC, I2C, PIC and random hacks/fixes +D: Embedded PowerPC 4xx: I2C, PIC and random hacks/fixes S: Sunnyvale, California 94085 S: USA diff --git a/trunk/Documentation/Changes b/trunk/Documentation/Changes index fe5ae0f55020..86b86399d61d 100644 --- a/trunk/Documentation/Changes +++ b/trunk/Documentation/Changes @@ -31,6 +31,8 @@ al espa Eine deutsche Version dieser Datei finden Sie unter . +Last updated: October 29th, 2002 + Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu). Current Minimal Requirements @@ -46,7 +48,7 @@ necessary on all systems; obviously, if you don't have any ISDN hardware, for example, you probably needn't concern yourself with isdn4k-utils. -o Gnu C 3.2 # gcc --version +o Gnu C 2.95.3 # gcc --version o Gnu make 3.79.1 # make --version o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version @@ -72,7 +74,26 @@ GCC --- The gcc version requirements may vary depending on the type of CPU in your -computer. +computer. The next paragraph applies to users of x86 CPUs, but not +necessarily to users of other CPUs. Users of other CPUs should obtain +information about their gcc version requirements from another source. + +The recommended compiler for the kernel is gcc 2.95.x (x >= 3), and it +should be used when you need absolute stability. You may use gcc 3.0.x +instead if you wish, although it may cause problems. Later versions of gcc +have not received much testing for Linux kernel compilation, and there are +almost certainly bugs (mainly, but not exclusively, in the kernel) that +will need to be fixed in order to use these compilers. In any case, using +pgcc instead of plain gcc is just asking for trouble. + +The Red Hat gcc 2.96 compiler subtree can also be used to build this tree. +You should ensure you use gcc-2.96-74 or later. gcc-2.96-54 will not build +the kernel correctly. + +In addition, please pay attention to compiler optimization. Anything +greater than -O2 may not be wise. Similarly, if you choose to use gcc-2.95.x +or derivatives, be sure not to use -fstrict-aliasing (which, depending on +your version of gcc 2.95.x, may necessitate using -fno-strict-aliasing). Make ---- @@ -301,9 +322,9 @@ Getting updated software Kernel compilation ****************** -gcc ---- -o +gcc 2.95.3 +---------- +o Make ---- diff --git a/trunk/Documentation/CodingStyle b/trunk/Documentation/CodingStyle index ce780ef648f1..eb7db3c19227 100644 --- a/trunk/Documentation/CodingStyle +++ b/trunk/Documentation/CodingStyle @@ -344,7 +344,7 @@ Remember: if another thread can find your data structure, and you don't have a reference count on it, you almost certainly have a bug. - Chapter 11: Macros, Enums and RTL + Chapter 11: Macros, Enums, Inline functions and RTL Names of macros defining constants and labels in enums are capitalized. @@ -429,35 +429,7 @@ from void pointer to any other pointer type is guaranteed by the C programming language. - Chapter 14: The inline disease - -There appears to be a common misperception that gcc has a magic "make me -faster" speedup option called "inline". While the use of inlines can be -appropriate (for example as a means of replacing macros, see Chapter 11), it -very often is not. Abundant use of the inline keyword leads to a much bigger -kernel, which in turn slows the system as a whole down, due to a bigger -icache footprint for the CPU and simply because there is less memory -available for the pagecache. Just think about it; a pagecache miss causes a -disk seek, which easily takes 5 miliseconds. There are a LOT of cpu cycles -that can go into these 5 miliseconds. - -A reasonable rule of thumb is to not put inline at functions that have more -than 3 lines of code in them. An exception to this rule are the cases where -a parameter is known to be a compiletime constant, and as a result of this -constantness you *know* the compiler will be able to optimize most of your -function away at compile time. For a good example of this later case, see -the kmalloc() inline function. - -Often people argue that adding inline to functions that are static and used -only once is always a win since there is no space tradeoff. While this is -technically correct, gcc is capable of inlining these automatically without -help, and the maintenance issue of removing the inline when a second user -appears outweighs the potential value of the hint that tells gcc to do -something it would have done anyway. - - - - Chapter 15: References + Chapter 14: References The C Programming Language, Second Edition by Brian W. Kernighan and Dennis M. Ritchie. @@ -472,13 +444,10 @@ ISBN 0-201-61586-X. URL: http://cm.bell-labs.com/cm/cs/tpop/ GNU manuals - where in compliance with K&R and this text - for cpp, gcc, -gcc internals and indent, all available from http://www.gnu.org/manual/ +gcc internals and indent, all available from http://www.gnu.org WG14 is the international standardization working group for the programming -language C, URL: http://www.open-std.org/JTC1/SC22/WG14/ - -Kernel CodingStyle, by greg@kroah.com at OLS 2002: -http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ +language C, URL: http://std.dkuug.dk/JTC1/SC22/WG14/ -- -Last updated on 30 December 2005 by a community effort on LKML. +Last updated on 16 February 2004 by a community effort on LKML. diff --git a/trunk/Documentation/RCU/rcuref.txt b/trunk/Documentation/RCU/rcuref.txt index 3f60db41b2f0..a23fee66064d 100644 --- a/trunk/Documentation/RCU/rcuref.txt +++ b/trunk/Documentation/RCU/rcuref.txt @@ -1,67 +1,74 @@ -Refcounter design for elements of lists/arrays protected by RCU. +Refcounter framework for elements of lists/arrays protected by +RCU. Refcounting on elements of lists which are protected by traditional reader/writer spinlocks or semaphores are straight forward as in: -1. 2. -add() search_and_reference() -{ { - alloc_object read_lock(&list_lock); - ... search_for_element - atomic_set(&el->rc, 1); atomic_inc(&el->rc); - write_lock(&list_lock); ... - add_element read_unlock(&list_lock); - ... ... - write_unlock(&list_lock); } +1. 2. +add() search_and_reference() +{ { + alloc_object read_lock(&list_lock); + ... search_for_element + atomic_set(&el->rc, 1); atomic_inc(&el->rc); + write_lock(&list_lock); ... + add_element read_unlock(&list_lock); + ... ... + write_unlock(&list_lock); } } 3. 4. release_referenced() delete() { { - ... write_lock(&list_lock); - atomic_dec(&el->rc, relfunc) ... - ... delete_element -} write_unlock(&list_lock); - ... - if (atomic_dec_and_test(&el->rc)) - kfree(el); - ... + ... write_lock(&list_lock); + atomic_dec(&el->rc, relfunc) ... + ... delete_element +} write_unlock(&list_lock); + ... + if (atomic_dec_and_test(&el->rc)) + kfree(el); + ... } 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 +in search_and_reference to rcu_read_lock(), the rcuref_get in search_and_reference could potentially hold reference to an element which -has already been deleted from the list/array. atomic_inc_not_zero takes +has already been deleted from the list/array. rcuref_lf_get_rcu takes care of this scenario. search_and_reference should look as; 1. 2. 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(); - return FAIL; - add_element } - ... ... - write_unlock(&list_lock); rcu_read_unlock(); + alloc_object rcu_read_lock(); + ... search_for_element + atomic_set(&el->rc, 1); if (rcuref_inc_lf(&el->rc)) { + write_lock(&list_lock); rcu_read_unlock(); + return FAIL; + add_element } + ... ... + write_unlock(&list_lock); rcu_read_unlock(); } } 3. 4. release_referenced() delete() { { - ... write_lock(&list_lock); - atomic_dec(&el->rc, relfunc) ... - ... delete_element -} write_unlock(&list_lock); - ... - if (atomic_dec_and_test(&el->rc)) - call_rcu(&el->head, el_free); - ... + ... write_lock(&list_lock); + rcuref_dec(&el->rc, relfunc) ... + ... delete_element +} write_unlock(&list_lock); + ... + if (rcuref_dec_and_test(&el->rc)) + call_rcu(&el->head, el_free); + ... } Sometimes, reference to the element need to be obtained in the -update (write) stream. In such cases, atomic_inc_not_zero might be an -overkill since the spinlock serialising list updates are held. atomic_inc +update (write) stream. In such cases, rcuref_inc_lf might be an overkill +since the spinlock serialising list updates are held. rcuref_inc is to be used in such cases. - +For arches which do not have cmpxchg rcuref_inc_lf +api uses a hashed spinlock implementation and the same hashed spinlock +is acquired in all rcuref_xxx primitives to preserve atomicity. +Note: Use rcuref_inc api only if you need to use rcuref_inc_lf on the +refcounter atleast at one place. Mixing rcuref_inc and atomic_xxx api +might lead to races. rcuref_inc_lf() must be used in lockfree +RCU critical sections only. diff --git a/trunk/Documentation/SubmittingDrivers b/trunk/Documentation/SubmittingDrivers index dd311cff1cc3..c3cca924e94b 100644 --- a/trunk/Documentation/SubmittingDrivers +++ b/trunk/Documentation/SubmittingDrivers @@ -27,17 +27,18 @@ Who To Submit Drivers To ------------------------ Linux 2.0: - No new drivers are accepted for this kernel tree. + No new drivers are accepted for this kernel tree Linux 2.2: - No new drivers are accepted for this kernel tree. - -Linux 2.4: If the code area has a general maintainer then please submit it to the maintainer listed in MAINTAINERS in the kernel file. If the maintainer does not respond or you cannot find the appropriate - maintainer then please contact Marcelo Tosatti - . + maintainer then please contact the 2.2 kernel maintainer: + Marc-Christian Petersen . + +Linux 2.4: + The same rules apply as 2.2. The final contact point for Linux 2.4 + submissions is Marcelo Tosatti . Linux 2.6: The same rules apply as 2.4 except that you should follow linux-kernel @@ -52,7 +53,6 @@ Licensing: The code must be released to us under the of exclusive GPL licensing, and if you wish the driver to be useful to other communities such as BSD you may well wish to release under multiple licenses. - See accepted licenses at include/linux/module.h Copyright: The copyright owner must agree to use of GPL. It's best if the submitter and copyright owner @@ -143,13 +143,5 @@ KernelNewbies: http://kernelnewbies.org/ Linux USB project: - http://linux-usb.sourceforge.net/ - -How to NOT write kernel driver by arjanv@redhat.com - http://people.redhat.com/arjanv/olspaper.pdf - -Kernel Janitor: - http://janitor.kernelnewbies.org/ + http://sourceforge.net/projects/linux-usb/ --- -Last updated on 17 Nov 2005. diff --git a/trunk/Documentation/SubmittingPatches b/trunk/Documentation/SubmittingPatches index 6198e5ebcf65..1d47e6c09dc6 100644 --- a/trunk/Documentation/SubmittingPatches +++ b/trunk/Documentation/SubmittingPatches @@ -78,9 +78,7 @@ Randy Dunlap's patch scripts: http://www.xenotime.net/linux/scripts/patching-scripts-002.tar.gz Andrew Morton's patch scripts: -http://www.zip.com.au/~akpm/linux/patches/ -Instead of these scripts, quilt is the recommended patch management -tool (see above). +http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.20 @@ -99,7 +97,7 @@ need to split up your patch. See #3, next. 3) Separate your changes. -Separate _logical changes_ into a single patch file. +Separate each logical change into its own patch. For example, if your changes include both bug fixes and performance enhancements for a single driver, separate those changes into two @@ -114,10 +112,6 @@ If one patch depends on another patch in order for a change to be complete, that is OK. Simply note "this patch depends on patch X" in your patch description. -If you cannot condense your patch set into a smaller set of patches, -then only post say 15 or so at a time and wait for review and integration. - - 4) Select e-mail destination. @@ -130,10 +124,6 @@ your patch to the primary Linux kernel developer's mailing list, linux-kernel@vger.kernel.org. Most kernel developers monitor this e-mail list, and can comment on your changes. - -Do not send more than 15 patches at once to the vger mailing lists!!! - - Linus Torvalds is the final arbiter of all changes accepted into the Linux kernel. His e-mail address is . He gets a lot of e-mail, so typically you should do your best to -avoid- sending @@ -159,9 +149,6 @@ USB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the MAINTAINERS file for a mailing list that relates specifically to your change. -Majordomo lists of VGER.KERNEL.ORG at: - - If changes affect userland-kernel interfaces, please send the MAN-PAGES maintainer (as listed in the MAINTAINERS file) a man-pages patch, or at least a notification of the change, @@ -386,14 +373,27 @@ a diffstat, to show what files have changed, and the number of inserted and deleted lines per file. A diffstat is especially useful on bigger patches. Other comments relevant only to the moment or the maintainer, not suitable for the permanent changelog, should also go here. -Use diffstat options "-p 1 -w 70" so that filenames are listed from the -top of the kernel source tree and don't use too much horizontal space -(easily fit in 80 columns, maybe with some indentation). See more details on the proper patch format in the following references. +13) More references for submitting patches + +Andrew Morton, "The perfect patch" (tpp). + + +Jeff Garzik, "Linux kernel patch submission format." + + +Greg KH, "How to piss off a kernel subsystem maintainer" + + +Kernel Documentation/CodingStyle + + +Linus Torvald's mail on the canonical patch format: + ----------------------------------- @@ -466,30 +466,3 @@ and 'extern __inline__'. Don't try to anticipate nebulous future cases which may or may not be useful: "Make it as simple as you can, and no simpler." - - ----------------------- -SECTION 3 - REFERENCES ----------------------- - -Andrew Morton, "The perfect patch" (tpp). - - -Jeff Garzik, "Linux kernel patch submission format." - - -Greg Kroah, "How to piss off a kernel subsystem maintainer". - - - - -NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!. - - -Kernel Documentation/CodingStyle - - -Linus Torvald's mail on the canonical patch format: - --- -Last updated on 17 Nov 2005. diff --git a/trunk/Documentation/applying-patches.txt b/trunk/Documentation/applying-patches.txt index 05a08c2c1889..681e426e2482 100644 --- a/trunk/Documentation/applying-patches.txt +++ b/trunk/Documentation/applying-patches.txt @@ -2,8 +2,7 @@ Applying Patches To The Linux Kernel ------------------------------------ - Original by: Jesper Juhl, August 2005 - Last update: 2005-12-02 + (Written by Jesper Juhl, August 2005) @@ -119,7 +118,7 @@ wrong. When patch encounters a change that it can't fix up with fuzz it rejects it outright and leaves a file with a .rej extension (a reject file). You can -read this file to see exactly what change couldn't be applied, so you can +read this file to see exactely what change couldn't be applied, so you can go fix it up by hand if you wish. If you don't have any third party patches applied to your kernel source, but @@ -128,7 +127,7 @@ and have made no modifications yourself to the source files, then you should never see a fuzz or reject message from patch. If you do see such messages anyway, then there's a high risk that either your local source tree or the patch file is corrupted in some way. In that case you should probably try -re-downloading the patch and if things are still not OK then you'd be advised +redownloading the patch and if things are still not OK then you'd be advised to start with a fresh tree downloaded in full from kernel.org. Let's look a bit more at some of the messages patch can produce. @@ -181,11 +180,9 @@ wish to apply. Are there any alternatives to `patch'? --- - Yes there are alternatives. - - You can use the `interdiff' program (http://cyberelk.net/tim/patchutils/) to -generate a patch representing the differences between two patches and then -apply the result. + Yes there are alternatives. You can use the `interdiff' program +(http://cyberelk.net/tim/patchutils/) to generate a patch representing the +differences between two patches and then apply the result. This will let you move from something like 2.6.12.2 to 2.6.12.3 in a single step. The -z flag to interdiff will even let you feed it patches in gzip or bzip2 compressed form directly without the use of zcat or bzcat or manual @@ -200,7 +197,7 @@ do the additional steps since interdiff can get things wrong in some cases. Another alternative is `ketchup', which is a python script for automatic downloading and applying of patches (http://www.selenic.com/ketchup/). - Other nice tools are diffstat which shows a summary of changes made by a +Other nice tools are diffstat which shows a summary of changes made by a patch, lsdiff which displays a short listing of affected files in a patch file, along with (optionally) the line numbers of the start of each patch and grepdiff which displays a list of the files modified by a patch where @@ -261,7 +258,7 @@ $ patch -p1 -R < ../patch-2.6.11.1 # revert the 2.6.11.1 patch # source dir is now 2.6.11 $ patch -p1 < ../patch-2.6.12 # apply new 2.6.12 patch $ cd .. -$ mv linux-2.6.11.1 linux-2.6.12 # rename source dir +$ mv linux-2.6.11.1 inux-2.6.12 # rename source dir The 2.6.x.y kernels @@ -436,11 +433,7 @@ $ cd .. $ mv linux-2.6.12-mm1 linux-2.6.13-rc3-mm3 # rename the source dir -This concludes this list of explanations of the various kernel trees. -I hope you are now clear on how to apply the various patches and help testing -the kernel. - -Thank you's to Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert, -Johannes Stezenbach, Grant Coady, Pavel Machek and others that I may have -forgotten for their reviews and contributions to this document. +This concludes this list of explanations of the various kernel trees and I +hope you are now crystal clear on how to apply the various patches and help +testing the kernel. diff --git a/trunk/Documentation/block/stat.txt b/trunk/Documentation/block/stat.txt deleted file mode 100644 index 0dbc946de2ea..000000000000 --- a/trunk/Documentation/block/stat.txt +++ /dev/null @@ -1,82 +0,0 @@ -Block layer statistics in /sys/block//stat -=============================================== - -This file documents the contents of the /sys/block//stat file. - -The stat file provides several statistics about the state of block -device . - -Q. Why are there multiple statistics in a single file? Doesn't sysfs - normally contain a single value per file? -A. By having a single file, the kernel can guarantee that the statistics - represent a consistent snapshot of the state of the device. If the - statistics were exported as multiple files containing one statistic - each, it would be impossible to guarantee that a set of readings - represent a single point in time. - -The stat file consists of a single line of text containing 11 decimal -values separated by whitespace. The fields are summarized in the -following table, and described in more detail below. - -Name units description ----- ----- ----------- -read I/Os requests number of read I/Os processed -read merges requests number of read I/Os merged with in-queue I/O -read sectors sectors number of sectors read -read ticks milliseconds total wait time for read requests -write I/Os requests number of write I/Os processed -write merges requests number of write I/Os merged with in-queue I/O -write sectors sectors number of sectors written -write ticks milliseconds total wait time for write requests -in_flight requests number of I/Os currently in flight -io_ticks milliseconds total time this block device has been active -time_in_queue milliseconds total wait time for all requests - -read I/Os, write I/Os -===================== - -These values increment when an I/O request completes. - -read merges, write merges -========================= - -These values increment when an I/O request is merged with an -already-queued I/O request. - -read sectors, write sectors -=========================== - -These values count the number of sectors read from or written to this -block device. The "sectors" in question are the standard UNIX 512-byte -sectors, not any device- or filesystem-specific block size. The -counters are incremented when the I/O completes. - -read ticks, write ticks -======================= - -These values count the number of milliseconds that I/O requests have -waited on this block device. If there are multiple I/O requests waiting, -these values will increase at a rate greater than 1000/second; for -example, if 60 read requests wait for an average of 30 ms, the read_ticks -field will increase by 60*30 = 1800. - -in_flight -========= - -This value counts the number of I/O requests that have been issued to -the device driver but have not yet completed. It does not include I/O -requests that are in the queue but not yet issued to the device driver. - -io_ticks -======== - -This value counts the number of milliseconds during which the device has -had I/O requests queued. - -time_in_queue -============= - -This value counts the number of milliseconds that I/O requests have waited -on this block device. If there are multiple I/O requests waiting, this -value will increase as the product of the number of milliseconds times the -number of requests waiting (see "read ticks" above for an example). diff --git a/trunk/Documentation/cpu-hotplug.txt b/trunk/Documentation/cpu-hotplug.txt deleted file mode 100644 index 08c5d04f3086..000000000000 --- a/trunk/Documentation/cpu-hotplug.txt +++ /dev/null @@ -1,357 +0,0 @@ - CPU hotplug Support in Linux(tm) Kernel - - Maintainers: - CPU Hotplug Core: - Rusty Russell - Srivatsa Vaddagiri - i386: - Zwane Mwaikambo - ppc64: - Nathan Lynch - Joel Schopp - ia64/x86_64: - Ashok Raj - -Authors: Ashok Raj -Lots of feedback: Nathan Lynch , - Joel Schopp - -Introduction - -Modern advances in system architectures have introduced advanced error -reporting and correction capabilities in processors. CPU architectures permit -partitioning support, where compute resources of a single CPU could be made -available to virtual machine environments. There are couple OEMS that -support NUMA hardware which are hot pluggable as well, where physical -node insertion and removal require support for CPU hotplug. - -Such advances require CPUs available to a kernel to be removed either for -provisioning reasons, or for RAS purposes to keep an offending CPU off -system execution path. Hence the need for CPU hotplug support in the -Linux kernel. - -A more novel use of CPU-hotplug support is its use today in suspend -resume support for SMP. Dual-core and HT support makes even -a laptop run SMP kernels which didn't support these methods. SMP support -for suspend/resume is a work in progress. - -General Stuff about CPU Hotplug --------------------------------- - -Command Line Switches ---------------------- -maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using - maxcpus=2 will only boot 2. You can choose to bring the - other cpus later online, read FAQ's for more info. - -additional_cpus=n [x86_64 only] use this to limit hotpluggable cpus. - This option sets - cpu_possible_map = cpu_present_map + additional_cpus - -CPU maps and such ------------------ -[More on cpumaps and primitive to manipulate, please check -include/linux/cpumask.h that has more descriptive text.] - -cpu_possible_map: Bitmap of possible CPUs that can ever be available in the -system. This is used to allocate some boot time memory for per_cpu variables -that aren't designed to grow/shrink as CPUs are made available or removed. -Once set during boot time discovery phase, the map is static, i.e no bits -are added or removed anytime. Trimming it accurately for your system needs -upfront can save some boot time memory. See below for how we use heuristics -in x86_64 case to keep this under check. - -cpu_online_map: Bitmap of all CPUs currently online. Its set in __cpu_up() -after a cpu is available for kernel scheduling and ready to receive -interrupts from devices. Its cleared when a cpu is brought down using -__cpu_disable(), before which all OS services including interrupts are -migrated to another target CPU. - -cpu_present_map: Bitmap of CPUs currently present in the system. Not all -of them may be online. When physical hotplug is processed by the relevant -subsystem (e.g ACPI) can change and new bit either be added or removed -from the map depending on the event is hot-add/hot-remove. There are currently -no locking rules as of now. Typical usage is to init topology during boot, -at which time hotplug is disabled. - -You really dont need to manipulate any of the system cpu maps. They should -be read-only for most use. When setting up per-cpu resources almost always use -cpu_possible_map/for_each_cpu() to iterate. - -Never use anything other than cpumask_t to represent bitmap of CPUs. - -#include - -for_each_cpu - Iterate over cpu_possible_map -for_each_online_cpu - Iterate over cpu_online_map -for_each_present_cpu - Iterate over cpu_present_map -for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask. - -#include -lock_cpu_hotplug() and unlock_cpu_hotplug(): - -The above calls are used to inhibit cpu hotplug operations. While holding the -cpucontrol mutex, cpu_online_map will not change. If you merely need to avoid -cpus going away, you could also use preempt_disable() and preempt_enable() -for those sections. Just remember the critical section cannot call any -function that can sleep or schedule this process away. The preempt_disable() -will work as long as stop_machine_run() is used to take a cpu down. - -CPU Hotplug - Frequently Asked Questions. - -Q: How to i enable my kernel to support CPU hotplug? -A: When doing make defconfig, Enable CPU hotplug support - - "Processor type and Features" -> Support for Hotpluggable CPUs - -Make sure that you have CONFIG_HOTPLUG, and CONFIG_SMP turned on as well. - -You would need to enable CONFIG_HOTPLUG_CPU for SMP suspend/resume support -as well. - -Q: What architectures support CPU hotplug? -A: As of 2.6.14, the following architectures support CPU hotplug. - -i386 (Intel), ppc, ppc64, parisc, s390, ia64 and x86_64 - -Q: How to test if hotplug is supported on the newly built kernel? -A: You should now notice an entry in sysfs. - -Check if sysfs is mounted, using the "mount" command. You should notice -an entry as shown below in the output. - -.... -none on /sys type sysfs (rw) -.... - -if this is not mounted, do the following. - -#mkdir /sysfs -#mount -t sysfs sys /sys - -now you should see entries for all present cpu, the following is an example -in a 8-way system. - -#pwd -#/sys/devices/system/cpu -#ls -l -total 0 -drwxr-xr-x 10 root root 0 Sep 19 07:44 . -drwxr-xr-x 13 root root 0 Sep 19 07:45 .. -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu0 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu1 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu2 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu3 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu4 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu5 -drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu6 -drwxr-xr-x 3 root root 0 Sep 19 07:48 cpu7 - -Under each directory you would find an "online" file which is the control -file to logically online/offline a processor. - -Q: Does hot-add/hot-remove refer to physical add/remove of cpus? -A: The usage of hot-add/remove may not be very consistently used in the code. -CONFIG_CPU_HOTPLUG enables logical online/offline capability in the kernel. -To support physical addition/removal, one would need some BIOS hooks and -the platform should have something like an attention button in PCI hotplug. -CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs. - -Q: How do i logically offline a CPU? -A: Do the following. - -#echo 0 > /sys/devices/system/cpu/cpuX/online - -once the logical offline is successful, check - -#cat /proc/interrupts - -you should now not see the CPU that you removed. Also online file will report -the state as 0 when a cpu if offline and 1 when its online. - -#To display the current cpu state. -#cat /sys/devices/system/cpu/cpuX/online - -Q: Why cant i remove CPU0 on some systems? -A: Some architectures may have some special dependency on a certain CPU. - -For e.g in IA64 platforms we have ability to sent platform interrupts to the -OS. a.k.a Corrected Platform Error Interrupts (CPEI). In current ACPI -specifications, we didn't have a way to change the target CPU. Hence if the -current ACPI version doesn't support such re-direction, we disable that CPU -by making it not-removable. - -In such cases you will also notice that the online file is missing under cpu0. - -Q: How do i find out if a particular CPU is not removable? -A: Depending on the implementation, some architectures may show this by the -absence of the "online" file. This is done if it can be determined ahead of -time that this CPU cannot be removed. - -In some situations, this can be a run time check, i.e if you try to remove the -last CPU, this will not be permitted. You can find such failures by -investigating the return value of the "echo" command. - -Q: What happens when a CPU is being logically offlined? -A: The following happen, listed in no particular order :-) - -- A notification is sent to in-kernel registered modules by sending an event - CPU_DOWN_PREPARE -- All process is migrated away from this outgoing CPU to a new CPU -- All interrupts targeted to this CPU is migrated to a new CPU -- timers/bottom half/task lets are also migrated to a new CPU -- Once all services are migrated, kernel calls an arch specific routine - __cpu_disable() to perform arch specific cleanup. -- Once this is successful, an event for successful cleanup is sent by an event - CPU_DEAD. - - "It is expected that each service cleans up when the CPU_DOWN_PREPARE - notifier is called, when CPU_DEAD is called its expected there is nothing - running on behalf of this CPU that was offlined" - -Q: If i have some kernel code that needs to be aware of CPU arrival and - departure, how to i arrange for proper notification? -A: This is what you would need in your kernel code to receive notifications. - - #include - static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) - { - unsigned int cpu = (unsigned long)hcpu; - - switch (action) { - case CPU_ONLINE: - foobar_online_action(cpu); - break; - case CPU_DEAD: - foobar_dead_action(cpu); - break; - } - return NOTIFY_OK; - } - - static struct notifier_block foobar_cpu_notifer = - { - .notifier_call = foobar_cpu_callback, - }; - - -In your init function, - - register_cpu_notifier(&foobar_cpu_notifier); - -You can fail PREPARE notifiers if something doesn't work to prepare resources. -This will stop the activity and send a following CANCELED event back. - -CPU_DEAD should not be failed, its just a goodness indication, but bad -things will happen if a notifier in path sent a BAD notify code. - -Q: I don't see my action being called for all CPUs already up and running? -A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined. - If you need to perform some action for each cpu already in the system, then - - for_each_online_cpu(i) { - foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i); - foobar_cpu_callback(&foobar-cpu_notifier, CPU_ONLINE, i); - } - -Q: If i would like to develop cpu hotplug support for a new architecture, - what do i need at a minimum? -A: The following are what is required for CPU hotplug infrastructure to work - correctly. - - - Make sure you have an entry in Kconfig to enable CONFIG_HOTPLUG_CPU - - __cpu_up() - Arch interface to bring up a CPU - - __cpu_disable() - Arch interface to shutdown a CPU, no more interrupts - can be handled by the kernel after the routine - returns. Including local APIC timers etc are - shutdown. - - __cpu_die() - This actually supposed to ensure death of the CPU. - Actually look at some example code in other arch - that implement CPU hotplug. The processor is taken - down from the idle() loop for that specific - architecture. __cpu_die() typically waits for some - per_cpu state to be set, to ensure the processor - dead routine is called to be sure positively. - -Q: I need to ensure that a particular cpu is not removed when there is some - work specific to this cpu is in progress. -A: First switch the current thread context to preferred cpu - - int my_func_on_cpu(int cpu) - { - cpumask_t saved_mask, new_mask = CPU_MASK_NONE; - int curr_cpu, err = 0; - - saved_mask = current->cpus_allowed; - cpu_set(cpu, new_mask); - err = set_cpus_allowed(current, new_mask); - - if (err) - return err; - - /* - * If we got scheduled out just after the return from - * set_cpus_allowed() before running the work, this ensures - * we stay locked. - */ - curr_cpu = get_cpu(); - - if (curr_cpu != cpu) { - err = -EAGAIN; - goto ret; - } else { - /* - * Do work : But cant sleep, since get_cpu() disables preempt - */ - } - ret: - put_cpu(); - set_cpus_allowed(current, saved_mask); - return err; - } - - -Q: How do we determine how many CPUs are available for hotplug. -A: There is no clear spec defined way from ACPI that can give us that - information today. Based on some input from Natalie of Unisys, - that the ACPI MADT (Multiple APIC Description Tables) marks those possible - CPUs in a system with disabled status. - - Andi implemented some simple heuristics that count the number of disabled - CPUs in MADT as hotpluggable CPUS. In the case there are no disabled CPUS - we assume 1/2 the number of CPUs currently present can be hotplugged. - - Caveat: Today's ACPI MADT can only provide 256 entries since the apicid field - in MADT is only 8 bits. - -User Space Notification - -Hotplug support for devices is common in Linux today. Its being used today to -support automatic configuration of network, usb and pci devices. A hotplug -event can be used to invoke an agent script to perform the configuration task. - -You can add /etc/hotplug/cpu.agent to handle hotplug notification user space -scripts. - - #!/bin/bash - # $Id: cpu.agent - # Kernel hotplug params include: - #ACTION=%s [online or offline] - #DEVPATH=%s - # - cd /etc/hotplug - . ./hotplug.functions - - case $ACTION in - online) - echo `date` ":cpu.agent" add cpu >> /tmp/hotplug.txt - ;; - offline) - echo `date` ":cpu.agent" remove cpu >>/tmp/hotplug.txt - ;; - *) - debug_mesg CPU $ACTION event not supported - exit 1 - ;; - esac diff --git a/trunk/Documentation/cpusets.txt b/trunk/Documentation/cpusets.txt index 9e49b1c35729..a09a8eb80665 100644 --- a/trunk/Documentation/cpusets.txt +++ b/trunk/Documentation/cpusets.txt @@ -14,10 +14,7 @@ CONTENTS: 1.1 What are cpusets ? 1.2 Why are cpusets needed ? 1.3 How are cpusets implemented ? - 1.4 What are exclusive cpusets ? - 1.5 What does notify_on_release do ? - 1.6 What is memory_pressure ? - 1.7 How do I use cpusets ? + 1.4 How do I use cpusets ? 2. Usage Examples and Syntax 2.1 Basic Usage 2.2 Adding/removing cpus @@ -52,6 +49,29 @@ its cpus_allowed vector, and the kernel page allocator will not allocate a page on a node that is not allowed in the requesting tasks mems_allowed vector. +If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct +ancestor or descendent, may share any of the same CPUs or Memory Nodes. +A cpuset that is cpu exclusive has a sched domain associated with it. +The sched domain consists of all cpus in the current cpuset that are not +part of any exclusive child cpusets. +This ensures that the scheduler load balacing code only balances +against the cpus that are in the sched domain as defined above and not +all of the cpus in the system. This removes any overhead due to +load balancing code trying to pull tasks outside of the cpu exclusive +cpuset only to be prevented by the tasks' cpus_allowed mask. + +A cpuset that is mem_exclusive restricts kernel allocations for +page, buffer and other data commonly shared by the kernel across +multiple users. All cpusets, whether mem_exclusive or not, restrict +allocations of memory for user space. This enables configuring a +system so that several independent jobs can share common kernel +data, such as file system pages, while isolating each jobs user +allocation in its own cpuset. To do this, construct a large +mem_exclusive cpuset to hold all the jobs, and construct child, +non-mem_exclusive cpusets for each individual job. Only a small +amount of typical kernel memory, such as requests from interrupt +handlers, is allowed to be taken outside even a mem_exclusive cpuset. + User level code may create and destroy cpusets by name in the cpuset virtual file system, manage the attributes and permissions of these cpusets and which CPUs and Memory Nodes are assigned to each cpuset, @@ -172,15 +192,9 @@ containing the following files describing that cpuset: - cpus: list of CPUs in that cpuset - mems: list of Memory Nodes in that cpuset - - memory_migrate flag: if set, move pages to cpusets nodes - cpu_exclusive flag: is cpu placement exclusive? - mem_exclusive flag: is memory placement exclusive? - tasks: list of tasks (by pid) attached to that cpuset - - notify_on_release flag: run /sbin/cpuset_release_agent on exit? - - memory_pressure: measure of how much paging pressure in cpuset - -In addition, the root cpuset only has the following file: - - memory_pressure_enabled flag: compute memory_pressure? New cpusets are created using the mkdir system call or shell command. The properties of a cpuset, such as its flags, allowed @@ -214,108 +228,7 @@ exclusive cpuset. Also, the use of a Linux virtual file system (vfs) to represent the cpuset hierarchy provides for a familiar permission and name space for cpusets, with a minimum of additional kernel code. - -1.4 What are exclusive cpusets ? --------------------------------- - -If a cpuset is cpu or mem exclusive, no other cpuset, other than -a direct ancestor or descendent, may share any of the same CPUs or -Memory Nodes. - -A cpuset that is cpu_exclusive has a scheduler (sched) domain -associated with it. The sched domain consists of all CPUs in the -current cpuset that are not part of any exclusive child cpusets. -This ensures that the scheduler load balancing code only balances -against the CPUs that are in the sched domain as defined above and -not all of the CPUs in the system. This removes any overhead due to -load balancing code trying to pull tasks outside of the cpu_exclusive -cpuset only to be prevented by the tasks' cpus_allowed mask. - -A cpuset that is mem_exclusive restricts kernel allocations for -page, buffer and other data commonly shared by the kernel across -multiple users. All cpusets, whether mem_exclusive or not, restrict -allocations of memory for user space. This enables configuring a -system so that several independent jobs can share common kernel data, -such as file system pages, while isolating each jobs user allocation in -its own cpuset. To do this, construct a large mem_exclusive cpuset to -hold all the jobs, and construct child, non-mem_exclusive cpusets for -each individual job. Only a small amount of typical kernel memory, -such as requests from interrupt handlers, is allowed to be taken -outside even a mem_exclusive cpuset. - - -1.5 What does notify_on_release do ? ------------------------------------- - -If the notify_on_release flag is enabled (1) in a cpuset, then whenever -the last task in the cpuset leaves (exits or attaches to some other -cpuset) and the last child cpuset of that cpuset is removed, then -the kernel runs the command /sbin/cpuset_release_agent, supplying the -pathname (relative to the mount point of the cpuset file system) of the -abandoned cpuset. This enables automatic removal of abandoned cpusets. -The default value of notify_on_release in the root cpuset at system -boot is disabled (0). The default value of other cpusets at creation -is the current value of their parents notify_on_release setting. - - -1.6 What is memory_pressure ? ------------------------------ -The memory_pressure of a cpuset provides a simple per-cpuset metric -of the rate that the tasks in a cpuset are attempting to free up in -use memory on the nodes of the cpuset to satisfy additional memory -requests. - -This enables batch managers monitoring jobs running in dedicated -cpusets to efficiently detect what level of memory pressure that job -is causing. - -This is useful both on tightly managed systems running a wide mix of -submitted jobs, which may choose to terminate or re-prioritize jobs that -are trying to use more memory than allowed on the nodes assigned them, -and with tightly coupled, long running, massively parallel scientific -computing jobs that will dramatically fail to meet required performance -goals if they start to use more memory than allowed to them. - -This mechanism provides a very economical way for the batch manager -to monitor a cpuset for signs of memory pressure. It's up to the -batch manager or other user code to decide what to do about it and -take action. - -==> Unless this feature is enabled by writing "1" to the special file - /dev/cpuset/memory_pressure_enabled, the hook in the rebalance - code of __alloc_pages() for this metric reduces to simply noticing - that the cpuset_memory_pressure_enabled flag is zero. So only - systems that enable this feature will compute the metric. - -Why a per-cpuset, running average: - - Because this meter is per-cpuset, rather than per-task or mm, - the system load imposed by a batch scheduler monitoring this - metric is sharply reduced on large systems, because a scan of - the tasklist can be avoided on each set of queries. - - Because this meter is a running average, instead of an accumulating - counter, a batch scheduler can detect memory pressure with a - single read, instead of having to read and accumulate results - for a period of time. - - Because this meter is per-cpuset rather than per-task or mm, - the batch scheduler can obtain the key information, memory - pressure in a cpuset, with a single read, rather than having to - query and accumulate results over all the (dynamically changing) - set of tasks in the cpuset. - -A per-cpuset simple digital filter (requires a spinlock and 3 words -of data per-cpuset) is kept, and updated by any task attached to that -cpuset, if it enters the synchronous (direct) page reclaim code. - -A per-cpuset file provides an integer number representing the recent -(half-life of 10 seconds) rate of direct page reclaims caused by -the tasks in the cpuset, in units of reclaims attempted per second, -times 1000. - - -1.7 How do I use cpusets ? +1.4 How do I use cpusets ? -------------------------- In order to minimize the impact of cpusets on critical kernel @@ -364,30 +277,6 @@ rewritten to the 'tasks' file of its cpuset. This is done to avoid impacting the scheduler code in the kernel with a check for changes in a tasks processor placement. -Normally, once a page is allocated (given a physical page -of main memory) then that page stays on whatever node it -was allocated, so long as it remains allocated, even if the -cpusets memory placement policy 'mems' subsequently changes. -If the cpuset flag file 'memory_migrate' is set true, then when -tasks are attached to that cpuset, any pages that task had -allocated to it on nodes in its previous cpuset are migrated -to the tasks new cpuset. Depending on the implementation, -this migration may either be done by swapping the page out, -so that the next time the page is referenced, it will be paged -into the tasks new cpuset, usually on the node where it was -referenced, or this migration may be done by directly copying -the pages from the tasks previous cpuset to the new cpuset, -where possible to the same node, relative to the new cpuset, -as the node that held the page, relative to the old cpuset. -Also if 'memory_migrate' is set true, then if that cpusets -'mems' file is modified, pages allocated to tasks in that -cpuset, that were on nodes in the previous setting of 'mems', -will be moved to nodes in the new setting of 'mems.' Again, -depending on the implementation, this might be done by swapping, -or by direct copying. In either case, pages that were not in -the tasks prior cpuset, or in the cpusets prior 'mems' setting, -will not be moved. - There is an exception to the above. If hotplug functionality is used to remove all the CPUs that are currently assigned to a cpuset, then the kernel will automatically update the cpus_allowed of all diff --git a/trunk/Documentation/fb/cyblafb/bugs b/trunk/Documentation/fb/cyblafb/bugs index 9443a6d72cdd..f90cc66ea919 100644 --- a/trunk/Documentation/fb/cyblafb/bugs +++ b/trunk/Documentation/fb/cyblafb/bugs @@ -11,3 +11,4 @@ Untested features All LCD stuff is untested. If it worked in tridentfb, it should work in cyblafb. Please test and report the results to Knut_Petersen@t-online.de. + diff --git a/trunk/Documentation/fb/cyblafb/fb.modes b/trunk/Documentation/fb/cyblafb/fb.modes index fe0e5223ba86..cf4351fc32ff 100644 --- a/trunk/Documentation/fb/cyblafb/fb.modes +++ b/trunk/Documentation/fb/cyblafb/fb.modes @@ -14,141 +14,142 @@ # mode "640x480-50" - geometry 640 480 2048 4096 8 + geometry 640 480 640 3756 8 timings 47619 4294967256 24 17 0 216 3 endmode mode "640x480-60" - geometry 640 480 2048 4096 8 + geometry 640 480 640 3756 8 timings 39682 4294967256 24 17 0 216 3 endmode mode "640x480-70" - geometry 640 480 2048 4096 8 + geometry 640 480 640 3756 8 timings 34013 4294967256 24 17 0 216 3 endmode mode "640x480-72" - geometry 640 480 2048 4096 8 + geometry 640 480 640 3756 8 timings 33068 4294967256 24 17 0 216 3 endmode mode "640x480-75" - geometry 640 480 2048 4096 8 + geometry 640 480 640 3756 8 timings 31746 4294967256 24 17 0 216 3 endmode mode "640x480-80" - geometry 640 480 2048 4096 8 + geometry 640 480 640 3756 8 timings 29761 4294967256 24 17 0 216 3 endmode mode "640x480-85" - geometry 640 480 2048 4096 8 + geometry 640 480 640 3756 8 timings 28011 4294967256 24 17 0 216 3 endmode mode "800x600-50" - geometry 800 600 2048 4096 8 + geometry 800 600 800 3221 8 timings 30303 96 24 14 0 136 11 endmode mode "800x600-60" - geometry 800 600 2048 4096 8 + geometry 800 600 800 3221 8 timings 25252 96 24 14 0 136 11 endmode mode "800x600-70" - geometry 800 600 2048 4096 8 + geometry 800 600 800 3221 8 timings 21645 96 24 14 0 136 11 endmode mode "800x600-72" - geometry 800 600 2048 4096 8 + geometry 800 600 800 3221 8 timings 21043 96 24 14 0 136 11 endmode mode "800x600-75" - geometry 800 600 2048 4096 8 + geometry 800 600 800 3221 8 timings 20202 96 24 14 0 136 11 endmode mode "800x600-80" - geometry 800 600 2048 4096 8 + geometry 800 600 800 3221 8 timings 18939 96 24 14 0 136 11 endmode mode "800x600-85" - geometry 800 600 2048 4096 8 + geometry 800 600 800 3221 8 timings 17825 96 24 14 0 136 11 endmode mode "1024x768-50" - geometry 1024 768 2048 4096 8 + geometry 1024 768 1024 2815 8 timings 19054 144 24 29 0 120 3 endmode mode "1024x768-60" - geometry 1024 768 2048 4096 8 + geometry 1024 768 1024 2815 8 timings 15880 144 24 29 0 120 3 endmode mode "1024x768-70" - geometry 1024 768 2048 4096 8 + geometry 1024 768 1024 2815 8 timings 13610 144 24 29 0 120 3 endmode mode "1024x768-72" - geometry 1024 768 2048 4096 8 + geometry 1024 768 1024 2815 8 timings 13232 144 24 29 0 120 3 endmode mode "1024x768-75" - geometry 1024 768 2048 4096 8 + geometry 1024 768 1024 2815 8 timings 12703 144 24 29 0 120 3 endmode mode "1024x768-80" - geometry 1024 768 2048 4096 8 + geometry 1024 768 1024 2815 8 timings 11910 144 24 29 0 120 3 endmode mode "1024x768-85" - geometry 1024 768 2048 4096 8 + geometry 1024 768 1024 2815 8 timings 11209 144 24 29 0 120 3 endmode mode "1280x1024-50" - geometry 1280 1024 2048 4096 8 + geometry 1280 1024 1280 2662 8 timings 11114 232 16 39 0 160 3 endmode mode "1280x1024-60" - geometry 1280 1024 2048 4096 8 + geometry 1280 1024 1280 2662 8 timings 9262 232 16 39 0 160 3 endmode mode "1280x1024-70" - geometry 1280 1024 2048 4096 8 + geometry 1280 1024 1280 2662 8 timings 7939 232 16 39 0 160 3 endmode mode "1280x1024-72" - geometry 1280 1024 2048 4096 8 + geometry 1280 1024 1280 2662 8 timings 7719 232 16 39 0 160 3 endmode mode "1280x1024-75" - geometry 1280 1024 2048 4096 8 + geometry 1280 1024 1280 2662 8 timings 7410 232 16 39 0 160 3 endmode mode "1280x1024-80" - geometry 1280 1024 2048 4096 8 + geometry 1280 1024 1280 2662 8 timings 6946 232 16 39 0 160 3 endmode mode "1280x1024-85" - geometry 1280 1024 2048 4096 8 + geometry 1280 1024 1280 2662 8 timings 6538 232 16 39 0 160 3 endmode + diff --git a/trunk/Documentation/fb/cyblafb/performance b/trunk/Documentation/fb/cyblafb/performance index 8d15d5dfc6b3..eb4e47a9cea6 100644 --- a/trunk/Documentation/fb/cyblafb/performance +++ b/trunk/Documentation/fb/cyblafb/performance @@ -77,3 +77,4 @@ patch that speeds up kernel bitblitting a lot ( > 20%). | | | | | | | | | | +-----------+-----------------+-----------------+-----------------+ + diff --git a/trunk/Documentation/fb/cyblafb/todo b/trunk/Documentation/fb/cyblafb/todo index c5f6d0eae545..80fb2f89b6c1 100644 --- a/trunk/Documentation/fb/cyblafb/todo +++ b/trunk/Documentation/fb/cyblafb/todo @@ -22,10 +22,11 @@ accelerated color blitting Who needs it? The console driver does use color everything else is done using color expanding blitting of 1bpp character bitmaps. +xpanning Who needs it? + ioctls Who needs it? -TV-out Will be done later. Use "vga= " at boot time - to set a suitable video mode. +TV-out Will be done later ??? Feel free to contact me if you have any feature requests diff --git a/trunk/Documentation/fb/cyblafb/usage b/trunk/Documentation/fb/cyblafb/usage index a39bb3d402a2..e627c8f54211 100644 --- a/trunk/Documentation/fb/cyblafb/usage +++ b/trunk/Documentation/fb/cyblafb/usage @@ -40,16 +40,6 @@ Selecting Modes None of the modes possible to select as startup modes are affected by the problems described at the end of the next subsection. - For all startup modes cyblafb chooses a virtual x resolution of 2048, - the only exception is mode 1280x1024 in combination with 32 bpp. This - allows ywrap scrolling for all those modes if rotation is 0 or 2, and - also fast scrolling if rotation is 1 or 3. The default virtual y reso- - lution is 4096 for bpp == 8, 2048 for bpp==16 and 1024 for bpp == 32, - again with the only exception of 1280x1024 at 32 bpp. - - Please do set your video memory size to 8 Mb in the Bios setup. Other - values will work, but performace is decreased for a lot of modes. - Mode changes using fbset ======================== @@ -64,26 +54,20 @@ Selecting Modes - if a flat panel is found, cyblafb does not allow you to program a resolution higher than the physical resolution of the flat panel monitor + - cyblafb does not allow xres to differ from xres_virtual - cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp and (currently) 24 bit modes use a doubled vclk internally, the dotclock limit as seen by fbset is 115 MHz for those modes and 230 MHz for 8 and 16 bpp modes. - - cyblafb will allow you to select very high resolutions as - long as the hardware can be programmed to these modes. The - documented limit 1600x1200 is not enforced, but don't expect - perfect signal quality. - Any request that violates the rules given above will be either changed - to something the hardware supports or an error value will be returned. + Any request that violates the rules given above will be ignored and + fbset will return an error. If you program a virtual y resolution higher than the hardware limit, cyblafb will silently decrease that value to the highest possible - value. The same is true for a virtual x resolution that is not - supported by the hardware. Cyblafb tries to adapt vyres first because - vxres decides if ywrap scrolling is possible or not. + value. - Attempts to disable acceleration are ignored, I believe that this is - safe. + Attempts to disable acceleration are ignored. Some video modes that should work do not work as expected. If you use the standard fb.modes, fbset 640x480-60 will program that mode, but @@ -145,6 +129,10 @@ mode 640x480 or 800x600 or 1024x768 or 1280x1024 verbosity 0 is the default, increase to at least 2 for every bug report! +vesafb allows cyblafb to be loaded after vesafb has been + loaded. See sections "Module unloading ...". + + Development hints ================= @@ -207,7 +195,7 @@ a graphics mode. After booting, load cyblafb without any mode and bpp parameter and assign cyblafb to individual ttys using con2fb, e.g.: - modprobe cyblafb + modprobe cyblafb vesafb=1 con2fb /dev/fb1 /dev/tty1 Unloading cyblafb works without problems after you assign vesafb to all @@ -215,3 +203,4 @@ ttys again, e.g.: con2fb /dev/fb0 /dev/tty1 rmmod cyblafb + diff --git a/trunk/Documentation/fb/cyblafb/whatsnew b/trunk/Documentation/fb/cyblafb/whatsnew deleted file mode 100644 index 76c07a26e044..000000000000 --- a/trunk/Documentation/fb/cyblafb/whatsnew +++ /dev/null @@ -1,29 +0,0 @@ -0.62 -==== - - - the vesafb parameter has been removed as I decided to allow the - feature without any special parameter. - - - Cyblafb does not use the vga style of panning any longer, now the - "right view" register in the graphics engine IO space is used. Without - that change it was impossible to use all available memory, and without - access to all available memory it is impossible to ywrap. - - - The imageblit function now uses hardware acceleration for all font - widths. Hardware blitting across pixel column 2048 is broken in the - cyberblade/i1 graphics core, but we work around that hardware bug. - - - modes with vxres != xres are supported now. - - - ywrap scrolling is supported now and the default. This is a big - performance gain. - - - default video modes use vyres > yres and vxres > xres to allow - almost optimal scrolling speed for normal and rotated screens - - - some features mainly usefull for debugging the upper layers of the - framebuffer system have been added, have a look at the code - - - fixed: Oops after unloading cyblafb when reading /proc/io* - - - we work around some bugs of the higher framebuffer layers. diff --git a/trunk/Documentation/filesystems/ext3.txt b/trunk/Documentation/filesystems/ext3.txt index 22e4040564d5..9840d5b8d5b9 100644 --- a/trunk/Documentation/filesystems/ext3.txt +++ b/trunk/Documentation/filesystems/ext3.txt @@ -22,11 +22,6 @@ journal=inum When a journal already exists, this option is the inode which will represent the ext3 file system's journal file. -journal_dev=devnum When the external journal device's major/minor numbers - have changed, this option allows to specify the new - journal location. The journal device is identified - through its new major/minor numbers encoded in devnum. - noload Don't load the journal on mounting. data=journal All data are committed into the journal prior diff --git a/trunk/Documentation/filesystems/proc.txt b/trunk/Documentation/filesystems/proc.txt index a4dcf42c2fd9..d4773565ea2f 100644 --- a/trunk/Documentation/filesystems/proc.txt +++ b/trunk/Documentation/filesystems/proc.txt @@ -1302,23 +1302,6 @@ VM has token based thrashing control mechanism and uses the token to prevent unnecessary page faults in thrashing situation. The unit of the value is second. The value would be useful to tune thrashing behavior. -drop_caches ------------ - -Writing to this will cause the kernel to drop clean caches, dentries and -inodes from memory, causing that memory to become free. - -To free pagecache: - echo 1 > /proc/sys/vm/drop_caches -To free dentries and inodes: - echo 2 > /proc/sys/vm/drop_caches -To free pagecache, dentries and inodes: - echo 3 > /proc/sys/vm/drop_caches - -As this is a non-destructive operation and dirty objects are not freeable, the -user should run `sync' first. - - 2.5 /proc/sys/dev - Device specific parameters ---------------------------------------------- diff --git a/trunk/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/trunk/Documentation/filesystems/ramfs-rootfs-initramfs.txt index 60ab61e54e8a..b3404a032596 100644 --- a/trunk/Documentation/filesystems/ramfs-rootfs-initramfs.txt +++ b/trunk/Documentation/filesystems/ramfs-rootfs-initramfs.txt @@ -143,26 +143,12 @@ as the following example: dir /mnt 755 0 0 file /init initramfs/init.sh 755 0 0 -Run "usr/gen_init_cpio" (after the kernel build) to get a usage message -documenting the above file format. - One advantage of the text file is that root access is not required to set permissions or create device nodes in the new archive. (Note that those two example "file" entries expect to find files named "init.sh" and "busybox" in a directory called "initramfs", under the linux-2.6.* directory. See Documentation/early-userspace/README for more details.) -The kernel does not depend on external cpio tools, gen_init_cpio is created -from usr/gen_init_cpio.c which is entirely self-contained, and the kernel's -boot-time extractor is also (obviously) self-contained. However, if you _do_ -happen to have cpio installed, the following command line can extract the -generated cpio image back into its component files: - - cpio -i -d -H newc -F initramfs_data.cpio --no-absolute-filenames - -Contents of initramfs: ----------------------- - If you don't already understand what shared libraries, devices, and paths you need to get a minimal root filesystem up and running, here are some references: @@ -175,69 +161,13 @@ designed to be a tiny C library to statically link early userspace code against, along with some related utilities. It is BSD licensed. I use uClibc (http://www.uclibc.org) and busybox (http://www.busybox.net) -myself. These are LGPL and GPL, respectively. (A self-contained initramfs -package is planned for the busybox 1.2 release.) +myself. These are LGPL and GPL, respectively. In theory you could use glibc, but that's not well suited for small embedded uses like this. (A "hello world" program statically linked against glibc is over 400k. With uClibc it's 7k. Also note that glibc dlopens libnss to do name lookups, even when otherwise statically linked.) -Why cpio rather than tar? -------------------------- - -This decision was made back in December, 2001. The discussion started here: - - http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1538.html - -And spawned a second thread (specifically on tar vs cpio), starting here: - - http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1587.html - -The quick and dirty summary version (which is no substitute for reading -the above threads) is: - -1) cpio is a standard. It's decades old (from the AT&T days), and already - widely used on Linux (inside RPM, Red Hat's device driver disks). Here's - a Linux Journal article about it from 1996: - - http://www.linuxjournal.com/article/1213 - - It's not as popular as tar because the traditional cpio command line tools - require _truly_hideous_ command line arguments. But that says nothing - either way about the archive format, and there are alternative tools, - such as: - - http://freshmeat.net/projects/afio/ - -2) The cpio archive format chosen by the kernel is simpler and cleaner (and - thus easier to create and parse) than any of the (literally dozens of) - various tar archive formats. The complete initramfs archive format is - explained in buffer-format.txt, created in usr/gen_init_cpio.c, and - extracted in init/initramfs.c. All three together come to less than 26k - total of human-readable text. - -3) The GNU project standardizing on tar is approximately as relevant as - Windows standardizing on zip. Linux is not part of either, and is free - to make its own technical decisions. - -4) Since this is a kernel internal format, it could easily have been - something brand new. The kernel provides its own tools to create and - extract this format anyway. Using an existing standard was preferable, - but not essential. - -5) Al Viro made the decision (quote: "tar is ugly as hell and not going to be - supported on the kernel side"): - - http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1540.html - - explained his reasoning: - - http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1550.html - http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1638.html - - and, most importantly, designed and implemented the initramfs code. - Future directions: ------------------ diff --git a/trunk/Documentation/filesystems/relayfs.txt b/trunk/Documentation/filesystems/relayfs.txt index 5832377b7340..d803abed29f0 100644 --- a/trunk/Documentation/filesystems/relayfs.txt +++ b/trunk/Documentation/filesystems/relayfs.txt @@ -44,41 +44,30 @@ relayfs can operate in a mode where it will overwrite data not yet collected by userspace, and not wait for it to consume it. relayfs itself does not provide for communication of such data between -userspace and kernel, allowing the kernel side to remain simple and -not impose a single interface on userspace. It does provide a set of -examples and a separate helper though, described below. - -klog and relay-apps example code -================================ - -relayfs itself is ready to use, but to make things easier, a couple -simple utility functions and a set of examples are provided. - -The relay-apps example tarball, available on the relayfs sourceforge -site, contains a set of self-contained examples, each consisting of a -pair of .c files containing boilerplate code for each of the user and -kernel sides of a relayfs application; combined these two sets of -boilerplate code provide glue to easily stream data to disk, without -having to bother with mundane housekeeping chores. - -The 'klog debugging functions' patch (klog.patch in the relay-apps -tarball) provides a couple of high-level logging functions to the -kernel which allow writing formatted text or raw data to a channel, -regardless of whether a channel to write into exists or not, or -whether relayfs is compiled into the kernel or is configured as a -module. These functions allow you to put unconditional 'trace' -statements anywhere in the kernel or kernel modules; only when there -is a 'klog handler' registered will data actually be logged (see the -klog and kleak examples for details). - -It is of course possible to use relayfs from scratch i.e. without -using any of the relay-apps example code or klog, but you'll have to -implement communication between userspace and kernel, allowing both to -convey the state of buffers (full, empty, amount of padding). - -klog and the relay-apps examples can be found in the relay-apps -tarball on http://relayfs.sourceforge.net +userspace and kernel, allowing the kernel side to remain simple and not +impose a single interface on userspace. It does provide a separate +helper though, described below. +klog, relay-app & librelay +========================== + +relayfs itself is ready to use, but to make things easier, two +additional systems are provided. klog is a simple wrapper to make +writing formatted text or raw data to a channel simpler, regardless of +whether a channel to write into exists or not, or whether relayfs is +compiled into the kernel or is configured as a module. relay-app is +the kernel counterpart of userspace librelay.c, combined these two +files provide glue to easily stream data to disk, without having to +bother with housekeeping. klog and relay-app can be used together, +with klog providing high-level logging functions to the kernel and +relay-app taking care of kernel-user control and disk-logging chores. + +It is possible to use relayfs without relay-app & librelay, but you'll +have to implement communication between userspace and kernel, allowing +both to convey the state of buffers (full, empty, amount of padding). + +klog, relay-app and librelay can be found in the relay-apps tarball on +http://relayfs.sourceforge.net The relayfs user space API ========================== @@ -136,8 +125,6 @@ Here's a summary of the API relayfs provides to in-kernel clients: relay_reset(chan) relayfs_create_dir(name, parent) relayfs_remove_dir(dentry) - relayfs_create_file(name, parent, mode, fops, data) - relayfs_remove_file(dentry) channel management typically called on instigation of userspace: @@ -154,8 +141,6 @@ Here's a summary of the API relayfs provides to in-kernel clients: subbuf_start(buf, subbuf, prev_subbuf, prev_padding) buf_mapped(buf, filp) buf_unmapped(buf, filp) - create_buf_file(filename, parent, mode, buf, is_global) - remove_buf_file(dentry) helper functions: @@ -335,71 +320,6 @@ forces a sub-buffer switch on all the channel buffers, and can be used to finalize and process the last sub-buffers before the channel is closed. -Creating non-relay files ------------------------- - -relay_open() automatically creates files in the relayfs filesystem to -represent the per-cpu kernel buffers; it's often useful for -applications to be able to create their own files alongside the relay -files in the relayfs filesystem as well e.g. 'control' files much like -those created in /proc or debugfs for similar purposes, used to -communicate control information between the kernel and user sides of a -relayfs application. For this purpose the relayfs_create_file() and -relayfs_remove_file() API functions exist. For relayfs_create_file(), -the caller passes in a set of user-defined file operations to be used -for the file and an optional void * to a user-specified data item, -which will be accessible via inode->u.generic_ip (see the relay-apps -tarball for examples). The file_operations are a required parameter -to relayfs_create_file() and thus the semantics of these files are -completely defined by the caller. - -See the relay-apps tarball at http://relayfs.sourceforge.net for -examples of how these non-relay files are meant to be used. - -Creating relay files in other filesystems ------------------------------------------ - -By default of course, relay_open() creates relay files in the relayfs -filesystem. Because relay_file_operations is exported, however, it's -also possible to create and use relay files in other pseudo-filesytems -such as debugfs. - -For this purpose, two callback functions are provided, -create_buf_file() and remove_buf_file(). create_buf_file() is called -once for each per-cpu buffer from relay_open() to allow the client to -create a file to be used to represent the corresponding buffer; if -this callback is not defined, the default implementation will create -and return a file in the relayfs filesystem to represent the buffer. -The callback should return the dentry of the file created to represent -the relay buffer. Note that the parent directory passed to -relay_open() (and passed along to the callback), if specified, must -exist in the same filesystem the new relay file is created in. If -create_buf_file() is defined, remove_buf_file() must also be defined; -it's responsible for deleting the file(s) created in create_buf_file() -and is called during relay_close(). - -The create_buf_file() implementation can also be defined in such a way -as to allow the creation of a single 'global' buffer instead of the -default per-cpu set. This can be useful for applications interested -mainly in seeing the relative ordering of system-wide events without -the need to bother with saving explicit timestamps for the purpose of -merging/sorting per-cpu files in a postprocessing step. - -To have relay_open() create a global buffer, the create_buf_file() -implementation should set the value of the is_global outparam to a -non-zero value in addition to creating the file that will be used to -represent the single buffer. In the case of a global buffer, -create_buf_file() and remove_buf_file() will be called only once. The -normal channel-writing functions e.g. relay_write() can still be used -- writes from any cpu will transparently end up in the global buffer - -but since it is a global buffer, callers should make sure they use the -proper locking for such a buffer, either by wrapping writes in a -spinlock, or by copying a write function from relayfs_fs.h and -creating a local version that internally does the proper locking. - -See the 'exported-relayfile' examples in the relay-apps tarball for -examples of creating and using relay files in debugfs. - Misc ---- diff --git a/trunk/Documentation/keys-request-key.txt b/trunk/Documentation/keys-request-key.txt index 22488d791168..5f2b9c5edbb5 100644 --- a/trunk/Documentation/keys-request-key.txt +++ b/trunk/Documentation/keys-request-key.txt @@ -56,12 +56,10 @@ A request proceeds in the following manner: (4) request_key() then forks and executes /sbin/request-key with a new session keyring that contains a link to auth key V. - (5) /sbin/request-key assumes the authority associated with key U. - - (6) /sbin/request-key execs an appropriate program to perform the actual + (5) /sbin/request-key execs an appropriate program to perform the actual instantiation. - (7) The program may want to access another key from A's context (say a + (6) The program may want to access another key from A's context (say a Kerberos TGT key). It just requests the appropriate key, and the keyring search notes that the session keyring has auth key V in its bottom level. @@ -69,19 +67,19 @@ A request proceeds in the following manner: UID, GID, groups and security info of process A as if it was process A, and come up with key W. - (8) The program then does what it must to get the data with which to + (7) The program then does what it must to get the data with which to instantiate key U, using key W as a reference (perhaps it contacts a Kerberos server using the TGT) and then instantiates key U. - (9) Upon instantiating key U, auth key V is automatically revoked so that it + (8) Upon instantiating key U, auth key V is automatically revoked so that it may not be used again. -(10) The program then exits 0 and request_key() deletes key V and returns key + (9) The program then exits 0 and request_key() deletes key V and returns key U to the caller. -This also extends further. If key W (step 7 above) didn't exist, key W would be -created uninstantiated, another auth key (X) would be created (as per step 3) -and another copy of /sbin/request-key spawned (as per step 4); but the context +This also extends further. If key W (step 5 above) didn't exist, key W would be +created uninstantiated, another auth key (X) would be created [as per step 3] +and another copy of /sbin/request-key spawned [as per step 4]; but the context specified by auth key X will still be process A, as it was in auth key V. This is because process A's keyrings can't simply be attached to @@ -140,8 +138,8 @@ until one succeeds: (3) The process's session keyring is searched. - (4) If the process has assumed the authority associated with a request_key() - authorisation key then: + (4) If the process has a request_key() authorisation key in its session + keyring then: (a) If extant, the calling process's thread keyring is searched. diff --git a/trunk/Documentation/keys.txt b/trunk/Documentation/keys.txt index aaa01b0e3ee9..6304db59bfe4 100644 --- a/trunk/Documentation/keys.txt +++ b/trunk/Documentation/keys.txt @@ -308,8 +308,6 @@ process making the call: KEY_SPEC_USER_KEYRING -4 UID-specific keyring KEY_SPEC_USER_SESSION_KEYRING -5 UID-session keyring KEY_SPEC_GROUP_KEYRING -6 GID-specific keyring - KEY_SPEC_REQKEY_AUTH_KEY -7 assumed request_key() - authorisation key The main syscalls are: @@ -500,11 +498,7 @@ The keyctl syscall functions are: keyring is full, error ENFILE will result. The link procedure checks the nesting of the keyrings, returning ELOOP if - it appears too deep or EDEADLK if the link would introduce a cycle. - - Any links within the keyring to keys that match the new key in terms of - type and description will be discarded from the keyring as the new one is - added. + it appears to deep or EDEADLK if the link would introduce a cycle. (*) Unlink a key or keyring from another keyring: @@ -634,41 +628,6 @@ The keyctl syscall functions are: there is one, otherwise the user default session keyring. - (*) Set the timeout on a key. - - long keyctl(KEYCTL_SET_TIMEOUT, key_serial_t key, unsigned timeout); - - This sets or clears the timeout on a key. The timeout can be 0 to clear - the timeout or a number of seconds to set the expiry time that far into - the future. - - The process must have attribute modification access on a key to set its - timeout. Timeouts may not be set with this function on negative, revoked - or expired keys. - - - (*) Assume the authority granted to instantiate a key - - long keyctl(KEYCTL_ASSUME_AUTHORITY, key_serial_t key); - - This assumes or divests the authority required to instantiate the - specified key. Authority can only be assumed if the thread has the - authorisation key associated with the specified key in its keyrings - somewhere. - - Once authority is assumed, searches for keys will also search the - requester's keyrings using the requester's security label, UID, GID and - groups. - - If the requested authority is unavailable, error EPERM will be returned, - likewise if the authority has been revoked because the target key is - already instantiated. - - If the specified key is 0, then any assumed authority will be divested. - - The assumed authorititive key is inherited across fork and exec. - - =============== KERNEL SERVICES =============== diff --git a/trunk/Documentation/networking/bonding.txt b/trunk/Documentation/networking/bonding.txt index 8d8b4e5ea184..b0fe41da007b 100644 --- a/trunk/Documentation/networking/bonding.txt +++ b/trunk/Documentation/networking/bonding.txt @@ -945,6 +945,7 @@ bond0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 collisions:0 txqueuelen:0 eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 + inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0 UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0 TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0 @@ -952,6 +953,7 @@ eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 Interrupt:10 Base address:0x1080 eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 + inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0 UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0 TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0 diff --git a/trunk/Documentation/sysctl/vm.txt b/trunk/Documentation/sysctl/vm.txt index 6910c0136f8d..2f1aae32a5d9 100644 --- a/trunk/Documentation/sysctl/vm.txt +++ b/trunk/Documentation/sysctl/vm.txt @@ -26,13 +26,12 @@ Currently, these files are in /proc/sys/vm: - min_free_kbytes - laptop_mode - block_dump -- drop-caches ============================================================== dirty_ratio, dirty_background_ratio, dirty_expire_centisecs, dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode, -block_dump, swap_token_timeout, drop-caches: +block_dump, swap_token_timeout: See Documentation/filesystems/proc.txt @@ -103,20 +102,3 @@ This is used to force the Linux VM to keep a minimum number of kilobytes free. The VM uses this number to compute a pages_min value for each lowmem zone in the system. Each lowmem zone gets a number of reserved free pages based proportionally on its size. - -============================================================== - -percpu_pagelist_fraction - -This is the fraction of pages at most (high mark pcp->high) in each zone that -are allocated for each per cpu page list. The min value for this is 8. It -means that we don't allow more than 1/8th of pages in each zone to be -allocated in any single per_cpu_pagelist. This entry only changes the value -of hot per cpu pagelists. User can specify a number like 100 to allocate -1/100th of each zone to each per cpu page list. - -The batch value of each per cpu pagelist is also updated as a result. It is -set to pcp->high/4. The upper limit of batch is (PAGE_SHIFT * 8) - -The initial value is zero. Kernel does not use this value at boot time to set -the high water marks for each per cpu page list. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 270e28c0506a..7e780906d34c 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -927,6 +927,7 @@ S: Maintained FARSYNC SYNCHRONOUS DRIVER P: Kevin Curtis M: kevin.curtis@farsite.co.uk +M: kevin.curtis@farsite.co.uk W: http://www.farsite.co.uk/ S: Supported @@ -1697,6 +1698,7 @@ S: Maintained MARVELL MV64340 ETHERNET DRIVER P: Manish Lachwani +M: Manish_Lachwani@pmc-sierra.com L: linux-mips@linux-mips.org L: netdev@vger.kernel.org S: Supported diff --git a/trunk/README b/trunk/README index cd5e2eb6213b..61c4f7429233 100644 --- a/trunk/README +++ b/trunk/README @@ -183,8 +183,11 @@ CONFIGURING the kernel: COMPILING the kernel: - - Make sure you have at least gcc 3.2 available. - For more information, refer to Documentation/Changes. + - Make sure you have gcc 2.95.3 available. + gcc 2.91.66 (egcs-1.1.2), and gcc 2.7.2.3 are known to miscompile + some parts of the kernel, and are *no longer supported*. + Also remember to upgrade your binutils package (for as/ld/nm and company) + if necessary. For more information, refer to Documentation/Changes. Please note that you can still run a.out user programs with this kernel. diff --git a/trunk/arch/alpha/Kconfig b/trunk/arch/alpha/Kconfig index eedf41bf7057..153337ff1d7b 100644 --- a/trunk/arch/alpha/Kconfig +++ b/trunk/arch/alpha/Kconfig @@ -18,6 +18,9 @@ config MMU bool default y +config UID16 + bool + config RWSEM_GENERIC_SPINLOCK bool diff --git a/trunk/arch/alpha/kernel/process.c b/trunk/arch/alpha/kernel/process.c index abb739b88ed1..a8682612abc0 100644 --- a/trunk/arch/alpha/kernel/process.c +++ b/trunk/arch/alpha/kernel/process.c @@ -43,11 +43,6 @@ #include "proto.h" #include "pci_impl.h" -/* - * Power off function, if any - */ -void (*pm_power_off)(void) = machine_power_off; - void cpu_idle(void) { diff --git a/trunk/arch/alpha/kernel/ptrace.c b/trunk/arch/alpha/kernel/ptrace.c index 9969d212e94d..bbd37536d14e 100644 --- a/trunk/arch/alpha/kernel/ptrace.c +++ b/trunk/arch/alpha/kernel/ptrace.c @@ -265,16 +265,30 @@ do_sys_ptrace(long request, long pid, long addr, long data, lock_kernel(); DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n", request, pid, addr, data)); + ret = -EPERM; if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) + goto out_notsk; + ret = security_ptrace(current->parent, current); + if (ret) + goto out_notsk; + /* set the ptrace bit in the process ptrace flags. */ + current->ptrace |= PT_PTRACED; + ret = 0; goto out_notsk; } + if (pid == 1) /* you may not mess with init */ + goto out_notsk; - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out_notsk; - } if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 7a74e3e5f916..16a5d522b2f2 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -46,6 +46,10 @@ config MCA (and especially the web page given there) before attempting to build an MCA bus kernel. +config UID16 + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/arm/common/scoop.c b/trunk/arch/arm/common/scoop.c index a2dfe0b0f1ec..b6de43e73699 100644 --- a/trunk/arch/arm/common/scoop.c +++ b/trunk/arch/arm/common/scoop.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/arm/kernel/asm-offsets.c b/trunk/arch/arm/kernel/asm-offsets.c index 0abbce8c70bc..04d3082a7b94 100644 --- a/trunk/arch/arm/kernel/asm-offsets.c +++ b/trunk/arch/arm/kernel/asm-offsets.c @@ -23,15 +23,20 @@ #error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32 #endif /* + * GCC 2.95.1, 2.95.2: ignores register clobber list in asm(). * GCC 3.0, 3.1: general bad code generation. * GCC 3.2.0: incorrect function argument offset calculation. * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c * (http://gcc.gnu.org/PR8896) and incorrect structure * initialisation in fs/jffs2/erase.c */ -#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +#if __GNUC__ < 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ < 95) || \ + (__GNUC__ == 2 && __GNUC_MINOR__ == 95 && __GNUC_PATCHLEVEL__ != 0 && \ + __GNUC_PATCHLEVEL__ < 3) || \ + (__GNUC__ == 3 && __GNUC_MINOR__ < 3) #error Your compiler is too buggy; it is known to miscompile kernels. -#error Known good compilers: 3.3 +#error Known good compilers: 2.95.3, 2.95.4, 2.96, 3.3 #endif /* Use marker if you need to separate the values later */ diff --git a/trunk/arch/arm/kernel/irq.c b/trunk/arch/arm/kernel/irq.c index b5645c4462cf..869c466e6258 100644 --- a/trunk/arch/arm/kernel/irq.c +++ b/trunk/arch/arm/kernel/irq.c @@ -684,12 +684,8 @@ int setup_irq(unsigned int irq, struct irqaction *new) spin_lock_irqsave(&irq_controller_lock, flags); p = &desc->action; if ((old = *p) != NULL) { - /* - * Can't share interrupts unless both agree to and are - * the same type. - */ - if (!(old->flags & new->flags & SA_SHIRQ) || - (~old->flags & new->flags) & SA_TRIGGER_MASK) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { spin_unlock_irqrestore(&irq_controller_lock, flags); return -EBUSY; } @@ -709,12 +705,6 @@ int setup_irq(unsigned int irq, struct irqaction *new) desc->running = 0; desc->pending = 0; desc->disable_depth = 1; - - if (new->flags & SA_TRIGGER_MASK) { - unsigned int type = new->flags & SA_TRIGGER_MASK; - desc->chip->set_type(irq, type); - } - if (!desc->noautoenable) { desc->disable_depth = 0; desc->chip->unmask(irq); diff --git a/trunk/arch/arm/mach-footbridge/netwinder-hw.c b/trunk/arch/arm/mach-footbridge/netwinder-hw.c index 9e563de465b5..775f85fc8513 100644 --- a/trunk/arch/arm/mach-footbridge/netwinder-hw.c +++ b/trunk/arch/arm/mach-footbridge/netwinder-hw.c @@ -601,7 +601,6 @@ EXPORT_SYMBOL(gpio_lock); EXPORT_SYMBOL(gpio_modify_op); EXPORT_SYMBOL(gpio_modify_io); EXPORT_SYMBOL(cpld_modify); -EXPORT_SYMBOL(gpio_read); /* * Initialise any other hardware after we've got the PCI bus diff --git a/trunk/arch/arm/mach-integrator/time.c b/trunk/arch/arm/mach-integrator/time.c index 3c22c16b38bf..9f46aaef8968 100644 --- a/trunk/arch/arm/mach-integrator/time.c +++ b/trunk/arch/arm/mach-integrator/time.c @@ -96,8 +96,7 @@ static struct rtc_ops rtc_ops = { .set_alarm = rtc_set_alarm, }; -static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { writel(0, rtc_base + RTC_EOI); return IRQ_HANDLED; @@ -125,7 +124,7 @@ static int rtc_probe(struct amba_device *dev, void *id) xtime.tv_sec = __raw_readl(rtc_base + RTC_DR); - ret = request_irq(dev->irq[0], arm_rtc_interrupt, SA_INTERRUPT, + ret = request_irq(dev->irq[0], rtc_interrupt, SA_INTERRUPT, "rtc-pl030", dev); if (ret) goto map_out; diff --git a/trunk/arch/arm/mach-omap1/serial.c b/trunk/arch/arm/mach-omap1/serial.c index 7a68f098a025..fcfb81d13cfe 100644 --- a/trunk/arch/arm/mach-omap1/serial.c +++ b/trunk/arch/arm/mach-omap1/serial.c @@ -252,8 +252,9 @@ static void __init omap_serial_set_port_wakeup(int gpio_nr) return; } omap_set_gpio_direction(gpio_nr, 1); + set_irq_type(OMAP_GPIO_IRQ(gpio_nr), IRQT_RISING); ret = request_irq(OMAP_GPIO_IRQ(gpio_nr), &omap_serial_wake_interrupt, - SA_TRIGGER_RISING, "serial wakeup", NULL); + 0, "serial wakeup", NULL); if (ret) { omap_free_gpio(gpio_nr); printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n", diff --git a/trunk/arch/arm/mach-pxa/corgi.c b/trunk/arch/arm/mach-pxa/corgi.c index 5a7b873f29b3..100fb31b5156 100644 --- a/trunk/arch/arm/mach-pxa/corgi.c +++ b/trunk/arch/arm/mach-pxa/corgi.c @@ -213,14 +213,15 @@ static int corgi_mci_init(struct device *dev, irqreturn_t (*corgi_detect_int)(in corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250); - err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, - "MMC card detect", data); + err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, SA_INTERRUPT, + "MMC card detect", data); if (err) { printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); return -1; } + set_irq_type(CORGI_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); + return 0; } diff --git a/trunk/arch/arm/mach-pxa/poodle.c b/trunk/arch/arm/mach-pxa/poodle.c index 663c95005985..eef3de26ad37 100644 --- a/trunk/arch/arm/mach-pxa/poodle.c +++ b/trunk/arch/arm/mach-pxa/poodle.c @@ -146,14 +146,15 @@ static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)( poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); - err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, - "MMC card detect", data); + err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT, + "MMC card detect", data); if (err) { printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); return -1; } + set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); + return 0; } diff --git a/trunk/arch/arm/mach-pxa/spitz.c b/trunk/arch/arm/mach-pxa/spitz.c index a9eacc06555f..f2007db0cda5 100644 --- a/trunk/arch/arm/mach-pxa/spitz.c +++ b/trunk/arch/arm/mach-pxa/spitz.c @@ -296,14 +296,15 @@ static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(in spitz_mci_platform_data.detect_delay = msecs_to_jiffies(250); - err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, - "MMC card detect", data); + err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int, SA_INTERRUPT, + "MMC card detect", data); if (err) { printk(KERN_ERR "spitz_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); return -1; } + set_irq_type(SPITZ_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); + return 0; } diff --git a/trunk/arch/arm/mach-realview/localtimer.c b/trunk/arch/arm/mach-realview/localtimer.c index caf6b8bb6c95..c9d7c596b200 100644 --- a/trunk/arch/arm/mach-realview/localtimer.c +++ b/trunk/arch/arm/mach-realview/localtimer.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/arm/mach-s3c2410/usb-simtec.c b/trunk/arch/arm/mach-s3c2410/usb-simtec.c index 495f8c6ffcb6..5098b50158a3 100644 --- a/trunk/arch/arm/mach-s3c2410/usb-simtec.c +++ b/trunk/arch/arm/mach-s3c2410/usb-simtec.c @@ -84,13 +84,13 @@ static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on) int ret; if (on) { - ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, - SA_INTERRUPT | SA_TRIGGER_RISING | - SA_TRIGGER_FALLING, + ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT, "USB Over-current", info); if (ret != 0) { printk(KERN_ERR "failed to request usb oc irq\n"); } + + set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE); } else { free_irq(IRQ_USBOC, info); } diff --git a/trunk/arch/arm26/Kconfig b/trunk/arch/arm26/Kconfig index 274e07019b46..1f00b3d03a07 100644 --- a/trunk/arch/arm26/Kconfig +++ b/trunk/arch/arm26/Kconfig @@ -34,6 +34,10 @@ config FORCE_MAX_ZONEORDER int default 9 +config UID16 + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/arm26/kernel/asm-offsets.c b/trunk/arch/arm26/kernel/asm-offsets.c index ac682d5fd039..4ccacaef94df 100644 --- a/trunk/arch/arm26/kernel/asm-offsets.c +++ b/trunk/arch/arm26/kernel/asm-offsets.c @@ -25,6 +25,13 @@ #if defined(__APCS_32__) && defined(CONFIG_CPU_26) #error Sorry, your compiler targets APCS-32 but this kernel requires APCS-26 #endif +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95) +#error Sorry, your compiler is known to miscompile kernels. Only use gcc 2.95.3 and later. +#endif +#if __GNUC__ == 2 && __GNUC_MINOR__ == 95 +/* shame we can't detect the .1 or .2 releases */ +#warning GCC 2.95.2 and earlier miscompiles kernels. +#endif /* Use marker if you need to separate the values later */ diff --git a/trunk/arch/cris/Kconfig b/trunk/arch/cris/Kconfig index b83261949737..e5979d68e352 100644 --- a/trunk/arch/cris/Kconfig +++ b/trunk/arch/cris/Kconfig @@ -9,6 +9,10 @@ config MMU bool default y +config UID16 + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/frv/Kconfig b/trunk/arch/frv/Kconfig index 61261b78ced7..ec85c0d6c6da 100644 --- a/trunk/arch/frv/Kconfig +++ b/trunk/arch/frv/Kconfig @@ -274,11 +274,6 @@ config GPREL_DATA_NONE endchoice -config FRV_ONCPU_SERIAL - bool "Use on-CPU serial ports" - select SERIAL_8250 - default y - config PCI bool "Use PCI" depends on MB93090_MB00 @@ -310,7 +305,23 @@ config RESERVE_DMA_COHERENT source "drivers/pci/Kconfig" -source "drivers/pcmcia/Kconfig" +config PCMCIA + tristate "Use PCMCIA" + help + Say Y here if you want to attach PCMCIA- or PC-cards to your FR-V + board. These are credit-card size devices such as network cards, + modems or hard drives often used with laptops computers. There are + actually two varieties of these cards: the older 16 bit PCMCIA cards + and the newer 32 bit CardBus cards. If you want to use CardBus + cards, you need to say Y here and also to "CardBus support" below. + + To use your PC-cards, you will need supporting software from David + Hinds pcmcia-cs package (see the file + for location). Please also read the PCMCIA-HOWTO, available from + . + + To compile this driver as modules, choose M here: the + modules will be called pcmcia_core and ds. #config MATH_EMULATION # bool "Math emulation support (EXPERIMENTAL)" diff --git a/trunk/arch/frv/Kconfig.debug b/trunk/arch/frv/Kconfig.debug index 211f01bc4caa..0034b654995d 100644 --- a/trunk/arch/frv/Kconfig.debug +++ b/trunk/arch/frv/Kconfig.debug @@ -2,10 +2,32 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config EARLY_PRINTK + bool "Early printk" + depends on EMBEDDED && DEBUG_KERNEL + default n + help + Write kernel log output directly into the VGA buffer or to a serial + port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL +config DEBUG_PAGEALLOC + bool "Page alloc debugging" + depends on DEBUG_KERNEL + help + Unmap pages from the kernel linear mapping after free_pages(). + This results in a large slowdown, but helps to find certain types + of memory corruptions. + config GDBSTUB bool "Remote GDB kernel debugging" depends on DEBUG_KERNEL diff --git a/trunk/arch/frv/Makefile b/trunk/arch/frv/Makefile index 90c0fb8d9dc3..54046d2386f5 100644 --- a/trunk/arch/frv/Makefile +++ b/trunk/arch/frv/Makefile @@ -109,10 +109,10 @@ bootstrap: $(Q)$(MAKEBOOT) bootstrap archmrproper: - $(Q)$(MAKE) $(build)=arch/frv/boot mrproper + $(Q)$(MAKE) -C arch/frv/boot mrproper archclean: - $(Q)$(MAKE) $(build)=arch/frv/boot clean + $(Q)$(MAKE) -C arch/frv/boot clean archdep: scripts/mkdep symlinks - $(Q)$(MAKE) $(build)=arch/frv/boot dep + $(Q)$(MAKE) -C arch/frv/boot dep diff --git a/trunk/arch/frv/kernel/Makefile b/trunk/arch/frv/kernel/Makefile index 5a827b349b5e..422f30ede575 100644 --- a/trunk/arch/frv/kernel/Makefile +++ b/trunk/arch/frv/kernel/Makefile @@ -21,4 +21,3 @@ obj-$(CONFIG_PM) += pm.o cmode.o obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o obj-$(CONFIG_SYSCTL) += sysctl.o obj-$(CONFIG_FUTEX) += futex.o -obj-$(CONFIG_MODULES) += module.o diff --git a/trunk/arch/frv/kernel/frv_ksyms.c b/trunk/arch/frv/kernel/frv_ksyms.c index 5f118c89d091..1a76d5247190 100644 --- a/trunk/arch/frv/kernel/frv_ksyms.c +++ b/trunk/arch/frv/kernel/frv_ksyms.c @@ -16,11 +16,10 @@ #include #include #include -#include +#include extern void dump_thread(struct pt_regs *, struct user *); extern long __memcpy_user(void *dst, const void *src, size_t count); -extern long __memset_user(void *dst, const void *src, size_t count); /* platform dependent support */ @@ -51,11 +50,7 @@ EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(__res_bus_clock_speed_HZ); EXPORT_SYMBOL(__page_offset); EXPORT_SYMBOL(__memcpy_user); -EXPORT_SYMBOL(__memset_user); -EXPORT_SYMBOL(frv_dcache_writeback); -EXPORT_SYMBOL(frv_cache_invalidate); -EXPORT_SYMBOL(frv_icache_invalidate); -EXPORT_SYMBOL(frv_cache_wback_inv); +EXPORT_SYMBOL(flush_dcache_page); #ifndef CONFIG_MMU EXPORT_SYMBOL(memory_start); @@ -77,9 +72,6 @@ EXPORT_SYMBOL(memcmp); EXPORT_SYMBOL(memscan); EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(__outsl_ns); -EXPORT_SYMBOL(__insl_ns); - EXPORT_SYMBOL(get_wchan); #ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS @@ -88,13 +80,14 @@ EXPORT_SYMBOL(atomic_test_and_OR_mask); EXPORT_SYMBOL(atomic_test_and_XOR_mask); EXPORT_SYMBOL(atomic_add_return); EXPORT_SYMBOL(atomic_sub_return); +EXPORT_SYMBOL(__xchg_8); +EXPORT_SYMBOL(__xchg_16); EXPORT_SYMBOL(__xchg_32); +EXPORT_SYMBOL(__cmpxchg_8); +EXPORT_SYMBOL(__cmpxchg_16); EXPORT_SYMBOL(__cmpxchg_32); #endif -EXPORT_SYMBOL(__debug_bug_printk); -EXPORT_SYMBOL(__delay_loops_MHz); - /* * libgcc functions - functions that are used internally by the * compiler... (prototypes are not correct though, but that @@ -108,8 +101,6 @@ extern void __divdi3(void); extern void __lshrdi3(void); extern void __moddi3(void); extern void __muldi3(void); -extern void __mulll(void); -extern void __umulll(void); extern void __negdi2(void); extern void __ucmpdi2(void); extern void __udivdi3(void); @@ -125,10 +116,8 @@ EXPORT_SYMBOL(__ashrdi3); EXPORT_SYMBOL(__lshrdi3); //EXPORT_SYMBOL(__moddi3); EXPORT_SYMBOL(__muldi3); -EXPORT_SYMBOL(__mulll); -EXPORT_SYMBOL(__umulll); EXPORT_SYMBOL(__negdi2); -EXPORT_SYMBOL(__ucmpdi2); +//EXPORT_SYMBOL(__ucmpdi2); //EXPORT_SYMBOL(__udivdi3); //EXPORT_SYMBOL(__udivmoddi4); //EXPORT_SYMBOL(__umoddi3); diff --git a/trunk/arch/frv/kernel/irq.c b/trunk/arch/frv/kernel/irq.c index 59580c59c62c..8c524cdd2717 100644 --- a/trunk/arch/frv/kernel/irq.c +++ b/trunk/arch/frv/kernel/irq.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -179,8 +178,6 @@ void disable_irq_nosync(unsigned int irq) spin_unlock_irqrestore(&level->lock, flags); } -EXPORT_SYMBOL(disable_irq_nosync); - /** * disable_irq - disable an irq and wait for completion * @irq: Interrupt to disable @@ -207,8 +204,6 @@ void disable_irq(unsigned int irq) #endif } -EXPORT_SYMBOL(disable_irq); - /** * enable_irq - enable handling of an irq * @irq: Interrupt to enable @@ -273,8 +268,6 @@ void enable_irq(unsigned int irq) spin_unlock_irqrestore(&level->lock, flags); } -EXPORT_SYMBOL(enable_irq); - /*****************************************************************************/ /* * handles all normal device IRQ's @@ -432,8 +425,6 @@ int request_irq(unsigned int irq, return retval; } -EXPORT_SYMBOL(request_irq); - /** * free_irq - free an interrupt * @irq: Interrupt line to free @@ -505,8 +496,6 @@ void free_irq(unsigned int irq, void *dev_id) } } -EXPORT_SYMBOL(free_irq); - /* * IRQ autodetection code.. * @@ -530,8 +519,6 @@ unsigned long probe_irq_on(void) return 0; } -EXPORT_SYMBOL(probe_irq_on); - /* * Return a mask of triggered interrupts (this * can handle only legacy ISA interrupts). @@ -555,8 +542,6 @@ unsigned int probe_irq_mask(unsigned long xmask) return 0; } -EXPORT_SYMBOL(probe_irq_mask); - /* * Return the one interrupt that triggered (this can * handle any interrupt source). @@ -586,8 +571,6 @@ int probe_irq_off(unsigned long xmask) return -1; } -EXPORT_SYMBOL(probe_irq_off); - /* this was setup_x86_irq but it seems pretty generic */ int setup_irq(unsigned int irq, struct irqaction *new) { diff --git a/trunk/arch/frv/kernel/module.c b/trunk/arch/frv/kernel/module.c deleted file mode 100644 index 850d168f69fc..000000000000 --- a/trunk/arch/frv/kernel/module.c +++ /dev/null @@ -1,80 +0,0 @@ -/* module.c: FRV specific module loading bits - * - * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - Derived from arch/i386/kernel/module.c, Copyright (C) 2001 Rusty Russell. - * - * 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 -#include -#include -#include -#include -#include - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - - return vmalloc_exec(size); -} - - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ -} - -/* We don't need anything special. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) -{ - return 0; -} - -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name); - return -ENOEXEC; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name); - return -ENOEXEC; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) -{ - return 0; -} - -void module_arch_cleanup(struct module *mod) -{ -} diff --git a/trunk/arch/frv/kernel/pm.c b/trunk/arch/frv/kernel/pm.c index f0b8fff3e733..712c3c24c954 100644 --- a/trunk/arch/frv/kernel/pm.c +++ b/trunk/arch/frv/kernel/pm.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -28,7 +27,6 @@ #include "local.h" void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); extern void frv_change_cmode(int); diff --git a/trunk/arch/frv/kernel/setup.c b/trunk/arch/frv/kernel/setup.c index 5908deae9607..767ebb55bd83 100644 --- a/trunk/arch/frv/kernel/setup.c +++ b/trunk/arch/frv/kernel/setup.c @@ -787,7 +787,6 @@ void __init setup_arch(char **cmdline_p) #endif /* register those serial ports that are available */ -#ifdef CONFIG_FRV_ONCPU_SERIAL #ifndef CONFIG_GDBSTUB_UART0 __reg(UART0_BASE + UART_IER * 8) = 0; early_serial_setup(&__frv_uart0); @@ -796,7 +795,6 @@ void __init setup_arch(char **cmdline_p) __reg(UART1_BASE + UART_IER * 8) = 0; early_serial_setup(&__frv_uart1); #endif -#endif #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) /* we need to initialize the Flashrom device here since we might diff --git a/trunk/arch/frv/kernel/time.c b/trunk/arch/frv/kernel/time.c index 24cf85f89e40..2e9741227b73 100644 --- a/trunk/arch/frv/kernel/time.c +++ b/trunk/arch/frv/kernel/time.c @@ -189,8 +189,6 @@ void do_gettimeofday(struct timeval *tv) tv->tv_usec = usec; } -EXPORT_SYMBOL(do_gettimeofday); - int do_settimeofday(struct timespec *tv) { time_t wtm_sec, sec = tv->tv_sec; @@ -220,7 +218,6 @@ int do_settimeofday(struct timespec *tv) clock_was_set(); return 0; } - EXPORT_SYMBOL(do_settimeofday); /* diff --git a/trunk/arch/frv/kernel/traps.c b/trunk/arch/frv/kernel/traps.c index 9eb84b2e6abc..89073cae4b5d 100644 --- a/trunk/arch/frv/kernel/traps.c +++ b/trunk/arch/frv/kernel/traps.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -251,8 +250,6 @@ void dump_stack(void) show_stack(NULL, NULL); } -EXPORT_SYMBOL(dump_stack); - void show_stack(struct task_struct *task, unsigned long *sp) { } diff --git a/trunk/arch/frv/kernel/uaccess.c b/trunk/arch/frv/kernel/uaccess.c index 9b751c0f0e84..f3fd58a5bc4a 100644 --- a/trunk/arch/frv/kernel/uaccess.c +++ b/trunk/arch/frv/kernel/uaccess.c @@ -10,7 +10,6 @@ */ #include -#include #include /*****************************************************************************/ @@ -59,11 +58,8 @@ long strncpy_from_user(char *dst, const char *src, long count) memset(p, 0, count); /* clear remainder of buffer [security] */ return err; - } /* end strncpy_from_user() */ -EXPORT_SYMBOL(strncpy_from_user); - /*****************************************************************************/ /* * Return the size of a string (including the ending 0) @@ -96,7 +92,4 @@ long strnlen_user(const char *src, long count) } return p - src + 1; /* return length including NUL */ - } /* end strnlen_user() */ - -EXPORT_SYMBOL(strnlen_user); diff --git a/trunk/arch/frv/kernel/vmlinux.lds.S b/trunk/arch/frv/kernel/vmlinux.lds.S index f474534ba78a..fceafd2cc202 100644 --- a/trunk/arch/frv/kernel/vmlinux.lds.S +++ b/trunk/arch/frv/kernel/vmlinux.lds.S @@ -112,7 +112,6 @@ SECTIONS #endif ) SCHED_TEXT - LOCK_TEXT *(.fixup) *(.gnu.warning) *(.exitcall.exit) diff --git a/trunk/arch/frv/lib/Makefile b/trunk/arch/frv/lib/Makefile index 08be305c9f44..19be2626d5e6 100644 --- a/trunk/arch/frv/lib/Makefile +++ b/trunk/arch/frv/lib/Makefile @@ -3,6 +3,6 @@ # lib-y := \ - __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \ + __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o \ checksum.o memcpy.o memset.o atomic-ops.o \ outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o diff --git a/trunk/arch/frv/lib/__ucmpdi2.S b/trunk/arch/frv/lib/__ucmpdi2.S deleted file mode 100644 index d892f16ffaa9..000000000000 --- a/trunk/arch/frv/lib/__ucmpdi2.S +++ /dev/null @@ -1,45 +0,0 @@ -/* __ucmpdi2.S: 64-bit unsigned compare - * - * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.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. - */ - - - .text - .p2align 4 - -############################################################################### -# -# int __ucmpdi2(unsigned long long a [GR8:GR9], -# unsigned long long b [GR10:GR11]) -# -# - returns 0, 1, or 2 as a <, =, > b respectively. -# -############################################################################### - .globl __ucmpdi2 - .type __ucmpdi2,@function -__ucmpdi2: - or.p gr8,gr0,gr4 - subcc gr8,gr10,gr0,icc0 - setlos.p #0,gr8 - bclr icc0,#2 ; a.msw < b.msw - - setlos.p #2,gr8 - bhilr icc0,#0 ; a.msw > b.msw - - subcc.p gr9,gr11,gr0,icc1 - setlos #0,gr8 - setlos.p #2,gr9 - setlos #1,gr7 - cknc icc1,cc6 - cor.p gr9,gr0,gr8, cc6,#1 - cckls icc1,cc4, cc6,#1 - andcr cc6,cc4,cc4 - cor gr7,gr0,gr8, cc4,#1 - bralr - .size __ucmpdi2, .-__ucmpdi2 diff --git a/trunk/arch/frv/lib/atomic-ops.S b/trunk/arch/frv/lib/atomic-ops.S index 545cd325ac57..b03d510a89e4 100644 --- a/trunk/arch/frv/lib/atomic-ops.S +++ b/trunk/arch/frv/lib/atomic-ops.S @@ -127,6 +127,48 @@ atomic_sub_return: .size atomic_sub_return, .-atomic_sub_return +############################################################################### +# +# uint8_t __xchg_8(uint8_t i, uint8_t *v) +# +############################################################################### + .globl __xchg_8 + .type __xchg_8,@function +__xchg_8: + or.p gr8,gr8,gr10 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldub.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + cstb.p gr10,@(gr9,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size __xchg_8, .-__xchg_8 + +############################################################################### +# +# uint16_t __xchg_16(uint16_t i, uint16_t *v) +# +############################################################################### + .globl __xchg_16 + .type __xchg_16,@function +__xchg_16: + or.p gr8,gr8,gr10 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + lduh.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + csth.p gr10,@(gr9,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size __xchg_16, .-__xchg_16 + ############################################################################### # # uint32_t __xchg_32(uint32_t i, uint32_t *v) @@ -148,6 +190,56 @@ __xchg_32: .size __xchg_32, .-__xchg_32 +############################################################################### +# +# uint8_t __cmpxchg_8(uint8_t *v, uint8_t test, uint8_t new) +# +############################################################################### + .globl __cmpxchg_8 + .type __cmpxchg_8,@function +__cmpxchg_8: + or.p gr8,gr8,gr11 +0: + orcc gr0,gr0,gr0,icc3 + ckeq icc3,cc7 + ldub.p @(gr11,gr0),gr8 + orcr cc7,cc7,cc3 + sub gr8,gr9,gr7 + sllicc gr7,#24,gr0,icc0 + bne icc0,#0,1f + cstb.p gr10,@(gr11,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 + beq icc3,#0,0b +1: + bralr + + .size __cmpxchg_8, .-__cmpxchg_8 + +############################################################################### +# +# uint16_t __cmpxchg_16(uint16_t *v, uint16_t test, uint16_t new) +# +############################################################################### + .globl __cmpxchg_16 + .type __cmpxchg_16,@function +__cmpxchg_16: + or.p gr8,gr8,gr11 +0: + orcc gr0,gr0,gr0,icc3 + ckeq icc3,cc7 + lduh.p @(gr11,gr0),gr8 + orcr cc7,cc7,cc3 + sub gr8,gr9,gr7 + sllicc gr7,#16,gr0,icc0 + bne icc0,#0,1f + csth.p gr10,@(gr11,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 + beq icc3,#0,0b +1: + bralr + + .size __cmpxchg_16, .-__cmpxchg_16 + ############################################################################### # # uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new) diff --git a/trunk/arch/frv/lib/checksum.c b/trunk/arch/frv/lib/checksum.c index 20e7dfc474ef..7bf5bd6cac8a 100644 --- a/trunk/arch/frv/lib/checksum.c +++ b/trunk/arch/frv/lib/checksum.c @@ -33,7 +33,6 @@ #include #include -#include static inline unsigned short from32to16(unsigned long x) { @@ -116,52 +115,34 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) return result; } -EXPORT_SYMBOL(csum_partial); - /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c */ unsigned short ip_compute_csum(const unsigned char * buff, int len) { - return ~do_csum(buff, len); + return ~do_csum(buff,len); } -EXPORT_SYMBOL(ip_compute_csum); - /* * copy from fs while checksumming, otherwise like csum_partial */ + unsigned int -csum_partial_copy_from_user(const char __user *src, char *dst, - int len, int sum, int *csum_err) +csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err) { - int rem; - - if (csum_err) - *csum_err = 0; - - rem = copy_from_user(dst, src, len); - if (rem != 0) { - if (csum_err) - *csum_err = -EFAULT; - memset(dst + len - rem, 0, rem); - len = rem; - } - + if (csum_err) *csum_err = 0; + memcpy(dst, src, len); return csum_partial(dst, len, sum); } -EXPORT_SYMBOL(csum_partial_copy_from_user); - /* * copy from ds while checksumming, otherwise like csum_partial */ + unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum) { memcpy(dst, src, len); return csum_partial(dst, len, sum); } - -EXPORT_SYMBOL(csum_partial_copy); diff --git a/trunk/arch/frv/mb93090-mb00/Makefile b/trunk/arch/frv/mb93090-mb00/Makefile index 76595e870733..3faf0f8cf9b5 100644 --- a/trunk/arch/frv/mb93090-mb00/Makefile +++ b/trunk/arch/frv/mb93090-mb00/Makefile @@ -3,7 +3,7 @@ # ifeq "$(CONFIG_PCI)" "y" -obj-y := pci-frv.o pci-irq.o pci-vdk.o pci-iomap.o +obj-y := pci-frv.o pci-irq.o pci-vdk.o ifeq "$(CONFIG_MMU)" "y" obj-y += pci-dma.o diff --git a/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c b/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c index 4985466b1a7c..2082a9647f4f 100644 --- a/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/trunk/arch/frv/mb93090-mb00/pci-dma-nommu.c @@ -83,8 +83,6 @@ void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_hand return NULL; } -EXPORT_SYMBOL(dma_alloc_coherent); - void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { struct dma_alloc_record *rec; @@ -104,8 +102,6 @@ void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_ BUG(); } -EXPORT_SYMBOL(dma_free_coherent); - /* * Map a single buffer of the indicated size for DMA in streaming mode. * The 32-bit bus address to use is returned. @@ -124,8 +120,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, return virt_to_bus(ptr); } -EXPORT_SYMBOL(dma_map_single); - /* * Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scather-gather version of the @@ -156,5 +150,3 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, return nents; } - -EXPORT_SYMBOL(dma_map_sg); diff --git a/trunk/arch/frv/mb93090-mb00/pci-dma.c b/trunk/arch/frv/mb93090-mb00/pci-dma.c index 671ce1e8434f..86fbdadc51b6 100644 --- a/trunk/arch/frv/mb93090-mb00/pci-dma.c +++ b/trunk/arch/frv/mb93090-mb00/pci-dma.c @@ -28,15 +28,11 @@ void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_hand return ret; } -EXPORT_SYMBOL(dma_alloc_coherent); - void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { consistent_free(vaddr); } -EXPORT_SYMBOL(dma_free_coherent); - /* * Map a single buffer of the indicated size for DMA in streaming mode. * The 32-bit bus address to use is returned. @@ -55,8 +51,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, return virt_to_bus(ptr); } -EXPORT_SYMBOL(dma_map_single); - /* * Map a set of buffers described by scatterlist in streaming * mode for DMA. This is the scather-gather version of the @@ -102,8 +96,6 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, return nents; } -EXPORT_SYMBOL(dma_map_sg); - dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction) { @@ -111,5 +103,3 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long off flush_dcache_page(page); return (dma_addr_t) page_to_phys(page) + offset; } - -EXPORT_SYMBOL(dma_map_page); diff --git a/trunk/arch/frv/mb93090-mb00/pci-iomap.c b/trunk/arch/frv/mb93090-mb00/pci-iomap.c deleted file mode 100644 index 068fa04bd527..000000000000 --- a/trunk/arch/frv/mb93090-mb00/pci-iomap.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pci-iomap.c: description - * - * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.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 -#include - -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) -{ - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len || !start) - return NULL; - - if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM)) - return (void __iomem *) start; - - return NULL; -} - -EXPORT_SYMBOL(pci_iomap); diff --git a/trunk/arch/frv/mm/cache-page.c b/trunk/arch/frv/mm/cache-page.c index 0261cbe153b5..683b5e344318 100644 --- a/trunk/arch/frv/mm/cache-page.c +++ b/trunk/arch/frv/mm/cache-page.c @@ -11,7 +11,6 @@ #include #include #include -#include #include /*****************************************************************************/ @@ -39,8 +38,6 @@ void flush_dcache_page(struct page *page) } /* end flush_dcache_page() */ -EXPORT_SYMBOL(flush_dcache_page); - /*****************************************************************************/ /* * ICI takes a virtual address and the page may not currently have one @@ -67,5 +64,3 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, } } /* end flush_icache_user_range() */ - -EXPORT_SYMBOL(flush_icache_user_range); diff --git a/trunk/arch/frv/mm/extable.c b/trunk/arch/frv/mm/extable.c index caacf030ac75..41be1128dc64 100644 --- a/trunk/arch/frv/mm/extable.c +++ b/trunk/arch/frv/mm/extable.c @@ -43,7 +43,7 @@ static inline unsigned long search_one_table(const struct exception_table_entry */ unsigned long search_exception_table(unsigned long pc) { - const struct exception_table_entry *extab; + unsigned long ret = 0; /* determine if the fault lay during a memcpy_user or a memset_user */ if (__frame->lr == (unsigned long) &__memset_user_error_lr && @@ -55,10 +55,9 @@ unsigned long search_exception_table(unsigned long pc) */ return (unsigned long) &__memset_user_error_handler; } - - if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && - (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end - ) { + else if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && + (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end + ) { /* the fault occurred in a protected memset * - we search for the return address (in LR) instead of the program counter * - it was probably during a copy_to/from_user() @@ -66,10 +65,27 @@ unsigned long search_exception_table(unsigned long pc) return (unsigned long) &__memcpy_user_error_handler; } - extab = search_exception_tables(pc); - if (extab) - return extab->fixup; +#ifndef CONFIG_MODULES + /* there is only the kernel to search. */ + ret = search_one_table(__start___ex_table, __stop___ex_table - 1, pc); + return ret; + +#else + /* the kernel is the last "module" -- no need to treat it special */ + unsigned long flags; + struct module *mp; - return 0; + spin_lock_irqsave(&modlist_lock, flags); + + for (mp = module_list; mp != NULL; mp = mp->next) { + if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) + continue; + ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, pc); + if (ret) + break; + } + spin_unlock_irqrestore(&modlist_lock, flags); + return ret; +#endif } /* end search_exception_table() */ diff --git a/trunk/arch/frv/mm/highmem.c b/trunk/arch/frv/mm/highmem.c index 7f77db7fabc7..7dc8fbf3af97 100644 --- a/trunk/arch/frv/mm/highmem.c +++ b/trunk/arch/frv/mm/highmem.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ #include -#include void *kmap(struct page *page) { @@ -19,8 +18,6 @@ void *kmap(struct page *page) return kmap_high(page); } -EXPORT_SYMBOL(kmap); - void kunmap(struct page *page) { if (in_interrupt()) @@ -30,12 +27,7 @@ void kunmap(struct page *page) kunmap_high(page); } -EXPORT_SYMBOL(kunmap); - struct page *kmap_atomic_to_page(void *ptr) { return virt_to_page(ptr); } - - -EXPORT_SYMBOL(kmap_atomic_to_page); diff --git a/trunk/arch/h8300/Kconfig b/trunk/arch/h8300/Kconfig index 80940d712acf..26698a49f153 100644 --- a/trunk/arch/h8300/Kconfig +++ b/trunk/arch/h8300/Kconfig @@ -21,6 +21,10 @@ config FPU bool default n +config UID16 + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/i386/Kconfig b/trunk/arch/i386/Kconfig index d849c6870e3a..968fabd8723f 100644 --- a/trunk/arch/i386/Kconfig +++ b/trunk/arch/i386/Kconfig @@ -29,6 +29,10 @@ config MMU config SBUS bool +config UID16 + bool + default y + config GENERIC_ISA_DMA bool default y @@ -626,6 +630,10 @@ config REGPARM and passes the first three arguments of a function call in registers. This will probably break binary only modules. + This feature is only enabled for gcc-3.0 and later - earlier compilers + generate incorrect output with certain kernel constructs when + -mregparm=3 is used. + config SECCOMP bool "Enable seccomp to safely compute untrusted bytecode" depends on PROC_FS @@ -695,7 +703,7 @@ depends on PM && !X86_VISWS config APM tristate "APM (Advanced Power Management) BIOS support" - depends on PM + depends on PM && PM_LEGACY ---help--- APM is a BIOS specification for saving power using several different techniques. This is mostly useful for battery powered laptops with diff --git a/trunk/arch/i386/Makefile b/trunk/arch/i386/Makefile index b84119f9cc63..d121ea18460f 100644 --- a/trunk/arch/i386/Makefile +++ b/trunk/arch/i386/Makefile @@ -37,7 +37,10 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) # CPU-specific tuning. Anything which can be shared with UML should go here. include $(srctree)/arch/i386/Makefile.cpu -cflags-$(CONFIG_REGPARM) += -mregparm=3 +# -mregparm=3 works ok on gcc-3.0 and later +# +GCC_VERSION := $(call cc-version) +cflags-$(CONFIG_REGPARM) += $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;) # Disable unit-at-a-time mode, it makes gcc use a lot more stack # due to the lack of sharing of stacklots. diff --git a/trunk/arch/i386/Makefile.cpu b/trunk/arch/i386/Makefile.cpu index dcd936ef45db..8e51456df23d 100644 --- a/trunk/arch/i386/Makefile.cpu +++ b/trunk/arch/i386/Makefile.cpu @@ -1,7 +1,7 @@ # CPU tuning section - shared with UML. # Must change only cflags-y (or [yn]), not CFLAGS! That makes a difference for UML. -#-mtune exists since gcc 3.4 +#-mtune exists since gcc 3.4, and some -mcpu flavors didn't exist in gcc 2.95. HAS_MTUNE := $(call cc-option-yn, -mtune=i386) ifeq ($(HAS_MTUNE),y) tune = $(call cc-option,-mtune=$(1),) @@ -14,7 +14,7 @@ cflags-$(CONFIG_M386) += -march=i386 cflags-$(CONFIG_M486) += -march=i486 cflags-$(CONFIG_M586) += -march=i586 cflags-$(CONFIG_M586TSC) += -march=i586 -cflags-$(CONFIG_M586MMX) += -march=pentium-mmx +cflags-$(CONFIG_M586MMX) += $(call cc-option,-march=pentium-mmx,-march=i586) cflags-$(CONFIG_M686) += -march=i686 cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call tune,pentium2) cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call tune,pentium3) @@ -23,8 +23,8 @@ cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call tune,pentium4) cflags-$(CONFIG_MK6) += -march=k6 # Please note, that patches that add -march=athlon-xp and friends are pointless. # They make zero difference whatsosever to performance at this time. -cflags-$(CONFIG_MK7) += -march=athlon -cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon) +cflags-$(CONFIG_MK7) += $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4) +cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)) cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) @@ -37,5 +37,5 @@ cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) cflags-$(CONFIG_X86_ELAN) += -march=i486 # Geode GX1 support -cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx +cflags-$(CONFIG_MGEODEGX1) += $(call cc-option,-march=pentium-mmx,-march=i486) diff --git a/trunk/arch/i386/boot/compressed/misc.c b/trunk/arch/i386/boot/compressed/misc.c index f19f3a7492a5..82a807f9f5e6 100644 --- a/trunk/arch/i386/boot/compressed/misc.c +++ b/trunk/arch/i386/boot/compressed/misc.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include diff --git a/trunk/arch/i386/kernel/Makefile b/trunk/arch/i386/kernel/Makefile index be1880bb75b4..f10de0f2c5e6 100644 --- a/trunk/arch/i386/kernel/Makefile +++ b/trunk/arch/i386/kernel/Makefile @@ -4,10 +4,10 @@ extra-y := head.o init_task.o vmlinux.lds -obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ +obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \ - quirks.o i8237.o + doublefault.o quirks.o i8237.o obj-y += cpu/ obj-y += timers/ @@ -33,8 +33,6 @@ obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_HPET_TIMER) += time_hpet.o obj-$(CONFIG_EFI) += efi.o efi_stub.o -obj-$(CONFIG_DOUBLEFAULT) += doublefault.o -obj-$(CONFIG_VM86) += vm86.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o EXTRA_AFLAGS := -traditional diff --git a/trunk/arch/i386/kernel/apm.c b/trunk/arch/i386/kernel/apm.c index 9d8827156e54..2d793d4aef1a 100644 --- a/trunk/arch/i386/kernel/apm.c +++ b/trunk/arch/i386/kernel/apm.c @@ -2291,9 +2291,7 @@ static int __init apm_init(void) apm_info.disabled = 1; return -ENODEV; } -#ifdef CONFIG_PM_LEGACY pm_active = 1; -#endif /* * Set up a segment that references the real mode segment 0x40 @@ -2384,9 +2382,7 @@ static void __exit apm_exit(void) exit_kapmd = 1; while (kapmd_running) schedule(); -#ifdef CONFIG_PM_LEGACY pm_active = 0; -#endif } module_init(apm_init); diff --git a/trunk/arch/i386/kernel/cpu/common.c b/trunk/arch/i386/kernel/cpu/common.c index 170400879f44..cca655688ffc 100644 --- a/trunk/arch/i386/kernel/cpu/common.c +++ b/trunk/arch/i386/kernel/cpu/common.c @@ -609,10 +609,8 @@ void __devinit cpu_init(void) load_TR_desc(); load_LDT(&init_mm.context); -#ifdef CONFIG_DOUBLEFAULT /* Set up doublefault TSS pointer in the GDT */ __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); -#endif /* Clear %fs and %gs. */ asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs"); diff --git a/trunk/arch/i386/kernel/entry.S b/trunk/arch/i386/kernel/entry.S index 4d704724b2f5..607c06007508 100644 --- a/trunk/arch/i386/kernel/entry.S +++ b/trunk/arch/i386/kernel/entry.S @@ -323,7 +323,6 @@ work_notifysig: # deal with pending signals and ALIGN work_notifysig_v86: -#ifdef CONFIG_VM86 pushl %ecx # save ti_flags for do_notify_resume call save_v86_state # %eax contains pt_regs pointer popl %ecx @@ -331,7 +330,6 @@ work_notifysig_v86: xorl %edx, %edx call do_notify_resume jmp resume_userspace -#endif # perform syscall exit tracing ALIGN diff --git a/trunk/arch/i386/kernel/init_task.c b/trunk/arch/i386/kernel/init_task.c index cff95d10a4d8..9caa8e8db80c 100644 --- a/trunk/arch/i386/kernel/init_task.c +++ b/trunk/arch/i386/kernel/init_task.c @@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task); * per-CPU TSS segments. Threads are completely 'soft' on Linux, * no more per-task TSS's. */ -DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; +DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS; diff --git a/trunk/arch/i386/kernel/irq.c b/trunk/arch/i386/kernel/irq.c index f3a9c78c4a24..1a201a932865 100644 --- a/trunk/arch/i386/kernel/irq.c +++ b/trunk/arch/i386/kernel/irq.c @@ -19,7 +19,7 @@ #include #include -DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp; +DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp; EXPORT_PER_CPU_SYMBOL(irq_stat); #ifndef CONFIG_X86_LOCAL_APIC diff --git a/trunk/arch/i386/kernel/process.c b/trunk/arch/i386/kernel/process.c index 035928f3f6c1..45e7f0ac4b04 100644 --- a/trunk/arch/i386/kernel/process.c +++ b/trunk/arch/i386/kernel/process.c @@ -48,7 +48,6 @@ #include #include #include -#include #ifdef CONFIG_MATH_EMULATION #include #endif diff --git a/trunk/arch/i386/kernel/syscall_table.S b/trunk/arch/i386/kernel/syscall_table.S index 6ff3e5243226..f7ba4acc20ec 100644 --- a/trunk/arch/i386/kernel/syscall_table.S +++ b/trunk/arch/i386/kernel/syscall_table.S @@ -293,4 +293,3 @@ ENTRY(sys_call_table) .long sys_inotify_init .long sys_inotify_add_watch .long sys_inotify_rm_watch - .long sys_migrate_pages diff --git a/trunk/arch/i386/kernel/time_hpet.c b/trunk/arch/i386/kernel/time_hpet.c index a529f0cdce17..9caeaa315cd7 100644 --- a/trunk/arch/i386/kernel/time_hpet.c +++ b/trunk/arch/i386/kernel/time_hpet.c @@ -259,6 +259,8 @@ __setup("hpet=", hpet_setup); #include #include +extern irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs); + #define DEFAULT_RTC_INT_FREQ 64 #define RTC_NUM_INTS 1 diff --git a/trunk/arch/ia64/Makefile b/trunk/arch/ia64/Makefile index 57b047c27e46..67932ad53082 100644 --- a/trunk/arch/ia64/Makefile +++ b/trunk/arch/ia64/Makefile @@ -37,6 +37,10 @@ $(error Sorry, you need a newer version of the assember, one that is built from ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz) endif +ifneq ($(shell if [ $(GCC_VERSION) -lt 0300 ] ; then echo "bad"; fi ;),) +$(error Sorry, your compiler is too old. GCC v2.96 is known to generate bad code.) +endif + ifeq ($(GCC_VERSION),0304) cflags-$(CONFIG_ITANIUM) += -mtune=merced cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley diff --git a/trunk/arch/ia64/ia32/sys_ia32.c b/trunk/arch/ia64/ia32/sys_ia32.c index 9f8e8d558873..dc282710421a 100644 --- a/trunk/arch/ia64/ia32/sys_ia32.c +++ b/trunk/arch/ia64/ia32/sys_ia32.c @@ -1761,15 +1761,21 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data) lock_kernel(); if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + ret = sys_ptrace(request, pid, addr, data); goto out; } - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out; - } + ret = -EPERM; + if (pid == 1) /* no messing around with init! */ + goto out_tsk; if (request == PTRACE_ATTACH) { ret = sys_ptrace(request, pid, addr, data); diff --git a/trunk/arch/ia64/kernel/efi.c b/trunk/arch/ia64/kernel/efi.c index c485a3b32ba8..a3aa45cbcfa0 100644 --- a/trunk/arch/ia64/kernel/efi.c +++ b/trunk/arch/ia64/kernel/efi.c @@ -247,32 +247,6 @@ typedef struct kern_memdesc { static kern_memdesc_t *kern_memmap; -#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT) - -static inline u64 -kmd_end(kern_memdesc_t *kmd) -{ - return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT)); -} - -static inline u64 -efi_md_end(efi_memory_desc_t *md) -{ - return (md->phys_addr + efi_md_size(md)); -} - -static inline int -efi_wb(efi_memory_desc_t *md) -{ - return (md->attribute & EFI_MEMORY_WB); -} - -static inline int -efi_uc(efi_memory_desc_t *md) -{ - return (md->attribute & EFI_MEMORY_UC); -} - static void walk (efi_freemem_callback_t callback, void *arg, u64 attr) { @@ -621,8 +595,8 @@ efi_get_iobase (void) return 0; } -static efi_memory_desc_t * -efi_memory_descriptor (unsigned long phys_addr) +u32 +efi_mem_type (unsigned long phys_addr) { void *efi_map_start, *efi_map_end, *p; efi_memory_desc_t *md; @@ -636,13 +610,13 @@ efi_memory_descriptor (unsigned long phys_addr) md = p; if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) - return md; + return md->type; } return 0; } -static int -efi_memmap_has_mmio (void) +u64 +efi_mem_attributes (unsigned long phys_addr) { void *efi_map_start, *efi_map_end, *p; efi_memory_desc_t *md; @@ -655,98 +629,36 @@ efi_memmap_has_mmio (void) for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { md = p; - if (md->type == EFI_MEMORY_MAPPED_IO) - return 1; + if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) + return md->attribute; } return 0; } - -u32 -efi_mem_type (unsigned long phys_addr) -{ - efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); - - if (md) - return md->type; - return 0; -} - -u64 -efi_mem_attributes (unsigned long phys_addr) -{ - efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); - - if (md) - return md->attribute; - return 0; -} EXPORT_SYMBOL(efi_mem_attributes); -/* - * Determines whether the memory at phys_addr supports the desired - * attribute (WB, UC, etc). If this returns 1, the caller can safely - * access *size bytes at phys_addr with the specified attribute. - */ -static int -efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr) -{ - efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); - unsigned long md_end; - - if (!md || (md->attribute & attr) != attr) - return 0; - - do { - md_end = efi_md_end(md); - if (phys_addr + *size <= md_end) - return 1; - - md = efi_memory_descriptor(md_end); - if (!md || (md->attribute & attr) != attr) { - *size = md_end - phys_addr; - return 1; - } - } while (md); - return 0; -} - -/* - * For /dev/mem, we only allow read & write system calls to access - * write-back memory, because read & write don't allow the user to - * control access size. - */ int valid_phys_addr_range (unsigned long phys_addr, unsigned long *size) { - return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); -} + void *efi_map_start, *efi_map_end, *p; + efi_memory_desc_t *md; + u64 efi_desc_size; -/* - * We allow mmap of anything in the EFI memory map that supports - * either write-back or uncacheable access. For uncacheable regions, - * the supported access sizes are system-dependent, and the user is - * responsible for using the correct size. - * - * Note that this doesn't currently allow access to hot-added memory, - * because that doesn't appear in the boot-time EFI memory map. - */ -int -valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size) -{ - if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB)) - return 1; + efi_map_start = __va(ia64_boot_param->efi_memmap); + efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; + efi_desc_size = ia64_boot_param->efi_memdesc_size; - if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) - return 1; + for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + md = p; - /* - * Some firmware doesn't report MMIO regions in the EFI memory map. - * The Intel BigSur (a.k.a. HP i2000) has this problem. In this - * case, we can't use the EFI memory map to validate mmap requests. - */ - if (!efi_memmap_has_mmio()) - return 1; + if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) { + if (!(md->attribute & EFI_MEMORY_WB)) + return 0; + if (*size > md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr) + *size = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr; + return 1; + } + } return 0; } @@ -795,6 +707,32 @@ efi_uart_console_only(void) return 0; } +#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT) + +static inline u64 +kmd_end(kern_memdesc_t *kmd) +{ + return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT)); +} + +static inline u64 +efi_md_end(efi_memory_desc_t *md) +{ + return (md->phys_addr + efi_md_size(md)); +} + +static inline int +efi_wb(efi_memory_desc_t *md) +{ + return (md->attribute & EFI_MEMORY_WB); +} + +static inline int +efi_uc(efi_memory_desc_t *md) +{ + return (md->attribute & EFI_MEMORY_UC); +} + /* * Look for the first granule aligned memory descriptor memory * that is big enough to hold EFI memory map. Make sure this diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index 7a6ffd613789..0741b066b98f 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -1600,6 +1600,5 @@ sys_call_table: data8 sys_inotify_init data8 sys_inotify_add_watch data8 sys_inotify_rm_watch - data8 sys_migrate_pages // 1280 .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/trunk/arch/ia64/kernel/head.S b/trunk/arch/ia64/kernel/head.S index fbc7ea35dd57..bfe65b2e8621 100644 --- a/trunk/arch/ia64/kernel/head.S +++ b/trunk/arch/ia64/kernel/head.S @@ -1060,7 +1060,7 @@ SET_REG(b5); * the clobber lists for spin_lock() in include/asm-ia64/spinlock.h. */ -#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4) .prologue diff --git a/trunk/arch/ia64/kernel/ia64_ksyms.c b/trunk/arch/ia64/kernel/ia64_ksyms.c index e72de580ebbf..5db9d3bcbbcb 100644 --- a/trunk/arch/ia64/kernel/ia64_ksyms.c +++ b/trunk/arch/ia64/kernel/ia64_ksyms.c @@ -103,7 +103,7 @@ EXPORT_SYMBOL(unw_init_running); #ifdef ASM_SUPPORTED # ifdef CONFIG_SMP -# if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) /* * This is not a normal routine and we don't want a function descriptor for it, so we use * a fake declaration here. diff --git a/trunk/arch/ia64/kernel/ptrace.c b/trunk/arch/ia64/kernel/ptrace.c index 8d88eeea02d1..4b19d0410632 100644 --- a/trunk/arch/ia64/kernel/ptrace.c +++ b/trunk/arch/ia64/kernel/ptrace.c @@ -1422,7 +1422,14 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) lock_kernel(); ret = -EPERM; if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) + goto out; + ret = security_ptrace(current->parent, current); + if (ret) + goto out; + current->ptrace |= PT_PTRACED; + ret = 0; goto out; } diff --git a/trunk/arch/ia64/oprofile/backtrace.c b/trunk/arch/ia64/oprofile/backtrace.c index adb01566bd57..b7dabbfb0d61 100644 --- a/trunk/arch/ia64/oprofile/backtrace.c +++ b/trunk/arch/ia64/oprofile/backtrace.c @@ -32,7 +32,7 @@ typedef struct u64 *prev_pfs_loc; /* state for WAR for old spinlock ool code */ } ia64_backtrace_t; -#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) /* * Returns non-zero if the PC is in the spinlock contention out-of-line code * with non-standard calling sequence (on older compilers). diff --git a/trunk/arch/m32r/kernel/process.c b/trunk/arch/m32r/kernel/process.c index 3bf55d92933f..cc4b571e5db7 100644 --- a/trunk/arch/m32r/kernel/process.c +++ b/trunk/arch/m32r/kernel/process.c @@ -50,10 +50,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) * Powermanagement idle function, if any.. */ void (*pm_idle)(void) = NULL; -EXPORT_SYMBOL(pm_idle); - -void (*pm_power_off)(void) = NULL; -EXPORT_SYMBOL(pm_power_off); void disable_hlt(void) { diff --git a/trunk/arch/m32r/kernel/ptrace.c b/trunk/arch/m32r/kernel/ptrace.c index 9b75caaf5cec..078d2a0e71c2 100644 --- a/trunk/arch/m32r/kernel/ptrace.c +++ b/trunk/arch/m32r/kernel/ptrace.c @@ -762,16 +762,28 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) int ret; lock_kernel(); + ret = -EPERM; if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) + goto out; + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + ret = 0; goto out; } + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + goto out; - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ goto out; - } if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index 96b919828053..1dd5d18b2201 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -10,6 +10,10 @@ config MMU bool default y +config UID16 + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/m68knommu/Kconfig b/trunk/arch/m68knommu/Kconfig index e2a6e8648960..b96498120fe9 100644 --- a/trunk/arch/m68knommu/Kconfig +++ b/trunk/arch/m68knommu/Kconfig @@ -17,6 +17,10 @@ config FPU bool default n +config UID16 + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/mips/kernel/ptrace32.c b/trunk/arch/mips/kernel/ptrace32.c index 7e55457a491f..9a9b04972132 100644 --- a/trunk/arch/mips/kernel/ptrace32.c +++ b/trunk/arch/mips/kernel/ptrace32.c @@ -57,16 +57,30 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) (unsigned long) data); #endif lock_kernel(); + ret = -EPERM; if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) + goto out; + if ((ret = security_ptrace(current->parent, current))) + goto out; + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + ret = 0; goto out; } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out; - } + + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out_tsk; if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); diff --git a/trunk/arch/mips/sgi-ip27/ip27-berr.c b/trunk/arch/mips/sgi-ip27/ip27-berr.c index ce907eda221b..07631a97670b 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-berr.c +++ b/trunk/arch/mips/sgi-ip27/ip27-berr.c @@ -11,7 +11,6 @@ #include #include #include /* for SIGBUS */ -#include /* schow_regs(), force_sig() */ #include #include diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index e77a06e9621e..874a283edb95 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -19,6 +19,9 @@ config MMU config STACK_GROWSUP def_bool y +config UID16 + bool + config RWSEM_GENERIC_SPINLOCK def_bool y diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 331483ace0d9..db93dbc0e21a 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -26,6 +26,9 @@ config MMU bool default y +config UID16 + bool + config GENERIC_HARDIRQS bool default y diff --git a/trunk/arch/powerpc/kernel/ppc_ksyms.c b/trunk/arch/powerpc/kernel/ppc_ksyms.c index 94db25708456..b2758148a0de 100644 --- a/trunk/arch/powerpc/kernel/ppc_ksyms.c +++ b/trunk/arch/powerpc/kernel/ppc_ksyms.c @@ -76,11 +76,6 @@ EXPORT_SYMBOL(single_step_exception); EXPORT_SYMBOL(sys_sigreturn); #endif -#if defined(CONFIG_PPC_PREP) -EXPORT_SYMBOL(_prep_type); -EXPORT_SYMBOL(ucSystemType); -#endif - EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strcat); diff --git a/trunk/arch/powerpc/kernel/ptrace32.c b/trunk/arch/powerpc/kernel/ptrace32.c index 826ee3d056de..61762640b877 100644 --- a/trunk/arch/powerpc/kernel/ptrace32.c +++ b/trunk/arch/powerpc/kernel/ptrace32.c @@ -45,19 +45,33 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, unsigned long data) { struct task_struct *child; - int ret; + int ret = -EPERM; lock_kernel(); if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) + goto out; + ret = security_ptrace(current->parent, current); + if (ret) + goto out; + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + ret = 0; goto out; } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out; - } + + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out_tsk; if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); diff --git a/trunk/arch/ppc/Kconfig b/trunk/arch/ppc/Kconfig index e396f4591d59..cc3f64c084c5 100644 --- a/trunk/arch/ppc/Kconfig +++ b/trunk/arch/ppc/Kconfig @@ -8,6 +8,9 @@ config MMU bool default y +config UID16 + bool + config GENERIC_HARDIRQS bool default y diff --git a/trunk/arch/ppc/kernel/ppc_ksyms.c b/trunk/arch/ppc/kernel/ppc_ksyms.c index bb6a5c6a64be..28f1082e5040 100644 --- a/trunk/arch/ppc/kernel/ppc_ksyms.c +++ b/trunk/arch/ppc/kernel/ppc_ksyms.c @@ -82,10 +82,6 @@ EXPORT_SYMBOL(ppc_n_lost_interrupts); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); EXPORT_SYMBOL(DMA_MODE_READ); EXPORT_SYMBOL(DMA_MODE_WRITE); -#if defined(CONFIG_PPC_PREP) -EXPORT_SYMBOL(_prep_type); -EXPORT_SYMBOL(ucSystemType); -#endif #if !defined(__INLINE_BITOPS) EXPORT_SYMBOL(set_bit); diff --git a/trunk/arch/ppc/platforms/prep_setup.c b/trunk/arch/ppc/platforms/prep_setup.c index 4415748071dc..a6a188910a1a 100644 --- a/trunk/arch/ppc/platforms/prep_setup.c +++ b/trunk/arch/ppc/platforms/prep_setup.c @@ -72,7 +72,6 @@ TODC_ALLOC(); -unsigned char ucSystemType; unsigned char ucBoardRev; unsigned char ucBoardRevMaj, ucBoardRevMin; diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index cc02232aa96e..8ecda6d66de4 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -712,18 +712,35 @@ sys_ptrace(long request, long pid, long addr, long data) int ret; lock_kernel(); + if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; + /* are we already being traced? */ + ret = -EPERM; + if (current->ptrace & PT_PTRACED) + goto out; + ret = security_ptrace(current->parent, current); + if (ret) + goto out; + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + goto out; } - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out; + + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out; - } ret = do_ptrace(child, request, addr, data); + put_task_struct(child); out: unlock_kernel(); diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 8cf6d437a630..64f5ae0ff96d 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -14,6 +14,10 @@ config SUPERH gaming console. The SuperH port has a home page at . +config UID16 + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/sh64/kernel/time.c b/trunk/arch/sh64/kernel/time.c index 1195af37ee5a..870fe5327e09 100644 --- a/trunk/arch/sh64/kernel/time.c +++ b/trunk/arch/sh64/kernel/time.c @@ -417,7 +417,7 @@ static __init unsigned int get_cpu_hz(void) /* ** Regardless the toolchain, force the compiler to use the ** arbitrary register r3 as a clock tick counter. - ** NOTE: r3 must be in accordance with sh64_rtc_interrupt() + ** NOTE: r3 must be in accordance with rtc_interrupt() */ register unsigned long long __rtc_irq_flag __asm__ ("r3"); @@ -482,8 +482,7 @@ static __init unsigned int get_cpu_hz(void) #endif } -static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { ctrl_outb(0, RCR1); /* Disable Carry Interrupts */ regs->regs[3] = 1; /* Using r3 */ @@ -492,7 +491,7 @@ static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id, } static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL}; -static struct irqaction irq1 = { sh64_rtc_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "rtc", NULL, NULL}; +static struct irqaction irq1 = { rtc_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "rtc", NULL, NULL}; void __init time_init(void) { diff --git a/trunk/arch/sparc/Kconfig b/trunk/arch/sparc/Kconfig index f944b58cdfe7..56c34e7fd4ee 100644 --- a/trunk/arch/sparc/Kconfig +++ b/trunk/arch/sparc/Kconfig @@ -9,6 +9,10 @@ config MMU bool default y +config UID16 + bool + default y + config HIGHMEM bool default y diff --git a/trunk/arch/sparc/kernel/ptrace.c b/trunk/arch/sparc/kernel/ptrace.c index fc470c0e9dc6..475c4c13462c 100644 --- a/trunk/arch/sparc/kernel/ptrace.c +++ b/trunk/arch/sparc/kernel/ptrace.c @@ -286,17 +286,40 @@ asmlinkage void do_ptrace(struct pt_regs *regs) s, (int) request, (int) pid, addr, data, addr2); } #endif - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + int my_ret; + + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) { + pt_error_return(regs, EPERM); + goto out; + } + my_ret = security_ptrace(current->parent, current); + if (my_ret) { + pt_error_return(regs, -my_ret); + goto out; + } + + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; pt_succ_return(regs, 0); goto out; } +#ifndef ALLOW_INIT_TRACING + if (pid == 1) { + /* Can't dork with init. */ + pt_error_return(regs, EPERM); + goto out; + } +#endif + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - pt_error_return(regs, -ret); + if (!child) { + pt_error_return(regs, ESRCH); goto out; } diff --git a/trunk/arch/sparc64/Kconfig b/trunk/arch/sparc64/Kconfig index b775ceb4cf98..c4b7ad70cd7c 100644 --- a/trunk/arch/sparc64/Kconfig +++ b/trunk/arch/sparc64/Kconfig @@ -309,6 +309,11 @@ config COMPAT depends on SPARC32_COMPAT default y +config UID16 + bool + depends on SPARC32_COMPAT + default y + config BINFMT_ELF32 tristate "Kernel support for 32-bit ELF binaries" depends on SPARC32_COMPAT diff --git a/trunk/arch/sparc64/kernel/ptrace.c b/trunk/arch/sparc64/kernel/ptrace.c index 84d3df2264cb..774ecbb8a031 100644 --- a/trunk/arch/sparc64/kernel/ptrace.c +++ b/trunk/arch/sparc64/kernel/ptrace.c @@ -198,15 +198,39 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } #endif if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); + int ret; + + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) { + pt_error_return(regs, EPERM); + goto out; + } + ret = security_ptrace(current->parent, current); + if (ret) { + pt_error_return(regs, -ret); + goto out; + } + + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; pt_succ_return(regs, 0); goto out; } +#ifndef ALLOW_INIT_TRACING + if (pid == 1) { + /* Can't dork with init. */ + pt_error_return(regs, EPERM); + goto out; + } +#endif + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - pt_error_return(regs, -ret); + if (!child) { + pt_error_return(regs, ESRCH); goto out; } diff --git a/trunk/arch/um/Kconfig b/trunk/arch/um/Kconfig index b4ff2e576021..1eb21de9d1b5 100644 --- a/trunk/arch/um/Kconfig +++ b/trunk/arch/um/Kconfig @@ -22,6 +22,10 @@ config SBUS config PCI bool +config UID16 + bool + default y + config GENERIC_CALIBRATE_DELAY bool default y @@ -79,7 +83,7 @@ config KERNEL_HALF_GIGS of physical memory. config MODE_SKAS - bool "Separate Kernel Address Space support" if MODE_TT + bool "Separate Kernel Address Space support" default y help This option controls whether skas (separate kernel address space) diff --git a/trunk/arch/um/drivers/ubd_kern.c b/trunk/arch/um/drivers/ubd_kern.c index 3a93c6f772fa..73f9652b2ee9 100644 --- a/trunk/arch/um/drivers/ubd_kern.c +++ b/trunk/arch/um/drivers/ubd_kern.c @@ -117,7 +117,6 @@ static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); -static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); #define MAX_DEV (8) @@ -126,7 +125,6 @@ static struct block_device_operations ubd_blops = { .open = ubd_open, .release = ubd_release, .ioctl = ubd_ioctl, - .getgeo = ubd_getgeo, }; /* Protected by the queue_lock */ @@ -1060,16 +1058,6 @@ static void do_ubd_request(request_queue_t *q) } } -static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ubd *dev = bdev->bd_disk->private_data; - - geo->heads = 128; - geo->sectors = 32; - geo->cylinders = dev->size / (128 * 32 * 512); - return 0; -} - static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { @@ -1082,7 +1070,16 @@ static int ubd_ioctl(struct inode * inode, struct file * file, }; switch (cmd) { + struct hd_geometry g; struct cdrom_volctrl volume; + case HDIO_GETGEO: + if(!loc) return(-EINVAL); + g.heads = 128; + g.sectors = 32; + g.cylinders = dev->size / (128 * 32 * 512); + g.start = get_start_sect(inode->i_bdev); + return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0); + case HDIO_GET_IDENTITY: ubd_id.cyls = dev->size / (128 * 32 * 512); if(copy_to_user((char __user *) arg, (char *) &ubd_id, diff --git a/trunk/arch/um/include/kern_util.h b/trunk/arch/um/include/kern_util.h index 8f4e46d677ab..e5fec5570199 100644 --- a/trunk/arch/um/include/kern_util.h +++ b/trunk/arch/um/include/kern_util.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -10,19 +10,6 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" -typedef void (*kern_hndl)(int, union uml_pt_regs *); - -struct kern_handlers { - kern_hndl relay_signal; - kern_hndl winch; - kern_hndl bus_handler; - kern_hndl page_fault; - kern_hndl sigio_handler; - kern_hndl timer_handler; -}; - -extern struct kern_handlers handlinfo_kern; - extern int ncpus; extern char *linux_prog; extern char *gdb_init; @@ -64,6 +51,8 @@ extern void timer_handler(int sig, union uml_pt_regs *regs); extern int set_signals(int enable); extern void force_sigbus(void); extern int pid_to_processor_id(int pid); +extern void block_signals(void); +extern void unblock_signals(void); extern void deliver_signals(void *t); extern int next_syscall_index(int max); extern int next_trap_index(int max); @@ -122,8 +111,6 @@ extern void arch_switch(void); extern void free_irq(unsigned int, void *); extern int um_in_interrupt(void); extern int cpu(void); -extern void segv_handler(int sig, union uml_pt_regs *regs); -extern void sigio_handler(int sig, union uml_pt_regs *regs); #endif diff --git a/trunk/arch/um/include/os.h b/trunk/arch/um/include/os.h index dd72d66cf0ed..c279ee6d89e4 100644 --- a/trunk/arch/um/include/os.h +++ b/trunk/arch/um/include/os.h @@ -9,8 +9,6 @@ #include "uml-config.h" #include "asm/types.h" #include "../os/include/file.h" -#include "sysdep/ptrace.h" -#include "kern_util.h" #define OS_TYPE_FILE 1 #define OS_TYPE_DIR 2 @@ -221,18 +219,4 @@ extern int umid_file_name(char *name, char *buf, int len); extern int set_umid(char *name); extern char *get_umid(void); -/* signal.c */ -extern void set_sigstack(void *sig_stack, int size); -extern void remove_sigstack(void); -extern void set_handler(int sig, void (*handler)(int), int flags, ...); -extern int change_sig(int signal, int on); -extern void block_signals(void); -extern void unblock_signals(void); -extern int get_signals(void); -extern int set_signals(int enable); - -/* trap.c */ -extern void os_fill_handlinfo(struct kern_handlers h); -extern void do_longjmp(void *p, int val); - #endif diff --git a/trunk/arch/um/include/signal_user.h b/trunk/arch/um/include/signal_user.h new file mode 100644 index 000000000000..b075e543d864 --- /dev/null +++ b/trunk/arch/um/include/signal_user.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SIGNAL_USER_H__ +#define __SIGNAL_USER_H__ + +extern int signal_stack_size; + +extern int change_sig(int signal, int on); +extern void set_sigstack(void *stack, int size); +extern void set_handler(int sig, void (*handler)(int), int flags, ...); +extern int set_signals(int enable); +extern int get_signals(void); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/user_util.h b/trunk/arch/um/include/user_util.h index c1dbd77b073f..b9984003e603 100644 --- a/trunk/arch/um/include/user_util.h +++ b/trunk/arch/um/include/user_util.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -23,7 +23,12 @@ struct cpu_task { extern struct cpu_task cpu_tasks[]; -extern void (*sig_info[])(int, union uml_pt_regs *); +struct signal_info { + void (*handler)(int, union uml_pt_regs *); + int is_irq; +}; + +extern struct signal_info sig_info[]; extern unsigned long low_physmem; extern unsigned long high_physmem; @@ -59,6 +64,7 @@ extern void setup_machinename(char *machine_out); extern void setup_hostinfo(void); extern void do_exec(int old_pid, int new_pid); extern void tracer_panic(char *msg, ...); +extern void do_longjmp(void *p, int val); extern int detach(int pid, int sig); extern int attach(int pid); extern void kill_child_dead(int pid); diff --git a/trunk/arch/um/kernel/Makefile b/trunk/arch/um/kernel/Makefile index 193cc2b7448d..6f7700593a6f 100644 --- a/trunk/arch/um/kernel/Makefile +++ b/trunk/arch/um/kernel/Makefile @@ -9,8 +9,8 @@ clean-files := obj-y = config.o exec_kern.o exitcode.o \ init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ - signal_kern.o smp.o syscall_kern.o sysrq.o time.o \ - time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o \ + signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ + time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o umid.o \ user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o diff --git a/trunk/arch/um/kernel/irq_user.c b/trunk/arch/um/kernel/irq_user.c index 0e32f5f4a887..50a2aa35cda9 100644 --- a/trunk/arch/um/kernel/irq_user.c +++ b/trunk/arch/um/kernel/irq_user.c @@ -15,6 +15,7 @@ #include "kern_util.h" #include "user.h" #include "process.h" +#include "signal_user.h" #include "sigio.h" #include "irq_user.h" #include "os.h" diff --git a/trunk/arch/um/kernel/process_kern.c b/trunk/arch/um/kernel/process_kern.c index d2d3f256778c..651abf255bc5 100644 --- a/trunk/arch/um/kernel/process_kern.c +++ b/trunk/arch/um/kernel/process_kern.c @@ -36,6 +36,7 @@ #include "kern_util.h" #include "kern.h" #include "signal_kern.h" +#include "signal_user.h" #include "init.h" #include "irq_user.h" #include "mem_user.h" diff --git a/trunk/arch/um/kernel/reboot.c b/trunk/arch/um/kernel/reboot.c index 6f1a3a288117..a637e885c583 100644 --- a/trunk/arch/um/kernel/reboot.c +++ b/trunk/arch/um/kernel/reboot.c @@ -12,8 +12,6 @@ #include "mode.h" #include "choose-mode.h" -void (*pm_power_off)(void); - #ifdef CONFIG_SMP static void kill_idlers(int me) { diff --git a/trunk/arch/um/kernel/signal_kern.c b/trunk/arch/um/kernel/signal_kern.c index 7b0e0e81c161..03618bd13d55 100644 --- a/trunk/arch/um/kernel/signal_kern.c +++ b/trunk/arch/um/kernel/signal_kern.c @@ -22,6 +22,7 @@ #include "asm/ucontext.h" #include "kern_util.h" #include "signal_kern.h" +#include "signal_user.h" #include "kern.h" #include "frame_kern.h" #include "sigcontext.h" diff --git a/trunk/arch/um/kernel/signal_user.c b/trunk/arch/um/kernel/signal_user.c new file mode 100644 index 000000000000..62f457835fb1 --- /dev/null +++ b/trunk/arch/um/kernel/signal_user.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "user_util.h" +#include "kern_util.h" +#include "user.h" +#include "signal_user.h" +#include "signal_kern.h" +#include "sysdep/sigcontext.h" +#include "sigcontext.h" + +void set_sigstack(void *sig_stack, int size) +{ + stack_t stack = ((stack_t) { .ss_flags = 0, + .ss_sp = (__ptr_t) sig_stack, + .ss_size = size - sizeof(void *) }); + + if(sigaltstack(&stack, NULL) != 0) + panic("enabling signal stack failed, errno = %d\n", errno); +} + +void set_handler(int sig, void (*handler)(int), int flags, ...) +{ + struct sigaction action; + va_list ap; + int mask; + + va_start(ap, flags); + action.sa_handler = handler; + sigemptyset(&action.sa_mask); + while((mask = va_arg(ap, int)) != -1){ + sigaddset(&action.sa_mask, mask); + } + va_end(ap); + action.sa_flags = flags; + action.sa_restorer = NULL; + if(sigaction(sig, &action, NULL) < 0) + panic("sigaction failed"); +} + +int change_sig(int signal, int on) +{ + sigset_t sigset, old; + + sigemptyset(&sigset); + sigaddset(&sigset, signal); + sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); + return(!sigismember(&old, signal)); +} + +/* Both here and in set/get_signal we don't touch SIGPROF, because we must not + * disable profiling; it's safe because the profiling code does not interact + * with the kernel code at all.*/ + +static void change_signals(int type) +{ + sigset_t mask; + + sigemptyset(&mask); + sigaddset(&mask, SIGVTALRM); + sigaddset(&mask, SIGALRM); + sigaddset(&mask, SIGIO); + if(sigprocmask(type, &mask, NULL) < 0) + panic("Failed to change signal mask - errno = %d", errno); +} + +void block_signals(void) +{ + change_signals(SIG_BLOCK); +} + +void unblock_signals(void) +{ + change_signals(SIG_UNBLOCK); +} + +/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled + * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to + * be able to profile all of UML, not just the non-critical sections. If + * profiling is not thread-safe, then that is not my problem. We can disable + * profiling when SMP is enabled in that case. + */ +#define SIGIO_BIT 0 +#define SIGVTALRM_BIT 1 + +static int enable_mask(sigset_t *mask) +{ + int sigs; + + sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; + sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; + sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; + return(sigs); +} + +int get_signals(void) +{ + sigset_t mask; + + if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) + panic("Failed to get signal mask"); + return(enable_mask(&mask)); +} + +int set_signals(int enable) +{ + sigset_t mask; + int ret; + + sigemptyset(&mask); + if(enable & (1 << SIGIO_BIT)) + sigaddset(&mask, SIGIO); + if(enable & (1 << SIGVTALRM_BIT)){ + sigaddset(&mask, SIGVTALRM); + sigaddset(&mask, SIGALRM); + } + + /* This is safe - sigprocmask is guaranteed to copy locally the + * value of new_set, do his work and then, at the end, write to + * old_set. + */ + if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) + panic("Failed to enable signals"); + ret = enable_mask(&mask); + sigemptyset(&mask); + if((enable & (1 << SIGIO_BIT)) == 0) + sigaddset(&mask, SIGIO); + if((enable & (1 << SIGVTALRM_BIT)) == 0){ + sigaddset(&mask, SIGVTALRM); + sigaddset(&mask, SIGALRM); + } + if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) + panic("Failed to block signals"); + + return(ret); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/skas/Makefile b/trunk/arch/um/kernel/skas/Makefile index 7a9fc16d71d4..8de471b59c1c 100644 --- a/trunk/arch/um/kernel/skas/Makefile +++ b/trunk/arch/um/kernel/skas/Makefile @@ -4,7 +4,7 @@ # obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ - syscall.o tlb.o uaccess.o + syscall.o tlb.o trap_user.o uaccess.o USER_OBJS := process.o clone.o diff --git a/trunk/arch/um/kernel/skas/include/skas.h b/trunk/arch/um/kernel/skas/include/skas.h index 01d489de3986..daa2f85b684c 100644 --- a/trunk/arch/um/kernel/skas/include/skas.h +++ b/trunk/arch/um/kernel/skas/include/skas.h @@ -22,6 +22,7 @@ extern int start_idle_thread(void *stack, void *switch_buf_ptr, extern int user_thread(unsigned long stack, int flags); extern void userspace(union uml_pt_regs *regs); extern void new_thread_proc(void *stack, void (*handler)(int sig)); +extern void remove_sigstack(void); extern void new_thread_handler(int sig); extern void handle_syscall(union uml_pt_regs *regs); extern int map(struct mm_id * mm_idp, unsigned long virt, diff --git a/trunk/arch/um/kernel/skas/process.c b/trunk/arch/um/kernel/skas/process.c index 9264d4021dfe..599d679bd4fc 100644 --- a/trunk/arch/um/kernel/skas/process.c +++ b/trunk/arch/um/kernel/skas/process.c @@ -31,6 +31,7 @@ #include "proc_mm.h" #include "skas_ptrace.h" #include "chan_user.h" +#include "signal_user.h" #include "registers.h" #include "mem.h" #include "uml-config.h" @@ -513,6 +514,16 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) siglongjmp(**switch_buf, 1); } +void remove_sigstack(void) +{ + stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, + .ss_sp = NULL, + .ss_size = 0 }); + + if(sigaltstack(&stack, NULL) != 0) + panic("disabling signal stack failed, errno = %d\n", errno); +} + void initial_thread_cb_skas(void (*proc)(void *), void *arg) { sigjmp_buf here; diff --git a/trunk/arch/um/kernel/skas/process_kern.c b/trunk/arch/um/kernel/skas/process_kern.c index 09790ccb161c..9c990253966c 100644 --- a/trunk/arch/um/kernel/skas/process_kern.c +++ b/trunk/arch/um/kernel/skas/process_kern.c @@ -14,6 +14,7 @@ #include "asm/atomic.h" #include "kern_util.h" #include "time_user.h" +#include "signal_user.h" #include "skas.h" #include "os.h" #include "user_util.h" diff --git a/trunk/arch/um/os-Linux/skas/trap.c b/trunk/arch/um/kernel/skas/trap_user.c similarity index 53% rename from trunk/arch/um/os-Linux/skas/trap.c rename to trunk/arch/um/kernel/skas/trap_user.c index 9ad5fbec4593..9950a6716fe5 100644 --- a/trunk/arch/um/os-Linux/skas/trap.c +++ b/trunk/arch/um/kernel/skas/trap_user.c @@ -1,10 +1,11 @@ -/* +/* * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include #include +#include "signal_user.h" #include "user_util.h" #include "kern_util.h" #include "task.h" @@ -13,13 +14,12 @@ #include "ptrace_user.h" #include "sysdep/ptrace.h" #include "sysdep/ptrace_user.h" -#include "os.h" void sig_handler_common_skas(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; struct skas_regs *r; - void (*handler)(int, union uml_pt_regs *); + struct signal_info *info; int save_errno = errno; int save_user; @@ -34,22 +34,17 @@ void sig_handler_common_skas(int sig, void *sc_ptr) r = &TASK_REGS(get_current())->skas; save_user = r->is_user; r->is_user = 0; - if ( sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGILL || - sig == SIGTRAP ) { - GET_FAULTINFO_FROM_SC(r->faultinfo, sc); - } + if ( sig == SIGFPE || sig == SIGSEGV || + sig == SIGBUS || sig == SIGILL || + sig == SIGTRAP ) { + GET_FAULTINFO_FROM_SC(r->faultinfo, sc); + } change_sig(SIGUSR1, 1); + info = &sig_info[sig]; + if(!info->is_irq) unblock_signals(); - handler = sig_info[sig]; - - /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ - if (sig != SIGIO && sig != SIGWINCH && - sig != SIGVTALRM && sig != SIGALRM) - unblock_signals(); - - handler(sig, (union uml_pt_regs *) r); + (*info->handler)(sig, (union uml_pt_regs *) r); errno = save_errno; r->is_user = save_user; @@ -59,15 +54,25 @@ extern int ptrace_faultinfo; void user_signal(int sig, union uml_pt_regs *regs, int pid) { - void (*handler)(int, union uml_pt_regs *); - int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || - (sig == SIGILL) || (sig == SIGTRAP)); + struct signal_info *info; + int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || + (sig == SIGILL) || (sig == SIGTRAP)); if (segv) get_skas_faultinfo(pid, ®s->skas.faultinfo); - - handler = sig_info[sig]; - handler(sig, (union uml_pt_regs *) regs); + info = &sig_info[sig]; + (*info->handler)(sig, regs); unblock_signals(); } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/time.c b/trunk/arch/um/kernel/time.c index 11f518a7e156..c40b611e3d93 100644 --- a/trunk/arch/um/kernel/time.c +++ b/trunk/arch/um/kernel/time.c @@ -14,9 +14,9 @@ #include "kern_util.h" #include "user.h" #include "process.h" +#include "signal_user.h" #include "time_user.h" #include "kern_constants.h" -#include "os.h" /* XXX This really needs to be declared and initialized in a kernel file since * it's in diff --git a/trunk/arch/um/kernel/trap_kern.c b/trunk/arch/um/kernel/trap_kern.c index d56046c2aba2..0d4c10a73607 100644 --- a/trunk/arch/um/kernel/trap_kern.c +++ b/trunk/arch/um/kernel/trap_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -26,13 +26,9 @@ #include "mconsole_kern.h" #include "mem.h" #include "mem_kern.h" -#include "sysdep/sigcontext.h" -#include "sysdep/ptrace.h" -#include "os.h" #ifdef CONFIG_MODE_SKAS #include "skas.h" #endif -#include "os.h" /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ int handle_page_fault(unsigned long address, unsigned long ip, @@ -129,25 +125,6 @@ int handle_page_fault(unsigned long address, unsigned long ip, goto out; } -void segv_handler(int sig, union uml_pt_regs *regs) -{ - struct faultinfo * fi = UPT_FAULTINFO(regs); - - if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ - bad_segv(*fi, UPT_IP(regs)); - return; - } - segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); -} - -struct kern_handlers handlinfo_kern = { - .relay_signal = relay_signal, - .winch = winch, - .bus_handler = relay_signal, - .page_fault = segv_handler, - .sigio_handler = sigio_handler, - .timer_handler = timer_handler -}; /* * We give a *copy* of the faultinfo in the regs to segv. * This must be done, since nesting SEGVs could overwrite diff --git a/trunk/arch/um/kernel/trap_user.c b/trunk/arch/um/kernel/trap_user.c new file mode 100644 index 000000000000..e9ccd6b8d3c7 --- /dev/null +++ b/trunk/arch/um/kernel/trap_user.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "init.h" +#include "sysdep/ptrace.h" +#include "sigcontext.h" +#include "sysdep/sigcontext.h" +#include "irq_user.h" +#include "signal_user.h" +#include "time_user.h" +#include "task.h" +#include "mode.h" +#include "choose-mode.h" +#include "kern_util.h" +#include "user_util.h" +#include "os.h" + +void kill_child_dead(int pid) +{ + kill(pid, SIGKILL); + kill(pid, SIGCONT); + do { + int n; + CATCH_EINTR(n = waitpid(pid, NULL, 0)); + if (n > 0) + kill(pid, SIGCONT); + else + break; + } while(1); +} + +void segv_handler(int sig, union uml_pt_regs *regs) +{ + struct faultinfo * fi = UPT_FAULTINFO(regs); + + if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ + bad_segv(*fi, UPT_IP(regs)); + return; + } + segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); +} + +void usr2_handler(int sig, union uml_pt_regs *regs) +{ + CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); +} + +struct signal_info sig_info[] = { + [ SIGTRAP ] { .handler = relay_signal, + .is_irq = 0 }, + [ SIGFPE ] { .handler = relay_signal, + .is_irq = 0 }, + [ SIGILL ] { .handler = relay_signal, + .is_irq = 0 }, + [ SIGWINCH ] { .handler = winch, + .is_irq = 1 }, + [ SIGBUS ] { .handler = bus_handler, + .is_irq = 0 }, + [ SIGSEGV] { .handler = segv_handler, + .is_irq = 0 }, + [ SIGIO ] { .handler = sigio_handler, + .is_irq = 1 }, + [ SIGVTALRM ] { .handler = timer_handler, + .is_irq = 1 }, + [ SIGALRM ] { .handler = timer_handler, + .is_irq = 1 }, + [ SIGUSR2 ] { .handler = usr2_handler, + .is_irq = 0 }, +}; + +void do_longjmp(void *b, int val) +{ + sigjmp_buf *buf = b; + + siglongjmp(*buf, val); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/kernel/tt/exec_kern.c b/trunk/arch/um/kernel/tt/exec_kern.c index 136e54c47d37..065b504a653b 100644 --- a/trunk/arch/um/kernel/tt/exec_kern.c +++ b/trunk/arch/um/kernel/tt/exec_kern.c @@ -14,6 +14,7 @@ #include "kern_util.h" #include "irq_user.h" #include "time_user.h" +#include "signal_user.h" #include "mem_user.h" #include "os.h" #include "tlb.h" diff --git a/trunk/arch/um/kernel/tt/process_kern.c b/trunk/arch/um/kernel/tt/process_kern.c index 14d4622a5fb8..cfaa373a6e77 100644 --- a/trunk/arch/um/kernel/tt/process_kern.c +++ b/trunk/arch/um/kernel/tt/process_kern.c @@ -13,6 +13,7 @@ #include "asm/ptrace.h" #include "asm/tlbflush.h" #include "irq_user.h" +#include "signal_user.h" #include "kern_util.h" #include "user_util.h" #include "os.h" diff --git a/trunk/arch/um/kernel/tt/tracer.c b/trunk/arch/um/kernel/tt/tracer.c index 71daae24e48a..d11e7399d7a1 100644 --- a/trunk/arch/um/kernel/tt/tracer.c +++ b/trunk/arch/um/kernel/tt/tracer.c @@ -19,6 +19,7 @@ #include "sigcontext.h" #include "sysdep/sigcontext.h" #include "os.h" +#include "signal_user.h" #include "user_util.h" #include "mem_user.h" #include "process.h" diff --git a/trunk/arch/um/kernel/tt/trap_user.c b/trunk/arch/um/kernel/tt/trap_user.c index a414c529fbcd..fc108615beaf 100644 --- a/trunk/arch/um/kernel/tt/trap_user.c +++ b/trunk/arch/um/kernel/tt/trap_user.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -8,18 +8,18 @@ #include #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" +#include "signal_user.h" #include "user_util.h" #include "kern_util.h" #include "task.h" #include "tt.h" -#include "os.h" void sig_handler_common_tt(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; struct tt_regs save_regs, *r; + struct signal_info *info; int save_errno = errno, is_user; - void (*handler)(int, union uml_pt_regs *); /* This is done because to allow SIGSEGV to be delivered inside a SEGV * handler. This can happen in copy_user, and if SEGV is disabled, @@ -40,14 +40,10 @@ void sig_handler_common_tt(int sig, void *sc_ptr) if(sig != SIGUSR2) r->syscall = -1; - handler = sig_info[sig]; - - /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ - if (sig != SIGIO && sig != SIGWINCH && - sig != SIGVTALRM && sig != SIGALRM) - unblock_signals(); + info = &sig_info[sig]; + if(!info->is_irq) unblock_signals(); - handler(sig, (union uml_pt_regs *) r); + (*info->handler)(sig, (union uml_pt_regs *) r); if(is_user){ interrupt_end(); diff --git a/trunk/arch/um/kernel/um_arch.c b/trunk/arch/um/kernel/um_arch.c index 73747ac19774..26626b2b9172 100644 --- a/trunk/arch/um/kernel/um_arch.c +++ b/trunk/arch/um/kernel/um_arch.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -363,11 +363,6 @@ int linux_main(int argc, char **argv) uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, &host_task_size, &task_size); - /* - * Setting up handlers to 'sig_info' struct - */ - os_fill_handlinfo(handlinfo_kern); - brk_start = (unsigned long) sbrk(0); CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); /* Increase physical memory size for exec-shield users diff --git a/trunk/arch/um/os-Linux/Makefile b/trunk/arch/um/os-Linux/Makefile index 40c7d6b1df68..11e30b13e318 100644 --- a/trunk/arch/um/os-Linux/Makefile +++ b/trunk/arch/um/os-Linux/Makefile @@ -4,13 +4,11 @@ # obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ - start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \ - drivers/ sys-$(SUBARCH)/ - -obj-$(CONFIG_MODE_SKAS) += skas/ + start_up.o time.o tt.o tty.o uaccess.o umid.o user_syms.o drivers/ \ + sys-$(SUBARCH)/ USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ - start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o + start_up.o time.o tt.o tty.o uaccess.o umid.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/trunk/arch/um/os-Linux/main.c b/trunk/arch/um/os-Linux/main.c index 172c8474453c..23da27d22569 100644 --- a/trunk/arch/um/os-Linux/main.c +++ b/trunk/arch/um/os-Linux/main.c @@ -16,6 +16,7 @@ #include "user_util.h" #include "kern_util.h" #include "mem_user.h" +#include "signal_user.h" #include "time_user.h" #include "irq_user.h" #include "user.h" diff --git a/trunk/arch/um/os-Linux/process.c b/trunk/arch/um/os-Linux/process.c index 39815c6b5e45..d9c52387c4a1 100644 --- a/trunk/arch/um/os-Linux/process.c +++ b/trunk/arch/um/os-Linux/process.c @@ -15,6 +15,7 @@ #include "os.h" #include "user.h" #include "user_util.h" +#include "signal_user.h" #include "process.h" #include "irq_user.h" #include "kern_util.h" diff --git a/trunk/arch/um/os-Linux/signal.c b/trunk/arch/um/os-Linux/signal.c index c1f46a0fef13..c7bfd5ee3925 100644 --- a/trunk/arch/um/os-Linux/signal.c +++ b/trunk/arch/um/os-Linux/signal.c @@ -4,22 +4,9 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include "user_util.h" -#include "kern_util.h" -#include "user.h" -#include "signal_kern.h" -#include "sysdep/sigcontext.h" -#include "sysdep/signal.h" -#include "sigcontext.h" #include "time_user.h" #include "mode.h" +#include "sysdep/signal.h" void sig_handler(ARCH_SIGHDLR_PARAM) { @@ -49,138 +36,13 @@ void alarm_handler(ARCH_SIGHDLR_PARAM) switch_timers(1); } -void set_sigstack(void *sig_stack, int size) -{ - stack_t stack = ((stack_t) { .ss_flags = 0, - .ss_sp = (__ptr_t) sig_stack, - .ss_size = size - sizeof(void *) }); - - if(sigaltstack(&stack, NULL) != 0) - panic("enabling signal stack failed, errno = %d\n", errno); -} - -void remove_sigstack(void) -{ - stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, - .ss_sp = NULL, - .ss_size = 0 }); - - if(sigaltstack(&stack, NULL) != 0) - panic("disabling signal stack failed, errno = %d\n", errno); -} - -void set_handler(int sig, void (*handler)(int), int flags, ...) -{ - struct sigaction action; - va_list ap; - int mask; - - va_start(ap, flags); - action.sa_handler = handler; - sigemptyset(&action.sa_mask); - while((mask = va_arg(ap, int)) != -1){ - sigaddset(&action.sa_mask, mask); - } - va_end(ap); - action.sa_flags = flags; - action.sa_restorer = NULL; - if(sigaction(sig, &action, NULL) < 0) - panic("sigaction failed"); -} - -int change_sig(int signal, int on) -{ - sigset_t sigset, old; - - sigemptyset(&sigset); - sigaddset(&sigset, signal); - sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); - return(!sigismember(&old, signal)); -} - -/* Both here and in set/get_signal we don't touch SIGPROF, because we must not - * disable profiling; it's safe because the profiling code does not interact - * with the kernel code at all.*/ - -static void change_signals(int type) -{ - sigset_t mask; - - sigemptyset(&mask); - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - sigaddset(&mask, SIGIO); - if(sigprocmask(type, &mask, NULL) < 0) - panic("Failed to change signal mask - errno = %d", errno); -} - -void block_signals(void) -{ - change_signals(SIG_BLOCK); -} - -void unblock_signals(void) -{ - change_signals(SIG_UNBLOCK); -} - -/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled - * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to - * be able to profile all of UML, not just the non-critical sections. If - * profiling is not thread-safe, then that is not my problem. We can disable - * profiling when SMP is enabled in that case. +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: */ -#define SIGIO_BIT 0 -#define SIGVTALRM_BIT 1 - -static int enable_mask(sigset_t *mask) -{ - int sigs; - - sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; - sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; - sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; - return(sigs); -} - -int get_signals(void) -{ - sigset_t mask; - - if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) - panic("Failed to get signal mask"); - return(enable_mask(&mask)); -} - -int set_signals(int enable) -{ - sigset_t mask; - int ret; - - sigemptyset(&mask); - if(enable & (1 << SIGIO_BIT)) - sigaddset(&mask, SIGIO); - if(enable & (1 << SIGVTALRM_BIT)){ - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } - - /* This is safe - sigprocmask is guaranteed to copy locally the - * value of new_set, do his work and then, at the end, write to - * old_set. - */ - if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) - panic("Failed to enable signals"); - ret = enable_mask(&mask); - sigemptyset(&mask); - if((enable & (1 << SIGIO_BIT)) == 0) - sigaddset(&mask, SIGIO); - if((enable & (1 << SIGVTALRM_BIT)) == 0){ - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } - if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) - panic("Failed to block signals"); - - return(ret); -} diff --git a/trunk/arch/um/os-Linux/skas/Makefile b/trunk/arch/um/os-Linux/skas/Makefile deleted file mode 100644 index eab5386d60a7..000000000000 --- a/trunk/arch/um/os-Linux/skas/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) -# Licensed under the GPL -# - -obj-y := trap.o - -USER_OBJS := trap.o - -include arch/um/scripts/Makefile.rules diff --git a/trunk/arch/um/os-Linux/start_up.c b/trunk/arch/um/os-Linux/start_up.c index b47e5e71d1a5..29a9e3f43763 100644 --- a/trunk/arch/um/os-Linux/start_up.c +++ b/trunk/arch/um/os-Linux/start_up.c @@ -24,6 +24,7 @@ #include "kern_util.h" #include "user.h" #include "signal_kern.h" +#include "signal_user.h" #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" #include "irq_user.h" diff --git a/trunk/arch/um/os-Linux/trap.c b/trunk/arch/um/os-Linux/trap.c deleted file mode 100644 index 321e1c8e227d..000000000000 --- a/trunk/arch/um/os-Linux/trap.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include "kern_util.h" -#include "user_util.h" -#include "os.h" -#include "mode.h" - -void usr2_handler(int sig, union uml_pt_regs *regs) -{ - CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); -} - -void (*sig_info[NSIG])(int, union uml_pt_regs *); - -void os_fill_handlinfo(struct kern_handlers h) -{ - sig_info[SIGTRAP] = h.relay_signal; - sig_info[SIGFPE] = h.relay_signal; - sig_info[SIGILL] = h.relay_signal; - sig_info[SIGWINCH] = h.winch; - sig_info[SIGBUS] = h.bus_handler; - sig_info[SIGSEGV] = h.page_fault; - sig_info[SIGIO] = h.sigio_handler; - sig_info[SIGVTALRM] = h.timer_handler; - sig_info[SIGALRM] = h.timer_handler; - sig_info[SIGUSR2] = usr2_handler; -} - -void do_longjmp(void *b, int val) -{ - sigjmp_buf *buf = b; - - siglongjmp(*buf, val); -} diff --git a/trunk/arch/um/os-Linux/tt.c b/trunk/arch/um/os-Linux/tt.c index cb2648b79d0f..a6db8877931a 100644 --- a/trunk/arch/um/os-Linux/tt.c +++ b/trunk/arch/um/os-Linux/tt.c @@ -23,6 +23,7 @@ #include "kern_util.h" #include "user.h" #include "signal_kern.h" +#include "signal_user.h" #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" #include "irq_user.h" @@ -49,20 +50,6 @@ int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, return(0); } -void kill_child_dead(int pid) -{ - kill(pid, SIGKILL); - kill(pid, SIGCONT); - do { - int n; - CATCH_EINTR(n = waitpid(pid, NULL, 0)); - if (n > 0) - kill(pid, SIGCONT); - else - break; - } while(1); -} - /* *------------------------- * only for tt mode (will be deleted in future...) diff --git a/trunk/arch/um/sys-i386/signal.c b/trunk/arch/um/sys-i386/signal.c index 7cd1a82dc8c2..16bc19928b3c 100644 --- a/trunk/arch/um/sys-i386/signal.c +++ b/trunk/arch/um/sys-i386/signal.c @@ -10,6 +10,7 @@ #include "asm/uaccess.h" #include "asm/unistd.h" #include "frame_kern.h" +#include "signal_user.h" #include "sigcontext.h" #include "registers.h" #include "mode.h" diff --git a/trunk/arch/v850/Kconfig b/trunk/arch/v850/Kconfig index 04494638b963..310865903234 100644 --- a/trunk/arch/v850/Kconfig +++ b/trunk/arch/v850/Kconfig @@ -10,6 +10,9 @@ mainmenu "uClinux/v850 (w/o MMU) Kernel Configuration" config MMU bool default n +config UID16 + bool + default n config RWSEM_GENERIC_SPINLOCK bool default y diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index 4f3e925962c3..6ece645e4dbe 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -542,6 +542,11 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y +config UID16 + bool + depends on IA32_EMULATION + default y + endmenu source "net/Kconfig" diff --git a/trunk/arch/x86_64/boot/compressed/misc.c b/trunk/arch/x86_64/boot/compressed/misc.c index cf4b88c416dc..0e10fd84c7cc 100644 --- a/trunk/arch/x86_64/boot/compressed/misc.c +++ b/trunk/arch/x86_64/boot/compressed/misc.c @@ -9,7 +9,7 @@ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */ -#include +#include "miscsetup.h" #include #include diff --git a/trunk/arch/x86_64/boot/compressed/miscsetup.h b/trunk/arch/x86_64/boot/compressed/miscsetup.h new file mode 100644 index 000000000000..bb1620531703 --- /dev/null +++ b/trunk/arch/x86_64/boot/compressed/miscsetup.h @@ -0,0 +1,39 @@ +#define NULL 0 +//typedef unsigned int size_t; + + +struct screen_info { + unsigned char orig_x; /* 0x00 */ + unsigned char orig_y; /* 0x01 */ + unsigned short dontuse1; /* 0x02 -- EXT_MEM_K sits here */ + unsigned short orig_video_page; /* 0x04 */ + unsigned char orig_video_mode; /* 0x06 */ + unsigned char orig_video_cols; /* 0x07 */ + unsigned short unused2; /* 0x08 */ + unsigned short orig_video_ega_bx; /* 0x0a */ + unsigned short unused3; /* 0x0c */ + unsigned char orig_video_lines; /* 0x0e */ + unsigned char orig_video_isVGA; /* 0x0f */ + unsigned short orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + unsigned short lfb_width; /* 0x12 */ + unsigned short lfb_height; /* 0x14 */ + unsigned short lfb_depth; /* 0x16 */ + unsigned long lfb_base; /* 0x18 */ + unsigned long lfb_size; /* 0x1c */ + unsigned short dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */ + unsigned short lfb_linelength; /* 0x24 */ + unsigned char red_size; /* 0x26 */ + unsigned char red_pos; /* 0x27 */ + unsigned char green_size; /* 0x28 */ + unsigned char green_pos; /* 0x29 */ + unsigned char blue_size; /* 0x2a */ + unsigned char blue_pos; /* 0x2b */ + unsigned char rsvd_size; /* 0x2c */ + unsigned char rsvd_pos; /* 0x2d */ + unsigned short vesapm_seg; /* 0x2e */ + unsigned short vesapm_off; /* 0x30 */ + unsigned short pages; /* 0x32 */ + /* 0x34 -- 0x3f reserved for future expansion */ +}; diff --git a/trunk/arch/x86_64/ia32/ia32entry.S b/trunk/arch/x86_64/ia32/ia32entry.S index 1f0ff5adc80e..df0773c9bdbe 100644 --- a/trunk/arch/x86_64/ia32/ia32entry.S +++ b/trunk/arch/x86_64/ia32/ia32entry.S @@ -643,7 +643,6 @@ ia32_sys_call_table: .quad sys_inotify_init .quad sys_inotify_add_watch .quad sys_inotify_rm_watch - .quad sys_migrate_pages ia32_syscall_end: .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 .quad ni_syscall diff --git a/trunk/arch/x86_64/ia32/ptrace32.c b/trunk/arch/x86_64/ia32/ptrace32.c index 5f4cdfa56901..2a925e2af390 100644 --- a/trunk/arch/x86_64/ia32/ptrace32.c +++ b/trunk/arch/x86_64/ia32/ptrace32.c @@ -196,6 +196,36 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) #undef R32 +static struct task_struct *find_target(int request, int pid, int *err) +{ + struct task_struct *child; + + *err = -EPERM; + if (pid == 1) + return NULL; + + *err = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (child) { + *err = -EPERM; + if (child->pid == 1) + goto out; + *err = ptrace_check_attach(child, request == PTRACE_KILL); + if (*err < 0) + goto out; + return child; + } + out: + if (child) + put_task_struct(child); + return NULL; + +} + asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) { struct task_struct *child; @@ -224,16 +254,9 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) break; } - if (request == PTRACE_TRACEME) - return ptrace_traceme(); - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) - return PTR_ERR(child); - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out; + child = find_target(request, pid, &ret); + if (!child) + return ret; childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs)); @@ -350,7 +373,6 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) break; } - out: put_task_struct(child); return ret; } diff --git a/trunk/arch/x86_64/kernel/init_task.c b/trunk/arch/x86_64/kernel/init_task.c index ce31d904d601..e0ba5c1043fd 100644 --- a/trunk/arch/x86_64/kernel/init_task.c +++ b/trunk/arch/x86_64/kernel/init_task.c @@ -44,6 +44,6 @@ EXPORT_SYMBOL(init_task); * section. Since TSS's are completely CPU-local, we want them * on exact cacheline boundaries, to eliminate cacheline ping-pong. */ -DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; +DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS; #define ALIGN_TO_4K __attribute__((section(".data.init_task"))) diff --git a/trunk/arch/x86_64/kernel/time.c b/trunk/arch/x86_64/kernel/time.c index 43c9fa0f8d5f..74102796e5c0 100644 --- a/trunk/arch/x86_64/kernel/time.c +++ b/trunk/arch/x86_64/kernel/time.c @@ -1075,6 +1075,8 @@ device_initcall(time_init_device); */ #include +extern irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs); + #define DEFAULT_RTC_INT_FREQ 64 #define RTC_NUM_INTS 1 diff --git a/trunk/block/elevator.c b/trunk/block/elevator.c index 99a4d7b2f8ad..39dcccc82ada 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -64,7 +64,7 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) } EXPORT_SYMBOL(elv_rq_merge_ok); -static inline int elv_try_merge(struct request *__rq, struct bio *bio) +inline int elv_try_merge(struct request *__rq, struct bio *bio) { int ret = ELEVATOR_NO_MERGE; @@ -80,6 +80,7 @@ static inline int elv_try_merge(struct request *__rq, struct bio *bio) return ret; } +EXPORT_SYMBOL(elv_try_merge); static struct elevator_type *elevator_find(const char *name) { diff --git a/trunk/block/ioctl.c b/trunk/block/ioctl.c index 82030e1dfd63..6e278474f9a8 100644 --- a/trunk/block/ioctl.c +++ b/trunk/block/ioctl.c @@ -1,7 +1,6 @@ #include /* for capable() */ #include #include -#include #include #include #include @@ -246,27 +245,6 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, set_device_ro(bdev, n); unlock_kernel(); return 0; - case HDIO_GETGEO: { - struct hd_geometry geo; - - if (!arg) - return -EINVAL; - if (!disk->fops->getgeo) - return -ENOTTY; - - /* - * We need to set the startsect first, the driver may - * want to override it. - */ - geo.start = get_start_sect(bdev); - ret = disk->fops->getgeo(bdev, &geo); - if (ret) - return ret; - if (copy_to_user((struct hd_geometry __user *)arg, &geo, - sizeof(geo))) - return -EFAULT; - return 0; - } } lock_kernel(); diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 8e27d0ab0d7c..91d3b4828c49 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -26,8 +26,7 @@ #include #include #include -#include -#include +#include /* * for max sense size @@ -63,15 +62,13 @@ static wait_queue_head_t congestion_wqh[2] = { /* * Controlling structure to kblockd */ -static struct workqueue_struct *kblockd_workqueue; +static struct workqueue_struct *kblockd_workqueue; unsigned long blk_max_low_pfn, blk_max_pfn; EXPORT_SYMBOL(blk_max_low_pfn); EXPORT_SYMBOL(blk_max_pfn); -static DEFINE_PER_CPU(struct list_head, blk_cpu_done); - /* Amount of time in which a process may batch requests */ #define BLK_BATCH_TIME (HZ/50UL) @@ -210,13 +207,6 @@ void blk_queue_merge_bvec(request_queue_t *q, merge_bvec_fn *mbfn) EXPORT_SYMBOL(blk_queue_merge_bvec); -void blk_queue_softirq_done(request_queue_t *q, softirq_done_fn *fn) -{ - q->softirq_done_fn = fn; -} - -EXPORT_SYMBOL(blk_queue_softirq_done); - /** * blk_queue_make_request - define an alternate make_request function for a device * @q: the request queue for the device to be affected @@ -280,7 +270,6 @@ EXPORT_SYMBOL(blk_queue_make_request); static inline void rq_init(request_queue_t *q, struct request *rq) { INIT_LIST_HEAD(&rq->queuelist); - INIT_LIST_HEAD(&rq->donelist); rq->errors = 0; rq->rq_status = RQ_ACTIVE; @@ -297,7 +286,6 @@ static inline void rq_init(request_queue_t *q, struct request *rq) rq->sense = NULL; rq->end_io = NULL; rq->end_io_data = NULL; - rq->completion_data = NULL; } /** @@ -2747,6 +2735,30 @@ static inline int attempt_front_merge(request_queue_t *q, struct request *rq) return 0; } +/** + * blk_attempt_remerge - attempt to remerge active head with next request + * @q: The &request_queue_t belonging to the device + * @rq: The head request (usually) + * + * Description: + * For head-active devices, the queue can easily be unplugged so quickly + * that proper merging is not done on the front request. This may hurt + * performance greatly for some devices. The block layer cannot safely + * do merging on that first request for these queues, but the driver can + * call this function and make it happen any way. Only the driver knows + * when it is safe to do so. + **/ +void blk_attempt_remerge(request_queue_t *q, struct request *rq) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + attempt_back_merge(q, rq); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +EXPORT_SYMBOL(blk_attempt_remerge); + static void init_request_from_bio(struct request *req, struct bio *bio) { req->flags |= REQ_CMD; @@ -3274,87 +3286,6 @@ int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes) EXPORT_SYMBOL(end_that_request_chunk); -/* - * 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; - LIST_HEAD(local_list); - - local_irq_disable(); - cpu_list = &__get_cpu_var(blk_cpu_done); - list_splice_init(cpu_list, &local_list); - local_irq_enable(); - - while (!list_empty(&local_list)) { - struct request *rq = list_entry(local_list.next, struct request, donelist); - - list_del_init(&rq->donelist); - rq->q->softirq_done_fn(rq); - } -} - -#ifdef CONFIG_HOTPLUG_CPU - -static int 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) { - 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 __devinitdata blk_cpu_notifier = { - .notifier_call = blk_cpu_notify, -}; - -#endif /* CONFIG_HOTPLUG_CPU */ - -/** - * 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 completionc callback - * through requeueing. Theh 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 */ @@ -3433,8 +3364,6 @@ EXPORT_SYMBOL(kblockd_flush); int __init blk_dev_init(void) { - int i; - kblockd_workqueue = create_workqueue("kblockd"); if (!kblockd_workqueue) panic("Failed to create kblockd\n"); @@ -3448,14 +3377,6 @@ int __init blk_dev_init(void) iocontext_cachep = kmem_cache_create("blkdev_ioc", sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); - for (i = 0; i < NR_CPUS; i++) - INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); - - open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL); -#ifdef CONFIG_HOTPLUG_CPU - register_cpu_notifier(&blk_cpu_notifier); -#endif - blk_max_low_pfn = max_low_pfn; blk_max_pfn = max_pfn; diff --git a/trunk/block/scsi_ioctl.c b/trunk/block/scsi_ioctl.c index 18de84c8ccd8..c2ac36dfe4f3 100644 --- a/trunk/block/scsi_ioctl.c +++ b/trunk/block/scsi_ioctl.c @@ -190,21 +190,16 @@ static int verify_command(struct file *file, unsigned char *cmd) safe_for_write(GPCMD_SET_STREAMING), }; unsigned char type = cmd_type[cmd[0]]; - int has_write_perm = 0; /* Anybody who can open the device can do a read-safe command */ if (type & CMD_READ_SAFE) return 0; - /* - * file can be NULL from ioctl_by_bdev()... - */ - if (file) - has_write_perm = file->f_mode & FMODE_WRITE; - /* Write-safe commands just require a writable open.. */ - if ((type & CMD_WRITE_SAFE) && has_write_perm) - return 0; + if (type & CMD_WRITE_SAFE) { + if (file->f_mode & FMODE_WRITE) + return 0; + } /* And root can do any command.. */ if (capable(CAP_SYS_RAWIO)) diff --git a/trunk/drivers/acorn/block/mfmhd.c b/trunk/drivers/acorn/block/mfmhd.c index ce074f6f3369..4b65f74d66b1 100644 --- a/trunk/drivers/acorn/block/mfmhd.c +++ b/trunk/drivers/acorn/block/mfmhd.c @@ -129,6 +129,19 @@ static DEFINE_SPINLOCK(mfm_lock); #define MAJOR_NR MFM_ACORN_MAJOR #define QUEUE (mfm_queue) #define CURRENT elv_next_request(mfm_queue) +/* + * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc + */ +#ifndef HDIO_GETGEO +#define HDIO_GETGEO 0x301 +struct hd_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + unsigned long start; +}; +#endif + /* * Configuration section @@ -1140,13 +1153,22 @@ static int mfm_initdrives(void) * The 'front' end of the mfm driver follows... */ -static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { - struct mfm_info *p = bdev->bd_disk->private_data; - - geo->heads = p->heads; - geo->sectors = p->sectors; - geo->cylinders = p->cylinders; + struct mfm_info *p = inode->i_bdev->bd_disk->private_data; + struct hd_geometry *geo = (struct hd_geometry *) arg; + if (cmd != HDIO_GETGEO) + return -EINVAL; + if (!arg) + return -EINVAL; + if (put_user (p->heads, &geo->heads)) + return -EFAULT; + if (put_user (p->sectors, &geo->sectors)) + return -EFAULT; + if (put_user (p->cylinders, &geo->cylinders)) + return -EFAULT; + if (put_user (get_start_sect(inode->i_bdev), &geo->start)) + return -EFAULT; return 0; } @@ -1197,7 +1219,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack, static struct block_device_operations mfm_fops = { .owner = THIS_MODULE, - .getgeo = mfm_getgeo, + .ioctl = mfm_ioctl, }; /* diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 20c9a37643c7..e3cd0b16031a 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -204,13 +204,11 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, return AE_OK; } -EXPORT_SYMBOL_GPL(acpi_os_map_memory); void acpi_os_unmap_memory(void __iomem * virt, acpi_size size) { iounmap(virt); } -EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); #ifdef ACPI_FUTURE_USAGE acpi_status diff --git a/trunk/drivers/atm/nicstar.c b/trunk/drivers/atm/nicstar.c index 074abc81ec3d..c57e20dcb0f8 100644 --- a/trunk/drivers/atm/nicstar.c +++ b/trunk/drivers/atm/nicstar.c @@ -2126,7 +2126,8 @@ static void process_rsq(ns_dev *card) if (!ns_rsqe_valid(card->rsq.next)) return; - do { + while (ns_rsqe_valid(card->rsq.next)) + { dequeue_rx(card, card->rsq.next); ns_rsqe_init(card->rsq.next); previous = card->rsq.next; @@ -2134,7 +2135,7 @@ static void process_rsq(ns_dev *card) card->rsq.next = card->rsq.base; else card->rsq.next++; - } while (ns_rsqe_valid(card->rsq.next)); + } writel((((u32) previous) - ((u32) card->rsq.base)), card->membase + RSQH); } diff --git a/trunk/drivers/block/DAC960.c b/trunk/drivers/block/DAC960.c index 4a7bb7dfce85..21097a39a057 100644 --- a/trunk/drivers/block/DAC960.c +++ b/trunk/drivers/block/DAC960.c @@ -92,28 +92,34 @@ static int DAC960_open(struct inode *inode, struct file *file) return 0; } -static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int DAC960_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { - struct gendisk *disk = bdev->bd_disk; + struct gendisk *disk = inode->i_bdev->bd_disk; DAC960_Controller_T *p = disk->queue->queuedata; int drive_nr = (long)disk->private_data; + struct hd_geometry g; + struct hd_geometry __user *loc = (struct hd_geometry __user *)arg; + + if (cmd != HDIO_GETGEO || !loc) + return -EINVAL; if (p->FirmwareType == DAC960_V1_Controller) { - geo->heads = p->V1.GeometryTranslationHeads; - geo->sectors = p->V1.GeometryTranslationSectors; - geo->cylinders = p->V1.LogicalDriveInformation[drive_nr]. - LogicalDriveSize / (geo->heads * geo->sectors); + g.heads = p->V1.GeometryTranslationHeads; + g.sectors = p->V1.GeometryTranslationSectors; + g.cylinders = p->V1.LogicalDriveInformation[drive_nr]. + LogicalDriveSize / (g.heads * g.sectors); } else { DAC960_V2_LogicalDeviceInfo_T *i = p->V2.LogicalDeviceInformation[drive_nr]; switch (i->DriveGeometry) { case DAC960_V2_Geometry_128_32: - geo->heads = 128; - geo->sectors = 32; + g.heads = 128; + g.sectors = 32; break; case DAC960_V2_Geometry_255_63: - geo->heads = 255; - geo->sectors = 63; + g.heads = 255; + g.sectors = 63; break; default: DAC960_Error("Illegal Logical Device Geometry %d\n", @@ -121,11 +127,12 @@ static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo) return -EINVAL; } - geo->cylinders = i->ConfigurableDeviceSize / - (geo->heads * geo->sectors); + g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors); } - return 0; + g.start = get_start_sect(inode->i_bdev); + + return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; } static int DAC960_media_changed(struct gendisk *disk) @@ -150,7 +157,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk) static struct block_device_operations DAC960_BlockDeviceOperations = { .owner = THIS_MODULE, .open = DAC960_open, - .getgeo = DAC960_getgeo, + .ioctl = DAC960_ioctl, .media_changed = DAC960_media_changed, .revalidate_disk = DAC960_revalidate_disk, }; @@ -3760,7 +3767,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command) if (SenseKey == DAC960_SenseKey_VendorSpecific && AdditionalSenseCode == 0x80 && AdditionalSenseCodeQualifier < - ARRAY_SIZE(DAC960_EventMessages)) + sizeof(DAC960_EventMessages) / sizeof(char *)) DAC960_Critical("Physical Device %d:%d %s\n", Controller, EventLogEntry->Channel, EventLogEntry->TargetID, diff --git a/trunk/drivers/block/acsi.c b/trunk/drivers/block/acsi.c index 196c0ec9cd54..5d2d649f7e8d 100644 --- a/trunk/drivers/block/acsi.c +++ b/trunk/drivers/block/acsi.c @@ -1079,19 +1079,6 @@ static void redo_acsi_request( void ) * ***********************************************************************/ -static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct acsi_info_struct *aip = bdev->bd_disk->private_data; - - /* - * Just fake some geometry here, it's nonsense anyway - * To make it easy, use Adaptec's usual 64/32 mapping - */ - geo->heads = 64; - geo->sectors = 32; - geo->cylinders = aip->size >> 11; - return 0; -} static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg ) @@ -1099,6 +1086,18 @@ static int acsi_ioctl( struct inode *inode, struct file *file, struct gendisk *disk = inode->i_bdev->bd_disk; struct acsi_info_struct *aip = disk->private_data; switch (cmd) { + case HDIO_GETGEO: + /* HDIO_GETGEO is supported more for getting the partition's + * start sector... */ + { struct hd_geometry *geo = (struct hd_geometry *)arg; + /* just fake some geometry here, it's nonsense anyway; to make it + * easy, use Adaptec's usual 64/32 mapping */ + put_user( 64, &geo->heads ); + put_user( 32, &geo->sectors ); + put_user( aip->size >> 11, &geo->cylinders ); + put_user(get_start_sect(inode->i_bdev), &geo->start); + return 0; + } case SCSI_IOCTL_GET_IDLUN: /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */ put_user( aip->target | (aip->lun << 8), @@ -1593,7 +1592,6 @@ static struct block_device_operations acsi_fops = { .open = acsi_open, .release = acsi_release, .ioctl = acsi_ioctl, - .getgeo = acsi_getgeo, .media_changed = acsi_media_change, .revalidate_disk= acsi_revalidate, }; diff --git a/trunk/drivers/block/amiflop.c b/trunk/drivers/block/amiflop.c index 3c679d30b698..0acbfff8ad28 100644 --- a/trunk/drivers/block/amiflop.c +++ b/trunk/drivers/block/amiflop.c @@ -131,7 +131,7 @@ static struct fd_drive_type drive_types[] = { { FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2}, { FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; -static int num_dr_types = ARRAY_SIZE(drive_types); +static int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]); static int amiga_read(int), dos_read(int); static void amiga_write(int), dos_write(int); @@ -1424,16 +1424,6 @@ static void do_fd_request(request_queue_t * q) redo_fd_request(); } -static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - int drive = MINOR(bdev->bd_dev) & 3; - - geo->heads = unit[drive].type->heads; - geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult; - geo->cylinders = unit[drive].type->tracks; - return 0; -} - static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long param) { @@ -1441,6 +1431,18 @@ static int fd_ioctl(struct inode *inode, struct file *filp, static struct floppy_struct getprm; switch(cmd){ + case HDIO_GETGEO: + { + struct hd_geometry loc; + loc.heads = unit[drive].type->heads; + loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult; + loc.cylinders = unit[drive].type->tracks; + loc.start = 0; + if (copy_to_user((void *)param, (void *)&loc, + sizeof(struct hd_geometry))) + return -EFAULT; + break; + } case FDFMTBEG: get_fdc(drive); if (fd_ref[drive] > 1) { @@ -1650,7 +1652,6 @@ static struct block_device_operations floppy_fops = { .open = floppy_open, .release = floppy_release, .ioctl = fd_ioctl, - .getgeo = fd_getgeo, .media_changed = amiga_floppy_change, }; diff --git a/trunk/drivers/block/aoe/aoeblk.c b/trunk/drivers/block/aoe/aoeblk.c index c05ee8bffd97..0e97fcb9f3a1 100644 --- a/trunk/drivers/block/aoe/aoeblk.c +++ b/trunk/drivers/block/aoe/aoeblk.c @@ -169,26 +169,38 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) return 0; } +/* This ioctl implementation expects userland to have the device node + * permissions set so that only priviledged users can open an aoe + * block device directly. + */ static int -aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) +aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg) { - struct aoedev *d = bdev->bd_disk->private_data; + struct aoedev *d; + + if (!arg) + return -EINVAL; + d = inode->i_bdev->bd_disk->private_data; if ((d->flags & DEVFL_UP) == 0) { printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); return -ENODEV; } - geo->cylinders = d->geo.cylinders; - geo->heads = d->geo.heads; - geo->sectors = d->geo.sectors; - return 0; + if (cmd == HDIO_GETGEO) { + d->geo.start = get_start_sect(inode->i_bdev); + if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo)) + return 0; + return -EFAULT; + } + printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd); + return -EINVAL; } static struct block_device_operations aoe_bdops = { .open = aoeblk_open, .release = aoeblk_release, - .getgeo = aoeblk_getgeo, + .ioctl = aoeblk_ioctl, .owner = THIS_MODULE, }; diff --git a/trunk/drivers/block/ataflop.c b/trunk/drivers/block/ataflop.c index 3aa68a5447d6..22bda05fc693 100644 --- a/trunk/drivers/block/ataflop.c +++ b/trunk/drivers/block/ataflop.c @@ -181,7 +181,7 @@ static struct { { 6, TYPE_HD }, /* 31: H1640 <- was H1600 == h1600 for PC */ }; -#define NUM_DISK_MINORS ARRAY_SIZE(minor2disktype) +#define NUM_DISK_MINORS (sizeof(minor2disktype)/sizeof(*minor2disktype)) /* * Maximum disk size (in kilobytes). This default is used whenever the diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index e4e9f255bd1f..d2815b7a9150 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -1,6 +1,6 @@ /* * Disk Array driver for HP SA 5xxx and 6xxx Controllers - * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P. + * Copyright 2000, 2005 Hewlett-Packard Development Company, L.P. * * 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 @@ -47,12 +47,12 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 2.6.10)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,10) +#define DRIVER_NAME "HP CISS Driver (v 2.6.8)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.10"); +MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" " SA6i P600 P800 P400 P400i E200 E200i"); MODULE_LICENSE("GPL"); @@ -103,7 +103,7 @@ static const struct pci_device_id cciss_pci_device_id[] = { }; MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); -#define NR_PRODUCTS ARRAY_SIZE(products) +#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type)) /* board_id = Subsystem Device ID & Vendor ID * product = Marketing Name for the board @@ -153,7 +153,6 @@ static int cciss_open(struct inode *inode, struct file *filep); static int cciss_release(struct inode *inode, struct file *filep); static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int revalidate_allvol(ctlr_info_t *host); static int cciss_revalidate(struct gendisk *disk); @@ -167,7 +166,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, unsigned int block_size, InquiryData_struct *inq_buff, drive_info_struct *drv); static void cciss_getgeometry(int cntl_num); -static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, __u32); + static void start_io( ctlr_info_t *h); static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, @@ -195,7 +194,6 @@ static struct block_device_operations cciss_fops = { .open = cciss_open, .release = cciss_release, .ioctl = cciss_ioctl, - .getgeo = cciss_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = cciss_compat_ioctl, #endif @@ -284,7 +282,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, h->product_name, (unsigned long)h->board_id, h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3], - (unsigned int)h->intr[SIMPLE_MODE_INT], + (unsigned int)h->intr, h->num_luns, h->Qdepth, h->commands_outstanding, h->maxQsinceinit, h->max_outstanding, h->maxSG); @@ -635,20 +633,6 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned return err; } #endif - -static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - drive_info_struct *drv = get_drv(bdev->bd_disk); - - if (!drv->cylinders) - return -ENXIO; - - geo->heads = drv->heads; - geo->sectors = drv->sectors; - geo->cylinders = drv->cylinders; - return 0; -} - /* * ioctl */ @@ -667,6 +651,21 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, #endif /* CCISS_DEBUG */ switch(cmd) { + case HDIO_GETGEO: + { + struct hd_geometry driver_geo; + if (drv->cylinders) { + driver_geo.heads = drv->heads; + driver_geo.sectors = drv->sectors; + driver_geo.cylinders = drv->cylinders; + } else + return -ENXIO; + driver_geo.start= get_start_sect(inode->i_bdev); + if (copy_to_user(argp, &driver_geo, sizeof(struct hd_geometry))) + return -EFAULT; + return(0); + } + case CCISS_GETPCIINFO: { cciss_pci_info_struct pciinfo; @@ -2178,48 +2177,16 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c) start_io(h); } - -static void cciss_softirq_done(struct request *rq) -{ - CommandList_struct *cmd = rq->completion_data; - ctlr_info_t *h = hba[cmd->ctlr]; - u64bit temp64; - int i, ddir; - - if (cmd->Request.Type.Direction == XFER_READ) - ddir = PCI_DMA_FROMDEVICE; - else - ddir = PCI_DMA_TODEVICE; - - /* command did not need to be retried */ - /* unmap the DMA mapping for all the scatter gather elements */ - for(i=0; iHeader.SGList; i++) { - temp64.val32.lower = cmd->SG[i].Addr.lower; - temp64.val32.upper = cmd->SG[i].Addr.upper; - pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir); - } - - complete_buffers(rq->bio, rq->errors); - -#ifdef CCISS_DEBUG - printk("Done with %p\n", rq); -#endif /* CCISS_DEBUG */ - - spin_lock_irq(&h->lock); - end_that_request_last(rq, rq->errors); - cmd_free(h, cmd,1); - spin_unlock_irq(&h->lock); -} - /* checks the status of the job and calls complete buffers to mark all - * buffers for the completed job. Note that this function does not need - * to hold the hba/queue lock. + * buffers for the completed job. */ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, int timeout) { int status = 1; + int i; int retry_cmd = 0; + u64bit temp64; if (timeout) status = 0; @@ -2327,10 +2294,24 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, resend_cciss_cmd(h,cmd); return; } + /* command did not need to be retried */ + /* unmap the DMA mapping for all the scatter gather elements */ + for(i=0; iHeader.SGList; i++) { + temp64.val32.lower = cmd->SG[i].Addr.lower; + temp64.val32.upper = cmd->SG[i].Addr.upper; + pci_unmap_page(hba[cmd->ctlr]->pdev, + temp64.val, cmd->SG[i].Len, + (cmd->Request.Type.Direction == XFER_READ) ? + PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + } + complete_buffers(cmd->rq->bio, status); - cmd->rq->completion_data = cmd; - cmd->rq->errors = status; - blk_complete_request(cmd->rq); +#ifdef CCISS_DEBUG + printk("Done with %p\n", cmd->rq); +#endif /* CCISS_DEBUG */ + + end_that_request_last(cmd->rq, status ? 1 : -EIO); + cmd_free(h,cmd,1); } /* @@ -2680,60 +2661,6 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, return -1; } -/* If MSI/MSI-X is supported by the kernel we will try to enable it on - * controllers that are capable. If not, we use IO-APIC mode. - */ - -static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, __u32 board_id) -{ -#ifdef CONFIG_PCI_MSI - int err; - struct msix_entry cciss_msix_entries[4] = {{0,0}, {0,1}, - {0,2}, {0,3}}; - - /* Some boards advertise MSI but don't really support it */ - if ((board_id == 0x40700E11) || - (board_id == 0x40800E11) || - (board_id == 0x40820E11) || - (board_id == 0x40830E11)) - goto default_int_mode; - - if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { - err = pci_enable_msix(pdev, cciss_msix_entries, 4); - if (!err) { - c->intr[0] = cciss_msix_entries[0].vector; - c->intr[1] = cciss_msix_entries[1].vector; - c->intr[2] = cciss_msix_entries[2].vector; - c->intr[3] = cciss_msix_entries[3].vector; - c->msix_vector = 1; - return; - } - if (err > 0) { - printk(KERN_WARNING "cciss: only %d MSI-X vectors " - "available\n", err); - } else { - printk(KERN_WARNING "cciss: MSI-X init failed %d\n", - err); - } - } - if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { - if (!pci_enable_msi(pdev)) { - c->intr[SIMPLE_MODE_INT] = pdev->irq; - c->msi_vector = 1; - return; - } else { - printk(KERN_WARNING "cciss: MSI init failed\n"); - c->intr[SIMPLE_MODE_INT] = pdev->irq; - return; - } - } -#endif /* CONFIG_PCI_MSI */ - /* if we get here we're going to use the default interrupt mode */ -default_int_mode: - c->intr[SIMPLE_MODE_INT] = pdev->irq; - return; -} - static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) { ushort subsystem_vendor_id, subsystem_device_id, command; @@ -2794,10 +2721,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) printk("board_id = %x\n", board_id); #endif /* CCISS_DEBUG */ -/* If the kernel supports MSI/MSI-X we will try to enable that functionality, - * else we use the IO-APIC interrupt assigned to us by system ROM. - */ - cciss_interrupt_mode(c, pdev, board_id); + c->intr = pdev->irq; /* * Memory base addr is first addr , the second points to the config @@ -2851,7 +2775,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) c->board_id = board_id; #ifdef CCISS_DEBUG - print_cfg_table(c->cfgtable); + print_cfg_table(c->cfgtable); #endif /* CCISS_DEBUG */ for(i=0; imajor = COMPAQ_CISS_MAJOR + i; + hba[i]->major = MAJOR_NR + i; rc = register_blkdev(hba[i]->major, hba[i]->devname); if(rc == -EBUSY || rc == -EINVAL) { printk(KERN_ERR @@ -3151,11 +3075,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); - if( request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr, + if( request_irq(hba[i]->intr, do_cciss_intr, SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, hba[i]->devname, hba[i])) { printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", - hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname); + hba[i]->intr, hba[i]->devname); goto clean2; } hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL); @@ -3217,17 +3141,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, drv->queue = q; q->backing_dev_info.ra_pages = READ_AHEAD; - blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); + blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); - /* This is a hardware imposed limit. */ - blk_queue_max_hw_segments(q, MAXSGENTRIES); + /* This is a hardware imposed limit. */ + blk_queue_max_hw_segments(q, MAXSGENTRIES); - /* This is a limit in the driver and could be eliminated. */ - blk_queue_max_phys_segments(q, MAXSGENTRIES); + /* This is a limit in the driver and could be eliminated. */ + blk_queue_max_phys_segments(q, MAXSGENTRIES); - blk_queue_max_sectors(q, 512); - - blk_queue_softirq_done(q, cciss_softirq_done); + blk_queue_max_sectors(q, 512); q->queuedata = hba[i]; sprintf(disk->disk_name, "cciss/c%dd%d", i, j); @@ -3263,7 +3185,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, NR_CMDS * sizeof( ErrorInfo_struct), hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); - free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]); + free_irq(hba[i]->intr, hba[i]); clean2: unregister_blkdev(hba[i]->major, hba[i]->devname); clean1: @@ -3304,15 +3226,7 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) printk(KERN_WARNING "Error Flushing cache on controller %d\n", i); } - free_irq(hba[i]->intr[2], hba[i]); - -#ifdef CONFIG_PCI_MSI - if (hba[i]->msix_vector) - pci_disable_msix(hba[i]->pdev); - else if (hba[i]->msi_vector) - pci_disable_msi(hba[i]->pdev); -#endif /* CONFIG_PCI_MSI */ - + free_irq(hba[i]->intr, hba[i]); pci_set_drvdata(pdev, NULL); iounmap(hba[i]->vaddr); cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ diff --git a/trunk/drivers/block/cciss.h b/trunk/drivers/block/cciss.h index b24fc0553ccf..3b0858c83897 100644 --- a/trunk/drivers/block/cciss.h +++ b/trunk/drivers/block/cciss.h @@ -13,6 +13,8 @@ #define IO_OK 0 #define IO_ERROR 1 +#define MAJOR_NR COMPAQ_CISS_MAJOR + struct ctlr_info; typedef struct ctlr_info ctlr_info_t; @@ -63,6 +65,7 @@ struct ctlr_info unsigned long io_mem_addr; unsigned long io_mem_length; CfgTable_struct __iomem *cfgtable; + unsigned int intr; int interrupts_enabled; int major; int max_commands; @@ -71,13 +74,6 @@ struct ctlr_info int num_luns; int highest_lun; int usage_count; /* number of opens all all minor devices */ -# define DOORBELL_INT 0 -# define PERF_MODE_INT 1 -# define SIMPLE_MODE_INT 2 -# define MEMQ_MODE_INT 3 - unsigned int intr[4]; - unsigned int msix_vector; - unsigned int msi_vector; // information about each logical volume drive_info_struct drv[CISS_MAX_LUN]; diff --git a/trunk/drivers/block/cciss_scsi.c b/trunk/drivers/block/cciss_scsi.c index 9e35de05d5c5..2942d32280a5 100644 --- a/trunk/drivers/block/cciss_scsi.c +++ b/trunk/drivers/block/cciss_scsi.c @@ -714,7 +714,7 @@ cciss_scsi_detect(int ctlr) ((struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr)->scsi_host = (void *) sh; sh->hostdata[0] = (unsigned long) hba[ctlr]; - sh->irq = hba[ctlr]->intr[SIMPLE_MODE_INT]; + sh->irq = hba[ctlr]->intr; sh->unique_id = sh->irq; error = scsi_add_host(sh, &hba[ctlr]->pdev->dev); if (error) diff --git a/trunk/drivers/block/cpqarray.c b/trunk/drivers/block/cpqarray.c index 862b9abac0ae..9bddb6874873 100644 --- a/trunk/drivers/block/cpqarray.c +++ b/trunk/drivers/block/cpqarray.c @@ -72,11 +72,11 @@ static ctlr_info_t *hba[MAX_CTLR]; static int eisa[8]; -#define NR_PRODUCTS ARRAY_SIZE(products) +#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type)) /* board_id = Subsystem Device ID & Vendor ID * product = Marketing Name for the board - * access = Address of the struct of function pointers + * access = Address of the struct of function pointers */ static struct board_type products[] = { { 0x0040110E, "IDA", &smart1_access }, @@ -160,7 +160,6 @@ static int sendcmd( static int ida_open(struct inode *inode, struct file *filep); static int ida_release(struct inode *inode, struct file *filep); static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io); static void do_ida_request(request_queue_t *q); @@ -200,7 +199,6 @@ static struct block_device_operations ida_fops = { .open = ida_open, .release = ida_release, .ioctl = ida_ioctl, - .getgeo = ida_getgeo, .revalidate_disk= ida_revalidate, }; @@ -1126,23 +1124,6 @@ static void ida_timer(unsigned long tdata) h->misc_tflags = 0; } -static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - drv_info_t *drv = get_drv(bdev->bd_disk); - - if (drv->cylinders) { - geo->heads = drv->heads; - geo->sectors = drv->sectors; - geo->cylinders = drv->cylinders; - } else { - geo->heads = 0xff; - geo->sectors = 0x3f; - geo->cylinders = drv->nr_blks / (0xff*0x3f); - } - - return 0; -} - /* * ida_ioctl does some miscellaneous stuff like reporting drive geometry, * setting readahead and submitting commands from userspace to the controller. @@ -1152,10 +1133,27 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, drv_info_t *drv = get_drv(inode->i_bdev->bd_disk); ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); int error; + int diskinfo[4]; + struct hd_geometry __user *geo = (struct hd_geometry __user *)arg; ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg; ida_ioctl_t *my_io; switch(cmd) { + case HDIO_GETGEO: + if (drv->cylinders) { + diskinfo[0] = drv->heads; + diskinfo[1] = drv->sectors; + diskinfo[2] = drv->cylinders; + } else { + diskinfo[0] = 0xff; + diskinfo[1] = 0x3f; + diskinfo[2] = drv->nr_blks / (0xff*0x3f); + } + put_user(diskinfo[0], &geo->heads); + put_user(diskinfo[1], &geo->sectors); + put_user(diskinfo[2], &geo->cylinders); + put_user(get_start_sect(inode->i_bdev), &geo->start); + return 0; case IDAGETDRVINFO: if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t))) return -EFAULT; diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 374621a512e0..a5b857c5c4b8 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -479,6 +479,7 @@ static struct floppy_struct floppy_type[32] = { { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ }; +#define NUMBER(x) (sizeof(x) / sizeof(*(x))) #define SECTSIZE (_FD_SECTSIZE(*floppy)) /* Auto-detection: Disk type used until the next media change occurs. */ @@ -3444,23 +3445,6 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) return 0; } -static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - int drive = (long)bdev->bd_disk->private_data; - int type = ITYPE(drive_state[drive].fd_device); - struct floppy_struct *g; - int ret; - - ret = get_floppy_geometry(drive, type, &g); - if (ret) - return ret; - - geo->heads = g->head; - geo->sectors = g->sect; - geo->cylinders = g->track; - return 0; -} - static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long param) { @@ -3490,6 +3474,23 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, cmd = FDEJECT; } + /* generic block device ioctls */ + switch (cmd) { + /* the following have been inspired by the corresponding + * code for other block devices. */ + struct floppy_struct *g; + case HDIO_GETGEO: + { + struct hd_geometry loc; + ECALL(get_floppy_geometry(drive, type, &g)); + loc.heads = g->head; + loc.sectors = g->sect; + loc.cylinders = g->track; + loc.start = 0; + return _COPYOUT(loc); + } + } + /* convert the old style command into a new style command */ if ((cmd & 0xff00) == 0x0200) { ECALL(normalize_ioctl(&cmd, &size)); @@ -3644,7 +3645,7 @@ static void __init config_types(void) const char *name = NULL; static char temparea[32]; - if (type < ARRAY_SIZE(default_drive_params)) { + if (type < NUMBER(default_drive_params)) { params = &default_drive_params[type].params; if (type) { name = default_drive_params[type].name; @@ -3937,7 +3938,6 @@ static struct block_device_operations floppy_fops = { .open = floppy_open, .release = floppy_release, .ioctl = fd_ioctl, - .getgeo = fd_getgeo, .media_changed = check_floppy_change, .revalidate_disk = floppy_revalidate, }; @@ -3960,7 +3960,7 @@ static void __init register_devfs_entries(int drive) { int base_minor = (drive < 4) ? drive : (124 + drive); - if (UDP->cmos < ARRAY_SIZE(default_drive_params)) { + if (UDP->cmos < NUMBER(default_drive_params)) { int i = 0; do { int minor = base_minor + (table_sup[UDP->cmos][i] << 2); @@ -4218,7 +4218,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) !(allowed_drive_mask & (1 << drive)) || fdc_state[FDC(drive)].version == FDC_NONE) return NULL; - if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) + if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type)) return NULL; *part = 0; return get_disk(disks[drive]); @@ -4570,7 +4570,7 @@ static void unregister_devfs_entries(int drive) { int i; - if (UDP->cmos < ARRAY_SIZE(default_drive_params)) { + if (UDP->cmos < NUMBER(default_drive_params)) { i = 0; do { devfs_remove("floppy/%d%s", drive, diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index 6997d8e6bfb5..33d6f237b2ed 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -174,6 +174,7 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; + msg.msg_namelen = 0; msg.msg_flags = msg_flags | MSG_NOSIGNAL; if (send) diff --git a/trunk/drivers/block/paride/pd.c b/trunk/drivers/block/paride/pd.c index 62d2464c12f2..fa49d62626ba 100644 --- a/trunk/drivers/block/paride/pd.c +++ b/trunk/drivers/block/paride/pd.c @@ -747,33 +747,32 @@ static int pd_open(struct inode *inode, struct file *file) return 0; } -static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct pd_unit *disk = bdev->bd_disk->private_data; - - if (disk->alt_geom) { - geo->heads = PD_LOG_HEADS; - geo->sectors = PD_LOG_SECTS; - geo->cylinders = disk->capacity / (geo->heads * geo->sectors); - } else { - geo->heads = disk->heads; - geo->sectors = disk->sectors; - geo->cylinders = disk->cylinders; - } - - return 0; -} - static int pd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct pd_unit *disk = inode->i_bdev->bd_disk->private_data; + struct hd_geometry __user *geo = (struct hd_geometry __user *) arg; + struct hd_geometry g; switch (cmd) { case CDROMEJECT: if (disk->access == 1) pd_special_command(disk, pd_eject); return 0; + case HDIO_GETGEO: + if (disk->alt_geom) { + g.heads = PD_LOG_HEADS; + g.sectors = PD_LOG_SECTS; + g.cylinders = disk->capacity / (g.heads * g.sectors); + } else { + g.heads = disk->heads; + g.sectors = disk->sectors; + g.cylinders = disk->cylinders; + } + g.start = get_start_sect(inode->i_bdev); + if (copy_to_user(geo, &g, sizeof(struct hd_geometry))) + return -EFAULT; + return 0; default: return -EINVAL; } @@ -816,7 +815,6 @@ static struct block_device_operations pd_fops = { .open = pd_open, .release = pd_release, .ioctl = pd_ioctl, - .getgeo = pd_getgeo, .media_changed = pd_check_media, .revalidate_disk= pd_revalidate }; diff --git a/trunk/drivers/block/paride/pf.c b/trunk/drivers/block/paride/pf.c index 852b564e903a..e9746af29b9f 100644 --- a/trunk/drivers/block/paride/pf.c +++ b/trunk/drivers/block/paride/pf.c @@ -205,7 +205,6 @@ static int pf_open(struct inode *inode, struct file *file); static void do_pf_request(request_queue_t * q); static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int pf_release(struct inode *inode, struct file *file); @@ -267,7 +266,6 @@ static struct block_device_operations pf_fops = { .open = pf_open, .release = pf_release, .ioctl = pf_ioctl, - .getgeo = pf_getgeo, .media_changed = pf_check_media, }; @@ -315,34 +313,34 @@ static int pf_open(struct inode *inode, struct file *file) return 0; } -static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct pf_unit *pf = bdev->bd_disk->private_data; - sector_t capacity = get_capacity(pf->disk); - - if (capacity < PF_FD_MAX) { - geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT); - geo->heads = PF_FD_HDS; - geo->sectors = PF_FD_SPT; - } else { - geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT); - geo->heads = PF_HD_HDS; - geo->sectors = PF_HD_SPT; - } - - return 0; -} - static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct pf_unit *pf = inode->i_bdev->bd_disk->private_data; - - if (cmd != CDROMEJECT) - return -EINVAL; - - if (pf->access != 1) + struct hd_geometry __user *geo = (struct hd_geometry __user *) arg; + struct hd_geometry g; + sector_t capacity; + + if (cmd == CDROMEJECT) { + if (pf->access == 1) { + pf_eject(pf); + return 0; + } return -EBUSY; - pf_eject(pf); + } + if (cmd != HDIO_GETGEO) + return -EINVAL; + capacity = get_capacity(pf->disk); + if (capacity < PF_FD_MAX) { + g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT); + g.heads = PF_FD_HDS; + g.sectors = PF_FD_SPT; + } else { + g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT); + g.heads = PF_HD_HDS; + g.sectors = PF_HD_SPT; + } + if (copy_to_user(geo, &g, sizeof(g))) + return -EFAULT; return 0; } diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c index 51b7a5c5b77a..c0233efabeba 100644 --- a/trunk/drivers/block/pktcdvd.c +++ b/trunk/drivers/block/pktcdvd.c @@ -1955,12 +1955,9 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) if ((ret = blkdev_get(pd->bdev, FMODE_READ, O_RDONLY))) goto out; - if ((ret = bd_claim(pd->bdev, pd))) - goto out_putdev; - if ((ret = pkt_get_last_written(pd, &lba))) { printk("pktcdvd: pkt_get_last_written failed\n"); - goto out_unclaim; + goto out_putdev; } set_capacity(pd->disk, lba << 2); @@ -1970,7 +1967,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) q = bdev_get_queue(pd->bdev); if (write) { if ((ret = pkt_open_write(pd))) - goto out_unclaim; + goto out_putdev; /* * Some CDRW drives can not handle writes larger than one packet, * even if the size is a multiple of the packet size. @@ -1985,15 +1982,13 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) } if ((ret = pkt_set_segment_merging(pd, q))) - goto out_unclaim; + goto out_putdev; if (write) printk("pktcdvd: %lukB available on disc\n", lba << 1); return 0; -out_unclaim: - bd_release(pd->bdev); out_putdev: blkdev_put(pd->bdev); out: @@ -2012,7 +2007,6 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) pkt_lock_door(pd, 0); pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); - bd_release(pd->bdev); blkdev_put(pd->bdev); } diff --git a/trunk/drivers/block/ps2esdi.c b/trunk/drivers/block/ps2esdi.c index 43415f69839f..29d1518be72a 100644 --- a/trunk/drivers/block/ps2esdi.c +++ b/trunk/drivers/block/ps2esdi.c @@ -81,7 +81,8 @@ static void (*current_int_handler) (u_int) = NULL; static void ps2esdi_normal_interrupt_handler(u_int); static void ps2esdi_initial_reset_int_handler(u_int); static void ps2esdi_geometry_int_handler(u_int); -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo); +static int ps2esdi_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg); static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); @@ -131,7 +132,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = static struct block_device_operations ps2esdi_fops = { .owner = THIS_MODULE, - .getgeo = ps2esdi_getgeo, + .ioctl = ps2esdi_ioctl, }; static struct gendisk *ps2esdi_gendisk[2]; @@ -1057,13 +1058,21 @@ static void dump_cmd_complete_status(u_int int_ret_code) } -static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int ps2esdi_ioctl(struct inode *inode, + struct file *file, u_int cmd, u_long arg) { - struct ps2esdi_i_struct *p = bdev->bd_disk->private_data; - - geo->heads = p->head; - geo->sectors = p->sect; - geo->cylinders = p->cyl; + struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data; + struct ps2esdi_geometry geom; + + if (cmd != HDIO_GETGEO) + return -EINVAL; + memset(&geom, 0, sizeof(geom)); + geom.heads = p->head; + geom.sectors = p->sect; + geom.cylinders = p->cyl; + geom.start = get_start_sect(inode->i_bdev); + if (copy_to_user((void __user *)arg, &geom, sizeof(geom))) + return -EFAULT; return 0; } diff --git a/trunk/drivers/block/sx8.c b/trunk/drivers/block/sx8.c index c0cdc182a8b0..9251f4131b53 100644 --- a/trunk/drivers/block/sx8.c +++ b/trunk/drivers/block/sx8.c @@ -407,7 +407,8 @@ struct carm_array_info { static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void carm_remove_one (struct pci_dev *pdev); -static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo); +static int carm_bdev_ioctl(struct inode *ino, struct file *fil, + unsigned int cmd, unsigned long arg); static struct pci_device_id carm_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, @@ -425,7 +426,7 @@ static struct pci_driver carm_driver = { static struct block_device_operations carm_bd_ops = { .owner = THIS_MODULE, - .getgeo = carm_bdev_getgeo, + .ioctl = carm_bdev_ioctl, }; static unsigned int carm_host_id; @@ -433,14 +434,32 @@ static unsigned long carm_major_alloc; -static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int carm_bdev_ioctl(struct inode *ino, struct file *fil, + unsigned int cmd, unsigned long arg) { - struct carm_port *port = bdev->bd_disk->private_data; + void __user *usermem = (void __user *) arg; + struct carm_port *port = ino->i_bdev->bd_disk->private_data; + struct hd_geometry geom; - geo->heads = (u8) port->dev_geom_head; - geo->sectors = (u8) port->dev_geom_sect; - geo->cylinders = port->dev_geom_cyl; - return 0; + switch (cmd) { + case HDIO_GETGEO: + if (!usermem) + return -EINVAL; + + geom.heads = (u8) port->dev_geom_head; + geom.sectors = (u8) port->dev_geom_sect; + geom.cylinders = port->dev_geom_cyl; + geom.start = get_start_sect(ino->i_bdev); + + if (copy_to_user(usermem, &geom, sizeof(geom))) + return -EFAULT; + return 0; + + default: + break; + } + + return -EOPNOTSUPP; } static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE }; diff --git a/trunk/drivers/block/umem.c b/trunk/drivers/block/umem.c index 15299e7a1ade..0f48301342da 100644 --- a/trunk/drivers/block/umem.c +++ b/trunk/drivers/block/umem.c @@ -809,23 +809,34 @@ static int mm_revalidate(struct gendisk *disk) set_capacity(disk, card->mm_size << 1); return 0; } - -static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo) +/* +----------------------------------------------------------------------------------- +-- mm_ioctl +----------------------------------------------------------------------------------- +*/ +static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) { - struct cardinfo *card = bdev->bd_disk->private_data; - int size = card->mm_size * (1024 / MM_HARDSECT); + if (cmd == HDIO_GETGEO) { + struct cardinfo *card = i->i_bdev->bd_disk->private_data; + int size = card->mm_size * (1024 / MM_HARDSECT); + struct hd_geometry geo; + /* + * get geometry: we have to fake one... trim the size to a + * multiple of 2048 (1M): tell we have 32 sectors, 64 heads, + * whatever cylinders. + */ + geo.heads = 64; + geo.sectors = 32; + geo.start = get_start_sect(i->i_bdev); + geo.cylinders = size / (geo.heads * geo.sectors); + + if (copy_to_user((void __user *) arg, &geo, sizeof(geo))) + return -EFAULT; + return 0; + } - /* - * get geometry: we have to fake one... trim the size to a - * multiple of 2048 (1M): tell we have 32 sectors, 64 heads, - * whatever cylinders. - */ - geo->heads = 64; - geo->sectors = 32; - geo->cylinders = size / (geo->heads * geo->sectors); - return 0; + return -EINVAL; } - /* ----------------------------------------------------------------------------------- -- mm_check_change @@ -844,7 +855,7 @@ static int mm_check_change(struct gendisk *disk) */ static struct block_device_operations mm_fops = { .owner = THIS_MODULE, - .getgeo = mm_getgeo, + .ioctl = mm_ioctl, .revalidate_disk= mm_revalidate, .media_changed = mm_check_change, }; diff --git a/trunk/drivers/block/viodasd.c b/trunk/drivers/block/viodasd.c index d1aaf31bd97e..063f0304a163 100644 --- a/trunk/drivers/block/viodasd.c +++ b/trunk/drivers/block/viodasd.c @@ -247,17 +247,43 @@ static int viodasd_release(struct inode *ino, struct file *fil) /* External ioctl entry point. */ -static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int viodasd_ioctl(struct inode *ino, struct file *fil, + unsigned int cmd, unsigned long arg) { - struct gendisk *disk = bdev->bd_disk; - struct viodasd_device *d = disk->private_data; + unsigned char sectors; + unsigned char heads; + unsigned short cylinders; + struct hd_geometry *geo; + struct gendisk *gendisk; + struct viodasd_device *d; - geo->sectors = d->sectors ? d->sectors : 0; - geo->heads = d->tracks ? d->tracks : 64; - geo->cylinders = d->cylinders ? d->cylinders : - get_capacity(disk) / (geo->cylinders * geo->heads); + switch (cmd) { + case HDIO_GETGEO: + geo = (struct hd_geometry *)arg; + if (geo == NULL) + return -EINVAL; + if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo))) + return -EFAULT; + gendisk = ino->i_bdev->bd_disk; + d = gendisk->private_data; + sectors = d->sectors; + if (sectors == 0) + sectors = 32; + heads = d->tracks; + if (heads == 0) + heads = 64; + cylinders = d->cylinders; + if (cylinders == 0) + cylinders = get_capacity(gendisk) / (sectors * heads); + if (__put_user(sectors, &geo->sectors) || + __put_user(heads, &geo->heads) || + __put_user(cylinders, &geo->cylinders) || + __put_user(get_start_sect(ino->i_bdev), &geo->start)) + return -EFAULT; + return 0; + } - return 0; + return -EINVAL; } /* @@ -267,7 +293,7 @@ static struct block_device_operations viodasd_fops = { .owner = THIS_MODULE, .open = viodasd_open, .release = viodasd_release, - .getgeo = viodasd_getgeo, + .ioctl = viodasd_ioctl, }; /* diff --git a/trunk/drivers/block/xd.c b/trunk/drivers/block/xd.c index cbce7c5e9445..68b6d7b154cf 100644 --- a/trunk/drivers/block/xd.c +++ b/trunk/drivers/block/xd.c @@ -128,12 +128,9 @@ static DEFINE_SPINLOCK(xd_lock); static struct gendisk *xd_gendisk[2]; -static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo); - static struct block_device_operations xd_fops = { .owner = THIS_MODULE, .ioctl = xd_ioctl, - .getgeo = xd_getgeo, }; static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int); static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors; @@ -279,11 +276,11 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address) return(1); } - for (i = 0; i < ARRAY_SIZE(xd_bases); i++) { + for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])); i++) { void __iomem *p = ioremap(xd_bases[i], 0x2000); if (!p) continue; - for (j = 1; j < ARRAY_SIZE(xd_sigs); j++) { + for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])); j++) { const char *s = xd_sigs[j].string; if (check_signature(p + xd_sigs[j].offset, s, strlen(s))) { *controller = j; @@ -333,20 +330,22 @@ static void do_xd_request (request_queue_t * q) } } -static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - XD_INFO *p = bdev->bd_disk->private_data; - - geo->heads = p->heads; - geo->sectors = p->sectors; - geo->cylinders = p->cylinders; - return 0; -} - /* xd_ioctl: handle device ioctl's */ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) { + XD_INFO *p = inode->i_bdev->bd_disk->private_data; + switch (cmd) { + case HDIO_GETGEO: + { + struct hd_geometry g; + struct hd_geometry __user *geom= (void __user *)arg; + g.heads = p->heads; + g.sectors = p->sectors; + g.cylinders = p->cylinders; + g.start = get_start_sect(inode->i_bdev); + return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0; + } case HDIO_SET_DMA: if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (xdc_busy) return -EBUSY; @@ -1018,7 +1017,7 @@ static void __init do_xd_setup (int *integers) case 2: if ((integers[2] > 0) && (integers[2] < 16)) xd_irq = integers[2]; case 1: xd_override = 1; - if ((integers[1] >= 0) && (integers[1] < ARRAY_SIZE(xd_sigs))) + if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0])))) xd_type = integers[1]; case 0: break; default:printk("xd: too many parameters for xd\n"); diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index dd7e6901c575..5ebd06b1b4ca 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -220,14 +220,6 @@ config SYNCLINKMP The module will be called synclinkmp. If you want to do that, say M here. -config SYNCLINK_GT - tristate "SyncLink GT/AC support" - depends on SERIAL_NONSTANDARD - help - Support for SyncLink GT and SyncLink AC families of - synchronous and asynchronous serial adapters - manufactured by Microgate Systems, Ltd. (www.microgate.com) - config N_HDLC tristate "HDLC line discipline support" depends on SERIAL_NONSTANDARD @@ -695,7 +687,7 @@ config NVRAM config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV + depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -743,7 +735,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV + depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you diff --git a/trunk/drivers/char/Makefile b/trunk/drivers/char/Makefile index d973d14d8f7f..4aeae687e88a 100644 --- a/trunk/drivers/char/Makefile +++ b/trunk/drivers/char/Makefile @@ -36,7 +36,6 @@ obj-$(CONFIG_RISCOM8) += riscom8.o obj-$(CONFIG_ISI) += isicom.o obj-$(CONFIG_SYNCLINK) += synclink.o obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o -obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o diff --git a/trunk/drivers/char/agp/sworks-agp.c b/trunk/drivers/char/agp/sworks-agp.c index 268f78d926d3..3f8f7fa6b0ff 100644 --- a/trunk/drivers/char/agp/sworks-agp.c +++ b/trunk/drivers/char/agp/sworks-agp.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "agp.h" diff --git a/trunk/drivers/char/hw_random.c b/trunk/drivers/char/hw_random.c index b3bc2e37e616..49769f59ea1b 100644 --- a/trunk/drivers/char/hw_random.c +++ b/trunk/drivers/char/hw_random.c @@ -169,7 +169,6 @@ static struct pci_device_id rng_pci_tbl[] = { { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, diff --git a/trunk/drivers/char/mem.c b/trunk/drivers/char/mem.c index 5b2d18035073..91dd669273e0 100644 --- a/trunk/drivers/char/mem.c +++ b/trunk/drivers/char/mem.c @@ -101,11 +101,6 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count) return 1; } - -static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size) -{ - return 1; -} #endif /* @@ -233,36 +228,26 @@ static ssize_t write_mem(struct file * file, const char __user * buf, return written; } -#ifndef __HAVE_PHYS_MEM_ACCESS_PROT -static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, - unsigned long size, pgprot_t vma_prot) -{ -#ifdef pgprot_noncached - unsigned long offset = pfn << PAGE_SHIFT; - - if (uncached_access(file, offset)) - return pgprot_noncached(vma_prot); -#endif - return vma_prot; -} -#endif - static int mmap_mem(struct file * file, struct vm_area_struct * vma) { - size_t size = vma->vm_end - vma->vm_start; - - if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size)) - return -EINVAL; - +#if defined(__HAVE_PHYS_MEM_ACCESS_PROT) vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, - size, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +#elif defined(pgprot_noncached) + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + int uncached; + + uncached = uncached_access(file, offset); + if (uncached) + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +#endif /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - size, + vma->vm_end-vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; @@ -832,7 +817,7 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { char *tmp; - ssize_t ret; + int ret; tmp = kmalloc(count + 1, GFP_KERNEL); if (tmp == NULL) @@ -841,9 +826,6 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, if (!copy_from_user(tmp, buf, count)) { tmp[count] = 0; ret = printk("%s", tmp); - if (ret > count) - /* printk can add a prefix */ - ret = count; } kfree(tmp); return ret; diff --git a/trunk/drivers/char/sonypi.c b/trunk/drivers/char/sonypi.c index f8dd8527c6aa..51a07370e636 100644 --- a/trunk/drivers/char/sonypi.c +++ b/trunk/drivers/char/sonypi.c @@ -471,6 +471,7 @@ struct sonypi_keypress { static struct sonypi_device { struct pci_dev *dev; + struct platform_device *pdev; u16 irq; u16 bits; u16 ioport1; @@ -510,11 +511,6 @@ static struct sonypi_device { #define SONYPI_ACPI_ACTIVE 0 #endif /* CONFIG_ACPI */ -#ifdef CONFIG_ACPI -static struct acpi_device *sonypi_acpi_device; -static int acpi_enabled; -#endif - static int sonypi_ec_write(u8 addr, u8 value) { #ifdef CONFIG_ACPI_EC @@ -868,11 +864,6 @@ static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) if (useinput) sonypi_report_input_event(event); -#ifdef CONFIG_ACPI - if (acpi_enabled) - acpi_bus_generate_event(sonypi_acpi_device, 1, event); -#endif - kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_device.fifo_proc_list); @@ -1174,38 +1165,45 @@ static int sonypi_disable(void) return 0; } -#ifdef CONFIG_ACPI -static int sonypi_acpi_add(struct acpi_device *device) +#ifdef CONFIG_PM +static int old_camera_power; + +static int sonypi_suspend(struct platform_device *dev, pm_message_t state) { - sonypi_acpi_device = device; - strcpy(acpi_device_name(device), "Sony laptop hotkeys"); - strcpy(acpi_device_class(device), "sony/hotkey"); + old_camera_power = sonypi_device.camera_power; + sonypi_disable(); + return 0; } -static int sonypi_acpi_remove(struct acpi_device *device, int type) +static int sonypi_resume(struct platform_device *dev) { - sonypi_acpi_device = NULL; + sonypi_enable(old_camera_power); return 0; } +#endif + +static void sonypi_shutdown(struct platform_device *dev) +{ + sonypi_disable(); +} -static struct acpi_driver sonypi_acpi_driver = { - .name = "sonypi", - .class = "hkey", - .ids = "SNY6001", - .ops = { - .add = sonypi_acpi_add, - .remove = sonypi_acpi_remove, +static struct platform_driver sonypi_driver = { +#ifdef CONFIG_PM + .suspend = sonypi_suspend, + .resume = sonypi_resume, +#endif + .shutdown = sonypi_shutdown, + .driver = { + .name = "sonypi", }, }; -#endif static int __devinit sonypi_create_input_devices(void) { struct input_dev *jog_dev; struct input_dev *key_dev; int i; - int error; sonypi_device.input_jog_dev = jog_dev = input_allocate_device(); if (!jog_dev) @@ -1221,8 +1219,9 @@ static int __devinit sonypi_create_input_devices(void) sonypi_device.input_key_dev = key_dev = input_allocate_device(); if (!key_dev) { - error = -ENOMEM; - goto err_free_jogdev; + input_free_device(jog_dev); + sonypi_device.input_jog_dev = NULL; + return -ENOMEM; } key_dev->name = "Sony Vaio Keys"; @@ -1235,122 +1234,56 @@ static int __devinit sonypi_create_input_devices(void) if (sonypi_inputkeys[i].inputev) set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit); - error = input_register_device(jog_dev); - if (error) - goto err_free_keydev; - - error = input_register_device(key_dev); - if (error) - goto err_unregister_jogdev; + input_register_device(jog_dev); + input_register_device(key_dev); return 0; - - err_unregister_jogdev: - input_unregister_device(jog_dev); - /* Set to NULL so we don't free it again below */ - jog_dev = NULL; - err_free_keydev: - input_free_device(key_dev); - sonypi_device.input_key_dev = NULL; - err_free_jogdev: - input_free_device(jog_dev); - sonypi_device.input_jog_dev = NULL; - - return error; -} - -static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, - const struct sonypi_ioport_list *ioport_list) -{ - while (ioport_list->port1) { - - if (request_region(ioport_list->port1, - sonypi_device.region_size, - "Sony Programable I/O Device")) { - dev->ioport1 = ioport_list->port1; - dev->ioport2 = ioport_list->port2; - return 0; - } - ioport_list++; - } - - return -EBUSY; -} - -static int __devinit sonypi_setup_irq(struct sonypi_device *dev, - const struct sonypi_irq_list *irq_list) -{ - while (irq_list->irq) { - - if (!request_irq(irq_list->irq, sonypi_irq, - SA_SHIRQ, "sonypi", sonypi_irq)) { - dev->irq = irq_list->irq; - dev->bits = irq_list->bits; - return 0; - } - irq_list++; - } - - return -EBUSY; } -static void __devinit sonypi_display_info(void) +static int __devinit sonypi_probe(void) { - printk(KERN_INFO "sonypi: detected type%d model, " - "verbose = %d, fnkeyinit = %s, camera = %s, " - "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", - sonypi_device.model, - verbose, - fnkeyinit ? "on" : "off", - camera ? "on" : "off", - compat ? "on" : "off", - mask, - useinput ? "on" : "off", - SONYPI_ACPI_ACTIVE ? "on" : "off"); - printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", - sonypi_device.irq, - sonypi_device.ioport1, sonypi_device.ioport2); + int i, ret; + struct sonypi_ioport_list *ioport_list; + struct sonypi_irq_list *irq_list; + struct pci_dev *pcidev; - if (minor == -1) - printk(KERN_INFO "sonypi: device allocated minor is %d\n", - sonypi_misc_device.minor); -} + if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) + sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; + else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) + sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; + else + sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; -static int __devinit sonypi_probe(struct platform_device *dev) -{ - const struct sonypi_ioport_list *ioport_list; - const struct sonypi_irq_list *irq_list; - struct pci_dev *pcidev; - int error; + sonypi_device.dev = pcidev; spin_lock_init(&sonypi_device.fifo_lock); sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, &sonypi_device.fifo_lock); if (IS_ERR(sonypi_device.fifo)) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - return PTR_ERR(sonypi_device.fifo); + ret = PTR_ERR(sonypi_device.fifo); + goto out_fifo; } init_waitqueue_head(&sonypi_device.fifo_proc_list); init_MUTEX(&sonypi_device.lock); sonypi_device.bluetooth_power = -1; - if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) - sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; - else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) - sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; - else - sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; - if (pcidev && pci_enable_device(pcidev)) { printk(KERN_ERR "sonypi: pci_enable_device failed\n"); - error = -EIO; - goto err_put_pcidev; + ret = -EIO; + goto out_pcienable; + } + + if (minor != -1) + sonypi_misc_device.minor = minor; + if ((ret = misc_register(&sonypi_misc_device))) { + printk(KERN_ERR "sonypi: misc_register failed\n"); + goto out_miscreg; } - sonypi_device.dev = pcidev; if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { ioport_list = sonypi_type1_ioport_list; @@ -1369,36 +1302,43 @@ static int __devinit sonypi_probe(struct platform_device *dev) irq_list = sonypi_type3_irq_list; } - error = sonypi_setup_ioports(&sonypi_device, ioport_list); - if (error) { - printk(KERN_ERR "sonypi: failed to request ioports\n"); - goto err_disable_pcidev; + for (i = 0; ioport_list[i].port1; i++) { + if (request_region(ioport_list[i].port1, + sonypi_device.region_size, + "Sony Programable I/O Device")) { + /* get the ioport */ + sonypi_device.ioport1 = ioport_list[i].port1; + sonypi_device.ioport2 = ioport_list[i].port2; + break; + } } - - error = sonypi_setup_irq(&sonypi_device, irq_list); - if (error) { - printk(KERN_ERR "sonypi: request_irq failed\n"); - goto err_free_ioports; + if (!sonypi_device.ioport1) { + printk(KERN_ERR "sonypi: request_region failed\n"); + ret = -ENODEV; + goto out_reqreg; } - if (minor != -1) - sonypi_misc_device.minor = minor; - error = misc_register(&sonypi_misc_device); - if (error) { - printk(KERN_ERR "sonypi: misc_register failed\n"); - goto err_free_irq; + for (i = 0; irq_list[i].irq; i++) { + + sonypi_device.irq = irq_list[i].irq; + sonypi_device.bits = irq_list[i].bits; + + if (!request_irq(sonypi_device.irq, sonypi_irq, + SA_SHIRQ, "sonypi", sonypi_irq)) + break; } - sonypi_display_info(); + if (!irq_list[i].irq) { + printk(KERN_ERR "sonypi: request_irq failed\n"); + ret = -ENODEV; + goto out_reqirq; + } if (useinput) { - error = sonypi_create_input_devices(); - if (error) { - printk(KERN_ERR - "sonypi: failed to create input devices\n"); - goto err_miscdev_unregister; - } + ret = sonypi_create_input_devices(); + if (ret) + goto out_inputdevices; spin_lock_init(&sonypi_device.input_fifo_lock); sonypi_device.input_fifo = @@ -1406,104 +1346,91 @@ static int __devinit sonypi_probe(struct platform_device *dev) &sonypi_device.input_fifo_lock); if (IS_ERR(sonypi_device.input_fifo)) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - error = PTR_ERR(sonypi_device.input_fifo); - goto err_inpdev_unregister; + ret = PTR_ERR(sonypi_device.input_fifo); + goto out_infifo; } INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); } + sonypi_device.pdev = platform_device_register_simple("sonypi", -1, + NULL, 0); + if (IS_ERR(sonypi_device.pdev)) { + ret = PTR_ERR(sonypi_device.pdev); + goto out_platformdev; + } + sonypi_enable(0); + printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" + "v%s.\n", SONYPI_DRIVER_VERSION); + printk(KERN_INFO "sonypi: detected type%d model, " + "verbose = %d, fnkeyinit = %s, camera = %s, " + "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", + sonypi_device.model, + verbose, + fnkeyinit ? "on" : "off", + camera ? "on" : "off", + compat ? "on" : "off", + mask, + useinput ? "on" : "off", + SONYPI_ACPI_ACTIVE ? "on" : "off"); + printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", + sonypi_device.irq, + sonypi_device.ioport1, sonypi_device.ioport2); + + if (minor == -1) + printk(KERN_INFO "sonypi: device allocated minor is %d\n", + sonypi_misc_device.minor); + return 0; - err_inpdev_unregister: +out_platformdev: + kfifo_free(sonypi_device.input_fifo); +out_infifo: input_unregister_device(sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_jog_dev); - err_miscdev_unregister: - misc_deregister(&sonypi_misc_device); - err_free_irq: +out_inputdevices: free_irq(sonypi_device.irq, sonypi_irq); - err_free_ioports: +out_reqirq: release_region(sonypi_device.ioport1, sonypi_device.region_size); - err_disable_pcidev: +out_reqreg: + misc_deregister(&sonypi_misc_device); +out_miscreg: if (pcidev) pci_disable_device(pcidev); - err_put_pcidev: - pci_dev_put(pcidev); +out_pcienable: kfifo_free(sonypi_device.fifo); - - return error; +out_fifo: + pci_dev_put(sonypi_device.dev); + return ret; } -static int __devexit sonypi_remove(struct platform_device *dev) +static void __devexit sonypi_remove(void) { sonypi_disable(); synchronize_sched(); /* Allow sonypi interrupt to complete. */ flush_scheduled_work(); + platform_device_unregister(sonypi_device.pdev); + if (useinput) { input_unregister_device(sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_jog_dev); kfifo_free(sonypi_device.input_fifo); } - misc_deregister(&sonypi_misc_device); - free_irq(sonypi_device.irq, sonypi_irq); release_region(sonypi_device.ioport1, sonypi_device.region_size); - - if (sonypi_device.dev) { + misc_deregister(&sonypi_misc_device); + if (sonypi_device.dev) pci_disable_device(sonypi_device.dev); - pci_dev_put(sonypi_device.dev); - } - kfifo_free(sonypi_device.fifo); - - return 0; -} - -#ifdef CONFIG_PM -static int old_camera_power; - -static int sonypi_suspend(struct platform_device *dev, pm_message_t state) -{ - old_camera_power = sonypi_device.camera_power; - sonypi_disable(); - - return 0; -} - -static int sonypi_resume(struct platform_device *dev) -{ - sonypi_enable(old_camera_power); - return 0; -} -#else -#define sonypi_suspend NULL -#define sonypi_resume NULL -#endif - -static void sonypi_shutdown(struct platform_device *dev) -{ - sonypi_disable(); + pci_dev_put(sonypi_device.dev); + printk(KERN_INFO "sonypi: removed.\n"); } -static struct platform_driver sonypi_driver = { - .driver = { - .name = "sonypi", - .owner = THIS_MODULE, - }, - .probe = sonypi_probe, - .remove = __devexit_p(sonypi_remove), - .shutdown = sonypi_shutdown, - .suspend = sonypi_suspend, - .resume = sonypi_resume, -}; - -static struct platform_device *sonypi_platform_device; - static struct dmi_system_id __initdata sonypi_dmi_table[] = { { .ident = "Sony Vaio", @@ -1524,52 +1451,26 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = { static int __init sonypi_init(void) { - int error; - - printk(KERN_INFO - "sonypi: Sony Programmable I/O Controller Driver v%s.\n", - SONYPI_DRIVER_VERSION); + int ret; if (!dmi_check_system(sonypi_dmi_table)) return -ENODEV; - error = platform_driver_register(&sonypi_driver); - if (error) - return error; - - sonypi_platform_device = platform_device_alloc("sonypi", -1); - if (!sonypi_platform_device) { - error = -ENOMEM; - goto err_driver_unregister; - } - - error = platform_device_add(sonypi_platform_device); - if (error) - goto err_free_device; - -#ifdef CONFIG_ACPI - if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0) - acpi_enabled = 1; -#endif + ret = platform_driver_register(&sonypi_driver); + if (ret) + return ret; - return 0; + ret = sonypi_probe(); + if (ret) + platform_driver_unregister(&sonypi_driver); - err_free_device: - platform_device_put(sonypi_platform_device); - err_driver_unregister: - platform_driver_unregister(&sonypi_driver); - return error; + return ret; } static void __exit sonypi_exit(void) { -#ifdef CONFIG_ACPI - if (acpi_enabled) - acpi_bus_unregister_driver(&sonypi_acpi_driver); -#endif - platform_device_unregister(sonypi_platform_device); platform_driver_unregister(&sonypi_driver); - printk(KERN_INFO "sonypi: removed.\n"); + sonypi_remove(); } module_init(sonypi_init); diff --git a/trunk/drivers/char/synclink_gt.c b/trunk/drivers/char/synclink_gt.c deleted file mode 100644 index 2b9cde94e2f7..000000000000 --- a/trunk/drivers/char/synclink_gt.c +++ /dev/null @@ -1,4501 +0,0 @@ -/* - * $Id: synclink_gt.c,v 4.20 2005/11/08 19:51:55 paulkf Exp $ - * - * Device driver for Microgate SyncLink GT serial adapters. - * - * written by Paul Fulghum for Microgate Corporation - * paulkf@microgate.com - * - * Microgate and SyncLink are trademarks of Microgate Corporation - * - * This code is released under the GNU General Public License (GPL) - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * DEBUG OUTPUT DEFINITIONS - * - * uncomment lines below to enable specific types of debug output - * - * DBGINFO information - most verbose output - * DBGERR serious errors - * DBGBH bottom half service routine debugging - * DBGISR interrupt service routine debugging - * DBGDATA output receive and transmit data - * DBGTBUF output transmit DMA buffers and registers - * DBGRBUF output receive DMA buffers and registers - */ - -#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt -#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt -#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt -#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt -#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) -//#define DBGTBUF(info) dump_tbufs(info) -//#define DBGRBUF(info) dump_rbufs(info) - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "linux/synclink.h" - -#ifdef CONFIG_HDLC_MODULE -#define CONFIG_HDLC 1 -#endif - -/* - * module identification - */ -static char *driver_name = "SyncLink GT"; -static char *driver_version = "$Revision: 4.20 $"; -static char *tty_driver_name = "synclink_gt"; -static char *tty_dev_prefix = "ttySLG"; -MODULE_LICENSE("GPL"); -#define MGSL_MAGIC 0x5401 -#define MAX_DEVICES 12 - -static struct pci_device_id pci_table[] = { - {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {0,}, /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, pci_table); - -static int init_one(struct pci_dev *dev,const struct pci_device_id *ent); -static void remove_one(struct pci_dev *dev); -static struct pci_driver pci_driver = { - .name = "synclink_gt", - .id_table = pci_table, - .probe = init_one, - .remove = __devexit_p(remove_one), -}; - -static int pci_registered; - -/* - * module configuration and status - */ -static struct slgt_info *slgt_device_list; -static int slgt_device_count; - -static int ttymajor; -static int debug_level; -static int maxframe[MAX_DEVICES]; -static int dosyncppp[MAX_DEVICES]; - -module_param(ttymajor, int, 0); -module_param(debug_level, int, 0); -module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); - -MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned"); -MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail"); -MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)"); -MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable"); - -/* - * tty support and callbacks - */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - -static struct tty_driver *serial_driver; - -static int open(struct tty_struct *tty, struct file * filp); -static void close(struct tty_struct *tty, struct file * filp); -static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); - -static int write(struct tty_struct *tty, const unsigned char *buf, int count); -static void put_char(struct tty_struct *tty, unsigned char ch); -static void send_xchar(struct tty_struct *tty, char ch); -static void wait_until_sent(struct tty_struct *tty, int timeout); -static int write_room(struct tty_struct *tty); -static void flush_chars(struct tty_struct *tty); -static void flush_buffer(struct tty_struct *tty); -static void tx_hold(struct tty_struct *tty); -static void tx_release(struct tty_struct *tty); - -static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); -static int chars_in_buffer(struct tty_struct *tty); -static void throttle(struct tty_struct * tty); -static void unthrottle(struct tty_struct * tty); -static void set_break(struct tty_struct *tty, int break_state); - -/* - * generic HDLC support and callbacks - */ -#ifdef CONFIG_HDLC -#define dev_to_port(D) (dev_to_hdlc(D)->priv) -static void hdlcdev_tx_done(struct slgt_info *info); -static void hdlcdev_rx(struct slgt_info *info, char *buf, int size); -static int hdlcdev_init(struct slgt_info *info); -static void hdlcdev_exit(struct slgt_info *info); -#endif - - -/* - * device specific structures, macros and functions - */ - -#define SLGT_MAX_PORTS 4 -#define SLGT_REG_SIZE 256 - -/* - * DMA buffer descriptor and access macros - */ -struct slgt_desc -{ - unsigned short count; - unsigned short status; - unsigned int pbuf; /* physical address of data buffer */ - unsigned int next; /* physical address of next descriptor */ - - /* driver book keeping */ - char *buf; /* virtual address of data buffer */ - unsigned int pdesc; /* physical address of this descriptor */ - dma_addr_t buf_dma_addr; -}; - -#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) -#define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) -#define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) -#define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) -#define desc_count(a) (le16_to_cpu((a).count)) -#define desc_status(a) (le16_to_cpu((a).status)) -#define desc_complete(a) (le16_to_cpu((a).status) & BIT15) -#define desc_eof(a) (le16_to_cpu((a).status) & BIT2) -#define desc_crc_error(a) (le16_to_cpu((a).status) & BIT1) -#define desc_abort(a) (le16_to_cpu((a).status) & BIT0) -#define desc_residue(a) ((le16_to_cpu((a).status) & 0x38) >> 3) - -struct _input_signal_events { - int ri_up; - int ri_down; - int dsr_up; - int dsr_down; - int dcd_up; - int dcd_down; - int cts_up; - int cts_down; -}; - -/* - * device instance data structure - */ -struct slgt_info { - void *if_ptr; /* General purpose pointer (used by SPPP) */ - - struct slgt_info *next_device; /* device list link */ - - int magic; - int flags; - - char device_name[25]; - struct pci_dev *pdev; - - int port_count; /* count of ports on adapter */ - int adapter_num; /* adapter instance number */ - int port_num; /* port instance number */ - - /* array of pointers to port contexts on this adapter */ - struct slgt_info *port_array[SLGT_MAX_PORTS]; - - int count; /* count of opens */ - int line; /* tty line instance number */ - unsigned short close_delay; - unsigned short closing_wait; /* time to wait before closing */ - - struct mgsl_icount icount; - - struct tty_struct *tty; - int timeout; - int x_char; /* xon/xoff character */ - int blocked_open; /* # of blocked opens */ - unsigned int read_status_mask; - unsigned int ignore_status_mask; - - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - - wait_queue_head_t status_event_wait_q; - wait_queue_head_t event_wait_q; - struct timer_list tx_timer; - struct timer_list rx_timer; - - spinlock_t lock; /* spinlock for synchronizing with ISR */ - - struct work_struct task; - u32 pending_bh; - int bh_requested; - int bh_running; - - int isr_overflow; - int irq_requested; /* nonzero if IRQ requested */ - int irq_occurred; /* for diagnostics use */ - - /* device configuration */ - - unsigned int bus_type; - unsigned int irq_level; - unsigned long irq_flags; - - unsigned char __iomem * reg_addr; /* memory mapped registers address */ - u32 phys_reg_addr; - u32 reg_offset; - int reg_addr_requested; - - MGSL_PARAMS params; /* communications parameters */ - u32 idle_mode; - u32 max_frame_size; /* as set by device config */ - - unsigned int raw_rx_size; - unsigned int if_mode; - - /* device status */ - - int rx_enabled; - int rx_restart; - - int tx_enabled; - int tx_active; - - unsigned char signals; /* serial signal states */ - unsigned int init_error; /* initialization error */ - - unsigned char *tx_buf; - int tx_count; - - char flag_buf[MAX_ASYNC_BUFFER_SIZE]; - char char_buf[MAX_ASYNC_BUFFER_SIZE]; - BOOLEAN drop_rts_on_tx_done; - struct _input_signal_events input_signal_events; - - int dcd_chkcount; /* check counts to prevent */ - int cts_chkcount; /* too many IRQs if a signal */ - int dsr_chkcount; /* is floating */ - int ri_chkcount; - - char *bufs; /* virtual address of DMA buffer lists */ - dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */ - - unsigned int rbuf_count; - struct slgt_desc *rbufs; - unsigned int rbuf_current; - unsigned int rbuf_index; - - unsigned int tbuf_count; - struct slgt_desc *tbufs; - unsigned int tbuf_current; - unsigned int tbuf_start; - - unsigned char *tmp_rbuf; - unsigned int tmp_rbuf_count; - - /* SPPP/Cisco HDLC device parts */ - - int netcount; - int dosyncppp; - spinlock_t netlock; -#ifdef CONFIG_HDLC - struct net_device *netdev; -#endif - -}; - -static MGSL_PARAMS default_params = { - .mode = MGSL_MODE_HDLC, - .loopback = 0, - .flags = HDLC_FLAG_UNDERRUN_ABORT15, - .encoding = HDLC_ENCODING_NRZI_SPACE, - .clock_speed = 0, - .addr_filter = 0xff, - .crc_type = HDLC_CRC_16_CCITT, - .preamble_length = HDLC_PREAMBLE_LENGTH_8BITS, - .preamble = HDLC_PREAMBLE_PATTERN_NONE, - .data_rate = 9600, - .data_bits = 8, - .stop_bits = 1, - .parity = ASYNC_PARITY_NONE -}; - - -#define BH_RECEIVE 1 -#define BH_TRANSMIT 2 -#define BH_STATUS 4 -#define IO_PIN_SHUTDOWN_LIMIT 100 - -#define DMABUFSIZE 256 -#define DESC_LIST_SIZE 4096 - -#define MASK_PARITY BIT1 -#define MASK_FRAMING BIT2 -#define MASK_BREAK BIT3 -#define MASK_OVERRUN BIT4 - -#define GSR 0x00 /* global status */ -#define TDR 0x80 /* tx data */ -#define RDR 0x80 /* rx data */ -#define TCR 0x82 /* tx control */ -#define TIR 0x84 /* tx idle */ -#define TPR 0x85 /* tx preamble */ -#define RCR 0x86 /* rx control */ -#define VCR 0x88 /* V.24 control */ -#define CCR 0x89 /* clock control */ -#define BDR 0x8a /* baud divisor */ -#define SCR 0x8c /* serial control */ -#define SSR 0x8e /* serial status */ -#define RDCSR 0x90 /* rx DMA control/status */ -#define TDCSR 0x94 /* tx DMA control/status */ -#define RDDAR 0x98 /* rx DMA descriptor address */ -#define TDDAR 0x9c /* tx DMA descriptor address */ - -#define RXIDLE BIT14 -#define RXBREAK BIT14 -#define IRQ_TXDATA BIT13 -#define IRQ_TXIDLE BIT12 -#define IRQ_TXUNDER BIT11 /* HDLC */ -#define IRQ_RXDATA BIT10 -#define IRQ_RXIDLE BIT9 /* HDLC */ -#define IRQ_RXBREAK BIT9 /* async */ -#define IRQ_RXOVER BIT8 -#define IRQ_DSR BIT7 -#define IRQ_CTS BIT6 -#define IRQ_DCD BIT5 -#define IRQ_RI BIT4 -#define IRQ_ALL 0x3ff0 -#define IRQ_MASTER BIT0 - -#define slgt_irq_on(info, mask) \ - wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask))) -#define slgt_irq_off(info, mask) \ - wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask))) - -static __u8 rd_reg8(struct slgt_info *info, unsigned int addr); -static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value); -static __u16 rd_reg16(struct slgt_info *info, unsigned int addr); -static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value); -static __u32 rd_reg32(struct slgt_info *info, unsigned int addr); -static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value); - -static void msc_set_vcr(struct slgt_info *info); - -static int startup(struct slgt_info *info); -static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info); -static void shutdown(struct slgt_info *info); -static void program_hw(struct slgt_info *info); -static void change_params(struct slgt_info *info); - -static int register_test(struct slgt_info *info); -static int irq_test(struct slgt_info *info); -static int loopback_test(struct slgt_info *info); -static int adapter_test(struct slgt_info *info); - -static void reset_adapter(struct slgt_info *info); -static void reset_port(struct slgt_info *info); -static void async_mode(struct slgt_info *info); -static void hdlc_mode(struct slgt_info *info); - -static void rx_stop(struct slgt_info *info); -static void rx_start(struct slgt_info *info); -static void reset_rbufs(struct slgt_info *info); -static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last); -static void rdma_reset(struct slgt_info *info); -static int rx_get_frame(struct slgt_info *info); -static int rx_get_buf(struct slgt_info *info); - -static void tx_start(struct slgt_info *info); -static void tx_stop(struct slgt_info *info); -static void tx_set_idle(struct slgt_info *info); -static unsigned int free_tbuf_count(struct slgt_info *info); -static void reset_tbufs(struct slgt_info *info); -static void tdma_reset(struct slgt_info *info); -static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); - -static void get_signals(struct slgt_info *info); -static void set_signals(struct slgt_info *info); -static void enable_loopback(struct slgt_info *info); -static void set_rate(struct slgt_info *info, u32 data_rate); - -static int bh_action(struct slgt_info *info); -static void bh_handler(void* context); -static void bh_transmit(struct slgt_info *info); -static void isr_serial(struct slgt_info *info); -static void isr_rdma(struct slgt_info *info); -static void isr_txeom(struct slgt_info *info, unsigned short status); -static void isr_tdma(struct slgt_info *info); -static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs); - -static int alloc_dma_bufs(struct slgt_info *info); -static void free_dma_bufs(struct slgt_info *info); -static int alloc_desc(struct slgt_info *info); -static void free_desc(struct slgt_info *info); -static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); -static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); - -static int alloc_tmp_rbuf(struct slgt_info *info); -static void free_tmp_rbuf(struct slgt_info *info); - -static void tx_timeout(unsigned long context); -static void rx_timeout(unsigned long context); - -/* - * ioctl handlers - */ -static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount); -static int get_params(struct slgt_info *info, MGSL_PARAMS __user *params); -static int set_params(struct slgt_info *info, MGSL_PARAMS __user *params); -static int get_txidle(struct slgt_info *info, int __user *idle_mode); -static int set_txidle(struct slgt_info *info, int idle_mode); -static int tx_enable(struct slgt_info *info, int enable); -static int tx_abort(struct slgt_info *info); -static int rx_enable(struct slgt_info *info, int enable); -static int modem_input_wait(struct slgt_info *info,int arg); -static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); -static int tiocmget(struct tty_struct *tty, struct file *file); -static int tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); -static void set_break(struct tty_struct *tty, int break_state); -static int get_interface(struct slgt_info *info, int __user *if_mode); -static int set_interface(struct slgt_info *info, int if_mode); - -/* - * driver functions - */ -static void add_device(struct slgt_info *info); -static void device_init(int adapter_num, struct pci_dev *pdev); -static int claim_resources(struct slgt_info *info); -static void release_resources(struct slgt_info *info); - -/* - * DEBUG OUTPUT CODE - */ -#ifndef DBGINFO -#define DBGINFO(fmt) -#endif -#ifndef DBGERR -#define DBGERR(fmt) -#endif -#ifndef DBGBH -#define DBGBH(fmt) -#endif -#ifndef DBGISR -#define DBGISR(fmt) -#endif - -#ifdef DBGDATA -static void trace_block(struct slgt_info *info, const char *data, int count, const char *label) -{ - int i; - int linecount; - printk("%s %s data:\n",info->device_name, label); - while(count) { - linecount = (count > 16) ? 16 : count; - for(i=0; i < linecount; i++) - printk("%02X ",(unsigned char)data[i]); - for(;i<17;i++) - printk(" "); - for(i=0;i=040 && data[i]<=0176) - printk("%c",data[i]); - else - printk("."); - } - printk("\n"); - data += linecount; - count -= linecount; - } -} -#else -#define DBGDATA(info, buf, size, label) -#endif - -#ifdef DBGTBUF -static void dump_tbufs(struct slgt_info *info) -{ - int i; - printk("tbuf_current=%d\n", info->tbuf_current); - for (i=0 ; i < info->tbuf_count ; i++) { - printk("%d: count=%04X status=%04X\n", - i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status)); - } -} -#else -#define DBGTBUF(info) -#endif - -#ifdef DBGRBUF -static void dump_rbufs(struct slgt_info *info) -{ - int i; - printk("rbuf_current=%d\n", info->rbuf_current); - for (i=0 ; i < info->rbuf_count ; i++) { - printk("%d: count=%04X status=%04X\n", - i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status)); - } -} -#else -#define DBGRBUF(info) -#endif - -static inline int sanity_check(struct slgt_info *info, char *devname, const char *name) -{ -#ifdef SANITY_CHECK - if (!info) { - printk("null struct slgt_info for (%s) in %s\n", devname, name); - return 1; - } - if (info->magic != MGSL_MAGIC) { - printk("bad magic number struct slgt_info (%s) in %s\n", devname, name); - return 1; - } -#else - if (!info) - return 1; -#endif - return 0; -} - -/** - * line discipline callback wrappers - * - * The wrappers maintain line discipline references - * while calling into the line discipline. - * - * ldisc_receive_buf - pass receive data to line discipline - */ -static void ldisc_receive_buf(struct tty_struct *tty, - const __u8 *data, char *flags, int count) -{ - struct tty_ldisc *ld; - if (!tty) - return; - ld = tty_ldisc_ref(tty); - if (ld) { - if (ld->receive_buf) - ld->receive_buf(tty, data, flags, count); - tty_ldisc_deref(ld); - } -} - -/* tty callbacks */ - -static int open(struct tty_struct *tty, struct file *filp) -{ - struct slgt_info *info; - int retval, line; - unsigned long flags; - - line = tty->index; - if ((line < 0) || (line >= slgt_device_count)) { - DBGERR(("%s: open with invalid line #%d.\n", driver_name, line)); - return -ENODEV; - } - - info = slgt_device_list; - while(info && info->line != line) - info = info->next_device; - if (sanity_check(info, tty->name, "open")) - return -ENODEV; - if (info->init_error) { - DBGERR(("%s init error=%d\n", info->device_name, info->init_error)); - return -ENODEV; - } - - tty->driver_data = info; - info->tty = tty; - - DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->count)); - - /* If port is closing, signal caller to try again */ - if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){ - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - retval = ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - goto cleanup; - } - - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - spin_lock_irqsave(&info->netlock, flags); - if (info->netcount) { - retval = -EBUSY; - spin_unlock_irqrestore(&info->netlock, flags); - goto cleanup; - } - info->count++; - spin_unlock_irqrestore(&info->netlock, flags); - - if (info->count == 1) { - /* 1st open on this device, init hardware */ - retval = startup(info); - if (retval < 0) - goto cleanup; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { - DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); - goto cleanup; - } - - retval = 0; - -cleanup: - if (retval) { - if (tty->count == 1) - info->tty = NULL; /* tty layer will release tty struct */ - if(info->count) - info->count--; - } - - DBGINFO(("%s open rc=%d\n", info->device_name, retval)); - return retval; -} - -static void close(struct tty_struct *tty, struct file *filp) -{ - struct slgt_info *info = tty->driver_data; - - if (sanity_check(info, tty->name, "close")) - return; - DBGINFO(("%s close entry, count=%d\n", info->device_name, info->count)); - - if (!info->count) - return; - - if (tty_hung_up_p(filp)) - goto cleanup; - - if ((tty->count == 1) && (info->count != 1)) { - /* - * tty->count is 1 and the tty structure will be freed. - * info->count should be one in this case. - * if it's not, correct it so that the port is shutdown. - */ - DBGERR(("%s close: bad refcount; tty->count=1, " - "info->count=%d\n", info->device_name, info->count)); - info->count = 1; - } - - info->count--; - - /* if at least one open remaining, leave hardware active */ - if (info->count) - goto cleanup; - - info->flags |= ASYNC_CLOSING; - - /* set tty->closing to notify line discipline to - * only process XON/XOFF characters. Only the N_TTY - * discipline appears to use this (ppp does not). - */ - tty->closing = 1; - - /* wait for transmit data to clear all layers */ - - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) { - DBGINFO(("%s call tty_wait_until_sent\n", info->device_name)); - tty_wait_until_sent(tty, info->closing_wait); - } - - if (info->flags & ASYNC_INITIALIZED) - wait_until_sent(tty, info->timeout); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - tty_ldisc_flush(tty); - - shutdown(info); - - tty->closing = 0; - info->tty = NULL; - - if (info->blocked_open) { - if (info->close_delay) { - msleep_interruptible(jiffies_to_msecs(info->close_delay)); - } - wake_up_interruptible(&info->open_wait); - } - - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - - wake_up_interruptible(&info->close_wait); - -cleanup: - DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->count)); -} - -static void hangup(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - - if (sanity_check(info, tty->name, "hangup")) - return; - DBGINFO(("%s hangup\n", info->device_name)); - - flush_buffer(tty); - shutdown(info); - - info->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = NULL; - - wake_up_interruptible(&info->open_wait); -} - -static void set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - DBGINFO(("%s set_termios\n", tty->driver->name)); - - /* just return if nothing has changed */ - if ((tty->termios->c_cflag == old_termios->c_cflag) - && (RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - - change_params(info); - - /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios->c_cflag & CBAUD)) { - info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios->c_cflag & CBAUD) { - info->signals |= SerialSignal_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->signals |= SerialSignal_RTS; - } - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } - - /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - tx_release(tty); - } -} - -static int write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int ret = 0; - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "write")) - goto cleanup; - DBGINFO(("%s write count=%d\n", info->device_name, count)); - - if (!tty || !info->tx_buf) - goto cleanup; - - if (count > info->max_frame_size) { - ret = -EIO; - goto cleanup; - } - - if (!count) - goto cleanup; - - if (info->params.mode == MGSL_MODE_RAW) { - unsigned int bufs_needed = (count/DMABUFSIZE); - unsigned int bufs_free = free_tbuf_count(info); - if (count % DMABUFSIZE) - ++bufs_needed; - if (bufs_needed > bufs_free) - goto cleanup; - } else { - if (info->tx_active) - goto cleanup; - if (info->tx_count) { - /* send accumulated data from send_char() calls */ - /* as frame and wait before accepting more data. */ - tx_load(info, info->tx_buf, info->tx_count); - goto start; - } - } - - ret = info->tx_count = count; - tx_load(info, buf, count); - goto start; - -start: - if (info->tx_count && !tty->stopped && !tty->hw_stopped) { - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } - -cleanup: - DBGINFO(("%s write rc=%d\n", info->device_name, ret)); - return ret; -} - -static void put_char(struct tty_struct *tty, unsigned char ch) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "put_char")) - return; - DBGINFO(("%s put_char(%d)\n", info->device_name, ch)); - if (!tty || !info->tx_buf) - return; - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active && (info->tx_count < info->max_frame_size)) - info->tx_buf[info->tx_count++] = ch; - spin_unlock_irqrestore(&info->lock,flags); -} - -static void send_xchar(struct tty_struct *tty, char ch) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "send_xchar")) - return; - DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch)); - info->x_char = ch; - if (ch) { - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_enabled) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -static void wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct slgt_info *info = tty->driver_data; - unsigned long orig_jiffies, char_time; - - if (!info ) - return; - if (sanity_check(info, tty->name, "wait_until_sent")) - return; - DBGINFO(("%s wait_until_sent entry\n", info->device_name)); - if (!(info->flags & ASYNC_INITIALIZED)) - goto exit; - - orig_jiffies = jiffies; - - /* Set check interval to 1/5 of estimated time to - * send a character, and make it at least 1. The check - * interval should also be less than the timeout. - * Note: use tight timings here to satisfy the NIST-PCTS. - */ - - if (info->params.data_rate) { - char_time = info->timeout/(32 * 5); - if (!char_time) - char_time++; - } else - char_time = 1; - - if (timeout) - char_time = min_t(unsigned long, char_time, timeout); - - while (info->tx_active) { - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - -exit: - DBGINFO(("%s wait_until_sent exit\n", info->device_name)); -} - -static int write_room(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - int ret; - - if (sanity_check(info, tty->name, "write_room")) - return 0; - ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; - DBGINFO(("%s write_room=%d\n", info->device_name, ret)); - return ret; -} - -static void flush_chars(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "flush_chars")) - return; - DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count)); - - if (info->tx_count <= 0 || tty->stopped || - tty->hw_stopped || !info->tx_buf) - return; - - DBGINFO(("%s flush_chars start transmit\n", info->device_name)); - - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active && info->tx_count) { - tx_load(info, info->tx_buf,info->tx_count); - tx_start(info); - } - spin_unlock_irqrestore(&info->lock,flags); -} - -static void flush_buffer(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "flush_buffer")) - return; - DBGINFO(("%s flush_buffer\n", info->device_name)); - - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - info->tx_count = 0; - spin_unlock_irqrestore(&info->lock,flags); - - wake_up_interruptible(&tty->write_wait); - tty_wakeup(tty); -} - -/* - * throttle (stop) transmitter - */ -static void tx_hold(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "tx_hold")) - return; - DBGINFO(("%s tx_hold\n", info->device_name)); - spin_lock_irqsave(&info->lock,flags); - if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC) - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); -} - -/* - * release (start) transmitter - */ -static void tx_release(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "tx_release")) - return; - DBGINFO(("%s tx_release\n", info->device_name)); - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active && info->tx_count) { - tx_load(info, info->tx_buf, info->tx_count); - tx_start(info); - } - spin_unlock_irqrestore(&info->lock,flags); -} - -/* - * Service an IOCTL request - * - * Arguments - * - * tty pointer to tty instance data - * file pointer to associated file object for device - * cmd IOCTL command code - * arg command argument/context - * - * Return 0 if success, otherwise error code - */ -static int ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct slgt_info *info = tty->driver_data; - struct mgsl_icount cnow; /* kernel counter temps */ - struct serial_icounter_struct __user *p_cuser; /* user space */ - unsigned long flags; - void __user *argp = (void __user *)arg; - - if (sanity_check(info, tty->name, "ioctl")) - return -ENODEV; - DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case MGSL_IOCGPARAMS: - return get_params(info, argp); - case MGSL_IOCSPARAMS: - return set_params(info, argp); - case MGSL_IOCGTXIDLE: - return get_txidle(info, argp); - case MGSL_IOCSTXIDLE: - return set_txidle(info, (int)arg); - case MGSL_IOCTXENABLE: - return tx_enable(info, (int)arg); - case MGSL_IOCRXENABLE: - return rx_enable(info, (int)arg); - case MGSL_IOCTXABORT: - return tx_abort(info); - case MGSL_IOCGSTATS: - return get_stats(info, argp); - case MGSL_IOCWAITEVENT: - return wait_mgsl_event(info, argp); - case TIOCMIWAIT: - return modem_input_wait(info,(int)arg); - case MGSL_IOCGIF: - return get_interface(info, argp); - case MGSL_IOCSIF: - return set_interface(info,(int)arg); - case TIOCGICOUNT: - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->lock,flags); - p_cuser = argp; - if (put_user(cnow.cts, &p_cuser->cts) || - put_user(cnow.dsr, &p_cuser->dsr) || - put_user(cnow.rng, &p_cuser->rng) || - put_user(cnow.dcd, &p_cuser->dcd) || - put_user(cnow.rx, &p_cuser->rx) || - put_user(cnow.tx, &p_cuser->tx) || - put_user(cnow.frame, &p_cuser->frame) || - put_user(cnow.overrun, &p_cuser->overrun) || - put_user(cnow.parity, &p_cuser->parity) || - put_user(cnow.brk, &p_cuser->brk) || - put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) - return -EFAULT; - return 0; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -/* - * proc fs support - */ -static inline int line_info(char *buf, struct slgt_info *info) -{ - char stat_buf[30]; - int ret; - unsigned long flags; - - ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", - info->device_name, info->phys_reg_addr, - info->irq_level, info->max_frame_size); - - /* output current serial signal states */ - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - stat_buf[0] = 0; - stat_buf[1] = 0; - if (info->signals & SerialSignal_RTS) - strcat(stat_buf, "|RTS"); - if (info->signals & SerialSignal_CTS) - strcat(stat_buf, "|CTS"); - if (info->signals & SerialSignal_DTR) - strcat(stat_buf, "|DTR"); - if (info->signals & SerialSignal_DSR) - strcat(stat_buf, "|DSR"); - if (info->signals & SerialSignal_DCD) - strcat(stat_buf, "|CD"); - if (info->signals & SerialSignal_RI) - strcat(stat_buf, "|RI"); - - if (info->params.mode != MGSL_MODE_ASYNC) { - ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", - info->icount.txok, info->icount.rxok); - if (info->icount.txunder) - ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); - if (info->icount.txabort) - ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); - if (info->icount.rxshort) - ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); - if (info->icount.rxlong) - ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); - if (info->icount.rxover) - ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); - if (info->icount.rxcrc) - ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); - } else { - ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", - info->icount.tx, info->icount.rx); - if (info->icount.frame) - ret += sprintf(buf+ret, " fe:%d", info->icount.frame); - if (info->icount.parity) - ret += sprintf(buf+ret, " pe:%d", info->icount.parity); - if (info->icount.brk) - ret += sprintf(buf+ret, " brk:%d", info->icount.brk); - if (info->icount.overrun) - ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); - } - - /* Append serial signal status to end */ - ret += sprintf(buf+ret, " %s\n", stat_buf+1); - - ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", - info->tx_active,info->bh_requested,info->bh_running, - info->pending_bh); - - return ret; -} - -/* Called to print information about devices - */ -static int read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - int len = 0, l; - off_t begin = 0; - struct slgt_info *info; - - len += sprintf(page, "synclink_gt driver:%s\n", driver_version); - - info = slgt_device_list; - while( info ) { - l = line_info(page + len, info); - len += l; - if (len+begin > off+count) - goto done; - if (len+begin < off) { - begin += len; - len = 0; - } - info = info->next_device; - } - - *eof = 1; -done: - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * return count of bytes in transmit buffer - */ -static int chars_in_buffer(struct tty_struct *tty) -{ - struct slgt_info *info = tty->driver_data; - if (sanity_check(info, tty->name, "chars_in_buffer")) - return 0; - DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count)); - return info->tx_count; -} - -/* - * signal remote device to throttle send data (our receive data) - */ -static void throttle(struct tty_struct * tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "throttle")) - return; - DBGINFO(("%s throttle\n", info->device_name)); - if (I_IXOFF(tty)) - send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); - info->signals &= ~SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -/* - * signal remote device to stop throttling send data (our receive data) - */ -static void unthrottle(struct tty_struct * tty) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - if (sanity_check(info, tty->name, "unthrottle")) - return; - DBGINFO(("%s unthrottle\n", info->device_name)); - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - send_xchar(tty, START_CHAR(tty)); - } - if (tty->termios->c_cflag & CRTSCTS) { - spin_lock_irqsave(&info->lock,flags); - info->signals |= SerialSignal_RTS; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } -} - -/* - * set or clear transmit break condition - * break_state -1=set break condition, 0=clear - */ -static void set_break(struct tty_struct *tty, int break_state) -{ - struct slgt_info *info = tty->driver_data; - unsigned short value; - unsigned long flags; - - if (sanity_check(info, tty->name, "set_break")) - return; - DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); - - spin_lock_irqsave(&info->lock,flags); - value = rd_reg16(info, TCR); - if (break_state == -1) - value |= BIT6; - else - value &= ~BIT6; - wr_reg16(info, TCR, value); - spin_unlock_irqrestore(&info->lock,flags); -} - -#ifdef CONFIG_HDLC - -/** - * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) - * set encoding and frame check sequence (FCS) options - * - * dev pointer to network device structure - * encoding serial encoding setting - * parity FCS setting - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, - unsigned short parity) -{ - struct slgt_info *info = dev_to_port(dev); - unsigned char new_encoding; - unsigned short new_crctype; - - /* return error if TTY interface open */ - if (info->count) - return -EBUSY; - - DBGINFO(("%s hdlcdev_attach\n", info->device_name)); - - switch (encoding) - { - case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; - case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; - case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; - case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; - case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; - default: return -EINVAL; - } - - switch (parity) - { - case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; - case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; - case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; - default: return -EINVAL; - } - - info->params.encoding = new_encoding; - info->params.crc_type = new_crctype;; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - program_hw(info); - - return 0; -} - -/** - * called by generic HDLC layer to send frame - * - * skb socket buffer containing HDLC frame - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - struct net_device_stats *stats = hdlc_stats(dev); - unsigned long flags; - - DBGINFO(("%s hdlc_xmit\n", dev->name)); - - /* stop sending until this frame completes */ - netif_stop_queue(dev); - - /* copy data to device buffers */ - info->tx_count = skb->len; - tx_load(info, skb->data, skb->len); - - /* update network statistics */ - stats->tx_packets++; - stats->tx_bytes += skb->len; - - /* done with socket buffer, so free it */ - dev_kfree_skb(skb); - - /* save start time for transmit timeout detection */ - dev->trans_start = jiffies; - - /* start hardware transmitter if necessary */ - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - - return 0; -} - -/** - * called by network layer when interface enabled - * claim resources and initialize hardware - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_open(struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - int rc; - unsigned long flags; - - DBGINFO(("%s hdlcdev_open\n", dev->name)); - - /* generic HDLC layer open processing */ - if ((rc = hdlc_open(dev))) - return rc; - - /* arbitrate between network and tty opens */ - spin_lock_irqsave(&info->netlock, flags); - if (info->count != 0 || info->netcount != 0) { - DBGINFO(("%s hdlc_open busy\n", dev->name)); - spin_unlock_irqrestore(&info->netlock, flags); - return -EBUSY; - } - info->netcount=1; - spin_unlock_irqrestore(&info->netlock, flags); - - /* claim resources and init adapter */ - if ((rc = startup(info)) != 0) { - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return rc; - } - - /* assert DTR and RTS, apply hardware settings */ - info->signals |= SerialSignal_RTS + SerialSignal_DTR; - program_hw(info); - - /* enable network layer transmit */ - dev->trans_start = jiffies; - netif_start_queue(dev); - - /* inform generic HDLC layer of current DCD status */ - spin_lock_irqsave(&info->lock, flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock, flags); - hdlc_set_carrier(info->signals & SerialSignal_DCD, dev); - - return 0; -} - -/** - * called by network layer when interface is disabled - * shutdown hardware and release resources - * - * dev pointer to network device structure - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_close(struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - unsigned long flags; - - DBGINFO(("%s hdlcdev_close\n", dev->name)); - - netif_stop_queue(dev); - - /* shutdown adapter and release resources */ - shutdown(info); - - hdlc_close(dev); - - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - - return 0; -} - -/** - * called by network layer to process IOCTL call to network device - * - * dev pointer to network device structure - * ifr pointer to network interface request structure - * cmd IOCTL command code - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line; - sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; - struct slgt_info *info = dev_to_port(dev); - unsigned int flags; - - DBGINFO(("%s hdlcdev_ioctl\n", dev->name)); - - /* return error if TTY interface open */ - if (info->count) - return -EBUSY; - - if (cmd != SIOCWANDEV) - return hdlc_ioctl(dev, ifr, cmd); - - switch(ifr->ifr_settings.type) { - case IF_GET_IFACE: /* return current sync_serial_settings */ - - ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - - flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - - switch (flags){ - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; - case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; - case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; - default: new_line.clock_type = CLOCK_DEFAULT; - } - - new_line.clock_rate = info->params.clock_speed; - new_line.loopback = info->params.loopback ? 1:0; - - if (copy_to_user(line, &new_line, size)) - return -EFAULT; - return 0; - - case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&new_line, line, size)) - return -EFAULT; - - switch (new_line.clock_type) - { - case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; - case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; - case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; - case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; - case CLOCK_DEFAULT: flags = info->params.flags & - (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; - default: return -EINVAL; - } - - if (new_line.loopback != 0 && new_line.loopback != 1) - return -EINVAL; - - info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | - HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | - HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | - HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); - info->params.flags |= flags; - - info->params.loopback = new_line.loopback; - - if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) - info->params.clock_speed = new_line.clock_rate; - else - info->params.clock_speed = 0; - - /* if network interface up, reprogram hardware */ - if (info->netcount) - program_hw(info); - return 0; - - default: - return hdlc_ioctl(dev, ifr, cmd); - } -} - -/** - * called by network layer when transmit timeout is detected - * - * dev pointer to network device structure - */ -static void hdlcdev_tx_timeout(struct net_device *dev) -{ - struct slgt_info *info = dev_to_port(dev); - struct net_device_stats *stats = hdlc_stats(dev); - unsigned long flags; - - DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name)); - - stats->tx_errors++; - stats->tx_aborted_errors++; - - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); - - netif_wake_queue(dev); -} - -/** - * called by device driver when transmit completes - * reenable network layer transmit if stopped - * - * info pointer to device instance information - */ -static void hdlcdev_tx_done(struct slgt_info *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); -} - -/** - * called by device driver when frame received - * pass frame to network layer - * - * info pointer to device instance information - * buf pointer to buffer contianing frame data - * size count of data bytes in buf - */ -static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) -{ - struct sk_buff *skb = dev_alloc_skb(size); - struct net_device *dev = info->netdev; - struct net_device_stats *stats = hdlc_stats(dev); - - DBGINFO(("%s hdlcdev_rx\n", dev->name)); - - if (skb == NULL) { - DBGERR(("%s: can't alloc skb, drop packet\n", dev->name)); - stats->rx_dropped++; - return; - } - - memcpy(skb_put(skb, size),buf,size); - - skb->protocol = hdlc_type_trans(skb, info->netdev); - - stats->rx_packets++; - stats->rx_bytes += size; - - netif_rx(skb); - - info->netdev->last_rx = jiffies; -} - -/** - * called by device driver when adding device instance - * do generic HDLC initialization - * - * info pointer to device instance information - * - * returns 0 if success, otherwise error code - */ -static int hdlcdev_init(struct slgt_info *info) -{ - int rc; - struct net_device *dev; - hdlc_device *hdlc; - - /* allocate and initialize network and HDLC layer objects */ - - if (!(dev = alloc_hdlcdev(info))) { - printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name); - return -ENOMEM; - } - - /* for network layer reporting purposes only */ - dev->mem_start = info->phys_reg_addr; - dev->mem_end = info->phys_reg_addr + SLGT_REG_SIZE - 1; - dev->irq = info->irq_level; - - /* network layer callbacks and settings */ - dev->do_ioctl = hdlcdev_ioctl; - dev->open = hdlcdev_open; - dev->stop = hdlcdev_close; - dev->tx_timeout = hdlcdev_tx_timeout; - dev->watchdog_timeo = 10*HZ; - dev->tx_queue_len = 50; - - /* generic HDLC layer callbacks and settings */ - hdlc = dev_to_hdlc(dev); - hdlc->attach = hdlcdev_attach; - hdlc->xmit = hdlcdev_xmit; - - /* register objects with HDLC layer */ - if ((rc = register_hdlc_device(dev))) { - printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); - free_netdev(dev); - return rc; - } - - info->netdev = dev; - return 0; -} - -/** - * called by device driver when removing device instance - * do generic HDLC cleanup - * - * info pointer to device instance information - */ -static void hdlcdev_exit(struct slgt_info *info) -{ - unregister_hdlc_device(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; -} - -#endif /* ifdef CONFIG_HDLC */ - -/* - * get async data from rx DMA buffers - */ -static void rx_async(struct slgt_info *info) -{ - struct tty_struct *tty = info->tty; - struct mgsl_icount *icount = &info->icount; - unsigned int start, end; - unsigned char *p; - unsigned char status; - struct slgt_desc *bufs = info->rbufs; - int i, count; - - start = end = info->rbuf_current; - - while(desc_complete(bufs[end])) { - count = desc_count(bufs[end]) - info->rbuf_index; - p = bufs[end].buf + info->rbuf_index; - - DBGISR(("%s rx_async count=%d\n", info->device_name, count)); - DBGDATA(info, p, count, "rx"); - - for(i=0 ; i < count; i+=2, p+=2) { - if (tty) { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - tty_flip_buffer_push(tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; - *tty->flip.char_buf_ptr = *p; - *tty->flip.flag_buf_ptr = 0; - } - icount->rx++; - - if ((status = *(p+1) & (BIT9 + BIT8))) { - if (status & BIT9) - icount->parity++; - else if (status & BIT8) - icount->frame++; - /* discard char if tty control flags say so */ - if (status & info->ignore_status_mask) - continue; - if (tty) { - if (status & BIT9) - *tty->flip.flag_buf_ptr = TTY_PARITY; - else if (status & BIT8) - *tty->flip.flag_buf_ptr = TTY_FRAME; - } - } - if (tty) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - } - } - - if (i < count) { - /* receive buffer not completed */ - info->rbuf_index += i; - info->rx_timer.expires = jiffies + 1; - add_timer(&info->rx_timer); - break; - } - - info->rbuf_index = 0; - free_rbufs(info, end, end); - - if (++end == info->rbuf_count) - end = 0; - - /* if entire list searched then no frame available */ - if (end == start) - break; - } - - if (tty && tty->flip.count) - tty_flip_buffer_push(tty); -} - -/* - * return next bottom half action to perform - */ -static int bh_action(struct slgt_info *info) -{ - unsigned long flags; - int rc; - - spin_lock_irqsave(&info->lock,flags); - - if (info->pending_bh & BH_RECEIVE) { - info->pending_bh &= ~BH_RECEIVE; - rc = BH_RECEIVE; - } else if (info->pending_bh & BH_TRANSMIT) { - info->pending_bh &= ~BH_TRANSMIT; - rc = BH_TRANSMIT; - } else if (info->pending_bh & BH_STATUS) { - info->pending_bh &= ~BH_STATUS; - rc = BH_STATUS; - } else { - /* Mark BH routine as complete */ - info->bh_running = 0; - info->bh_requested = 0; - rc = 0; - } - - spin_unlock_irqrestore(&info->lock,flags); - - return rc; -} - -/* - * perform bottom half processing - */ -static void bh_handler(void* context) -{ - struct slgt_info *info = context; - int action; - - if (!info) - return; - info->bh_running = 1; - - while((action = bh_action(info))) { - switch (action) { - case BH_RECEIVE: - DBGBH(("%s bh receive\n", info->device_name)); - switch(info->params.mode) { - case MGSL_MODE_ASYNC: - rx_async(info); - break; - case MGSL_MODE_HDLC: - while(rx_get_frame(info)); - break; - case MGSL_MODE_RAW: - while(rx_get_buf(info)); - break; - } - /* restart receiver if rx DMA buffers exhausted */ - if (info->rx_restart) - rx_start(info); - break; - case BH_TRANSMIT: - bh_transmit(info); - break; - case BH_STATUS: - DBGBH(("%s bh status\n", info->device_name)); - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - info->dcd_chkcount = 0; - info->cts_chkcount = 0; - break; - default: - DBGBH(("%s unknown action\n", info->device_name)); - break; - } - } - DBGBH(("%s bh_handler exit\n", info->device_name)); -} - -static void bh_transmit(struct slgt_info *info) -{ - struct tty_struct *tty = info->tty; - - DBGBH(("%s bh_transmit\n", info->device_name)); - if (tty) { - tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } -} - -static void dsr_change(struct slgt_info *info) -{ - get_signals(info); - DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_DSR); - return; - } - info->icount.dsr++; - if (info->signals & SerialSignal_DSR) - info->input_signal_events.dsr_up++; - else - info->input_signal_events.dsr_down++; - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; -} - -static void cts_change(struct slgt_info *info) -{ - get_signals(info); - DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_CTS); - return; - } - info->icount.cts++; - if (info->signals & SerialSignal_CTS) - info->input_signal_events.cts_up++; - else - info->input_signal_events.cts_down++; - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; - - if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty) { - if (info->tty->hw_stopped) { - if (info->signals & SerialSignal_CTS) { - info->tty->hw_stopped = 0; - info->pending_bh |= BH_TRANSMIT; - return; - } - } else { - if (!(info->signals & SerialSignal_CTS)) - info->tty->hw_stopped = 1; - } - } - } -} - -static void dcd_change(struct slgt_info *info) -{ - get_signals(info); - DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_DCD); - return; - } - info->icount.dcd++; - if (info->signals & SerialSignal_DCD) { - info->input_signal_events.dcd_up++; - } else { - info->input_signal_events.dcd_down++; - } -#ifdef CONFIG_HDLC - if (info->netcount) - hdlc_set_carrier(info->signals & SerialSignal_DCD, info->netdev); -#endif - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; - - if (info->flags & ASYNC_CHECK_CD) { - if (info->signals & SerialSignal_DCD) - wake_up_interruptible(&info->open_wait); - else { - if (info->tty) - tty_hangup(info->tty); - } - } -} - -static void ri_change(struct slgt_info *info) -{ - get_signals(info); - DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); - if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { - slgt_irq_off(info, IRQ_RI); - return; - } - info->icount.dcd++; - if (info->signals & SerialSignal_RI) { - info->input_signal_events.ri_up++; - } else { - info->input_signal_events.ri_down++; - } - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - info->pending_bh |= BH_STATUS; -} - -static void isr_serial(struct slgt_info *info) -{ - unsigned short status = rd_reg16(info, SSR); - - DBGISR(("%s isr_serial status=%04X\n", info->device_name, status)); - - wr_reg16(info, SSR, status); /* clear pending */ - - info->irq_occurred = 1; - - if (info->params.mode == MGSL_MODE_ASYNC) { - if (status & IRQ_TXIDLE) { - if (info->tx_count) - isr_txeom(info, status); - } - if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { - info->icount.brk++; - /* process break detection if tty control allows */ - if (info->tty) { - if (!(status & info->ignore_status_mask)) { - if (info->read_status_mask & MASK_BREAK) { - *info->tty->flip.flag_buf_ptr = TTY_BREAK; - if (info->flags & ASYNC_SAK) - do_SAK(info->tty); - } - } - } - } - } else { - if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) - isr_txeom(info, status); - - if (status & IRQ_RXIDLE) { - if (status & RXIDLE) - info->icount.rxidle++; - else - info->icount.exithunt++; - wake_up_interruptible(&info->event_wait_q); - } - - if (status & IRQ_RXOVER) - rx_start(info); - } - - if (status & IRQ_DSR) - dsr_change(info); - if (status & IRQ_CTS) - cts_change(info); - if (status & IRQ_DCD) - dcd_change(info); - if (status & IRQ_RI) - ri_change(info); -} - -static void isr_rdma(struct slgt_info *info) -{ - unsigned int status = rd_reg32(info, RDCSR); - - DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status)); - - /* RDCSR (rx DMA control/status) - * - * 31..07 reserved - * 06 save status byte to DMA buffer - * 05 error - * 04 eol (end of list) - * 03 eob (end of buffer) - * 02 IRQ enable - * 01 reset - * 00 enable - */ - wr_reg32(info, RDCSR, status); /* clear pending */ - - if (status & (BIT5 + BIT4)) { - DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name)); - info->rx_restart = 1; - } - info->pending_bh |= BH_RECEIVE; -} - -static void isr_tdma(struct slgt_info *info) -{ - unsigned int status = rd_reg32(info, TDCSR); - - DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status)); - - /* TDCSR (tx DMA control/status) - * - * 31..06 reserved - * 05 error - * 04 eol (end of list) - * 03 eob (end of buffer) - * 02 IRQ enable - * 01 reset - * 00 enable - */ - wr_reg32(info, TDCSR, status); /* clear pending */ - - if (status & (BIT5 + BIT4 + BIT3)) { - // another transmit buffer has completed - // run bottom half to get more send data from user - info->pending_bh |= BH_TRANSMIT; - } -} - -static void isr_txeom(struct slgt_info *info, unsigned short status) -{ - DBGISR(("%s txeom status=%04x\n", info->device_name, status)); - - slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); - tdma_reset(info); - reset_tbufs(info); - if (status & IRQ_TXUNDER) { - unsigned short val = rd_reg16(info, TCR); - wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, TCR, val); /* clear reset bit */ - } - - if (info->tx_active) { - if (info->params.mode != MGSL_MODE_ASYNC) { - if (status & IRQ_TXUNDER) - info->icount.txunder++; - else if (status & IRQ_TXIDLE) - info->icount.txok++; - } - - info->tx_active = 0; - info->tx_count = 0; - - del_timer(&info->tx_timer); - - if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) { - info->signals &= ~SerialSignal_RTS; - info->drop_rts_on_tx_done = 0; - set_signals(info); - } - -#ifdef CONFIG_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - { - if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) { - tx_stop(info); - return; - } - info->pending_bh |= BH_TRANSMIT; - } - } -} - -/* interrupt service routine - * - * irq interrupt number - * dev_id device ID supplied during interrupt registration - * regs interrupted processor context - */ -static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - struct slgt_info *info; - unsigned int gsr; - unsigned int i; - - DBGISR(("slgt_interrupt irq=%d entry\n", irq)); - - info = dev_id; - if (!info) - return IRQ_NONE; - - spin_lock(&info->lock); - - while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { - DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); - info->irq_occurred = 1; - for(i=0; i < info->port_count ; i++) { - if (info->port_array[i] == NULL) - continue; - if (gsr & (BIT8 << i)) - isr_serial(info->port_array[i]); - if (gsr & (BIT16 << (i*2))) - isr_rdma(info->port_array[i]); - if (gsr & (BIT17 << (i*2))) - isr_tdma(info->port_array[i]); - } - } - - for(i=0; i < info->port_count ; i++) { - struct slgt_info *port = info->port_array[i]; - - if (port && (port->count || port->netcount) && - port->pending_bh && !port->bh_running && - !port->bh_requested) { - DBGISR(("%s bh queued\n", port->device_name)); - schedule_work(&port->task); - port->bh_requested = 1; - } - } - - spin_unlock(&info->lock); - - DBGISR(("slgt_interrupt irq=%d exit\n", irq)); - return IRQ_HANDLED; -} - -static int startup(struct slgt_info *info) -{ - DBGINFO(("%s startup\n", info->device_name)); - - if (info->flags & ASYNC_INITIALIZED) - return 0; - - if (!info->tx_buf) { - info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); - if (!info->tx_buf) { - DBGERR(("%s can't allocate tx buffer\n", info->device_name)); - return -ENOMEM; - } - } - - info->pending_bh = 0; - - memset(&info->icount, 0, sizeof(info->icount)); - - /* program hardware for current parameters */ - change_params(info); - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags |= ASYNC_INITIALIZED; - - return 0; -} - -/* - * called by close() and hangup() to shutdown hardware - */ -static void shutdown(struct slgt_info *info) -{ - unsigned long flags; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - - DBGINFO(("%s shutdown\n", info->device_name)); - - /* clear status wait queue because status changes */ - /* can't happen after shutting down the hardware */ - wake_up_interruptible(&info->status_event_wait_q); - wake_up_interruptible(&info->event_wait_q); - - del_timer_sync(&info->tx_timer); - del_timer_sync(&info->rx_timer); - - kfree(info->tx_buf); - info->tx_buf = NULL; - - spin_lock_irqsave(&info->lock,flags); - - tx_stop(info); - rx_stop(info); - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); - - if (!info->tty || info->tty->termios->c_cflag & HUPCL) { - info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); - set_signals(info); - } - - spin_unlock_irqrestore(&info->lock,flags); - - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; -} - -static void program_hw(struct slgt_info *info) -{ - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - - rx_stop(info); - tx_stop(info); - - if (info->params.mode == MGSL_MODE_HDLC || - info->params.mode == MGSL_MODE_RAW || - info->netcount) - hdlc_mode(info); - else - async_mode(info); - - set_signals(info); - - info->dcd_chkcount = 0; - info->cts_chkcount = 0; - info->ri_chkcount = 0; - info->dsr_chkcount = 0; - - slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR); - get_signals(info); - - if (info->netcount || - (info->tty && info->tty->termios->c_cflag & CREAD)) - rx_start(info); - - spin_unlock_irqrestore(&info->lock,flags); -} - -/* - * reconfigure adapter based on new parameters - */ -static void change_params(struct slgt_info *info) -{ - unsigned cflag; - int bits_per_char; - - if (!info->tty || !info->tty->termios) - return; - DBGINFO(("%s change_params\n", info->device_name)); - - cflag = info->tty->termios->c_cflag; - - /* if B0 rate (hangup) specified then negate DTR and RTS */ - /* otherwise assert DTR and RTS */ - if (cflag & CBAUD) - info->signals |= SerialSignal_RTS + SerialSignal_DTR; - else - info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); - - /* byte size and parity */ - - switch (cflag & CSIZE) { - case CS5: info->params.data_bits = 5; break; - case CS6: info->params.data_bits = 6; break; - case CS7: info->params.data_bits = 7; break; - case CS8: info->params.data_bits = 8; break; - default: info->params.data_bits = 7; break; - } - - info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1; - - if (cflag & PARENB) - info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN; - else - info->params.parity = ASYNC_PARITY_NONE; - - /* calculate number of jiffies to transmit a full - * FIFO (32 bytes) at specified data rate - */ - bits_per_char = info->params.data_bits + - info->params.stop_bits + 1; - - info->params.data_rate = tty_get_baud_rate(info->tty); - - if (info->params.data_rate) { - info->timeout = (32*HZ*bits_per_char) / - info->params.data_rate; - } - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - if (cflag & CRTSCTS) - info->flags |= ASYNC_CTS_FLOW; - else - info->flags &= ~ASYNC_CTS_FLOW; - - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; - - /* process tty input control flags */ - - info->read_status_mask = IRQ_RXOVER; - if (I_INPCK(info->tty)) - info->read_status_mask |= MASK_PARITY | MASK_FRAMING; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) - info->read_status_mask |= MASK_BREAK; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING; - if (I_IGNBRK(info->tty)) { - info->ignore_status_mask |= MASK_BREAK; - /* If ignoring parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= MASK_OVERRUN; - } - - program_hw(info); -} - -static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount) -{ - DBGINFO(("%s get_stats\n", info->device_name)); - if (!user_icount) { - memset(&info->icount, 0, sizeof(info->icount)); - } else { - if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount))) - return -EFAULT; - } - return 0; -} - -static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params) -{ - DBGINFO(("%s get_params\n", info->device_name)); - if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS))) - return -EFAULT; - return 0; -} - -static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params) -{ - unsigned long flags; - MGSL_PARAMS tmp_params; - - DBGINFO(("%s set_params\n", info->device_name)); - if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS))) - return -EFAULT; - - spin_lock_irqsave(&info->lock, flags); - memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS)); - spin_unlock_irqrestore(&info->lock, flags); - - change_params(info); - - return 0; -} - -static int get_txidle(struct slgt_info *info, int __user *idle_mode) -{ - DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode)); - if (put_user(info->idle_mode, idle_mode)) - return -EFAULT; - return 0; -} - -static int set_txidle(struct slgt_info *info, int idle_mode) -{ - unsigned long flags; - DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode)); - spin_lock_irqsave(&info->lock,flags); - info->idle_mode = idle_mode; - tx_set_idle(info); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int tx_enable(struct slgt_info *info, int enable) -{ - unsigned long flags; - DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable)); - spin_lock_irqsave(&info->lock,flags); - if (enable) { - if (!info->tx_enabled) - tx_start(info); - } else { - if (info->tx_enabled) - tx_stop(info); - } - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -/* - * abort transmit HDLC frame - */ -static int tx_abort(struct slgt_info *info) -{ - unsigned long flags; - DBGINFO(("%s tx_abort\n", info->device_name)); - spin_lock_irqsave(&info->lock,flags); - tdma_reset(info); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int rx_enable(struct slgt_info *info, int enable) -{ - unsigned long flags; - DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable)); - spin_lock_irqsave(&info->lock,flags); - if (enable) { - if (!info->rx_enabled) - rx_start(info); - } else { - if (info->rx_enabled) - rx_stop(info); - } - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -/* - * wait for specified event to occur - */ -static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr) -{ - unsigned long flags; - int s; - int rc=0; - struct mgsl_icount cprev, cnow; - int events; - int mask; - struct _input_signal_events oldsigs, newsigs; - DECLARE_WAITQUEUE(wait, current); - - if (get_user(mask, mask_ptr)) - return -EFAULT; - - DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask)); - - spin_lock_irqsave(&info->lock,flags); - - /* return immediately if state matches requested events */ - get_signals(info); - s = info->signals; - - events = mask & - ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + - ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + - ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + - ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); - if (events) { - spin_unlock_irqrestore(&info->lock,flags); - goto exit; - } - - /* save current irq counts */ - cprev = info->icount; - oldsigs = info->input_signal_events; - - /* enable hunt and idle irqs if needed */ - if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) { - unsigned short val = rd_reg16(info, SCR); - if (!(val & IRQ_RXIDLE)) - wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE)); - } - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&info->event_wait_q, &wait); - - spin_unlock_irqrestore(&info->lock,flags); - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get current irq counts */ - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - newsigs = info->input_signal_events; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - /* if no change, wait aborted for some reason */ - if (newsigs.dsr_up == oldsigs.dsr_up && - newsigs.dsr_down == oldsigs.dsr_down && - newsigs.dcd_up == oldsigs.dcd_up && - newsigs.dcd_down == oldsigs.dcd_down && - newsigs.cts_up == oldsigs.cts_up && - newsigs.cts_down == oldsigs.cts_down && - newsigs.ri_up == oldsigs.ri_up && - newsigs.ri_down == oldsigs.ri_down && - cnow.exithunt == cprev.exithunt && - cnow.rxidle == cprev.rxidle) { - rc = -EIO; - break; - } - - events = mask & - ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + - (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + - (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + - (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + - (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + - (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + - (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + - (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + - (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + - (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); - if (events) - break; - - cprev = cnow; - oldsigs = newsigs; - } - - remove_wait_queue(&info->event_wait_q, &wait); - set_current_state(TASK_RUNNING); - - - if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { - spin_lock_irqsave(&info->lock,flags); - if (!waitqueue_active(&info->event_wait_q)) { - /* disable enable exit hunt mode/idle rcvd IRQs */ - wr_reg16(info, SCR, - (unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE)); - } - spin_unlock_irqrestore(&info->lock,flags); - } -exit: - if (rc == 0) - rc = put_user(events, mask_ptr); - return rc; -} - -static int get_interface(struct slgt_info *info, int __user *if_mode) -{ - DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode)); - if (put_user(info->if_mode, if_mode)) - return -EFAULT; - return 0; -} - -static int set_interface(struct slgt_info *info, int if_mode) -{ - unsigned long flags; - unsigned char val; - - DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode)); - spin_lock_irqsave(&info->lock,flags); - info->if_mode = if_mode; - - msc_set_vcr(info); - - /* TCR (tx control) 07 1=RTS driver control */ - val = rd_reg16(info, TCR); - if (info->if_mode & MGSL_INTERFACE_RTS_EN) - val |= BIT7; - else - val &= ~BIT7; - wr_reg16(info, TCR, val); - - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -static int modem_input_wait(struct slgt_info *info,int arg) -{ - unsigned long flags; - int rc; - struct mgsl_icount cprev, cnow; - DECLARE_WAITQUEUE(wait, current); - - /* save current irq counts */ - spin_lock_irqsave(&info->lock,flags); - cprev = info->icount; - add_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - for(;;) { - schedule(); - if (signal_pending(current)) { - rc = -ERESTARTSYS; - break; - } - - /* get new irq counts */ - spin_lock_irqsave(&info->lock,flags); - cnow = info->icount; - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irqrestore(&info->lock,flags); - - /* if no change, wait aborted for some reason */ - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - rc = -EIO; - break; - } - - /* check for change in caller specified modem input */ - if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || - (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || - (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || - (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { - rc = 0; - break; - } - - cprev = cnow; - } - remove_wait_queue(&info->status_event_wait_q, &wait); - set_current_state(TASK_RUNNING); - return rc; -} - -/* - * return state of serial control and status signals - */ -static int tiocmget(struct tty_struct *tty, struct file *file) -{ - struct slgt_info *info = tty->driver_data; - unsigned int result; - unsigned long flags; - - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) + - ((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) + - ((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) + - ((info->signals & SerialSignal_RI) ? TIOCM_RNG:0) + - ((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) + - ((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0); - - DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result)); - return result; -} - -/* - * set modem control signals (DTR/RTS) - * - * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit - * TIOCMSET = set/clear signal values - * value bit mask for command - */ -static int tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct slgt_info *info = tty->driver_data; - unsigned long flags; - - DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear)); - - if (set & TIOCM_RTS) - info->signals |= SerialSignal_RTS; - if (set & TIOCM_DTR) - info->signals |= SerialSignal_DTR; - if (clear & TIOCM_RTS) - info->signals &= ~SerialSignal_RTS; - if (clear & TIOCM_DTR) - info->signals &= ~SerialSignal_DTR; - - spin_lock_irqsave(&info->lock,flags); - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - return 0; -} - -/* - * block current process until the device is ready to open - */ -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct slgt_info *info) -{ - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0, extra_count = 0; - unsigned long flags; - - DBGINFO(("%s block_til_ready\n", tty->driver->name)); - - if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ - /* nonblock mode is set or port is not enabled */ - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - - /* Wait for carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - - retval = 0; - add_wait_queue(&info->open_wait, &wait); - - spin_lock_irqsave(&info->lock, flags); - if (!tty_hung_up_p(filp)) { - extra_count = 1; - info->count--; - } - spin_unlock_irqrestore(&info->lock, flags); - info->blocked_open++; - - while (1) { - if ((tty->termios->c_cflag & CBAUD)) { - spin_lock_irqsave(&info->lock,flags); - info->signals |= SerialSignal_RTS + SerialSignal_DTR; - set_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - } - - set_current_state(TASK_INTERRUPTIBLE); - - if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){ - retval = (info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS; - break; - } - - spin_lock_irqsave(&info->lock,flags); - get_signals(info); - spin_unlock_irqrestore(&info->lock,flags); - - if (!(info->flags & ASYNC_CLOSING) && - (do_clocal || (info->signals & SerialSignal_DCD)) ) { - break; - } - - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - - DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); - schedule(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); - - if (extra_count) - info->count++; - info->blocked_open--; - - if (!retval) - info->flags |= ASYNC_NORMAL_ACTIVE; - - DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); - return retval; -} - -static int alloc_tmp_rbuf(struct slgt_info *info) -{ - info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL); - if (info->tmp_rbuf == NULL) - return -ENOMEM; - return 0; -} - -static void free_tmp_rbuf(struct slgt_info *info) -{ - kfree(info->tmp_rbuf); - info->tmp_rbuf = NULL; -} - -/* - * allocate DMA descriptor lists. - */ -static int alloc_desc(struct slgt_info *info) -{ - unsigned int i; - unsigned int pbufs; - - /* allocate memory to hold descriptor lists */ - info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr); - if (info->bufs == NULL) - return -ENOMEM; - - memset(info->bufs, 0, DESC_LIST_SIZE); - - info->rbufs = (struct slgt_desc*)info->bufs; - info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count; - - pbufs = (unsigned int)info->bufs_dma_addr; - - /* - * Build circular lists of descriptors - */ - - for (i=0; i < info->rbuf_count; i++) { - /* physical address of this descriptor */ - info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc)); - - /* physical address of next descriptor */ - if (i == info->rbuf_count - 1) - info->rbufs[i].next = cpu_to_le32(pbufs); - else - info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc))); - set_desc_count(info->rbufs[i], DMABUFSIZE); - } - - for (i=0; i < info->tbuf_count; i++) { - /* physical address of this descriptor */ - info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc)); - - /* physical address of next descriptor */ - if (i == info->tbuf_count - 1) - info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc)); - else - info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc))); - } - - return 0; -} - -static void free_desc(struct slgt_info *info) -{ - if (info->bufs != NULL) { - pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr); - info->bufs = NULL; - info->rbufs = NULL; - info->tbufs = NULL; - } -} - -static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) -{ - int i; - for (i=0; i < count; i++) { - if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL) - return -ENOMEM; - bufs[i].pbuf = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr); - } - return 0; -} - -static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) -{ - int i; - for (i=0; i < count; i++) { - if (bufs[i].buf == NULL) - continue; - pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr); - bufs[i].buf = NULL; - } -} - -static int alloc_dma_bufs(struct slgt_info *info) -{ - info->rbuf_count = 32; - info->tbuf_count = 32; - - if (alloc_desc(info) < 0 || - alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 || - alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 || - alloc_tmp_rbuf(info) < 0) { - DBGERR(("%s DMA buffer alloc fail\n", info->device_name)); - return -ENOMEM; - } - reset_rbufs(info); - return 0; -} - -static void free_dma_bufs(struct slgt_info *info) -{ - if (info->bufs) { - free_bufs(info, info->rbufs, info->rbuf_count); - free_bufs(info, info->tbufs, info->tbuf_count); - free_desc(info); - } - free_tmp_rbuf(info); -} - -static int claim_resources(struct slgt_info *info) -{ - if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) { - DBGERR(("%s reg addr conflict, addr=%08X\n", - info->device_name, info->phys_reg_addr)); - info->init_error = DiagStatus_AddressConflict; - goto errout; - } - else - info->reg_addr_requested = 1; - - info->reg_addr = ioremap(info->phys_reg_addr, PAGE_SIZE); - if (!info->reg_addr) { - DBGERR(("%s cant map device registers, addr=%08X\n", - info->device_name, info->phys_reg_addr)); - info->init_error = DiagStatus_CantAssignPciResources; - goto errout; - } - info->reg_addr += info->reg_offset; - return 0; - -errout: - release_resources(info); - return -ENODEV; -} - -static void release_resources(struct slgt_info *info) -{ - if (info->irq_requested) { - free_irq(info->irq_level, info); - info->irq_requested = 0; - } - - if (info->reg_addr_requested) { - release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE); - info->reg_addr_requested = 0; - } - - if (info->reg_addr) { - iounmap(info->reg_addr - info->reg_offset); - info->reg_addr = NULL; - } -} - -/* Add the specified device instance data structure to the - * global linked list of devices and increment the device count. - */ -static void add_device(struct slgt_info *info) -{ - char *devstr; - - info->next_device = NULL; - info->line = slgt_device_count; - sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line); - - if (info->line < MAX_DEVICES) { - if (maxframe[info->line]) - info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; - } - - slgt_device_count++; - - if (!slgt_device_list) - slgt_device_list = info; - else { - struct slgt_info *current_dev = slgt_device_list; - while(current_dev->next_device) - current_dev = current_dev->next_device; - current_dev->next_device = info; - } - - if (info->max_frame_size < 4096) - info->max_frame_size = 4096; - else if (info->max_frame_size > 65535) - info->max_frame_size = 65535; - - switch(info->pdev->device) { - case SYNCLINK_GT_DEVICE_ID: - devstr = "GT"; - break; - case SYNCLINK_GT4_DEVICE_ID: - devstr = "GT4"; - break; - case SYNCLINK_AC_DEVICE_ID: - devstr = "AC"; - info->params.mode = MGSL_MODE_ASYNC; - break; - default: - devstr = "(unknown model)"; - } - printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n", - devstr, info->device_name, info->phys_reg_addr, - info->irq_level, info->max_frame_size); - -#ifdef CONFIG_HDLC - hdlcdev_init(info); -#endif -} - -/* - * allocate device instance structure, return NULL on failure - */ -static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) -{ - struct slgt_info *info; - - info = kmalloc(sizeof(struct slgt_info), GFP_KERNEL); - - if (!info) { - DBGERR(("%s device alloc failed adapter=%d port=%d\n", - driver_name, adapter_num, port_num)); - } else { - memset(info, 0, sizeof(struct slgt_info)); - info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); - info->max_frame_size = 4096; - info->raw_rx_size = DMABUFSIZE; - info->close_delay = 5*HZ/10; - info->closing_wait = 30*HZ; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->status_event_wait_q); - init_waitqueue_head(&info->event_wait_q); - spin_lock_init(&info->netlock); - memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); - info->idle_mode = HDLC_TXIDLE_FLAGS; - info->adapter_num = adapter_num; - info->port_num = port_num; - - init_timer(&info->tx_timer); - info->tx_timer.data = (unsigned long)info; - info->tx_timer.function = tx_timeout; - - init_timer(&info->rx_timer); - info->rx_timer.data = (unsigned long)info; - info->rx_timer.function = rx_timeout; - - /* Copy configuration info to device instance data */ - info->pdev = pdev; - info->irq_level = pdev->irq; - info->phys_reg_addr = pci_resource_start(pdev,0); - - /* veremap works on page boundaries - * map full page starting at the page boundary - */ - info->reg_offset = info->phys_reg_addr & (PAGE_SIZE-1); - info->phys_reg_addr &= ~(PAGE_SIZE-1); - - info->bus_type = MGSL_BUS_TYPE_PCI; - info->irq_flags = SA_SHIRQ; - - info->init_error = -1; /* assume error, set to 0 on successful init */ - } - - return info; -} - -static void device_init(int adapter_num, struct pci_dev *pdev) -{ - struct slgt_info *port_array[SLGT_MAX_PORTS]; - int i; - int port_count = 1; - - if (pdev->device == SYNCLINK_GT4_DEVICE_ID) - port_count = 4; - - /* allocate device instances for all ports */ - for (i=0; i < port_count; ++i) { - port_array[i] = alloc_dev(adapter_num, i, pdev); - if (port_array[i] == NULL) { - for (--i; i >= 0; --i) - kfree(port_array[i]); - return; - } - } - - /* give copy of port_array to all ports and add to device list */ - for (i=0; i < port_count; ++i) { - memcpy(port_array[i]->port_array, port_array, sizeof(port_array)); - add_device(port_array[i]); - port_array[i]->port_count = port_count; - spin_lock_init(&port_array[i]->lock); - } - - /* Allocate and claim adapter resources */ - if (!claim_resources(port_array[0])) { - - alloc_dma_bufs(port_array[0]); - - /* copy resource information from first port to others */ - for (i = 1; i < port_count; ++i) { - port_array[i]->lock = port_array[0]->lock; - port_array[i]->irq_level = port_array[0]->irq_level; - port_array[i]->reg_addr = port_array[0]->reg_addr; - alloc_dma_bufs(port_array[i]); - } - - if (request_irq(port_array[0]->irq_level, - slgt_interrupt, - port_array[0]->irq_flags, - port_array[0]->device_name, - port_array[0]) < 0) { - DBGERR(("%s request_irq failed IRQ=%d\n", - port_array[0]->device_name, - port_array[0]->irq_level)); - } else { - port_array[0]->irq_requested = 1; - adapter_test(port_array[0]); - for (i=1 ; i < port_count ; i++) - port_array[i]->init_error = port_array[0]->init_error; - } - } -} - -static int __devinit init_one(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - if (pci_enable_device(dev)) { - printk("error enabling pci device %p\n", dev); - return -EIO; - } - pci_set_master(dev); - device_init(slgt_device_count, dev); - return 0; -} - -static void __devexit remove_one(struct pci_dev *dev) -{ -} - -static struct tty_operations ops = { - .open = open, - .close = close, - .write = write, - .put_char = put_char, - .flush_chars = flush_chars, - .write_room = write_room, - .chars_in_buffer = chars_in_buffer, - .flush_buffer = flush_buffer, - .ioctl = ioctl, - .throttle = throttle, - .unthrottle = unthrottle, - .send_xchar = send_xchar, - .break_ctl = set_break, - .wait_until_sent = wait_until_sent, - .read_proc = read_proc, - .set_termios = set_termios, - .stop = tx_hold, - .start = tx_release, - .hangup = hangup, - .tiocmget = tiocmget, - .tiocmset = tiocmset, -}; - -static void slgt_cleanup(void) -{ - int rc; - struct slgt_info *info; - struct slgt_info *tmp; - - printk("unload %s %s\n", driver_name, driver_version); - - if (serial_driver) { - if ((rc = tty_unregister_driver(serial_driver))) - DBGERR(("tty_unregister_driver error=%d\n", rc)); - put_tty_driver(serial_driver); - } - - /* reset devices */ - info = slgt_device_list; - while(info) { - reset_port(info); - info = info->next_device; - } - - /* release devices */ - info = slgt_device_list; - while(info) { -#ifdef CONFIG_HDLC - hdlcdev_exit(info); -#endif - free_dma_bufs(info); - free_tmp_rbuf(info); - if (info->port_num == 0) - release_resources(info); - tmp = info; - info = info->next_device; - kfree(tmp); - } - - if (pci_registered) - pci_unregister_driver(&pci_driver); -} - -/* - * Driver initialization entry point. - */ -static int __init slgt_init(void) -{ - int rc; - - printk("%s %s\n", driver_name, driver_version); - - slgt_device_count = 0; - if ((rc = pci_register_driver(&pci_driver)) < 0) { - printk("%s pci_register_driver error=%d\n", driver_name, rc); - return rc; - } - pci_registered = 1; - - if (!slgt_device_list) { - printk("%s no devices found\n",driver_name); - return -ENODEV; - } - - serial_driver = alloc_tty_driver(MAX_DEVICES); - if (!serial_driver) { - rc = -ENOMEM; - goto error; - } - - /* Initialize the tty_driver structure */ - - serial_driver->owner = THIS_MODULE; - serial_driver->driver_name = tty_driver_name; - serial_driver->name = tty_dev_prefix; - serial_driver->major = ttymajor; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(serial_driver, &ops); - if ((rc = tty_register_driver(serial_driver)) < 0) { - DBGERR(("%s can't register serial driver\n", driver_name)); - put_tty_driver(serial_driver); - serial_driver = NULL; - goto error; - } - - printk("%s %s, tty major#%d\n", - driver_name, driver_version, - serial_driver->major); - - return 0; - -error: - slgt_cleanup(); - return rc; -} - -static void __exit slgt_exit(void) -{ - slgt_cleanup(); -} - -module_init(slgt_init); -module_exit(slgt_exit); - -/* - * register access routines - */ - -#define CALC_REGADDR() \ - unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ - if (addr >= 0x80) \ - reg_addr += (info->port_num) * 32; - -static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) -{ - CALC_REGADDR(); - return readb((void __iomem *)reg_addr); -} - -static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value) -{ - CALC_REGADDR(); - writeb(value, (void __iomem *)reg_addr); -} - -static __u16 rd_reg16(struct slgt_info *info, unsigned int addr) -{ - CALC_REGADDR(); - return readw((void __iomem *)reg_addr); -} - -static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value) -{ - CALC_REGADDR(); - writew(value, (void __iomem *)reg_addr); -} - -static __u32 rd_reg32(struct slgt_info *info, unsigned int addr) -{ - CALC_REGADDR(); - return readl((void __iomem *)reg_addr); -} - -static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value) -{ - CALC_REGADDR(); - writel(value, (void __iomem *)reg_addr); -} - -static void rdma_reset(struct slgt_info *info) -{ - unsigned int i; - - /* set reset bit */ - wr_reg32(info, RDCSR, BIT1); - - /* wait for enable bit cleared */ - for(i=0 ; i < 1000 ; i++) - if (!(rd_reg32(info, RDCSR) & BIT0)) - break; -} - -static void tdma_reset(struct slgt_info *info) -{ - unsigned int i; - - /* set reset bit */ - wr_reg32(info, TDCSR, BIT1); - - /* wait for enable bit cleared */ - for(i=0 ; i < 1000 ; i++) - if (!(rd_reg32(info, TDCSR) & BIT0)) - break; -} - -/* - * enable internal loopback - * TxCLK and RxCLK are generated from BRG - * and TxD is looped back to RxD internally. - */ -static void enable_loopback(struct slgt_info *info) -{ - /* SCR (serial control) BIT2=looopback enable */ - wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2)); - - if (info->params.mode != MGSL_MODE_ASYNC) { - /* CCR (clock control) - * 07..05 tx clock source (010 = BRG) - * 04..02 rx clock source (010 = BRG) - * 01 auxclk enable (0 = disable) - * 00 BRG enable (1 = enable) - * - * 0100 1001 - */ - wr_reg8(info, CCR, 0x49); - - /* set speed if available, otherwise use default */ - if (info->params.clock_speed) - set_rate(info, info->params.clock_speed); - else - set_rate(info, 3686400); - } -} - -/* - * set baud rate generator to specified rate - */ -static void set_rate(struct slgt_info *info, u32 rate) -{ - unsigned int div; - static unsigned int osc = 14745600; - - /* div = osc/rate - 1 - * - * Round div up if osc/rate is not integer to - * force to next slowest rate. - */ - - if (rate) { - div = osc/rate; - if (!(osc % rate) && div) - div--; - wr_reg16(info, BDR, (unsigned short)div); - } -} - -static void rx_stop(struct slgt_info *info) -{ - unsigned short val; - - /* disable and reset receiver */ - val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ - wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, RCR, val); /* clear reset bit */ - - slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE); - - /* clear pending rx interrupts */ - wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER); - - rdma_reset(info); - - info->rx_enabled = 0; - info->rx_restart = 0; -} - -static void rx_start(struct slgt_info *info) -{ - unsigned short val; - - slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA); - - /* clear pending rx overrun IRQ */ - wr_reg16(info, SSR, IRQ_RXOVER); - - /* reset and disable receiver */ - val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ - wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, RCR, val); /* clear reset bit */ - - rdma_reset(info); - reset_rbufs(info); - - /* set 1st descriptor address */ - wr_reg32(info, RDDAR, info->rbufs[0].pdesc); - - if (info->params.mode != MGSL_MODE_ASYNC) { - /* enable rx DMA and DMA interrupt */ - wr_reg32(info, RDCSR, (BIT2 + BIT0)); - } else { - /* enable saving of rx status, rx DMA and DMA interrupt */ - wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); - } - - slgt_irq_on(info, IRQ_RXOVER); - - /* enable receiver */ - wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1)); - - info->rx_restart = 0; - info->rx_enabled = 1; -} - -static void tx_start(struct slgt_info *info) -{ - if (!info->tx_enabled) { - wr_reg16(info, TCR, - (unsigned short)(rd_reg16(info, TCR) | BIT1)); - info->tx_enabled = TRUE; - } - - if (info->tx_count) { - info->drop_rts_on_tx_done = 0; - - if (info->params.mode != MGSL_MODE_ASYNC) { - if (info->params.flags & HDLC_FLAG_AUTO_RTS) { - get_signals(info); - if (!(info->signals & SerialSignal_RTS)) { - info->signals |= SerialSignal_RTS; - set_signals(info); - info->drop_rts_on_tx_done = 1; - } - } - - slgt_irq_off(info, IRQ_TXDATA); - slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); - /* clear tx idle and underrun status bits */ - wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); - - if (!(rd_reg32(info, TDCSR) & BIT0)) { - /* tx DMA stopped, restart tx DMA */ - tdma_reset(info); - /* set 1st descriptor address */ - wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); - if (info->params.mode == MGSL_MODE_RAW) - wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ - else - wr_reg32(info, TDCSR, BIT0); /* DMA enable */ - } - - if (info->params.mode != MGSL_MODE_RAW) { - info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); - add_timer(&info->tx_timer); - } - } else { - tdma_reset(info); - /* set 1st descriptor address */ - wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); - - slgt_irq_off(info, IRQ_TXDATA); - slgt_irq_on(info, IRQ_TXIDLE); - /* clear tx idle status bit */ - wr_reg16(info, SSR, IRQ_TXIDLE); - - /* enable tx DMA */ - wr_reg32(info, TDCSR, BIT0); - } - - info->tx_active = 1; - } -} - -static void tx_stop(struct slgt_info *info) -{ - unsigned short val; - - del_timer(&info->tx_timer); - - tdma_reset(info); - - /* reset and disable transmitter */ - val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */ - wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ - wr_reg16(info, TCR, val); /* clear reset */ - - slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); - - /* clear tx idle and underrun status bit */ - wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); - - reset_tbufs(info); - - info->tx_enabled = 0; - info->tx_active = 0; -} - -static void reset_port(struct slgt_info *info) -{ - if (!info->reg_addr) - return; - - tx_stop(info); - rx_stop(info); - - info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); - set_signals(info); - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); -} - -static void reset_adapter(struct slgt_info *info) -{ - int i; - for (i=0; i < info->port_count; ++i) { - if (info->port_array[i]) - reset_port(info->port_array[i]); - } -} - -static void async_mode(struct slgt_info *info) -{ - unsigned short val; - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); - tx_stop(info); - rx_stop(info); - - /* TCR (tx control) - * - * 15..13 mode, 010=async - * 12..10 encoding, 000=NRZ - * 09 parity enable - * 08 1=odd parity, 0=even parity - * 07 1=RTS driver control - * 06 1=break enable - * 05..04 character length - * 00=5 bits - * 01=6 bits - * 10=7 bits - * 11=8 bits - * 03 0=1 stop bit, 1=2 stop bits - * 02 reset - * 01 enable - * 00 auto-CTS enable - */ - val = 0x4000; - - if (info->if_mode & MGSL_INTERFACE_RTS_EN) - val |= BIT7; - - if (info->params.parity != ASYNC_PARITY_NONE) { - val |= BIT9; - if (info->params.parity == ASYNC_PARITY_ODD) - val |= BIT8; - } - - switch (info->params.data_bits) - { - case 6: val |= BIT4; break; - case 7: val |= BIT5; break; - case 8: val |= BIT5 + BIT4; break; - } - - if (info->params.stop_bits != 1) - val |= BIT3; - - if (info->params.flags & HDLC_FLAG_AUTO_CTS) - val |= BIT0; - - wr_reg16(info, TCR, val); - - /* RCR (rx control) - * - * 15..13 mode, 010=async - * 12..10 encoding, 000=NRZ - * 09 parity enable - * 08 1=odd parity, 0=even parity - * 07..06 reserved, must be 0 - * 05..04 character length - * 00=5 bits - * 01=6 bits - * 10=7 bits - * 11=8 bits - * 03 reserved, must be zero - * 02 reset - * 01 enable - * 00 auto-DCD enable - */ - val = 0x4000; - - if (info->params.parity != ASYNC_PARITY_NONE) { - val |= BIT9; - if (info->params.parity == ASYNC_PARITY_ODD) - val |= BIT8; - } - - switch (info->params.data_bits) - { - case 6: val |= BIT4; break; - case 7: val |= BIT5; break; - case 8: val |= BIT5 + BIT4; break; - } - - if (info->params.flags & HDLC_FLAG_AUTO_DCD) - val |= BIT0; - - wr_reg16(info, RCR, val); - - /* CCR (clock control) - * - * 07..05 011 = tx clock source is BRG/16 - * 04..02 010 = rx clock source is BRG - * 01 0 = auxclk disabled - * 00 1 = BRG enabled - * - * 0110 1001 - */ - wr_reg8(info, CCR, 0x69); - - msc_set_vcr(info); - - tx_set_idle(info); - - /* SCR (serial control) - * - * 15 1=tx req on FIFO half empty - * 14 1=rx req on FIFO half full - * 13 tx data IRQ enable - * 12 tx idle IRQ enable - * 11 rx break on IRQ enable - * 10 rx data IRQ enable - * 09 rx break off IRQ enable - * 08 overrun IRQ enable - * 07 DSR IRQ enable - * 06 CTS IRQ enable - * 05 DCD IRQ enable - * 04 RI IRQ enable - * 03 reserved, must be zero - * 02 1=txd->rxd internal loopback enable - * 01 reserved, must be zero - * 00 1=master IRQ enable - */ - val = BIT15 + BIT14 + BIT0; - wr_reg16(info, SCR, val); - - slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER); - - set_rate(info, info->params.data_rate * 16); - - if (info->params.loopback) - enable_loopback(info); -} - -static void hdlc_mode(struct slgt_info *info) -{ - unsigned short val; - - slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); - tx_stop(info); - rx_stop(info); - - /* TCR (tx control) - * - * 15..13 mode, 000=HDLC 001=raw sync - * 12..10 encoding - * 09 CRC enable - * 08 CRC32 - * 07 1=RTS driver control - * 06 preamble enable - * 05..04 preamble length - * 03 share open/close flag - * 02 reset - * 01 enable - * 00 auto-CTS enable - */ - val = 0; - - if (info->params.mode == MGSL_MODE_RAW) - val |= BIT13; - if (info->if_mode & MGSL_INTERFACE_RTS_EN) - val |= BIT7; - - switch(info->params.encoding) - { - case HDLC_ENCODING_NRZB: val |= BIT10; break; - case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; - case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; - case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; - case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; - case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; - } - - switch (info->params.crc_type) - { - case HDLC_CRC_16_CCITT: val |= BIT9; break; - case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; - } - - if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) - val |= BIT6; - - switch (info->params.preamble_length) - { - case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break; - case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break; - case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break; - } - - if (info->params.flags & HDLC_FLAG_AUTO_CTS) - val |= BIT0; - - wr_reg16(info, TCR, val); - - /* TPR (transmit preamble) */ - - switch (info->params.preamble) - { - case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break; - case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break; - case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break; - case HDLC_PREAMBLE_PATTERN_10: val = 0x55; break; - case HDLC_PREAMBLE_PATTERN_01: val = 0xaa; break; - default: val = 0x7e; break; - } - wr_reg8(info, TPR, (unsigned char)val); - - /* RCR (rx control) - * - * 15..13 mode, 000=HDLC 001=raw sync - * 12..10 encoding - * 09 CRC enable - * 08 CRC32 - * 07..03 reserved, must be 0 - * 02 reset - * 01 enable - * 00 auto-DCD enable - */ - val = 0; - - if (info->params.mode == MGSL_MODE_RAW) - val |= BIT13; - - switch(info->params.encoding) - { - case HDLC_ENCODING_NRZB: val |= BIT10; break; - case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; - case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; - case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; - case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; - case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; - } - - switch (info->params.crc_type) - { - case HDLC_CRC_16_CCITT: val |= BIT9; break; - case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; - } - - if (info->params.flags & HDLC_FLAG_AUTO_DCD) - val |= BIT0; - - wr_reg16(info, RCR, val); - - /* CCR (clock control) - * - * 07..05 tx clock source - * 04..02 rx clock source - * 01 auxclk enable - * 00 BRG enable - */ - val = 0; - - if (info->params.flags & HDLC_FLAG_TXC_BRG) - { - // when RxC source is DPLL, BRG generates 16X DPLL - // reference clock, so take TxC from BRG/16 to get - // transmit clock at actual data rate - if (info->params.flags & HDLC_FLAG_RXC_DPLL) - val |= BIT6 + BIT5; /* 011, txclk = BRG/16 */ - else - val |= BIT6; /* 010, txclk = BRG */ - } - else if (info->params.flags & HDLC_FLAG_TXC_DPLL) - val |= BIT7; /* 100, txclk = DPLL Input */ - else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN) - val |= BIT5; /* 001, txclk = RXC Input */ - - if (info->params.flags & HDLC_FLAG_RXC_BRG) - val |= BIT3; /* 010, rxclk = BRG */ - else if (info->params.flags & HDLC_FLAG_RXC_DPLL) - val |= BIT4; /* 100, rxclk = DPLL */ - else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN) - val |= BIT2; /* 001, rxclk = TXC Input */ - - if (info->params.clock_speed) - val |= BIT1 + BIT0; - - wr_reg8(info, CCR, (unsigned char)val); - - if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL)) - { - // program DPLL mode - switch(info->params.encoding) - { - case HDLC_ENCODING_BIPHASE_MARK: - case HDLC_ENCODING_BIPHASE_SPACE: - val = BIT7; break; - case HDLC_ENCODING_BIPHASE_LEVEL: - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: - val = BIT7 + BIT6; break; - default: val = BIT6; // NRZ encodings - } - wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val)); - - // DPLL requires a 16X reference clock from BRG - set_rate(info, info->params.clock_speed * 16); - } - else - set_rate(info, info->params.clock_speed); - - tx_set_idle(info); - - msc_set_vcr(info); - - /* SCR (serial control) - * - * 15 1=tx req on FIFO half empty - * 14 1=rx req on FIFO half full - * 13 tx data IRQ enable - * 12 tx idle IRQ enable - * 11 underrun IRQ enable - * 10 rx data IRQ enable - * 09 rx idle IRQ enable - * 08 overrun IRQ enable - * 07 DSR IRQ enable - * 06 CTS IRQ enable - * 05 DCD IRQ enable - * 04 RI IRQ enable - * 03 reserved, must be zero - * 02 1=txd->rxd internal loopback enable - * 01 reserved, must be zero - * 00 1=master IRQ enable - */ - wr_reg16(info, SCR, BIT15 + BIT14 + BIT0); - - if (info->params.loopback) - enable_loopback(info); -} - -/* - * set transmit idle mode - */ -static void tx_set_idle(struct slgt_info *info) -{ - unsigned char val = 0xff; - - switch(info->idle_mode) - { - case HDLC_TXIDLE_FLAGS: val = 0x7e; break; - case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break; - case HDLC_TXIDLE_ZEROS: val = 0x00; break; - case HDLC_TXIDLE_ONES: val = 0xff; break; - case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; - case HDLC_TXIDLE_SPACE: val = 0x00; break; - case HDLC_TXIDLE_MARK: val = 0xff; break; - } - - wr_reg8(info, TIR, val); -} - -/* - * get state of V24 status (input) signals - */ -static void get_signals(struct slgt_info *info) -{ - unsigned short status = rd_reg16(info, SSR); - - /* clear all serial signals except DTR and RTS */ - info->signals &= SerialSignal_DTR + SerialSignal_RTS; - - if (status & BIT3) - info->signals |= SerialSignal_DSR; - if (status & BIT2) - info->signals |= SerialSignal_CTS; - if (status & BIT1) - info->signals |= SerialSignal_DCD; - if (status & BIT0) - info->signals |= SerialSignal_RI; -} - -/* - * set V.24 Control Register based on current configuration - */ -static void msc_set_vcr(struct slgt_info *info) -{ - unsigned char val = 0; - - /* VCR (V.24 control) - * - * 07..04 serial IF select - * 03 DTR - * 02 RTS - * 01 LL - * 00 RL - */ - - switch(info->if_mode & MGSL_INTERFACE_MASK) - { - case MGSL_INTERFACE_RS232: - val |= BIT5; /* 0010 */ - break; - case MGSL_INTERFACE_V35: - val |= BIT7 + BIT6 + BIT5; /* 1110 */ - break; - case MGSL_INTERFACE_RS422: - val |= BIT6; /* 0100 */ - break; - } - - if (info->signals & SerialSignal_DTR) - val |= BIT3; - if (info->signals & SerialSignal_RTS) - val |= BIT2; - if (info->if_mode & MGSL_INTERFACE_LL) - val |= BIT1; - if (info->if_mode & MGSL_INTERFACE_RL) - val |= BIT0; - wr_reg8(info, VCR, val); -} - -/* - * set state of V24 control (output) signals - */ -static void set_signals(struct slgt_info *info) -{ - unsigned char val = rd_reg8(info, VCR); - if (info->signals & SerialSignal_DTR) - val |= BIT3; - else - val &= ~BIT3; - if (info->signals & SerialSignal_RTS) - val |= BIT2; - else - val &= ~BIT2; - wr_reg8(info, VCR, val); -} - -/* - * free range of receive DMA buffers (i to last) - */ -static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last) -{ - int done = 0; - - while(!done) { - /* reset current buffer for reuse */ - info->rbufs[i].status = 0; - if (info->params.mode == MGSL_MODE_RAW) - set_desc_count(info->rbufs[i], info->raw_rx_size); - else - set_desc_count(info->rbufs[i], DMABUFSIZE); - - if (i == last) - done = 1; - if (++i == info->rbuf_count) - i = 0; - } - info->rbuf_current = i; -} - -/* - * mark all receive DMA buffers as free - */ -static void reset_rbufs(struct slgt_info *info) -{ - free_rbufs(info, 0, info->rbuf_count - 1); -} - -/* - * pass receive HDLC frame to upper layer - * - * return 1 if frame available, otherwise 0 - */ -static int rx_get_frame(struct slgt_info *info) -{ - unsigned int start, end; - unsigned short status; - unsigned int framesize = 0; - int rc = 0; - unsigned long flags; - struct tty_struct *tty = info->tty; - unsigned char addr_field = 0xff; - -check_again: - - framesize = 0; - addr_field = 0xff; - start = end = info->rbuf_current; - - for (;;) { - if (!desc_complete(info->rbufs[end])) - goto cleanup; - - if (framesize == 0 && info->params.addr_filter != 0xff) - addr_field = info->rbufs[end].buf[0]; - - framesize += desc_count(info->rbufs[end]); - - if (desc_eof(info->rbufs[end])) - break; - - if (++end == info->rbuf_count) - end = 0; - - if (end == info->rbuf_current) { - if (info->rx_enabled){ - spin_lock_irqsave(&info->lock,flags); - rx_start(info); - spin_unlock_irqrestore(&info->lock,flags); - } - goto cleanup; - } - } - - /* status - * - * 15 buffer complete - * 14..06 reserved - * 05..04 residue - * 02 eof (end of frame) - * 01 CRC error - * 00 abort - */ - status = desc_status(info->rbufs[end]); - - /* ignore CRC bit if not using CRC (bit is undefined) */ - if (info->params.crc_type == HDLC_CRC_NONE) - status &= ~BIT1; - - if (framesize == 0 || - (addr_field != 0xff && addr_field != info->params.addr_filter)) { - free_rbufs(info, start, end); - goto check_again; - } - - if (framesize < 2 || status & (BIT1+BIT0)) { - if (framesize < 2 || (status & BIT0)) - info->icount.rxshort++; - else - info->icount.rxcrc++; - framesize = 0; - -#ifdef CONFIG_HDLC - { - struct net_device_stats *stats = hdlc_stats(info->netdev); - stats->rx_errors++; - stats->rx_frame_errors++; - } -#endif - } else { - /* adjust frame size for CRC, if any */ - if (info->params.crc_type == HDLC_CRC_16_CCITT) - framesize -= 2; - else if (info->params.crc_type == HDLC_CRC_32_CCITT) - framesize -= 4; - } - - DBGBH(("%s rx frame status=%04X size=%d\n", - info->device_name, status, framesize)); - DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); - - if (framesize) { - if (framesize > info->max_frame_size) - info->icount.rxlong++; - else { - /* copy dma buffer(s) to contiguous temp buffer */ - int copy_count = framesize; - int i = start; - unsigned char *p = info->tmp_rbuf; - info->tmp_rbuf_count = framesize; - - info->icount.rxok++; - - while(copy_count) { - int partial_count = min(copy_count, DMABUFSIZE); - memcpy(p, info->rbufs[i].buf, partial_count); - p += partial_count; - copy_count -= partial_count; - if (++i == info->rbuf_count) - i = 0; - } - -#ifdef CONFIG_HDLC - if (info->netcount) - hdlcdev_rx(info,info->tmp_rbuf, framesize); - else -#endif - ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize); - } - } - free_rbufs(info, start, end); - rc = 1; - -cleanup: - return rc; -} - -/* - * pass receive buffer (RAW synchronous mode) to tty layer - * return 1 if buffer available, otherwise 0 - */ -static int rx_get_buf(struct slgt_info *info) -{ - unsigned int i = info->rbuf_current; - - if (!desc_complete(info->rbufs[i])) - return 0; - DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx"); - DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i]))); - ldisc_receive_buf(info->tty, info->rbufs[i].buf, - info->flag_buf, desc_count(info->rbufs[i])); - free_rbufs(info, i, i); - return 1; -} - -static void reset_tbufs(struct slgt_info *info) -{ - unsigned int i; - info->tbuf_current = 0; - for (i=0 ; i < info->tbuf_count ; i++) { - info->tbufs[i].status = 0; - info->tbufs[i].count = 0; - } -} - -/* - * return number of free transmit DMA buffers - */ -static unsigned int free_tbuf_count(struct slgt_info *info) -{ - unsigned int count = 0; - unsigned int i = info->tbuf_current; - - do - { - if (desc_count(info->tbufs[i])) - break; /* buffer in use */ - ++count; - if (++i == info->tbuf_count) - i=0; - } while (i != info->tbuf_current); - - /* last buffer with zero count may be in use, assume it is */ - if (count) - --count; - - return count; -} - -/* - * load transmit DMA buffer(s) with data - */ -static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) -{ - unsigned short count; - unsigned int i; - struct slgt_desc *d; - - if (size == 0) - return; - - DBGDATA(info, buf, size, "tx"); - - info->tbuf_start = i = info->tbuf_current; - - while (size) { - d = &info->tbufs[i]; - if (++i == info->tbuf_count) - i = 0; - - count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); - memcpy(d->buf, buf, count); - - size -= count; - buf += count; - - if (!size && info->params.mode != MGSL_MODE_RAW) - set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */ - else - set_desc_eof(*d, 0); - - set_desc_count(*d, count); - } - - info->tbuf_current = i; -} - -static int register_test(struct slgt_info *info) -{ - static unsigned short patterns[] = - {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696}; - static unsigned int count = sizeof(patterns)/sizeof(patterns[0]); - unsigned int i; - int rc = 0; - - for (i=0 ; i < count ; i++) { - wr_reg16(info, TIR, patterns[i]); - wr_reg16(info, BDR, patterns[(i+1)%count]); - if ((rd_reg16(info, TIR) != patterns[i]) || - (rd_reg16(info, BDR) != patterns[(i+1)%count])) { - rc = -ENODEV; - break; - } - } - - info->init_error = rc ? 0 : DiagStatus_AddressFailure; - return rc; -} - -static int irq_test(struct slgt_info *info) -{ - unsigned long timeout; - unsigned long flags; - struct tty_struct *oldtty = info->tty; - u32 speed = info->params.data_rate; - - info->params.data_rate = 921600; - info->tty = NULL; - - spin_lock_irqsave(&info->lock, flags); - async_mode(info); - slgt_irq_on(info, IRQ_TXIDLE); - - /* enable transmitter */ - wr_reg16(info, TCR, - (unsigned short)(rd_reg16(info, TCR) | BIT1)); - - /* write one byte and wait for tx idle */ - wr_reg16(info, TDR, 0); - - /* assume failure */ - info->init_error = DiagStatus_IrqFailure; - info->irq_occurred = FALSE; - - spin_unlock_irqrestore(&info->lock, flags); - - timeout=100; - while(timeout-- && !info->irq_occurred) - msleep_interruptible(10); - - spin_lock_irqsave(&info->lock,flags); - reset_port(info); - spin_unlock_irqrestore(&info->lock,flags); - - info->params.data_rate = speed; - info->tty = oldtty; - - info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure; - return info->irq_occurred ? 0 : -ENODEV; -} - -static int loopback_test_rx(struct slgt_info *info) -{ - unsigned char *src, *dest; - int count; - - if (desc_complete(info->rbufs[0])) { - count = desc_count(info->rbufs[0]); - src = info->rbufs[0].buf; - dest = info->tmp_rbuf; - - for( ; count ; count-=2, src+=2) { - /* src=data byte (src+1)=status byte */ - if (!(*(src+1) & (BIT9 + BIT8))) { - *dest = *src; - dest++; - info->tmp_rbuf_count++; - } - } - DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx"); - return 1; - } - return 0; -} - -static int loopback_test(struct slgt_info *info) -{ -#define TESTFRAMESIZE 20 - - unsigned long timeout; - u16 count = TESTFRAMESIZE; - unsigned char buf[TESTFRAMESIZE]; - int rc = -ENODEV; - unsigned long flags; - - struct tty_struct *oldtty = info->tty; - MGSL_PARAMS params; - - memcpy(¶ms, &info->params, sizeof(params)); - - info->params.mode = MGSL_MODE_ASYNC; - info->params.data_rate = 921600; - info->params.loopback = 1; - info->tty = NULL; - - /* build and send transmit frame */ - for (count = 0; count < TESTFRAMESIZE; ++count) - buf[count] = (unsigned char)count; - - info->tmp_rbuf_count = 0; - memset(info->tmp_rbuf, 0, TESTFRAMESIZE); - - /* program hardware for HDLC and enabled receiver */ - spin_lock_irqsave(&info->lock,flags); - async_mode(info); - rx_start(info); - info->tx_count = count; - tx_load(info, buf, count); - tx_start(info); - spin_unlock_irqrestore(&info->lock, flags); - - /* wait for receive complete */ - for (timeout = 100; timeout; --timeout) { - msleep_interruptible(10); - if (loopback_test_rx(info)) { - rc = 0; - break; - } - } - - /* verify received frame length and contents */ - if (!rc && (info->tmp_rbuf_count != count || - memcmp(buf, info->tmp_rbuf, count))) { - rc = -ENODEV; - } - - spin_lock_irqsave(&info->lock,flags); - reset_adapter(info); - spin_unlock_irqrestore(&info->lock,flags); - - memcpy(&info->params, ¶ms, sizeof(info->params)); - info->tty = oldtty; - - info->init_error = rc ? DiagStatus_DmaFailure : 0; - return rc; -} - -static int adapter_test(struct slgt_info *info) -{ - DBGINFO(("testing %s\n", info->device_name)); - if ((info->init_error = register_test(info)) < 0) { - printk("register test failure %s addr=%08X\n", - info->device_name, info->phys_reg_addr); - } else if ((info->init_error = irq_test(info)) < 0) { - printk("IRQ test failure %s IRQ=%d\n", - info->device_name, info->irq_level); - } else if ((info->init_error = loopback_test(info)) < 0) { - printk("loopback test failure %s\n", info->device_name); - } - return info->init_error; -} - -/* - * transmit timeout handler - */ -static void tx_timeout(unsigned long context) -{ - struct slgt_info *info = (struct slgt_info*)context; - unsigned long flags; - - DBGINFO(("%s tx_timeout\n", info->device_name)); - if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) { - info->icount.txtimeout++; - } - spin_lock_irqsave(&info->lock,flags); - info->tx_active = 0; - info->tx_count = 0; - spin_unlock_irqrestore(&info->lock,flags); - -#ifdef CONFIG_HDLC - if (info->netcount) - hdlcdev_tx_done(info); - else -#endif - bh_transmit(info); -} - -/* - * receive buffer polling timer - */ -static void rx_timeout(unsigned long context) -{ - struct slgt_info *info = (struct slgt_info*)context; - unsigned long flags; - - DBGINFO(("%s rx_timeout\n", info->device_name)); - spin_lock_irqsave(&info->lock, flags); - info->pending_bh |= BH_RECEIVE; - spin_unlock_irqrestore(&info->lock, flags); - bh_handler(info); -} - diff --git a/trunk/drivers/char/tpm/Makefile b/trunk/drivers/char/tpm/Makefile index ba4582d160fd..2392e404e8d1 100644 --- a/trunk/drivers/char/tpm/Makefile +++ b/trunk/drivers/char/tpm/Makefile @@ -2,9 +2,6 @@ # Makefile for the kernel tpm device drivers. # obj-$(CONFIG_TCG_TPM) += tpm.o -ifdef CONFIG_ACPI - obj-$(CONFIG_TCG_TPM) += tpm_bios.o -endif obj-$(CONFIG_TCG_NSC) += tpm_nsc.o obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o diff --git a/trunk/drivers/char/tpm/tpm.c b/trunk/drivers/char/tpm/tpm.c index 5a3870477ef1..a9be0e8eaea5 100644 --- a/trunk/drivers/char/tpm/tpm.c +++ b/trunk/drivers/char/tpm/tpm.c @@ -466,7 +466,6 @@ void tpm_remove_hardware(struct device *dev) kfree(chip->vendor->miscdev.name); sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); - tpm_bios_log_teardown(chip->bios_dir); dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); @@ -594,8 +593,6 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) sysfs_create_group(&dev->kobj, chip->vendor->attr_group); - chip->bios_dir = tpm_bios_log_setup(devname); - return 0; } EXPORT_SYMBOL_GPL(tpm_register_hardware); diff --git a/trunk/drivers/char/tpm/tpm.h b/trunk/drivers/char/tpm/tpm.h index fd3a4beaa53d..159882ca69dd 100644 --- a/trunk/drivers/char/tpm/tpm.h +++ b/trunk/drivers/char/tpm/tpm.h @@ -82,8 +82,6 @@ struct tpm_chip { struct tpm_vendor_specific *vendor; - struct dentry **bios_dir; - struct list_head list; }; @@ -109,16 +107,3 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); extern void tpm_remove_hardware(struct device *); extern int tpm_pm_suspend(struct device *, pm_message_t); extern int tpm_pm_resume(struct device *); - -#ifdef CONFIG_ACPI -extern struct dentry ** tpm_bios_log_setup(char *); -extern void tpm_bios_log_teardown(struct dentry **); -#else -static inline struct dentry* tpm_bios_log_setup(char *name) -{ - return NULL; -} -static inline void tpm_bios_log_teardown(struct dentry **dir) -{ -} -#endif diff --git a/trunk/drivers/char/tpm/tpm_bios.c b/trunk/drivers/char/tpm/tpm_bios.c deleted file mode 100644 index aedf7a8e6da7..000000000000 --- a/trunk/drivers/char/tpm/tpm_bios.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright (C) 2005 IBM Corporation - * - * Authors: - * Seiji Munetoh - * Stefan Berger - * Reiner Sailer - * Kylene Hall - * - * Access to the eventlog extended by the TCG BIOS of PC platform - * - * 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 -#include -#include -#include -#include -#include -#include -#include "tpm.h" - -#define TCG_EVENT_NAME_LEN_MAX 255 -#define MAX_TEXT_EVENT 1000 /* Max event string length */ -#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ - -struct tpm_bios_log { - void *bios_event_log; - void *bios_event_log_end; -}; - -struct acpi_tcpa { - struct acpi_table_header hdr; - u16 reserved; - u32 log_max_len __attribute__ ((packed)); - u32 log_start_addr __attribute__ ((packed)); -}; - -struct tcpa_event { - u32 pcr_index; - u32 event_type; - u8 pcr_value[20]; /* SHA1 */ - u32 event_size; - u8 event_data[0]; -}; - -enum tcpa_event_types { - PREBOOT = 0, - POST_CODE, - UNUSED, - NO_ACTION, - SEPARATOR, - ACTION, - EVENT_TAG, - SCRTM_CONTENTS, - SCRTM_VERSION, - CPU_MICROCODE, - PLATFORM_CONFIG_FLAGS, - TABLE_OF_DEVICES, - COMPACT_HASH, - IPL, - IPL_PARTITION_DATA, - NONHOST_CODE, - NONHOST_CONFIG, - NONHOST_INFO, -}; - -static const char* tcpa_event_type_strings[] = { - "PREBOOT", - "POST CODE", - "", - "NO ACTION", - "SEPARATOR", - "ACTION", - "EVENT TAG", - "S-CRTM Contents", - "S-CRTM Version", - "CPU Microcode", - "Platform Config Flags", - "Table of Devices", - "Compact Hash", - "IPL", - "IPL Partition Data", - "Non-Host Code", - "Non-Host Config", - "Non-Host Info" -}; - -enum tcpa_pc_event_ids { - SMBIOS = 1, - BIS_CERT, - POST_BIOS_ROM, - ESCD, - CMOS, - NVRAM, - OPTION_ROM_EXEC, - OPTION_ROM_CONFIG, - OPTION_ROM_MICROCODE, - S_CRTM_VERSION, - S_CRTM_CONTENTS, - POST_CONTENTS, -}; - -static const char* tcpa_pc_event_id_strings[] = { - "" - "SMBIOS", - "BIS Certificate", - "POST BIOS ", - "ESCD ", - "CMOS", - "NVRAM", - "Option ROM", - "Option ROM config", - "Option ROM microcode", - "S-CRTM Version", - "S-CRTM Contents", - "S-CRTM POST Contents", -}; - -/* returns pointer to start of pos. entry of tcg log */ -static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) -{ - loff_t i; - struct tpm_bios_log *log = m->private; - void *addr = log->bios_event_log; - void *limit = log->bios_event_log_end; - struct tcpa_event *event; - - /* read over *pos measurements */ - for (i = 0; i < *pos; i++) { - event = addr; - - if ((addr + sizeof(struct tcpa_event)) < limit) { - if (event->event_type == 0 && event->event_size == 0) - return NULL; - addr += sizeof(struct tcpa_event) + event->event_size; - } - } - - /* now check if current entry is valid */ - if ((addr + sizeof(struct tcpa_event)) >= limit) - return NULL; - - event = addr; - - if ((event->event_type == 0 && event->event_size == 0) || - ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit)) - return NULL; - - return addr; -} - -static void *tpm_bios_measurements_next(struct seq_file *m, void *v, - loff_t *pos) -{ - struct tcpa_event *event = v; - struct tpm_bios_log *log = m->private; - void *limit = log->bios_event_log_end; - - v += sizeof(struct tcpa_event) + event->event_size; - - /* now check if current entry is valid */ - if ((v + sizeof(struct tcpa_event)) >= limit) - return NULL; - - event = v; - - if (event->event_type == 0 && event->event_size == 0) - return NULL; - - if ((event->event_type == 0 && event->event_size == 0) || - ((v + sizeof(struct tcpa_event) + event->event_size) >= limit)) - return NULL; - - (*pos)++; - return v; -} - -static void tpm_bios_measurements_stop(struct seq_file *m, void *v) -{ -} - -static int get_event_name(char *dest, struct tcpa_event *event, - unsigned char * event_entry) -{ - const char *name = ""; - char data[40] = ""; - int i, n_len = 0, d_len = 0; - u32 event_id, event_data_size; - - switch(event->event_type) { - case PREBOOT: - case POST_CODE: - case UNUSED: - case NO_ACTION: - case SCRTM_CONTENTS: - case SCRTM_VERSION: - case CPU_MICROCODE: - case PLATFORM_CONFIG_FLAGS: - case TABLE_OF_DEVICES: - case COMPACT_HASH: - case IPL: - case IPL_PARTITION_DATA: - case NONHOST_CODE: - case NONHOST_CONFIG: - case NONHOST_INFO: - name = tcpa_event_type_strings[event->event_type]; - n_len = strlen(name); - break; - case SEPARATOR: - case ACTION: - if (MAX_TEXT_EVENT > event->event_size) { - name = event_entry; - n_len = event->event_size; - } - break; - case EVENT_TAG: - event_id = be32_to_cpu(event_entry); - event_data_size = be32_to_cpu(&event_entry[4]); - - /* ToDo Row data -> Base64 */ - - switch (event_id) { - case SMBIOS: - case BIS_CERT: - case CMOS: - case NVRAM: - case OPTION_ROM_EXEC: - case OPTION_ROM_CONFIG: - case OPTION_ROM_MICROCODE: - case S_CRTM_VERSION: - case S_CRTM_CONTENTS: - case POST_CONTENTS: - name = tcpa_pc_event_id_strings[event_id]; - n_len = strlen(name); - break; - case POST_BIOS_ROM: - case ESCD: - name = tcpa_pc_event_id_strings[event_id]; - n_len = strlen(name); - for (i = 0; i < 20; i++) - d_len += sprintf(data, "%02x", - event_entry[8 + i]); - break; - default: - break; - } - default: - break; - } - - return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]", - n_len, name, d_len, data); - -} - -static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) -{ - - char *eventname; - char data[4]; - u32 help; - int i, len; - struct tcpa_event *event = (struct tcpa_event *) v; - unsigned char *event_entry = - (unsigned char *) (v + sizeof(struct tcpa_event)); - - eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); - if (!eventname) { - printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", - __func__); - return -ENOMEM; - } - - /* 1st: PCR used is in little-endian format (4 bytes) */ - help = le32_to_cpu(event->pcr_index); - memcpy(data, &help, 4); - for (i = 0; i < 4; i++) - seq_putc(m, data[i]); - - /* 2nd: SHA1 (20 bytes) */ - for (i = 0; i < 20; i++) - seq_putc(m, event->pcr_value[i]); - - /* 3rd: event type identifier (4 bytes) */ - help = le32_to_cpu(event->event_type); - memcpy(data, &help, 4); - for (i = 0; i < 4; i++) - seq_putc(m, data[i]); - - len = 0; - - len += get_event_name(eventname, event, event_entry); - - /* 4th: filename <= 255 + \'0' delimiter */ - if (len > TCG_EVENT_NAME_LEN_MAX) - len = TCG_EVENT_NAME_LEN_MAX; - - for (i = 0; i < len; i++) - seq_putc(m, eventname[i]); - - /* 5th: delimiter */ - seq_putc(m, '\0'); - - return 0; -} - -static int tpm_bios_measurements_release(struct inode *inode, - struct file *file) -{ - struct seq_file *seq = file->private_data; - struct tpm_bios_log *log = seq->private; - - if (log) { - kfree(log->bios_event_log); - kfree(log); - } - - return seq_release(inode, file); -} - -static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) -{ - int len = 0; - int i; - char *eventname; - struct tcpa_event *event = v; - unsigned char *event_entry = - (unsigned char *) (v + sizeof(struct tcpa_event)); - - eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); - if (!eventname) { - printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", - __func__); - return -EFAULT; - } - - seq_printf(m, "%2d ", event->pcr_index); - - /* 2nd: SHA1 */ - for (i = 0; i < 20; i++) - seq_printf(m, "%02x", event->pcr_value[i]); - - /* 3rd: event type identifier */ - seq_printf(m, " %02x", event->event_type); - - len += get_event_name(eventname, event, event_entry); - - /* 4th: eventname <= max + \'0' delimiter */ - seq_printf(m, " %s\n", eventname); - - return 0; -} - -static struct seq_operations tpm_ascii_b_measurments_seqops = { - .start = tpm_bios_measurements_start, - .next = tpm_bios_measurements_next, - .stop = tpm_bios_measurements_stop, - .show = tpm_ascii_bios_measurements_show, -}; - -static struct seq_operations tpm_binary_b_measurments_seqops = { - .start = tpm_bios_measurements_start, - .next = tpm_bios_measurements_next, - .stop = tpm_bios_measurements_stop, - .show = tpm_binary_bios_measurements_show, -}; - -/* read binary bios log */ -static int read_log(struct tpm_bios_log *log) -{ - struct acpi_tcpa *buff; - acpi_status status; - void *virt; - - if (log->bios_event_log != NULL) { - printk(KERN_ERR - "%s: ERROR - Eventlog already initialized\n", - __func__); - return -EFAULT; - } - - /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ - status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1, - ACPI_LOGICAL_ADDRESSING, - (struct acpi_table_header **) - &buff); - - if (ACPI_FAILURE(status)) { - printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", - __func__); - return -EIO; - } - - if (buff->log_max_len == 0) { - printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); - return -EIO; - } - - /* malloc EventLog space */ - log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); - if (!log->bios_event_log) { - printk - ("%s: ERROR - Not enough Memory for BIOS measurements\n", - __func__); - return -ENOMEM; - } - - log->bios_event_log_end = log->bios_event_log + buff->log_max_len; - - acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt); - - memcpy(log->bios_event_log, virt, buff->log_max_len); - - acpi_os_unmap_memory(virt, buff->log_max_len); - return 0; -} - -static int tpm_ascii_bios_measurements_open(struct inode *inode, - struct file *file) -{ - int err; - struct tpm_bios_log *log; - struct seq_file *seq; - - log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL); - if (!log) - return -ENOMEM; - - if ((err = read_log(log))) - return err; - - /* now register seq file */ - err = seq_open(file, &tpm_ascii_b_measurments_seqops); - if (!err) { - seq = file->private_data; - seq->private = log; - } else { - kfree(log->bios_event_log); - kfree(log); - } - return err; -} - -struct file_operations tpm_ascii_bios_measurements_ops = { - .open = tpm_ascii_bios_measurements_open, - .read = seq_read, - .llseek = seq_lseek, - .release = tpm_bios_measurements_release, -}; - -static int tpm_binary_bios_measurements_open(struct inode *inode, - struct file *file) -{ - int err; - struct tpm_bios_log *log; - struct seq_file *seq; - - log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL); - if (!log) - return -ENOMEM; - - if ((err = read_log(log))) - return err; - - /* now register seq file */ - err = seq_open(file, &tpm_binary_b_measurments_seqops); - if (!err) { - seq = file->private_data; - seq->private = log; - } else { - kfree(log->bios_event_log); - kfree(log); - } - return err; -} - -struct file_operations tpm_binary_bios_measurements_ops = { - .open = tpm_binary_bios_measurements_open, - .read = seq_read, - .llseek = seq_lseek, - .release = tpm_bios_measurements_release, -}; - -struct dentry **tpm_bios_log_setup(char *name) -{ - struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file; - - tpm_dir = securityfs_create_dir(name, NULL); - if (!tpm_dir) - goto out; - - bin_file = - securityfs_create_file("binary_bios_measurements", - S_IRUSR | S_IRGRP, tpm_dir, NULL, - &tpm_binary_bios_measurements_ops); - if (!bin_file) - goto out_tpm; - - ascii_file = - securityfs_create_file("ascii_bios_measurements", - S_IRUSR | S_IRGRP, tpm_dir, NULL, - &tpm_ascii_bios_measurements_ops); - if (!ascii_file) - goto out_bin; - - ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL); - if (!ret) - goto out_ascii; - - ret[0] = ascii_file; - ret[1] = bin_file; - ret[2] = tpm_dir; - - return ret; - -out_ascii: - securityfs_remove(ascii_file); -out_bin: - securityfs_remove(bin_file); -out_tpm: - securityfs_remove(tpm_dir); -out: - return NULL; -} -EXPORT_SYMBOL_GPL(tpm_bios_log_setup); - -void tpm_bios_log_teardown(struct dentry **lst) -{ - int i; - - for (i = 0; i < 3; i++) - securityfs_remove(lst[i]); -} -EXPORT_SYMBOL_GPL(tpm_bios_log_teardown); diff --git a/trunk/drivers/char/vr41xx_giu.c b/trunk/drivers/char/vr41xx_giu.c index a5b18e086a94..9ac6d43437b3 100644 --- a/trunk/drivers/char/vr41xx_giu.c +++ b/trunk/drivers/char/vr41xx_giu.c @@ -718,7 +718,7 @@ static struct platform_driver giu_device_driver = { }, }; -static int __init vr41xx_giu_init(void) +static int __devinit vr41xx_giu_init(void) { int retval; @@ -733,7 +733,7 @@ static int __init vr41xx_giu_init(void) return retval; } -static void __exit vr41xx_giu_exit(void) +static void __devexit vr41xx_giu_exit(void) { platform_driver_unregister(&giu_device_driver); diff --git a/trunk/drivers/char/watchdog/wdt977.c b/trunk/drivers/char/watchdog/wdt977.c index 3843900e94c4..44d49dfacbb3 100644 --- a/trunk/drivers/char/watchdog/wdt977.c +++ b/trunk/drivers/char/watchdog/wdt977.c @@ -1,5 +1,5 @@ /* - * Wdt977 0.04: A Watchdog Device for Netwinder W83977AF chip + * Wdt977 0.03: A Watchdog Device for Netwinder W83977AF chip * * (c) Copyright 1998 Rebel.com (Woody Suwalski ) * @@ -18,8 +18,6 @@ * from minutes to seconds. * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in * nwwatchdog_init. - * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks - * remove limitiation to be used on Netwinders only */ #include @@ -30,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -40,18 +37,8 @@ #include #include -#define WATCHDOG_VERSION "0.04" -#define WATCHDOG_NAME "Wdt977" -#define PFX WATCHDOG_NAME ": " -#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" - -#define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */ -#define IO_DATA_PORT (IO_INDEX_PORT+1) - -#define UNLOCK_DATA 0x87 -#define LOCK_DATA 0xAA -#define DEVICE_REGISTER 0x07 - +#define PFX "Wdt977: " +#define WATCHDOG_MINOR 130 #define DEFAULT_TIMEOUT 60 /* default timeout in seconds */ @@ -60,7 +47,6 @@ static int timeoutM; /* timeout in minutes */ static unsigned long timer_alive; static int testmode; static char expect_close; -static spinlock_t spinlock; module_param(timeout, int, 0); MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); @@ -77,13 +63,9 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON static int wdt977_start(void) { - unsigned long flags; - - spin_lock_irqsave(&spinlock, flags); - /* unlock the SuperIO chip */ - outb_p(UNLOCK_DATA, IO_INDEX_PORT); - outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb(0x87,0x370); + outb(0x87,0x370); /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4 * F2 has the timeout in minutes @@ -91,29 +73,28 @@ static int wdt977_start(void) * at timeout, and to reset timer on kbd/mouse activity (not impl.) * F4 is used to just clear the TIMEOUT'ed state (bit 0) */ - outb_p(DEVICE_REGISTER, IO_INDEX_PORT); - outb_p(0x08, IO_DATA_PORT); - outb_p(0xF2, IO_INDEX_PORT); - outb_p(timeoutM, IO_DATA_PORT); - outb_p(0xF3, IO_INDEX_PORT); - outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for kbd/mouse/LED */ - outb_p(0xF4, IO_INDEX_PORT); - outb_p(0x00, IO_DATA_PORT); + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF2,0x370); + outb(timeoutM,0x371); + outb(0xF3,0x370); + outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */ + outb(0xF4,0x370); + outb(0x00,0x371); /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ /* in test mode watch the bit 1 on F4 to indicate "triggered" */ if (!testmode) { - outb_p(DEVICE_REGISTER, IO_INDEX_PORT); - outb_p(0x07, IO_DATA_PORT); - outb_p(0xE6, IO_INDEX_PORT); - outb_p(0x08, IO_DATA_PORT); + outb(0x07,0x370); + outb(0x07,0x371); + outb(0xE6,0x370); + outb(0x08,0x371); } /* lock the SuperIO chip */ - outb_p(LOCK_DATA, IO_INDEX_PORT); + outb(0xAA,0x370); - spin_unlock_irqrestore(&spinlock, flags); printk(KERN_INFO PFX "activated.\n"); return 0; @@ -125,39 +106,35 @@ static int wdt977_start(void) static int wdt977_stop(void) { - unsigned long flags; - spin_lock_irqsave(&spinlock, flags); - /* unlock the SuperIO chip */ - outb_p(UNLOCK_DATA, IO_INDEX_PORT); - outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb(0x87,0x370); + outb(0x87,0x370); /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4 * F3 is reset to its default state * F4 can clear the TIMEOUT'ed state (bit 0) - back to default * We can not use GP17 as a PowerLed, as we use its usage as a RedLed */ - outb_p(DEVICE_REGISTER, IO_INDEX_PORT); - outb_p(0x08, IO_DATA_PORT); - outb_p(0xF2, IO_INDEX_PORT); - outb_p(0xFF, IO_DATA_PORT); - outb_p(0xF3, IO_INDEX_PORT); - outb_p(0x00, IO_DATA_PORT); - outb_p(0xF4, IO_INDEX_PORT); - outb_p(0x00, IO_DATA_PORT); - outb_p(0xF2, IO_INDEX_PORT); - outb_p(0x00, IO_DATA_PORT); + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF2,0x370); + outb(0xFF,0x371); + outb(0xF3,0x370); + outb(0x00,0x371); + outb(0xF4,0x370); + outb(0x00,0x371); + outb(0xF2,0x370); + outb(0x00,0x371); /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ - outb_p(DEVICE_REGISTER, IO_INDEX_PORT); - outb_p(0x07, IO_DATA_PORT); - outb_p(0xE6, IO_INDEX_PORT); - outb_p(0x08, IO_DATA_PORT); + outb(0x07,0x370); + outb(0x07,0x371); + outb(0xE6,0x370); + outb(0x08,0x371); /* lock the SuperIO chip */ - outb_p(LOCK_DATA, IO_INDEX_PORT); + outb(0xAA,0x370); - spin_unlock_irqrestore(&spinlock, flags); printk(KERN_INFO PFX "shutdown.\n"); return 0; @@ -170,23 +147,19 @@ static int wdt977_stop(void) static int wdt977_keepalive(void) { - unsigned long flags; - spin_lock_irqsave(&spinlock, flags); - /* unlock the SuperIO chip */ - outb_p(UNLOCK_DATA, IO_INDEX_PORT); - outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb(0x87,0x370); + outb(0x87,0x370); /* select device Aux2 (device=8) and kicks watchdog reg F2 */ /* F2 has the timeout in minutes */ - outb_p(DEVICE_REGISTER, IO_INDEX_PORT); - outb_p(0x08, IO_DATA_PORT); - outb_p(0xF2, IO_INDEX_PORT); - outb_p(timeoutM, IO_DATA_PORT); + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF2,0x370); + outb(timeoutM,0x371); /* lock the SuperIO chip */ - outb_p(LOCK_DATA, IO_INDEX_PORT); - spin_unlock_irqrestore(&spinlock, flags); + outb(0xAA,0x370); return 0; } @@ -225,26 +198,22 @@ static int wdt977_set_timeout(int t) static int wdt977_get_status(int *status) { int new_status; - unsigned long flags; - spin_lock_irqsave(&spinlock, flags); + *status=0; /* unlock the SuperIO chip */ - outb_p(UNLOCK_DATA, IO_INDEX_PORT); - outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb(0x87,0x370); + outb(0x87,0x370); /* select device Aux2 (device=8) and read watchdog reg F4 */ - outb_p(DEVICE_REGISTER, IO_INDEX_PORT); - outb_p(0x08, IO_DATA_PORT); - outb_p(0xF4, IO_INDEX_PORT); - new_status = inb_p(IO_DATA_PORT); + outb(0x07,0x370); + outb(0x08,0x371); + outb(0xF4,0x370); + new_status = inb(0x371); /* lock the SuperIO chip */ - outb_p(LOCK_DATA, IO_INDEX_PORT); + outb(0xAA,0x370); - spin_unlock_irqrestore(&spinlock, flags); - - *status=0; if (new_status & 1) *status |= WDIOF_CARDRESET; @@ -280,8 +249,8 @@ static int wdt977_release(struct inode *inode, struct file *file) wdt977_stop(); clear_bit(0,&timer_alive); } else { - wdt977_keepalive(); printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + wdt977_keepalive(); } expect_close = 0; return 0; @@ -302,17 +271,14 @@ static int wdt977_release(struct inode *inode, struct file *file) static ssize_t wdt977_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - if (count) - { - if (!nowayout) - { + if (count) { + if (!nowayout) { size_t i; /* In case it was set long ago */ expect_close = 0; - for (i = 0; i != count; i++) - { + for (i = 0; i != count; i++) { char c; if (get_user(c, buf + i)) return -EFAULT; @@ -321,7 +287,6 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf, } } - /* someone wrote to us, we should restart timer */ wdt977_keepalive(); } return count; @@ -343,7 +308,7 @@ static struct watchdog_info ident = { WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 1, - .identity = WATCHDOG_NAME, + .identity = "Winbond 83977", }; static int wdt977_ioctl(struct inode *inode, struct file *file, @@ -440,81 +405,50 @@ static struct notifier_block wdt977_notifier = { .notifier_call = wdt977_notify_sys, }; -static int __init wd977_init(void) +static int __init nwwatchdog_init(void) { - int rc; - - //if (!machine_is_netwinder()) - // return -ENODEV; - - printk(KERN_INFO PFX DRIVER_VERSION); - - spin_lock_init(&spinlock); + int retval; + if (!machine_is_netwinder()) + return -ENODEV; /* Check that the timeout value is within it's range ; if not reset to the default */ - if (wdt977_set_timeout(timeout)) - { + if (wdt977_set_timeout(timeout)) { wdt977_set_timeout(DEFAULT_TIMEOUT); printk(KERN_INFO PFX "timeout value must be 60"); +MODULE_AUTHOR("Woody Suwalski "); MODULE_DESCRIPTION("W83977AF Watchdog driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/trunk/drivers/connector/cn_proc.c b/trunk/drivers/connector/cn_proc.c index 385e52930c02..969d2b4aaec0 100644 --- a/trunk/drivers/connector/cn_proc.c +++ b/trunk/drivers/connector/cn_proc.c @@ -34,14 +34,14 @@ static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; -/* proc_event_counts is used as the sequence number of the netlink message */ +/* proc_counts is used as the sequence number of the netlink message */ static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; static inline void get_seq(__u32 *ts, int *cpu) { *ts = get_cpu_var(proc_event_counts)++; *cpu = smp_processor_id(); - put_cpu_var(proc_event_counts); + put_cpu_var(proc_counts); } void proc_fork_connector(struct task_struct *task) diff --git a/trunk/drivers/i2c/chips/tps65010.c b/trunk/drivers/i2c/chips/tps65010.c index 1af3dfbb8086..e70b3db69edd 100644 --- a/trunk/drivers/i2c/chips/tps65010.c +++ b/trunk/drivers/i2c/chips/tps65010.c @@ -494,7 +494,6 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) { struct tps65010 *tps; int status; - unsigned long irqflags; if (the_tps) { dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME); @@ -521,14 +520,13 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) } #ifdef CONFIG_ARM - irqflags = SA_SAMPLE_RANDOM | SA_TRIGGER_LOW; if (machine_is_omap_h2()) { tps->model = TPS65010; omap_cfg_reg(W4_GPIO58); tps->irq = OMAP_GPIO_IRQ(58); omap_request_gpio(58); omap_set_gpio_direction(58, 1); - irqflags |= SA_TRIGGER_FALLING; + set_irq_type(tps->irq, IRQT_FALLING); } if (machine_is_omap_osk()) { tps->model = TPS65010; @@ -536,7 +534,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)); omap_request_gpio(OMAP_MPUIO(1)); omap_set_gpio_direction(OMAP_MPUIO(1), 1); - irqflags |= SA_TRIGGER_FALLING; + set_irq_type(tps->irq, IRQT_FALLING); } if (machine_is_omap_h3()) { tps->model = TPS65013; @@ -544,12 +542,13 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) // FIXME set up this board's IRQ ... } #else - irqflags = SA_SAMPLE_RANDOM; +#define set_irq_type(num,trigger) do{}while(0) #endif if (tps->irq > 0) { + set_irq_type(tps->irq, IRQT_LOW); status = request_irq(tps->irq, tps65010_irq, - irqflags, DRIVER_NAME, tps); + SA_SAMPLE_RANDOM, DRIVER_NAME, tps); if (status < 0) { dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n", tps->irq, status); diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index e4d55ad32d2f..d31117eb95aa 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -1332,6 +1332,8 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) if (cdrom_read_from_buffer(drive)) return ide_stopped; + blk_attempt_remerge(drive->queue, rq); + /* Clear the local sector buffer. */ info->nsectors_buffered = 0; @@ -1872,6 +1874,14 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) return ide_stopped; } + /* + * for dvd-ram and such media, it's a really big deal to get + * big writes all the time. so scour the queue and attempt to + * remerge requests, often the plugging will not have had time + * to do this properly + */ + blk_attempt_remerge(drive->queue, rq); + info->nsectors_buffered = 0; /* use dma, if possible. we don't need to check more, since we diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index cab362ea0336..4b441720b6ba 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -1130,17 +1130,6 @@ static int idedisk_release(struct inode *inode, struct file *filp) return 0; } -static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); - ide_drive_t *drive = idkp->drive; - - geo->heads = drive->bios_head; - geo->sectors = drive->bios_sect; - geo->cylinders = (u16)drive->bios_cyl; /* truncate */ - return 0; -} - static int idedisk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -1175,7 +1164,6 @@ static struct block_device_operations idedisk_ops = { .open = idedisk_open, .release = idedisk_release, .ioctl = idedisk_ioctl, - .getgeo = idedisk_getgeo, .media_changed = idedisk_media_changed, .revalidate_disk= idedisk_revalidate_disk }; diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c index 5945f551aaaa..fba3fffc2d66 100644 --- a/trunk/drivers/ide/ide-floppy.c +++ b/trunk/drivers/ide/ide-floppy.c @@ -2031,17 +2031,6 @@ static int idefloppy_release(struct inode *inode, struct file *filp) return 0; } -static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); - ide_drive_t *drive = floppy->drive; - - geo->heads = drive->bios_head; - geo->sectors = drive->bios_sect; - geo->cylinders = (u16)drive->bios_cyl; /* truncate */ - return 0; -} - static int idefloppy_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2131,7 +2120,6 @@ static struct block_device_operations idefloppy_ops = { .open = idefloppy_open, .release = idefloppy_release, .ioctl = idefloppy_ioctl, - .getgeo = idefloppy_getgeo, .media_changed = idefloppy_media_changed, .revalidate_disk= idefloppy_revalidate_disk }; diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index dea2d4dcc698..b5dc6df8e67d 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -55,22 +55,9 @@ #include #include -void ide_softirq_done(struct request *rq) -{ - request_queue_t *q = rq->q; - - add_disk_randomness(rq->rq_disk); - end_that_request_chunk(rq, rq->errors, rq->data_len); - - spin_lock_irq(q->queue_lock); - end_that_request_last(rq, rq->errors); - spin_unlock_irq(q->queue_lock); -} - int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, int nr_sectors) { - unsigned int nbytes; int ret = 1; BUG_ON(!(rq->flags & REQ_STARTED)); @@ -94,28 +81,17 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, HWGROUP(drive)->hwif->ide_dma_on(drive); } - /* - * For partial completions (or non fs/pc requests), use the regular - * direct completion path. - */ - nbytes = nr_sectors << 9; - if (rq_all_done(rq, nbytes)) { - rq->errors = uptodate; - rq->data_len = nbytes; + if (!end_that_request_first(rq, uptodate, nr_sectors)) { + add_disk_randomness(rq->rq_disk); + + if (blk_rq_tagged(rq)) + blk_queue_end_tag(drive->queue, rq); + blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - blk_complete_request(rq); + end_that_request_last(rq, uptodate); ret = 0; - } else { - if (!end_that_request_first(rq, uptodate, nr_sectors)) { - add_disk_randomness(rq->rq_disk); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq, uptodate); - ret = 0; - } } - return ret; } EXPORT_SYMBOL(__ide_end_request); @@ -137,10 +113,6 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) unsigned long flags; int ret = 1; - /* - * room for locking improvements here, the calls below don't - * need the queue lock held at all - */ spin_lock_irqsave(&ide_lock, flags); rq = HWGROUP(drive)->rq; diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 1ddaa71a8f45..02167a5b751d 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -1011,8 +1011,6 @@ static int ide_init_queue(ide_drive_t *drive) blk_queue_max_hw_segments(q, max_sg_entries); blk_queue_max_phys_segments(q, max_sg_entries); - blk_queue_softirq_done(q, ide_softirq_done); - /* assign drive queue */ drive->queue = q; diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index b069b13b75a7..4b524f6b3ecd 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -1278,6 +1278,19 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device up(&ide_setting_sem); switch (cmd) { + case HDIO_GETGEO: + { + struct hd_geometry geom; + if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; + geom.heads = drive->bios_head; + geom.sectors = drive->bios_sect; + geom.cylinders = (u16)drive->bios_cyl; /* truncate */ + geom.start = get_start_sect(bdev); + if (copy_to_user(p, &geom, sizeof(struct hd_geometry))) + return -EFAULT; + return 0; + } + case HDIO_OBSOLETE_IDENTITY: case HDIO_GET_IDENTITY: if (bdev != bdev->bd_contains) diff --git a/trunk/drivers/ide/legacy/hd.c b/trunk/drivers/ide/legacy/hd.c index 6439dec66881..242029c9c0ca 100644 --- a/trunk/drivers/ide/legacy/hd.c +++ b/trunk/drivers/ide/legacy/hd.c @@ -658,14 +658,22 @@ static void do_hd_request (request_queue_t * q) enable_irq(HD_IRQ); } -static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int hd_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) { - struct hd_i_struct *disk = bdev->bd_disk->private_data; - - geo->heads = disk->head; - geo->sectors = disk->sect; - geo->cylinders = disk->cyl; - return 0; + struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data; + struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; + struct hd_geometry g; + + if (cmd != HDIO_GETGEO) + return -EINVAL; + if (!loc) + return -EINVAL; + g.heads = disk->head; + g.sectors = disk->sect; + g.cylinders = disk->cyl; + g.start = get_start_sect(inode->i_bdev); + return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; } /* @@ -687,7 +695,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) } static struct block_device_operations hd_fops = { - .getgeo = hd_getgeo, + .ioctl = hd_ioctl, }; /* diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c index 0d3073f4eab4..ff2e217a8c84 100644 --- a/trunk/drivers/ide/pci/serverworks.c +++ b/trunk/drivers/ide/pci/serverworks.c @@ -69,7 +69,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) static u8 svwks_ratemask (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mode = 0; + u8 mode; if (!svwks_revision) pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); diff --git a/trunk/drivers/infiniband/core/cm.c b/trunk/drivers/infiniband/core/cm.c index 3a611fe5497e..02110e00d145 100644 --- a/trunk/drivers/infiniband/core/cm.c +++ b/trunk/drivers/infiniband/core/cm.c @@ -308,11 +308,10 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv) { unsigned long flags; int ret; - static int next_id; do { spin_lock_irqsave(&cm.lock, flags); - ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, next_id++, + ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1, (__force int *) &cm_id_priv->id.local_id); spin_unlock_irqrestore(&cm.lock, flags); } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); @@ -685,13 +684,6 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id) cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT); break; case IB_CM_REQ_SENT: - ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT, - &cm_id_priv->av.port->cm_dev->ca_guid, - sizeof cm_id_priv->av.port->cm_dev->ca_guid, - NULL, 0); - break; case IB_CM_MRA_REQ_RCVD: case IB_CM_REP_SENT: case IB_CM_MRA_REP_RCVD: @@ -702,8 +694,10 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id) case IB_CM_REP_RCVD: case IB_CM_MRA_REP_SENT: spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, - NULL, 0, NULL, 0); + ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT, + &cm_id_priv->av.port->cm_dev->ca_guid, + sizeof cm_id_priv->av.port->cm_dev->ca_guid, + NULL, 0); break; case IB_CM_ESTABLISHED: spin_unlock_irqrestore(&cm_id_priv->lock, flags); diff --git a/trunk/drivers/infiniband/core/user_mad.c b/trunk/drivers/infiniband/core/user_mad.c index c908de8db5a9..eb7f52537ccc 100644 --- a/trunk/drivers/infiniband/core/user_mad.c +++ b/trunk/drivers/infiniband/core/user_mad.c @@ -197,8 +197,8 @@ static void send_handler(struct ib_mad_agent *agent, memcpy(timeout->mad.data, packet->mad.data, sizeof (struct ib_mad_hdr)); - if (queue_packet(file, agent, timeout)) - kfree(timeout); + if (!queue_packet(file, agent, timeout)) + return; } out: kfree(packet); diff --git a/trunk/drivers/infiniband/core/uverbs_cmd.c b/trunk/drivers/infiniband/core/uverbs_cmd.c index a02c5a05c984..a57d021d435a 100644 --- a/trunk/drivers/infiniband/core/uverbs_cmd.c +++ b/trunk/drivers/infiniband/core/uverbs_cmd.c @@ -489,7 +489,6 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, err_unreg: ib_dereg_mr(mr); - atomic_dec(&pd->usecnt); err_up: up(&ib_uverbs_idr_mutex); @@ -594,18 +593,13 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, if (cmd.comp_vector >= file->device->num_comp_vectors) return -EINVAL; + if (cmd.comp_channel >= 0) + ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); + uobj = kmalloc(sizeof *uobj, GFP_KERNEL); if (!uobj) return -ENOMEM; - if (cmd.comp_channel >= 0) { - ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); - if (!ev_file) { - ret = -EINVAL; - goto err; - } - } - uobj->uobject.user_handle = cmd.user_handle; uobj->uobject.context = file->ucontext; uobj->uverbs_file = file; @@ -669,8 +663,6 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, ib_destroy_cq(cq); err: - if (ev_file) - ib_uverbs_release_ucq(file, ev_file, uobj); kfree(uobj); return ret; } @@ -943,11 +935,6 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, err_destroy: ib_destroy_qp(qp); - atomic_dec(&pd->usecnt); - atomic_dec(&attr.send_cq->usecnt); - atomic_dec(&attr.recv_cq->usecnt); - if (attr.srq) - atomic_dec(&attr.srq->usecnt); err_up: up(&ib_uverbs_idr_mutex); @@ -1461,7 +1448,6 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, attr.sl = cmd.attr.sl; attr.src_path_bits = cmd.attr.src_path_bits; attr.static_rate = cmd.attr.static_rate; - attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0; attr.port_num = cmd.attr.port_num; attr.grh.flow_label = cmd.attr.grh.flow_label; attr.grh.sgid_index = cmd.attr.grh.sgid_index; @@ -1743,7 +1729,6 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, err_destroy: ib_destroy_srq(srq); - atomic_dec(&pd->usecnt); err_up: up(&ib_uverbs_idr_mutex); diff --git a/trunk/drivers/infiniband/core/verbs.c b/trunk/drivers/infiniband/core/verbs.c index c857361be449..4c15e112736c 100644 --- a/trunk/drivers/infiniband/core/verbs.c +++ b/trunk/drivers/infiniband/core/verbs.c @@ -107,9 +107,9 @@ struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, if (wc->wc_flags & IB_WC_GRH) { ah_attr.ah_flags = IB_AH_GRH; - ah_attr.grh.dgid = grh->sgid; + ah_attr.grh.dgid = grh->dgid; - ret = ib_find_cached_gid(pd->device, &grh->dgid, &port_num, + ret = ib_find_cached_gid(pd->device, &grh->sgid, &port_num, &gid_index); if (ret) return ERR_PTR(ret); diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c index 22ac72bc20c3..9ed34587fc5c 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -937,6 +937,10 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, if (err) goto out; + MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); + dev_lim->max_srq_sz = (1 << field) - 1; + MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); + dev_lim->max_qp_sz = (1 << field) - 1; MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET); dev_lim->reserved_qps = 1 << (field & 0xf); MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET); @@ -1052,10 +1056,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); if (mthca_is_memfree(dev)) { - MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); - dev_lim->max_srq_sz = 1 << field; - MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); - dev_lim->max_qp_sz = 1 << field; MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSZ_SRQ_OFFSET); dev_lim->hca.arbel.resize_srq = field & 1; MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); @@ -1087,10 +1087,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, mthca_dbg(dev, "Max ICM size %lld MB\n", (unsigned long long) dev_lim->hca.arbel.max_icm_sz >> 20); } else { - MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); - dev_lim->max_srq_sz = (1 << field) - 1; - MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); - dev_lim->max_qp_sz = (1 << field) - 1; MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_AV_OFFSET); dev_lim->hca.tavor.max_avs = 1 << (field & 0x3f); dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c index 96f1a86bf049..4a8adcef2079 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c @@ -128,12 +128,12 @@ struct mthca_err_cqe { __be32 my_qpn; u32 reserved1[3]; u8 syndrome; - u8 vendor_err; + u8 reserved2; __be16 db_cnt; - u32 reserved2; + u32 reserved3; __be32 wqe; u8 opcode; - u8 reserved3[2]; + u8 reserved4[2]; u8 owner; }; @@ -253,15 +253,6 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn, wake_up(&cq->wait); } -static inline int is_recv_cqe(struct mthca_cqe *cqe) -{ - if ((cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) == - MTHCA_ERROR_CQE_OPCODE_MASK) - return !(cqe->opcode & 0x01); - else - return !(cqe->is_send & 0x80); -} - void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, struct mthca_srq *srq) { @@ -305,7 +296,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, while ((int) --prod_index - (int) cq->cons_index >= 0) { cqe = get_cqe(cq, prod_index & cq->ibcq.cqe); if (cqe->my_qpn == cpu_to_be32(qpn)) { - if (srq && is_recv_cqe(cqe)) + if (srq) mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe)); ++nfreed; } else if (nfreed) @@ -342,8 +333,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, } /* - * For completions in error, only work request ID, status, vendor error - * (and freed resource count for RD) have to be set. + * For completions in error, only work request ID, status (and + * freed resource count for RD) have to be set. */ switch (cqe->syndrome) { case SYNDROME_LOCAL_LENGTH_ERR: @@ -405,8 +396,6 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, break; } - entry->vendor_err = cqe->vendor_err; - /* * Mem-free HCAs always generate one CQE per WQE, even in the * error case, so we don't have to check the doorbell count, etc. diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h index 795b379260bf..497ff794ef6a 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include "mthca_provider.h" diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_eq.c b/trunk/drivers/infiniband/hw/mthca/mthca_eq.c index e8a948f087c0..34d68e5a72d8 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_eq.c @@ -484,7 +484,8 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, u8 intr, struct mthca_eq *eq) { - int npages; + int npages = (nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) / + PAGE_SIZE; u64 *dma_list = NULL; dma_addr_t t; struct mthca_mailbox *mailbox; @@ -495,7 +496,6 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, eq->dev = dev; eq->nent = roundup_pow_of_two(max(nent, 2)); - npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE; eq->page_list = kmalloc(npages * sizeof *eq->page_list, GFP_KERNEL); diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_main.c b/trunk/drivers/infiniband/hw/mthca/mthca_main.c index 8b00d9a0f6f4..6f94b25f3acd 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_main.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_main.c @@ -261,10 +261,6 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev) } err = mthca_dev_lim(mdev, &dev_lim); - if (err) { - mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n"); - goto err_disable; - } profile = default_profile; profile.num_uar = dev_lim.uar_size / PAGE_SIZE; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c b/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c index 77bc6c746f43..2fc449da418d 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -111,8 +111,7 @@ static int find_mgm(struct mthca_dev *dev, goto out; if (status) { mthca_err(dev, "READ_MGM returned status %02x\n", status); - err = -EINVAL; - goto out; + return -EINVAL; } if (!memcmp(mgm->gid, zero_gid, 16)) { @@ -127,7 +126,7 @@ static int find_mgm(struct mthca_dev *dev, goto out; *prev = *index; - *index = be32_to_cpu(mgm->next_gid_index) >> 6; + *index = be32_to_cpu(mgm->next_gid_index) >> 5; } while (*index); *index = -1; @@ -154,10 +153,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) return PTR_ERR(mailbox); mgm = mailbox->buf; - if (down_interruptible(&dev->mcg_table.sem)) { - err = -EINTR; - goto err_sem; - } + if (down_interruptible(&dev->mcg_table.sem)) + return -EINTR; err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); if (err) @@ -184,8 +181,9 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) err = -EINVAL; goto out; } - memset(mgm, 0, sizeof *mgm); + memcpy(mgm->gid, gid->raw, 16); + mgm->next_gid_index = 0; } for (i = 0; i < MTHCA_QP_PER_MGM; ++i) @@ -211,7 +209,6 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) if (status) { mthca_err(dev, "WRITE_MGM returned status %02x\n", status); err = -EINVAL; - goto out; } if (!link) @@ -226,7 +223,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) goto out; } - mgm->next_gid_index = cpu_to_be32(index << 6); + mgm->next_gid_index = cpu_to_be32(index << 5); err = mthca_WRITE_MGM(dev, prev, mailbox, &status); if (err) @@ -237,12 +234,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) } out: - if (err && link && index != -1) { - BUG_ON(index < dev->limits.num_mgms); - mthca_free(&dev->mcg_table.alloc, index); - } up(&dev->mcg_table.sem); - err_sem: mthca_free_mailbox(dev, mailbox); return err; } @@ -263,10 +255,8 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) return PTR_ERR(mailbox); mgm = mailbox->buf; - if (down_interruptible(&dev->mcg_table.sem)) { - err = -EINTR; - goto err_sem; - } + if (down_interruptible(&dev->mcg_table.sem)) + return -EINTR; err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); if (err) @@ -315,11 +305,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) if (i != 1) goto out; + goto out; + if (prev == -1) { /* Remove entry from MGM */ - int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6; - if (amgm_index_to_free) { - err = mthca_READ_MGM(dev, amgm_index_to_free, + if (be32_to_cpu(mgm->next_gid_index) >> 5) { + err = mthca_READ_MGM(dev, + be32_to_cpu(mgm->next_gid_index) >> 5, mailbox, &status); if (err) goto out; @@ -340,13 +332,9 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) err = -EINVAL; goto out; } - if (amgm_index_to_free) { - BUG_ON(amgm_index_to_free < dev->limits.num_mgms); - mthca_free(&dev->mcg_table.alloc, amgm_index_to_free); - } } else { /* Remove entry from AMGM */ - int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; + index = be32_to_cpu(mgm->next_gid_index) >> 5; err = mthca_READ_MGM(dev, prev, mailbox, &status); if (err) goto out; @@ -356,7 +344,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) goto out; } - mgm->next_gid_index = cpu_to_be32(curr_next_index << 6); + mgm->next_gid_index = cpu_to_be32(index << 5); err = mthca_WRITE_MGM(dev, prev, mailbox, &status); if (err) @@ -366,13 +354,10 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) err = -EINVAL; goto out; } - BUG_ON(index < dev->limits.num_mgms); - mthca_free(&dev->mcg_table.alloc, index); } out: up(&dev->mcg_table.sem); - err_sem: mthca_free_mailbox(dev, mailbox); return err; } @@ -380,12 +365,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) int __devinit mthca_init_mcg_table(struct mthca_dev *dev) { int err; - int table_size = dev->limits.num_mgms + dev->limits.num_amgms; err = mthca_alloc_init(&dev->mcg_table.alloc, - table_size, - table_size - 1, - dev->limits.num_mgms); + dev->limits.num_amgms, + dev->limits.num_amgms - 1, + 0); if (err) return err; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c index 9fb985a016e9..d72fe95cba08 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -233,7 +233,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj) for (i = 0; i < chunk->npages; ++i) { if (chunk->mem[i].length >= offset) { page = chunk->mem[i].page; - goto out; + break; } offset -= chunk->mem[i].length; } @@ -485,8 +485,6 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar, put_page(db_tab->page[i].mem.page); } } - - kfree(db_tab); } int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type, diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c index 564b6d51c394..7450550db736 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c @@ -383,10 +383,12 @@ static const struct { [UC] = (IB_QP_CUR_STATE | IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | IB_QP_PATH_MIG_STATE), [RC] = (IB_QP_CUR_STATE | IB_QP_ALT_PATH | IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | IB_QP_MIN_RNR_TIMER | IB_QP_PATH_MIG_STATE), [MLX] = (IB_QP_CUR_STATE | @@ -474,8 +476,9 @@ static const struct { .opt_param = { [UD] = (IB_QP_CUR_STATE | IB_QP_QKEY), - [UC] = (IB_QP_CUR_STATE | - IB_QP_ACCESS_FLAGS), + [UC] = IB_QP_CUR_STATE, + [RC] = (IB_QP_CUR_STATE | + IB_QP_MIN_RNR_TIMER), [MLX] = (IB_QP_CUR_STATE | IB_QP_QKEY), } @@ -519,55 +522,6 @@ static void init_port(struct mthca_dev *dev, int port) mthca_warn(dev, "INIT_IB returned status %02x.\n", status); } -static __be32 get_hw_access_flags(struct mthca_qp *qp, struct ib_qp_attr *attr, - int attr_mask) -{ - u8 dest_rd_atomic; - u32 access_flags; - u32 hw_access_flags = 0; - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - dest_rd_atomic = attr->max_dest_rd_atomic; - else - dest_rd_atomic = qp->resp_depth; - - if (attr_mask & IB_QP_ACCESS_FLAGS) - access_flags = attr->qp_access_flags; - else - access_flags = qp->atomic_rd_en; - - if (!dest_rd_atomic) - access_flags &= IB_ACCESS_REMOTE_WRITE; - - if (access_flags & IB_ACCESS_REMOTE_READ) - hw_access_flags |= MTHCA_QP_BIT_RRE; - if (access_flags & IB_ACCESS_REMOTE_ATOMIC) - hw_access_flags |= MTHCA_QP_BIT_RAE; - if (access_flags & IB_ACCESS_REMOTE_WRITE) - hw_access_flags |= MTHCA_QP_BIT_RWE; - - return cpu_to_be32(hw_access_flags); -} - -static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path) -{ - path->g_mylmc = ah->src_path_bits & 0x7f; - path->rlid = cpu_to_be16(ah->dlid); - path->static_rate = !!ah->static_rate; - - if (ah->ah_flags & IB_AH_GRH) { - path->g_mylmc |= 1 << 7; - path->mgid_index = ah->grh.sgid_index; - path->hop_limit = ah->grh.hop_limit; - path->sl_tclass_flowlabel = - cpu_to_be32((ah->sl << 28) | - (ah->grh.traffic_class << 20) | - (ah->grh.flow_label)); - memcpy(path->rgid, ah->grh.dgid.raw, 16); - } else - path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28); -} - int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) { struct mthca_dev *dev = to_mdev(ibqp->device); @@ -637,26 +591,6 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) return -EINVAL; } - if ((attr_mask & IB_QP_PORT) && - (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) { - mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num); - return -EINVAL; - } - - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && - attr->max_rd_atomic > dev->limits.max_qp_init_rdma) { - mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n", - attr->max_rd_atomic, dev->limits.max_qp_init_rdma); - return -EINVAL; - } - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && - attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) { - mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n", - attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift); - return -EINVAL; - } - mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); if (IS_ERR(mailbox)) return PTR_ERR(mailbox); @@ -731,14 +665,28 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } if (attr_mask & IB_QP_RNR_RETRY) { - qp_context->alt_path.rnr_retry = qp_context->pri_path.rnr_retry = - attr->rnr_retry << 5; - qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY | - MTHCA_QP_OPTPAR_ALT_RNR_RETRY); + qp_context->pri_path.rnr_retry = attr->rnr_retry << 5; + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY); } if (attr_mask & IB_QP_AV) { - mthca_path_set(&attr->ah_attr, &qp_context->pri_path); + qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f; + qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid); + qp_context->pri_path.static_rate = !!attr->ah_attr.static_rate; + if (attr->ah_attr.ah_flags & IB_AH_GRH) { + qp_context->pri_path.g_mylmc |= 1 << 7; + qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index; + qp_context->pri_path.hop_limit = attr->ah_attr.grh.hop_limit; + qp_context->pri_path.sl_tclass_flowlabel = + cpu_to_be32((attr->ah_attr.sl << 28) | + (attr->ah_attr.grh.traffic_class << 20) | + (attr->ah_attr.grh.flow_label)); + memcpy(qp_context->pri_path.rgid, + attr->ah_attr.grh.dgid.raw, 16); + } else { + qp_context->pri_path.sl_tclass_flowlabel = + cpu_to_be32(attr->ah_attr.sl << 28); + } qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH); } @@ -747,19 +695,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT); } - if (attr_mask & IB_QP_ALT_PATH) { - if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) { - mthca_dbg(dev, "Alternate port number (%u) is invalid\n", - attr->alt_port_num); - return -EINVAL; - } - - mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path); - qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index | - attr->alt_port_num << 24); - qp_context->alt_path.ackto = attr->alt_timeout << 3; - qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ALT_ADDR_PATH); - } + /* XXX alt_path */ /* leave rdd as 0 */ qp_context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pd_num); @@ -767,7 +703,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) qp_context->wqe_lkey = cpu_to_be32(qp->mr.ibmr.lkey); qp_context->params1 = cpu_to_be32((MTHCA_ACK_REQ_FREQ << 28) | (MTHCA_FLIGHT_LIMIT << 24) | - MTHCA_QP_BIT_SWE); + MTHCA_QP_BIT_SRE | + MTHCA_QP_BIT_SWE | + MTHCA_QP_BIT_SAE); if (qp->sq_policy == IB_SIGNAL_ALL_WR) qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC); if (attr_mask & IB_QP_RETRY_CNT) { @@ -776,13 +714,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { - if (attr->max_rd_atomic) { - qp_context->params1 |= - cpu_to_be32(MTHCA_QP_BIT_SRE | - MTHCA_QP_BIT_SAE); - qp_context->params1 |= - cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21); - } + qp_context->params1 |= cpu_to_be32(min(attr->max_rd_atomic ? + ffs(attr->max_rd_atomic) - 1 : 0, + 7) << 21); qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX); } @@ -795,19 +729,71 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) qp_context->snd_db_index = cpu_to_be32(qp->sq.db_index); } - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { - if (attr->max_dest_rd_atomic) - qp_context->params2 |= - cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21); + if (attr_mask & IB_QP_ACCESS_FLAGS) { + qp_context->params2 |= + cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ? + MTHCA_QP_BIT_RWE : 0); - qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX); - } + /* + * Only enable RDMA reads and atomics if we have + * responder resources set to a non-zero value. + */ + if (qp->resp_depth) { + qp_context->params2 |= + cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_READ ? + MTHCA_QP_BIT_RRE : 0); + qp_context->params2 |= + cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC ? + MTHCA_QP_BIT_RAE : 0); + } - if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) { - qp_context->params2 |= get_hw_access_flags(qp, attr, attr_mask); qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE | MTHCA_QP_OPTPAR_RRE | MTHCA_QP_OPTPAR_RAE); + + qp->atomic_rd_en = attr->qp_access_flags; + } + + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { + u8 rra_max; + + if (qp->resp_depth && !attr->max_dest_rd_atomic) { + /* + * Lowering our responder resources to zero. + * Turn off reads RDMA and atomics as responder. + * (RRE/RAE in params2 already zero) + */ + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE | + MTHCA_QP_OPTPAR_RAE); + } + + if (!qp->resp_depth && attr->max_dest_rd_atomic) { + /* + * Increasing our responder resources from + * zero. Turn on RDMA reads and atomics as + * appropriate. + */ + qp_context->params2 |= + cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_READ ? + MTHCA_QP_BIT_RRE : 0); + qp_context->params2 |= + cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_ATOMIC ? + MTHCA_QP_BIT_RAE : 0); + + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE | + MTHCA_QP_OPTPAR_RAE); + } + + for (rra_max = 0; + 1 << rra_max < attr->max_dest_rd_atomic && + rra_max < dev->qp_table.rdb_shift; + ++rra_max) + ; /* nothing */ + + qp_context->params2 |= cpu_to_be32(rra_max << 21); + qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX); + + qp->resp_depth = attr->max_dest_rd_atomic; } qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC); @@ -849,13 +835,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) err = -EINVAL; } - if (!err) { + if (!err) qp->state = new_state; - if (attr_mask & IB_QP_ACCESS_FLAGS) - qp->atomic_rd_en = attr->qp_access_flags; - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - qp->resp_depth = attr->max_dest_rd_atomic; - } mthca_free_mailbox(dev, mailbox); @@ -904,13 +885,18 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) return err; } -static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz) +static void mthca_adjust_qp_caps(struct mthca_dev *dev, + struct mthca_pd *pd, + struct mthca_qp *qp) { + int max_data_size; + /* * Calculate the maximum size of WQE s/g segments, excluding * the next segment and other non-data segments. */ - int max_data_size = desc_sz - sizeof (struct mthca_next_seg); + max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) - + sizeof (struct mthca_next_seg); switch (qp->transport) { case MLX: @@ -929,24 +915,11 @@ static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int d break; } - return max_data_size; -} - -static inline int mthca_max_inline_data(struct mthca_pd *pd, int max_data_size) -{ /* We don't support inline data for kernel QPs (yet). */ - return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0; -} - -static void mthca_adjust_qp_caps(struct mthca_dev *dev, - struct mthca_pd *pd, - struct mthca_qp *qp) -{ - int max_data_size = mthca_max_data_size(dev, qp, - min(dev->limits.max_desc_sz, - 1 << qp->sq.wqe_shift)); - - qp->max_inline_data = mthca_max_inline_data(pd, max_data_size); + if (!pd->ibpd.uobject) + qp->max_inline_data = 0; + else + qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE; qp->sq.max_gs = min_t(int, dev->limits.max_sg, max_data_size / sizeof (struct mthca_data_seg)); @@ -1213,23 +1186,13 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, } static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, - struct mthca_pd *pd, struct mthca_qp *qp) + struct mthca_qp *qp) { - int max_data_size = mthca_max_data_size(dev, qp, dev->limits.max_desc_sz); - /* Sanity check QP size before proceeding */ - if (cap->max_send_wr > dev->limits.max_wqes || - cap->max_recv_wr > dev->limits.max_wqes || - cap->max_send_sge > dev->limits.max_sg || - cap->max_recv_sge > dev->limits.max_sg || - cap->max_inline_data > mthca_max_inline_data(pd, max_data_size)) - return -EINVAL; - - /* - * For MLX transport we need 2 extra S/G entries: - * one for the header and one for the checksum at the end - */ - if (qp->transport == MLX && cap->max_recv_sge + 2 > dev->limits.max_sg) + if (cap->max_send_wr > dev->limits.max_wqes || + cap->max_recv_wr > dev->limits.max_wqes || + cap->max_send_sge > dev->limits.max_sg || + cap->max_recv_sge > dev->limits.max_sg) return -EINVAL; if (mthca_is_memfree(dev)) { @@ -1248,6 +1211,14 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, MTHCA_INLINE_CHUNK_SIZE) / sizeof (struct mthca_data_seg)); + /* + * For MLX transport we need 2 extra S/G entries: + * one for the header and one for the checksum at the end + */ + if ((qp->transport == MLX && qp->sq.max_gs + 2 > dev->limits.max_sg) || + qp->sq.max_gs > dev->limits.max_sg || qp->rq.max_gs > dev->limits.max_sg) + return -EINVAL; + return 0; } @@ -1262,7 +1233,7 @@ int mthca_alloc_qp(struct mthca_dev *dev, { int err; - err = mthca_set_qp_size(dev, cap, pd, qp); + err = mthca_set_qp_size(dev, cap, qp); if (err) return err; @@ -1305,7 +1276,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev, u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1; int err; - err = mthca_set_qp_size(dev, cap, pd, &sqp->qp); + err = mthca_set_qp_size(dev, cap, &sqp->qp); if (err) return err; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_srq.c b/trunk/drivers/infiniband/hw/mthca/mthca_srq.c index e7e153d9c4c6..f7d234295efe 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_srq.c @@ -201,7 +201,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, if (mthca_is_memfree(dev)) srq->max = roundup_pow_of_two(srq->max + 1); - ds = max(64UL, + ds = min(64UL, roundup_pow_of_two(sizeof (struct mthca_next_seg) + srq->max_gs * sizeof (struct mthca_data_seg))); srq->wqe_shift = long_log2(ds); diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index dd488d3cffa9..ee9fe226ae99 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -39,7 +39,6 @@ #include #include #include -#include #include diff --git a/trunk/drivers/input/keyboard/corgikbd.c b/trunk/drivers/input/keyboard/corgikbd.c index e301ee4ca264..64672d491222 100644 --- a/trunk/drivers/input/keyboard/corgikbd.c +++ b/trunk/drivers/input/keyboard/corgikbd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -342,9 +343,10 @@ static int __init corgikbd_probe(struct platform_device *pdev) for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, - SA_INTERRUPT | SA_TRIGGER_RISING, - "corgikbd", corgikbd)) + SA_INTERRUPT, "corgikbd", corgikbd)) printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); + else + set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING); } /* Set Strobe lines as outputs - set high */ diff --git a/trunk/drivers/input/keyboard/spitzkbd.c b/trunk/drivers/input/keyboard/spitzkbd.c index 83999d583122..6a15fe3bc527 100644 --- a/trunk/drivers/input/keyboard/spitzkbd.c +++ b/trunk/drivers/input/keyboard/spitzkbd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -406,9 +407,10 @@ static int __init spitzkbd_probe(struct platform_device *dev) for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { pxa_gpio_mode(spitz_senses[i] | GPIO_IN); if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, - SA_INTERRUPT|SA_TRIGGER_RISING, - "Spitzkbd Sense", spitzkbd)) + SA_INTERRUPT, "Spitzkbd Sense", spitzkbd)) printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); + else + set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING); } /* Set Strobe lines as outputs - set high */ @@ -420,18 +422,15 @@ static int __init spitzkbd_probe(struct platform_device *dev) pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); - request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, - "Spitzkbd Sync", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, - "Spitzkbd PwrOn", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, - "Spitzkbd SWA", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, - "Spitzkbd SWB", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd); + + set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE); + set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE); + set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE); + set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE); printk(KERN_INFO "input: Spitz Keyboard Registered\n"); diff --git a/trunk/drivers/input/misc/hp_sdc_rtc.c b/trunk/drivers/input/misc/hp_sdc_rtc.c index 1be963961c15..1cd7657f7e42 100644 --- a/trunk/drivers/input/misc/hp_sdc_rtc.c +++ b/trunk/drivers/input/misc/hp_sdc_rtc.c @@ -60,6 +60,8 @@ static struct fasync_struct *hp_sdc_rtc_async_queue; static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); +static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin); + static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos); @@ -385,6 +387,11 @@ static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) return 0; } +static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) { ssize_t retval; @@ -672,7 +679,7 @@ static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, static struct file_operations hp_sdc_rtc_fops = { .owner = THIS_MODULE, - .llseek = no_llseek, + .llseek = hp_sdc_rtc_llseek, .read = hp_sdc_rtc_read, .poll = hp_sdc_rtc_poll, .ioctl = hp_sdc_rtc_ioctl, diff --git a/trunk/drivers/isdn/act2000/act2000.h b/trunk/drivers/isdn/act2000/act2000.h index d4c50512a1ff..b091d1a54125 100644 --- a/trunk/drivers/isdn/act2000/act2000.h +++ b/trunk/drivers/isdn/act2000/act2000.h @@ -181,17 +181,17 @@ typedef struct act2000_card { char regname[35]; /* Name used for request_region */ } act2000_card; -static inline void act2000_schedule_tx(act2000_card *card) +extern __inline__ void act2000_schedule_tx(act2000_card *card) { schedule_work(&card->snd_tq); } -static inline void act2000_schedule_rx(act2000_card *card) +extern __inline__ void act2000_schedule_rx(act2000_card *card) { schedule_work(&card->rcv_tq); } -static inline void act2000_schedule_poll(act2000_card *card) +extern __inline__ void act2000_schedule_poll(act2000_card *card) { schedule_work(&card->poll_tq); } diff --git a/trunk/drivers/isdn/act2000/capi.h b/trunk/drivers/isdn/act2000/capi.h index 49f453c53c64..f6d5f530b86b 100644 --- a/trunk/drivers/isdn/act2000/capi.h +++ b/trunk/drivers/isdn/act2000/capi.h @@ -78,29 +78,29 @@ typedef union actcapi_infoel { /* info element */ typedef struct actcapi_msn { __u8 eaz; __u8 len; /* Length of MSN */ - __u8 msn[15]; -} __attribute__((packed)) actcapi_msn; + __u8 msn[15] __attribute__ ((packed)); +} actcapi_msn; typedef struct actcapi_dlpd { __u8 len; /* Length of structure */ - __u16 dlen; /* Data Length */ - __u8 laa; /* Link Address A */ + __u16 dlen __attribute__ ((packed)); /* Data Length */ + __u8 laa __attribute__ ((packed)); /* Link Address A */ __u8 lab; /* Link Address B */ __u8 modulo; /* Modulo Mode */ __u8 win; /* Window size */ __u8 xid[100]; /* XID Information */ -} __attribute__((packed)) actcapi_dlpd; +} actcapi_dlpd; typedef struct actcapi_ncpd { __u8 len; /* Length of structure */ - __u16 lic; - __u16 hic; - __u16 ltc; - __u16 htc; - __u16 loc; - __u16 hoc; - __u8 modulo; -} __attribute__((packed)) actcapi_ncpd; + __u16 lic __attribute__ ((packed)); + __u16 hic __attribute__ ((packed)); + __u16 ltc __attribute__ ((packed)); + __u16 htc __attribute__ ((packed)); + __u16 loc __attribute__ ((packed)); + __u16 hoc __attribute__ ((packed)); + __u8 modulo __attribute__ ((packed)); +} actcapi_ncpd; #define actcapi_ncpi actcapi_ncpd /* @@ -168,19 +168,19 @@ typedef struct actcapi_msg { __u16 manuf_msg; __u16 controller; actcapi_msn msnmap; - } __attribute ((packed)) manufacturer_req_msn; + } manufacturer_req_msn; /* TODO: TraceInit-req/conf/ind/resp and * TraceDump-req/conf/ind/resp */ struct connect_req { __u8 controller; __u8 bchan; - __u32 infomask; + __u32 infomask __attribute__ ((packed)); __u8 si1; __u8 si2; __u8 eaz; actcapi_addr addr; - } __attribute__ ((packed)) connect_req; + } connect_req; struct connect_conf { __u16 plci; __u16 info; @@ -192,7 +192,7 @@ typedef struct actcapi_msg { __u8 si2; __u8 eaz; actcapi_addr addr; - } __attribute__ ((packed)) connect_ind; + } connect_ind; struct connect_resp { __u16 plci; __u8 rejectcause; @@ -200,14 +200,14 @@ typedef struct actcapi_msg { struct connect_active_ind { __u16 plci; actcapi_addr addr; - } __attribute__ ((packed)) connect_active_ind; + } connect_active_ind; struct connect_active_resp { __u16 plci; } connect_active_resp; struct connect_b3_req { __u16 plci; actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_req; + } connect_b3_req; struct connect_b3_conf { __u16 plci; __u16 ncci; @@ -217,12 +217,12 @@ typedef struct actcapi_msg { __u16 ncci; __u16 plci; actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_ind; + } connect_b3_ind; struct connect_b3_resp { __u16 ncci; __u8 rejectcause; - actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_resp; + actcapi_ncpi ncpi __attribute__ ((packed)); + } connect_b3_resp; struct disconnect_req { __u16 plci; __u8 cause; @@ -241,14 +241,14 @@ typedef struct actcapi_msg { struct connect_b3_active_ind { __u16 ncci; actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_active_ind; + } connect_b3_active_ind; struct connect_b3_active_resp { __u16 ncci; } connect_b3_active_resp; struct disconnect_b3_req { __u16 ncci; actcapi_ncpi ncpi; - } __attribute__ ((packed)) disconnect_b3_req; + } disconnect_b3_req; struct disconnect_b3_conf { __u16 ncci; __u16 info; @@ -257,7 +257,7 @@ typedef struct actcapi_msg { __u16 ncci; __u16 info; actcapi_ncpi ncpi; - } __attribute__ ((packed)) disconnect_b3_ind; + } disconnect_b3_ind; struct disconnect_b3_resp { __u16 ncci; } disconnect_b3_resp; @@ -265,7 +265,7 @@ typedef struct actcapi_msg { __u16 plci; actcapi_infonr nr; actcapi_infoel el; - } __attribute__ ((packed)) info_ind; + } info_ind; struct info_resp { __u16 plci; } info_resp; @@ -279,8 +279,8 @@ typedef struct actcapi_msg { struct select_b2_protocol_req { __u16 plci; __u8 protocol; - actcapi_dlpd dlpd; - } __attribute__ ((packed)) select_b2_protocol_req; + actcapi_dlpd dlpd __attribute__ ((packed)); + } select_b2_protocol_req; struct select_b2_protocol_conf { __u16 plci; __u16 info; @@ -288,49 +288,49 @@ typedef struct actcapi_msg { struct select_b3_protocol_req { __u16 plci; __u8 protocol; - actcapi_ncpd ncpd; - } __attribute__ ((packed)) select_b3_protocol_req; + actcapi_ncpd ncpd __attribute__ ((packed)); + } select_b3_protocol_req; struct select_b3_protocol_conf { __u16 plci; __u16 info; } select_b3_protocol_conf; struct listen_req { __u8 controller; - __u32 infomask; - __u16 eazmask; - __u16 simask; - } __attribute__ ((packed)) listen_req; + __u32 infomask __attribute__ ((packed)); + __u16 eazmask __attribute__ ((packed)); + __u16 simask __attribute__ ((packed)); + } listen_req; struct listen_conf { __u8 controller; - __u16 info; - } __attribute__ ((packed)) listen_conf; + __u16 info __attribute__ ((packed)); + } listen_conf; struct data_b3_req { __u16 fakencci; __u16 datalen; __u32 unused; __u8 blocknr; - __u16 flags; - } __attribute ((packed)) data_b3_req; + __u16 flags __attribute__ ((packed)); + } data_b3_req; struct data_b3_ind { __u16 fakencci; __u16 datalen; __u32 unused; __u8 blocknr; - __u16 flags; - } __attribute__ ((packed)) data_b3_ind; + __u16 flags __attribute__ ((packed)); + } data_b3_ind; struct data_b3_resp { __u16 ncci; __u8 blocknr; - } __attribute__ ((packed)) data_b3_resp; + } data_b3_resp; struct data_b3_conf { __u16 ncci; __u8 blocknr; - __u16 info; - } __attribute__ ((packed)) data_b3_conf; + __u16 info __attribute__ ((packed)); + } data_b3_conf; } msg; -} __attribute__ ((packed)) actcapi_msg; +} actcapi_msg; -static inline unsigned short +extern __inline__ unsigned short actcapi_nextsmsg(act2000_card *card) { unsigned long flags; diff --git a/trunk/drivers/isdn/capi/capifs.c b/trunk/drivers/isdn/capi/capifs.c index 207cae366256..7b564c0dd996 100644 --- a/trunk/drivers/isdn/capi/capifs.c +++ b/trunk/drivers/isdn/capi/capifs.c @@ -17,8 +17,6 @@ #include #include /* current */ -#include "capifs.h" - MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/isdn/hardware/eicon/os_4bri.c b/trunk/drivers/isdn/hardware/eicon/os_4bri.c index 11e6f937c1e4..cccfabc1117d 100644 --- a/trunk/drivers/isdn/hardware/eicon/os_4bri.c +++ b/trunk/drivers/isdn/hardware/eicon/os_4bri.c @@ -16,7 +16,6 @@ #include "diva_pci.h" #include "mi_pc.h" #include "dsrv4bri.h" -#include "helpers.h" static void *diva_xdiLoadFileFile = NULL; static dword diva_xdiLoadFileLength = 0; @@ -816,7 +815,7 @@ diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, return (ret); } -void *xdiLoadFile(char *FileName, dword *FileLength, +void *xdiLoadFile(char *FileName, unsigned long *FileLength, unsigned long lim) { void *ret = diva_xdiLoadFileFile; diff --git a/trunk/drivers/isdn/hardware/eicon/os_bri.c b/trunk/drivers/isdn/hardware/eicon/os_bri.c index f31bba5b16ff..4cc44a5dd1db 100644 --- a/trunk/drivers/isdn/hardware/eicon/os_bri.c +++ b/trunk/drivers/isdn/hardware/eicon/os_bri.c @@ -16,7 +16,6 @@ #include "diva_pci.h" #include "mi_pc.h" #include "pc_maint.h" -#include "dsrv_bri.h" /* ** IMPORTS diff --git a/trunk/drivers/isdn/hardware/eicon/os_pri.c b/trunk/drivers/isdn/hardware/eicon/os_pri.c index a296a846f296..8ac207f75e54 100644 --- a/trunk/drivers/isdn/hardware/eicon/os_pri.c +++ b/trunk/drivers/isdn/hardware/eicon/os_pri.c @@ -18,7 +18,6 @@ #include "pc_maint.h" #include "dsp_tst.h" #include "diva_dma.h" -#include "dsrv_pri.h" /* -------------------------------------------------------------------------- OS Dependent part of XDI driver for DIVA PRI Adapter diff --git a/trunk/drivers/isdn/hisax/Kconfig b/trunk/drivers/isdn/hisax/Kconfig index 0ef560144be3..c82105920d71 100644 --- a/trunk/drivers/isdn/hisax/Kconfig +++ b/trunk/drivers/isdn/hisax/Kconfig @@ -110,7 +110,7 @@ config HISAX_16_3 config HISAX_TELESPCI bool "Teles PCI" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the Teles PCI. See on how to configure it. @@ -238,7 +238,7 @@ config HISAX_MIC config HISAX_NETJET bool "NETjet card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the NetJet from Traverse Technologies. @@ -249,7 +249,7 @@ config HISAX_NETJET config HISAX_NETJET_U bool "NETspider U card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the Netspider U interface ISDN card from Traverse Technologies. @@ -317,7 +317,7 @@ config HISAX_GAZEL config HISAX_HFC_PCI bool "HFC PCI-Bus cards" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the HFC-S PCI 2BDS0 based cards. @@ -344,7 +344,7 @@ config HISAX_HFC_SX config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) help This enables HiSax support for the Formula-n enter:now PCI ISDN card. diff --git a/trunk/drivers/isdn/hisax/hisax.h b/trunk/drivers/isdn/hisax/hisax.h index 1b85ce166af8..26c545fa223b 100644 --- a/trunk/drivers/isdn/hisax/hisax.h +++ b/trunk/drivers/isdn/hisax/hisax.h @@ -396,17 +396,17 @@ struct isar_hw { struct hdlc_stat_reg { #ifdef __BIG_ENDIAN - u_char fill; - u_char mode; - u_char xml; - u_char cmd; + u_char fill __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char cmd __attribute__((packed)); #else - u_char cmd; - u_char xml; - u_char mode; - u_char fill; + u_char cmd __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char fill __attribute__((packed)); #endif -} __attribute__((packed)); +}; struct hdlc_hw { union { diff --git a/trunk/drivers/isdn/hisax/hisax_fcpcipnp.h b/trunk/drivers/isdn/hisax/hisax_fcpcipnp.h index 21fbcedf3a94..bd8a22e4d6a2 100644 --- a/trunk/drivers/isdn/hisax/hisax_fcpcipnp.h +++ b/trunk/drivers/isdn/hisax/hisax_fcpcipnp.h @@ -12,17 +12,17 @@ enum { struct hdlc_stat_reg { #ifdef __BIG_ENDIAN - u_char fill; - u_char mode; - u_char xml; - u_char cmd; + u_char fill __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char cmd __attribute__((packed)); #else - u_char cmd; - u_char xml; - u_char mode; - u_char fill; + u_char cmd __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char fill __attribute__((packed)); #endif -} __attribute__((packed)); +}; struct fritz_bcs { struct hisax_b_if b_if; diff --git a/trunk/drivers/isdn/sc/command.c b/trunk/drivers/isdn/sc/command.c index b4b24335f716..19f2fcf0ae4a 100644 --- a/trunk/drivers/isdn/sc/command.c +++ b/trunk/drivers/isdn/sc/command.c @@ -43,6 +43,7 @@ extern int send_and_receive(int, unsigned int, unsigned char, unsigned char, RspMessage *, int); extern int sendmessage(int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int *); +extern inline void pullphone(char *, char *); #ifdef DEBUG /* diff --git a/trunk/drivers/macintosh/windfarm_smu_controls.c b/trunk/drivers/macintosh/windfarm_smu_controls.c index 4d811600bdab..2c3158c81ff2 100644 --- a/trunk/drivers/macintosh/windfarm_smu_controls.c +++ b/trunk/drivers/macintosh/windfarm_smu_controls.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/drivers/macintosh/windfarm_smu_sensors.c b/trunk/drivers/macintosh/windfarm_smu_sensors.c index 1a00d9c75a23..b558cc209d49 100644 --- a/trunk/drivers/macintosh/windfarm_smu_sensors.c +++ b/trunk/drivers/macintosh/windfarm_smu_sensors.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index e423a16ba3c9..1b76fb29fb70 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -3598,21 +3598,12 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev) return 0; } -static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - mddev_t *mddev = bdev->bd_disk->private_data; - - geo->heads = 2; - geo->sectors = 4; - geo->cylinders = get_capacity(mddev->gendisk) / 8; - return 0; -} - static int md_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int err = 0; void __user *argp = (void __user *)arg; + struct hd_geometry __user *loc = argp; mddev_t *mddev = NULL; if (!capable(CAP_SYS_ADMIN)) @@ -3774,6 +3765,24 @@ static int md_ioctl(struct inode *inode, struct file *file, * 4 sectors (with a BIG number of cylinders...). This drives * dosfs just mad... ;-) */ + case HDIO_GETGEO: + if (!loc) { + err = -EINVAL; + goto abort_unlock; + } + err = put_user (2, (char __user *) &loc->heads); + if (err) + goto abort_unlock; + err = put_user (4, (char __user *) &loc->sectors); + if (err) + goto abort_unlock; + err = put_user(get_capacity(mddev->gendisk)/8, + (short __user *) &loc->cylinders); + if (err) + goto abort_unlock; + err = put_user (get_start_sect(inode->i_bdev), + (long __user *) &loc->start); + goto done_unlock; } /* @@ -3902,7 +3911,6 @@ static struct block_device_operations md_fops = .open = md_open, .release = md_release, .ioctl = md_ioctl, - .getgeo = md_getgeo, .media_changed = md_media_changed, .revalidate_disk= md_revalidate, }; diff --git a/trunk/drivers/md/raid0.c b/trunk/drivers/md/raid0.c index d03f99cf4b7d..abbca150202b 100644 --- a/trunk/drivers/md/raid0.c +++ b/trunk/drivers/md/raid0.c @@ -306,6 +306,9 @@ static int raid0_run (mddev_t *mddev) printk("raid0 : conf->hash_spacing is %llu blocks.\n", (unsigned long long)conf->hash_spacing); { +#if __GNUC__ < 3 + volatile +#endif sector_t s = mddev->array_size; sector_t space = conf->hash_spacing; int round; @@ -436,6 +439,9 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio) { +#if __GNUC__ < 3 + volatile +#endif sector_t x = block >> conf->preshift; sector_div(x, (u32)conf->hash_spacing); zone = conf->hash_table[x]; diff --git a/trunk/drivers/media/video/v4l2-common.c b/trunk/drivers/media/video/v4l2-common.c index 62a7d636ef11..597b8db35a13 100644 --- a/trunk/drivers/media/video/v4l2-common.c +++ b/trunk/drivers/media/video/v4l2-common.c @@ -191,7 +191,9 @@ char *v4l2_type_names[] = { }; char *v4l2_ioctl_names[256] = { +#if __GNUC__ >= 3 [0 ... 255] = "UNKNOWN", +#endif [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", diff --git a/trunk/drivers/message/i2o/i2o_block.c b/trunk/drivers/message/i2o/i2o_block.c index b09fb6307153..5b1febed3133 100644 --- a/trunk/drivers/message/i2o/i2o_block.c +++ b/trunk/drivers/message/i2o/i2o_block.c @@ -662,13 +662,6 @@ static int i2o_block_release(struct inode *inode, struct file *file) return 0; } -static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - i2o_block_biosparam(get_capacity(bdev->bd_disk), - &geo->cylinders, &geo->heads, &geo->sectors); - return 0; -} - /** * i2o_block_ioctl - Issue device specific ioctl calls. * @cmd: ioctl command @@ -683,6 +676,7 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, { struct gendisk *disk = inode->i_bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; + void __user *argp = (void __user *)arg; /* Anyone capable of this syscall can do *real bad* things */ @@ -690,6 +684,15 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, return -EPERM; switch (cmd) { + case HDIO_GETGEO: + { + struct hd_geometry g; + i2o_block_biosparam(get_capacity(disk), + &g.cylinders, &g.heads, &g.sectors); + g.start = get_start_sect(inode->i_bdev); + return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0; + } + case BLKI2OGRSTRAT: return put_user(dev->rcache, (int __user *)arg); case BLKI2OGWSTRAT: @@ -959,7 +962,6 @@ static struct block_device_operations i2o_block_fops = { .open = i2o_block_open, .release = i2o_block_release, .ioctl = i2o_block_ioctl, - .getgeo = i2o_block_getgeo, .media_changed = i2o_block_media_changed }; diff --git a/trunk/drivers/mfd/ucb1x00-core.c b/trunk/drivers/mfd/ucb1x00-core.c index b42e0fbab59b..e335d54c4659 100644 --- a/trunk/drivers/mfd/ucb1x00-core.c +++ b/trunk/drivers/mfd/ucb1x00-core.c @@ -27,6 +27,7 @@ #include #include +#include #include "ucb1x00.h" @@ -506,14 +507,14 @@ static int ucb1x00_probe(struct mcp *mcp) goto err_free; } - ret = request_irq(ucb->irq, ucb1x00_irq, SA_TRIGGER_RISING, - "UCB1x00", ucb); + ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb); if (ret) { printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", ucb->irq, ret); goto err_free; } + set_irq_type(ucb->irq, IRQT_RISING); mcp_set_drvdata(mcp, ucb); ret = class_device_register(&ucb->cdev); diff --git a/trunk/drivers/mfd/ucb1x00-ts.c b/trunk/drivers/mfd/ucb1x00-ts.c index 79fd062ccb34..551061c2eadf 100644 --- a/trunk/drivers/mfd/ucb1x00-ts.c +++ b/trunk/drivers/mfd/ucb1x00-ts.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/trunk/drivers/mmc/mmc_block.c b/trunk/drivers/mmc/mmc_block.c index d5f28981596b..198561d21710 100644 --- a/trunk/drivers/mmc/mmc_block.c +++ b/trunk/drivers/mmc/mmc_block.c @@ -113,18 +113,31 @@ static int mmc_blk_release(struct inode *inode, struct file *filp) } static int -mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) +mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); - geo->heads = 4; - geo->sectors = 16; - return 0; + struct block_device *bdev = inode->i_bdev; + + if (cmd == HDIO_GETGEO) { + struct hd_geometry geo; + + memset(&geo, 0, sizeof(struct hd_geometry)); + + geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16); + geo.heads = 4; + geo.sectors = 16; + geo.start = get_start_sect(bdev); + + return copy_to_user((void __user *)arg, &geo, sizeof(geo)) + ? -EFAULT : 0; + } + + return -ENOTTY; } static struct block_device_operations mmc_bdops = { .open = mmc_blk_open, .release = mmc_blk_release, - .getgeo = mmc_blk_getgeo, + .ioctl = mmc_blk_ioctl, .owner = THIS_MODULE, }; diff --git a/trunk/drivers/mtd/mtd_blkdevs.c b/trunk/drivers/mtd/mtd_blkdevs.c index 7f3ff500b68e..339cb1218eaa 100644 --- a/trunk/drivers/mtd/mtd_blkdevs.c +++ b/trunk/drivers/mtd/mtd_blkdevs.c @@ -194,14 +194,6 @@ static int blktrans_release(struct inode *i, struct file *f) return ret; } -static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; - - if (dev->tr->getgeo) - return dev->tr->getgeo(dev, geo); - return -ENOTTY; -} static int blktrans_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -215,6 +207,22 @@ static int blktrans_ioctl(struct inode *inode, struct file *file, return tr->flush(dev); /* The core code did the work, we had nothing to do. */ return 0; + + case HDIO_GETGEO: + if (tr->getgeo) { + struct hd_geometry g; + int ret; + + memset(&g, 0, sizeof(g)); + ret = tr->getgeo(dev, &g); + if (ret) + return ret; + + g.start = get_start_sect(inode->i_bdev); + if (copy_to_user((void __user *)arg, &g, sizeof(g))) + return -EFAULT; + return 0; + } /* else */ default: return -ENOTTY; } @@ -225,7 +233,6 @@ struct block_device_operations mtd_blktrans_ops = { .open = blktrans_open, .release = blktrans_release, .ioctl = blktrans_ioctl, - .getgeo = blktrans_getgeo, }; int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) diff --git a/trunk/drivers/mtd/onenand/generic.c b/trunk/drivers/mtd/onenand/generic.c index af06a80f44de..45c077d0f063 100644 --- a/trunk/drivers/mtd/onenand/generic.c +++ b/trunk/drivers/mtd/onenand/generic.c @@ -14,7 +14,6 @@ #include #include -#include #include #include #include diff --git a/trunk/drivers/mtd/rfd_ftl.c b/trunk/drivers/mtd/rfd_ftl.c index a3e00a4635a5..20ce212638fc 100644 --- a/trunk/drivers/mtd/rfd_ftl.c +++ b/trunk/drivers/mtd/rfd_ftl.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/trunk/drivers/net/3c503.c b/trunk/drivers/net/3c503.c index dcc98afa65d7..5c5eebdb6914 100644 --- a/trunk/drivers/net/3c503.c +++ b/trunk/drivers/net/3c503.c @@ -148,6 +148,14 @@ el2_pio_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: el2_close() handles free_irq */ + release_region(dev->base_addr, EL2_IO_EXTENT); + if (ei_status.mem) + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init el2_probe(int unit) { @@ -718,14 +726,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: el2_close() handles free_irq */ - release_region(dev->base_addr, EL2_IO_EXTENT); - if (ei_status.mem) - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/3c527.h b/trunk/drivers/net/3c527.h index 53b5b071df08..c10f009ce9b6 100644 --- a/trunk/drivers/net/3c527.h +++ b/trunk/drivers/net/3c527.h @@ -32,43 +32,43 @@ struct mc32_mailbox { - u16 mbox; - u16 data[1]; -} __attribute((packed)); + u16 mbox __attribute((packed)); + u16 data[1] __attribute((packed)); +}; struct skb_header { - u8 status; - u8 control; - u16 next; /* Do not change! */ - u16 length; - u32 data; -} __attribute((packed)); + u8 status __attribute((packed)); + u8 control __attribute((packed)); + u16 next __attribute((packed)); /* Do not change! */ + u16 length __attribute((packed)); + u32 data __attribute((packed)); +}; struct mc32_stats { /* RX Errors */ - u32 rx_crc_errors; - u32 rx_alignment_errors; - u32 rx_overrun_errors; - u32 rx_tooshort_errors; - u32 rx_toolong_errors; - u32 rx_outofresource_errors; + u32 rx_crc_errors __attribute((packed)); + u32 rx_alignment_errors __attribute((packed)); + u32 rx_overrun_errors __attribute((packed)); + u32 rx_tooshort_errors __attribute((packed)); + u32 rx_toolong_errors __attribute((packed)); + u32 rx_outofresource_errors __attribute((packed)); - u32 rx_discarded; /* via card pattern match filter */ + u32 rx_discarded __attribute((packed)); /* via card pattern match filter */ /* TX Errors */ - u32 tx_max_collisions; - u32 tx_carrier_errors; - u32 tx_underrun_errors; - u32 tx_cts_errors; - u32 tx_timeout_errors; + u32 tx_max_collisions __attribute((packed)); + u32 tx_carrier_errors __attribute((packed)); + u32 tx_underrun_errors __attribute((packed)); + u32 tx_cts_errors __attribute((packed)); + u32 tx_timeout_errors __attribute((packed)) ; /* various cruft */ - u32 dataA[6]; - u16 dataB[5]; - u32 dataC[14]; -} __attribute((packed)); + u32 dataA[6] __attribute((packed)); + u16 dataB[5] __attribute((packed)); + u32 dataC[14] __attribute((packed)); +}; #define STATUS_MASK 0x0F #define COMPLETED (1<<7) diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 733bc25b2bf9..e2fa29b612cd 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -129,7 +129,7 @@ config NET_SB1000 If you don't have this card, of course say N. -source "drivers/net/arcnet/Kconfig" + source "drivers/net/arcnet/Kconfig" source "drivers/net/phy/Kconfig" @@ -844,7 +844,7 @@ config SMC9194 config DM9000 tristate "DM9000 support" - depends on (ARM || MIPS) && NET_ETHERNET + depends on ARM && NET_ETHERNET select CRC32 select MII ---help--- @@ -1374,7 +1374,7 @@ config FORCEDETH config CS89x0 tristate "CS89x0 support" - depends on NET_PCI && (ISA || ARCH_IXDP2X01 || ARCH_PNX010X) + depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105 ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the diff --git a/trunk/drivers/net/ac3200.c b/trunk/drivers/net/ac3200.c index 7952dc6d77e3..8a0af5453e21 100644 --- a/trunk/drivers/net/ac3200.c +++ b/trunk/drivers/net/ac3200.c @@ -123,6 +123,14 @@ static int __init do_ac3200_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* Someday free_irq may be in ac_close_card() */ + free_irq(dev->irq, dev); + release_region(dev->base_addr, AC_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init ac3200_probe(int unit) { @@ -398,14 +406,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* Someday free_irq may be in ac_close_card() */ - free_irq(dev->irq, dev); - release_region(dev->base_addr, AC_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/bonding/bonding.h b/trunk/drivers/net/bonding/bonding.h index f20bb85c1ea5..015c7f1d1bc0 100644 --- a/trunk/drivers/net/bonding/bonding.h +++ b/trunk/drivers/net/bonding/bonding.h @@ -205,7 +205,7 @@ struct bonding { * * Caller must hold bond lock for read */ -static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev) +extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev) { struct slave *slave = NULL; int i; @@ -219,7 +219,7 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n return slave; } -static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) +extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave) { if (!slave || !slave->dev->master) { return NULL; @@ -228,13 +228,13 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) return (struct bonding *)slave->dev->master->priv; } -static inline void bond_set_slave_inactive_flags(struct slave *slave) +extern inline void bond_set_slave_inactive_flags(struct slave *slave) { slave->state = BOND_STATE_BACKUP; slave->dev->flags |= IFF_NOARP; } -static inline void bond_set_slave_active_flags(struct slave *slave) +extern inline void bond_set_slave_active_flags(struct slave *slave) { slave->state = BOND_STATE_ACTIVE; slave->dev->flags &= ~IFF_NOARP; diff --git a/trunk/drivers/net/cs89x0.c b/trunk/drivers/net/cs89x0.c index 907c01009746..a6078ad9b654 100644 --- a/trunk/drivers/net/cs89x0.c +++ b/trunk/drivers/net/cs89x0.c @@ -175,7 +175,7 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0}; #include static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; -#elif defined(CONFIG_ARCH_PNX010X) +#elif defined(CONFIG_ARCH_PNX0105) #include #include #define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ @@ -338,86 +338,30 @@ struct net_device * __init cs89x0_probe(int unit) } #endif -#if defined(CONFIG_ARCH_IXDP2X01) static int -readword(unsigned long base_addr, int portno) +readreg(struct net_device *dev, int portno) { - return (u16)__raw_readl(base_addr + (portno << 1)); + outw(portno, dev->base_addr + ADD_PORT); + return inw(dev->base_addr + DATA_PORT); } static void -writeword(unsigned long base_addr, int portno, int value) +writereg(struct net_device *dev, int portno, int value) { - __raw_writel((u16)value, base_addr + (portno << 1)); -} -#else -#if defined(CONFIG_ARCH_PNX010X) -static int -readword(unsigned long base_addr, int portno) -{ - return inw(base_addr + (portno << 1)); -} - -static void -writeword(unsigned long base_addr, int portno, int value) -{ - outw(value, base_addr + (portno << 1)); -} -#else -static int -readword(unsigned long base_addr, int portno) -{ - return inw(base_addr + portno); -} - -static void -writeword(unsigned long base_addr, int portno, int value) -{ - outw(value, base_addr + portno); -} -#endif -#endif - -static void -readwords(unsigned long base_addr, int portno, void *buf, int length) -{ - u8 *buf8 = (u8 *)buf; - - do { - u32 tmp32; - - tmp32 = readword(base_addr, portno); - *buf8++ = (u8)tmp32; - *buf8++ = (u8)(tmp32 >> 8); - } while (--length); -} - -static void -writewords(unsigned long base_addr, int portno, void *buf, int length) -{ - u8 *buf8 = (u8 *)buf; - - do { - u32 tmp32; - - tmp32 = *buf8++; - tmp32 |= (*buf8++) << 8; - writeword(base_addr, portno, tmp32); - } while (--length); + outw(portno, dev->base_addr + ADD_PORT); + outw(value, dev->base_addr + DATA_PORT); } static int -readreg(struct net_device *dev, int regno) +readword(struct net_device *dev, int portno) { - writeword(dev->base_addr, ADD_PORT, regno); - return readword(dev->base_addr, DATA_PORT); + return inw(dev->base_addr + portno); } static void -writereg(struct net_device *dev, int regno, int value) +writeword(struct net_device *dev, int portno, int value) { - writeword(dev->base_addr, ADD_PORT, regno); - writeword(dev->base_addr, DATA_PORT, value); + outw(value, dev->base_addr + portno); } static int __init @@ -512,7 +456,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) #endif } -#ifdef CONFIG_ARCH_PNX010X +#ifdef CONFIG_ARCH_PNX0105 initialize_ebi(); /* Map GPIO registers for the pins connected to the CS8900a. */ @@ -547,8 +491,8 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) #ifdef CONFIG_SH_HICOSH4 /* truely reset the chip */ - writeword(ioaddr, ADD_PORT, 0x0114); - writeword(ioaddr, DATA_PORT, 0x0040); + outw(0x0114, ioaddr + ADD_PORT); + outw(0x0040, ioaddr + DATA_PORT); #endif /* if they give us an odd I/O address, then do ONE write to @@ -559,24 +503,24 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) if (net_debug > 1) printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr); if ((ioaddr & 2) != 2) - if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) { + if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) { printk(KERN_ERR "%s: bad signature 0x%x\n", - dev->name, readword(ioaddr & ~3, ADD_PORT)); + dev->name, inw((ioaddr & ~3)+ ADD_PORT)); retval = -ENODEV; goto out2; } } - printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", - ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); + printk(KERN_DEBUG "PP_addr at %x: 0x%x\n", + ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT)); ioaddr &= ~3; - writeword(ioaddr, ADD_PORT, PP_ChipID); + outw(PP_ChipID, ioaddr + ADD_PORT); - tmp = readword(ioaddr, DATA_PORT); + tmp = inw(ioaddr + DATA_PORT); if (tmp != CHIP_EISA_ID_SIG) { - printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!=" + printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!=" CHIP_EISA_ID_SIG_STR "\n", - dev->name, ioaddr, DATA_PORT, tmp); + dev->name, ioaddr + DATA_PORT, tmp); retval = -ENODEV; goto out2; } @@ -780,7 +724,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) } else { i = lp->isa_config & INT_NO_MASK; if (lp->chip_type == CS8900) { -#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) +#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) i = cs8900_irq_map[0]; #else /* Translate the IRQ using the IRQ mapping table. */ @@ -846,7 +790,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) goto out3; return 0; out3: - writeword(dev->base_addr, ADD_PORT, PP_ChipID); + outw(PP_ChipID, dev->base_addr + ADD_PORT); out2: release_region(ioaddr & ~3, NETCARD_IO_EXTENT); out1: @@ -1026,11 +970,11 @@ void __init reset_chip(struct net_device *dev) #ifndef CONFIG_ARCH_IXDP2X01 if (lp->chip_type != CS8900) { /* Hardware problem requires PNP registers to be reconfigured after a reset */ - writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); + outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT); outb(dev->irq, ioaddr + DATA_PORT); outb(0, ioaddr + DATA_PORT + 1); - writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB); + outw(PP_CS8920_ISAMemB, ioaddr + ADD_PORT); outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT); outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1); } @@ -1160,8 +1104,8 @@ send_test_pkt(struct net_device *dev) memcpy(test_packet, dev->dev_addr, ETH_ALEN); memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN); - writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL); - writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN); + writeword(dev, TX_CMD_PORT, TX_AFTER_ALL); + writeword(dev, TX_LEN_PORT, ETH_ZLEN); /* Test to see if the chip has allocated memory for the packet */ while (jiffies - timenow < 5) @@ -1171,7 +1115,7 @@ send_test_pkt(struct net_device *dev) return 0; /* this shouldn't happen */ /* Write the contents of the packet */ - writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); + outsw(dev->base_addr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); if (net_debug > 1) printk("Sending test packet "); /* wait a couple of jiffies for packet to be received */ @@ -1256,7 +1200,7 @@ net_open(struct net_device *dev) int i; int ret; -#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */ +#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */ if (dev->irq < 2) { /* Allow interrupts to be generated by the chip */ /* Cirrus' release had this: */ @@ -1287,7 +1231,7 @@ net_open(struct net_device *dev) else #endif { -#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) +#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105) if (((1 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); @@ -1372,7 +1316,7 @@ net_open(struct net_device *dev) case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); } -#ifdef CONFIG_ARCH_PNX010X +#ifdef CONFIG_ARCH_PNX0105 result = A_CNF_10B_T; #endif if (!result) { @@ -1513,8 +1457,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); /* initiate a transmit sequence */ - writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd); - writeword(dev->base_addr, TX_LEN_PORT, skb->len); + writeword(dev, TX_CMD_PORT, lp->send_cmd); + writeword(dev, TX_LEN_PORT, skb->len); /* Test to see if the chip has allocated memory for the packet */ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { @@ -1528,7 +1472,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) return 1; } /* Write the contents of the packet */ - writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1); + outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1); spin_unlock_irq(&lp->lock); lp->stats.tx_bytes += skb->len; dev->trans_start = jiffies; @@ -1568,7 +1512,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs) course, if you're on a slow machine, and packets are arriving faster than you can read them off, you're screwed. Hasta la vista, baby! */ - while ((status = readword(dev->base_addr, ISQ_PORT))) { + while ((status = readword(dev, ISQ_PORT))) { if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status); handled = 1; switch(status & ISQ_EVENT_MASK) { @@ -1662,8 +1606,8 @@ net_rx(struct net_device *dev) int status, length; int ioaddr = dev->base_addr; - status = readword(ioaddr, RX_FRAME_PORT); - length = readword(ioaddr, RX_FRAME_PORT); + status = inw(ioaddr + RX_FRAME_PORT); + length = inw(ioaddr + RX_FRAME_PORT); if ((status & RX_OK) == 0) { count_rx_errors(status, lp); @@ -1682,9 +1626,9 @@ net_rx(struct net_device *dev) skb_reserve(skb, 2); /* longword align L3 header */ skb->dev = dev; - readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1); + insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1); if (length & 1) - skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT); + skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT); if (net_debug > 3) { printk( "%s: received %d byte packet of type %x\n", @@ -1957,7 +1901,7 @@ void cleanup_module(void) { unregister_netdev(dev_cs89x0); - writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID); + outw(PP_ChipID, dev_cs89x0->base_addr + ADD_PORT); release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT); free_netdev(dev_cs89x0); } diff --git a/trunk/drivers/net/cs89x0.h b/trunk/drivers/net/cs89x0.h index bd954aaa636f..decea264f121 100644 --- a/trunk/drivers/net/cs89x0.h +++ b/trunk/drivers/net/cs89x0.h @@ -16,6 +16,13 @@ #include +#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) +/* IXDP2401/IXDP2801 uses dword-aligned register addressing */ +#define CS89x0_PORT(reg) ((reg) * 2) +#else +#define CS89x0_PORT(reg) (reg) +#endif + #define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */ /* offset 2h -> Model/Product Number */ /* offset 3h -> Chip Revision Number */ @@ -325,16 +332,16 @@ #define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */ #define PKT_START PP_TxFrame /* Start of packet RAM */ -#define RX_FRAME_PORT 0x0000 +#define RX_FRAME_PORT CS89x0_PORT(0x0000) #define TX_FRAME_PORT RX_FRAME_PORT -#define TX_CMD_PORT 0x0004 +#define TX_CMD_PORT CS89x0_PORT(0x0004) #define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */ #define TX_AFTER_381 0x0040 /* Tx packet after 381 bytes copied */ #define TX_AFTER_ALL 0x00c0 /* Tx packet after all bytes copied */ -#define TX_LEN_PORT 0x0006 -#define ISQ_PORT 0x0008 -#define ADD_PORT 0x000A -#define DATA_PORT 0x000C +#define TX_LEN_PORT CS89x0_PORT(0x0006) +#define ISQ_PORT CS89x0_PORT(0x0008) +#define ADD_PORT CS89x0_PORT(0x000A) +#define DATA_PORT CS89x0_PORT(0x000C) #define EEPROM_WRITE_EN 0x00F0 #define EEPROM_WRITE_DIS 0x0000 diff --git a/trunk/drivers/net/e1000/e1000_param.c b/trunk/drivers/net/e1000/e1000_param.c index ccbbe5ad8e0f..38695d5b4637 100644 --- a/trunk/drivers/net/e1000/e1000_param.c +++ b/trunk/drivers/net/e1000/e1000_param.c @@ -545,7 +545,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter) static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { - int speed, dplx, an; + int speed, dplx; int bd = adapter->bd_number; { /* Speed */ @@ -641,12 +641,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) .p = an_list }} }; - if (num_AutoNeg > bd) { - an = AutoNeg[bd]; - e1000_validate_option(&an, &opt, adapter); - } else { - an = opt.def; - } + int an = AutoNeg[bd]; + e1000_validate_option(&an, &opt, adapter); adapter->hw.autoneg_advertised = an; } diff --git a/trunk/drivers/net/e2100.c b/trunk/drivers/net/e2100.c index e5c5cd2a2712..f5a4dd7d8564 100644 --- a/trunk/drivers/net/e2100.c +++ b/trunk/drivers/net/e2100.c @@ -140,6 +140,13 @@ static int __init do_e2100_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: e21_close() handles free_irq */ + iounmap(ei_status.mem); + release_region(dev->base_addr, E21_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init e2100_probe(int unit) { @@ -456,13 +463,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: e21_close() handles free_irq */ - iounmap(ei_status.mem); - release_region(dev->base_addr, E21_IO_EXTENT); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/es3210.c b/trunk/drivers/net/es3210.c index 6b0ab1eac3fb..50f8e23bb9e5 100644 --- a/trunk/drivers/net/es3210.c +++ b/trunk/drivers/net/es3210.c @@ -155,6 +155,13 @@ static int __init do_es_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr, ES_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init es_probe(int unit) { @@ -449,13 +456,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr, ES_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index 3682ec61e8a8..c39344adecce 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -101,7 +101,6 @@ * 0.46: 20 Oct 2005: Add irq optimization modes. * 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan. * 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single - * 0.49: 10 Dec 2005: Fix tso for large buffers. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -113,7 +112,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.49" +#define FORCEDETH_VERSION "0.48" #define DRV_NAME "forcedeth" #include @@ -350,8 +349,6 @@ typedef union _ring_type { #define NV_TX2_VALID (1<<31) #define NV_TX2_TSO (1<<28) #define NV_TX2_TSO_SHIFT 14 -#define NV_TX2_TSO_MAX_SHIFT 14 -#define NV_TX2_TSO_MAX_SIZE (1<tx_ring.ex[i].FlagLen = 0; np->tx_skbuff[i] = NULL; - np->tx_dma[i] = 0; } } @@ -950,27 +945,30 @@ static int nv_init_ring(struct net_device *dev) return nv_alloc_rx(dev); } -static int nv_release_txskb(struct net_device *dev, unsigned int skbnr) +static void nv_release_txskb(struct net_device *dev, unsigned int skbnr) { struct fe_priv *np = netdev_priv(dev); - - dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d\n", - dev->name, skbnr); - - if (np->tx_dma[skbnr]) { - pci_unmap_page(np->pci_dev, np->tx_dma[skbnr], - np->tx_dma_len[skbnr], - PCI_DMA_TODEVICE); - np->tx_dma[skbnr] = 0; - } - - if (np->tx_skbuff[skbnr]) { - dev_kfree_skb_irq(np->tx_skbuff[skbnr]); - np->tx_skbuff[skbnr] = NULL; - return 1; - } else { - return 0; + struct sk_buff *skb = np->tx_skbuff[skbnr]; + unsigned int j, entry, fragments; + + dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n", + dev->name, skbnr, np->tx_skbuff[skbnr]); + + entry = skbnr; + if ((fragments = skb_shinfo(skb)->nr_frags) != 0) { + for (j = fragments; j >= 1; j--) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1]; + pci_unmap_page(np->pci_dev, np->tx_dma[entry], + frag->size, + PCI_DMA_TODEVICE); + entry = (entry - 1) % TX_RING; + } } + pci_unmap_single(np->pci_dev, np->tx_dma[entry], + skb->len - skb->data_len, + PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + np->tx_skbuff[skbnr] = NULL; } static void nv_drain_tx(struct net_device *dev) @@ -983,8 +981,10 @@ static void nv_drain_tx(struct net_device *dev) np->tx_ring.orig[i].FlagLen = 0; else np->tx_ring.ex[i].FlagLen = 0; - if (nv_release_txskb(dev, i)) + if (np->tx_skbuff[i]) { + nv_release_txskb(dev, i); np->stats.tx_dropped++; + } } } @@ -1021,105 +1021,68 @@ static void drain_ring(struct net_device *dev) static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); - u32 tx_flags = 0; u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET); unsigned int fragments = skb_shinfo(skb)->nr_frags; - unsigned int nr = (np->next_tx - 1) % TX_RING; - unsigned int start_nr = np->next_tx % TX_RING; + unsigned int nr = (np->next_tx + fragments) % TX_RING; unsigned int i; - u32 offset = 0; - u32 bcnt; - u32 size = skb->len-skb->data_len; - u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); - - /* add fragments to entries count */ - for (i = 0; i < fragments; i++) { - entries += (skb_shinfo(skb)->frags[i].size >> NV_TX2_TSO_MAX_SHIFT) + - ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); - } spin_lock_irq(&np->lock); - if ((np->next_tx - np->nic_tx + entries - 1) > TX_LIMIT_STOP) { + if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) { spin_unlock_irq(&np->lock); netif_stop_queue(dev); return NETDEV_TX_BUSY; } - /* setup the header buffer */ - do { - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - nr = (nr + 1) % TX_RING; - - np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt, - PCI_DMA_TODEVICE); - np->tx_dma_len[nr] = bcnt; - - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { - np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]); - np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); - } else { - np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32; - np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; - np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); - } - tx_flags = np->tx_flags; - offset += bcnt; - size -= bcnt; - } while(size); - - /* setup the fragments */ - for (i = 0; i < fragments; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - u32 size = frag->size; - offset = 0; - - do { - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - nr = (nr + 1) % TX_RING; - - np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, - PCI_DMA_TODEVICE); - np->tx_dma_len[nr] = bcnt; + np->tx_skbuff[nr] = skb; + + if (fragments) { + dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments); + /* setup descriptors in reverse order */ + for (i = fragments; i >= 1; i--) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1]; + np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size, + PCI_DMA_TODEVICE); if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]); - np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); + np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra); } else { np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32; np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; - np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags); + np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra); } - offset += bcnt; - size -= bcnt; - } while (size); - } + + nr = (nr - 1) % TX_RING; - /* set last fragment flag */ - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { - np->tx_ring.orig[nr].FlagLen |= cpu_to_le32(tx_flags_extra); - } else { - np->tx_ring.ex[nr].FlagLen |= cpu_to_le32(tx_flags_extra); + if (np->desc_ver == DESC_VER_1) + tx_flags_extra &= ~NV_TX_LASTPACKET; + else + tx_flags_extra &= ~NV_TX2_LASTPACKET; + } } - np->tx_skbuff[nr] = skb; - #ifdef NETIF_F_TSO if (skb_shinfo(skb)->tso_size) - tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); + tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); else #endif - tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); + tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); - /* set tx flags */ + np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len, + PCI_DMA_TODEVICE); + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { - np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); + np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]); + np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra); } else { - np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); + np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32; + np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; + np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra); } - dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n", - dev->name, np->next_tx, entries, tx_flags_extra); + dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n", + dev->name, np->next_tx, tx_flags_extra); { int j; for (j=0; j<64; j++) { @@ -1130,7 +1093,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) dprintk("\n"); } - np->next_tx += entries; + np->next_tx += 1 + fragments; dev->trans_start = jiffies; spin_unlock_irq(&np->lock); @@ -1177,6 +1140,7 @@ static void nv_tx_done(struct net_device *dev) np->stats.tx_packets++; np->stats.tx_bytes += skb->len; } + nv_release_txskb(dev, i); } } else { if (Flags & NV_TX2_LASTPACKET) { @@ -1192,9 +1156,9 @@ static void nv_tx_done(struct net_device *dev) np->stats.tx_packets++; np->stats.tx_bytes += skb->len; } + nv_release_txskb(dev, i); } } - nv_release_txskb(dev, i); np->nic_tx++; } if (np->next_tx - np->nic_tx < TX_LIMIT_START) @@ -2492,7 +2456,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; #ifdef NETIF_F_TSO - dev->features |= NETIF_F_TSO; + /* disabled dev->features |= NETIF_F_TSO; */ #endif } diff --git a/trunk/drivers/net/gianfar.h b/trunk/drivers/net/gianfar.h index cb9d66ac3ab9..94a91da84fbb 100644 --- a/trunk/drivers/net/gianfar.h +++ b/trunk/drivers/net/gianfar.h @@ -718,14 +718,14 @@ struct gfar_private { uint32_t msg_enable; }; -static inline u32 gfar_read(volatile unsigned *addr) +extern inline u32 gfar_read(volatile unsigned *addr) { u32 val; val = in_be32(addr); return val; } -static inline void gfar_write(volatile unsigned *addr, u32 val) +extern inline void gfar_write(volatile unsigned *addr, u32 val) { out_be32(addr, val); } diff --git a/trunk/drivers/net/hamradio/mkiss.c b/trunk/drivers/net/hamradio/mkiss.c index 41b3d83c2ab8..3e9accf137e7 100644 --- a/trunk/drivers/net/hamradio/mkiss.c +++ b/trunk/drivers/net/hamradio/mkiss.c @@ -524,7 +524,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) ax->dev->trans_start = jiffies; ax->xleft = count - actual; ax->xhead = ax->xbuff + actual; - spin_unlock_bh(&ax->buflock); } /* Encapsulate an AX.25 packet and kick it into a TTY queue. */ diff --git a/trunk/drivers/net/hp-plus.c b/trunk/drivers/net/hp-plus.c index 74e167e7dea7..0abf5dd08b4c 100644 --- a/trunk/drivers/net/hp-plus.c +++ b/trunk/drivers/net/hp-plus.c @@ -138,6 +138,12 @@ static int __init do_hpp_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: hpp_close() handles free_irq */ + release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init hp_plus_probe(int unit) { @@ -467,12 +473,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: hpp_close() handles free_irq */ - release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/hp.c b/trunk/drivers/net/hp.c index cf9fb3698a6b..59cf841b14ab 100644 --- a/trunk/drivers/net/hp.c +++ b/trunk/drivers/net/hp.c @@ -102,6 +102,12 @@ static int __init do_hp_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init hp_probe(int unit) { @@ -438,12 +444,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/ibm_emac/ibm_emac.h b/trunk/drivers/net/ibm_emac/ibm_emac.h index c2dae6092c4c..644edbff4f94 100644 --- a/trunk/drivers/net/ibm_emac/ibm_emac.h +++ b/trunk/drivers/net/ibm_emac/ibm_emac.h @@ -110,7 +110,6 @@ struct emac_regs { #define EMAC_MR1_TFS_2K 0x00080000 #define EMAC_MR1_TR0_MULT 0x00008000 #define EMAC_MR1_JPSM 0x00000000 -#define EMAC_MR1_MWSW_001 0x00000000 #define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT) #else #define EMAC_MR1_RFS_4K 0x00180000 @@ -131,7 +130,7 @@ struct emac_regs { (freq) <= 83 ? EMAC_MR1_OBCI_83 : \ (freq) <= 100 ? EMAC_MR1_OBCI_100 : EMAC_MR1_OBCI_100P) #define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR | \ - EMAC_MR1_OBCI(opb)) + EMAC_MR1_MWSW_001 | EMAC_MR1_OBCI(opb)) #endif /* EMACx_TMR0 */ diff --git a/trunk/drivers/net/ibm_emac/ibm_emac_core.c b/trunk/drivers/net/ibm_emac/ibm_emac_core.c index 591c5864ffb1..1da8a66f91e1 100644 --- a/trunk/drivers/net/ibm_emac/ibm_emac_core.c +++ b/trunk/drivers/net/ibm_emac/ibm_emac_core.c @@ -408,7 +408,7 @@ static int emac_configure(struct ocp_enet_private *dev) /* Mode register */ r = EMAC_MR1_BASE(emac_opb_mhz()) | EMAC_MR1_VLE | EMAC_MR1_IST; if (dev->phy.duplex == DUPLEX_FULL) - r |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001; + r |= EMAC_MR1_FDE; dev->stop_timeout = STOP_TIMEOUT_10; switch (dev->phy.speed) { case SPEED_1000: diff --git a/trunk/drivers/net/irda/vlsi_ir.h b/trunk/drivers/net/irda/vlsi_ir.h index a82a4ba8de4f..741aecc655df 100644 --- a/trunk/drivers/net/irda/vlsi_ir.h +++ b/trunk/drivers/net/irda/vlsi_ir.h @@ -577,8 +577,8 @@ struct ring_descr_hw { struct { u8 addr_res[3]; volatile u8 status; /* descriptor status */ - } __attribute__((packed)) rd_s; - } __attribute((packed)) rd_u; + } rd_s __attribute__((packed)); + } rd_u __attribute((packed)); } __attribute__ ((packed)); #define rd_addr rd_u.addr diff --git a/trunk/drivers/net/lance.c b/trunk/drivers/net/lance.c index d1d714faa6ce..1d75ca0bb939 100644 --- a/trunk/drivers/net/lance.c +++ b/trunk/drivers/net/lance.c @@ -309,6 +309,17 @@ static void lance_tx_timeout (struct net_device *dev); +static void cleanup_card(struct net_device *dev) +{ + struct lance_private *lp = dev->priv; + if (dev->dma != 4) + free_dma(dev->dma); + release_region(dev->base_addr, LANCE_TOTAL_SIZE); + kfree(lp->tx_bounce_buffs); + kfree((void*)lp->rx_buffs); + kfree(lp); +} + #ifdef MODULE #define MAX_CARDS 8 /* Max number of interfaces (cards) per module */ @@ -356,17 +367,6 @@ int init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - struct lance_private *lp = dev->priv; - if (dev->dma != 4) - free_dma(dev->dma); - release_region(dev->base_addr, LANCE_TOTAL_SIZE); - kfree(lp->tx_bounce_buffs); - kfree((void*)lp->rx_buffs); - kfree(lp); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/lne390.c b/trunk/drivers/net/lne390.c index 646e89fc3562..309d254842cf 100644 --- a/trunk/drivers/net/lne390.c +++ b/trunk/drivers/net/lne390.c @@ -145,6 +145,13 @@ static int __init do_lne390_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr, LNE390_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init lne390_probe(int unit) { @@ -433,13 +440,6 @@ int init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr, LNE390_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index 22c3a37bba5a..3cb9b3fe0cf1 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -6,7 +6,7 @@ * Copyright (C) 2002 rabeeh@galileo.co.il * * Copyright (C) 2003 PMC-Sierra, Inc., - * written by Manish Lachwani + * written by Manish Lachwani (lachwani@pmc-sierra.com) * * Copyright (C) 2003 Ralf Baechle * diff --git a/trunk/drivers/net/ne.c b/trunk/drivers/net/ne.c index 94f782d51f0f..0de8fdd2aa86 100644 --- a/trunk/drivers/net/ne.c +++ b/trunk/drivers/net/ne.c @@ -212,6 +212,15 @@ static int __init do_ne_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; + if (idev) + pnp_device_detach(idev); + free_irq(dev->irq, dev); + release_region(dev->base_addr, NE_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init ne_probe(int unit) { @@ -850,15 +859,6 @@ int init_module(void) return -ENODEV; } -static void cleanup_card(struct net_device *dev) -{ - struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; - if (idev) - pnp_device_detach(idev); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/ne2.c b/trunk/drivers/net/ne2.c index e6df375a1d4b..6d62ada85de6 100644 --- a/trunk/drivers/net/ne2.c +++ b/trunk/drivers/net/ne2.c @@ -278,6 +278,14 @@ static int __init do_ne2_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + mca_mark_as_unused(ei_status.priv); + mca_set_adapter_procfn( ei_status.priv, NULL, NULL); + free_irq(dev->irq, dev); + release_region(dev->base_addr, NE_IO_EXTENT); +} + #ifndef MODULE struct net_device * __init ne2_probe(int unit) { @@ -804,14 +812,6 @@ int init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - mca_mark_as_unused(ei_status.priv); - mca_set_adapter_procfn( ei_status.priv, NULL, NULL); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); -} - void cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/sk98lin/skge.c b/trunk/drivers/net/sk98lin/skge.c index 197edd74fbb5..9a76ac180b11 100644 --- a/trunk/drivers/net/sk98lin/skge.c +++ b/trunk/drivers/net/sk98lin/skge.c @@ -282,22 +282,26 @@ SK_U32 Val) /* pointer to store the read value */ * Description: * This function initialize the PCI resources and IO * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication + * Returns: N/A + * */ -static __devinit int SkGeInitPCI(SK_AC *pAC) +int SkGeInitPCI(SK_AC *pAC) { struct SK_NET_DEVICE *dev = pAC->dev[0]; struct pci_dev *pdev = pAC->PciDev; int retval; + if (pci_enable_device(pdev) != 0) { + return 1; + } + dev->mem_start = pci_resource_start (pdev, 0); pci_set_master(pdev); - retval = pci_request_regions(pdev, "sk98lin"); - if (retval) - goto out; + if (pci_request_regions(pdev, "sk98lin") != 0) { + retval = 2; + goto out_disable; + } #ifdef SK_BIG_ENDIAN /* @@ -316,8 +320,9 @@ static __devinit int SkGeInitPCI(SK_AC *pAC) * Remap the regs into kernel space. */ pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000); - if (!pAC->IoBase) { - retval = -EIO; + + if (!pAC->IoBase){ + retval = 3; goto out_release; } @@ -325,7 +330,8 @@ static __devinit int SkGeInitPCI(SK_AC *pAC) out_release: pci_release_regions(pdev); - out: + out_disable: + pci_disable_device(pdev); return retval; } @@ -486,7 +492,7 @@ module_param_array(AutoSizing, charp, NULL, 0); * 0, if everything is ok * !=0, on error */ -static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) +static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) { short i; unsigned long Flags; @@ -523,7 +529,7 @@ SK_BOOL DualNet; if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { printk("HWInit (0) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; + return(-EAGAIN); } SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA); SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA); @@ -545,7 +551,7 @@ SK_BOOL DualNet; if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { printk("sk98lin: HWInit (1) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; + return(-EAGAIN); } SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); @@ -577,20 +583,20 @@ SK_BOOL DualNet; } else { printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", pAC->GIni.GIMacsFound); - return -EIO; + return -EAGAIN; } if (Ret) { printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", dev->irq); - return Ret; + return -EAGAIN; } pAC->AllocFlag |= SK_ALLOC_IRQ; /* Alloc memory for this board (Mem for RxD/TxD) : */ if(!BoardAllocMem(pAC)) { printk("No memory for descriptor rings.\n"); - return -ENOMEM; + return(-EAGAIN); } BoardInitMem(pAC); @@ -606,7 +612,7 @@ SK_BOOL DualNet; DualNet)) { BoardFreeMem(pAC); printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); - return -EIO; + return(-EAGAIN); } return (0); @@ -627,7 +633,8 @@ SK_BOOL DualNet; * SK_TRUE, if all memory could be allocated * SK_FALSE, if not */ -static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC) +static SK_BOOL BoardAllocMem( +SK_AC *pAC) { caddr_t pDescrMem; /* pointer to descriptor memory area */ size_t AllocLength; /* length of complete descriptor area */ @@ -720,7 +727,8 @@ size_t AllocLength; /* length of complete descriptor area */ * * Returns: N/A */ -static __devinit void BoardInitMem(SK_AC *pAC) +static void BoardInitMem( +SK_AC *pAC) /* pointer to adapter context */ { int i; /* loop counter */ int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/ @@ -4768,47 +4776,32 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, struct net_device *dev = NULL; static int boards_found = 0; int error = -ENODEV; - int using_dac = 0; char DeviceStr[80]; if (pci_enable_device(pdev)) goto out; /* Configure DMA attributes. */ - if (sizeof(dma_addr_t) > sizeof(u32) && - !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { - using_dac = 1; - error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (error < 0) { - printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA " - "for consistent allocations\n", pci_name(pdev)); - goto out_disable_device; - } - } else { - error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (error) { - printk(KERN_ERR "sk98lin %s no usable DMA configuration\n", - pci_name(pdev)); - goto out_disable_device; - } - } + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) && + pci_set_dma_mask(pdev, DMA_32BIT_MASK)) + goto out_disable_device; + - error = -ENOMEM; - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { + printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); goto out_disable_device; } pNet = netdev_priv(dev); - pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL); + pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); if (!pNet->pAC) { - printk(KERN_ERR "sk98lin: unable to allocate adapter " + printk(KERN_ERR "Unable to allocate adapter " "structure!\n"); goto out_free_netdev; } + memset(pNet->pAC, 0, sizeof(SK_AC)); pAC = pNet->pAC; pAC->PciDev = pdev; @@ -4817,7 +4810,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, pAC->CheckQueue = SK_FALSE; dev->irq = pdev->irq; - error = SkGeInitPCI(pAC); if (error) { printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error); @@ -4852,25 +4844,19 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, #endif } - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - pAC->Index = boards_found++; - error = SkGeBoardInit(dev, pAC); - if (error) + if (SkGeBoardInit(dev, pAC)) goto out_free_netdev; /* Read Adapter name from VPD */ if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) { - error = -EIO; printk(KERN_ERR "sk98lin: Could not read VPD data.\n"); goto out_free_resources; } /* Register net device */ - error = register_netdev(dev); - if (error) { + if (register_netdev(dev)) { printk(KERN_ERR "sk98lin: Could not register device.\n"); goto out_free_resources; } @@ -4897,17 +4883,15 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, boards_found++; - pci_set_drvdata(pdev, dev); - /* More then one port found */ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) { + printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); - goto single_port; + goto out; } + pAC->dev[1] = dev; pNet = netdev_priv(dev); pNet->PortNr = 1; pNet->NetNr = 1; @@ -4936,28 +4920,20 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, #endif } - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - - error = register_netdev(dev); - if (error) { - printk(KERN_ERR "sk98lin: Could not register device" - " for second port. (%d)\n", error); + if (register_netdev(dev)) { + printk(KERN_ERR "sk98lin: Could not register device for seconf port.\n"); free_netdev(dev); - goto single_port; + pAC->dev[1] = pAC->dev[0]; + } else { + memcpy(&dev->dev_addr, + &pAC->Addr.Net[1].CurrentMacAddress, 6); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + + printk("%s: %s\n", dev->name, DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); } - - pAC->dev[1] = dev; - memcpy(&dev->dev_addr, - &pAC->Addr.Net[1].CurrentMacAddress, 6); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - printk("%s: %s\n", dev->name, DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); } -single_port: - /* Save the hardware revision */ pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + (pAC->GIni.GIPciHwRev & 0x0F); @@ -4969,6 +4945,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA)); memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA)); + pci_set_drvdata(pdev, dev); return 0; out_free_resources: diff --git a/trunk/drivers/net/smc-ultra.c b/trunk/drivers/net/smc-ultra.c index 3db30cd0625e..ba8593ac3f8a 100644 --- a/trunk/drivers/net/smc-ultra.c +++ b/trunk/drivers/net/smc-ultra.c @@ -168,6 +168,18 @@ static int __init do_ultra_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: ultra_close_card() does free_irq */ +#ifdef __ISAPNP__ + struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; + if (idev) + pnp_device_detach(idev); +#endif + release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init ultra_probe(int unit) { @@ -582,18 +594,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - /* NB: ultra_close_card() does free_irq */ -#ifdef __ISAPNP__ - struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; - if (idev) - pnp_device_detach(idev); -#endif - release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/smc91x.c b/trunk/drivers/net/smc91x.c index 7ec08127c9d6..28bf2e69eb5e 100644 --- a/trunk/drivers/net/smc91x.c +++ b/trunk/drivers/net/smc91x.c @@ -88,6 +88,7 @@ static const char version[] = #include #include +#include #include "smc91x.h" @@ -2006,10 +2007,12 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) } /* Grab the IRQ */ - retval = request_irq(dev->irq, &smc_interrupt, SMC_IRQ_FLAGS, dev->name, dev); + retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); if (retval) goto err_out; + set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE); + #ifdef SMC_USE_PXA_DMA { int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, diff --git a/trunk/drivers/net/smc91x.h b/trunk/drivers/net/smc91x.h index e0efd1964e72..5c2824be4ee6 100644 --- a/trunk/drivers/net/smc91x.h +++ b/trunk/drivers/net/smc91x.h @@ -90,7 +90,7 @@ __l--; \ } \ } while (0) -#define SMC_IRQ_FLAGS (0) +#define set_irq_type(irq, type) #elif defined(CONFIG_SA1100_PLEB) /* We can only do 16-bit reads and writes in the static memory space. */ @@ -109,7 +109,7 @@ #define SMC_outw(v, a, r) writew(v, (a) + (r)) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) -#define SMC_IRQ_FLAGS (0) +#define set_irq_type(irq, type) do {} while (0) #elif defined(CONFIG_SA1100_ASSABET) @@ -185,11 +185,11 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #include #include -#define SMC_IRQ_FLAGS (( \ +#define SMC_IRQ_TRIGGER_TYPE (( \ machine_is_omap_h2() \ || machine_is_omap_h3() \ || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ - ) ? SA_TRIGGER_FALLING : SA_TRIGGER_RISING) + ) ? IRQT_FALLING : IRQT_RISING) #elif defined(CONFIG_SH_SH4202_MICRODEV) @@ -209,7 +209,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l) #define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l) -#define SMC_IRQ_FLAGS (0) +#define set_irq_type(irq, type) do {} while(0) #elif defined(CONFIG_ISA) @@ -237,7 +237,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l) #define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l) -#define SMC_IRQ_FLAGS (0) +#define set_irq_type(irq, type) do {} while(0) #define RPC_LSA_DEFAULT RPC_LED_TX_RX #define RPC_LSB_DEFAULT RPC_LED_100_10 @@ -319,7 +319,7 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) au_writew(*_p++ , _a); \ } while(0) -#define SMC_IRQ_FLAGS (0) +#define set_irq_type(irq, type) do {} while (0) #else @@ -342,8 +342,8 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) #endif -#ifndef SMC_IRQ_FLAGS -#define SMC_IRQ_FLAGS SA_TRIGGER_RISING +#ifndef SMC_IRQ_TRIGGER_TYPE +#define SMC_IRQ_TRIGGER_TYPE IRQT_RISING #endif #ifdef SMC_USE_PXA_DMA diff --git a/trunk/drivers/net/tulip/tulip_core.c b/trunk/drivers/net/tulip/tulip_core.c index c67c91251d04..125ed00e95a5 100644 --- a/trunk/drivers/net/tulip/tulip_core.c +++ b/trunk/drivers/net/tulip/tulip_core.c @@ -1564,7 +1564,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, dev->dev_addr, 6); } #endif -#if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */ +#if defined(__i386__) /* Patch up x86 BIOS bug. */ if (last_irq) irq = last_irq; #endif diff --git a/trunk/drivers/net/wan/sdla.c b/trunk/drivers/net/wan/sdla.c index 22e794071cf4..036adc4f8ba7 100644 --- a/trunk/drivers/net/wan/sdla.c +++ b/trunk/drivers/net/wan/sdla.c @@ -329,9 +329,9 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr) struct _dlci_stat { - short dlci; - char flags; -} __attribute__((packed)); + short dlci __attribute__((packed)); + char flags __attribute__((packed)); +}; struct _frad_stat { diff --git a/trunk/drivers/net/wd.c b/trunk/drivers/net/wd.c index 7caa8dc88a58..b03feae459fc 100644 --- a/trunk/drivers/net/wd.c +++ b/trunk/drivers/net/wd.c @@ -127,6 +127,13 @@ static int __init do_wd_probe(struct net_device *dev) return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + free_irq(dev->irq, dev); + release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT); + iounmap(ei_status.mem); +} + #ifndef MODULE struct net_device * __init wd_probe(int unit) { @@ -531,13 +538,6 @@ init_module(void) return -ENXIO; } -static void cleanup_card(struct net_device *dev) -{ - free_irq(dev->irq, dev); - release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT); - iounmap(ei_status.mem); -} - void cleanup_module(void) { diff --git a/trunk/drivers/net/wireless/ipw2100.c b/trunk/drivers/net/wireless/ipw2100.c index cf05661fb1bd..44cd3fcd1572 100644 --- a/trunk/drivers/net/wireless/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2100.c @@ -7153,7 +7153,7 @@ static int ipw2100_wx_get_range(struct net_device *dev, /* Set the Wireless Extension versions */ range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 18; + range->we_version_source = 16; // range->retry_capa; /* What retry options are supported */ // range->retry_flags; /* How to decode max/min retry limit */ @@ -7184,9 +7184,6 @@ static int ipw2100_wx_get_range(struct net_device *dev, IW_EVENT_CAPA_MASK(SIOCGIWAP)); range->event_capa[1] = IW_EVENT_CAPA_K_1; - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - IPW_DEBUG_WX("GET Range\n"); return 0; diff --git a/trunk/drivers/oprofile/buffer_sync.c b/trunk/drivers/oprofile/buffer_sync.c index b2e8e49c8659..531b07313141 100644 --- a/trunk/drivers/oprofile/buffer_sync.c +++ b/trunk/drivers/oprofile/buffer_sync.c @@ -43,16 +43,13 @@ static void process_task_mortuary(void); * list for processing. Only after two full buffer syncs * does the task eventually get freed, because by then * we are sure we will not reference it again. - * Can be invoked from softirq via RCU callback due to - * call_rcu() of the task struct, hence the _irqsave. */ static int task_free_notify(struct notifier_block * self, unsigned long val, void * data) { - unsigned long flags; struct task_struct * task = data; - spin_lock_irqsave(&task_mortuary, flags); + spin_lock(&task_mortuary); list_add(&task->tasks, &dying_tasks); - spin_unlock_irqrestore(&task_mortuary, flags); + spin_unlock(&task_mortuary); return NOTIFY_OK; } @@ -434,22 +431,25 @@ static void increment_tail(struct oprofile_cpu_buffer * b) */ static void process_task_mortuary(void) { - unsigned long flags; - LIST_HEAD(local_dead_tasks); + struct list_head * pos; + struct list_head * pos2; struct task_struct * task; - struct task_struct * ttask; - spin_lock_irqsave(&task_mortuary, flags); + spin_lock(&task_mortuary); - list_splice_init(&dead_tasks, &local_dead_tasks); - list_splice_init(&dying_tasks, &dead_tasks); - - spin_unlock_irqrestore(&task_mortuary, flags); - - list_for_each_entry_safe(task, ttask, &local_dead_tasks, tasks) { + list_for_each_safe(pos, pos2, &dead_tasks) { + task = list_entry(pos, struct task_struct, tasks); list_del(&task->tasks); free_task(task); } + + list_for_each_safe(pos, pos2, &dying_tasks) { + task = list_entry(pos, struct task_struct, tasks); + list_del(&task->tasks); + list_add_tail(&task->tasks, &dead_tasks); + } + + spin_unlock(&task_mortuary); } diff --git a/trunk/drivers/oprofile/cpu_buffer.c b/trunk/drivers/oprofile/cpu_buffer.c index 78193e4bbdb5..026f671ea558 100644 --- a/trunk/drivers/oprofile/cpu_buffer.c +++ b/trunk/drivers/oprofile/cpu_buffer.c @@ -52,8 +52,7 @@ int alloc_cpu_buffers(void) for_each_online_cpu(i) { struct oprofile_cpu_buffer * b = &cpu_buffer[i]; - b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size, - cpu_to_node(i)); + b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size); if (!b->buffer) goto fail; diff --git a/trunk/drivers/parport/Kconfig b/trunk/drivers/parport/Kconfig index a665951b1586..b8241561da45 100644 --- a/trunk/drivers/parport/Kconfig +++ b/trunk/drivers/parport/Kconfig @@ -34,7 +34,7 @@ config PARPORT config PARPORT_PC tristate "PC-style hardware" - depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV + depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R ---help--- You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style diff --git a/trunk/drivers/parport/parport_pc.c b/trunk/drivers/parport/parport_pc.c index 9302b8fd7461..18e85ccdae67 100644 --- a/trunk/drivers/parport/parport_pc.c +++ b/trunk/drivers/parport/parport_pc.c @@ -2371,10 +2371,8 @@ void parport_pc_unregister_port (struct parport *p) spin_lock(&ports_lock); list_del_init(&priv->list); spin_unlock(&ports_lock); -#if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA) if (p->dma != PARPORT_DMA_NONE) free_dma(p->dma); -#endif if (p->irq != PARPORT_IRQ_NONE) free_irq(p->irq, p); release_region(p->base, 3); @@ -2382,11 +2380,13 @@ void parport_pc_unregister_port (struct parport *p) release_region(p->base + 3, p->size - 3); if (p->modes & PARPORT_MODE_ECP) release_region(p->base_hi, 3); -#if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA) +#ifdef CONFIG_PARPORT_PC_FIFO +#ifdef HAS_DMA if (priv->dma_buf) pci_free_consistent(priv->dev, PAGE_SIZE, priv->dma_buf, priv->dma_handle); +#endif #endif kfree (p->private_data); parport_put_port(p); diff --git a/trunk/drivers/pci/hotplug/pciehp.h b/trunk/drivers/pci/hotplug/pciehp.h index 0aac6a61337d..6a61b9f286e1 100644 --- a/trunk/drivers/pci/hotplug/pciehp.h +++ b/trunk/drivers/pci/hotplug/pciehp.h @@ -32,7 +32,6 @@ #include #include #include -#include /* signal_pending() */ #include #include "pci_hotplug.h" diff --git a/trunk/drivers/pci/hotplug/pciehp_hpc.c b/trunk/drivers/pci/hotplug/pciehp_hpc.c index ac1e495c314e..0b8b26beb163 100644 --- a/trunk/drivers/pci/hotplug/pciehp_hpc.c +++ b/trunk/drivers/pci/hotplug/pciehp_hpc.c @@ -30,9 +30,6 @@ #include #include #include -#include -#include -#include #include #include diff --git a/trunk/drivers/rapidio/rio-scan.c b/trunk/drivers/rapidio/rio-scan.c index 94e30fe4b8f3..4f7ed4bd3be9 100644 --- a/trunk/drivers/rapidio/rio-scan.c +++ b/trunk/drivers/rapidio/rio-scan.c @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include "rio.h" diff --git a/trunk/drivers/rapidio/rio-sysfs.c b/trunk/drivers/rapidio/rio-sysfs.c index bef9316e95df..30a11436e241 100644 --- a/trunk/drivers/rapidio/rio-sysfs.c +++ b/trunk/drivers/rapidio/rio-sysfs.c @@ -15,7 +15,6 @@ #include #include #include -#include /* for capable() */ #include "rio.h" diff --git a/trunk/drivers/rapidio/rio.c b/trunk/drivers/rapidio/rio.c index 5e382470faa2..3ca1011ceaac 100644 --- a/trunk/drivers/rapidio/rio.c +++ b/trunk/drivers/rapidio/rio.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "rio.h" diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index 2472fa1a1be1..f779f674dfa0 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -1724,34 +1723,12 @@ dasd_release(struct inode *inp, struct file *filp) return 0; } -/* - * Return disk geometry. - */ -static int -dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct dasd_device *device; - - device = bdev->bd_disk->private_data; - if (!device) - return -ENODEV; - - if (!device->discipline || - !device->discipline->fill_geometry) - return -EINVAL; - - device->discipline->fill_geometry(device, geo); - geo->start = get_start_sect(bdev) >> device->s2b_shift; - return 0; -} - struct block_device_operations dasd_device_operations = { .owner = THIS_MODULE, .open = dasd_open, .release = dasd_release, .ioctl = dasd_ioctl, - .getgeo = dasd_getgeo, }; diff --git a/trunk/drivers/s390/block/dasd_ioctl.c b/trunk/drivers/s390/block/dasd_ioctl.c index 8e4dcd58599e..044b75371990 100644 --- a/trunk/drivers/s390/block/dasd_ioctl.c +++ b/trunk/drivers/s390/block/dasd_ioctl.c @@ -485,6 +485,33 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) return rc; } +/* + * Return disk geometry. + */ +static int +dasd_ioctl_getgeo(struct block_device *bdev, int no, long args) +{ + struct hd_geometry geo = { 0, }; + struct dasd_device *device; + + device = bdev->bd_disk->private_data; + if (device == NULL) + return -ENODEV; + + if (device == NULL || device->discipline == NULL || + device->discipline->fill_geometry == NULL) + return -EINVAL; + + geo = (struct hd_geometry) {}; + device->discipline->fill_geometry(device, &geo); + geo.start = get_start_sect(bdev) >> device->s2b_shift; + if (copy_to_user((struct hd_geometry __user *) args, &geo, + sizeof (struct hd_geometry))) + return -EFAULT; + + return 0; +} + /* * List of static ioctls. */ @@ -501,6 +528,7 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] = { BIODASDPRRST, dasd_ioctl_reset_profile }, { BLKROSET, dasd_ioctl_set_ro }, { DASDAPIVER, dasd_ioctl_api_version }, + { HDIO_GETGEO, dasd_ioctl_getgeo }, { -1, NULL } }; diff --git a/trunk/drivers/s390/block/xpram.c b/trunk/drivers/s390/block/xpram.c index 54ecd548c318..bf3a67c3cc5e 100644 --- a/trunk/drivers/s390/block/xpram.c +++ b/trunk/drivers/s390/block/xpram.c @@ -328,27 +328,31 @@ static int xpram_make_request(request_queue_t *q, struct bio *bio) return 0; } -static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int xpram_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { + struct hd_geometry __user *geo; unsigned long size; - + if (cmd != HDIO_GETGEO) + return -EINVAL; /* * get geometry: we have to fake one... trim the size to a * multiple of 64 (32k): tell we have 16 sectors, 4 heads, * whatever cylinders. Tell also that data starts at sector. 4. */ + geo = (struct hd_geometry __user *) arg; size = (xpram_pages * 8) & ~0x3f; - geo->cylinders = size >> 6; - geo->heads = 4; - geo->sectors = 16; - geo->start = 4; + put_user(size >> 6, &geo->cylinders); + put_user(4, &geo->heads); + put_user(16, &geo->sectors); + put_user(4, &geo->start); return 0; } static struct block_device_operations xpram_devops = { .owner = THIS_MODULE, - .getgeo = xpram_getgeo, + .ioctl = xpram_ioctl, }; /* diff --git a/trunk/drivers/scsi/sata_nv.c b/trunk/drivers/scsi/sata_nv.c index bbbb55eeb73a..c0cf52cb975a 100644 --- a/trunk/drivers/scsi/sata_nv.c +++ b/trunk/drivers/scsi/sata_nv.c @@ -29,12 +29,6 @@ * NV-specific details such as register offsets, SATA phy location, * hotplug info, etc. * - * 0.10 - * - Fixed spurious interrupts issue seen with the Maxtor 6H500F0 500GB - * drive. Also made the check_hotplug() callbacks return whether there - * was a hotplug interrupt or not. This was not the source of the - * spurious interrupts, but is the right thing to do anyway. - * * 0.09 * - Fixed bug introduced by 0.08's MCP51 and MCP55 support. * @@ -130,10 +124,10 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void nv_host_stop (struct ata_host_set *host_set); static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); static void nv_disable_hotplug(struct ata_host_set *host_set); -static int nv_check_hotplug(struct ata_host_set *host_set); +static void nv_check_hotplug(struct ata_host_set *host_set); static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); -static int nv_check_hotplug_ck804(struct ata_host_set *host_set); +static void nv_check_hotplug_ck804(struct ata_host_set *host_set); enum nv_host_type { @@ -182,7 +176,7 @@ struct nv_host_desc enum nv_host_type host_type; void (*enable_hotplug)(struct ata_probe_ent *probe_ent); void (*disable_hotplug)(struct ata_host_set *host_set); - int (*check_hotplug)(struct ata_host_set *host_set); + void (*check_hotplug)(struct ata_host_set *host_set); }; static struct nv_host_desc nv_device_tbl[] = { @@ -315,16 +309,12 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) handled += ata_host_intr(ap, qc); - else - // No request pending? Clear interrupt status - // anyway, in case there's one pending. - ap->ops->check_status(ap); } } if (host->host_desc->check_hotplug) - handled += host->host_desc->check_hotplug(host_set); + host->host_desc->check_hotplug(host_set); spin_unlock_irqrestore(&host_set->lock, flags); @@ -507,7 +497,7 @@ static void nv_disable_hotplug(struct ata_host_set *host_set) outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); } -static int nv_check_hotplug(struct ata_host_set *host_set) +static void nv_check_hotplug(struct ata_host_set *host_set) { u8 intr_status; @@ -532,11 +522,7 @@ static int nv_check_hotplug(struct ata_host_set *host_set) if (intr_status & NV_INT_STATUS_SDEV_REMOVED) printk(KERN_WARNING "nv_sata: " "Secondary device removed\n"); - - return 1; } - - return 0; } static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) @@ -574,7 +560,7 @@ static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); } -static int nv_check_hotplug_ck804(struct ata_host_set *host_set) +static void nv_check_hotplug_ck804(struct ata_host_set *host_set) { u8 intr_status; @@ -599,11 +585,7 @@ static int nv_check_hotplug_ck804(struct ata_host_set *host_set) if (intr_status & NV_INT_STATUS_SDEV_REMOVED) printk(KERN_WARNING "nv_sata: " "Secondary device removed\n"); - - return 1; } - - return 0; } static int __init nv_init(void) diff --git a/trunk/drivers/scsi/scsi.c b/trunk/drivers/scsi/scsi.c index ee5f4dfdab14..180676d7115a 100644 --- a/trunk/drivers/scsi/scsi.c +++ b/trunk/drivers/scsi/scsi.c @@ -69,6 +69,7 @@ #include "scsi_logging.h" static void scsi_done(struct scsi_cmnd *cmd); +static int scsi_retry_command(struct scsi_cmnd *cmd); /* * Definitions and constants. @@ -751,7 +752,7 @@ static void scsi_done(struct scsi_cmnd *cmd) * isn't running --- used by scsi_times_out */ void __scsi_done(struct scsi_cmnd *cmd) { - struct request *rq = cmd->request; + unsigned long flags; /* * Set the serial numbers back to zero @@ -762,14 +763,71 @@ void __scsi_done(struct scsi_cmnd *cmd) 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 + * Next, enqueue the command into the done queue. + * It is a per-CPU queue, so we just disable local interrupts + * and need no spinlock. */ - rq->completion_data = cmd; - blk_complete_request(rq); + local_irq_save(flags); + list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q)); + raise_softirq_irqoff(SCSI_SOFTIRQ); + local_irq_restore(flags); +} + +/** + * scsi_softirq - Perform post-interrupt processing of finished SCSI commands. + * + * This is the consumer of the done queue. + * + * This is called with all interrupts enabled. This should reduce + * interrupt latency, stack depth, and reentrancy of the low-level + * drivers. + */ +static void scsi_softirq(struct softirq_action *h) +{ + int disposition; + LIST_HEAD(local_q); + + local_irq_disable(); + list_splice_init(&__get_cpu_var(scsi_done_q), &local_q); + local_irq_enable(); + + while (!list_empty(&local_q)) { + struct scsi_cmnd *cmd = list_entry(local_q.next, + struct scsi_cmnd, eh_entry); + /* The longest time any command should be outstanding is the + * per command timeout multiplied by the number of retries. + * + * For a typical command, this is 2.5 minutes */ + unsigned long wait_for + = cmd->allowed * cmd->timeout_per_command; + list_del_init(&cmd->eh_entry); + + disposition = scsi_decide_disposition(cmd); + if (disposition != SUCCESS && + time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { + sdev_printk(KERN_ERR, cmd->device, + "timing out command, waited %lus\n", + wait_for/HZ); + disposition = SUCCESS; + } + + scsi_log_completion(cmd, disposition); + switch (disposition) { + case SUCCESS: + scsi_finish_command(cmd); + break; + case NEEDS_RETRY: + scsi_retry_command(cmd); + break; + case ADD_TO_MLQUEUE: + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); + break; + default: + if (!scsi_eh_scmd_add(cmd, 0)) + scsi_finish_command(cmd); + } + } } /* @@ -782,7 +840,7 @@ void __scsi_done(struct scsi_cmnd *cmd) * level drivers should not become re-entrant as a result of * this. */ -int scsi_retry_command(struct scsi_cmnd *cmd) +static int scsi_retry_command(struct scsi_cmnd *cmd) { /* * Restore the SCSI command state. @@ -1215,6 +1273,38 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) } EXPORT_SYMBOL(scsi_device_cancel); +#ifdef CONFIG_HOTPLUG_CPU +static int scsi_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + int cpu = (unsigned long)hcpu; + + switch(action) { + case CPU_DEAD: + /* Drain scsi_done_q. */ + local_irq_disable(); + list_splice_init(&per_cpu(scsi_done_q, cpu), + &__get_cpu_var(scsi_done_q)); + raise_softirq_irqoff(SCSI_SOFTIRQ); + local_irq_enable(); + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __devinitdata scsi_cpu_nb = { + .notifier_call = scsi_cpu_notify, +}; + +#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb) +#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb) +#else +#define register_scsi_cpu() +#define unregister_scsi_cpu() +#endif /* CONFIG_HOTPLUG_CPU */ + MODULE_DESCRIPTION("SCSI core"); MODULE_LICENSE("GPL"); @@ -1248,6 +1338,8 @@ static int __init init_scsi(void) INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); devfs_mk_dir("scsi"); + open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL); + register_scsi_cpu(); printk(KERN_NOTICE "SCSI subsystem initialized\n"); return 0; @@ -1275,6 +1367,7 @@ static void __exit exit_scsi(void) devfs_remove("scsi"); scsi_exit_procfs(); scsi_exit_queue(); + unregister_scsi_cpu(); } subsys_initcall(init_scsi); diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 00c9bf383e23..ba93d6e66d48 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -1493,41 +1493,6 @@ static void scsi_kill_request(struct request *req, request_queue_t *q) __scsi_done(cmd); } -static void scsi_softirq_done(struct request *rq) -{ - struct scsi_cmnd *cmd = rq->completion_data; - unsigned long wait_for = cmd->allowed * cmd->timeout_per_command; - int disposition; - - INIT_LIST_HEAD(&cmd->eh_entry); - - disposition = scsi_decide_disposition(cmd); - if (disposition != SUCCESS && - time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { - sdev_printk(KERN_ERR, cmd->device, - "timing out command, waited %lus\n", - wait_for/HZ); - disposition = SUCCESS; - } - - scsi_log_completion(cmd, disposition); - - switch (disposition) { - case SUCCESS: - scsi_finish_command(cmd); - break; - case NEEDS_RETRY: - scsi_retry_command(cmd); - break; - case ADD_TO_MLQUEUE: - scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); - break; - default: - if (!scsi_eh_scmd_add(cmd, 0)) - scsi_finish_command(cmd); - } -} - /* * Function: scsi_request_fn() * @@ -1702,7 +1667,6 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); - blk_queue_softirq_done(q, scsi_softirq_done); if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); diff --git a/trunk/drivers/scsi/scsi_priv.h b/trunk/drivers/scsi/scsi_priv.h index 14a6198cb8d2..f04e7e11f57a 100644 --- a/trunk/drivers/scsi/scsi_priv.h +++ b/trunk/drivers/scsi/scsi_priv.h @@ -44,7 +44,6 @@ extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq); extern void __scsi_release_request(struct scsi_request *sreq); extern void __scsi_done(struct scsi_cmnd *cmd); -extern int scsi_retry_command(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); diff --git a/trunk/drivers/scsi/sd.c b/trunk/drivers/scsi/sd.c index 4c5127ed379c..32d4d8d7b9f3 100644 --- a/trunk/drivers/scsi/sd.c +++ b/trunk/drivers/scsi/sd.c @@ -527,7 +527,7 @@ static int sd_release(struct inode *inode, struct file *filp) return 0; } -static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) +static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc) { struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); struct scsi_device *sdp = sdkp->device; @@ -545,9 +545,15 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) else scsicam_bios_param(bdev, sdkp->capacity, diskinfo); - geo->heads = diskinfo[0]; - geo->sectors = diskinfo[1]; - geo->cylinders = diskinfo[2]; + if (put_user(diskinfo[0], &loc->heads)) + return -EFAULT; + if (put_user(diskinfo[1], &loc->sectors)) + return -EFAULT; + if (put_user(diskinfo[2], &loc->cylinders)) + return -EFAULT; + if (put_user((unsigned)get_start_sect(bdev), + (unsigned long __user *)&loc->start)) + return -EFAULT; return 0; } @@ -587,6 +593,12 @@ static int sd_ioctl(struct inode * inode, struct file * filp, if (!scsi_block_when_processing_errors(sdp) || !error) return error; + if (cmd == HDIO_GETGEO) { + if (!arg) + return -EINVAL; + return sd_hdio_getgeo(bdev, p); + } + /* * Send SCSI addressing ioctls directly to mid level, send other * ioctls to block level and then onto mid level if they can't be @@ -788,7 +800,6 @@ static struct block_device_operations sd_fops = { .open = sd_open, .release = sd_release, .ioctl = sd_ioctl, - .getgeo = sd_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, #endif diff --git a/trunk/drivers/usb/core/inode.c b/trunk/drivers/usb/core/inode.c index 4ddc453023a2..c44bbedec817 100644 --- a/trunk/drivers/usb/core/inode.c +++ b/trunk/drivers/usb/core/inode.c @@ -186,7 +186,7 @@ static void update_bus(struct dentry *bus) down(&bus->d_inode->i_sem); - list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child) + list_for_each_entry(dev, &bus->d_subdirs, d_child) if (dev->d_inode) update_dev(dev); @@ -203,7 +203,7 @@ static void update_sb(struct super_block *sb) down(&root->d_inode->i_sem); - list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { + list_for_each_entry(bus, &root->d_subdirs, d_child) { if (bus->d_inode) { switch (S_IFMT & bus->d_inode->i_mode) { case S_IFDIR: @@ -319,7 +319,7 @@ static int usbfs_empty (struct dentry *dentry) spin_lock(&dcache_lock); list_for_each(list, &dentry->d_subdirs) { - struct dentry *de = list_entry(list, struct dentry, d_u.d_child); + struct dentry *de = list_entry(list, struct dentry, d_child); if (usbfs_positive(de)) { spin_unlock(&dcache_lock); return 0; diff --git a/trunk/drivers/usb/host/ohci-au1xxx.c b/trunk/drivers/usb/host/ohci-au1xxx.c index 77cd6ac07e3c..d9cf3b327d96 100644 --- a/trunk/drivers/usb/host/ohci-au1xxx.c +++ b/trunk/drivers/usb/host/ohci-au1xxx.c @@ -19,7 +19,6 @@ */ #include -#include #include diff --git a/trunk/drivers/usb/host/ohci-lh7a404.c b/trunk/drivers/usb/host/ohci-lh7a404.c index 0020ed7a39d0..3959ccc88332 100644 --- a/trunk/drivers/usb/host/ohci-lh7a404.c +++ b/trunk/drivers/usb/host/ohci-lh7a404.c @@ -17,7 +17,6 @@ */ #include -#include #include diff --git a/trunk/drivers/usb/host/ohci-ppc-soc.c b/trunk/drivers/usb/host/ohci-ppc-soc.c index b2a8dfa48870..2ec6a78bd65e 100644 --- a/trunk/drivers/usb/host/ohci-ppc-soc.c +++ b/trunk/drivers/usb/host/ohci-ppc-soc.c @@ -15,7 +15,6 @@ */ #include -#include /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 3f04427c9026..cc8e3bf5001b 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -1151,7 +1151,7 @@ config FB_VOODOO1 config FB_CYBLA tristate "Cyberblade/i1 support" - depends on FB && PCI && X86_32 && !64BIT + depends on FB && PCI select FB_CFB_IMAGEBLIT select VIDEO_SELECT ---help--- diff --git a/trunk/drivers/video/console/Kconfig b/trunk/drivers/video/console/Kconfig index 6ee449858a5c..a5d09e159cd1 100644 --- a/trunk/drivers/video/console/Kconfig +++ b/trunk/drivers/video/console/Kconfig @@ -6,7 +6,7 @@ menu "Console display driver support" config VGA_CONSOLE bool "VGA text console" if EMBEDDED || !X86 - depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE + depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !ARCH_VERSATILE default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/trunk/drivers/video/console/vgacon.c b/trunk/drivers/video/console/vgacon.c index 12d9329d1408..167de397e4b4 100644 --- a/trunk/drivers/video/console/vgacon.c +++ b/trunk/drivers/video/console/vgacon.c @@ -56,8 +56,6 @@ static DEFINE_SPINLOCK(vga_lock); static int cursor_size_lastfrom; static int cursor_size_lastto; -static u32 vgacon_xres; -static u32 vgacon_yres; static struct vgastate state; #define BLANK 0x0020 @@ -71,7 +69,7 @@ static struct vgastate state; * appear. */ #undef TRIDENT_GLITCH -#define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */ + /* * Interface used by the world */ @@ -327,10 +325,6 @@ static const char __init *vgacon_startup(void) vga_scan_lines = vga_video_font_height * vga_video_num_lines; } - - vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; - vgacon_yres = vga_scan_lines; - return display_desc; } @@ -509,18 +503,10 @@ static int vgacon_doresize(struct vc_data *c, { unsigned long flags; unsigned int scanlines = height * c->vc_font.height; - u8 scanlines_lo, r7, vsync_end, mode, max_scan; + u8 scanlines_lo, r7, vsync_end, mode; spin_lock_irqsave(&vga_lock, flags); - outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg); - max_scan = inb_p(vga_video_port_val); - - if (max_scan & 0x80) - scanlines <<= 1; - - vgacon_xres = width * VGA_FONTWIDTH; - vgacon_yres = height * c->vc_font.height; outb_p(VGA_CRTC_MODE, vga_video_port_reg); mode = inb_p(vga_video_port_val); @@ -565,10 +551,6 @@ static int vgacon_doresize(struct vc_data *c, static int vgacon_switch(struct vc_data *c) { - int x = c->vc_cols * VGA_FONTWIDTH; - int y = c->vc_rows * c->vc_font.height; - int rows = ORIG_VIDEO_LINES * vga_default_font_height/ - c->vc_font.height; /* * We need to save screen size here as it's the only way * we can spot the screen has been resized and we need to @@ -584,11 +566,10 @@ static int vgacon_switch(struct vc_data *c) scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); - - if ((vgacon_xres != x || vgacon_yres != y) && - (!(vga_video_num_columns % 2) && - vga_video_num_columns <= ORIG_VIDEO_COLS && - vga_video_num_lines <= rows)) + if (!(vga_video_num_columns % 2) && + vga_video_num_columns <= ORIG_VIDEO_COLS && + vga_video_num_lines <= (ORIG_VIDEO_LINES * + vga_default_font_height) / c->vc_font.height) vgacon_doresize(c, c->vc_cols, c->vc_rows); } @@ -1012,8 +993,7 @@ static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigne if (vga_video_type < VIDEO_TYPE_EGAM) return -EINVAL; - if (font->width != VGA_FONTWIDTH || - (charcount != 256 && charcount != 512)) + if (font->width != 8 || (charcount != 256 && charcount != 512)) return -EINVAL; rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512); @@ -1030,7 +1010,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) if (vga_video_type < VIDEO_TYPE_EGAM) return -EINVAL; - font->width = VGA_FONTWIDTH; + font->width = 8; font->height = c->vc_font.height; font->charcount = vga_512_chars ? 512 : 256; if (!font->data) diff --git a/trunk/drivers/video/cyblafb.c b/trunk/drivers/video/cyblafb.c index e9f5dee67e3c..03fbe83d71a8 100644 --- a/trunk/drivers/video/cyblafb.c +++ b/trunk/drivers/video/cyblafb.c @@ -7,12 +7,11 @@ * tridentfb.c by Jani Monoses * see files above for further credits * + * TODO: + * */ #define CYBLAFB_DEBUG 0 -#define CYBLAFB_KD_GRAPHICS_QUIRK 1 - -#define CYBLAFB_PIXMAPSIZE 8192 #include #include @@ -23,7 +22,7 @@ #include #include